Update impl

This commit is contained in:
2026-04-13 18:46:18 +08:00
parent cdd21f4633
commit a6fce677e8
7 changed files with 93 additions and 56 deletions

View File

@@ -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",

26
src-tauri/Cargo.lock generated
View File

@@ -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"

View File

@@ -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"

View File

@@ -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"
]
}

View File

@@ -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,

View File

@@ -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<string | null>(null);
const containerRef = useRef<HTMLDivElement>(null);
const imgRef = useRef<HTMLImageElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(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 (
<div style={containerStyle} ref={containerRef}>
{/* Hidden original image for pica source */}
<img
ref={imgRef}
src={objectUrl!}
alt={path.split('|').pop()?.split(/[/\\]/).pop() ?? ''}
style={{ display: 'none' }}
onLoad={handleImageLoad}
/>
<canvas
ref={canvasRef}
style={{
...imgStyle,
transform: `translate(calc(-50% + ${position.x}px), calc(-50% + ${position.y}px)) scale(${currentScale})`,
width: baseW,
height: baseH,
transform: `translate(calc(-50% + ${position.x}px), calc(-50% + ${position.y}px)) scale(${visualScale})`,
cursor: 'grab',
imageRendering: 'auto',
visibility: baseW > 0 ? 'visible' : 'hidden',
}}
draggable={false}
onClick={(e) => e.stopPropagation()}
onMouseDown={handleMouseDown}
onLoad={handleImageLoad}
/>
{/* Toolbar */}

View File

@@ -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"