mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-07-30 17:48:50 +02:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc9ec9b4ad | ||
|
|
dc7f87bc7e | ||
|
|
304292d740 | ||
|
|
622f02bf21 | ||
|
|
abc903c240 | ||
|
|
ab7489c964 | ||
|
|
3fb27bf13a | ||
|
|
7e45774610 | ||
|
|
526726162f |
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"deep-link": patch
|
||||||
|
"deep-link-js": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
adds proper Platform-specific sections to the docs for `register`, `unregister`, `isRegistered`, and `onOpenUrl`
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"dialog": patch
|
||||||
|
"dialog-js": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix Android save dialog MIME type when a single MIME type is provided.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"fs": patch
|
||||||
|
"fs-js": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixed `deny-webview-data` has no effect
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
nfc: patch
|
||||||
|
nfc-js: patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Expect a `NFCTag` as input and return a `ScanResponse` in the `scan` function.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
notification: minor
|
||||||
|
notification-js: minor
|
||||||
|
---
|
||||||
|
|
||||||
|
- Add Rust builders for mobile notification action types.
|
||||||
|
- Fix Android action-group entries being stored under the action type ID instead of sequential indices, causing later actions to overwrite earlier ones.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"updater": patch
|
||||||
|
"updater-js": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
On Windows, returns an error if failed to spawn the installer in `install` through `ShellExecuteW`
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"updater": minor
|
||||||
|
"updater-js": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
On Windows, add a new option `restartAfterInstall`/`restart_after_install` to install an update without the installer re-launching the app
|
||||||
Generated
+3
-23
@@ -916,17 +916,6 @@ dependencies = [
|
|||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfb"
|
|
||||||
version = "0.14.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a347dcabdae9c31b0825fd6a8bed285ec9c2acb89c47827126d52fa4f59cece3"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"uuid",
|
|
||||||
"web-time",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-expr"
|
name = "cfg-expr"
|
||||||
version = "0.15.8"
|
version = "0.15.8"
|
||||||
@@ -3036,16 +3025,7 @@ version = "0.19.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
|
checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfb 0.7.3",
|
"cfb",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "infer"
|
|
||||||
version = "0.22.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f4200d433cbd5178df7797c9c2e75b348b728e39631cf14520d1e2fc424201f4"
|
|
||||||
dependencies = [
|
|
||||||
"cfb 0.14.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6879,7 +6859,7 @@ dependencies = [
|
|||||||
"flate2",
|
"flate2",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"infer 0.22.0",
|
"infer",
|
||||||
"log",
|
"log",
|
||||||
"minisign-verify",
|
"minisign-verify",
|
||||||
"osakit",
|
"osakit",
|
||||||
@@ -7016,7 +6996,7 @@ dependencies = [
|
|||||||
"getrandom 0.3.2",
|
"getrandom 0.3.2",
|
||||||
"glob",
|
"glob",
|
||||||
"http",
|
"http",
|
||||||
"infer 0.19.0",
|
"infer",
|
||||||
"json-patch",
|
"json-patch",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"@tauri-apps/plugin-biometric": "workspace:*",
|
"@tauri-apps/plugin-biometric": "workspace:*",
|
||||||
"@tauri-apps/plugin-cli": "workspace:*",
|
"@tauri-apps/plugin-cli": "workspace:*",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "workspace:*",
|
"@tauri-apps/plugin-clipboard-manager": "workspace:*",
|
||||||
"@tauri-apps/plugin-dialog": "2",
|
"@tauri-apps/plugin-dialog": "workspace:*",
|
||||||
"@tauri-apps/plugin-fs": "workspace:*",
|
"@tauri-apps/plugin-fs": "workspace:*",
|
||||||
"@tauri-apps/plugin-geolocation": "workspace:*",
|
"@tauri-apps/plugin-geolocation": "workspace:*",
|
||||||
"@tauri-apps/plugin-global-shortcut": "workspace:*",
|
"@tauri-apps/plugin-global-shortcut": "workspace:*",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"@tauri-apps/plugin-os": "workspace:*",
|
"@tauri-apps/plugin-os": "workspace:*",
|
||||||
"@tauri-apps/plugin-process": "workspace:*",
|
"@tauri-apps/plugin-process": "workspace:*",
|
||||||
"@tauri-apps/plugin-shell": "workspace:*",
|
"@tauri-apps/plugin-shell": "workspace:*",
|
||||||
"@tauri-apps/plugin-store": "2",
|
"@tauri-apps/plugin-store": "workspace:*",
|
||||||
"@tauri-apps/plugin-updater": "workspace:*",
|
"@tauri-apps/plugin-updater": "workspace:*",
|
||||||
"@tauri-apps/plugin-upload": "workspace:*",
|
"@tauri-apps/plugin-upload": "workspace:*",
|
||||||
"@zerodevx/svelte-json-view": "1.0.11"
|
"@zerodevx/svelte-json-view": "1.0.11"
|
||||||
@@ -38,8 +38,8 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||||
"@tauri-apps/cli": "2.11.4",
|
"@tauri-apps/cli": "2.11.4",
|
||||||
"@unocss/extractor-svelte": "^66.6.7",
|
"@unocss/extractor-svelte": "^66.6.7",
|
||||||
"svelte": "^5.54.0",
|
"svelte": "^5.55.7",
|
||||||
"unocss": "^66.6.7",
|
"unocss": "^66.6.7",
|
||||||
"vite": "^8.0.1"
|
"vite": "^8.0.16"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,9 @@
|
|||||||
},
|
},
|
||||||
"updater": {
|
"updater": {
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK",
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK",
|
||||||
|
"dangerousInsecureTransportProtocol": true,
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
|
"http://localhost:5173/updater-test/updater.json",
|
||||||
"https://tauri-update-server.vercel.app/update/{{target}}/{{current_version}}"
|
"https://tauri-update-server.vercel.app/update/{{target}}/{{current_version}}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -99,6 +101,9 @@
|
|||||||
"localePath": "locales/pt-BR.wxl"
|
"localePath": "locales/pt-BR.wxl"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"nsis": {
|
||||||
|
"compression": "none"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"iOS": {
|
"iOS": {
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import { check } from '@tauri-apps/plugin-updater'
|
import { check, Update } from '@tauri-apps/plugin-updater'
|
||||||
import { relaunch } from '@tauri-apps/plugin-process'
|
import { relaunch } from '@tauri-apps/plugin-process'
|
||||||
|
import { onDestroy } from 'svelte'
|
||||||
|
|
||||||
export let onMessage
|
let { onMessage } = $props()
|
||||||
|
|
||||||
let isChecking, isInstalling, newUpdate
|
let isChecking = $state(false)
|
||||||
let totalSize = 0,
|
let isInstalling = $state(false)
|
||||||
downloadedSize = 0
|
let newUpdate = $state<Update | undefined>()
|
||||||
|
let totalSize = $state(0)
|
||||||
|
let downloadedSize = $state(0)
|
||||||
|
let progress = $derived(
|
||||||
|
totalSize ? Math.round((downloadedSize / totalSize) * 100) : 0
|
||||||
|
)
|
||||||
|
|
||||||
async function checkUpdate() {
|
async function checkUpdate() {
|
||||||
isChecking = true
|
isChecking = true
|
||||||
@@ -31,10 +37,10 @@
|
|||||||
isInstalling = true
|
isInstalling = true
|
||||||
downloadedSize = 0
|
downloadedSize = 0
|
||||||
try {
|
try {
|
||||||
await newUpdate.downloadAndInstall((downloadProgress) => {
|
await newUpdate!.downloadAndInstall((downloadProgress) => {
|
||||||
switch (downloadProgress.event) {
|
switch (downloadProgress.event) {
|
||||||
case 'Started':
|
case 'Started':
|
||||||
totalSize = downloadProgress.data.contentLength
|
totalSize = downloadProgress.data.contentLength!
|
||||||
break
|
break
|
||||||
case 'Progress':
|
case 'Progress':
|
||||||
downloadedSize += downloadProgress.data.chunkLength
|
downloadedSize += downloadProgress.data.chunkLength
|
||||||
@@ -54,14 +60,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: progress = totalSize ? Math.round((downloadedSize / totalSize) * 100) : 0
|
onDestroy(() => {
|
||||||
|
newUpdate?.close()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex children:grow children:h10">
|
<div class="flex children:grow children:h10">
|
||||||
{#if !isChecking && !newUpdate}
|
{#if !isChecking && !newUpdate}
|
||||||
<button class="btn" on:click={checkUpdate}>Check update</button>
|
<button class="btn" onclick={checkUpdate}>Check update</button>
|
||||||
{:else if !isInstalling && newUpdate}
|
{:else if !isInstalling && newUpdate}
|
||||||
<button class="btn" on:click={install}>Install update</button>
|
<button class="btn" onclick={install}>Install update</button>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
<span>{progress}%</span>
|
<span>{progress}%</span>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
*
|
||||||
|
|
||||||
|
!.gitignore
|
||||||
|
!README.md
|
||||||
|
!updater.json
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
To test the updater:
|
||||||
|
|
||||||
|
1. Comment out `verify_signature` inside `plugins/updater/src/updater.rs`
|
||||||
|
2. Run `pnpm tauri build --debug` to build the bundles
|
||||||
|
3. Copy the bundle you want to test to this folder (`examples/api/updater-test/`)
|
||||||
|
4. Run `pnpm tauri dev` and open the Updater tab to check
|
||||||
|
|
||||||
|
If the bundle you're testing doesn't exist in the `updater.json` yet, add it manually and welcome to open an PR
|
||||||
|
|
||||||
|
> The `updater.json` and debug bundles will be served by `vite`
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "2.1.0",
|
||||||
|
"notes": "Test update!",
|
||||||
|
"pub_date": "2026-03-01T14:04:20+00:00",
|
||||||
|
"platforms": {
|
||||||
|
"windows-x86_64": {
|
||||||
|
"signature": "",
|
||||||
|
"url": "http://localhost:5173/updater-test/Tauri API_2.0.0_x64_en-US.msi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ export default defineConfig(async () => {
|
|||||||
port: 5173,
|
port: 5173,
|
||||||
strictPort: true,
|
strictPort: true,
|
||||||
fs: {
|
fs: {
|
||||||
allow: ['.', '../../tooling/api/dist']
|
allow: ['.']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@
|
|||||||
"eslint-config-prettier": "10.1.8",
|
"eslint-config-prettier": "10.1.8",
|
||||||
"eslint-plugin-security": "4.0.1",
|
"eslint-plugin-security": "4.0.1",
|
||||||
"prettier": "3.8.3",
|
"prettier": "3.8.3",
|
||||||
"rollup": "4.60.3",
|
"rollup": "4.62.2",
|
||||||
"tslib": "2.8.1",
|
"tslib": "2.8.1",
|
||||||
"typescript": "6.0.3",
|
"typescript": "6.0.3",
|
||||||
"typescript-eslint": "8.58.2"
|
"typescript-eslint": "8.58.2"
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-autostart"
|
links = "tauri-plugin-autostart"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-barcode-scanner"
|
links = "tauri-plugin-barcode-scanner"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-linux-android"]
|
targets = ["x86_64-linux-android"]
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ authors = { workspace = true }
|
|||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-biometric"
|
links = "tauri-plugin-biometric"
|
||||||
|
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-linux-android"]
|
targets = ["x86_64-linux-android"]
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-cli"
|
links = "tauri-plugin-cli"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-clipboard-manager"
|
links = "tauri-plugin-clipboard-manager"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-deep-link"
|
links = "tauri-plugin-deep-link"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/examples",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-linux-android"]
|
targets = ["x86_64-linux-android"]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "2.11.4",
|
"@tauri-apps/cli": "2.11.4",
|
||||||
"typescript": "^6.0.0",
|
"typescript": "^6.0.3",
|
||||||
"vite": "^8.0.1"
|
"vite": "^8.0.16"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ import { type UnlistenFn, listen } from '@tauri-apps/api/event'
|
|||||||
* const urls = await getCurrent();
|
* const urls = await getCurrent();
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### - **Windows / Linux**: This function reads the command line arguments and checks if there's only one value, which must be an URL with scheme matching one of the configured values.
|
* #### Platform-specific
|
||||||
* Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
|
*
|
||||||
* Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect..
|
* - **Windows / Linux:** This function reads the command line arguments and checks if there's only one value, which must be an URL with scheme matching one of the configured values.
|
||||||
|
* Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
|
||||||
|
* Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@@ -35,7 +37,9 @@ export async function getCurrent(): Promise<string[] | null> {
|
|||||||
* await register("my-scheme");
|
* await register("my-scheme");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### - **macOS / Android / iOS**: Unsupported.
|
* #### Platform-specific
|
||||||
|
*
|
||||||
|
* - **macOS / Android / iOS:** Unsupported.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +58,9 @@ export async function register(protocol: string): Promise<null> {
|
|||||||
* await unregister("my-scheme");
|
* await unregister("my-scheme");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### - **macOS / Linux / Android / iOS**: Unsupported.
|
* #### Platform-specific
|
||||||
|
*
|
||||||
|
* - **macOS / Linux / Android / iOS:** Unsupported.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@@ -73,7 +79,9 @@ export async function unregister(protocol: string): Promise<null> {
|
|||||||
* await isRegistered("my-scheme");
|
* await isRegistered("my-scheme");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### - **macOS / Android / iOS**: Unsupported.
|
* #### Platform-specific
|
||||||
|
*
|
||||||
|
* - **macOS / Android / iOS:** Unsupported.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@@ -92,7 +100,9 @@ export async function isRegistered(protocol: string): Promise<boolean> {
|
|||||||
* await onOpenUrl((urls) => { console.log(urls) });
|
* await onOpenUrl((urls) => { console.log(urls) });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### - **Windows / Linux**: Unsupported without the single-instance plugin. The OS will spawn a new app instance passing the URL as a CLI argument.
|
* #### Platform-specific
|
||||||
|
*
|
||||||
|
* - **Windows / Linux:** Unsupported without the single-instance plugin. The OS will spawn a new app instance passing the URL as a CLI argument.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-dialog"
|
links = "tauri-plugin-dialog"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/test",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["gtk3"]
|
default = ["gtk3"]
|
||||||
|
|||||||
@@ -204,9 +204,10 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
|
|||||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
intent.putExtra(Intent.EXTRA_TITLE, args.fileName ?: "")
|
intent.putExtra(Intent.EXTRA_TITLE, args.fileName ?: "")
|
||||||
intent.type = "*/*"
|
if (parsedTypes.size == 1) {
|
||||||
|
intent.type = parsedTypes.first()
|
||||||
if (parsedTypes.isNotEmpty()) {
|
} else {
|
||||||
|
intent.type = "*/*"
|
||||||
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
|
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-fs"
|
links = "tauri-plugin-fs"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write access in `$RESOURCES` folder" }
|
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write access in `$RESOURCES` folder" }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ description = """This denies read access to the
|
|||||||
`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.
|
`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.
|
||||||
Allowing access can lead to sensitive information disclosure and should be well considered."""
|
Allowing access can lead to sensitive information disclosure and should be well considered."""
|
||||||
|
|
||||||
[[scope.deny]]
|
[[permission.scope.deny]]
|
||||||
path = "$APPLOCALDATA/**"
|
path = "$APPLOCALDATA/**"
|
||||||
|
|
||||||
[[permission]]
|
[[permission]]
|
||||||
@@ -15,5 +15,5 @@ description = """This denies read access to the
|
|||||||
`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.
|
`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.
|
||||||
Allowing access can lead to sensitive information disclosure and should be well considered."""
|
Allowing access can lead to sensitive information disclosure and should be well considered."""
|
||||||
|
|
||||||
[[scope.deny]]
|
[[permission.scope.deny]]
|
||||||
path = "$APPLOCALDATA/EBWebView/**"
|
path = "$APPLOCALDATA/EBWebView/**"
|
||||||
|
|||||||
+106
-109
@@ -74,7 +74,7 @@ pub type CommandResult<T> = std::result::Result<T, CommandError>;
|
|||||||
/// Represents either a plain PathBuf or a PathHandle that manages security-scoped resources.
|
/// Represents either a plain PathBuf or a PathHandle that manages security-scoped resources.
|
||||||
pub enum PathKind<R: Runtime> {
|
pub enum PathKind<R: Runtime> {
|
||||||
/// A plain path that doesn't manage security-scoped resources.
|
/// A plain path that doesn't manage security-scoped resources.
|
||||||
#[allow(dead_code)] // only used on mobile
|
#[cfg(mobile)] // only used on mobile
|
||||||
Path(PathBuf),
|
Path(PathBuf),
|
||||||
/// A path handle that manages security-scoped resources and will clean them up on drop.
|
/// A path handle that manages security-scoped resources and will clean them up on drop.
|
||||||
Handle(PathHandle<R>),
|
Handle(PathHandle<R>),
|
||||||
@@ -84,6 +84,7 @@ impl<R: Runtime> PathKind<R> {
|
|||||||
/// Get a reference to the underlying path.
|
/// Get a reference to the underlying path.
|
||||||
pub fn as_path(&self) -> &Path {
|
pub fn as_path(&self) -> &Path {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(mobile)]
|
||||||
PathKind::Path(p) => p.as_ref(),
|
PathKind::Path(p) => p.as_ref(),
|
||||||
PathKind::Handle(h) => h.as_ref(),
|
PathKind::Handle(h) => h.as_ref(),
|
||||||
}
|
}
|
||||||
@@ -92,6 +93,7 @@ impl<R: Runtime> PathKind<R> {
|
|||||||
/// Get a reference to the underlying PathBuf.
|
/// Get a reference to the underlying PathBuf.
|
||||||
pub fn as_path_buf(&self) -> &PathBuf {
|
pub fn as_path_buf(&self) -> &PathBuf {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(mobile)]
|
||||||
PathKind::Path(p) => p,
|
PathKind::Path(p) => p,
|
||||||
PathKind::Handle(h) => h,
|
PathKind::Handle(h) => h,
|
||||||
}
|
}
|
||||||
@@ -114,27 +116,13 @@ impl<R: Runtime> AsRef<PathBuf> for PathKind<R> {
|
|||||||
pub struct FileHandle<R: Runtime> {
|
pub struct FileHandle<R: Runtime> {
|
||||||
file: File,
|
file: File,
|
||||||
path: PathKind<R>,
|
path: PathKind<R>,
|
||||||
#[allow(dead_code)] // Used in Drop implementation
|
#[cfg(target_os = "ios")]
|
||||||
path_: SafeFilePath,
|
path_: SafeFilePath,
|
||||||
#[allow(dead_code)] // Used in Drop implementation
|
#[cfg(target_os = "ios")]
|
||||||
app_handle: tauri::AppHandle<R>,
|
app_handle: tauri::AppHandle<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Runtime> FileHandle<R> {
|
impl<R: Runtime> FileHandle<R> {
|
||||||
fn new(
|
|
||||||
file: File,
|
|
||||||
path: PathKind<R>,
|
|
||||||
path_: SafeFilePath,
|
|
||||||
app_handle: tauri::AppHandle<R>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
file,
|
|
||||||
path,
|
|
||||||
path_,
|
|
||||||
app_handle,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the resolved path.
|
/// Get the resolved path.
|
||||||
pub fn path(&self) -> &Path {
|
pub fn path(&self) -> &Path {
|
||||||
self.path.as_path()
|
self.path.as_path()
|
||||||
@@ -155,41 +143,39 @@ impl<R: Runtime> DerefMut for FileHandle<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
impl<R: Runtime> Drop for FileHandle<R> {
|
impl<R: Runtime> Drop for FileHandle<R> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
#[cfg(target_os = "ios")]
|
// Only clean up if we have a plain PathBuf, not a PathHandle
|
||||||
{
|
// PathHandle will handle its own cleanup when it's dropped
|
||||||
// Only clean up if we have a plain PathBuf, not a PathHandle
|
if let PathKind::Path(_) = &self.path {
|
||||||
// PathHandle will handle its own cleanup when it's dropped
|
use crate::{FilePath, FsExt};
|
||||||
if let PathKind::Path(_) = &self.path {
|
// Convert SafeFilePath to FilePath
|
||||||
use crate::{FilePath, FsExt};
|
let file_path: FilePath = match &self.path_ {
|
||||||
// Convert SafeFilePath to FilePath
|
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
|
||||||
let file_path: FilePath = match &self.path_ {
|
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
|
||||||
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
|
};
|
||||||
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only clean up if we're tracking this resource
|
// Only clean up if we're tracking this resource
|
||||||
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
|
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
|
||||||
// and we shouldn't interfere
|
// and we shouldn't interfere
|
||||||
if let FilePath::Url(url) = file_path {
|
if let FilePath::Url(url) = file_path {
|
||||||
if url.scheme() == "file" {
|
if url.scheme() == "file" {
|
||||||
let security_scoped_resources =
|
let security_scoped_resources =
|
||||||
self.app_handle.state::<crate::SecurityScopedResources>();
|
self.app_handle.state::<crate::SecurityScopedResources>();
|
||||||
|
|
||||||
// Only clean up if it's not tracked manually
|
// Only clean up if it's not tracked manually
|
||||||
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
|
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
|
||||||
log::debug!("Stopping accessing security-scoped resource for URL: {url} on drop");
|
log::debug!(
|
||||||
let _ = self
|
"Stopping accessing security-scoped resource for URL: {url} on drop"
|
||||||
.app_handle
|
);
|
||||||
.fs()
|
let _ = self
|
||||||
.stop_accessing_security_scoped_resource(FilePath::Url(
|
.app_handle
|
||||||
url.clone(),
|
.fs()
|
||||||
));
|
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
|
||||||
security_scoped_resources.remove(url.as_str());
|
security_scoped_resources.remove(url.as_str());
|
||||||
} else {
|
} else {
|
||||||
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
|
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,38 +222,36 @@ impl<R: Runtime> AsRef<PathBuf> for PathHandle<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
impl<R: Runtime> Drop for PathHandle<R> {
|
impl<R: Runtime> Drop for PathHandle<R> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
#[cfg(target_os = "ios")]
|
use crate::{FilePath, FsExt};
|
||||||
{
|
// Convert SafeFilePath to FilePath
|
||||||
use crate::{FilePath, FsExt};
|
let file_path: FilePath = match &self.path_ {
|
||||||
// Convert SafeFilePath to FilePath
|
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
|
||||||
let file_path: FilePath = match &self.path_ {
|
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
|
||||||
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
|
};
|
||||||
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only clean up if we're tracking this resource (i.e., resolve_path started it)
|
// Only clean up if we're tracking this resource (i.e., resolve_path started it)
|
||||||
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
|
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
|
||||||
// and we shouldn't interfere
|
// and we shouldn't interfere
|
||||||
if let FilePath::Url(url) = file_path {
|
if let FilePath::Url(url) = file_path {
|
||||||
if url.scheme() == "file" {
|
if url.scheme() == "file" {
|
||||||
let security_scoped_resources =
|
let security_scoped_resources =
|
||||||
self.app_handle.state::<crate::SecurityScopedResources>();
|
self.app_handle.state::<crate::SecurityScopedResources>();
|
||||||
|
|
||||||
// Only clean up if it's not tracked manually
|
// Only clean up if it's not tracked manually
|
||||||
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
|
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Stopping accessing security-scoped resource for URL: {url} on drop"
|
"Stopping accessing security-scoped resource for URL: {url} on drop"
|
||||||
);
|
);
|
||||||
let _ = self
|
let _ = self
|
||||||
.app_handle
|
.app_handle
|
||||||
.fs()
|
.fs()
|
||||||
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
|
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
|
||||||
security_scoped_resources.remove(url.as_str());
|
security_scoped_resources.remove(url.as_str());
|
||||||
} else {
|
} else {
|
||||||
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
|
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,6 +272,7 @@ pub fn create<R: Runtime>(
|
|||||||
path: SafeFilePath,
|
path: SafeFilePath,
|
||||||
options: Option<BaseOptions>,
|
options: Option<BaseOptions>,
|
||||||
) -> CommandResult<ResourceId> {
|
) -> CommandResult<ResourceId> {
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
let path_ = path.clone();
|
let path_ = path.clone();
|
||||||
let resolved_path_handle = resolve_path(
|
let resolved_path_handle = resolve_path(
|
||||||
"create",
|
"create",
|
||||||
@@ -303,13 +288,16 @@ pub fn create<R: Runtime>(
|
|||||||
resolved_path_handle.display()
|
resolved_path_handle.display()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
let app_handle = webview.app_handle().clone();
|
let app_handle = webview.app_handle().clone();
|
||||||
let file_handle = FileHandle::new(
|
let file_handle = FileHandle {
|
||||||
file,
|
file,
|
||||||
PathKind::Handle(resolved_path_handle),
|
path: PathKind::Handle(resolved_path_handle),
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
path_,
|
path_,
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
app_handle,
|
app_handle,
|
||||||
);
|
};
|
||||||
let rid = webview
|
let rid = webview
|
||||||
.resources_table()
|
.resources_table()
|
||||||
.add(StdFileResource::new(file_handle));
|
.add(StdFileResource::new(file_handle));
|
||||||
@@ -1417,6 +1405,7 @@ fn resolve_file_in_fs<R: Runtime>(
|
|||||||
path: SafeFilePath,
|
path: SafeFilePath,
|
||||||
open_options: OpenOptions,
|
open_options: OpenOptions,
|
||||||
) -> CommandResult<FileHandle<R>> {
|
) -> CommandResult<FileHandle<R>> {
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
let path_ = path.clone();
|
let path_ = path.clone();
|
||||||
let resolved_path_handle = resolve_path(
|
let resolved_path_handle = resolve_path(
|
||||||
permission,
|
permission,
|
||||||
@@ -1436,13 +1425,16 @@ fn resolve_file_in_fs<R: Runtime>(
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
let app_handle = webview.app_handle().clone();
|
let app_handle = webview.app_handle().clone();
|
||||||
Ok(FileHandle::new(
|
Ok(FileHandle {
|
||||||
file,
|
file,
|
||||||
PathKind::Handle(resolved_path_handle),
|
path: PathKind::Handle(resolved_path_handle),
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
path_,
|
path_,
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
app_handle,
|
app_handle,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(mobile)]
|
#[cfg(mobile)]
|
||||||
@@ -1456,6 +1448,7 @@ pub fn resolve_file<R: Runtime>(
|
|||||||
) -> CommandResult<FileHandle<R>> {
|
) -> CommandResult<FileHandle<R>> {
|
||||||
use crate::FsExt;
|
use crate::FsExt;
|
||||||
|
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
let path_ = path.clone();
|
let path_ = path.clone();
|
||||||
match path {
|
match path {
|
||||||
SafeFilePath::Url(url) => {
|
SafeFilePath::Url(url) => {
|
||||||
@@ -1463,13 +1456,16 @@ pub fn resolve_file<R: Runtime>(
|
|||||||
let file = webview
|
let file = webview
|
||||||
.fs()
|
.fs()
|
||||||
.open(SafeFilePath::Url(url.clone()), open_options.options)?;
|
.open(SafeFilePath::Url(url.clone()), open_options.options)?;
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
let app_handle = webview.app_handle().clone();
|
let app_handle = webview.app_handle().clone();
|
||||||
Ok(FileHandle::new(
|
Ok(FileHandle {
|
||||||
file,
|
file,
|
||||||
PathKind::Path(resolved_path),
|
path: PathKind::Path(resolved_path),
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
path_,
|
path_,
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
app_handle,
|
app_handle,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
SafeFilePath::Path(path) => resolve_file_in_fs(
|
SafeFilePath::Path(path) => resolve_file_in_fs(
|
||||||
permission,
|
permission,
|
||||||
@@ -1494,36 +1490,37 @@ pub fn resolve_path<R: Runtime>(
|
|||||||
// On iOS, start accessing security-scoped resource if the path is a file URL
|
// On iOS, start accessing security-scoped resource if the path is a file URL
|
||||||
// Only if it hasn't been started already via start_accessing_security_scoped_resource
|
// Only if it hasn't been started already via start_accessing_security_scoped_resource
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
{
|
if let SafeFilePath::Url(url) = &path {
|
||||||
if let SafeFilePath::Url(url) = &path {
|
if url.scheme() == "file" {
|
||||||
if url.scheme() == "file" {
|
use objc2_foundation::{NSString, NSURL};
|
||||||
use objc2_foundation::{NSString, NSURL};
|
|
||||||
|
|
||||||
let security_scoped_resources = webview.state::<crate::SecurityScopedResources>();
|
let security_scoped_resources = webview.state::<crate::SecurityScopedResources>();
|
||||||
|
|
||||||
// Check if already active (started via start_accessing_security_scoped_resource)
|
// Check if already active (started via start_accessing_security_scoped_resource)
|
||||||
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
|
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
|
||||||
let url_nsstring = NSString::from_str(url.as_str());
|
let url_nsstring = NSString::from_str(url.as_str());
|
||||||
let ns_url = unsafe { NSURL::URLWithString(&url_nsstring) };
|
let ns_url = unsafe { NSURL::URLWithString(&url_nsstring) };
|
||||||
if let Some(ns_url) = ns_url {
|
if let Some(ns_url) = ns_url {
|
||||||
// Start accessing the security-scoped resource
|
// Start accessing the security-scoped resource
|
||||||
// This is required for files outside the app's sandbox (e.g., from file picker)
|
// This is required for files outside the app's sandbox (e.g., from file picker)
|
||||||
unsafe {
|
unsafe {
|
||||||
let success = ns_url.startAccessingSecurityScopedResource();
|
let success = ns_url.startAccessingSecurityScopedResource();
|
||||||
if success {
|
if success {
|
||||||
log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str());
|
log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str());
|
||||||
// Track it so we know to clean it up
|
// Track it so we know to clean it up
|
||||||
security_scoped_resources.track_manually(url.as_str().to_string());
|
security_scoped_resources.track_manually(url.as_str().to_string());
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Failed to start accessing security-scoped resource for URL: {}", url.as_str());
|
log::warn!(
|
||||||
}
|
"Failed to start accessing security-scoped resource for URL: {}",
|
||||||
|
url.as_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str());
|
log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ authors = { workspace = true }
|
|||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-geolocation"
|
links = "tauri-plugin-geolocation"
|
||||||
|
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-linux-android"]
|
targets = ["x86_64-linux-android"]
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-global-shortcut"
|
links = "tauri-plugin-global-shortcut"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ authors = { workspace = true }
|
|||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-haptics"
|
links = "tauri-plugin-haptics"
|
||||||
|
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-linux-android"]
|
targets = ["x86_64-linux-android"]
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-http"
|
links = "tauri-plugin-http"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ license = { workspace = true }
|
|||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
|
exclude = ["/banner.png"]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-log"
|
links = "tauri-plugin-log"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ authors = { workspace = true }
|
|||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-nfc"
|
links = "tauri-plugin-nfc"
|
||||||
|
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-linux-android"]
|
targets = ["x86_64-linux-android"]
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ impl<R: Runtime> Nfc<R> {
|
|||||||
pub fn scan(&self, payload: ScanRequest) -> crate::Result<ScanResponse> {
|
pub fn scan(&self, payload: ScanRequest) -> crate::Result<ScanResponse> {
|
||||||
self.0
|
self.0
|
||||||
.run_mobile_plugin("scan", payload)
|
.run_mobile_plugin("scan", payload)
|
||||||
|
.map(|v| ScanResponse { tag: v })
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-notification"
|
links = "tauri-plugin-notification"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/test",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
|
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
|
||||||
|
|||||||
@@ -80,11 +80,11 @@ class NotificationStorage(private val context: Context, private val jsonMapper:
|
|||||||
|
|
||||||
fun writeActionGroup(actions: List<ActionType>) {
|
fun writeActionGroup(actions: List<ActionType>) {
|
||||||
for (type in actions) {
|
for (type in actions) {
|
||||||
val i = type.id
|
|
||||||
val editor = getStorage(ACTION_TYPES_ID + type.id).edit()
|
val editor = getStorage(ACTION_TYPES_ID + type.id).edit()
|
||||||
editor.clear()
|
editor.clear()
|
||||||
editor.putInt("count", type.actions.size)
|
editor.putInt("count", type.actions.size)
|
||||||
for (action in type.actions) {
|
for (i in 0 until type.actions.size) {
|
||||||
|
val action = type.actions[i]
|
||||||
editor.putString("id$i", action.id)
|
editor.putString("id$i", action.id)
|
||||||
editor.putString("title$i", action.title)
|
editor.putString("title$i", action.title)
|
||||||
editor.putBoolean("input$i", action.input ?: false)
|
editor.putBoolean("input$i", action.input ?: false)
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ interface Options {
|
|||||||
/**
|
/**
|
||||||
* The sound resource name or file path for the notification.
|
* The sound resource name or file path for the notification.
|
||||||
*
|
*
|
||||||
* Platform specific behavior:
|
* ## Platform-specific behavior:
|
||||||
|
*
|
||||||
* - On macOS: use system sounds (e.g., "Ping", "Blow") or sound files in the app bundle
|
* - On macOS: use system sounds (e.g., "Ping", "Blow") or sound files in the app bundle
|
||||||
* - On Linux: use XDG theme sounds (e.g., "message-new-instant") or file paths
|
* - On Linux: use XDG theme sounds (e.g., "message-new-instant") or file paths
|
||||||
* - On Windows: use file paths to sound files (.wav format)
|
* - On Windows: use file paths to sound files (.wav format)
|
||||||
|
|||||||
@@ -320,6 +320,95 @@ pub struct ActionType {
|
|||||||
hidden_previews_show_subtitle: bool,
|
hidden_previews_show_subtitle: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(mobile)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ActionTypeBuilder(ActionType);
|
||||||
|
|
||||||
|
#[cfg(mobile)]
|
||||||
|
impl ActionType {
|
||||||
|
pub fn builder(id: impl Into<String>) -> ActionTypeBuilder {
|
||||||
|
ActionTypeBuilder(Self {
|
||||||
|
id: id.into(),
|
||||||
|
actions: Vec::new(),
|
||||||
|
hidden_previews_body_placeholder: None,
|
||||||
|
custom_dismiss_action: false,
|
||||||
|
allow_in_car_play: false,
|
||||||
|
hidden_previews_show_title: false,
|
||||||
|
hidden_previews_show_subtitle: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> &str {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn actions(&self) -> &[Action] {
|
||||||
|
&self.actions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden_previews_body_placeholder(&self) -> Option<&str> {
|
||||||
|
self.hidden_previews_body_placeholder.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn custom_dismiss_action(&self) -> bool {
|
||||||
|
self.custom_dismiss_action
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow_in_car_play(&self) -> bool {
|
||||||
|
self.allow_in_car_play
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden_previews_show_title(&self) -> bool {
|
||||||
|
self.hidden_previews_show_title
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden_previews_show_subtitle(&self) -> bool {
|
||||||
|
self.hidden_previews_show_subtitle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(mobile)]
|
||||||
|
impl ActionTypeBuilder {
|
||||||
|
pub fn actions(mut self, actions: Vec<Action>) -> Self {
|
||||||
|
self.0.actions = actions;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden_previews_body_placeholder(
|
||||||
|
mut self,
|
||||||
|
hidden_previews_body_placeholder: impl Into<String>,
|
||||||
|
) -> Self {
|
||||||
|
self.0
|
||||||
|
.hidden_previews_body_placeholder
|
||||||
|
.replace(hidden_previews_body_placeholder.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn custom_dismiss_action(mut self, custom_dismiss_action: bool) -> Self {
|
||||||
|
self.0.custom_dismiss_action = custom_dismiss_action;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow_in_car_play(mut self, allow_in_car_play: bool) -> Self {
|
||||||
|
self.0.allow_in_car_play = allow_in_car_play;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden_previews_show_title(mut self, hidden_previews_show_title: bool) -> Self {
|
||||||
|
self.0.hidden_previews_show_title = hidden_previews_show_title;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden_previews_show_subtitle(mut self, hidden_previews_show_subtitle: bool) -> Self {
|
||||||
|
self.0.hidden_previews_show_subtitle = hidden_previews_show_subtitle;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> ActionType {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(mobile)]
|
#[cfg(mobile)]
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -334,6 +423,95 @@ pub struct Action {
|
|||||||
input_placeholder: Option<String>,
|
input_placeholder: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(mobile)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ActionBuilder(Action);
|
||||||
|
|
||||||
|
#[cfg(mobile)]
|
||||||
|
impl Action {
|
||||||
|
pub fn builder(id: impl Into<String>, title: impl Into<String>) -> ActionBuilder {
|
||||||
|
ActionBuilder(Self {
|
||||||
|
id: id.into(),
|
||||||
|
title: title.into(),
|
||||||
|
requires_authentication: false,
|
||||||
|
foreground: false,
|
||||||
|
destructive: false,
|
||||||
|
input: false,
|
||||||
|
input_button_title: None,
|
||||||
|
input_placeholder: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> &str {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn title(&self) -> &str {
|
||||||
|
&self.title
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn requires_authentication(&self) -> bool {
|
||||||
|
self.requires_authentication
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn foreground(&self) -> bool {
|
||||||
|
self.foreground
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destructive(&self) -> bool {
|
||||||
|
self.destructive
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input(&self) -> bool {
|
||||||
|
self.input
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_button_title(&self) -> Option<&str> {
|
||||||
|
self.input_button_title.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_placeholder(&self) -> Option<&str> {
|
||||||
|
self.input_placeholder.as_deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(mobile)]
|
||||||
|
impl ActionBuilder {
|
||||||
|
pub fn requires_authentication(mut self, requires_authentication: bool) -> Self {
|
||||||
|
self.0.requires_authentication = requires_authentication;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn foreground(mut self, foreground: bool) -> Self {
|
||||||
|
self.0.foreground = foreground;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destructive(mut self, destructive: bool) -> Self {
|
||||||
|
self.0.destructive = destructive;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input(mut self, input: bool) -> Self {
|
||||||
|
self.0.input = input;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_button_title(mut self, input_button_title: impl Into<String>) -> Self {
|
||||||
|
self.0.input_button_title.replace(input_button_title.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_placeholder(mut self, input_placeholder: impl Into<String>) -> Self {
|
||||||
|
self.0.input_placeholder.replace(input_placeholder.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Action {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
pub use android::*;
|
pub use android::*;
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ links = "tauri-plugin-opener"
|
|||||||
# Platforms supported by the plugin
|
# Platforms supported by the plugin
|
||||||
# Support levels are "full", "partial", "none", "unknown"
|
# Support levels are "full", "partial", "none", "unknown"
|
||||||
# Details of the support level are left to plugin maintainer
|
# Details of the support level are left to plugin maintainer
|
||||||
|
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
linux = { level = "full", notes = "" }
|
linux = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-os"
|
links = "tauri-plugin-os"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ license = { workspace = true }
|
|||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
|
exclude = ["/banner.png"]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-positioner"
|
links = "tauri-plugin-positioner"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-process"
|
links = "tauri-plugin-process"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-shell"
|
links = "tauri-plugin-shell"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/test",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ license = { workspace = true }
|
|||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
exclude = ["/examples"]
|
exclude = ["/banner.png", "/examples"]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-sql"
|
links = "tauri-plugin-sql"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["sqlite"]
|
features = ["sqlite"]
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-store"
|
links = "tauri-plugin-store"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/examples",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "2.11.4",
|
"@tauri-apps/cli": "2.11.4",
|
||||||
"typescript": "^6.0.0",
|
"typescript": "^6.0.3",
|
||||||
"vite": "^8.0.1"
|
"vite": "^8.0.16"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-stronghold"
|
links = "tauri-plugin-stronghold"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ license = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-updater"
|
links = "tauri-plugin-updater"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tests",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
no-default-features = true
|
no-default-features = true
|
||||||
@@ -45,7 +53,7 @@ base64 = "0.22"
|
|||||||
semver = { version = "1", features = ["serde"] }
|
semver = { version = "1", features = ["serde"] }
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
tempfile = "3.20"
|
tempfile = "3.20"
|
||||||
infer = "0.22"
|
infer = "0.19"
|
||||||
percent-encoding = "2.3"
|
percent-encoding = "2.3"
|
||||||
|
|
||||||
[target."cfg(target_os = \"windows\")".dependencies]
|
[target."cfg(target_os = \"windows\")".dependencies]
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ import { relaunch } from '@tauri-apps/plugin-process'
|
|||||||
const update = await check()
|
const update = await check()
|
||||||
if (update) {
|
if (update) {
|
||||||
await update.downloadAndInstall()
|
await update.downloadAndInstall()
|
||||||
|
// Relaunch the app on macOS and Linux to run the newly install version
|
||||||
await relaunch()
|
await relaunch()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(t){"use strict";function e(t,e,s,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(t):n?n.value:e.get(t)}function s(t,e,s,n,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,s),s}var n,i,a,r,o;"function"==typeof SuppressedError&&SuppressedError;const d="__TAURI_TO_IPC_KEY__";class c{constructor(t){n.set(this,void 0),i.set(this,0),a.set(this,[]),r.set(this,void 0),s(this,n,t||(()=>{})),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}(t=>{const o=t.index;if("end"in t)return void(o==e(this,i,"f")?this.cleanupCallback():s(this,r,o));const d=t.message;if(o==e(this,i,"f")){for(e(this,n,"f").call(this,d),s(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,a,"f");){const t=e(this,a,"f")[e(this,i,"f")];e(this,n,"f").call(this,t),delete e(this,a,"f")[e(this,i,"f")],s(this,i,e(this,i,"f")+1)}e(this,i,"f")===e(this,r,"f")&&this.cleanupCallback()}else e(this,a,"f")[o]=d})}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(t){s(this,n,t)}get onmessage(){return e(this,n,"f")}[(n=new WeakMap,i=new WeakMap,a=new WeakMap,r=new WeakMap,d)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[d]()}}async function l(t,e={},s){return window.__TAURI_INTERNALS__.invoke(t,e,s)}class h{get rid(){return e(this,o,"f")}constructor(t){o.set(this,void 0),s(this,o,t)}async close(){return l("plugin:resources|close",{rid:this.rid})}}o=new WeakMap;class u extends h{constructor(t){super(t.rid),this.available=!0,this.currentVersion=t.currentVersion,this.version=t.version,this.date=t.date,this.body=t.body,this.rawJson=t.rawJson}async download(t,e){_(e);const s=new c;t&&(s.onmessage=t);const n=await l("plugin:updater|download",{onEvent:s,rid:this.rid,...e});this.downloadedBytes=new h(n)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await l("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(t,e){_(e);const s=new c;t&&(s.onmessage=t),await l("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...e})}async close(){await(this.downloadedBytes?.close()),await super.close()}}function _(t){t?.headers&&(t.headers=Array.from(new Headers(t.headers).entries()))}return t.Update=u,t.check=async function(t){_(t);const e=await l("plugin:updater|check",{...t});return e?new u(e):null},t}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
|
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(t){"use strict";function e(t,e,s,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(t):n?n.value:e.get(t)}function s(t,e,s,n,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,s),s}var n,i,a,r,o;"function"==typeof SuppressedError&&SuppressedError;const d="__TAURI_TO_IPC_KEY__";class c{constructor(t){n.set(this,void 0),i.set(this,0),a.set(this,[]),r.set(this,void 0),s(this,n,t||(()=>{})),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}(t=>{const o=t.index;if("end"in t)return void(o==e(this,i,"f")?this.cleanupCallback():s(this,r,o));const d=t.message;if(o==e(this,i,"f")){for(e(this,n,"f").call(this,d),s(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,a,"f");){const t=e(this,a,"f")[e(this,i,"f")];e(this,n,"f").call(this,t),delete e(this,a,"f")[e(this,i,"f")],s(this,i,e(this,i,"f")+1)}e(this,i,"f")===e(this,r,"f")&&this.cleanupCallback()}else e(this,a,"f")[o]=d})}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(t){s(this,n,t)}get onmessage(){return e(this,n,"f")}[(n=new WeakMap,i=new WeakMap,a=new WeakMap,r=new WeakMap,d)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[d]()}}async function l(t,e={},s){return window.__TAURI_INTERNALS__.invoke(t,e,s)}class h{get rid(){return e(this,o,"f")}constructor(t){o.set(this,void 0),s(this,o,t)}async close(){return l("plugin:resources|close",{rid:this.rid})}}o=new WeakMap;class u extends h{constructor(t){super(t.rid),this.available=!0,this.currentVersion=t.currentVersion,this.version=t.version,this.date=t.date,this.body=t.body,this.rawJson=t.rawJson}async download(t,e){_(e);const s=new c;t&&(s.onmessage=t);const n=await l("plugin:updater|download",{onEvent:s,rid:this.rid,...e});this.downloadedBytes=new h(n)}async install(t){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await l("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid,...t}),this.downloadedBytes=void 0}async downloadAndInstall(t,e){_(e);const s=new c;t&&(s.onmessage=t),await l("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...e})}async close(){await(this.downloadedBytes?.close()),await super.close()}}function _(t){t?.headers&&(t.headers=Array.from(new Headers(t.headers).entries()))}return t.Update=u,t.check=async function(t){_(t);const e=await l("plugin:updater|check",{...t});return e?new u(e):null},t}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ interface DownloadOptions {
|
|||||||
timeout?: number
|
timeout?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Options used when installing an update */
|
||||||
|
interface InstallOptions {
|
||||||
|
/**
|
||||||
|
* If the Windows installer should restart the app after installed, default is `true`
|
||||||
|
*/
|
||||||
|
restartAfterInstall?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
interface UpdateMetadata {
|
interface UpdateMetadata {
|
||||||
rid: number
|
rid: number
|
||||||
currentVersion: string
|
currentVersion: string
|
||||||
@@ -76,7 +84,7 @@ class Update extends Resource {
|
|||||||
this.rawJson = metadata.rawJson
|
this.rawJson = metadata.rawJson
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Download the updater package */
|
/** Download the updater package. Call {@linkcode install} later to install it */
|
||||||
async download(
|
async download(
|
||||||
onEvent?: (progress: DownloadEvent) => void,
|
onEvent?: (progress: DownloadEvent) => void,
|
||||||
options?: DownloadOptions
|
options?: DownloadOptions
|
||||||
@@ -94,25 +102,40 @@ class Update extends Resource {
|
|||||||
this.downloadedBytes = new Resource(downloadedBytesRid)
|
this.downloadedBytes = new Resource(downloadedBytesRid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Install downloaded updater package */
|
/**
|
||||||
async install(): Promise<void> {
|
* Install downloaded updater package. Must be called after {@linkcode download}.
|
||||||
|
*
|
||||||
|
* ## Platform-specific:
|
||||||
|
*
|
||||||
|
* - **Windows:** This function exits the app after launching the updater installer successfully
|
||||||
|
* - **macOS / Linux:** You need to relaunch the app to run the newly install version
|
||||||
|
*/
|
||||||
|
async install(options?: InstallOptions): Promise<void> {
|
||||||
if (!this.downloadedBytes) {
|
if (!this.downloadedBytes) {
|
||||||
throw new Error('Update.install called before Update.download')
|
throw new Error('Update.install called before Update.download')
|
||||||
}
|
}
|
||||||
|
|
||||||
await invoke('plugin:updater|install', {
|
await invoke('plugin:updater|install', {
|
||||||
updateRid: this.rid,
|
updateRid: this.rid,
|
||||||
bytesRid: this.downloadedBytes.rid
|
bytesRid: this.downloadedBytes.rid,
|
||||||
|
...options
|
||||||
})
|
})
|
||||||
|
|
||||||
// Don't need to call close, we did it in rust side already
|
// Don't need to call close, we did it in rust side already
|
||||||
this.downloadedBytes = undefined
|
this.downloadedBytes = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Downloads the updater package and installs it */
|
/**
|
||||||
|
* Downloads the updater package and installs it
|
||||||
|
*
|
||||||
|
* ## Platform-specific:
|
||||||
|
*
|
||||||
|
* - **Windows:** This function exits the app after launching the updater installer successfully
|
||||||
|
* - **macOS / Linux:** You need to relaunch the app to run the newly install version
|
||||||
|
*/
|
||||||
async downloadAndInstall(
|
async downloadAndInstall(
|
||||||
onEvent?: (progress: DownloadEvent) => void,
|
onEvent?: (progress: DownloadEvent) => void,
|
||||||
options?: DownloadOptions
|
options?: DownloadOptions & InstallOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
convertToRustHeaders(options)
|
convertToRustHeaders(options)
|
||||||
const channel = new Channel<DownloadEvent>()
|
const channel = new Channel<DownloadEvent>()
|
||||||
|
|||||||
@@ -142,12 +142,22 @@ pub(crate) async fn install<R: Runtime>(
|
|||||||
webview: Webview<R>,
|
webview: Webview<R>,
|
||||||
update_rid: ResourceId,
|
update_rid: ResourceId,
|
||||||
bytes_rid: ResourceId,
|
bytes_rid: ResourceId,
|
||||||
|
restart_after_install: Option<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let update = webview.resources_table().get::<Update>(update_rid)?;
|
let update = webview.resources_table().get::<Update>(update_rid)?;
|
||||||
let bytes = webview
|
let bytes = webview
|
||||||
.resources_table()
|
.resources_table()
|
||||||
.get::<DownloadedBytes>(bytes_rid)?;
|
.get::<DownloadedBytes>(bytes_rid)?;
|
||||||
update.install(&bytes.0)?;
|
|
||||||
|
if let Some(restart_after_install) = restart_after_install {
|
||||||
|
let update = (*update).clone();
|
||||||
|
update
|
||||||
|
.restart_after_install(restart_after_install)
|
||||||
|
.install(&bytes.0)?;
|
||||||
|
} else {
|
||||||
|
update.install(&bytes.0)?;
|
||||||
|
}
|
||||||
|
|
||||||
let _ = webview.resources_table().close(bytes_rid);
|
let _ = webview.resources_table().close(bytes_rid);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -159,6 +169,7 @@ pub(crate) async fn download_and_install<R: Runtime>(
|
|||||||
on_event: Channel<DownloadEvent>,
|
on_event: Channel<DownloadEvent>,
|
||||||
headers: Option<Vec<(String, String)>>,
|
headers: Option<Vec<(String, String)>>,
|
||||||
timeout: Option<u64>,
|
timeout: Option<u64>,
|
||||||
|
restart_after_install: Option<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let update = webview.resources_table().get::<Update>(rid)?;
|
let update = webview.resources_table().get::<Update>(rid)?;
|
||||||
|
|
||||||
@@ -176,6 +187,10 @@ pub(crate) async fn download_and_install<R: Runtime>(
|
|||||||
update.timeout = Some(Duration::from_millis(timeout));
|
update.timeout = Some(Duration::from_millis(timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(restart_after_install) = restart_after_install {
|
||||||
|
update = update.restart_after_install(restart_after_install);
|
||||||
|
}
|
||||||
|
|
||||||
let mut first_chunk = true;
|
let mut first_chunk = true;
|
||||||
|
|
||||||
update
|
update
|
||||||
|
|||||||
@@ -32,17 +32,30 @@ impl WindowsUpdateInstallMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub(crate) fn msi_restart_after_install_args(&self) -> &'static [&'static str] {
|
||||||
|
&["AUTOLAUNCHAPP=True"]
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the associated nsis arguments.
|
/// Returns the associated nsis arguments.
|
||||||
pub fn nsis_args(&self) -> &'static [&'static str] {
|
pub fn nsis_args(&self) -> &'static [&'static str] {
|
||||||
// `/P`: Passive
|
// `/P`: Passive
|
||||||
// `/S`: Silent
|
// `/S`: Silent
|
||||||
// `/R`: Restart
|
// `/R`: Restart
|
||||||
match self {
|
match self {
|
||||||
Self::Passive => &["/P", "/R"],
|
Self::Passive => &["/P"],
|
||||||
Self::Quiet => &["/S", "/R"],
|
Self::Quiet => &["/S"],
|
||||||
_ => &[],
|
_ => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub(crate) fn nsis_restart_after_install_args(&self) -> &'static [&'static str] {
|
||||||
|
match self {
|
||||||
|
Self::BasicUi => &[],
|
||||||
|
_ => &["/R"],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for WindowsUpdateInstallMode {
|
impl Display for WindowsUpdateInstallMode {
|
||||||
@@ -63,6 +76,8 @@ impl Display for WindowsUpdateInstallMode {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct WindowsConfig {
|
pub struct WindowsConfig {
|
||||||
/// Additional arguments given to the NSIS or WiX installer.
|
/// Additional arguments given to the NSIS or WiX installer.
|
||||||
|
///
|
||||||
|
/// Note: this applies to both WiX and NSIS installers
|
||||||
#[serde(
|
#[serde(
|
||||||
default,
|
default,
|
||||||
alias = "installer-args",
|
alias = "installer-args",
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ impl<R: Runtime, T: Manager<R>> UpdaterExt<R> for T {
|
|||||||
builder = builder.target(target);
|
builder = builder.target(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = self.env().args_os;
|
#[cfg(windows)]
|
||||||
if !args.is_empty() {
|
{
|
||||||
builder = builder.current_exe_args(args);
|
builder = builder.current_exe_args(self.env().args_os);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.version_comparator = version_comparator.clone();
|
builder.version_comparator = version_comparator.clone();
|
||||||
|
|||||||
+226
-149
@@ -129,16 +129,34 @@ impl RemoteRelease {
|
|||||||
pub type OnBeforeExit = Arc<dyn Fn() + Send + Sync + 'static>;
|
pub type OnBeforeExit = Arc<dyn Fn() + Send + Sync + 'static>;
|
||||||
pub type OnBeforeRequest = Arc<dyn Fn(ClientBuilder) -> ClientBuilder + Send + Sync + 'static>;
|
pub type OnBeforeRequest = Arc<dyn Fn(ClientBuilder) -> ClientBuilder + Send + Sync + 'static>;
|
||||||
pub type VersionComparator = Arc<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>;
|
pub type VersionComparator = Arc<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
type MainThreadClosure = Box<dyn FnOnce() + Send + Sync + 'static>;
|
type MainThreadClosure = Box<dyn FnOnce() + Send + Sync + 'static>;
|
||||||
type RunOnMainThread =
|
#[cfg(target_os = "macos")]
|
||||||
Box<dyn Fn(MainThreadClosure) -> std::result::Result<(), tauri::Error> + Send + Sync + 'static>;
|
type RunOnMainThread = Arc<dyn Fn(MainThreadClosure) -> tauri::Result<()> + Send + Sync + 'static>;
|
||||||
|
|
||||||
|
// TODO: Move more fields to this in v3 if we can mark those fields non `pub`
|
||||||
|
/// Updater context shared between [`UpdaterBuilder`], [`Updater`] and [`Update`]
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct UpdaterContext {
|
||||||
|
config: Config,
|
||||||
|
configure_client: Option<OnBeforeRequest>,
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
run_on_main_thread: RunOnMainThread,
|
||||||
|
/// App name, used for creating named tempfiles
|
||||||
|
#[cfg(windows)]
|
||||||
|
app_name: String,
|
||||||
|
#[cfg(windows)]
|
||||||
|
installer_args: Vec<OsString>,
|
||||||
|
#[cfg(windows)]
|
||||||
|
current_exe_args: Vec<OsString>,
|
||||||
|
#[cfg(windows)]
|
||||||
|
on_before_exit: Option<OnBeforeExit>,
|
||||||
|
#[cfg(windows)]
|
||||||
|
restart_after_install: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct UpdaterBuilder {
|
pub struct UpdaterBuilder {
|
||||||
#[allow(dead_code)]
|
|
||||||
run_on_main_thread: RunOnMainThread,
|
|
||||||
app_name: String,
|
|
||||||
current_version: Version,
|
current_version: Version,
|
||||||
config: Config,
|
|
||||||
pub(crate) version_comparator: Option<VersionComparator>,
|
pub(crate) version_comparator: Option<VersionComparator>,
|
||||||
executable_path: Option<PathBuf>,
|
executable_path: Option<PathBuf>,
|
||||||
target: Option<String>,
|
target: Option<String>,
|
||||||
@@ -147,27 +165,38 @@ pub struct UpdaterBuilder {
|
|||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
proxy: Option<Url>,
|
proxy: Option<Url>,
|
||||||
no_proxy: bool,
|
no_proxy: bool,
|
||||||
installer_args: Vec<OsString>,
|
context: UpdaterContext,
|
||||||
current_exe_args: Vec<OsString>,
|
|
||||||
on_before_exit: Option<OnBeforeExit>,
|
|
||||||
configure_client: Option<OnBeforeRequest>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdaterBuilder {
|
impl UpdaterBuilder {
|
||||||
pub(crate) fn new<R: Runtime>(app: &AppHandle<R>, config: crate::Config) -> Self {
|
pub(crate) fn new<R: Runtime>(app: &AppHandle<R>, config: crate::Config) -> Self {
|
||||||
let app_ = app.clone();
|
#[cfg(target_os = "macos")]
|
||||||
let run_on_main_thread = move |f| app_.run_on_main_thread(f);
|
let run_on_main_thread = {
|
||||||
|
let app_ = app.clone();
|
||||||
|
Arc::new(move |f| app_.run_on_main_thread(f))
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
run_on_main_thread: Box::new(run_on_main_thread),
|
context: UpdaterContext {
|
||||||
installer_args: config
|
#[cfg(windows)]
|
||||||
.windows
|
installer_args: config
|
||||||
.as_ref()
|
.windows
|
||||||
.map(|w| w.installer_args.clone())
|
.as_ref()
|
||||||
.unwrap_or_default(),
|
.map(|w| w.installer_args.clone())
|
||||||
current_exe_args: Vec::new(),
|
.unwrap_or_default(),
|
||||||
app_name: app.package_info().name.clone(),
|
config,
|
||||||
|
configure_client: None,
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
run_on_main_thread,
|
||||||
|
#[cfg(windows)]
|
||||||
|
app_name: app.package_info().name.clone(),
|
||||||
|
#[cfg(windows)]
|
||||||
|
current_exe_args: Vec::new(),
|
||||||
|
#[cfg(windows)]
|
||||||
|
on_before_exit: None,
|
||||||
|
#[cfg(windows)]
|
||||||
|
restart_after_install: true,
|
||||||
|
},
|
||||||
current_version: app.package_info().version.clone(),
|
current_version: app.package_info().version.clone(),
|
||||||
config,
|
|
||||||
version_comparator: None,
|
version_comparator: None,
|
||||||
executable_path: None,
|
executable_path: None,
|
||||||
target: None,
|
target: None,
|
||||||
@@ -176,8 +205,6 @@ impl UpdaterBuilder {
|
|||||||
timeout: None,
|
timeout: None,
|
||||||
proxy: None,
|
proxy: None,
|
||||||
no_proxy: false,
|
no_proxy: false,
|
||||||
on_before_exit: None,
|
|
||||||
configure_client: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +224,7 @@ impl UpdaterBuilder {
|
|||||||
pub fn endpoints(mut self, endpoints: Vec<Url>) -> Result<Self> {
|
pub fn endpoints(mut self, endpoints: Vec<Url>) -> Result<Self> {
|
||||||
crate::config::validate_endpoints(
|
crate::config::validate_endpoints(
|
||||||
&endpoints,
|
&endpoints,
|
||||||
self.config.dangerous_insecure_transport_protocol,
|
self.context.config.dangerous_insecure_transport_protocol,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.endpoints.replace(endpoints);
|
self.endpoints.replace(endpoints);
|
||||||
@@ -251,26 +278,40 @@ impl UpdaterBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pubkey<S: Into<String>>(mut self, pubkey: S) -> Self {
|
pub fn pubkey<S: Into<String>>(mut self, pubkey: S) -> Self {
|
||||||
self.config.pubkey = pubkey.into();
|
self.context.config.pubkey = pubkey.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an argument to pass to the Windows installer.
|
/// Adds an argument to pass to the Windows installer.
|
||||||
|
///
|
||||||
|
/// Note: this applies to both WiX and NSIS installers
|
||||||
|
#[cfg_attr(not(windows), allow(unused))]
|
||||||
pub fn installer_arg<S>(mut self, arg: S) -> Self
|
pub fn installer_arg<S>(mut self, arg: S) -> Self
|
||||||
where
|
where
|
||||||
S: Into<OsString>,
|
S: Into<OsString>,
|
||||||
{
|
{
|
||||||
self.installer_args.push(arg.into());
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
self.context.installer_args.push(arg.into());
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds multiple arguments to pass to the Windows installer.
|
/// Adds multiple arguments to pass to the Windows installer.
|
||||||
|
///
|
||||||
|
/// Note: this applies to both WiX and NSIS installers
|
||||||
|
#[cfg_attr(not(windows), allow(unused))]
|
||||||
pub fn installer_args<I, S>(mut self, args: I) -> Self
|
pub fn installer_args<I, S>(mut self, args: I) -> Self
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = S>,
|
I: IntoIterator<Item = S>,
|
||||||
S: Into<OsString>,
|
S: Into<OsString>,
|
||||||
{
|
{
|
||||||
self.installer_args.extend(args.into_iter().map(Into::into));
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
self.context
|
||||||
|
.installer_args
|
||||||
|
.extend(args.into_iter().map(Into::into));
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,14 +321,32 @@ impl UpdaterBuilder {
|
|||||||
/// [`Self::installer_arg`], [`crate::Builder::installer_arg`]
|
/// [`Self::installer_arg`], [`crate::Builder::installer_arg`]
|
||||||
/// and the `plugins > updater > windows > installerArgs` config,
|
/// and the `plugins > updater > windows > installerArgs` config,
|
||||||
/// not the ones managed by us (e.g. `/UPDATER` flag passed to the NSIS installer)
|
/// not the ones managed by us (e.g. `/UPDATER` flag passed to the NSIS installer)
|
||||||
|
#[cfg_attr(not(windows), allow(unused))]
|
||||||
pub fn clear_installer_args(mut self) -> Self {
|
pub fn clear_installer_args(mut self) -> Self {
|
||||||
self.installer_args.clear();
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
self.context.installer_args.clear();
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function to run before we run the installer and exit the app through `std::process::exit(0)` on Windows
|
/// Function to run before we run the installer and exit the app through `std::process::exit(0)` on Windows
|
||||||
|
#[cfg_attr(not(windows), allow(unused))]
|
||||||
pub fn on_before_exit<F: Fn() + Send + Sync + 'static>(mut self, f: F) -> Self {
|
pub fn on_before_exit<F: Fn() + Send + Sync + 'static>(mut self, f: F) -> Self {
|
||||||
self.on_before_exit.replace(Arc::new(f));
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
self.context.on_before_exit.replace(Arc::new(f));
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the Windows installer should restart the app after installed, default is `true`
|
||||||
|
#[cfg_attr(not(windows), allow(unused))]
|
||||||
|
pub fn restart_after_install(mut self, restart_after_install: bool) -> Self {
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
self.context.restart_after_install = restart_after_install;
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,14 +358,14 @@ impl UpdaterBuilder {
|
|||||||
mut self,
|
mut self,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.configure_client.replace(Arc::new(f));
|
self.context.configure_client.replace(Arc::new(f));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Result<Updater> {
|
pub fn build(self) -> Result<Updater> {
|
||||||
let endpoints = self
|
let endpoints = self
|
||||||
.endpoints
|
.endpoints
|
||||||
.unwrap_or_else(|| self.config.endpoints.clone());
|
.unwrap_or_else(|| self.context.config.endpoints.clone());
|
||||||
|
|
||||||
if endpoints.is_empty() {
|
if endpoints.is_empty() {
|
||||||
return Err(Error::EmptyEndpoints);
|
return Err(Error::EmptyEndpoints);
|
||||||
@@ -324,44 +383,36 @@ impl UpdaterBuilder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(Updater {
|
Ok(Updater {
|
||||||
run_on_main_thread: Arc::new(self.run_on_main_thread),
|
|
||||||
config: self.config,
|
|
||||||
app_name: self.app_name,
|
|
||||||
current_version: self.current_version,
|
current_version: self.current_version,
|
||||||
version_comparator: self.version_comparator,
|
version_comparator: self.version_comparator,
|
||||||
timeout: self.timeout,
|
timeout: self.timeout,
|
||||||
proxy: self.proxy,
|
proxy: self.proxy,
|
||||||
no_proxy: self.no_proxy,
|
no_proxy: self.no_proxy,
|
||||||
endpoints,
|
endpoints,
|
||||||
installer_args: self.installer_args,
|
|
||||||
current_exe_args: self.current_exe_args,
|
|
||||||
arch,
|
arch,
|
||||||
target: self.target,
|
target: self.target,
|
||||||
headers: self.headers,
|
headers: self.headers,
|
||||||
extract_path,
|
extract_path,
|
||||||
on_before_exit: self.on_before_exit,
|
context: self.context.clone(),
|
||||||
configure_client: self.configure_client,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
impl UpdaterBuilder {
|
impl UpdaterBuilder {
|
||||||
pub(crate) fn current_exe_args<I, S>(mut self, args: I) -> Self
|
pub(crate) fn current_exe_args<I, S>(mut self, args: I) -> Self
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = S>,
|
I: IntoIterator<Item = S>,
|
||||||
S: Into<OsString>,
|
S: Into<OsString>,
|
||||||
{
|
{
|
||||||
self.current_exe_args
|
self.context
|
||||||
|
.current_exe_args
|
||||||
.extend(args.into_iter().map(Into::into));
|
.extend(args.into_iter().map(Into::into));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Updater {
|
pub struct Updater {
|
||||||
#[allow(dead_code)]
|
|
||||||
run_on_main_thread: Arc<RunOnMainThread>,
|
|
||||||
config: Config,
|
|
||||||
app_name: String,
|
|
||||||
current_version: Version,
|
current_version: Version,
|
||||||
version_comparator: Option<VersionComparator>,
|
version_comparator: Option<VersionComparator>,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
@@ -374,12 +425,7 @@ pub struct Updater {
|
|||||||
target: Option<String>,
|
target: Option<String>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
extract_path: PathBuf,
|
extract_path: PathBuf,
|
||||||
on_before_exit: Option<OnBeforeExit>,
|
context: UpdaterContext,
|
||||||
configure_client: Option<OnBeforeRequest>,
|
|
||||||
#[allow(unused)]
|
|
||||||
installer_args: Vec<OsString>,
|
|
||||||
#[allow(unused)]
|
|
||||||
current_exe_args: Vec<OsString>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Updater {
|
impl Updater {
|
||||||
@@ -449,10 +495,10 @@ impl Updater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut request = ClientBuilder::new().user_agent(UPDATER_USER_AGENT);
|
let mut request = ClientBuilder::new().user_agent(UPDATER_USER_AGENT);
|
||||||
if self.config.dangerous_accept_invalid_certs {
|
if self.context.config.dangerous_accept_invalid_certs {
|
||||||
request = request.danger_accept_invalid_certs(true);
|
request = request.danger_accept_invalid_certs(true);
|
||||||
}
|
}
|
||||||
if self.config.dangerous_accept_invalid_hostnames {
|
if self.context.config.dangerous_accept_invalid_hostnames {
|
||||||
request = request.danger_accept_invalid_hostnames(true);
|
request = request.danger_accept_invalid_hostnames(true);
|
||||||
}
|
}
|
||||||
if let Some(timeout) = self.timeout {
|
if let Some(timeout) = self.timeout {
|
||||||
@@ -467,7 +513,7 @@ impl Updater {
|
|||||||
request = request.proxy(proxy);
|
request = request.proxy(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref configure_client) = self.configure_client {
|
if let Some(ref configure_client) = self.context.configure_client {
|
||||||
request = configure_client(request);
|
request = configure_client(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,10 +583,6 @@ impl Updater {
|
|||||||
|
|
||||||
let update = if should_update {
|
let update = if should_update {
|
||||||
Some(Update {
|
Some(Update {
|
||||||
run_on_main_thread: self.run_on_main_thread.clone(),
|
|
||||||
config: self.config.clone(),
|
|
||||||
on_before_exit: self.on_before_exit.clone(),
|
|
||||||
app_name: self.app_name.clone(),
|
|
||||||
current_version: self.current_version.to_string(),
|
current_version: self.current_version.to_string(),
|
||||||
target: target.to_owned(),
|
target: target.to_owned(),
|
||||||
extract_path: self.extract_path.clone(),
|
extract_path: self.extract_path.clone(),
|
||||||
@@ -554,9 +596,7 @@ impl Updater {
|
|||||||
proxy: self.proxy.clone(),
|
proxy: self.proxy.clone(),
|
||||||
no_proxy: self.no_proxy,
|
no_proxy: self.no_proxy,
|
||||||
headers: self.headers.clone(),
|
headers: self.headers.clone(),
|
||||||
installer_args: self.installer_args.clone(),
|
context: self.context.clone(),
|
||||||
current_exe_args: self.current_exe_args.clone(),
|
|
||||||
configure_client: self.configure_client.clone(),
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -600,11 +640,6 @@ impl Updater {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Update {
|
pub struct Update {
|
||||||
#[allow(dead_code)]
|
|
||||||
run_on_main_thread: Arc<RunOnMainThread>,
|
|
||||||
config: Config,
|
|
||||||
#[allow(unused)]
|
|
||||||
on_before_exit: Option<OnBeforeExit>,
|
|
||||||
/// Update description
|
/// Update description
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
/// Version used to check for update
|
/// Version used to check for update
|
||||||
@@ -633,14 +668,7 @@ pub struct Update {
|
|||||||
/// Extract path
|
/// Extract path
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
extract_path: PathBuf,
|
extract_path: PathBuf,
|
||||||
/// App name, used for creating named tempfiles on Windows
|
context: UpdaterContext,
|
||||||
#[allow(unused)]
|
|
||||||
app_name: String,
|
|
||||||
#[allow(unused)]
|
|
||||||
installer_args: Vec<OsString>,
|
|
||||||
#[allow(unused)]
|
|
||||||
current_exe_args: Vec<OsString>,
|
|
||||||
configure_client: Option<OnBeforeRequest>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for Update {}
|
impl Resource for Update {}
|
||||||
@@ -661,10 +689,10 @@ impl Update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut request = ClientBuilder::new().user_agent(UPDATER_USER_AGENT);
|
let mut request = ClientBuilder::new().user_agent(UPDATER_USER_AGENT);
|
||||||
if self.config.dangerous_accept_invalid_certs {
|
if self.context.config.dangerous_accept_invalid_certs {
|
||||||
request = request.danger_accept_invalid_certs(true);
|
request = request.danger_accept_invalid_certs(true);
|
||||||
}
|
}
|
||||||
if self.config.dangerous_accept_invalid_hostnames {
|
if self.context.config.dangerous_accept_invalid_hostnames {
|
||||||
request = request.danger_accept_invalid_hostnames(true);
|
request = request.danger_accept_invalid_hostnames(true);
|
||||||
}
|
}
|
||||||
if let Some(timeout) = self.timeout {
|
if let Some(timeout) = self.timeout {
|
||||||
@@ -676,7 +704,7 @@ impl Update {
|
|||||||
let proxy = reqwest::Proxy::all(proxy.as_str())?;
|
let proxy = reqwest::Proxy::all(proxy.as_str())?;
|
||||||
request = request.proxy(proxy);
|
request = request.proxy(proxy);
|
||||||
}
|
}
|
||||||
if let Some(ref configure_client) = self.configure_client {
|
if let Some(ref configure_client) = self.context.configure_client {
|
||||||
request = configure_client(request);
|
request = configure_client(request);
|
||||||
}
|
}
|
||||||
let response = request
|
let response = request
|
||||||
@@ -709,17 +737,27 @@ impl Update {
|
|||||||
}
|
}
|
||||||
on_download_finish();
|
on_download_finish();
|
||||||
|
|
||||||
verify_signature(&buffer, &self.signature, &self.config.pubkey)?;
|
verify_signature(&buffer, &self.signature, &self.context.config.pubkey)?;
|
||||||
|
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Installs the updater package downloaded by [`Update::download`]
|
/// Installs the updater package downloaded by [`Update::download`]
|
||||||
|
///
|
||||||
|
/// ## Platform-specific:
|
||||||
|
///
|
||||||
|
/// - **Windows:** This function exits the app after launching the updater installer successfully
|
||||||
|
/// - **macOS / Linux:** You need to relaunch the app to run the newly install version
|
||||||
pub fn install(&self, bytes: impl AsRef<[u8]>) -> Result<()> {
|
pub fn install(&self, bytes: impl AsRef<[u8]>) -> Result<()> {
|
||||||
self.install_inner(bytes.as_ref())
|
self.install_inner(bytes.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Downloads and installs the updater package
|
/// Downloads and installs the updater package
|
||||||
|
///
|
||||||
|
/// ## Platform-specific:
|
||||||
|
///
|
||||||
|
/// - **Windows:** This function exits the app after launching the updater installer successfully
|
||||||
|
/// - **macOS / Linux:** You need to relaunch the app to run the newly install version
|
||||||
pub async fn download_and_install<C: FnMut(usize, Option<u64>), D: FnOnce()>(
|
pub async fn download_and_install<C: FnMut(usize, Option<u64>), D: FnOnce()>(
|
||||||
&self,
|
&self,
|
||||||
on_chunk: C,
|
on_chunk: C,
|
||||||
@@ -733,6 +771,16 @@ impl Update {
|
|||||||
fn install_inner(&self, _bytes: &[u8]) -> Result<()> {
|
fn install_inner(&self, _bytes: &[u8]) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the Windows installer should restart the app after installed, default is `true`
|
||||||
|
#[cfg_attr(not(windows), allow(unused))]
|
||||||
|
pub fn restart_after_install(mut self, restart_after_install: bool) -> Self {
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
self.context.restart_after_install = restart_after_install;
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -785,7 +833,6 @@ impl Update {
|
|||||||
/// │ └──[AppName]_[version]_x64-setup.exe # NSIS installer
|
/// │ └──[AppName]_[version]_x64-setup.exe # NSIS installer
|
||||||
/// └── ...
|
/// └── ...
|
||||||
fn install_inner(&self, bytes: &[u8]) -> Result<()> {
|
fn install_inner(&self, bytes: &[u8]) -> Result<()> {
|
||||||
use std::iter::once;
|
|
||||||
use windows_sys::{
|
use windows_sys::{
|
||||||
w,
|
w,
|
||||||
Win32::UI::{Shell::ShellExecuteW, WindowsAndMessaging::SW_SHOW},
|
Win32::UI::{Shell::ShellExecuteW, WindowsAndMessaging::SW_SHOW},
|
||||||
@@ -793,48 +840,7 @@ impl Update {
|
|||||||
|
|
||||||
let updater_type = self.extract(bytes)?;
|
let updater_type = self.extract(bytes)?;
|
||||||
|
|
||||||
let install_mode = self.config.install_mode();
|
if let Some(on_before_exit) = self.context.on_before_exit.as_ref() {
|
||||||
let current_args = &self.current_exe_args()[1..];
|
|
||||||
let msi_args;
|
|
||||||
let nsis_args;
|
|
||||||
|
|
||||||
let installer_args: Vec<&OsStr> = match &updater_type {
|
|
||||||
WindowsUpdaterType::Nsis { .. } => {
|
|
||||||
nsis_args = current_args
|
|
||||||
.iter()
|
|
||||||
.map(escape_nsis_current_exe_arg)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
install_mode
|
|
||||||
.nsis_args()
|
|
||||||
.iter()
|
|
||||||
.map(OsStr::new)
|
|
||||||
.chain(once(OsStr::new("/UPDATE")))
|
|
||||||
.chain(once(OsStr::new("/ARGS")))
|
|
||||||
.chain(nsis_args.iter().map(OsStr::new))
|
|
||||||
.chain(self.installer_args())
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
WindowsUpdaterType::Msi { path, .. } => {
|
|
||||||
let escaped_args = current_args
|
|
||||||
.iter()
|
|
||||||
.map(escape_msi_property_arg)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(" ");
|
|
||||||
msi_args = OsString::from(format!("LAUNCHAPPARGS=\"{escaped_args}\""));
|
|
||||||
|
|
||||||
[OsStr::new("/i"), path.as_os_str()]
|
|
||||||
.into_iter()
|
|
||||||
.chain(install_mode.msiexec_args().iter().map(OsStr::new))
|
|
||||||
.chain(once(OsStr::new("/promptrestart")))
|
|
||||||
.chain(self.installer_args())
|
|
||||||
.chain(once(OsStr::new("AUTOLAUNCHAPP=True")))
|
|
||||||
.chain(once(msi_args.as_os_str()))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(on_before_exit) = self.on_before_exit.as_ref() {
|
|
||||||
log::debug!("running on_before_exit hook");
|
log::debug!("running on_before_exit hook");
|
||||||
on_before_exit();
|
on_before_exit();
|
||||||
}
|
}
|
||||||
@@ -846,12 +852,14 @@ impl Update {
|
|||||||
|p| OsString::from(format!("{p}\\System32\\msiexec.exe")),
|
|p| OsString::from(format!("{p}\\System32\\msiexec.exe")),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let file = encode_wide(file);
|
let parameters = self.updater_parameters(&updater_type);
|
||||||
|
|
||||||
let parameters = installer_args.join(OsStr::new(" "));
|
log::debug!("Executing updater {file:?} with parameters: {parameters:?}");
|
||||||
|
|
||||||
|
let file = encode_wide(file);
|
||||||
let parameters = encode_wide(parameters);
|
let parameters = encode_wide(parameters);
|
||||||
|
|
||||||
unsafe {
|
let result = unsafe {
|
||||||
ShellExecuteW(
|
ShellExecuteW(
|
||||||
std::ptr::null_mut(),
|
std::ptr::null_mut(),
|
||||||
w!("open"),
|
w!("open"),
|
||||||
@@ -861,22 +869,79 @@ impl Update {
|
|||||||
SW_SHOW,
|
SW_SHOW,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
if result as isize <= 32 {
|
||||||
|
return Err(crate::Error::Io(std::io::Error::last_os_error()));
|
||||||
|
}
|
||||||
|
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn installer_args(&self) -> Vec<&OsStr> {
|
fn updater_parameters(&self, updater_type: &WindowsUpdaterType) -> OsString {
|
||||||
self.installer_args
|
let install_mode = self.context.config.install_mode();
|
||||||
.iter()
|
let current_args = &self.context.current_exe_args[1..];
|
||||||
.map(OsStr::new)
|
|
||||||
.collect::<Vec<_>>()
|
match updater_type {
|
||||||
|
WindowsUpdaterType::Nsis { .. } => {
|
||||||
|
let mut installer_args: Vec<&OsStr> = Vec::new();
|
||||||
|
installer_args.extend(install_mode.nsis_args().iter().map(OsStr::new));
|
||||||
|
installer_args.push(OsStr::new("/UPDATE"));
|
||||||
|
|
||||||
|
let nsis_current_exe_arg;
|
||||||
|
if self.context.restart_after_install {
|
||||||
|
nsis_current_exe_arg = current_args
|
||||||
|
.iter()
|
||||||
|
.map(escape_nsis_current_exe_arg)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
installer_args.extend(
|
||||||
|
install_mode
|
||||||
|
.nsis_restart_after_install_args()
|
||||||
|
.iter()
|
||||||
|
.map(OsStr::new),
|
||||||
|
);
|
||||||
|
installer_args.push(OsStr::new("/ARGS"));
|
||||||
|
installer_args.extend(nsis_current_exe_arg.iter().map(OsStr::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
installer_args.extend(self.installer_args());
|
||||||
|
|
||||||
|
installer_args.join(OsStr::new(" "))
|
||||||
|
}
|
||||||
|
WindowsUpdaterType::Msi { path, .. } => {
|
||||||
|
let mut installer_args: Vec<&OsStr> = vec![OsStr::new("/i"), path.as_os_str()];
|
||||||
|
installer_args.extend(install_mode.msiexec_args().iter().map(OsStr::new));
|
||||||
|
installer_args.push(OsStr::new("/promptrestart"));
|
||||||
|
installer_args.extend(self.installer_args());
|
||||||
|
|
||||||
|
let msi_current_exe_arg;
|
||||||
|
if self.context.restart_after_install {
|
||||||
|
msi_current_exe_arg = format!(
|
||||||
|
"LAUNCHAPPARGS=\"{}\"",
|
||||||
|
current_args
|
||||||
|
.iter()
|
||||||
|
.map(escape_msi_property_arg)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" ")
|
||||||
|
);
|
||||||
|
|
||||||
|
installer_args.extend(
|
||||||
|
install_mode
|
||||||
|
.msi_restart_after_install_args()
|
||||||
|
.iter()
|
||||||
|
.map(OsStr::new),
|
||||||
|
);
|
||||||
|
installer_args.push(OsStr::new(&msi_current_exe_arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
installer_args.join(OsStr::new(" "))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_exe_args(&self) -> Vec<&OsStr> {
|
fn installer_args(
|
||||||
self.current_exe_args
|
&self,
|
||||||
.iter()
|
) -> std::iter::Map<std::slice::Iter<'_, OsString>, fn(&OsString) -> &OsStr> {
|
||||||
.map(OsStr::new)
|
self.context.installer_args.iter().map(OsStr::new)
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract(&self, bytes: &[u8]) -> Result<WindowsUpdaterType> {
|
fn extract(&self, bytes: &[u8]) -> Result<WindowsUpdaterType> {
|
||||||
@@ -890,7 +955,10 @@ impl Update {
|
|||||||
|
|
||||||
fn make_temp_dir(&self) -> Result<PathBuf> {
|
fn make_temp_dir(&self) -> Result<PathBuf> {
|
||||||
Ok(tempfile::Builder::new()
|
Ok(tempfile::Builder::new()
|
||||||
.prefix(&format!("{}-{}-updater-", self.app_name, self.version))
|
.prefix(&format!(
|
||||||
|
"{}-{}-updater-",
|
||||||
|
self.context.app_name, self.version
|
||||||
|
))
|
||||||
.tempdir()?
|
.tempdir()?
|
||||||
.keep())
|
.keep())
|
||||||
}
|
}
|
||||||
@@ -938,7 +1006,10 @@ impl Update {
|
|||||||
|
|
||||||
let temp_dir = self.make_temp_dir()?;
|
let temp_dir = self.make_temp_dir()?;
|
||||||
let mut temp_file = tempfile::Builder::new()
|
let mut temp_file = tempfile::Builder::new()
|
||||||
.prefix(&format!("{}-{}-installer", self.app_name, self.version))
|
.prefix(&format!(
|
||||||
|
"{}-{}-installer",
|
||||||
|
self.context.app_name, self.version
|
||||||
|
))
|
||||||
.suffix(ext)
|
.suffix(ext)
|
||||||
.rand_bytes(0)
|
.rand_bytes(0)
|
||||||
.tempfile_in(temp_dir)?;
|
.tempfile_in(temp_dir)?;
|
||||||
@@ -1277,7 +1348,7 @@ impl Update {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let (tx, rx) = std::sync::mpsc::channel();
|
let (tx, rx) = std::sync::mpsc::channel();
|
||||||
let res = (self.run_on_main_thread)(Box::new(move || {
|
let res = (self.context.run_on_main_thread)(Box::new(move || {
|
||||||
let mut script =
|
let mut script =
|
||||||
osakit::Script::new_from_source(osakit::Language::AppleScript, &apple_script);
|
osakit::Script::new_from_source(osakit::Language::AppleScript, &apple_script);
|
||||||
script.compile().expect("invalid AppleScript");
|
script.compile().expect("invalid AppleScript");
|
||||||
@@ -1450,7 +1521,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate signature
|
// Validate signature
|
||||||
fn verify_signature(data: &[u8], release_signature: &str, pub_key: &str) -> Result<bool> {
|
fn verify_signature(data: &[u8], release_signature: &str, pub_key: &str) -> Result<()> {
|
||||||
// we need to convert the pub key
|
// we need to convert the pub key
|
||||||
let pub_key_decoded = base64_to_string(pub_key)?;
|
let pub_key_decoded = base64_to_string(pub_key)?;
|
||||||
let public_key = PublicKey::decode(&pub_key_decoded)?;
|
let public_key = PublicKey::decode(&pub_key_decoded)?;
|
||||||
@@ -1459,7 +1530,7 @@ fn verify_signature(data: &[u8], release_signature: &str, pub_key: &str) -> Resu
|
|||||||
|
|
||||||
// Validate signature or bail out
|
// Validate signature or bail out
|
||||||
public_key.verify(data, &signature, true)?;
|
public_key.verify(data, &signature, true)?;
|
||||||
Ok(true)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base64_to_string(base64_string: &str) -> Result<String> {
|
fn base64_to_string(base64_string: &str) -> Result<String> {
|
||||||
@@ -1498,25 +1569,31 @@ impl PathExt for PathBuf {
|
|||||||
|
|
||||||
// adapted from https://github.com/rust-lang/rust/blob/1c047506f94cd2d05228eb992b0a6bbed1942349/library/std/src/sys/args/windows.rs#L174
|
// adapted from https://github.com/rust-lang/rust/blob/1c047506f94cd2d05228eb992b0a6bbed1942349/library/std/src/sys/args/windows.rs#L174
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn escape_nsis_current_exe_arg(arg: &&OsStr) -> String {
|
fn escape_nsis_current_exe_arg(arg: impl AsRef<OsStr>) -> OsString {
|
||||||
let arg = arg.to_string_lossy();
|
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||||
let mut cmd: Vec<char> = Vec::new();
|
|
||||||
|
let arg = arg.as_ref();
|
||||||
|
let mut cmd: Vec<u16> = Vec::new();
|
||||||
|
|
||||||
// compared to std we additionally escape `/` so that nsis won't interpret them as a beginning of an nsis argument.
|
// compared to std we additionally escape `/` so that nsis won't interpret them as a beginning of an nsis argument.
|
||||||
let quote = arg.chars().any(|c| c == ' ' || c == '\t' || c == '/') || arg.is_empty();
|
let quote = arg
|
||||||
|
.as_encoded_bytes()
|
||||||
|
.iter()
|
||||||
|
.any(|c| *c == b' ' || *c == b'\t' || *c == b'/')
|
||||||
|
|| arg.is_empty();
|
||||||
let escape = true;
|
let escape = true;
|
||||||
if quote {
|
if quote {
|
||||||
cmd.push('"');
|
cmd.push('"' as u16);
|
||||||
}
|
}
|
||||||
let mut backslashes: usize = 0;
|
let mut backslashes: usize = 0;
|
||||||
for x in arg.chars() {
|
for x in arg.encode_wide() {
|
||||||
if escape {
|
if escape {
|
||||||
if x == '\\' {
|
if x == '\\' as u16 {
|
||||||
backslashes += 1;
|
backslashes += 1;
|
||||||
} else {
|
} else {
|
||||||
if x == '"' {
|
if x == '"' as u16 {
|
||||||
// Add n+1 backslashes to total 2n+1 before internal '"'.
|
// Add n+1 backslashes to total 2n+1 before internal '"'.
|
||||||
cmd.extend((0..=backslashes).map(|_| '\\'));
|
cmd.extend((0..=backslashes).map(|_| '\\' as u16));
|
||||||
}
|
}
|
||||||
backslashes = 0;
|
backslashes = 0;
|
||||||
}
|
}
|
||||||
@@ -1525,10 +1602,10 @@ fn escape_nsis_current_exe_arg(arg: &&OsStr) -> String {
|
|||||||
}
|
}
|
||||||
if quote {
|
if quote {
|
||||||
// Add n backslashes to total 2n before ending '"'.
|
// Add n backslashes to total 2n before ending '"'.
|
||||||
cmd.extend((0..backslashes).map(|_| '\\'));
|
cmd.extend((0..backslashes).map(|_| '\\' as u16));
|
||||||
cmd.push('"');
|
cmd.push('"' as u16);
|
||||||
}
|
}
|
||||||
cmd.into_iter().collect()
|
OsString::from_wide(&cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
"endpoints": ["http://localhost:3007"],
|
"endpoints": ["http://localhost:3007"],
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUwNDRGMjkwRjg2MDhCRDAKUldUUWkyRDRrUEpFNEQ4SmdwcU5PaXl6R2ZRUUNvUnhIaVkwVUltV0NMaEx6VTkrWVhpT0ZqeEEK",
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUwNDRGMjkwRjg2MDhCRDAKUldUUWkyRDRrUEpFNEQ4SmdwcU5PaXl6R2ZRUUNvUnhIaVkwVUltV0NMaEx6VTkrWVhpT0ZqeEEK",
|
||||||
"windows": {
|
"windows": {
|
||||||
"installMode": "quiet",
|
"installMode": "quiet"
|
||||||
"installerArgs": ["/NS"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ struct Update {
|
|||||||
platforms: HashMap<String, PlatformUpdate>,
|
platforms: HashMap<String, PlatformUpdate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_app(cwd: &Path, config: &Config, bundle_updater: bool, target: BundleTarget) {
|
fn build_app(cwd: &Path, config: &Config, target: Option<BundleTarget>) {
|
||||||
let mut command = Command::new("cargo");
|
let mut command = Command::new("cargo");
|
||||||
command
|
command
|
||||||
.args(["tauri", "build", "--verbose"])
|
.args(["tauri", "build", "--verbose"])
|
||||||
@@ -56,17 +56,10 @@ fn build_app(cwd: &Path, config: &Config, bundle_updater: bool, target: BundleTa
|
|||||||
.env("TAURI_SIGNING_PRIVATE_KEY_PASSWORD", "")
|
.env("TAURI_SIGNING_PRIVATE_KEY_PASSWORD", "")
|
||||||
.current_dir(cwd);
|
.current_dir(cwd);
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
if let Some(target) = target {
|
||||||
command.args(["--bundles", target.name()]);
|
command.arg("--bundles").arg(target.name());
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
command.args(["--bundles", target.name()]);
|
|
||||||
|
|
||||||
if bundle_updater {
|
|
||||||
#[cfg(windows)]
|
|
||||||
command.args(["--bundles", "msi", "nsis"]);
|
|
||||||
} else {
|
} else {
|
||||||
#[cfg(windows)]
|
command.arg("--no-bundle");
|
||||||
command.args(["--bundles", target.name()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = command
|
let status = command
|
||||||
@@ -318,7 +311,7 @@ fn update_app() {
|
|||||||
{
|
{
|
||||||
// bundle app update
|
// bundle app update
|
||||||
config.version = "1.0.0";
|
config.version = "1.0.0";
|
||||||
build_app(&manifest_dir, &config, true, BundleTarget::default());
|
build_app(&manifest_dir, &config, Some(bundle_target));
|
||||||
|
|
||||||
let bundle_updater_ext = if v1_compatible {
|
let bundle_updater_ext = if v1_compatible {
|
||||||
out_bundle_path
|
out_bundle_path
|
||||||
@@ -401,7 +394,7 @@ fn update_app() {
|
|||||||
config.version = "0.1.0";
|
config.version = "0.1.0";
|
||||||
|
|
||||||
// bundle initial app version
|
// bundle initial app version
|
||||||
build_app(&manifest_dir, &config, false, bundle_target);
|
build_app(&manifest_dir, &config, None);
|
||||||
|
|
||||||
for expected_exit_code in status_checks {
|
for expected_exit_code in status_checks {
|
||||||
let mut binary_cmd = if cfg!(windows) {
|
let mut binary_cmd = if cfg!(windows) {
|
||||||
|
|||||||
+3
-3
@@ -3794,7 +3794,7 @@ version = "0.1.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4137,9 +4137,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wry"
|
name = "wry"
|
||||||
version = "0.24.10"
|
version = "0.24.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00711278ed357350d44c749c286786ecac644e044e4da410d466212152383b45"
|
checksum = "4a2a144c3ab5e83e04724bc8e67cea552ffae413185fda459fafdae173fd985d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"block",
|
"block",
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-upload"
|
links = "tauri-plugin-upload"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/test",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -8,7 +8,14 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-websocket"
|
links = "tauri-plugin-websocket"
|
||||||
exclude = ["/examples"]
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/examples",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "2.11.4",
|
"@tauri-apps/cli": "2.11.4",
|
||||||
"typescript": "^6.0.0",
|
"typescript": "^6.0.3",
|
||||||
"vite": "^8.0.1"
|
"vite": "^8.0.16"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tauri-plugin-websocket-api": "link:..\\.."
|
"tauri-plugin-websocket-api": "link:..\\.."
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
links = "tauri-plugin-window-state"
|
links = "tauri-plugin-window-state"
|
||||||
|
exclude = [
|
||||||
|
"/banner.png",
|
||||||
|
"/guest-js",
|
||||||
|
"/package.json",
|
||||||
|
"/rollup.config.js",
|
||||||
|
"/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.platforms.support]
|
[package.metadata.platforms.support]
|
||||||
windows = { level = "full", notes = "" }
|
windows = { level = "full", notes = "" }
|
||||||
|
|||||||
Generated
+144
-163
@@ -13,13 +13,13 @@ importers:
|
|||||||
version: 10.0.1(eslint@10.4.0(jiti@2.6.1))
|
version: 10.0.1(eslint@10.4.0(jiti@2.6.1))
|
||||||
'@rollup/plugin-node-resolve':
|
'@rollup/plugin-node-resolve':
|
||||||
specifier: 16.0.3
|
specifier: 16.0.3
|
||||||
version: 16.0.3(rollup@4.60.3)
|
version: 16.0.3(rollup@4.62.2)
|
||||||
'@rollup/plugin-terser':
|
'@rollup/plugin-terser':
|
||||||
specifier: 1.0.0
|
specifier: 1.0.0
|
||||||
version: 1.0.0(rollup@4.60.3)
|
version: 1.0.0(rollup@4.62.2)
|
||||||
'@rollup/plugin-typescript':
|
'@rollup/plugin-typescript':
|
||||||
specifier: 12.3.0
|
specifier: 12.3.0
|
||||||
version: 12.3.0(rollup@4.60.3)(tslib@2.8.1)(typescript@6.0.3)
|
version: 12.3.0(rollup@4.62.2)(tslib@2.8.1)(typescript@6.0.3)
|
||||||
eslint:
|
eslint:
|
||||||
specifier: 10.4.0
|
specifier: 10.4.0
|
||||||
version: 10.4.0(jiti@2.6.1)
|
version: 10.4.0(jiti@2.6.1)
|
||||||
@@ -33,8 +33,8 @@ importers:
|
|||||||
specifier: 3.8.3
|
specifier: 3.8.3
|
||||||
version: 3.8.3
|
version: 3.8.3
|
||||||
rollup:
|
rollup:
|
||||||
specifier: 4.60.3
|
specifier: 4.62.2
|
||||||
version: 4.60.3
|
version: 4.62.2
|
||||||
tslib:
|
tslib:
|
||||||
specifier: 2.8.1
|
specifier: 2.8.1
|
||||||
version: 2.8.1
|
version: 2.8.1
|
||||||
@@ -63,8 +63,8 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../plugins/clipboard-manager
|
version: link:../../plugins/clipboard-manager
|
||||||
'@tauri-apps/plugin-dialog':
|
'@tauri-apps/plugin-dialog':
|
||||||
specifier: '2'
|
specifier: workspace:*
|
||||||
version: 2.7.1
|
version: link:../../plugins/dialog
|
||||||
'@tauri-apps/plugin-fs':
|
'@tauri-apps/plugin-fs':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../plugins/fs
|
version: link:../../plugins/fs
|
||||||
@@ -99,8 +99,8 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../plugins/shell
|
version: link:../../plugins/shell
|
||||||
'@tauri-apps/plugin-store':
|
'@tauri-apps/plugin-store':
|
||||||
specifier: '2'
|
specifier: workspace:*
|
||||||
version: 2.4.3
|
version: link:../../plugins/store
|
||||||
'@tauri-apps/plugin-updater':
|
'@tauri-apps/plugin-updater':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../plugins/updater
|
version: link:../../plugins/updater
|
||||||
@@ -127,13 +127,13 @@ importers:
|
|||||||
specifier: ^66.6.7
|
specifier: ^66.6.7
|
||||||
version: 66.6.7
|
version: 66.6.7
|
||||||
svelte:
|
svelte:
|
||||||
specifier: ^5.54.0
|
specifier: ^5.55.7
|
||||||
version: 5.55.7(@typescript-eslint/types@8.58.2)
|
version: 5.55.7(@typescript-eslint/types@8.58.2)
|
||||||
unocss:
|
unocss:
|
||||||
specifier: ^66.6.7
|
specifier: ^66.6.7
|
||||||
version: 66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1))
|
version: 66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1))
|
||||||
vite:
|
vite:
|
||||||
specifier: ^8.0.1
|
specifier: ^8.0.16
|
||||||
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
||||||
|
|
||||||
plugins/autostart:
|
plugins/autostart:
|
||||||
@@ -189,10 +189,10 @@ importers:
|
|||||||
specifier: 2.11.4
|
specifier: 2.11.4
|
||||||
version: 2.11.4
|
version: 2.11.4
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.3
|
||||||
version: 6.0.3
|
version: 6.0.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^8.0.1
|
specifier: ^8.0.16
|
||||||
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
||||||
|
|
||||||
plugins/dialog:
|
plugins/dialog:
|
||||||
@@ -303,10 +303,10 @@ importers:
|
|||||||
specifier: 2.11.4
|
specifier: 2.11.4
|
||||||
version: 2.11.4
|
version: 2.11.4
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.3
|
||||||
version: 6.0.3
|
version: 6.0.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^8.0.1
|
specifier: ^8.0.16
|
||||||
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
||||||
|
|
||||||
plugins/stronghold:
|
plugins/stronghold:
|
||||||
@@ -343,10 +343,10 @@ importers:
|
|||||||
specifier: 2.11.4
|
specifier: 2.11.4
|
||||||
version: 2.11.4
|
version: 2.11.4
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.3
|
||||||
version: 6.0.3
|
version: 6.0.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^8.0.1
|
specifier: ^8.0.16
|
||||||
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
version: 8.0.16(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.1)
|
||||||
|
|
||||||
plugins/window-state:
|
plugins/window-state:
|
||||||
@@ -894,141 +894,141 @@ packages:
|
|||||||
rollup:
|
rollup:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.60.3':
|
'@rollup/rollup-android-arm-eabi@4.62.2':
|
||||||
resolution: {integrity: sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==}
|
resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@rollup/rollup-android-arm64@4.60.3':
|
'@rollup/rollup-android-arm64@4.62.2':
|
||||||
resolution: {integrity: sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==}
|
resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@rollup/rollup-darwin-arm64@4.60.3':
|
'@rollup/rollup-darwin-arm64@4.62.2':
|
||||||
resolution: {integrity: sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==}
|
resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@rollup/rollup-darwin-x64@4.60.3':
|
'@rollup/rollup-darwin-x64@4.62.2':
|
||||||
resolution: {integrity: sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==}
|
resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-arm64@4.60.3':
|
'@rollup/rollup-freebsd-arm64@4.62.2':
|
||||||
resolution: {integrity: sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==}
|
resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-x64@4.60.3':
|
'@rollup/rollup-freebsd-x64@4.62.2':
|
||||||
resolution: {integrity: sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==}
|
resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf@4.60.3':
|
'@rollup/rollup-linux-arm-gnueabihf@4.62.2':
|
||||||
resolution: {integrity: sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==}
|
resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf@4.60.3':
|
'@rollup/rollup-linux-arm-musleabihf@4.62.2':
|
||||||
resolution: {integrity: sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==}
|
resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-gnu@4.60.3':
|
'@rollup/rollup-linux-arm64-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==}
|
resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-musl@4.60.3':
|
'@rollup/rollup-linux-arm64-musl@4.62.2':
|
||||||
resolution: {integrity: sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==}
|
resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-gnu@4.60.3':
|
'@rollup/rollup-linux-loong64-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==}
|
resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==}
|
||||||
cpu: [loong64]
|
cpu: [loong64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-musl@4.60.3':
|
'@rollup/rollup-linux-loong64-musl@4.62.2':
|
||||||
resolution: {integrity: sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==}
|
resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==}
|
||||||
cpu: [loong64]
|
cpu: [loong64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu@4.60.3':
|
'@rollup/rollup-linux-ppc64-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==}
|
resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==}
|
||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-musl@4.60.3':
|
'@rollup/rollup-linux-ppc64-musl@4.62.2':
|
||||||
resolution: {integrity: sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==}
|
resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==}
|
||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu@4.60.3':
|
'@rollup/rollup-linux-riscv64-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==}
|
resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==}
|
||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-musl@4.60.3':
|
'@rollup/rollup-linux-riscv64-musl@4.62.2':
|
||||||
resolution: {integrity: sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==}
|
resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==}
|
||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@rollup/rollup-linux-s390x-gnu@4.60.3':
|
'@rollup/rollup-linux-s390x-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==}
|
resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==}
|
||||||
cpu: [s390x]
|
cpu: [s390x]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-gnu@4.60.3':
|
'@rollup/rollup-linux-x64-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==}
|
resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-musl@4.60.3':
|
'@rollup/rollup-linux-x64-musl@4.62.2':
|
||||||
resolution: {integrity: sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==}
|
resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@rollup/rollup-openbsd-x64@4.60.3':
|
'@rollup/rollup-openbsd-x64@4.62.2':
|
||||||
resolution: {integrity: sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==}
|
resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [openbsd]
|
os: [openbsd]
|
||||||
|
|
||||||
'@rollup/rollup-openharmony-arm64@4.60.3':
|
'@rollup/rollup-openharmony-arm64@4.62.2':
|
||||||
resolution: {integrity: sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==}
|
resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [openharmony]
|
os: [openharmony]
|
||||||
|
|
||||||
'@rollup/rollup-win32-arm64-msvc@4.60.3':
|
'@rollup/rollup-win32-arm64-msvc@4.62.2':
|
||||||
resolution: {integrity: sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==}
|
resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rollup/rollup-win32-ia32-msvc@4.60.3':
|
'@rollup/rollup-win32-ia32-msvc@4.62.2':
|
||||||
resolution: {integrity: sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==}
|
resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-gnu@4.60.3':
|
'@rollup/rollup-win32-x64-gnu@4.62.2':
|
||||||
resolution: {integrity: sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==}
|
resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-msvc@4.60.3':
|
'@rollup/rollup-win32-x64-msvc@4.62.2':
|
||||||
resolution: {integrity: sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==}
|
resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
@@ -1123,21 +1123,12 @@ packages:
|
|||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@tauri-apps/plugin-dialog@2.7.1':
|
|
||||||
resolution: {integrity: sha512-OK1UBXYt+ojcmxMktzzuyonYIFta8CmAASpX+CA+DTGK24KlHjhYI6x2iOJ/TjZF4N7/ACK1oFmEOjIY9IhzOQ==}
|
|
||||||
|
|
||||||
'@tauri-apps/plugin-store@2.4.3':
|
|
||||||
resolution: {integrity: sha512-9LWPj9yMphRi9czEtUv87XHbl1b6xgd9EXpPrUnq6nG7+nbtoF84d4Kwz9xhAv/Hf30sr58pq7EOlyI936y8qw==}
|
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.2':
|
'@tybys/wasm-util@0.10.2':
|
||||||
resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==}
|
resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==}
|
||||||
|
|
||||||
'@types/esrecurse@4.3.1':
|
'@types/esrecurse@4.3.1':
|
||||||
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
|
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
|
||||||
|
|
||||||
'@types/estree@1.0.8':
|
|
||||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
|
||||||
|
|
||||||
'@types/estree@1.0.9':
|
'@types/estree@1.0.9':
|
||||||
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
|
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
|
||||||
|
|
||||||
@@ -1311,9 +1302,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
||||||
engines: {node: 18 || 20 || >=22}
|
engines: {node: 18 || 20 || >=22}
|
||||||
|
|
||||||
brace-expansion@5.0.6:
|
brace-expansion@5.0.8:
|
||||||
resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
|
resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==}
|
||||||
engines: {node: 18 || 20 || >=22}
|
engines: {node: 20 || >=22}
|
||||||
|
|
||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
@@ -1671,8 +1662,8 @@ packages:
|
|||||||
ms@2.1.3:
|
ms@2.1.3:
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
|
|
||||||
nanoid@3.3.12:
|
nanoid@3.3.16:
|
||||||
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
|
resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==}
|
||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -1739,8 +1730,8 @@ packages:
|
|||||||
pkg-types@1.3.1:
|
pkg-types@1.3.1:
|
||||||
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
|
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
|
||||||
|
|
||||||
postcss@8.5.15:
|
postcss@8.5.23:
|
||||||
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
|
resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
@@ -1777,8 +1768,8 @@ packages:
|
|||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
rollup@4.60.3:
|
rollup@4.62.2:
|
||||||
resolution: {integrity: sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==}
|
resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==}
|
||||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -2303,114 +2294,114 @@ snapshots:
|
|||||||
|
|
||||||
'@rolldown/pluginutils@1.0.1': {}
|
'@rolldown/pluginutils@1.0.1': {}
|
||||||
|
|
||||||
'@rollup/plugin-node-resolve@16.0.3(rollup@4.60.3)':
|
'@rollup/plugin-node-resolve@16.0.3(rollup@4.62.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.3)
|
'@rollup/pluginutils': 5.3.0(rollup@4.62.2)
|
||||||
'@types/resolve': 1.20.2
|
'@types/resolve': 1.20.2
|
||||||
deepmerge: 4.3.1
|
deepmerge: 4.3.1
|
||||||
is-module: 1.0.0
|
is-module: 1.0.0
|
||||||
resolve: 1.22.11
|
resolve: 1.22.11
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.60.3
|
rollup: 4.62.2
|
||||||
|
|
||||||
'@rollup/plugin-terser@1.0.0(rollup@4.60.3)':
|
'@rollup/plugin-terser@1.0.0(rollup@4.62.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
serialize-javascript: 7.0.5
|
serialize-javascript: 7.0.5
|
||||||
smob: 1.6.1
|
smob: 1.6.1
|
||||||
terser: 5.46.1
|
terser: 5.46.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.60.3
|
rollup: 4.62.2
|
||||||
|
|
||||||
'@rollup/plugin-typescript@12.3.0(rollup@4.60.3)(tslib@2.8.1)(typescript@6.0.3)':
|
'@rollup/plugin-typescript@12.3.0(rollup@4.62.2)(tslib@2.8.1)(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.3)
|
'@rollup/pluginutils': 5.3.0(rollup@4.62.2)
|
||||||
resolve: 1.22.11
|
resolve: 1.22.11
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.60.3
|
rollup: 4.62.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@rollup/pluginutils@5.3.0(rollup@4.60.3)':
|
'@rollup/pluginutils@5.3.0(rollup@4.62.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.9
|
'@types/estree': 1.0.9
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 4.0.4
|
picomatch: 4.0.4
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.60.3
|
rollup: 4.62.2
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.60.3':
|
'@rollup/rollup-android-arm-eabi@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-android-arm64@4.60.3':
|
'@rollup/rollup-android-arm64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-darwin-arm64@4.60.3':
|
'@rollup/rollup-darwin-arm64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-darwin-x64@4.60.3':
|
'@rollup/rollup-darwin-x64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-arm64@4.60.3':
|
'@rollup/rollup-freebsd-arm64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-x64@4.60.3':
|
'@rollup/rollup-freebsd-x64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf@4.60.3':
|
'@rollup/rollup-linux-arm-gnueabihf@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf@4.60.3':
|
'@rollup/rollup-linux-arm-musleabihf@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-gnu@4.60.3':
|
'@rollup/rollup-linux-arm64-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-musl@4.60.3':
|
'@rollup/rollup-linux-arm64-musl@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-gnu@4.60.3':
|
'@rollup/rollup-linux-loong64-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-musl@4.60.3':
|
'@rollup/rollup-linux-loong64-musl@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu@4.60.3':
|
'@rollup/rollup-linux-ppc64-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-musl@4.60.3':
|
'@rollup/rollup-linux-ppc64-musl@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu@4.60.3':
|
'@rollup/rollup-linux-riscv64-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-musl@4.60.3':
|
'@rollup/rollup-linux-riscv64-musl@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-s390x-gnu@4.60.3':
|
'@rollup/rollup-linux-s390x-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-gnu@4.60.3':
|
'@rollup/rollup-linux-x64-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-musl@4.60.3':
|
'@rollup/rollup-linux-x64-musl@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-openbsd-x64@4.60.3':
|
'@rollup/rollup-openbsd-x64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-openharmony-arm64@4.60.3':
|
'@rollup/rollup-openharmony-arm64@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-arm64-msvc@4.60.3':
|
'@rollup/rollup-win32-arm64-msvc@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-ia32-msvc@4.60.3':
|
'@rollup/rollup-win32-ia32-msvc@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-gnu@4.60.3':
|
'@rollup/rollup-win32-x64-gnu@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-msvc@4.60.3':
|
'@rollup/rollup-win32-x64-msvc@4.62.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@sveltejs/acorn-typescript@1.0.9(acorn@8.16.0)':
|
'@sveltejs/acorn-typescript@1.0.9(acorn@8.16.0)':
|
||||||
@@ -2475,14 +2466,6 @@ snapshots:
|
|||||||
'@tauri-apps/cli-win32-ia32-msvc': 2.11.4
|
'@tauri-apps/cli-win32-ia32-msvc': 2.11.4
|
||||||
'@tauri-apps/cli-win32-x64-msvc': 2.11.4
|
'@tauri-apps/cli-win32-x64-msvc': 2.11.4
|
||||||
|
|
||||||
'@tauri-apps/plugin-dialog@2.7.1':
|
|
||||||
dependencies:
|
|
||||||
'@tauri-apps/api': 2.11.0
|
|
||||||
|
|
||||||
'@tauri-apps/plugin-store@2.4.3':
|
|
||||||
dependencies:
|
|
||||||
'@tauri-apps/api': 2.11.0
|
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.2':
|
'@tybys/wasm-util@0.10.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@@ -2490,8 +2473,6 @@ snapshots:
|
|||||||
|
|
||||||
'@types/esrecurse@4.3.1': {}
|
'@types/esrecurse@4.3.1': {}
|
||||||
|
|
||||||
'@types/estree@1.0.8': {}
|
|
||||||
|
|
||||||
'@types/estree@1.0.9': {}
|
'@types/estree@1.0.9': {}
|
||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
@@ -2748,7 +2729,7 @@ snapshots:
|
|||||||
|
|
||||||
balanced-match@4.0.4: {}
|
balanced-match@4.0.4: {}
|
||||||
|
|
||||||
brace-expansion@5.0.6:
|
brace-expansion@5.0.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
balanced-match: 4.0.4
|
balanced-match: 4.0.4
|
||||||
|
|
||||||
@@ -3076,7 +3057,7 @@ snapshots:
|
|||||||
|
|
||||||
minimatch@10.2.4:
|
minimatch@10.2.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion: 5.0.6
|
brace-expansion: 5.0.8
|
||||||
|
|
||||||
mlly@1.8.2:
|
mlly@1.8.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3089,7 +3070,7 @@ snapshots:
|
|||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|
||||||
nanoid@3.3.12: {}
|
nanoid@3.3.16: {}
|
||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
@@ -3175,9 +3156,9 @@ snapshots:
|
|||||||
mlly: 1.8.2
|
mlly: 1.8.2
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
|
|
||||||
postcss@8.5.15:
|
postcss@8.5.23:
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid: 3.3.12
|
nanoid: 3.3.16
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
@@ -3220,35 +3201,35 @@ snapshots:
|
|||||||
'@rolldown/binding-win32-arm64-msvc': 1.0.3
|
'@rolldown/binding-win32-arm64-msvc': 1.0.3
|
||||||
'@rolldown/binding-win32-x64-msvc': 1.0.3
|
'@rolldown/binding-win32-x64-msvc': 1.0.3
|
||||||
|
|
||||||
rollup@4.60.3:
|
rollup@4.62.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.8
|
'@types/estree': 1.0.9
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@rollup/rollup-android-arm-eabi': 4.60.3
|
'@rollup/rollup-android-arm-eabi': 4.62.2
|
||||||
'@rollup/rollup-android-arm64': 4.60.3
|
'@rollup/rollup-android-arm64': 4.62.2
|
||||||
'@rollup/rollup-darwin-arm64': 4.60.3
|
'@rollup/rollup-darwin-arm64': 4.62.2
|
||||||
'@rollup/rollup-darwin-x64': 4.60.3
|
'@rollup/rollup-darwin-x64': 4.62.2
|
||||||
'@rollup/rollup-freebsd-arm64': 4.60.3
|
'@rollup/rollup-freebsd-arm64': 4.62.2
|
||||||
'@rollup/rollup-freebsd-x64': 4.60.3
|
'@rollup/rollup-freebsd-x64': 4.62.2
|
||||||
'@rollup/rollup-linux-arm-gnueabihf': 4.60.3
|
'@rollup/rollup-linux-arm-gnueabihf': 4.62.2
|
||||||
'@rollup/rollup-linux-arm-musleabihf': 4.60.3
|
'@rollup/rollup-linux-arm-musleabihf': 4.62.2
|
||||||
'@rollup/rollup-linux-arm64-gnu': 4.60.3
|
'@rollup/rollup-linux-arm64-gnu': 4.62.2
|
||||||
'@rollup/rollup-linux-arm64-musl': 4.60.3
|
'@rollup/rollup-linux-arm64-musl': 4.62.2
|
||||||
'@rollup/rollup-linux-loong64-gnu': 4.60.3
|
'@rollup/rollup-linux-loong64-gnu': 4.62.2
|
||||||
'@rollup/rollup-linux-loong64-musl': 4.60.3
|
'@rollup/rollup-linux-loong64-musl': 4.62.2
|
||||||
'@rollup/rollup-linux-ppc64-gnu': 4.60.3
|
'@rollup/rollup-linux-ppc64-gnu': 4.62.2
|
||||||
'@rollup/rollup-linux-ppc64-musl': 4.60.3
|
'@rollup/rollup-linux-ppc64-musl': 4.62.2
|
||||||
'@rollup/rollup-linux-riscv64-gnu': 4.60.3
|
'@rollup/rollup-linux-riscv64-gnu': 4.62.2
|
||||||
'@rollup/rollup-linux-riscv64-musl': 4.60.3
|
'@rollup/rollup-linux-riscv64-musl': 4.62.2
|
||||||
'@rollup/rollup-linux-s390x-gnu': 4.60.3
|
'@rollup/rollup-linux-s390x-gnu': 4.62.2
|
||||||
'@rollup/rollup-linux-x64-gnu': 4.60.3
|
'@rollup/rollup-linux-x64-gnu': 4.62.2
|
||||||
'@rollup/rollup-linux-x64-musl': 4.60.3
|
'@rollup/rollup-linux-x64-musl': 4.62.2
|
||||||
'@rollup/rollup-openbsd-x64': 4.60.3
|
'@rollup/rollup-openbsd-x64': 4.62.2
|
||||||
'@rollup/rollup-openharmony-arm64': 4.60.3
|
'@rollup/rollup-openharmony-arm64': 4.62.2
|
||||||
'@rollup/rollup-win32-arm64-msvc': 4.60.3
|
'@rollup/rollup-win32-arm64-msvc': 4.62.2
|
||||||
'@rollup/rollup-win32-ia32-msvc': 4.60.3
|
'@rollup/rollup-win32-ia32-msvc': 4.62.2
|
||||||
'@rollup/rollup-win32-x64-gnu': 4.60.3
|
'@rollup/rollup-win32-x64-gnu': 4.62.2
|
||||||
'@rollup/rollup-win32-x64-msvc': 4.60.3
|
'@rollup/rollup-win32-x64-msvc': 4.62.2
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
safe-regex@2.1.1:
|
safe-regex@2.1.1:
|
||||||
@@ -3412,7 +3393,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lightningcss: 1.32.0
|
lightningcss: 1.32.0
|
||||||
picomatch: 4.0.4
|
picomatch: 4.0.4
|
||||||
postcss: 8.5.15
|
postcss: 8.5.23
|
||||||
rolldown: 1.0.3
|
rolldown: 1.0.3
|
||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user