mirror of
https://github.com/nimbold/Firelink.git
synced 2026-10-25 21:19:49 +00:00
chore(deps): refresh Firelink packages and engines
- Refresh compatible Tauri, React i18n, Rust, and FFmpeg dependencies. - Migrate macOS integrations to objc2 with main-thread Automation execution. - Buffer early Torrent launches and update Node 24-compatible CI actions.
This commit is contained in:
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 22.12
|
||||
cache: npm
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 22.12
|
||||
cache: npm
|
||||
@@ -155,9 +155,9 @@ jobs:
|
||||
- name: Restore verified engine payload cache
|
||||
id: engine-cache
|
||||
if: runner.os != 'macOS'
|
||||
# v4.2.0 pinned to an immutable commit; this cache is an optimization,
|
||||
# v6.1.0 pinned to an immutable commit; this cache is an optimization,
|
||||
# and a miss always falls back to source provisioning below.
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
||||
with:
|
||||
path: src-tauri/provisioned-engines/${{ matrix.target }}
|
||||
# The target, toolchain fingerprint, lockfiles, provisioning code,
|
||||
@@ -179,7 +179,7 @@ jobs:
|
||||
runner.os != 'macOS' &&
|
||||
(steps.engine-cache.outputs.cache-hit != 'true' ||
|
||||
steps.engine-cache-validation.outcome != 'success')
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
||||
with:
|
||||
path: src-tauri/provisioned-engines/.aria2-cache/${{ matrix.target }}
|
||||
key: firelink-aria2-build-v1-${{ matrix.target }}-${{ steps.engine-toolchain.outputs.aria2-fingerprint }}
|
||||
@@ -216,7 +216,7 @@ jobs:
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/main' &&
|
||||
steps.aria2-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
||||
with:
|
||||
path: src-tauri/provisioned-engines/.aria2-cache/${{ matrix.target }}
|
||||
key: firelink-aria2-build-v1-${{ matrix.target }}-${{ steps.engine-toolchain.outputs.aria2-fingerprint }}
|
||||
@@ -226,7 +226,7 @@ jobs:
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/main' &&
|
||||
steps.engine-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
||||
with:
|
||||
path: src-tauri/provisioned-engines/${{ matrix.target }}
|
||||
key: firelink-engine-payload-v1-${{ matrix.target }}-${{ steps.engine-toolchain.outputs.fingerprint }}-${{ hashFiles('engine-sources.lock.json', 'engines.lock.json', 'scripts/aria2/**', 'scripts/engine-*.js', 'scripts/provision-engines.js', 'scripts/stage-engines.js', 'scripts/verify-binaries.js', 'scripts/aria2-route-contract.js', '.github/workflows/ci.yml', '.github/workflows/release.yml') }}
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 22.12
|
||||
cache: npm
|
||||
@@ -125,9 +125,9 @@ jobs:
|
||||
- name: Restore verified engine payload cache
|
||||
id: engine-cache
|
||||
if: runner.os != 'macOS'
|
||||
# v4.2.0 pinned to an immutable commit; release jobs never write cache
|
||||
# v6.1.0 pinned to an immutable commit; release jobs never write cache
|
||||
# entries, so only trusted CI pushes can populate the shared payload.
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
||||
with:
|
||||
path: src-tauri/provisioned-engines/${{ matrix.target }}
|
||||
key: firelink-engine-payload-v1-${{ matrix.target }}-${{ steps.engine-toolchain.outputs.fingerprint }}-${{ hashFiles('engine-sources.lock.json', 'engines.lock.json', 'scripts/aria2/**', 'scripts/engine-*.js', 'scripts/provision-engines.js', 'scripts/stage-engines.js', 'scripts/verify-binaries.js', 'scripts/aria2-route-contract.js', '.github/workflows/ci.yml', '.github/workflows/release.yml') }}
|
||||
@@ -147,7 +147,7 @@ jobs:
|
||||
runner.os != 'macOS' &&
|
||||
(steps.engine-cache.outputs.cache-hit != 'true' ||
|
||||
steps.engine-cache-validation.outcome != 'success')
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
||||
with:
|
||||
path: src-tauri/provisioned-engines/.aria2-cache/${{ matrix.target }}
|
||||
key: firelink-aria2-build-v1-${{ matrix.target }}-${{ steps.engine-toolchain.outputs.aria2-fingerprint }}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
"sha256": "a0c3101b4158d1dfb7d6a78a7bf0f3de80c96bb423c152beec8beb22786f2238"
|
||||
},
|
||||
"ffmpeg": {
|
||||
"version": "9.0.1-29-gad500d59cb",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-09-14-13-17/ffmpeg-n9.0.1-29-gad500d59cb-win64-gpl-9.0.zip",
|
||||
"sha256": "755186bad114362356359d8e4e6e6f1e2bac3ed4df12b94588f004b411859428"
|
||||
"version": "9.0.2-3-ga5923073bf",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-09-23-14-55/ffmpeg-n9.0.2-3-ga5923073bf-win64-gpl-9.0.zip",
|
||||
"sha256": "fdea132b8059ba9dfd6c1ce05bd831a85e665705f03e50162ae2fe599223b5ae"
|
||||
},
|
||||
"aria2c": {
|
||||
"version": "1.37.0-firelink-native-dns-v1",
|
||||
@@ -45,9 +45,9 @@
|
||||
"sha256": "c6527f24f4b16031d3ae4fa9f658d5f11534c8d84ce7dc8502420280919c3490"
|
||||
},
|
||||
"ffmpeg": {
|
||||
"version": "9.0.1-29-gad500d59cb",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-09-14-13-17/ffmpeg-n9.0.1-29-gad500d59cb-linux64-gpl-9.0.tar.xz",
|
||||
"sha256": "f78852b0c4286d245a6bc989704ea03f8f7dcd8b66cd1ad55d190131d4f21bb9"
|
||||
"version": "9.0.2-3-ga5923073bf",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-09-23-14-55/ffmpeg-n9.0.2-3-ga5923073bf-linux64-gpl-9.0.tar.xz",
|
||||
"sha256": "f984634f1ba66f8f0a771c5ea681d72dd19233fc869e0e6c5aaac7c1e73ded00"
|
||||
},
|
||||
"aria2c": {
|
||||
"version": "1.37.0-firelink-native-dns-v1",
|
||||
|
||||
+4
-4
@@ -24,12 +24,12 @@
|
||||
"patchSha256": "1210eeeb0c82a2fee1ef5d28521569259c18a122d3b439135bba57ee39c5f61d"
|
||||
},
|
||||
"ffmpeg": {
|
||||
"version": "9.0.1",
|
||||
"version": "9.0.2",
|
||||
"source": "https://ffmpeg.org/",
|
||||
"build": "Stable GPLv3 build identified by binary as https://www.martin-riedl.de",
|
||||
"url": "https://ffmpeg.martin-riedl.de/download/macos/arm64/1787073674_9.0.1/ffmpeg.zip",
|
||||
"sourceSha256": "8287a1b2229e05eb41859f073e18e6c52c60a778f2f5e6881070fe51b79407fe",
|
||||
"sha256": "393e4c395020a1cb7cbd77fbe00599ce69d1c6466fee0dbd59d13f86a81a1611"
|
||||
"url": "https://ffmpeg.martin-riedl.de/download/macos/arm64/1789931890_9.0.2/ffmpeg.zip",
|
||||
"sourceSha256": "c8ed4c4e6978a03c485edbfe4e0a5dc2380f8a30bba5150531b31b094492d924",
|
||||
"sha256": "2e11c6f90993cdb79fff84d3f90044d28316b310e75b3e030cfc9a54f2c9d384"
|
||||
},
|
||||
"deno": {
|
||||
"version": "2.9.7",
|
||||
|
||||
Generated
+142
-202
@@ -20,18 +20,18 @@
|
||||
"@tauri-apps/plugin-clipboard-manager": "^2.3.3",
|
||||
"@tauri-apps/plugin-dialog": "^2.7.3",
|
||||
"@tauri-apps/plugin-fs": "^2.5.2",
|
||||
"@tauri-apps/plugin-log": "^2.9.1",
|
||||
"@tauri-apps/plugin-log": "^2.9.2",
|
||||
"@tauri-apps/plugin-notification": "^2.4.0",
|
||||
"@tauri-apps/plugin-opener": "^2.5.5",
|
||||
"i18next": "^26.4.2",
|
||||
"lucide-react": "^1.47.0",
|
||||
"react": "^19.3.0",
|
||||
"react-dom": "^19.3.0",
|
||||
"react-i18next": "^17.0.14",
|
||||
"react-i18next": "^17.0.15",
|
||||
"zustand": "^5.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.11.4",
|
||||
"@tauri-apps/cli": "^2.11.5",
|
||||
"@types/react": "^19.3.0",
|
||||
"@types/react-dom": "^19.3.0",
|
||||
"@vitejs/plugin-react": "^6.1.1",
|
||||
@@ -153,18 +153,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.149.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.149.0.tgz",
|
||||
"integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==",
|
||||
"version": "0.151.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.151.0.tgz",
|
||||
"integrity": "sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/oxc-project"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm-eabi": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz",
|
||||
"integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.10.tgz",
|
||||
"integrity": "sha512-bp9svZb+QurZeh+8H4BhrZkifEB0YBNvTVzNSJnJQkj4NrRwmQoDUCGP0vSN7PbvLeM7l1tK6GXL8mrTiH2myg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -178,9 +178,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz",
|
||||
"integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.10.tgz",
|
||||
"integrity": "sha512-wm6Dld3RXUAZ/gRWKyUy+4W1B5CB5UeFaOzsSWJWEdxZXHH8rCYiZ5dGe6oJmhsunAPWzL7FZV+VtvmN5Ye2eA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -194,9 +194,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz",
|
||||
"integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.10.tgz",
|
||||
"integrity": "sha512-UbEfXq/AqGNgRTV3ik+X/iR6mUxu2QdYAadwRxJWquUGnW6gDqdP1FtLtFXRow7RJx0ssRwi80XAPr4r+4DtsA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -210,9 +210,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-x64": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz",
|
||||
"integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.10.tgz",
|
||||
"integrity": "sha512-7f5h17q5KZVx/ji1vb8OTq31ch1O2I7K8NPIr44GkyWTApXMIsmhWqZfgpOH10xeauqghDAvGlZktasCkcF6Eg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -226,9 +226,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz",
|
||||
"integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.10.tgz",
|
||||
"integrity": "sha512-ynOk/eEYhC6ZB2xCGvKrEOwE58oBy9LnrAqtkrDF9Fz1VTaNdGZTsV0VarJdhPwb+sOJTGjCLwcuyRJZ1dnMcQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -242,9 +242,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz",
|
||||
"integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.10.tgz",
|
||||
"integrity": "sha512-ERrAs185meZZhGan7a4l3RiiJK1ArSDlHdST++uvSxe+FDbR4TwUPahT/cbZJvaG6fIpDpF78surN+tX708Y4Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -258,9 +258,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz",
|
||||
"integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.10.tgz",
|
||||
"integrity": "sha512-KN7OHKD0J3jy1UzBwZWPxpwhODf9IARUIJcrH+yLYKOcmegZ8luEUM38lDP1bDVj40yP6PsSzCqOJF76vljFnQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -277,9 +277,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz",
|
||||
"integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.10.tgz",
|
||||
"integrity": "sha512-8l9wP8O+wa8zD6iw6egSfzVtu7oZVfH3hlUsMM4MwbLMhxleqeoXbZzjddyK3YyNlwLhqznq3tF7PkNJ8T/V2w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -296,9 +296,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz",
|
||||
"integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.10.tgz",
|
||||
"integrity": "sha512-SeXNKeQzA5kLhz/J0CH6ZP0/HJ3v1xm/0YbiYpE0kK7emfRC2OIGGIaE14xzkISEGv2aYuUSpiLiU5Gbq+OI0A==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -315,9 +315,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz",
|
||||
"integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.10.tgz",
|
||||
"integrity": "sha512-mtht0nR+y8/hart4175Ll15w7lY8dg7CtQ+j2FDNTsDRspOWTK/2V3l0aj9sIj7XmvqxT8Yli/wq22e7feTTWg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -334,9 +334,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz",
|
||||
"integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.10.tgz",
|
||||
"integrity": "sha512-FSM94nGd55NYo48usCyM/nHfUKRnqc9+b0vJNuKV0oCCpIp/OGims7rO1Nv/DkFkt0S/s2rxsJ2kkS8J3HcpeA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -353,9 +353,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz",
|
||||
"integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.10.tgz",
|
||||
"integrity": "sha512-C3YxNB16myRLs7o+B+6PnQ6jBsdIS4+AE4Ah8glVGhDpEv9AOvxhZ/1duAb4B0UGczEK/lBbccksd8VI+p6zfw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -372,9 +372,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz",
|
||||
"integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.10.tgz",
|
||||
"integrity": "sha512-571TlE/F1eeTjjdjYAMMMPs1Mfv3MtX6s3+ZKVU6HiUjZ5Njc6c/qzNy/8K3zALTZnaw3JQVYrHxvNfjm43KAg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -388,9 +388,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz",
|
||||
"integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.10.tgz",
|
||||
"integrity": "sha512-QXW+ZWaiqs2c7Fi++D/SsW07LTPcUrncxcskJGfGNBoaLik1IU6fJymz4HsqwEO0u5Iq11yTO0B/mc4cPk7jrQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -404,9 +404,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz",
|
||||
"integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.10.tgz",
|
||||
"integrity": "sha512-5FQFGgah17YeMtG1Yd5a+rMxQpTksyNXxRtKz06FVTaQw3RKYUJQbUoKk0/5jrXBpDo+7makNP7UHA2LQyH64A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -648,66 +648,6 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||
"version": "1.11.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.2.2",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||
"version": "1.11.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.2.2",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.1.4",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emnapi/core": "^1.7.1",
|
||||
"@emnapi/runtime": "^1.7.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.2",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"inBundle": true,
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
|
||||
@@ -765,9 +705,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.4.tgz",
|
||||
"integrity": "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.5.tgz",
|
||||
"integrity": "sha512-YbeJ6tctNoo40purO4u3Eeo3RVqmsjJr0NoKQRu+4pvO4gMLzkjta7x0k96SxSLmx+rQ+8um1ThOlw+HLpgFug==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"bin": {
|
||||
@@ -781,23 +721,23 @@
|
||||
"url": "https://opencollective.com/tauri"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tauri-apps/cli-darwin-arm64": "2.11.4",
|
||||
"@tauri-apps/cli-darwin-x64": "2.11.4",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.11.4",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.11.4",
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": "2.11.4",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.11.4",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.11.4",
|
||||
"@tauri-apps/cli-win32-arm64-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-darwin-arm64": "2.11.5",
|
||||
"@tauri-apps/cli-darwin-x64": "2.11.5",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.11.5",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.11.5",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.11.5",
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": "2.11.5",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.11.5",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.11.5",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "2.11.5",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "2.11.5",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "2.11.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.4.tgz",
|
||||
"integrity": "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.5.tgz",
|
||||
"integrity": "sha512-tggOiVOohjIHdiElbjeBfB41s6cmfsq+ZQ0PX0fEtCdsDdZ9cCi54e5gNK7tdPbR6JbdDe7RA4kbQdyyBUUk/Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -812,9 +752,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.4.tgz",
|
||||
"integrity": "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.5.tgz",
|
||||
"integrity": "sha512-SrO+KCbqvG1IvVPdlzQX4GEGZRQDISrmDY9bGcW68DLVFBCC06H+Loz6oyUZETUxsSMR6B4oDfvbQVgD4hxsqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -829,9 +769,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.4.tgz",
|
||||
"integrity": "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.5.tgz",
|
||||
"integrity": "sha512-qLrOaCa8hLD5QVPQRjAgOXvhlTFKXmTliVF773GgvADYcWZSdmncnF5zBFAkdu1uQK8KfQbDlBUwqQYZqBfBRQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -846,9 +786,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.4.tgz",
|
||||
"integrity": "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.5.tgz",
|
||||
"integrity": "sha512-Tq32xpQjiQEdIrvwDq7lwHhXemn070CXWdbCvr9rdi9rsv9NFTbQ6izVSIfNE+59QaerxuwtUtZ5IxDNWaoYBw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -866,9 +806,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.4.tgz",
|
||||
"integrity": "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.5.tgz",
|
||||
"integrity": "sha512-+OdWKj5Aq+C8HXypQ4t926V8cpVnc0ZcJIdhTXWjVAJHkaNuo8EuQR6KRZKHWIbJJgKdMPCDosvwzIFaBBqHKQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -886,9 +826,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.4.tgz",
|
||||
"integrity": "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.5.tgz",
|
||||
"integrity": "sha512-Q0V2hjpllyDW8dWQZSsITuQDfcY9BpBZuhXkMa2T5AFLZAn+FJPXQSyvnxWNVxRowdQ59Xn0QVtGm6HEHNUEvw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -906,9 +846,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.4.tgz",
|
||||
"integrity": "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.5.tgz",
|
||||
"integrity": "sha512-Xz1s87gFjZJZMQKAhLa77YeiCJM6yVog3f9OxDgVd/KxDIoB1dA5V2xOnMM+SRkOGk9juwIBqesVAjV0kUB0DA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -926,9 +866,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.4.tgz",
|
||||
"integrity": "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.5.tgz",
|
||||
"integrity": "sha512-6A88wqAZXZHgMaBrGiy/Bpa4GgUnftXM7uquKOeOXCuK78/XdBxEECicK/1oHgrT179XBFOaA6lQEHysjRmGig==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -946,9 +886,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.4.tgz",
|
||||
"integrity": "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.5.tgz",
|
||||
"integrity": "sha512-sRGgF/ObRfLcS3PtUdyTbJtkGq3E+PNZTknvAURwMNUtHw9DU/BF6S5si43y9lS5yEO9bWJCA+GGYvnn6cphQw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -963,9 +903,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.4.tgz",
|
||||
"integrity": "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.5.tgz",
|
||||
"integrity": "sha512-bHOv/yxqfKpI7ioIFQi5wOfZ7jkbPzJD/UhXY52I/hrmE3qNh71cohIPyqZB5GQn3LZeJWdCUOqmIg/w6XX+Wg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -980,9 +920,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||
"version": "2.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.4.tgz",
|
||||
"integrity": "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw==",
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.5.tgz",
|
||||
"integrity": "sha512-vaaOmavqdCeS7oMib2banBZemgrC5v54tSkwoBV+bxrXQZhQZrOwE2EO2i4x+CHNtvQUM/6bSs3iymZMAsycWg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1024,9 +964,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-log": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-log/-/plugin-log-2.9.1.tgz",
|
||||
"integrity": "sha512-8dYNEQOgZcIEqeFtHAsOIGLoptm+j94270Jf2MrGS/zbsYNd4C8DKyOdeYggAyE3ugwr12mTefIfC8lVVEhdlg==",
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-log/-/plugin-log-2.9.2.tgz",
|
||||
"integrity": "sha512-QC2uTQyC+4269xawGXzVLDzIvMB2JwzZHd1lg3ltXtXqrauwikqlbNt6Tm3H++1RN0gPtcvp4cBc5bF6u/DUnw==",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.11.0"
|
||||
@@ -1474,9 +1414,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker/node_modules/magic-string": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.1.tgz",
|
||||
"integrity": "sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
|
||||
"integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1530,9 +1470,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.24.5",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz",
|
||||
"integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==",
|
||||
"version": "5.25.1",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.25.1.tgz",
|
||||
"integrity": "sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
@@ -1932,9 +1872,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.18",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
|
||||
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
|
||||
"version": "3.3.19",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
|
||||
"integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1950,9 +1890,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/obug": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz",
|
||||
"integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz",
|
||||
"integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
"https://github.com/sponsors/sxzz",
|
||||
@@ -2031,9 +1971,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-i18next": {
|
||||
"version": "17.0.14",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.14.tgz",
|
||||
"integrity": "sha512-ZpMBfJL3BiXPuYHj5QMY1GwvKJNhE1vCxOJQ8BoMBdHP5XONTfi/Qss1nuRlnFdIl72PKo2jPmw+fxuLjRFgaQ==",
|
||||
"version": "17.0.15",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.15.tgz",
|
||||
"integrity": "sha512-7uYpx/oBkesLto7cOzOmfITlUBaXHCAcFahmgETMfWr8nbbWRRnVGvz8wsH/xpbNcyoH+NpCcnOQEqWPMO6/hw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.29.7",
|
||||
@@ -2058,12 +1998,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.8.tgz",
|
||||
"integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==",
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.10.tgz",
|
||||
"integrity": "sha512-OxkA08pSryMK7B3XiFA09B4OJ1xJMPgIYCBMY2xchzpqgBGsV1o0DetPAE+Sl3N3L4oCPiEzmHVSOj7iR04Zog==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "=0.149.0",
|
||||
"@oxc-project/types": "=0.151.0",
|
||||
"@rolldown/pluginutils": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -2073,21 +2013,21 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rolldown/binding-android-arm-eabi": "1.2.8",
|
||||
"@rolldown/binding-android-arm64": "1.2.8",
|
||||
"@rolldown/binding-darwin-arm64": "1.2.8",
|
||||
"@rolldown/binding-darwin-x64": "1.2.8",
|
||||
"@rolldown/binding-freebsd-x64": "1.2.8",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.2.8",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.2.8",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.2.8",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.2.8",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.2.8",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.2.8",
|
||||
"@rolldown/binding-linux-x64-musl": "1.2.8",
|
||||
"@rolldown/binding-openharmony-arm64": "1.2.8",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.2.8",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.2.8"
|
||||
"@rolldown/binding-android-arm-eabi": "1.2.10",
|
||||
"@rolldown/binding-android-arm64": "1.2.10",
|
||||
"@rolldown/binding-darwin-arm64": "1.2.10",
|
||||
"@rolldown/binding-darwin-x64": "1.2.10",
|
||||
"@rolldown/binding-freebsd-x64": "1.2.10",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.2.10",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.2.10",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.2.10",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.2.10",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.2.10",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.2.10",
|
||||
"@rolldown/binding-linux-x64-musl": "1.2.10",
|
||||
"@rolldown/binding-openharmony-arm64": "1.2.10",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.2.10",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.2.10"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
@@ -2217,9 +2157,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz",
|
||||
"integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
@@ -2647,13 +2587,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/magic-string": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz",
|
||||
"integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
|
||||
"integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
"@jridgewell/sourcemap-codec": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/why-is-node-running": {
|
||||
|
||||
+3
-3
@@ -56,18 +56,18 @@
|
||||
"@tauri-apps/plugin-clipboard-manager": "^2.3.3",
|
||||
"@tauri-apps/plugin-dialog": "^2.7.3",
|
||||
"@tauri-apps/plugin-fs": "^2.5.2",
|
||||
"@tauri-apps/plugin-log": "^2.9.1",
|
||||
"@tauri-apps/plugin-log": "^2.9.2",
|
||||
"@tauri-apps/plugin-notification": "^2.4.0",
|
||||
"@tauri-apps/plugin-opener": "^2.5.5",
|
||||
"i18next": "^26.4.2",
|
||||
"lucide-react": "^1.47.0",
|
||||
"react": "^19.3.0",
|
||||
"react-dom": "^19.3.0",
|
||||
"react-i18next": "^17.0.14",
|
||||
"react-i18next": "^17.0.15",
|
||||
"zustand": "^5.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.11.4",
|
||||
"@tauri-apps/cli": "^2.11.5",
|
||||
"@types/react": "^19.3.0",
|
||||
"@types/react-dom": "^19.3.0",
|
||||
"@vitejs/plugin-react": "^6.1.1",
|
||||
|
||||
@@ -12,7 +12,15 @@ const releaseWorkflow = fs.readFileSync(
|
||||
path.join(repositoryRoot, '.github', 'workflows', 'release.yml'),
|
||||
'utf8',
|
||||
);
|
||||
const cacheActionSha = '1bd1e32a3bdc45362d1e726936510720a7c30a57';
|
||||
const cacheActionSha = '55cc8345863c7cc4c66a329aec7e433d2d1c52a9';
|
||||
|
||||
test('CI and release use setup-node v7 while installing the supported app Node version', () => {
|
||||
for (const workflow of [ciWorkflow, releaseWorkflow]) {
|
||||
assert.match(workflow, /uses: actions\/setup-node@v7/);
|
||||
assert.match(workflow, /node-version: 22\.12/);
|
||||
assert.doesNotMatch(workflow, /actions\/setup-node@v6/);
|
||||
}
|
||||
});
|
||||
|
||||
function assertSafeEngineCacheWorkflow(workflow) {
|
||||
assert.match(workflow, new RegExp(`actions/cache/restore@${cacheActionSha}`));
|
||||
|
||||
Generated
+33
-32
@@ -1442,7 +1442,10 @@ dependencies = [
|
||||
"keepawake",
|
||||
"keyring-core",
|
||||
"log",
|
||||
"objc",
|
||||
"objc2",
|
||||
"objc2-app-kit",
|
||||
"objc2-core-services",
|
||||
"objc2-foundation",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rusqlite",
|
||||
@@ -2125,9 +2128,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.9"
|
||||
version = "0.27.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f"
|
||||
checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53"
|
||||
dependencies = [
|
||||
"http",
|
||||
"hyper",
|
||||
@@ -2662,9 +2665,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6480ccc157a1389bb2e4891b24751b0f798ba640d22386f23143fbcc89da195a"
|
||||
checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -2721,15 +2724,6 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.38.0"
|
||||
@@ -3040,15 +3034,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.4"
|
||||
@@ -3140,6 +3125,21 @@ dependencies = [
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-services"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "583300ad934cba24ff5292aee751ecc070f7ca6b39a574cc21b7b5e588e06a0b"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"block2",
|
||||
"dispatch2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-security",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
@@ -3178,6 +3178,7 @@ dependencies = [
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-services",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3741,9 +3742,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.10.2"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||
checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
|
||||
dependencies = [
|
||||
"chacha20",
|
||||
"getrandom 0.4.3",
|
||||
@@ -4807,9 +4808,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
||||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.11.5"
|
||||
version = "2.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5"
|
||||
checksum = "6fa5bacdb9bbad5954af3d1bd6cf6ae9192cab1b2e270f4a07f904610b9e85f4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -5015,9 +5016,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-log"
|
||||
version = "2.9.1"
|
||||
version = "2.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4e8861142c21636b03ff6eb9682a073814112e35220435670738a8be7b49896"
|
||||
checksum = "86f2e3c40b77fd1eb7f8e1b6900fb036aee2da1ea2d3783c91255a82c636649d"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"fern",
|
||||
@@ -5098,9 +5099,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.4.4"
|
||||
version = "2.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cd0cb5c412a5071b69bab6a6df1583cbb89460d4a83b6a24769b08d15b6b1e1"
|
||||
checksum = "db817fe9295e19b7d8357e900af31edb93703dd9fb6de524b007b47b6afc63b0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -5734,7 +5735,7 @@ dependencies = [
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.10.2",
|
||||
"rand 0.10.3",
|
||||
"sha1",
|
||||
"thiserror 2.0.20",
|
||||
]
|
||||
|
||||
@@ -43,7 +43,7 @@ sha2 = "0.11"
|
||||
sha1 = "0.11"
|
||||
base64 = { version = "0.23.1", default-features = false, features = ["std"] }
|
||||
tauri-plugin-deep-link = "2.4.10"
|
||||
tauri-plugin-single-instance = { version = "2.4.4", features = ["deep-link"] }
|
||||
tauri-plugin-single-instance = { version = "2.4.5", features = ["deep-link"] }
|
||||
tempfile = "3"
|
||||
thiserror = "2.0.20"
|
||||
axum = "0.8.9"
|
||||
@@ -57,14 +57,17 @@ chrono = "0.4.38"
|
||||
url = "2"
|
||||
rusqlite = { version = "0.40.2", features = ["bundled"] }
|
||||
log = "0.4.34"
|
||||
tauri-plugin-log = "2.9.1"
|
||||
tauri-plugin-log = "2.9.2"
|
||||
trash = "5"
|
||||
async-trait = "0.1"
|
||||
keyring-core = "1.0.0"
|
||||
auto-launch = "0.6.0"
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
apple-native-keyring-store = { version = "1.0.2", features = ["keychain"] }
|
||||
objc = "0.2.7"
|
||||
objc2 = "0.6"
|
||||
objc2-app-kit = { version = "0.3", default-features = false, features = ["NSApplication", "NSDockTile"] }
|
||||
objc2-core-services = "0.3"
|
||||
objc2-foundation = { version = "0.3", default-features = false, features = ["NSAppleEventDescriptor", "NSAppleEventManager", "NSAppleScript", "NSDictionary", "NSNotification", "NSObject", "NSString", "objc2-core-services", "std"] }
|
||||
smappservice-rs = "0.1.3"
|
||||
unicode-normalization = "0.1.25"
|
||||
|
||||
|
||||
Binary file not shown.
+209
-49
@@ -3821,6 +3821,48 @@ struct MainWindowRestoreState {
|
||||
requested: AtomicBool,
|
||||
startup_complete: AtomicBool,
|
||||
started_at_login: AtomicBool,
|
||||
pending_opened_torrent_paths: std::sync::Mutex<PendingOpenedTorrentPaths>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct PendingOpenedTorrentPaths {
|
||||
app_state_ready: bool,
|
||||
paths: Vec<String>,
|
||||
}
|
||||
|
||||
impl MainWindowRestoreState {
|
||||
fn route_opened_torrent_paths(&self, paths: Vec<String>) -> Option<Vec<String>> {
|
||||
let mut pending = match self.pending_opened_torrent_paths.lock() {
|
||||
Ok(pending) => pending,
|
||||
Err(_) => {
|
||||
log::error!("could not access pending opened Torrent paths during startup");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
if pending.app_state_ready {
|
||||
return Some(paths);
|
||||
}
|
||||
|
||||
let remaining = MAX_DEEP_LINK_URLS.saturating_sub(pending.paths.len());
|
||||
let dropped = paths.len().saturating_sub(remaining);
|
||||
pending.paths.extend(paths.into_iter().take(remaining));
|
||||
if dropped > 0 {
|
||||
log::warn!(
|
||||
"discarded {dropped} opened Torrent paths because the startup queue reached its capacity"
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn mark_app_state_ready_and_take_pending_paths(&self) -> Vec<String> {
|
||||
let Ok(mut pending) = self.pending_opened_torrent_paths.lock() else {
|
||||
log::error!("could not drain pending opened Torrent paths during startup");
|
||||
return Vec::new();
|
||||
};
|
||||
pending.app_state_ready = true;
|
||||
std::mem::take(&mut pending.paths)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -4220,7 +4262,24 @@ fn dispatch_opened_torrent_paths(app_handle: tauri::AppHandle, paths: Vec<String
|
||||
return;
|
||||
}
|
||||
restore_main_window(&app_handle);
|
||||
let coordinator = app_handle.state::<AppState>().download_coordinator.clone();
|
||||
let Some(startup_state) = app_handle.try_state::<MainWindowRestoreState>() else {
|
||||
log::error!("could not route opened Torrent paths because startup state is unavailable");
|
||||
return;
|
||||
};
|
||||
let Some(paths) = startup_state.route_opened_torrent_paths(paths) else {
|
||||
return;
|
||||
};
|
||||
if paths.is_empty() {
|
||||
return;
|
||||
}
|
||||
let Some(app_state) = app_handle.try_state::<AppState>() else {
|
||||
// AppState is published before startup_state is marked ready. Reaching
|
||||
// this branch indicates a broken startup ordering, so fail without
|
||||
// panicking inside the platform's single-instance message callback.
|
||||
log::error!("opened Torrent paths became dispatchable before app state was available");
|
||||
return;
|
||||
};
|
||||
let coordinator = app_state.download_coordinator.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
if let Err(error) = coordinator
|
||||
.send(download::DownloadCmd::CaptureUrls(paths))
|
||||
@@ -8735,14 +8794,18 @@ fn update_dock_badge(
|
||||
properties_window::ensure_main_window(&caller)?;
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use objc::runtime::Object;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
use std::ffi::CString;
|
||||
use objc2::MainThreadMarker;
|
||||
use objc2_app_kit::NSApplication;
|
||||
use objc2_foundation::NSString;
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
|
||||
static LAST_DOCK_BADGE_STATE: OnceLock<Mutex<(u64, u64)>> = OnceLock::new();
|
||||
|
||||
let _ = app_handle.run_on_main_thread(move || {
|
||||
if let Err(error) = app_handle.run_on_main_thread(move || {
|
||||
let Some(main_thread) = MainThreadMarker::new() else {
|
||||
log::error!("Tauri dispatched Dock badge update off the macOS main thread");
|
||||
return;
|
||||
};
|
||||
let state = LAST_DOCK_BADGE_STATE.get_or_init(|| Mutex::new((0, 0)));
|
||||
let Ok(mut state) = state.lock() else {
|
||||
return;
|
||||
@@ -8752,23 +8815,16 @@ fn update_dock_badge(
|
||||
}
|
||||
*state = (session, generation);
|
||||
drop(state);
|
||||
unsafe {
|
||||
let app_class = class!(NSApplication);
|
||||
let app: *mut Object = msg_send![app_class, sharedApplication];
|
||||
let dock_tile: *mut Object = msg_send![app, dockTile];
|
||||
let label = if count > 0 {
|
||||
count.to_string()
|
||||
let dock_tile = NSApplication::sharedApplication(main_thread).dockTile();
|
||||
if count > 0 {
|
||||
let label = NSString::from_str(&count.to_string());
|
||||
dock_tile.setBadgeLabel(Some(&label));
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
let c_label = CString::new(label).unwrap();
|
||||
let ns_string_class = class!(NSString);
|
||||
let ns_label: *mut Object = msg_send![ns_string_class, alloc];
|
||||
let ns_label: *mut Object = msg_send![ns_label, initWithUTF8String: c_label.as_ptr()];
|
||||
let _: () = msg_send![dock_tile, setBadgeLabel: ns_label];
|
||||
let _: () = msg_send![ns_label, release];
|
||||
dock_tile.setBadgeLabel(None);
|
||||
}
|
||||
});
|
||||
}) {
|
||||
log::warn!("could not schedule macOS Dock badge update: {error}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -13271,43 +13327,66 @@ async fn set_global_speed_limit(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn check_automation_permission_on_main_thread(
|
||||
_main_thread: objc2::MainThreadMarker,
|
||||
) -> Result<(), String> {
|
||||
use objc2::msg_send;
|
||||
use objc2::rc::{autoreleasepool, Retained};
|
||||
use objc2::runtime::AnyObject;
|
||||
use objc2::AnyThread;
|
||||
use objc2_foundation::{NSAppleEventDescriptor, NSAppleScript, NSDictionary, NSString};
|
||||
|
||||
autoreleasepool(|_| {
|
||||
let script_source = NSString::from_str("tell application \"System Events\" to get name");
|
||||
let Some(script) = NSAppleScript::initWithSource(NSAppleScript::alloc(), &script_source)
|
||||
else {
|
||||
return Err("Automation permission was not granted".to_string());
|
||||
};
|
||||
|
||||
let mut error_info: Option<Retained<NSDictionary<NSString, AnyObject>>> = None;
|
||||
// Apple's SDK documents a nil result on failure, but its header
|
||||
// omits nullable from the return type. Preserve the real failure
|
||||
// contract by decoding the Objective-C object result as optional.
|
||||
// objc2 retains +0 object returns and autoreleased out-parameters when
|
||||
// converting them to Retained, so they remain valid through this pool.
|
||||
let result: Option<Retained<NSAppleEventDescriptor>> =
|
||||
unsafe { msg_send![&*script, executeAndReturnError: &mut error_info] };
|
||||
if result.is_none() || error_info.is_some() {
|
||||
return Err("Automation permission was not granted".to_string());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn check_automation_permission(caller: tauri::WebviewWindow) -> Result<(), String> {
|
||||
async fn check_automation_permission(
|
||||
caller: tauri::WebviewWindow,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<(), String> {
|
||||
properties_window::ensure_main_window(&caller)?;
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use objc::runtime::Object;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
use std::ffi::CString;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
unsafe {
|
||||
objc::rc::autoreleasepool(|| {
|
||||
let script = "tell application \"System Events\" to get name";
|
||||
let c_script = CString::new(script).unwrap();
|
||||
let ns_string_class = class!(NSString);
|
||||
let script_str: *mut Object = msg_send![ns_string_class, alloc];
|
||||
let script_str: *mut Object = msg_send![script_str, initWithUTF8String: c_script.as_ptr()];
|
||||
|
||||
let ns_apple_script: *mut Object = msg_send![class!(NSAppleScript), alloc];
|
||||
let ns_apple_script: *mut Object = msg_send![ns_apple_script, initWithSource: script_str];
|
||||
|
||||
let mut error_dict: *mut Object = null_mut();
|
||||
let result: *mut Object = msg_send![ns_apple_script, executeAndReturnError: &mut error_dict];
|
||||
|
||||
let _: () = msg_send![script_str, release];
|
||||
let _: () = msg_send![ns_apple_script, release];
|
||||
|
||||
if result.is_null() {
|
||||
return Err("Automation permission was not granted".to_string());
|
||||
}
|
||||
Ok(())
|
||||
let (result_sender, result_receiver) = tokio::sync::oneshot::channel();
|
||||
app_handle
|
||||
.run_on_main_thread(move || {
|
||||
let result = match objc2::MainThreadMarker::new() {
|
||||
Some(main_thread) => check_automation_permission_on_main_thread(main_thread),
|
||||
None => Err("macOS Automation check did not run on the main thread".to_string()),
|
||||
};
|
||||
let _ = result_sender.send(result);
|
||||
})
|
||||
}
|
||||
.map_err(|error| format!("could not schedule macOS Automation check: {error}"))?;
|
||||
result_receiver
|
||||
.await
|
||||
.map_err(|_| "macOS Automation check did not complete".to_string())?
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
Ok(())
|
||||
{
|
||||
let _ = app_handle;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -18858,6 +18937,77 @@ mod tests {
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffers_opened_torrent_paths_until_app_state_is_ready() {
|
||||
let state = super::MainWindowRestoreState::default();
|
||||
|
||||
assert_eq!(
|
||||
state.route_opened_torrent_paths(vec!["first.torrent".to_string()]),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
state.route_opened_torrent_paths(vec!["second.torrent".to_string()]),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
state.mark_app_state_ready_and_take_pending_paths(),
|
||||
vec!["first.torrent".to_string(), "second.torrent".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
state.route_opened_torrent_paths(vec!["third.torrent".to_string()]),
|
||||
Some(vec!["third.torrent".to_string()])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounds_opened_torrent_paths_buffer_during_startup() {
|
||||
let state = super::MainWindowRestoreState::default();
|
||||
let paths = (0..super::MAX_DEEP_LINK_URLS)
|
||||
.map(|index| format!("{index}.torrent"))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(state.route_opened_torrent_paths(paths.clone()), None);
|
||||
assert_eq!(
|
||||
state.route_opened_torrent_paths(vec!["overflow.torrent".to_string()]),
|
||||
None
|
||||
);
|
||||
assert_eq!(state.mark_app_state_ready_and_take_pending_paths(), paths);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opened_torrent_paths_racing_startup_are_never_lost() {
|
||||
use std::sync::{Arc, Barrier};
|
||||
|
||||
const PATH_COUNT: usize = 16;
|
||||
let state = Arc::new(super::MainWindowRestoreState::default());
|
||||
let barrier = Arc::new(Barrier::new(PATH_COUNT + 1));
|
||||
let workers = (0..PATH_COUNT)
|
||||
.map(|index| {
|
||||
let state = Arc::clone(&state);
|
||||
let barrier = Arc::clone(&barrier);
|
||||
std::thread::spawn(move || {
|
||||
barrier.wait();
|
||||
state.route_opened_torrent_paths(vec![format!("{index}.torrent")])
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
barrier.wait();
|
||||
let mut delivered = state.mark_app_state_ready_and_take_pending_paths();
|
||||
for worker in workers {
|
||||
if let Some(paths) = worker.join().expect("path dispatch worker should complete") {
|
||||
delivered.extend(paths);
|
||||
}
|
||||
}
|
||||
|
||||
delivered.sort();
|
||||
let mut expected = (0..PATH_COUNT)
|
||||
.map(|index| format!("{index}.torrent"))
|
||||
.collect::<Vec<_>>();
|
||||
expected.sort();
|
||||
assert_eq!(delivered, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_launch_variants_and_nested_schemes() {
|
||||
let links = [
|
||||
@@ -20363,6 +20513,16 @@ pub fn run() {
|
||||
queue_manager,
|
||||
});
|
||||
|
||||
let pending_opened_torrent_paths = app
|
||||
.state::<MainWindowRestoreState>()
|
||||
.mark_app_state_ready_and_take_pending_paths();
|
||||
if !pending_opened_torrent_paths.is_empty() {
|
||||
dispatch_opened_torrent_paths(
|
||||
app.handle().clone(),
|
||||
pending_opened_torrent_paths,
|
||||
);
|
||||
}
|
||||
|
||||
if let Err(error) = power_manager.activate() {
|
||||
log::error!("power: failed to activate backend power management: {error}");
|
||||
}
|
||||
|
||||
@@ -61,112 +61,116 @@ pub fn install_macos_login_launch_detector() {}
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos_login_event {
|
||||
use super::{AtomicBool, Once, Ordering};
|
||||
use objc::declare::ClassDecl;
|
||||
use objc::runtime::{Object, Sel};
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
use objc2::rc::{Allocated, Retained};
|
||||
use objc2::{define_class, msg_send, sel, ClassType, MainThreadMarker};
|
||||
use objc2_app_kit::{NSApplication, NSApplicationWillFinishLaunchingNotification};
|
||||
use objc2_core_services::{AEEventClass, AEEventID, AEKeyword};
|
||||
use objc2_foundation::{
|
||||
NSAppleEventDescriptor, NSAppleEventManager, NSNotification, NSNotificationCenter,
|
||||
NSObject, NSObjectProtocol,
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
// Core Event / Open Application / property-data / login-item marker.
|
||||
const K_CORE_EVENT_CLASS: u32 = u32::from_be_bytes(*b"aevt");
|
||||
const K_AE_OPEN_APPLICATION: u32 = u32::from_be_bytes(*b"oapp");
|
||||
const KEY_AE_PROP_DATA: u32 = u32::from_be_bytes(*b"prdt");
|
||||
const K_CORE_EVENT_CLASS: AEEventClass = u32::from_be_bytes(*b"aevt");
|
||||
const K_AE_OPEN_APPLICATION: AEEventID = u32::from_be_bytes(*b"oapp");
|
||||
const KEY_AE_PROP_DATA: AEKeyword = u32::from_be_bytes(*b"prdt");
|
||||
const KEY_AE_LAUNCHED_AS_LOGIN_ITEM: u32 = u32::from_be_bytes(*b"lgit");
|
||||
const TYPE_TYPE: u32 = u32::from_be_bytes(*b"type");
|
||||
|
||||
static INSTALL: Once = Once::new();
|
||||
static OBSERVER: OnceLock<Retained<LoginLaunchObserver>> = OnceLock::new();
|
||||
static LOGIN_LAUNCH: AtomicBool = AtomicBool::new(false);
|
||||
static DECIDED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
extern "C" fn application_will_finish_launching(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
_notification: *mut Object,
|
||||
) {
|
||||
unsafe {
|
||||
let manager: *mut Object =
|
||||
msg_send![class!(NSAppleEventManager), sharedAppleEventManager];
|
||||
if manager.is_null() {
|
||||
return;
|
||||
define_class!(
|
||||
// SAFETY:
|
||||
// - NSObject has no subclassing requirements.
|
||||
// - The observer has no Rust destructor or thread-confined state.
|
||||
#[unsafe(super(NSObject))]
|
||||
#[name = "FirelinkLoginLaunchObserver"]
|
||||
#[ivars = ()]
|
||||
struct LoginLaunchObserver;
|
||||
|
||||
impl LoginLaunchObserver {
|
||||
#[unsafe(method_id(init))]
|
||||
fn init(this: Allocated<Self>) -> Retained<Self> {
|
||||
let this = this.set_ivars(());
|
||||
unsafe { msg_send![super(this), init] }
|
||||
}
|
||||
|
||||
let _: () = msg_send![
|
||||
manager,
|
||||
setEventHandler: this as *const Object as *mut Object
|
||||
andSelector: sel!(handleAppleEvent:withReplyEvent:)
|
||||
forEventClass: K_CORE_EVENT_CLASS
|
||||
andEventID: K_AE_OPEN_APPLICATION
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn handle_apple_event(
|
||||
_this: &Object,
|
||||
_cmd: Sel,
|
||||
event: *mut Object,
|
||||
_reply_event: *mut Object,
|
||||
) {
|
||||
let is_login_launch = unsafe {
|
||||
if event.is_null() {
|
||||
false
|
||||
} else {
|
||||
let property_data: *mut Object =
|
||||
msg_send![event, paramDescriptorForKeyword: KEY_AE_PROP_DATA];
|
||||
if property_data.is_null() {
|
||||
false
|
||||
} else {
|
||||
let descriptor_type: u32 = msg_send![property_data, descriptorType];
|
||||
if descriptor_type != TYPE_TYPE {
|
||||
false
|
||||
} else {
|
||||
let value: u32 = msg_send![property_data, typeCodeValue];
|
||||
value == KEY_AE_LAUNCHED_AS_LOGIN_ITEM
|
||||
}
|
||||
#[unsafe(method(applicationWillFinishLaunching:))]
|
||||
fn application_will_finish_launching(&self, _notification: &NSNotification) {
|
||||
let manager = NSAppleEventManager::sharedAppleEventManager();
|
||||
// SAFETY: The selector is implemented below with the matching
|
||||
// Apple Event handler signature, and `self` is this observer.
|
||||
unsafe {
|
||||
manager.setEventHandler_andSelector_forEventClass_andEventID(
|
||||
self,
|
||||
sel!(handleAppleEvent:withReplyEvent:),
|
||||
K_CORE_EVENT_CLASS,
|
||||
K_AE_OPEN_APPLICATION,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if DECIDED
|
||||
.compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire)
|
||||
.is_ok()
|
||||
{
|
||||
LOGIN_LAUNCH.store(is_login_launch, Ordering::Release);
|
||||
#[unsafe(method(handleAppleEvent:withReplyEvent:))]
|
||||
fn handle_apple_event(
|
||||
&self,
|
||||
event: Option<&NSAppleEventDescriptor>,
|
||||
_reply_event: Option<&NSAppleEventDescriptor>,
|
||||
) {
|
||||
let is_login_launch = event
|
||||
.and_then(|event| event.paramDescriptorForKeyword(KEY_AE_PROP_DATA))
|
||||
.is_some_and(|property_data| {
|
||||
property_data.descriptorType() == TYPE_TYPE
|
||||
&& property_data.typeCodeValue() == KEY_AE_LAUNCHED_AS_LOGIN_ITEM
|
||||
});
|
||||
|
||||
if DECIDED
|
||||
.compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire)
|
||||
.is_ok()
|
||||
{
|
||||
LOGIN_LAUNCH.store(is_login_launch, Ordering::Release);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl NSObjectProtocol for LoginLaunchObserver {}
|
||||
);
|
||||
|
||||
pub fn install() {
|
||||
INSTALL.call_once(|| unsafe {
|
||||
let mut declaration = ClassDecl::new("FirelinkLoginLaunchObserver", class!(NSObject))
|
||||
.expect("could not allocate macOS login-launch observer class");
|
||||
declaration.add_method(
|
||||
sel!(applicationWillFinishLaunching:),
|
||||
application_will_finish_launching as extern "C" fn(&Object, Sel, *mut Object),
|
||||
);
|
||||
declaration.add_method(
|
||||
sel!(handleAppleEvent:withReplyEvent:),
|
||||
handle_apple_event as extern "C" fn(&Object, Sel, *mut Object, *mut Object),
|
||||
);
|
||||
let observer_class = declaration.register();
|
||||
let observer: *mut Object = msg_send![observer_class, new];
|
||||
if observer.is_null() {
|
||||
log::error!("could not create macOS login-launch observer");
|
||||
INSTALL.call_once(|| {
|
||||
let Some(main_thread) = MainThreadMarker::new() else {
|
||||
log::error!("could not install macOS login-launch observer off the main thread");
|
||||
return;
|
||||
};
|
||||
|
||||
let application = NSApplication::sharedApplication(main_thread);
|
||||
let observer: Retained<LoginLaunchObserver> =
|
||||
unsafe { msg_send![LoginLaunchObserver::class(), new] };
|
||||
if OBSERVER.set(observer).is_err() {
|
||||
log::error!("could not retain macOS login-launch observer");
|
||||
return;
|
||||
}
|
||||
|
||||
// NotificationCenter does not own selector-based observers. The
|
||||
// object is intentionally retained for the process lifetime.
|
||||
let notification_center: *mut Object =
|
||||
msg_send![class!(NSNotificationCenter), defaultCenter];
|
||||
let application: *mut Object = msg_send![class!(NSApplication), sharedApplication];
|
||||
let notification_name: *mut Object = msg_send![
|
||||
class!(NSString),
|
||||
stringWithUTF8String: b"NSApplicationWillFinishLaunchingNotification\0".as_ptr()
|
||||
];
|
||||
let _: () = msg_send![
|
||||
notification_center,
|
||||
addObserver: observer
|
||||
selector: sel!(applicationWillFinishLaunching:)
|
||||
name: notification_name
|
||||
object: application
|
||||
];
|
||||
let Some(observer) = OBSERVER.get() else {
|
||||
log::error!("macOS login-launch observer was not retained");
|
||||
return;
|
||||
};
|
||||
let notification_center = NSNotificationCenter::defaultCenter();
|
||||
// NotificationCenter does not own selector-based observers. Keep
|
||||
// the observer retained in OBSERVER for the process lifetime.
|
||||
// SAFETY: The selector is implemented by LoginLaunchObserver and
|
||||
// the notification name and object are the matching AppKit values.
|
||||
unsafe {
|
||||
notification_center.addObserver_selector_name_object(
|
||||
observer,
|
||||
sel!(applicationWillFinishLaunching:),
|
||||
Some(NSApplicationWillFinishLaunchingNotification),
|
||||
Some(&application),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user