From a6fce677e83a41c15fae5c33e900f35516f76945 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Mon, 13 Apr 2026 18:46:18 +0800 Subject: [PATCH] Update impl --- package.json | 6 ++-- src-tauri/Cargo.lock | 26 -------------- src-tauri/Cargo.toml | 3 +- src-tauri/capabilities/default.json | 16 +-------- src-tauri/src/lib.rs | 1 - src/components/ImagePreviewPanel.tsx | 45 ++++++++++++++++++++++-- yarn.lock | 52 +++++++++++++++++++++++----- 7 files changed, 93 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index fd3eaf7..ee4cd31 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,16 @@ "dependencies": { "@ant-design/icons": "^6.1.1", "@tauri-apps/api": "^2", - "@tauri-apps/plugin-fs": "^2.5.0", "@tauri-apps/plugin-opener": "^2", "antd": "^6.3.5", + "pica": "^9.0.1", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "use-debounce": "^10.1.1" }, "devDependencies": { "@tauri-apps/cli": "^2", + "@types/pica": "^9.0.5", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.4", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1ac332d..2ff256a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1837,7 +1837,6 @@ dependencies = [ "serde_json", "tauri", "tauri-build", - "tauri-plugin-fs", "tauri-plugin-opener", ] @@ -3469,7 +3468,6 @@ checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.11.0", "block2", - "libc", "objc2", "objc2-core-foundation", ] @@ -5202,30 +5200,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "tauri-plugin-fs" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36e1ec28b79f3d0683f4507e1615c36292c0ea6716668770d4396b9b39871ed8" -dependencies = [ - "anyhow", - "dunce", - "glob", - "log", - "objc2-foundation", - "percent-encoding", - "schemars 0.8.22", - "serde", - "serde_json", - "serde_repr", - "tauri", - "tauri-plugin", - "tauri-utils", - "thiserror 2.0.18", - "toml 0.9.12+spec-1.1.0", - "url", -] - [[package]] name = "tauri-plugin-opener" version = "2.5.3" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a2372f1..67e58b5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -23,9 +23,8 @@ encoding = "0.2" image = { version = "0.25", default-features = false, features = ["png", "jpeg", "gif", "bmp", "tiff", "ico", "webp"] } lazy_static = "1.5" msg_tool = { path = "../../MsgTool" } -tauri = { version = "2", features = [] } +tauri = { version = "2", features = ["devtools"] } tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" -tauri-plugin-fs = "2.5.0" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 5d8648c..4cdbf49 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -5,20 +5,6 @@ "windows": ["main"], "permissions": [ "core:default", - "opener:default", - "fs:default", - { - "identifier": "fs:allow-read", - "allow": [{ "path": "**" }] - }, - { - "identifier": "fs:allow-write", - "allow": [{ "path": "**" }] - }, - { - "identifier": "fs:allow-mkdir", - "allow": [{ "path": "**" }] - }, - "fs:allow-exists" + "opener:default" ] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index f25834a..a3d0b24 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -4,7 +4,6 @@ mod backend; pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) - .plugin(tauri_plugin_fs::init()) .invoke_handler(tauri::generate_handler![ backend::get_start_directory, backend::get_xp3_supported_games, diff --git a/src/components/ImagePreviewPanel.tsx b/src/components/ImagePreviewPanel.tsx index 0fc8989..1a433f2 100644 --- a/src/components/ImagePreviewPanel.tsx +++ b/src/components/ImagePreviewPanel.tsx @@ -3,6 +3,10 @@ import { Spin, Button, Tooltip, Space } from 'antd'; import { CompressOutlined, BorderOuterOutlined } from '@ant-design/icons'; import { FileOptions } from '../types'; import { previewImage } from '../api'; +import pica from 'pica'; +import { useDebounce } from 'use-debounce'; + +const picaInstance = pica({ features: ['js', 'wasm', 'cib'] }); interface ImagePreviewPanelProps { path: string; @@ -24,6 +28,8 @@ export function ImagePreviewPanel({ path, options }: ImagePreviewPanelProps) { const prevUrlRef = useRef(null); const containerRef = useRef(null); + const imgRef = useRef(null); + const canvasRef = useRef(null); const isDragging = useRef(false); const dragStart = useRef({ mouseX: 0, mouseY: 0, imgX: 0, imgY: 0 }); @@ -141,7 +147,27 @@ export function ImagePreviewPanel({ path, options }: ImagePreviewPanelProps) { }; const currentScale = getScale(); + const [debouncedScale] = useDebounce(currentScale, 300); + useEffect(() => { + if (!imgRef.current || !canvasRef.current || !imageSize || !objectUrl) return; + const cw = Math.max(1, Math.round(imageSize.w * debouncedScale)); + const ch = Math.max(1, Math.round(imageSize.h * debouncedScale)); + + // To support retina displays, multiply canvas actual dimensions by devicePixelRatio + const dpr = window.devicePixelRatio || 1; + const canvas = canvasRef.current; + if (canvas.width !== cw * dpr || canvas.height !== ch * dpr) { + canvas.width = cw * dpr; + canvas.height = ch * dpr; + } + + picaInstance.resize(imgRef.current, canvas, { + unsharpAmount: 60, + unsharpRadius: 0.6, + unsharpThreshold: 2 + }).catch(console.warn); + }, [debouncedScale, imageSize, objectUrl]); const stateRef = useRef({ imageSize, containerSize, scaleMode, customScale, position }); stateRef.current = { imageSize, containerSize, scaleMode, customScale, position }; @@ -207,20 +233,35 @@ export function ImagePreviewPanel({ path, options }: ImagePreviewPanelProps) { if (!objectUrl) return null; + const visualScale = currentScale / (debouncedScale || currentScale); + const baseW = imageSize ? imageSize.w * debouncedScale : 0; + const baseH = imageSize ? imageSize.h * debouncedScale : 0; + return (
+ {/* Hidden original image for pica source */} {path.split('|').pop()?.split(/[/\\]/).pop() + + 0 ? 'visible' : 'hidden', }} draggable={false} onClick={(e) => e.stopPropagation()} onMouseDown={handleMouseDown} - onLoad={handleImageLoad} /> {/* Toolbar */} diff --git a/yarn.lock b/yarn.lock index 87b3800..f6368ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -919,7 +919,7 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz#23b860113e9f87eea015d1fa3a4240a52b42fcd4" integrity sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ== -"@tauri-apps/api@^2", "@tauri-apps/api@^2.10.1", "@tauri-apps/api@^2.8.0": +"@tauri-apps/api@^2", "@tauri-apps/api@^2.8.0": version "2.10.1" resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-2.10.1.tgz#57c1bae6114ec33d977eb2b50dfefc25fa84fc93" integrity sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw== @@ -996,13 +996,6 @@ "@tauri-apps/cli-win32-ia32-msvc" "2.10.1" "@tauri-apps/cli-win32-x64-msvc" "2.10.1" -"@tauri-apps/plugin-fs@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-fs/-/plugin-fs-2.5.0.tgz#977d31ceb6aad600817aaa5233e0d86aee500aad" - integrity sha512-c83kbz61AK+rKjhS+je9+stIO27nXj7p9cqeg36TwkIUtxpCFTttlHHtqon6h6FN54cXjyAjlMPOJcW3mwE5XQ== - dependencies: - "@tauri-apps/api" "^2.10.1" - "@tauri-apps/plugin-opener@^2": version "2.5.3" resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz#09f8fe143567839cc491f4f8fde21caa0f1a8b89" @@ -1048,6 +1041,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== +"@types/pica@^9.0.5": + version "9.0.5" + resolved "https://registry.yarnpkg.com/@types/pica/-/pica-9.0.5.tgz#a526b51d45b7cb70423b7af0223ab9afd151a26e" + integrity sha512-OSd4905yxFNtRanHuyyQAfC9AkxiYcbhlzP606Gl6rFcYRgq4vdLCZuYKokLQBihgrkNzyPkoeykvJDWcPjaCw== + "@types/prop-types@*": version "15.7.15" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.15.tgz#e6e5a86d602beaca71ce5163fadf5f95d70931c7" @@ -1242,6 +1240,11 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +glur@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/glur/-/glur-1.1.2.tgz#f20ea36db103bfc292343921f1f91e83c3467689" + integrity sha512-l+8esYHTKOx2G/Aao4lEQ0bnHWg4fWtJbVoZZT9Knxi01pB8C80BR85nONLFwkkQoFRCmXY+BUcGZN3yZ2QsRA== + is-mobile@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-mobile/-/is-mobile-5.0.0.tgz#1e08a0ef2c38a67bff84a52af68d67bcef445333" @@ -1288,6 +1291,14 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multimath@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/multimath/-/multimath-2.0.0.tgz#0d37acf67c328f30e3d8c6b0d3209e6082710302" + integrity sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g== + dependencies: + glur "^1.1.2" + object-assign "^4.1.1" + nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" @@ -1298,6 +1309,21 @@ node-releases@^2.0.36: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.37.tgz#9bd4f10b77ba39c2b9402d4e8399c482a797f671" integrity sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg== +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +pica@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/pica/-/pica-9.0.1.tgz#9ba5a5e81fc09dca9800abef9fb8388434b18b2f" + integrity sha512-v0U4vY6Z3ztz9b4jBIhCD3WYoecGXCQeCsYep+sXRefViL+mVVoTL+wqzdPeE+GpBFsRUtQZb6dltvAt2UkMtQ== + dependencies: + glur "^1.1.2" + multimath "^2.0.0" + object-assign "^4.1.1" + webworkify "^1.5.0" + picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -1436,6 +1462,11 @@ update-browserslist-db@^1.2.3: escalade "^3.2.0" picocolors "^1.1.1" +use-debounce@^10.1.1: + version "10.1.1" + resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-10.1.1.tgz#b08b596b60a55fd4c18b44b37fdc02f058baf30a" + integrity sha512-kvds8BHR2k28cFsxW8k3nc/tRga2rs1RHYCqmmGqb90MEeE++oALwzh2COiuBLO1/QXiOuShXoSN2ZpWnMmvuQ== + vite@^6.0.3: version "6.4.2" resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.2.tgz#a4e548ca3a90ca9f3724582cab35e1ba15efc6f2" @@ -1450,6 +1481,11 @@ vite@^6.0.3: optionalDependencies: fsevents "~2.3.3" +webworkify@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/webworkify/-/webworkify-1.5.0.tgz#734ad87a774de6ebdd546e1d3e027da5b8f4a42c" + integrity sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"