Skip to content

Commit 25dbcf5

Browse files
authored
Merge pull request #37 from nuthx/dev-2.0.2
Dev 2.0.2
2 parents 3863ffb + d9c4aae commit 25dbcf5

9 files changed

Lines changed: 107 additions & 40 deletions

File tree

icons/icon.ico

-9.95 KB
Binary file not shown.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "subtitle-renamer",
33
"private": true,
4-
"version": "2.0.1",
4+
"version": "2.0.2",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",
@@ -26,7 +26,8 @@
2626
"react-dom": "^19.2.3",
2727
"react-router-dom": "^7.11.0",
2828
"sonner": "^2.0.7",
29-
"tailwind-merge": "^3.4.0"
29+
"tailwind-merge": "^3.4.0",
30+
"zustand": "^5.0.9"
3031
},
3132
"devDependencies": {
3233
"@eslint/js": "^9.39.2",
@@ -37,7 +38,7 @@
3738
"eslint": "^9.39.2",
3839
"eslint-plugin-react": "^7.37.5",
3940
"eslint-plugin-react-hooks": "^7.0.1",
40-
"globals": "^16.5.0",
41+
"globals": "^17.0.0",
4142
"tailwind-scrollbar": "^4.0.2",
4243
"tailwindcss": "^4.1.18",
4344
"vite": "^7.3.0"

pnpm-lock.yaml

Lines changed: 31 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod extract;
22
#[cfg(target_os = "macos")]
33
mod menu;
44
mod theme;
5+
mod trash;
56

67
use tauri::{generate_context, generate_handler, AppHandle, Builder, Manager, Window};
78
use tauri_plugin_store::StoreExt;
@@ -23,7 +24,7 @@ fn extract_archive(app: AppHandle, archive_path: String) -> Result<Vec<String>,
2324

2425
#[tauri::command]
2526
fn move_to_trash(paths: Vec<String>) -> Result<(), String> {
26-
trash::delete_all(&paths).map_err(|e| e.to_string())
27+
trash::move_to_trash_inner(paths)
2728
}
2829

2930
#[cfg_attr(mobile, tauri::mobile_entry_point)]
@@ -59,11 +60,9 @@ pub fn run() {
5960
// 在 Windows 下依次尝试应用云母、亚克力、模糊材质
6061
#[cfg(target_os = "windows")]
6162
{
62-
if apply_mica(&window, None).is_err() {
63-
if apply_acrylic(&window, None).is_err() {
64-
let _ = apply_blur(&window, None);
65-
}
66-
}
63+
let _ = apply_mica(&window, None)
64+
.or_else(|_| apply_acrylic(&window, None))
65+
.or_else(|_| apply_blur(&window, None));
6766
}
6867

6968
// 应用 macOS 模糊材质
@@ -78,6 +77,9 @@ pub fn run() {
7877
let _ = app.set_menu(menu);
7978
}
8079

80+
// 初始化完成后再显示窗口
81+
let _ = window.show();
82+
8183
Ok(())
8284
})
8385
.run(generate_context!())

src/src/trash.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use std::fs::remove_file;
2+
use trash::delete;
3+
4+
pub fn move_to_trash_inner(paths: Vec<String>) -> Result<(), String> {
5+
// 先尝试批量删除到回收站
6+
if trash::delete_all(&paths).is_ok() {
7+
return Ok(());
8+
}
9+
10+
// 已知使用 SMB 挂载的内容无法移动到回收站
11+
// 使用循环依次尝试放入回收站或者直接删除文件
12+
let errors: Vec<String> = paths
13+
.iter()
14+
.filter_map(|path| {
15+
delete(path)
16+
.or_else(|_| remove_file(path))
17+
.err()
18+
.map(|e| format!("{}: {}", path, e))
19+
})
20+
.collect();
21+
22+
if errors.is_empty() {
23+
Ok(())
24+
} else {
25+
Err(errors.join(", "))
26+
}
27+
}

src/tauri.conf.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"height": 680,
1919
"minWidth": 1000,
2020
"minHeight": 640,
21+
"visible": false,
2122
"dragDropEnabled": true,
2223
"transparent": true,
2324
"titleBarStyle": "Overlay",

ui/pages/subtitle.jsx

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ import { DropArea } from "@/components/drop"
1111
import { Table } from "@/components/table"
1212
import { Button } from "@/components/button"
1313
import { FileVideoIcon, FileTextIcon, FileArchiveIcon } from "@phosphor-icons/react"
14+
import { useSubtitleStore } from "@/store/subtitle"
1415

1516
const colKeys = ["video", "sc", "tc"]
1617

1718
export function SubtitleRename() {
1819
const [cell, setCell] = useState(null)
19-
const [fileList, setFileList] = useState({}) // 拖入时生成,便于排序,右键菜单也会操作此对象
2020
const [fileData, setFileData] = useState([]) // 展平为带路径的数组,用于重命名
2121
const [tableData, setTableData] = useState([]) // 上面数组的基础上移除了路径,只保留文件名
22-
const [archiveList, setArchiveList] = useState([]) // 拖入的压缩包路径
22+
23+
const { fileList, archiveList, setFileList, setArchiveList, clearAll } = useSubtitleStore()
2324

2425
const tableColumns = [
2526
{ key: "video", title: "视频文件" },
@@ -66,8 +67,8 @@ export function SubtitleRename() {
6667
if (addedCount === 0) {
6768
throw new Error(`${filterText},耗时 ${elapsedTime(startTime)}`)
6869
} else {
69-
setFileList(files)
70-
setArchiveList(archives)
70+
setFileList(() => files)
71+
setArchiveList(() => archives)
7172
return { message: `添加了 ${addedCount} 个文件${filterText && `,${filterText}`},耗时 ${elapsedTime(startTime)}` }
7273
}
7374
})()
@@ -77,7 +78,7 @@ export function SubtitleRename() {
7778
success: { title: (data) => data.message },
7879
error: { type: "warning", title: (err) => err.message }
7980
})
80-
}, [fileList, archiveList])
81+
}, [fileList, archiveList, setFileList, setArchiveList])
8182

8283
// 更改字幕类型
8384
const handleChangeType = useCallback(() => {
@@ -89,7 +90,7 @@ export function SubtitleRename() {
8990
[sourceKey]: (prev[sourceKey] || []).filter((_, i) => i !== cell.row),
9091
[targetKey]: [...(prev[targetKey] || []), value].sort(sortFiles)
9192
}))
92-
}, [cell, fileList])
93+
}, [cell, fileList, setFileList])
9394

9495
// 内容移动
9596
const handleMove = useCallback((offset) => {
@@ -100,7 +101,7 @@ export function SubtitleRename() {
100101
[key]: prev[key].map((v, i) => i === cell.row ? prev[key][targetRow] : i === targetRow ? prev[key][cell.row] : v
101102
)
102103
}))
103-
}, [cell])
104+
}, [cell, setFileList])
104105

105106
// 删除单个内容
106107
const handleDeleteItem = useCallback(() => {
@@ -109,7 +110,7 @@ export function SubtitleRename() {
109110
...prev,
110111
[key]: prev[key].filter((_, i) => i !== cell.row)
111112
}))
112-
}, [cell])
113+
}, [cell, setFileList])
113114

114115
// 删除整行
115116
const handleDeleteRow = useCallback(() => {
@@ -118,18 +119,12 @@ export function SubtitleRename() {
118119
Object.entries(prev).map(([key, arr]) => [key, arr.filter((_, i) => i !== cell.row)])
119120
)
120121
)
121-
}, [cell])
122-
123-
// 清空列表
124-
const handleClearList = () => {
125-
setFileList({})
126-
setArchiveList([])
127-
}
122+
}, [cell, setFileList])
128123

129124
// 重命名字幕
130125
const handleRename = async () => {
131126
const success = await renameSubtitles(fileData, archiveList)
132-
if (success) handleClearList()
127+
if (success) clearAll()
133128
}
134129

135130
return (
@@ -175,7 +170,7 @@ export function SubtitleRename() {
175170
</PageBlock>
176171

177172
<PageBlock className="items-center justify-end gap-3 p-4" last>
178-
<Button className="w-26" onClick={() => handleClearList()}>清空列表</Button>
173+
<Button className="w-26" onClick={() => clearAll()}>清空列表</Button>
179174
<Button variant="primary" className="w-26" onClick={handleRename}>重命名</Button>
180175
</PageBlock>
181176
</Page>

ui/store/subtitle.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { create } from "zustand"
2+
3+
export const useSubtitleStore = create((set) => ({
4+
fileList: {},
5+
archiveList: [],
6+
7+
setFileList: (updater) => set((state) => ({
8+
fileList: updater(state.fileList)
9+
})),
10+
setArchiveList: (updater) => set((state) => ({
11+
archiveList: updater(state.archiveList)
12+
})),
13+
14+
clearAll: () => set({
15+
fileList: {},
16+
archiveList: []
17+
})
18+
}))

ui/utils/rename.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,12 @@ export async function renameSubtitles(fileData, archiveList) {
6161
}
6262

6363
for (const path of filePaths) {
64-
// 重命名字幕
65-
if (moveSub === "copy") {
66-
await copyFile(path.old, path.new)
67-
// 若在同一目录复制,需要删除目录下的原文件
68-
if (await dirname(path.old) === await dirname(path.new)) {
69-
pathsToTrash.push(path.old)
70-
}
71-
} else {
72-
await rename(path.old, path.new)
64+
// 使用复制操作来重命名
65+
await copyFile(path.old, path.new)
66+
67+
// 非复制模式,或复制模式但字幕在同文件夹时,删除旧字幕
68+
if (moveSub !== "copy" || dirname(path.old) === dirname(path.new)) {
69+
pathsToTrash.push(path.old)
7370
}
7471

7572
// 检测编码,非 UTF-8 则转换

0 commit comments

Comments
 (0)