@huyooo/file-explorer-frontend-react 0.4.18 → 0.4.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +0 -1
- package/dist/index.js +1 -3456
- package/package.json +4 -4
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/src/components/Breadcrumb.css +0 -61
- package/src/components/Breadcrumb.tsx +0 -38
- package/src/components/CompressDialog.css +0 -267
- package/src/components/CompressDialog.tsx +0 -222
- package/src/components/ContextMenu.css +0 -155
- package/src/components/ContextMenu.tsx +0 -375
- package/src/components/FileGrid.css +0 -239
- package/src/components/FileGrid.tsx +0 -278
- package/src/components/FileIcon.css +0 -41
- package/src/components/FileIcon.tsx +0 -86
- package/src/components/FileInfoDialog.css +0 -214
- package/src/components/FileInfoDialog.tsx +0 -202
- package/src/components/FileList.css +0 -169
- package/src/components/FileList.tsx +0 -228
- package/src/components/FileListView.css +0 -36
- package/src/components/FileListView.tsx +0 -355
- package/src/components/FileSidebar.css +0 -94
- package/src/components/FileSidebar.tsx +0 -66
- package/src/components/ProgressDialog.css +0 -211
- package/src/components/ProgressDialog.tsx +0 -183
- package/src/components/SortIndicator.css +0 -7
- package/src/components/SortIndicator.tsx +0 -19
- package/src/components/StatusBar.css +0 -20
- package/src/components/StatusBar.tsx +0 -21
- package/src/components/Toolbar.css +0 -150
- package/src/components/Toolbar.tsx +0 -127
- package/src/components/Window.css +0 -246
- package/src/components/Window.tsx +0 -335
- package/src/hooks/useApplicationIcon.ts +0 -80
- package/src/hooks/useDragAndDrop.ts +0 -104
- package/src/hooks/useMediaPlayer.ts +0 -164
- package/src/hooks/useSelection.ts +0 -112
- package/src/hooks/useWindowDrag.ts +0 -60
- package/src/hooks/useWindowResize.ts +0 -126
- package/src/index.css +0 -184
- package/src/index.ts +0 -37
- package/src/types/index.ts +0 -274
- package/src/utils/fileTypeIcon.ts +0 -309
- package/src/utils/folderTypeIcon.ts +0 -132
package/dist/index.js
CHANGED
|
@@ -1,3456 +1 @@
|
|
|
1
|
-
// src/types/index.ts
|
|
2
|
-
var FileType = {
|
|
3
|
-
FOLDER: "folder",
|
|
4
|
-
FILE: "file",
|
|
5
|
-
IMAGE: "image",
|
|
6
|
-
VIDEO: "video",
|
|
7
|
-
MUSIC: "music",
|
|
8
|
-
DOCUMENT: "document",
|
|
9
|
-
CODE: "code",
|
|
10
|
-
TEXT: "text",
|
|
11
|
-
PDF: "pdf",
|
|
12
|
-
ARCHIVE: "archive",
|
|
13
|
-
APPLICATION: "application",
|
|
14
|
-
UNKNOWN: "unknown"
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// src/components/FileListView.tsx
|
|
18
|
-
import { useState, useCallback, useImperativeHandle, forwardRef } from "react";
|
|
19
|
-
import { Icon as Icon3 } from "@iconify/react";
|
|
20
|
-
|
|
21
|
-
// src/components/FileGrid.tsx
|
|
22
|
-
import { useRef, useMemo as useMemo2 } from "react";
|
|
23
|
-
|
|
24
|
-
// src/components/FileIcon.tsx
|
|
25
|
-
import { useMemo } from "react";
|
|
26
|
-
import { Icon } from "@iconify/react";
|
|
27
|
-
|
|
28
|
-
// src/utils/fileTypeIcon.ts
|
|
29
|
-
var KNOWN_TYPES = /* @__PURE__ */ new Set([
|
|
30
|
-
"3d",
|
|
31
|
-
"actionscript",
|
|
32
|
-
"ada",
|
|
33
|
-
"adobe-illustrator",
|
|
34
|
-
"adobe-photoshop",
|
|
35
|
-
"android",
|
|
36
|
-
"angular",
|
|
37
|
-
"applescript",
|
|
38
|
-
"arduino",
|
|
39
|
-
"asciidoc",
|
|
40
|
-
"assembly",
|
|
41
|
-
"astro",
|
|
42
|
-
"audio",
|
|
43
|
-
"aurelia",
|
|
44
|
-
"babel",
|
|
45
|
-
"ballerina",
|
|
46
|
-
"bazel",
|
|
47
|
-
"biome",
|
|
48
|
-
"blender",
|
|
49
|
-
"bower",
|
|
50
|
-
"bun",
|
|
51
|
-
"c",
|
|
52
|
-
"cabal",
|
|
53
|
-
"caddy",
|
|
54
|
-
"cake",
|
|
55
|
-
"certificate",
|
|
56
|
-
"changelog",
|
|
57
|
-
"circleci",
|
|
58
|
-
"claude",
|
|
59
|
-
"clojure",
|
|
60
|
-
"cmake",
|
|
61
|
-
"cobol",
|
|
62
|
-
"coffee",
|
|
63
|
-
"command",
|
|
64
|
-
"conduct",
|
|
65
|
-
"contributing",
|
|
66
|
-
"controller",
|
|
67
|
-
"copilot",
|
|
68
|
-
"cpp",
|
|
69
|
-
"crystal",
|
|
70
|
-
"csharp",
|
|
71
|
-
"css",
|
|
72
|
-
"css-map",
|
|
73
|
-
"cucumber",
|
|
74
|
-
"cuda",
|
|
75
|
-
"cursor",
|
|
76
|
-
"cypress",
|
|
77
|
-
"d",
|
|
78
|
-
"dart",
|
|
79
|
-
"database",
|
|
80
|
-
"deno",
|
|
81
|
-
"dependabot",
|
|
82
|
-
"diff",
|
|
83
|
-
"django",
|
|
84
|
-
"docker",
|
|
85
|
-
"document",
|
|
86
|
-
"drawio",
|
|
87
|
-
"drizzle",
|
|
88
|
-
"editorconfig",
|
|
89
|
-
"ejs",
|
|
90
|
-
"elixir",
|
|
91
|
-
"elm",
|
|
92
|
-
"email",
|
|
93
|
-
"ember",
|
|
94
|
-
"epub",
|
|
95
|
-
"erlang",
|
|
96
|
-
"esbuild",
|
|
97
|
-
"eslint",
|
|
98
|
-
"excalidraw",
|
|
99
|
-
"exe",
|
|
100
|
-
"favicon",
|
|
101
|
-
"figma",
|
|
102
|
-
"firebase",
|
|
103
|
-
"flash",
|
|
104
|
-
"flow",
|
|
105
|
-
"font",
|
|
106
|
-
"forth",
|
|
107
|
-
"fortran",
|
|
108
|
-
"freemarker",
|
|
109
|
-
"fsharp",
|
|
110
|
-
"gamemaker",
|
|
111
|
-
"gatsby",
|
|
112
|
-
"gcp",
|
|
113
|
-
"gemfile",
|
|
114
|
-
"gemini",
|
|
115
|
-
"git",
|
|
116
|
-
"gitlab",
|
|
117
|
-
"gleam",
|
|
118
|
-
"go",
|
|
119
|
-
"go-mod",
|
|
120
|
-
"godot",
|
|
121
|
-
"gradle",
|
|
122
|
-
"graphql",
|
|
123
|
-
"groovy",
|
|
124
|
-
"grunt",
|
|
125
|
-
"gulp",
|
|
126
|
-
"h",
|
|
127
|
-
"haml",
|
|
128
|
-
"handlebars",
|
|
129
|
-
"hardhat",
|
|
130
|
-
"haskell",
|
|
131
|
-
"haxe",
|
|
132
|
-
"hcl",
|
|
133
|
-
"helm",
|
|
134
|
-
"hjson",
|
|
135
|
-
"hosts",
|
|
136
|
-
"hpp",
|
|
137
|
-
"html",
|
|
138
|
-
"http",
|
|
139
|
-
"husky",
|
|
140
|
-
"i18n",
|
|
141
|
-
"image",
|
|
142
|
-
"imba",
|
|
143
|
-
"ionic",
|
|
144
|
-
"jar",
|
|
145
|
-
"java",
|
|
146
|
-
"javaclass",
|
|
147
|
-
"javascript",
|
|
148
|
-
"javascript-map",
|
|
149
|
-
"jenkins",
|
|
150
|
-
"jest",
|
|
151
|
-
"jinja",
|
|
152
|
-
"jsconfig",
|
|
153
|
-
"json",
|
|
154
|
-
"julia",
|
|
155
|
-
"jupyter",
|
|
156
|
-
"just",
|
|
157
|
-
"karma",
|
|
158
|
-
"key",
|
|
159
|
-
"kotlin",
|
|
160
|
-
"kubernetes",
|
|
161
|
-
"laravel",
|
|
162
|
-
"lean",
|
|
163
|
-
"lefthook",
|
|
164
|
-
"lerna",
|
|
165
|
-
"less",
|
|
166
|
-
"lib",
|
|
167
|
-
"license",
|
|
168
|
-
"lighthouse",
|
|
169
|
-
"liquid",
|
|
170
|
-
"lisp",
|
|
171
|
-
"livescript",
|
|
172
|
-
"lock",
|
|
173
|
-
"log",
|
|
174
|
-
"lua",
|
|
175
|
-
"luau",
|
|
176
|
-
"makefile",
|
|
177
|
-
"markdown",
|
|
178
|
-
"markdownlint",
|
|
179
|
-
"matlab",
|
|
180
|
-
"maven",
|
|
181
|
-
"mdx",
|
|
182
|
-
"mercurial",
|
|
183
|
-
"mermaid",
|
|
184
|
-
"meson",
|
|
185
|
-
"minecraft",
|
|
186
|
-
"mjml",
|
|
187
|
-
"mocha",
|
|
188
|
-
"mojo",
|
|
189
|
-
"nest",
|
|
190
|
-
"netlify",
|
|
191
|
-
"next",
|
|
192
|
-
"nginx",
|
|
193
|
-
"nim",
|
|
194
|
-
"nix",
|
|
195
|
-
"nodejs",
|
|
196
|
-
"nodemon",
|
|
197
|
-
"npm",
|
|
198
|
-
"nuget",
|
|
199
|
-
"nunjucks",
|
|
200
|
-
"nuxt",
|
|
201
|
-
"nx",
|
|
202
|
-
"objective-c",
|
|
203
|
-
"objective-cpp",
|
|
204
|
-
"ocaml",
|
|
205
|
-
"odin",
|
|
206
|
-
"openapi",
|
|
207
|
-
"opentofu",
|
|
208
|
-
"pascal",
|
|
209
|
-
"pdf",
|
|
210
|
-
"perl",
|
|
211
|
-
"php",
|
|
212
|
-
"phpstan",
|
|
213
|
-
"phpunit",
|
|
214
|
-
"pipeline",
|
|
215
|
-
"playwright",
|
|
216
|
-
"pnpm",
|
|
217
|
-
"postcss",
|
|
218
|
-
"powerpoint",
|
|
219
|
-
"powershell",
|
|
220
|
-
"prettier",
|
|
221
|
-
"prisma",
|
|
222
|
-
"processing",
|
|
223
|
-
"prolog",
|
|
224
|
-
"proto",
|
|
225
|
-
"pug",
|
|
226
|
-
"puppet",
|
|
227
|
-
"purescript",
|
|
228
|
-
"python",
|
|
229
|
-
"pytorch",
|
|
230
|
-
"quasar",
|
|
231
|
-
"r",
|
|
232
|
-
"racket",
|
|
233
|
-
"razor",
|
|
234
|
-
"react",
|
|
235
|
-
"react-ts",
|
|
236
|
-
"readme",
|
|
237
|
-
"reason",
|
|
238
|
-
"remark",
|
|
239
|
-
"remix",
|
|
240
|
-
"renovate",
|
|
241
|
-
"replit",
|
|
242
|
-
"rescript",
|
|
243
|
-
"riot",
|
|
244
|
-
"roadmap",
|
|
245
|
-
"robot",
|
|
246
|
-
"robots",
|
|
247
|
-
"rollup",
|
|
248
|
-
"routing",
|
|
249
|
-
"rspec",
|
|
250
|
-
"rubocop",
|
|
251
|
-
"ruby",
|
|
252
|
-
"ruff",
|
|
253
|
-
"rust",
|
|
254
|
-
"salt",
|
|
255
|
-
"san",
|
|
256
|
-
"sas",
|
|
257
|
-
"sass",
|
|
258
|
-
"sbt",
|
|
259
|
-
"scala",
|
|
260
|
-
"scheme",
|
|
261
|
-
"search",
|
|
262
|
-
"sentry",
|
|
263
|
-
"sequelize",
|
|
264
|
-
"serverless",
|
|
265
|
-
"settings",
|
|
266
|
-
"shader",
|
|
267
|
-
"shellcheck",
|
|
268
|
-
"sketch",
|
|
269
|
-
"slim",
|
|
270
|
-
"slint",
|
|
271
|
-
"smarty",
|
|
272
|
-
"snakemake",
|
|
273
|
-
"snapcraft",
|
|
274
|
-
"snyk",
|
|
275
|
-
"solidity",
|
|
276
|
-
"spwn",
|
|
277
|
-
"stackblitz",
|
|
278
|
-
"stan",
|
|
279
|
-
"stencil",
|
|
280
|
-
"storybook",
|
|
281
|
-
"stryker",
|
|
282
|
-
"stylelint",
|
|
283
|
-
"stylus",
|
|
284
|
-
"sublime",
|
|
285
|
-
"subtitles",
|
|
286
|
-
"supabase",
|
|
287
|
-
"svelte",
|
|
288
|
-
"svg",
|
|
289
|
-
"svgo",
|
|
290
|
-
"swagger",
|
|
291
|
-
"swc",
|
|
292
|
-
"swift",
|
|
293
|
-
"tailwindcss",
|
|
294
|
-
"taskfile",
|
|
295
|
-
"tauri",
|
|
296
|
-
"tcl",
|
|
297
|
-
"teal",
|
|
298
|
-
"templ",
|
|
299
|
-
"template",
|
|
300
|
-
"terraform",
|
|
301
|
-
"test-js",
|
|
302
|
-
"test-jsx",
|
|
303
|
-
"test-ts",
|
|
304
|
-
"tex",
|
|
305
|
-
"todo",
|
|
306
|
-
"toml",
|
|
307
|
-
"travis",
|
|
308
|
-
"tree",
|
|
309
|
-
"tsconfig",
|
|
310
|
-
"tsdoc",
|
|
311
|
-
"turborepo",
|
|
312
|
-
"twig",
|
|
313
|
-
"typescript",
|
|
314
|
-
"typescript-def",
|
|
315
|
-
"unity",
|
|
316
|
-
"unocss",
|
|
317
|
-
"vagrant",
|
|
318
|
-
"vanilla-extract",
|
|
319
|
-
"vercel",
|
|
320
|
-
"verilog",
|
|
321
|
-
"video",
|
|
322
|
-
"vim",
|
|
323
|
-
"vite",
|
|
324
|
-
"vitest",
|
|
325
|
-
"vlang",
|
|
326
|
-
"vscode",
|
|
327
|
-
"vue",
|
|
328
|
-
"vue-config",
|
|
329
|
-
"wakatime",
|
|
330
|
-
"wallaby",
|
|
331
|
-
"webassembly",
|
|
332
|
-
"webhint",
|
|
333
|
-
"webpack",
|
|
334
|
-
"windicss",
|
|
335
|
-
"word",
|
|
336
|
-
"wrangler",
|
|
337
|
-
"wxt",
|
|
338
|
-
"xaml",
|
|
339
|
-
"xmake",
|
|
340
|
-
"xml",
|
|
341
|
-
"yaml",
|
|
342
|
-
"yarn",
|
|
343
|
-
"zig",
|
|
344
|
-
"zip"
|
|
345
|
-
]);
|
|
346
|
-
var EXT_MAP = {
|
|
347
|
-
// JavaScript/TypeScript
|
|
348
|
-
"js": "javascript",
|
|
349
|
-
"mjs": "javascript",
|
|
350
|
-
"cjs": "javascript",
|
|
351
|
-
"jsx": "react",
|
|
352
|
-
"ts": "typescript",
|
|
353
|
-
"mts": "typescript",
|
|
354
|
-
"cts": "typescript",
|
|
355
|
-
"tsx": "react-ts",
|
|
356
|
-
// 前端框架
|
|
357
|
-
"vue": "vue",
|
|
358
|
-
"svelte": "svelte",
|
|
359
|
-
"astro": "astro",
|
|
360
|
-
// 后端语言
|
|
361
|
-
"py": "python",
|
|
362
|
-
"pyw": "python",
|
|
363
|
-
"pyi": "python",
|
|
364
|
-
"pyc": "python",
|
|
365
|
-
"java": "java",
|
|
366
|
-
"class": "javaclass",
|
|
367
|
-
"jar": "jar",
|
|
368
|
-
"c": "c",
|
|
369
|
-
"h": "h",
|
|
370
|
-
"cpp": "cpp",
|
|
371
|
-
"cc": "cpp",
|
|
372
|
-
"cxx": "cpp",
|
|
373
|
-
"hpp": "hpp",
|
|
374
|
-
"hh": "hpp",
|
|
375
|
-
"hxx": "hpp",
|
|
376
|
-
"cs": "csharp",
|
|
377
|
-
"csx": "csharp",
|
|
378
|
-
"go": "go",
|
|
379
|
-
"rs": "rust",
|
|
380
|
-
"php": "php",
|
|
381
|
-
"phtml": "php",
|
|
382
|
-
"rb": "ruby",
|
|
383
|
-
"rake": "ruby",
|
|
384
|
-
"swift": "swift",
|
|
385
|
-
"kt": "kotlin",
|
|
386
|
-
"kts": "kotlin",
|
|
387
|
-
"scala": "scala",
|
|
388
|
-
"dart": "dart",
|
|
389
|
-
"lua": "lua",
|
|
390
|
-
"luau": "luau",
|
|
391
|
-
"r": "r",
|
|
392
|
-
"rdata": "r",
|
|
393
|
-
"rds": "r",
|
|
394
|
-
"pl": "perl",
|
|
395
|
-
"pm": "perl",
|
|
396
|
-
"sh": "command",
|
|
397
|
-
"bash": "command",
|
|
398
|
-
"zsh": "command",
|
|
399
|
-
"fish": "command",
|
|
400
|
-
"ps1": "powershell",
|
|
401
|
-
"psm1": "powershell",
|
|
402
|
-
"psd1": "powershell",
|
|
403
|
-
"bat": "command",
|
|
404
|
-
"cmd": "command",
|
|
405
|
-
// 样式
|
|
406
|
-
"css": "css",
|
|
407
|
-
"scss": "sass",
|
|
408
|
-
"sass": "sass",
|
|
409
|
-
"less": "less",
|
|
410
|
-
"styl": "stylus",
|
|
411
|
-
// 标记/配置
|
|
412
|
-
"html": "html",
|
|
413
|
-
"htm": "html",
|
|
414
|
-
"xhtml": "html",
|
|
415
|
-
"xml": "xml",
|
|
416
|
-
"xsl": "xml",
|
|
417
|
-
"xslt": "xml",
|
|
418
|
-
"json": "json",
|
|
419
|
-
"jsonc": "json",
|
|
420
|
-
"json5": "json",
|
|
421
|
-
"yaml": "yaml",
|
|
422
|
-
"yml": "yaml",
|
|
423
|
-
"toml": "toml",
|
|
424
|
-
"ini": "settings",
|
|
425
|
-
"conf": "settings",
|
|
426
|
-
"config": "settings",
|
|
427
|
-
// 文档
|
|
428
|
-
"md": "markdown",
|
|
429
|
-
"markdown": "markdown",
|
|
430
|
-
"mdx": "mdx",
|
|
431
|
-
"txt": "document",
|
|
432
|
-
"pdf": "pdf",
|
|
433
|
-
"doc": "word",
|
|
434
|
-
"docx": "word",
|
|
435
|
-
"dot": "word",
|
|
436
|
-
"dotx": "word",
|
|
437
|
-
"odt": "word",
|
|
438
|
-
"xls": "table",
|
|
439
|
-
"xlsx": "table",
|
|
440
|
-
"xlsm": "table",
|
|
441
|
-
"ods": "table",
|
|
442
|
-
"csv": "table",
|
|
443
|
-
"ppt": "powerpoint",
|
|
444
|
-
"pptx": "powerpoint",
|
|
445
|
-
"odp": "powerpoint",
|
|
446
|
-
// 图片
|
|
447
|
-
"jpg": "image",
|
|
448
|
-
"jpeg": "image",
|
|
449
|
-
"png": "image",
|
|
450
|
-
"gif": "image",
|
|
451
|
-
"webp": "image",
|
|
452
|
-
"ico": "image",
|
|
453
|
-
"bmp": "image",
|
|
454
|
-
"tiff": "image",
|
|
455
|
-
"tif": "image",
|
|
456
|
-
"heic": "image",
|
|
457
|
-
"heif": "image",
|
|
458
|
-
"svg": "svg",
|
|
459
|
-
"psd": "adobe-photoshop",
|
|
460
|
-
"ai": "adobe-illustrator",
|
|
461
|
-
"sketch": "sketch",
|
|
462
|
-
"fig": "figma",
|
|
463
|
-
"figma": "figma",
|
|
464
|
-
// 视频/音频
|
|
465
|
-
"mp4": "video",
|
|
466
|
-
"mov": "video",
|
|
467
|
-
"avi": "video",
|
|
468
|
-
"mkv": "video",
|
|
469
|
-
"webm": "video",
|
|
470
|
-
"flv": "video",
|
|
471
|
-
"wmv": "video",
|
|
472
|
-
"m4v": "video",
|
|
473
|
-
"3gp": "video",
|
|
474
|
-
"mpeg": "video",
|
|
475
|
-
"mpg": "video",
|
|
476
|
-
"mp3": "audio",
|
|
477
|
-
"wav": "audio",
|
|
478
|
-
"flac": "audio",
|
|
479
|
-
"aac": "audio",
|
|
480
|
-
"ogg": "audio",
|
|
481
|
-
"wma": "audio",
|
|
482
|
-
"m4a": "audio",
|
|
483
|
-
"aiff": "audio",
|
|
484
|
-
// 压缩
|
|
485
|
-
"zip": "zip",
|
|
486
|
-
"rar": "zip",
|
|
487
|
-
"7z": "zip",
|
|
488
|
-
"tar": "zip",
|
|
489
|
-
"gz": "zip",
|
|
490
|
-
"bz2": "zip",
|
|
491
|
-
"xz": "zip",
|
|
492
|
-
"tgz": "zip",
|
|
493
|
-
"tbz2": "zip",
|
|
494
|
-
// 数据库
|
|
495
|
-
"sql": "database",
|
|
496
|
-
"db": "database",
|
|
497
|
-
"sqlite": "database",
|
|
498
|
-
"sqlite3": "database",
|
|
499
|
-
"prisma": "prisma",
|
|
500
|
-
// 其他
|
|
501
|
-
"log": "log",
|
|
502
|
-
"lock": "lock",
|
|
503
|
-
"env": "settings",
|
|
504
|
-
"graphql": "graphql",
|
|
505
|
-
"gql": "graphql",
|
|
506
|
-
"proto": "proto",
|
|
507
|
-
"wasm": "webassembly",
|
|
508
|
-
"zig": "zig",
|
|
509
|
-
"nim": "nim",
|
|
510
|
-
"nix": "nix",
|
|
511
|
-
"hcl": "hcl",
|
|
512
|
-
"tf": "terraform",
|
|
513
|
-
"sol": "solidity",
|
|
514
|
-
"ex": "elixir",
|
|
515
|
-
"exs": "elixir",
|
|
516
|
-
"erl": "erlang",
|
|
517
|
-
"hrl": "erlang",
|
|
518
|
-
"hs": "haskell",
|
|
519
|
-
"lhs": "haskell",
|
|
520
|
-
"ml": "ocaml",
|
|
521
|
-
"mli": "ocaml",
|
|
522
|
-
"clj": "clojure",
|
|
523
|
-
"cljs": "clojure",
|
|
524
|
-
"cljc": "clojure",
|
|
525
|
-
"lisp": "lisp",
|
|
526
|
-
"lsp": "lisp",
|
|
527
|
-
"el": "lisp",
|
|
528
|
-
"vim": "vim",
|
|
529
|
-
"dockerfile": "docker"
|
|
530
|
-
};
|
|
531
|
-
var SPECIAL_FILES = {
|
|
532
|
-
// Git
|
|
533
|
-
".gitignore": "git",
|
|
534
|
-
".gitattributes": "git",
|
|
535
|
-
".gitmodules": "git",
|
|
536
|
-
".gitkeep": "git",
|
|
537
|
-
// 环境
|
|
538
|
-
".env": "settings",
|
|
539
|
-
".env.local": "settings",
|
|
540
|
-
".env.development": "settings",
|
|
541
|
-
".env.production": "settings",
|
|
542
|
-
".env.test": "settings",
|
|
543
|
-
".env.example": "settings",
|
|
544
|
-
// Node/包管理
|
|
545
|
-
"package.json": "nodejs",
|
|
546
|
-
"package-lock.json": "npm",
|
|
547
|
-
"yarn.lock": "yarn",
|
|
548
|
-
".yarnrc": "yarn",
|
|
549
|
-
".yarnrc.yml": "yarn",
|
|
550
|
-
"pnpm-lock.yaml": "pnpm",
|
|
551
|
-
".pnpmfile.cjs": "pnpm",
|
|
552
|
-
"bun.lockb": "bun",
|
|
553
|
-
"bunfig.toml": "bun",
|
|
554
|
-
// Python
|
|
555
|
-
"requirements.txt": "python",
|
|
556
|
-
"pipfile": "python",
|
|
557
|
-
"pipfile.lock": "python",
|
|
558
|
-
"pyproject.toml": "python",
|
|
559
|
-
"poetry.lock": "python",
|
|
560
|
-
"setup.py": "python",
|
|
561
|
-
// Rust
|
|
562
|
-
"cargo.toml": "rust",
|
|
563
|
-
"cargo.lock": "rust",
|
|
564
|
-
// Go
|
|
565
|
-
"go.mod": "go-mod",
|
|
566
|
-
"go.sum": "go-mod",
|
|
567
|
-
"go.work": "go-mod",
|
|
568
|
-
// PHP
|
|
569
|
-
"composer.json": "php",
|
|
570
|
-
"composer.lock": "php",
|
|
571
|
-
// Ruby
|
|
572
|
-
"gemfile": "gemfile",
|
|
573
|
-
"gemfile.lock": "gemfile",
|
|
574
|
-
"rakefile": "ruby",
|
|
575
|
-
// Docker
|
|
576
|
-
"dockerfile": "docker",
|
|
577
|
-
"docker-compose.yml": "docker",
|
|
578
|
-
"docker-compose.yaml": "docker",
|
|
579
|
-
".dockerignore": "docker",
|
|
580
|
-
// 构建工具
|
|
581
|
-
"makefile": "makefile",
|
|
582
|
-
"gnumakefile": "makefile",
|
|
583
|
-
"cmakelists.txt": "cmake",
|
|
584
|
-
"build.gradle": "gradle",
|
|
585
|
-
"build.gradle.kts": "gradle",
|
|
586
|
-
"settings.gradle": "gradle",
|
|
587
|
-
"pom.xml": "maven",
|
|
588
|
-
// 配置
|
|
589
|
-
"tsconfig.json": "tsconfig",
|
|
590
|
-
"jsconfig.json": "jsconfig",
|
|
591
|
-
".prettierrc": "prettier",
|
|
592
|
-
".prettierrc.json": "prettier",
|
|
593
|
-
".prettierrc.js": "prettier",
|
|
594
|
-
".prettierignore": "prettier",
|
|
595
|
-
"prettier.config.js": "prettier",
|
|
596
|
-
".eslintrc": "eslint",
|
|
597
|
-
".eslintrc.json": "eslint",
|
|
598
|
-
".eslintrc.js": "eslint",
|
|
599
|
-
".eslintignore": "eslint",
|
|
600
|
-
"eslint.config.js": "eslint",
|
|
601
|
-
"eslint.config.mjs": "eslint",
|
|
602
|
-
".editorconfig": "editorconfig",
|
|
603
|
-
"vite.config.ts": "vite",
|
|
604
|
-
"vite.config.js": "vite",
|
|
605
|
-
"webpack.config.js": "webpack",
|
|
606
|
-
"webpack.config.ts": "webpack",
|
|
607
|
-
"rollup.config.js": "rollup",
|
|
608
|
-
"rollup.config.ts": "rollup",
|
|
609
|
-
"esbuild.config.js": "esbuild",
|
|
610
|
-
"tailwind.config.js": "tailwindcss",
|
|
611
|
-
"tailwind.config.ts": "tailwindcss",
|
|
612
|
-
"postcss.config.js": "postcss",
|
|
613
|
-
"postcss.config.cjs": "postcss",
|
|
614
|
-
"babel.config.js": "babel",
|
|
615
|
-
".babelrc": "babel",
|
|
616
|
-
"jest.config.js": "jest",
|
|
617
|
-
"jest.config.ts": "jest",
|
|
618
|
-
"vitest.config.ts": "vitest",
|
|
619
|
-
"vitest.config.js": "vitest",
|
|
620
|
-
"playwright.config.ts": "playwright",
|
|
621
|
-
"playwright.config.js": "playwright",
|
|
622
|
-
"cypress.config.ts": "cypress",
|
|
623
|
-
"cypress.config.js": "cypress",
|
|
624
|
-
".swcrc": "swc",
|
|
625
|
-
"swc.config.js": "swc",
|
|
626
|
-
"turbo.json": "turborepo",
|
|
627
|
-
"nx.json": "nx",
|
|
628
|
-
"biome.json": "biome",
|
|
629
|
-
".nvmrc": "nodejs",
|
|
630
|
-
".node-version": "nodejs",
|
|
631
|
-
// 框架配置
|
|
632
|
-
"nuxt.config.ts": "nuxt",
|
|
633
|
-
"nuxt.config.js": "nuxt",
|
|
634
|
-
"next.config.js": "next",
|
|
635
|
-
"next.config.mjs": "next",
|
|
636
|
-
"next.config.ts": "next",
|
|
637
|
-
"svelte.config.js": "svelte",
|
|
638
|
-
"astro.config.mjs": "astro",
|
|
639
|
-
"astro.config.ts": "astro",
|
|
640
|
-
"vue.config.js": "vue-config",
|
|
641
|
-
"angular.json": "angular",
|
|
642
|
-
"nest-cli.json": "nest",
|
|
643
|
-
"tauri.conf.json": "tauri",
|
|
644
|
-
// CI/CD
|
|
645
|
-
".travis.yml": "travis",
|
|
646
|
-
".gitlab-ci.yml": "gitlab",
|
|
647
|
-
"vercel.json": "vercel",
|
|
648
|
-
"netlify.toml": "netlify",
|
|
649
|
-
// 其他
|
|
650
|
-
"license": "license",
|
|
651
|
-
"license.md": "license",
|
|
652
|
-
"license.txt": "license",
|
|
653
|
-
"readme": "readme",
|
|
654
|
-
"readme.md": "readme",
|
|
655
|
-
"readme.txt": "readme",
|
|
656
|
-
"changelog": "changelog",
|
|
657
|
-
"changelog.md": "changelog",
|
|
658
|
-
".npmrc": "npm",
|
|
659
|
-
".npmignore": "npm",
|
|
660
|
-
"robots.txt": "robots",
|
|
661
|
-
".htaccess": "nginx",
|
|
662
|
-
"vagrantfile": "vagrant",
|
|
663
|
-
".stylelintrc": "stylelint",
|
|
664
|
-
".stylelintrc.json": "stylelint",
|
|
665
|
-
"nodemon.json": "nodemon",
|
|
666
|
-
".huskyrc": "husky",
|
|
667
|
-
"renovate.json": "renovate",
|
|
668
|
-
".snyk": "snyk",
|
|
669
|
-
"deno.json": "deno",
|
|
670
|
-
"deno.jsonc": "deno"
|
|
671
|
-
};
|
|
672
|
-
function getFileTypeIcon(fileName, fallbackType) {
|
|
673
|
-
const lowerName = fileName.toLowerCase();
|
|
674
|
-
if (SPECIAL_FILES[lowerName]) {
|
|
675
|
-
const type = SPECIAL_FILES[lowerName];
|
|
676
|
-
if (KNOWN_TYPES.has(type)) {
|
|
677
|
-
return `material-icon-theme:${type}`;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
if (lowerName === "dockerfile" || lowerName.startsWith("dockerfile.")) {
|
|
681
|
-
return "material-icon-theme:docker";
|
|
682
|
-
}
|
|
683
|
-
if (lowerName === ".env" || lowerName.startsWith(".env.")) {
|
|
684
|
-
return "material-icon-theme:settings";
|
|
685
|
-
}
|
|
686
|
-
const lastDotIndex = fileName.lastIndexOf(".");
|
|
687
|
-
const ext = lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1).toLowerCase() : "";
|
|
688
|
-
if (ext === "ts" || ext === "js") {
|
|
689
|
-
const baseName = fileName.substring(0, lastDotIndex).toLowerCase();
|
|
690
|
-
if (baseName.endsWith(".d")) {
|
|
691
|
-
return "material-icon-theme:typescript-def";
|
|
692
|
-
}
|
|
693
|
-
if (baseName.endsWith(".test") || baseName.endsWith(".spec")) {
|
|
694
|
-
return ext === "ts" ? "material-icon-theme:test-ts" : "material-icon-theme:test-js";
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
if (ext === "jsx" || ext === "tsx") {
|
|
698
|
-
const baseName = fileName.substring(0, lastDotIndex).toLowerCase();
|
|
699
|
-
if (baseName.endsWith(".test") || baseName.endsWith(".spec")) {
|
|
700
|
-
return ext === "tsx" ? "material-icon-theme:test-ts" : "material-icon-theme:test-jsx";
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
if (ext && EXT_MAP[ext]) {
|
|
704
|
-
const type = EXT_MAP[ext];
|
|
705
|
-
if (KNOWN_TYPES.has(type)) {
|
|
706
|
-
return `material-icon-theme:${type}`;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
if (fallbackType) {
|
|
710
|
-
return getFallbackIcon(fallbackType);
|
|
711
|
-
}
|
|
712
|
-
return "material-icon-theme:document";
|
|
713
|
-
}
|
|
714
|
-
function getFallbackIcon(type) {
|
|
715
|
-
switch (type) {
|
|
716
|
-
case FileType.IMAGE:
|
|
717
|
-
return "material-icon-theme:image";
|
|
718
|
-
case FileType.VIDEO:
|
|
719
|
-
return "material-icon-theme:video";
|
|
720
|
-
case FileType.MUSIC:
|
|
721
|
-
return "material-icon-theme:audio";
|
|
722
|
-
case FileType.CODE:
|
|
723
|
-
return "material-icon-theme:javascript";
|
|
724
|
-
case FileType.TEXT:
|
|
725
|
-
return "material-icon-theme:document";
|
|
726
|
-
case FileType.DOCUMENT:
|
|
727
|
-
return "material-icon-theme:word";
|
|
728
|
-
case FileType.PDF:
|
|
729
|
-
return "material-icon-theme:pdf";
|
|
730
|
-
case FileType.ARCHIVE:
|
|
731
|
-
return "material-icon-theme:zip";
|
|
732
|
-
case FileType.APPLICATION:
|
|
733
|
-
return "material-icon-theme:exe";
|
|
734
|
-
default:
|
|
735
|
-
return "material-icon-theme:document";
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// src/utils/folderTypeIcon.ts
|
|
740
|
-
var KNOWN_TYPES2 = /* @__PURE__ */ new Set([
|
|
741
|
-
"admin",
|
|
742
|
-
"android",
|
|
743
|
-
"angular",
|
|
744
|
-
"animation",
|
|
745
|
-
"ansible",
|
|
746
|
-
"api",
|
|
747
|
-
"apollo",
|
|
748
|
-
"app",
|
|
749
|
-
"archive",
|
|
750
|
-
"astro",
|
|
751
|
-
"atom",
|
|
752
|
-
"attachment",
|
|
753
|
-
"audio",
|
|
754
|
-
"aurelia",
|
|
755
|
-
"aws",
|
|
756
|
-
"azure-pipelines",
|
|
757
|
-
"backup",
|
|
758
|
-
"base",
|
|
759
|
-
"batch",
|
|
760
|
-
"benchmark",
|
|
761
|
-
"bibliography",
|
|
762
|
-
"bicep",
|
|
763
|
-
"blender",
|
|
764
|
-
"bloc",
|
|
765
|
-
"bower",
|
|
766
|
-
"buildkite",
|
|
767
|
-
"cart",
|
|
768
|
-
"changesets",
|
|
769
|
-
"ci",
|
|
770
|
-
"circleci",
|
|
771
|
-
"class",
|
|
772
|
-
"claude",
|
|
773
|
-
"client",
|
|
774
|
-
"cline",
|
|
775
|
-
"cloud-functions",
|
|
776
|
-
"cloudflare",
|
|
777
|
-
"cluster",
|
|
778
|
-
"cobol",
|
|
779
|
-
"command",
|
|
780
|
-
"components",
|
|
781
|
-
"config",
|
|
782
|
-
"connection",
|
|
783
|
-
"console",
|
|
784
|
-
"constant",
|
|
785
|
-
"container",
|
|
786
|
-
"content",
|
|
787
|
-
"context",
|
|
788
|
-
"contract",
|
|
789
|
-
"controller",
|
|
790
|
-
"core",
|
|
791
|
-
"coverage",
|
|
792
|
-
"css",
|
|
793
|
-
"cue",
|
|
794
|
-
"cursor",
|
|
795
|
-
"custom",
|
|
796
|
-
"cypress",
|
|
797
|
-
"dal",
|
|
798
|
-
"dart",
|
|
799
|
-
"database",
|
|
800
|
-
"debug",
|
|
801
|
-
"decorators",
|
|
802
|
-
"delta",
|
|
803
|
-
"desktop",
|
|
804
|
-
"directive",
|
|
805
|
-
"dist",
|
|
806
|
-
"docker",
|
|
807
|
-
"docs",
|
|
808
|
-
"download",
|
|
809
|
-
"drizzle",
|
|
810
|
-
"dump",
|
|
811
|
-
"element",
|
|
812
|
-
"enum",
|
|
813
|
-
"environment",
|
|
814
|
-
"error",
|
|
815
|
-
"eslint",
|
|
816
|
-
"event",
|
|
817
|
-
"examples",
|
|
818
|
-
"expo",
|
|
819
|
-
"export",
|
|
820
|
-
"fastlane",
|
|
821
|
-
"favicon",
|
|
822
|
-
"features",
|
|
823
|
-
"filter",
|
|
824
|
-
"firebase",
|
|
825
|
-
"firestore",
|
|
826
|
-
"flow",
|
|
827
|
-
"flutter",
|
|
828
|
-
"font",
|
|
829
|
-
"forgejo",
|
|
830
|
-
"functions",
|
|
831
|
-
"gamemaker",
|
|
832
|
-
"generator",
|
|
833
|
-
"gh-workflows",
|
|
834
|
-
"git",
|
|
835
|
-
"gitea",
|
|
836
|
-
"github",
|
|
837
|
-
"gitlab",
|
|
838
|
-
"global",
|
|
839
|
-
"godot",
|
|
840
|
-
"gradle",
|
|
841
|
-
"graphql",
|
|
842
|
-
"guard",
|
|
843
|
-
"gulp",
|
|
844
|
-
"helm",
|
|
845
|
-
"helper",
|
|
846
|
-
"home",
|
|
847
|
-
"hook",
|
|
848
|
-
"husky",
|
|
849
|
-
"i18n",
|
|
850
|
-
"images",
|
|
851
|
-
"import",
|
|
852
|
-
"include",
|
|
853
|
-
"input",
|
|
854
|
-
"intellij",
|
|
855
|
-
"interceptor",
|
|
856
|
-
"interface",
|
|
857
|
-
"ios",
|
|
858
|
-
"java",
|
|
859
|
-
"javascript",
|
|
860
|
-
"jinja",
|
|
861
|
-
"job",
|
|
862
|
-
"json",
|
|
863
|
-
"jupyter",
|
|
864
|
-
"keys",
|
|
865
|
-
"kubernetes",
|
|
866
|
-
"kusto",
|
|
867
|
-
"layout",
|
|
868
|
-
"lefthook",
|
|
869
|
-
"less",
|
|
870
|
-
"lib",
|
|
871
|
-
"license",
|
|
872
|
-
"link",
|
|
873
|
-
"linux",
|
|
874
|
-
"liquibase",
|
|
875
|
-
"log",
|
|
876
|
-
"lottie",
|
|
877
|
-
"lua",
|
|
878
|
-
"luau",
|
|
879
|
-
"macos",
|
|
880
|
-
"mail",
|
|
881
|
-
"mappings",
|
|
882
|
-
"markdown",
|
|
883
|
-
"mercurial",
|
|
884
|
-
"messages",
|
|
885
|
-
"meta",
|
|
886
|
-
"metro",
|
|
887
|
-
"middleware",
|
|
888
|
-
"migrations",
|
|
889
|
-
"mjml",
|
|
890
|
-
"mobile",
|
|
891
|
-
"mock",
|
|
892
|
-
"mojo",
|
|
893
|
-
"molecule",
|
|
894
|
-
"moon",
|
|
895
|
-
"netlify",
|
|
896
|
-
"next",
|
|
897
|
-
"ngrx-store",
|
|
898
|
-
"node",
|
|
899
|
-
"nuxt",
|
|
900
|
-
"obsidian",
|
|
901
|
-
"organism",
|
|
902
|
-
"other",
|
|
903
|
-
"packages",
|
|
904
|
-
"pdf",
|
|
905
|
-
"pdm",
|
|
906
|
-
"php",
|
|
907
|
-
"phpmailer",
|
|
908
|
-
"pipe",
|
|
909
|
-
"plastic",
|
|
910
|
-
"plugin",
|
|
911
|
-
"policy",
|
|
912
|
-
"powershell",
|
|
913
|
-
"prisma",
|
|
914
|
-
"private",
|
|
915
|
-
"project",
|
|
916
|
-
"prompts",
|
|
917
|
-
"proto",
|
|
918
|
-
"public",
|
|
919
|
-
"python",
|
|
920
|
-
"pytorch",
|
|
921
|
-
"quasar",
|
|
922
|
-
"queue",
|
|
923
|
-
"react-components",
|
|
924
|
-
"redux-reducer",
|
|
925
|
-
"repository",
|
|
926
|
-
"resolver",
|
|
927
|
-
"resource",
|
|
928
|
-
"review",
|
|
929
|
-
"robot",
|
|
930
|
-
"routes",
|
|
931
|
-
"rules",
|
|
932
|
-
"rust",
|
|
933
|
-
"salt",
|
|
934
|
-
"sandbox",
|
|
935
|
-
"sass",
|
|
936
|
-
"scala",
|
|
937
|
-
"scons",
|
|
938
|
-
"scripts",
|
|
939
|
-
"secure",
|
|
940
|
-
"seeders",
|
|
941
|
-
"server",
|
|
942
|
-
"serverless",
|
|
943
|
-
"shader",
|
|
944
|
-
"shared",
|
|
945
|
-
"simulations",
|
|
946
|
-
"snapcraft",
|
|
947
|
-
"snippet",
|
|
948
|
-
"src",
|
|
949
|
-
"src-tauri",
|
|
950
|
-
"stack",
|
|
951
|
-
"stencil",
|
|
952
|
-
"store",
|
|
953
|
-
"storybook",
|
|
954
|
-
"stylus",
|
|
955
|
-
"sublime",
|
|
956
|
-
"supabase",
|
|
957
|
-
"svelte",
|
|
958
|
-
"svg",
|
|
959
|
-
"syntax",
|
|
960
|
-
"target",
|
|
961
|
-
"taskfile",
|
|
962
|
-
"tasks",
|
|
963
|
-
"television",
|
|
964
|
-
"temp",
|
|
965
|
-
"template",
|
|
966
|
-
"terraform",
|
|
967
|
-
"test",
|
|
968
|
-
"theme",
|
|
969
|
-
"toc",
|
|
970
|
-
"tools",
|
|
971
|
-
"trash",
|
|
972
|
-
"trigger",
|
|
973
|
-
"turborepo",
|
|
974
|
-
"typescript",
|
|
975
|
-
"ui",
|
|
976
|
-
"unity",
|
|
977
|
-
"update",
|
|
978
|
-
"upload",
|
|
979
|
-
"utils",
|
|
980
|
-
"vercel",
|
|
981
|
-
"verdaccio",
|
|
982
|
-
"video",
|
|
983
|
-
"views",
|
|
984
|
-
"vm",
|
|
985
|
-
"vscode",
|
|
986
|
-
"vue",
|
|
987
|
-
"vue-directives",
|
|
988
|
-
"vuepress",
|
|
989
|
-
"vuex-store",
|
|
990
|
-
"wakatime",
|
|
991
|
-
"webpack",
|
|
992
|
-
"windows",
|
|
993
|
-
"wordpress",
|
|
994
|
-
"yarn",
|
|
995
|
-
"zeabur"
|
|
996
|
-
]);
|
|
997
|
-
var ALIASES = {
|
|
998
|
-
// 复数/变体
|
|
999
|
-
"tests": "test",
|
|
1000
|
-
"__tests__": "test",
|
|
1001
|
-
"__test__": "test",
|
|
1002
|
-
"spec": "test",
|
|
1003
|
-
"specs": "test",
|
|
1004
|
-
"script": "scripts",
|
|
1005
|
-
"configs": "config",
|
|
1006
|
-
"configuration": "config",
|
|
1007
|
-
"configurations": "config",
|
|
1008
|
-
"route": "routes",
|
|
1009
|
-
"routing": "routes",
|
|
1010
|
-
"stories": "storybook",
|
|
1011
|
-
"story": "storybook",
|
|
1012
|
-
"templates": "template",
|
|
1013
|
-
"themes": "theme",
|
|
1014
|
-
"videos": "video",
|
|
1015
|
-
"imgs": "images",
|
|
1016
|
-
"img": "images",
|
|
1017
|
-
"image": "images",
|
|
1018
|
-
"fonts": "font",
|
|
1019
|
-
"styles": "css",
|
|
1020
|
-
"style": "css",
|
|
1021
|
-
"styling": "css",
|
|
1022
|
-
"stylesheets": "css",
|
|
1023
|
-
"view": "views",
|
|
1024
|
-
"pages": "views",
|
|
1025
|
-
"page": "views",
|
|
1026
|
-
"layouts": "layout",
|
|
1027
|
-
"models": "database",
|
|
1028
|
-
"model": "database",
|
|
1029
|
-
"modules": "lib",
|
|
1030
|
-
"module": "lib",
|
|
1031
|
-
"mods": "lib",
|
|
1032
|
-
"plugins": "plugin",
|
|
1033
|
-
"addons": "plugin",
|
|
1034
|
-
"extensions": "plugin",
|
|
1035
|
-
"middlewares": "middleware",
|
|
1036
|
-
"helpers": "helper",
|
|
1037
|
-
"utilities": "utils",
|
|
1038
|
-
"util": "utils",
|
|
1039
|
-
"tool": "tools",
|
|
1040
|
-
"tooling": "tools",
|
|
1041
|
-
"resources": "resource",
|
|
1042
|
-
"res": "resource",
|
|
1043
|
-
"assets": "resource",
|
|
1044
|
-
"asset": "resource",
|
|
1045
|
-
"hooks": "hook",
|
|
1046
|
-
"composables": "hook",
|
|
1047
|
-
"mocks": "mock",
|
|
1048
|
-
"__mocks__": "mock",
|
|
1049
|
-
"fixtures": "mock",
|
|
1050
|
-
"__fixtures__": "mock",
|
|
1051
|
-
"logs": "log",
|
|
1052
|
-
"uploads": "upload",
|
|
1053
|
-
"function": "functions",
|
|
1054
|
-
"func": "functions",
|
|
1055
|
-
"fns": "functions",
|
|
1056
|
-
"services": "server",
|
|
1057
|
-
"service": "server",
|
|
1058
|
-
"component": "components",
|
|
1059
|
-
"comp": "components",
|
|
1060
|
-
"comps": "components",
|
|
1061
|
-
"controllers": "controller",
|
|
1062
|
-
// 常见变体
|
|
1063
|
-
"source": "src",
|
|
1064
|
-
"sources": "src",
|
|
1065
|
-
"distribution": "dist",
|
|
1066
|
-
"build": "dist",
|
|
1067
|
-
"builds": "dist",
|
|
1068
|
-
"out": "dist",
|
|
1069
|
-
"output": "dist",
|
|
1070
|
-
"documentation": "docs",
|
|
1071
|
-
"doc": "docs",
|
|
1072
|
-
"document": "docs",
|
|
1073
|
-
"documents": "docs",
|
|
1074
|
-
"static": "public",
|
|
1075
|
-
"statics": "public",
|
|
1076
|
-
"publics": "public",
|
|
1077
|
-
"libs": "lib",
|
|
1078
|
-
"library": "lib",
|
|
1079
|
-
"vendor": "lib",
|
|
1080
|
-
"vendors": "lib",
|
|
1081
|
-
"bin": "scripts",
|
|
1082
|
-
"binaries": "scripts",
|
|
1083
|
-
"tmp": "temp",
|
|
1084
|
-
"temporary": "temp",
|
|
1085
|
-
"cache": "temp",
|
|
1086
|
-
"caches": "temp",
|
|
1087
|
-
".cache": "temp",
|
|
1088
|
-
".turbo": "temp",
|
|
1089
|
-
"types": "typescript",
|
|
1090
|
-
"@types": "typescript",
|
|
1091
|
-
"typings": "typescript",
|
|
1092
|
-
"dts": "typescript",
|
|
1093
|
-
"locales": "i18n",
|
|
1094
|
-
"locale": "i18n",
|
|
1095
|
-
"lang": "i18n",
|
|
1096
|
-
"languages": "i18n",
|
|
1097
|
-
"translations": "i18n",
|
|
1098
|
-
"db": "database",
|
|
1099
|
-
"databases": "database",
|
|
1100
|
-
"sql": "database",
|
|
1101
|
-
"queries": "database",
|
|
1102
|
-
"migration": "migrations",
|
|
1103
|
-
"seeds": "seeders",
|
|
1104
|
-
"seed": "seeders",
|
|
1105
|
-
// 技术栈
|
|
1106
|
-
".vscode": "vscode",
|
|
1107
|
-
".github": "github",
|
|
1108
|
-
".gitlab": "gitlab",
|
|
1109
|
-
".circleci": "circleci",
|
|
1110
|
-
".husky": "husky",
|
|
1111
|
-
".docker": "docker",
|
|
1112
|
-
"node_modules": "node",
|
|
1113
|
-
"scss": "sass",
|
|
1114
|
-
"renderer": "client",
|
|
1115
|
-
"frontend": "client",
|
|
1116
|
-
"web": "client",
|
|
1117
|
-
"webapp": "client",
|
|
1118
|
-
"website": "client",
|
|
1119
|
-
"backend": "server",
|
|
1120
|
-
"main": "server",
|
|
1121
|
-
"preload": "scripts",
|
|
1122
|
-
".idea": "intellij",
|
|
1123
|
-
".git": "git",
|
|
1124
|
-
"k8s": "kubernetes",
|
|
1125
|
-
"kube": "kubernetes",
|
|
1126
|
-
"mongo": "database",
|
|
1127
|
-
"mongodb": "database",
|
|
1128
|
-
"mysql": "database",
|
|
1129
|
-
"postgres": "database",
|
|
1130
|
-
"api": "api",
|
|
1131
|
-
"apis": "api",
|
|
1132
|
-
"interfaces": "interface",
|
|
1133
|
-
"notebook": "jupyter",
|
|
1134
|
-
"notebooks": "jupyter",
|
|
1135
|
-
"ipynb": "jupyter",
|
|
1136
|
-
"notification": "messages",
|
|
1137
|
-
"notifications": "messages",
|
|
1138
|
-
"env": "environment",
|
|
1139
|
-
"envs": "environment",
|
|
1140
|
-
"redux": "redux-reducer",
|
|
1141
|
-
"store": "store",
|
|
1142
|
-
"stores": "store",
|
|
1143
|
-
"electron": "desktop",
|
|
1144
|
-
"tauri": "src-tauri"
|
|
1145
|
-
};
|
|
1146
|
-
function getFolderTypeIcon(folderName) {
|
|
1147
|
-
const name = (folderName || "").trim();
|
|
1148
|
-
if (!name) return void 0;
|
|
1149
|
-
const lower = name.replace(/[\\/]+$/, "").toLowerCase();
|
|
1150
|
-
const standardName = ALIASES[lower] ?? lower;
|
|
1151
|
-
if (KNOWN_TYPES2.has(standardName)) {
|
|
1152
|
-
return `material-icon-theme:folder-${standardName}`;
|
|
1153
|
-
}
|
|
1154
|
-
return void 0;
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
// src/components/FileIcon.tsx
|
|
1158
|
-
import { jsx } from "react/jsx-runtime";
|
|
1159
|
-
function FileIcon({ type, name, className = "", size = 24 }) {
|
|
1160
|
-
const iconName = useMemo(() => {
|
|
1161
|
-
if (type === FileType.FOLDER) {
|
|
1162
|
-
const folderIcon = name ? getFolderTypeIcon(name) : void 0;
|
|
1163
|
-
return folderIcon ?? "ic:round-folder";
|
|
1164
|
-
}
|
|
1165
|
-
if (name) {
|
|
1166
|
-
return getFileTypeIcon(name, type);
|
|
1167
|
-
}
|
|
1168
|
-
switch (type) {
|
|
1169
|
-
case FileType.IMAGE:
|
|
1170
|
-
return "material-icon-theme:image";
|
|
1171
|
-
case FileType.TEXT:
|
|
1172
|
-
return "material-icon-theme:document";
|
|
1173
|
-
case FileType.CODE:
|
|
1174
|
-
return "material-icon-theme:javascript";
|
|
1175
|
-
case FileType.MUSIC:
|
|
1176
|
-
return "material-icon-theme:audio";
|
|
1177
|
-
case FileType.VIDEO:
|
|
1178
|
-
return "material-icon-theme:video";
|
|
1179
|
-
case FileType.PDF:
|
|
1180
|
-
return "material-icon-theme:pdf";
|
|
1181
|
-
case FileType.DOCUMENT:
|
|
1182
|
-
return "material-icon-theme:word";
|
|
1183
|
-
case FileType.APPLICATION:
|
|
1184
|
-
return "material-icon-theme:exe";
|
|
1185
|
-
case FileType.ARCHIVE:
|
|
1186
|
-
return "material-icon-theme:zip";
|
|
1187
|
-
default:
|
|
1188
|
-
return "material-icon-theme:document";
|
|
1189
|
-
}
|
|
1190
|
-
}, [type, name]);
|
|
1191
|
-
const iconClass = useMemo(() => {
|
|
1192
|
-
const base = "file-icon";
|
|
1193
|
-
switch (type) {
|
|
1194
|
-
case FileType.FOLDER:
|
|
1195
|
-
return `${base} file-icon--folder`;
|
|
1196
|
-
case FileType.IMAGE:
|
|
1197
|
-
return `${base} file-icon--image`;
|
|
1198
|
-
case FileType.TEXT:
|
|
1199
|
-
return `${base} file-icon--text`;
|
|
1200
|
-
case FileType.CODE:
|
|
1201
|
-
return `${base} file-icon--code`;
|
|
1202
|
-
case FileType.MUSIC:
|
|
1203
|
-
return `${base} file-icon--music`;
|
|
1204
|
-
case FileType.VIDEO:
|
|
1205
|
-
return `${base} file-icon--video`;
|
|
1206
|
-
case FileType.PDF:
|
|
1207
|
-
case FileType.DOCUMENT:
|
|
1208
|
-
return `${base} file-icon--pdf`;
|
|
1209
|
-
case FileType.APPLICATION:
|
|
1210
|
-
return `${base} file-icon--application`;
|
|
1211
|
-
case FileType.ARCHIVE:
|
|
1212
|
-
return `${base} file-icon--archive`;
|
|
1213
|
-
default:
|
|
1214
|
-
return `${base} file-icon--default`;
|
|
1215
|
-
}
|
|
1216
|
-
}, [type]);
|
|
1217
|
-
return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(Icon, { icon: iconName, width: size, height: size, className: iconClass }) });
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
// src/components/FileGrid.tsx
|
|
1221
|
-
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1222
|
-
function splitFileName(name, isFolder) {
|
|
1223
|
-
if (isFolder) {
|
|
1224
|
-
return { baseName: name, ext: "" };
|
|
1225
|
-
}
|
|
1226
|
-
const lastDot = name.lastIndexOf(".");
|
|
1227
|
-
if (lastDot <= 0) {
|
|
1228
|
-
return { baseName: name, ext: "" };
|
|
1229
|
-
}
|
|
1230
|
-
return {
|
|
1231
|
-
baseName: name.substring(0, lastDot),
|
|
1232
|
-
ext: name.substring(lastDot)
|
|
1233
|
-
// 包含点号
|
|
1234
|
-
};
|
|
1235
|
-
}
|
|
1236
|
-
function FileName({
|
|
1237
|
-
name,
|
|
1238
|
-
isFolder,
|
|
1239
|
-
isSelected,
|
|
1240
|
-
onClick
|
|
1241
|
-
}) {
|
|
1242
|
-
const { baseName, ext } = useMemo2(() => splitFileName(name, isFolder), [name, isFolder]);
|
|
1243
|
-
return /* @__PURE__ */ jsx2(
|
|
1244
|
-
"span",
|
|
1245
|
-
{
|
|
1246
|
-
onClick,
|
|
1247
|
-
className: `file-grid-item-name ${isSelected ? "file-grid-item-name--selected" : ""}`,
|
|
1248
|
-
title: name,
|
|
1249
|
-
children: ext ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1250
|
-
/* @__PURE__ */ jsx2("span", { className: "file-grid-item-name-base", children: baseName }),
|
|
1251
|
-
/* @__PURE__ */ jsx2("span", { className: "file-grid-item-name-ext", children: ext })
|
|
1252
|
-
] }) : (
|
|
1253
|
-
// 无扩展名(包含文件夹/无扩展名文件/隐藏文件等):允许两行并省略
|
|
1254
|
-
/* @__PURE__ */ jsx2("span", { className: "file-grid-item-name-base file-grid-item-name-base--two-lines", children: baseName })
|
|
1255
|
-
)
|
|
1256
|
-
}
|
|
1257
|
-
);
|
|
1258
|
-
}
|
|
1259
|
-
function FileGrid({
|
|
1260
|
-
items,
|
|
1261
|
-
selectedIds,
|
|
1262
|
-
editingId,
|
|
1263
|
-
dragOverId,
|
|
1264
|
-
getAppIconUrl,
|
|
1265
|
-
onSelect,
|
|
1266
|
-
onOpen,
|
|
1267
|
-
onContextMenu,
|
|
1268
|
-
onContextMenuEmpty,
|
|
1269
|
-
onNameClick,
|
|
1270
|
-
onRename,
|
|
1271
|
-
onRenameCancel,
|
|
1272
|
-
onDragStart,
|
|
1273
|
-
onDragOver,
|
|
1274
|
-
onDragLeave,
|
|
1275
|
-
onDrop,
|
|
1276
|
-
onThumbnailError
|
|
1277
|
-
}) {
|
|
1278
|
-
const renameInputRef = useRef(null);
|
|
1279
|
-
const handleEmptyContextMenu = (e) => {
|
|
1280
|
-
const target = e.target;
|
|
1281
|
-
if (!target.closest(".file-grid-item")) {
|
|
1282
|
-
onContextMenuEmpty?.(e);
|
|
1283
|
-
}
|
|
1284
|
-
};
|
|
1285
|
-
const hasThumbnail = (item) => {
|
|
1286
|
-
if (item.type === FileType.APPLICATION && getAppIconUrl?.(item)) {
|
|
1287
|
-
return true;
|
|
1288
|
-
}
|
|
1289
|
-
if (item.type === FileType.IMAGE) {
|
|
1290
|
-
return !!item.thumbnailUrl;
|
|
1291
|
-
}
|
|
1292
|
-
if (item.type === FileType.VIDEO) {
|
|
1293
|
-
return !!item.thumbnailUrl;
|
|
1294
|
-
}
|
|
1295
|
-
return false;
|
|
1296
|
-
};
|
|
1297
|
-
const handleVideoHover = (e, isHover) => {
|
|
1298
|
-
const video = e.currentTarget;
|
|
1299
|
-
if (isHover) {
|
|
1300
|
-
video.play().catch(() => {
|
|
1301
|
-
});
|
|
1302
|
-
} else {
|
|
1303
|
-
video.pause();
|
|
1304
|
-
video.currentTime = 0;
|
|
1305
|
-
}
|
|
1306
|
-
};
|
|
1307
|
-
const handleRename = (item, e) => {
|
|
1308
|
-
const input = e.target;
|
|
1309
|
-
const newName = input.value.trim();
|
|
1310
|
-
if (newName && newName !== item.name) {
|
|
1311
|
-
onRename?.(item, newName);
|
|
1312
|
-
} else {
|
|
1313
|
-
onRenameCancel?.(item);
|
|
1314
|
-
}
|
|
1315
|
-
};
|
|
1316
|
-
const handleEnterKey = (e) => {
|
|
1317
|
-
e.currentTarget.blur();
|
|
1318
|
-
};
|
|
1319
|
-
const handleEscapeKey = (e) => {
|
|
1320
|
-
const input = e.currentTarget;
|
|
1321
|
-
const item = items.find((i) => i.id === editingId);
|
|
1322
|
-
if (item) {
|
|
1323
|
-
input.value = item.name;
|
|
1324
|
-
}
|
|
1325
|
-
input.blur();
|
|
1326
|
-
};
|
|
1327
|
-
return /* @__PURE__ */ jsx2("div", { className: "file-grid", onContextMenu: (e) => {
|
|
1328
|
-
e.preventDefault();
|
|
1329
|
-
handleEmptyContextMenu(e);
|
|
1330
|
-
}, children: items.map((item) => {
|
|
1331
|
-
const isSelected = selectedIds.has(item.id);
|
|
1332
|
-
const isEditing = editingId === item.id;
|
|
1333
|
-
const isDragOver = dragOverId === item.id;
|
|
1334
|
-
const hasThumb = hasThumbnail(item);
|
|
1335
|
-
const appIconUrl = item.type === FileType.APPLICATION ? getAppIconUrl?.(item) : void 0;
|
|
1336
|
-
let itemClassName = "file-grid-item";
|
|
1337
|
-
if (isSelected && !isEditing) {
|
|
1338
|
-
itemClassName += " file-grid-item--selected";
|
|
1339
|
-
} else if (isDragOver) {
|
|
1340
|
-
itemClassName += " file-grid-item--drag-over";
|
|
1341
|
-
} else {
|
|
1342
|
-
itemClassName += " file-grid-item--normal";
|
|
1343
|
-
}
|
|
1344
|
-
return /* @__PURE__ */ jsxs(
|
|
1345
|
-
"div",
|
|
1346
|
-
{
|
|
1347
|
-
draggable: !isEditing,
|
|
1348
|
-
onDragStart: (e) => onDragStart?.(e, item),
|
|
1349
|
-
onDragOver: (e) => {
|
|
1350
|
-
e.preventDefault();
|
|
1351
|
-
onDragOver?.(e, item);
|
|
1352
|
-
},
|
|
1353
|
-
onDragLeave: (e) => onDragLeave?.(e),
|
|
1354
|
-
onDrop: (e) => {
|
|
1355
|
-
e.preventDefault();
|
|
1356
|
-
onDrop?.(e, item);
|
|
1357
|
-
},
|
|
1358
|
-
onClick: (e) => {
|
|
1359
|
-
e.stopPropagation();
|
|
1360
|
-
onSelect?.(item, e);
|
|
1361
|
-
},
|
|
1362
|
-
onDoubleClick: (e) => {
|
|
1363
|
-
e.stopPropagation();
|
|
1364
|
-
onOpen?.(item);
|
|
1365
|
-
},
|
|
1366
|
-
onContextMenu: (e) => {
|
|
1367
|
-
e.preventDefault();
|
|
1368
|
-
e.stopPropagation();
|
|
1369
|
-
onContextMenu?.(item, e);
|
|
1370
|
-
},
|
|
1371
|
-
className: itemClassName,
|
|
1372
|
-
children: [
|
|
1373
|
-
/* @__PURE__ */ jsxs("div", { className: "file-grid-item-icon", children: [
|
|
1374
|
-
appIconUrl && /* @__PURE__ */ jsx2(
|
|
1375
|
-
"img",
|
|
1376
|
-
{
|
|
1377
|
-
src: appIconUrl,
|
|
1378
|
-
alt: item.name,
|
|
1379
|
-
className: `file-grid-item-thumbnail file-grid-item-thumbnail--application ${isSelected && !isEditing ? "file-grid-item-thumbnail--selected" : ""}`
|
|
1380
|
-
}
|
|
1381
|
-
),
|
|
1382
|
-
!appIconUrl && item.type === FileType.VIDEO && item.thumbnailUrl && hasThumb && /* @__PURE__ */ jsxs("div", { className: "file-grid-item-thumbnail file-grid-item-thumbnail--video", children: [
|
|
1383
|
-
/* @__PURE__ */ jsx2(
|
|
1384
|
-
"img",
|
|
1385
|
-
{
|
|
1386
|
-
src: item.thumbnailUrl,
|
|
1387
|
-
alt: item.name,
|
|
1388
|
-
className: "file-grid-item-thumbnail",
|
|
1389
|
-
onError: (e) => onThumbnailError?.(item, e)
|
|
1390
|
-
}
|
|
1391
|
-
),
|
|
1392
|
-
/* @__PURE__ */ jsx2("div", { className: "file-grid-item-video-play", children: /* @__PURE__ */ jsx2("div", { className: "file-grid-item-video-play-icon" }) })
|
|
1393
|
-
] }),
|
|
1394
|
-
!appIconUrl && item.type === FileType.IMAGE && item.thumbnailUrl && hasThumb && /* @__PURE__ */ jsx2(
|
|
1395
|
-
"img",
|
|
1396
|
-
{
|
|
1397
|
-
src: item.thumbnailUrl,
|
|
1398
|
-
alt: item.name,
|
|
1399
|
-
className: "file-grid-item-thumbnail",
|
|
1400
|
-
onError: (e) => onThumbnailError?.(item, e)
|
|
1401
|
-
}
|
|
1402
|
-
),
|
|
1403
|
-
!appIconUrl && !hasThumb && /* @__PURE__ */ jsx2(FileIcon, { type: item.type, name: item.name, size: 48 })
|
|
1404
|
-
] }),
|
|
1405
|
-
/* @__PURE__ */ jsx2("div", { className: "file-grid-item-name-wrapper", children: isEditing ? /* @__PURE__ */ jsx2(
|
|
1406
|
-
"input",
|
|
1407
|
-
{
|
|
1408
|
-
ref: renameInputRef,
|
|
1409
|
-
type: "text",
|
|
1410
|
-
className: "file-grid-item-rename-input",
|
|
1411
|
-
defaultValue: item.name,
|
|
1412
|
-
onBlur: (e) => handleRename(item, e),
|
|
1413
|
-
onKeyDown: (e) => {
|
|
1414
|
-
if (e.key === "Enter") {
|
|
1415
|
-
handleEnterKey(e);
|
|
1416
|
-
} else if (e.key === "Escape") {
|
|
1417
|
-
handleEscapeKey(e);
|
|
1418
|
-
}
|
|
1419
|
-
},
|
|
1420
|
-
autoFocus: true
|
|
1421
|
-
}
|
|
1422
|
-
) : /* @__PURE__ */ jsx2(
|
|
1423
|
-
FileName,
|
|
1424
|
-
{
|
|
1425
|
-
name: item.name,
|
|
1426
|
-
isFolder: item.type === FileType.FOLDER,
|
|
1427
|
-
isSelected,
|
|
1428
|
-
onClick: (e) => {
|
|
1429
|
-
e.stopPropagation();
|
|
1430
|
-
onNameClick?.(item, e);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
) })
|
|
1434
|
-
]
|
|
1435
|
-
},
|
|
1436
|
-
item.id
|
|
1437
|
-
);
|
|
1438
|
-
}) });
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
// src/components/FileList.tsx
|
|
1442
|
-
import { useRef as useRef2 } from "react";
|
|
1443
|
-
|
|
1444
|
-
// src/components/SortIndicator.tsx
|
|
1445
|
-
import { Icon as Icon2 } from "@iconify/react";
|
|
1446
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1447
|
-
function SortIndicator({ direction }) {
|
|
1448
|
-
return /* @__PURE__ */ jsx3("span", { className: "sort-indicator", children: /* @__PURE__ */ jsx3(
|
|
1449
|
-
Icon2,
|
|
1450
|
-
{
|
|
1451
|
-
icon: direction === "asc" ? "lucide:chevron-up" : "lucide:chevron-down",
|
|
1452
|
-
width: 12,
|
|
1453
|
-
height: 12
|
|
1454
|
-
}
|
|
1455
|
-
) });
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
// src/components/FileList.tsx
|
|
1459
|
-
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1460
|
-
function getTypeLabel(type) {
|
|
1461
|
-
const labels = {
|
|
1462
|
-
[FileType.FOLDER]: "\u6587\u4EF6\u5939",
|
|
1463
|
-
[FileType.FILE]: "\u6587\u4EF6",
|
|
1464
|
-
[FileType.IMAGE]: "\u56FE\u7247",
|
|
1465
|
-
[FileType.VIDEO]: "\u89C6\u9891",
|
|
1466
|
-
[FileType.MUSIC]: "\u97F3\u9891",
|
|
1467
|
-
[FileType.DOCUMENT]: "\u6587\u6863",
|
|
1468
|
-
[FileType.CODE]: "\u4EE3\u7801",
|
|
1469
|
-
[FileType.TEXT]: "\u6587\u672C",
|
|
1470
|
-
[FileType.PDF]: "PDF",
|
|
1471
|
-
[FileType.ARCHIVE]: "\u538B\u7F29\u5305",
|
|
1472
|
-
[FileType.APPLICATION]: "\u5E94\u7528\u7A0B\u5E8F",
|
|
1473
|
-
[FileType.UNKNOWN]: "\u672A\u77E5"
|
|
1474
|
-
};
|
|
1475
|
-
return labels[type] || type;
|
|
1476
|
-
}
|
|
1477
|
-
function FileList({
|
|
1478
|
-
items,
|
|
1479
|
-
selectedIds,
|
|
1480
|
-
sortConfig,
|
|
1481
|
-
editingId,
|
|
1482
|
-
dragOverId,
|
|
1483
|
-
onSelect,
|
|
1484
|
-
onOpen,
|
|
1485
|
-
onContextMenu,
|
|
1486
|
-
onContextMenuEmpty,
|
|
1487
|
-
onNameClick,
|
|
1488
|
-
onRename,
|
|
1489
|
-
onRenameCancel,
|
|
1490
|
-
onSort,
|
|
1491
|
-
onDragStart,
|
|
1492
|
-
onDragOver,
|
|
1493
|
-
onDragLeave,
|
|
1494
|
-
onDrop
|
|
1495
|
-
}) {
|
|
1496
|
-
const renameInputRef = useRef2(null);
|
|
1497
|
-
const handleEmptyContextMenu = (e) => {
|
|
1498
|
-
const target = e.target;
|
|
1499
|
-
if (!target.closest("tr")) {
|
|
1500
|
-
onContextMenuEmpty?.(e);
|
|
1501
|
-
}
|
|
1502
|
-
};
|
|
1503
|
-
const handleRename = (item, e) => {
|
|
1504
|
-
const input = e.target;
|
|
1505
|
-
const newName = input.value.trim();
|
|
1506
|
-
if (newName && newName !== item.name) {
|
|
1507
|
-
onRename?.(item, newName);
|
|
1508
|
-
} else {
|
|
1509
|
-
onRenameCancel?.(item);
|
|
1510
|
-
}
|
|
1511
|
-
};
|
|
1512
|
-
const handleEnterKey = (e) => {
|
|
1513
|
-
e.currentTarget.blur();
|
|
1514
|
-
};
|
|
1515
|
-
const handleEscapeKey = (e) => {
|
|
1516
|
-
const input = e.currentTarget;
|
|
1517
|
-
const item = items.find((i) => i.id === editingId);
|
|
1518
|
-
if (item) {
|
|
1519
|
-
input.value = item.name;
|
|
1520
|
-
}
|
|
1521
|
-
input.blur();
|
|
1522
|
-
};
|
|
1523
|
-
return /* @__PURE__ */ jsx4("div", { className: "file-list", onContextMenu: (e) => {
|
|
1524
|
-
e.preventDefault();
|
|
1525
|
-
handleEmptyContextMenu(e);
|
|
1526
|
-
}, children: /* @__PURE__ */ jsxs2("table", { className: "file-list-table", children: [
|
|
1527
|
-
/* @__PURE__ */ jsx4("thead", { className: "file-list-header", children: /* @__PURE__ */ jsxs2("tr", { children: [
|
|
1528
|
-
/* @__PURE__ */ jsxs2(
|
|
1529
|
-
"th",
|
|
1530
|
-
{
|
|
1531
|
-
className: "file-list-header-cell file-list-header-cell--name",
|
|
1532
|
-
onClick: () => onSort?.("name"),
|
|
1533
|
-
children: [
|
|
1534
|
-
"\u540D\u79F0",
|
|
1535
|
-
sortConfig?.field === "name" && /* @__PURE__ */ jsx4(SortIndicator, { direction: sortConfig.direction })
|
|
1536
|
-
]
|
|
1537
|
-
}
|
|
1538
|
-
),
|
|
1539
|
-
/* @__PURE__ */ jsxs2(
|
|
1540
|
-
"th",
|
|
1541
|
-
{
|
|
1542
|
-
className: "file-list-header-cell",
|
|
1543
|
-
onClick: () => onSort?.("dateModified"),
|
|
1544
|
-
children: [
|
|
1545
|
-
"\u4FEE\u6539\u65E5\u671F",
|
|
1546
|
-
sortConfig?.field === "dateModified" && /* @__PURE__ */ jsx4(SortIndicator, { direction: sortConfig.direction })
|
|
1547
|
-
]
|
|
1548
|
-
}
|
|
1549
|
-
),
|
|
1550
|
-
/* @__PURE__ */ jsxs2(
|
|
1551
|
-
"th",
|
|
1552
|
-
{
|
|
1553
|
-
className: "file-list-header-cell",
|
|
1554
|
-
onClick: () => onSort?.("size"),
|
|
1555
|
-
children: [
|
|
1556
|
-
"\u5927\u5C0F",
|
|
1557
|
-
sortConfig?.field === "size" && /* @__PURE__ */ jsx4(SortIndicator, { direction: sortConfig.direction })
|
|
1558
|
-
]
|
|
1559
|
-
}
|
|
1560
|
-
),
|
|
1561
|
-
/* @__PURE__ */ jsxs2(
|
|
1562
|
-
"th",
|
|
1563
|
-
{
|
|
1564
|
-
className: "file-list-header-cell",
|
|
1565
|
-
onClick: () => onSort?.("type"),
|
|
1566
|
-
children: [
|
|
1567
|
-
"\u7C7B\u578B",
|
|
1568
|
-
sortConfig?.field === "type" && /* @__PURE__ */ jsx4(SortIndicator, { direction: sortConfig.direction })
|
|
1569
|
-
]
|
|
1570
|
-
}
|
|
1571
|
-
)
|
|
1572
|
-
] }) }),
|
|
1573
|
-
/* @__PURE__ */ jsx4("tbody", { className: "file-list-body", children: items.map((item, index) => {
|
|
1574
|
-
const isSelected = selectedIds.has(item.id);
|
|
1575
|
-
const isEditing = editingId === item.id;
|
|
1576
|
-
const isDragOver = dragOverId === item.id;
|
|
1577
|
-
let rowClassName = "file-list-row";
|
|
1578
|
-
if (isSelected) {
|
|
1579
|
-
rowClassName += " file-list-row--selected";
|
|
1580
|
-
} else if (isDragOver) {
|
|
1581
|
-
rowClassName += " file-list-row--drag-over";
|
|
1582
|
-
} else if (index % 2 === 0) {
|
|
1583
|
-
rowClassName += " file-list-row--even";
|
|
1584
|
-
} else {
|
|
1585
|
-
rowClassName += " file-list-row--odd";
|
|
1586
|
-
}
|
|
1587
|
-
return /* @__PURE__ */ jsxs2(
|
|
1588
|
-
"tr",
|
|
1589
|
-
{
|
|
1590
|
-
draggable: !isEditing,
|
|
1591
|
-
onDragStart: (e) => onDragStart?.(e, item),
|
|
1592
|
-
onDragOver: (e) => {
|
|
1593
|
-
e.preventDefault();
|
|
1594
|
-
onDragOver?.(e, item);
|
|
1595
|
-
},
|
|
1596
|
-
onDragLeave: (e) => onDragLeave?.(e),
|
|
1597
|
-
onDrop: (e) => {
|
|
1598
|
-
e.preventDefault();
|
|
1599
|
-
onDrop?.(e, item);
|
|
1600
|
-
},
|
|
1601
|
-
onClick: (e) => {
|
|
1602
|
-
e.stopPropagation();
|
|
1603
|
-
onSelect?.(item, e);
|
|
1604
|
-
},
|
|
1605
|
-
onDoubleClick: (e) => {
|
|
1606
|
-
e.stopPropagation();
|
|
1607
|
-
onOpen?.(item);
|
|
1608
|
-
},
|
|
1609
|
-
onContextMenu: (e) => {
|
|
1610
|
-
e.preventDefault();
|
|
1611
|
-
e.stopPropagation();
|
|
1612
|
-
onContextMenu?.(item, e);
|
|
1613
|
-
},
|
|
1614
|
-
className: rowClassName,
|
|
1615
|
-
children: [
|
|
1616
|
-
/* @__PURE__ */ jsxs2("td", { className: `file-list-cell file-list-cell--name ${isSelected ? "file-list-cell--selected" : ""}`, children: [
|
|
1617
|
-
/* @__PURE__ */ jsx4(FileIcon, { type: item.type, name: item.name, size: 16 }),
|
|
1618
|
-
isEditing ? /* @__PURE__ */ jsx4(
|
|
1619
|
-
"input",
|
|
1620
|
-
{
|
|
1621
|
-
ref: renameInputRef,
|
|
1622
|
-
type: "text",
|
|
1623
|
-
className: "file-list-rename-input",
|
|
1624
|
-
defaultValue: item.name,
|
|
1625
|
-
onBlur: (e) => handleRename(item, e),
|
|
1626
|
-
onKeyDown: (e) => {
|
|
1627
|
-
if (e.key === "Enter") {
|
|
1628
|
-
handleEnterKey(e);
|
|
1629
|
-
} else if (e.key === "Escape") {
|
|
1630
|
-
handleEscapeKey(e);
|
|
1631
|
-
}
|
|
1632
|
-
},
|
|
1633
|
-
autoFocus: true
|
|
1634
|
-
}
|
|
1635
|
-
) : /* @__PURE__ */ jsx4(
|
|
1636
|
-
"span",
|
|
1637
|
-
{
|
|
1638
|
-
onClick: (e) => {
|
|
1639
|
-
e.stopPropagation();
|
|
1640
|
-
onNameClick?.(item, e);
|
|
1641
|
-
},
|
|
1642
|
-
className: `file-list-name ${isSelected ? "file-list-name--selected" : ""}`,
|
|
1643
|
-
children: item.name
|
|
1644
|
-
}
|
|
1645
|
-
)
|
|
1646
|
-
] }),
|
|
1647
|
-
/* @__PURE__ */ jsx4("td", { className: `file-list-cell ${isSelected ? "file-list-cell--selected" : ""}`, children: item.dateModified || "--" }),
|
|
1648
|
-
/* @__PURE__ */ jsx4("td", { className: `file-list-cell file-list-cell--size ${isSelected ? "file-list-cell--selected" : ""}`, children: item.size || "--" }),
|
|
1649
|
-
/* @__PURE__ */ jsx4("td", { className: `file-list-cell ${isSelected ? "file-list-cell--selected" : ""}`, children: getTypeLabel(item.type) })
|
|
1650
|
-
]
|
|
1651
|
-
},
|
|
1652
|
-
item.id
|
|
1653
|
-
);
|
|
1654
|
-
}) })
|
|
1655
|
-
] }) });
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
// src/components/FileListView.tsx
|
|
1659
|
-
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1660
|
-
var FileListView = forwardRef(
|
|
1661
|
-
({
|
|
1662
|
-
items,
|
|
1663
|
-
viewMode = "grid",
|
|
1664
|
-
loading = false,
|
|
1665
|
-
adapter,
|
|
1666
|
-
currentPath,
|
|
1667
|
-
getAppIconUrl,
|
|
1668
|
-
onOpen,
|
|
1669
|
-
onSelectionChange,
|
|
1670
|
-
onContextMenu,
|
|
1671
|
-
onContextMenuEmpty,
|
|
1672
|
-
onRename,
|
|
1673
|
-
onSortChange,
|
|
1674
|
-
onMove
|
|
1675
|
-
}, ref) => {
|
|
1676
|
-
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
1677
|
-
const [editingId, setEditingId] = useState(null);
|
|
1678
|
-
const [dragOverId, setDragOverId] = useState(null);
|
|
1679
|
-
const [sortConfig, setSortConfig] = useState({
|
|
1680
|
-
field: "name",
|
|
1681
|
-
direction: "asc"
|
|
1682
|
-
});
|
|
1683
|
-
const selectedItems = items.filter((item) => selectedIds.has(item.id));
|
|
1684
|
-
const handleSelect = useCallback(
|
|
1685
|
-
(item, e) => {
|
|
1686
|
-
if (e.metaKey || e.ctrlKey) {
|
|
1687
|
-
setSelectedIds((prev) => {
|
|
1688
|
-
const newSet = new Set(prev);
|
|
1689
|
-
if (newSet.has(item.id)) {
|
|
1690
|
-
newSet.delete(item.id);
|
|
1691
|
-
} else {
|
|
1692
|
-
newSet.add(item.id);
|
|
1693
|
-
}
|
|
1694
|
-
const newItems = items.filter((i) => newSet.has(i.id));
|
|
1695
|
-
onSelectionChange?.(newSet, newItems);
|
|
1696
|
-
return newSet;
|
|
1697
|
-
});
|
|
1698
|
-
} else if (e.shiftKey && selectedIds.size > 0) {
|
|
1699
|
-
const lastId = Array.from(selectedIds).pop();
|
|
1700
|
-
const lastIndex = items.findIndex((i) => i.id === lastId);
|
|
1701
|
-
const currentIndex = items.findIndex((i) => i.id === item.id);
|
|
1702
|
-
const start = Math.min(lastIndex, currentIndex);
|
|
1703
|
-
const end = Math.max(lastIndex, currentIndex);
|
|
1704
|
-
const newSet = /* @__PURE__ */ new Set();
|
|
1705
|
-
for (let i = start; i <= end; i++) {
|
|
1706
|
-
newSet.add(items[i].id);
|
|
1707
|
-
}
|
|
1708
|
-
setSelectedIds(newSet);
|
|
1709
|
-
const newItems = items.filter((i) => newSet.has(i.id));
|
|
1710
|
-
onSelectionChange?.(newSet, newItems);
|
|
1711
|
-
} else {
|
|
1712
|
-
const newSet = /* @__PURE__ */ new Set([item.id]);
|
|
1713
|
-
setSelectedIds(newSet);
|
|
1714
|
-
onSelectionChange?.(newSet, [item]);
|
|
1715
|
-
}
|
|
1716
|
-
},
|
|
1717
|
-
[items, selectedIds, onSelectionChange]
|
|
1718
|
-
);
|
|
1719
|
-
const handleEmptyClick = useCallback(
|
|
1720
|
-
(e) => {
|
|
1721
|
-
if (e.target === e.currentTarget) {
|
|
1722
|
-
clearSelection();
|
|
1723
|
-
}
|
|
1724
|
-
},
|
|
1725
|
-
[]
|
|
1726
|
-
);
|
|
1727
|
-
const clearSelection = useCallback(() => {
|
|
1728
|
-
setSelectedIds(/* @__PURE__ */ new Set());
|
|
1729
|
-
onSelectionChange?.(/* @__PURE__ */ new Set(), []);
|
|
1730
|
-
}, [onSelectionChange]);
|
|
1731
|
-
const handleOpen = useCallback(
|
|
1732
|
-
(item) => {
|
|
1733
|
-
onOpen?.(item);
|
|
1734
|
-
},
|
|
1735
|
-
[onOpen]
|
|
1736
|
-
);
|
|
1737
|
-
const handleContextMenu = useCallback(
|
|
1738
|
-
(item, e) => {
|
|
1739
|
-
if (!selectedIds.has(item.id)) {
|
|
1740
|
-
const newSet = /* @__PURE__ */ new Set([item.id]);
|
|
1741
|
-
setSelectedIds(newSet);
|
|
1742
|
-
onSelectionChange?.(newSet, [item]);
|
|
1743
|
-
}
|
|
1744
|
-
onContextMenu?.(e, item);
|
|
1745
|
-
},
|
|
1746
|
-
[selectedIds, onSelectionChange, onContextMenu]
|
|
1747
|
-
);
|
|
1748
|
-
const handleEmptyContextMenu = useCallback(
|
|
1749
|
-
(e) => {
|
|
1750
|
-
const target = e.target;
|
|
1751
|
-
if (!target.closest(".file-grid-item") && !target.closest(".file-list-row")) {
|
|
1752
|
-
clearSelection();
|
|
1753
|
-
onContextMenuEmpty?.(e);
|
|
1754
|
-
}
|
|
1755
|
-
},
|
|
1756
|
-
[clearSelection, onContextMenuEmpty]
|
|
1757
|
-
);
|
|
1758
|
-
const handleEmptyContextMenuFromChild = useCallback(
|
|
1759
|
-
(e) => {
|
|
1760
|
-
clearSelection();
|
|
1761
|
-
onContextMenuEmpty?.(e);
|
|
1762
|
-
},
|
|
1763
|
-
[clearSelection, onContextMenuEmpty]
|
|
1764
|
-
);
|
|
1765
|
-
const handleNameClick = useCallback(
|
|
1766
|
-
(item, e) => {
|
|
1767
|
-
if (selectedIds.has(item.id) && selectedIds.size === 1) {
|
|
1768
|
-
setTimeout(() => {
|
|
1769
|
-
if (selectedIds.has(item.id)) {
|
|
1770
|
-
setEditingId(item.id);
|
|
1771
|
-
}
|
|
1772
|
-
}, 500);
|
|
1773
|
-
}
|
|
1774
|
-
},
|
|
1775
|
-
[selectedIds]
|
|
1776
|
-
);
|
|
1777
|
-
const handleRename = useCallback(
|
|
1778
|
-
(item, newName) => {
|
|
1779
|
-
if (newName && newName !== item.name) {
|
|
1780
|
-
onRename?.(item, newName);
|
|
1781
|
-
}
|
|
1782
|
-
setEditingId(null);
|
|
1783
|
-
},
|
|
1784
|
-
[onRename]
|
|
1785
|
-
);
|
|
1786
|
-
const handleRenameCancel = useCallback(() => {
|
|
1787
|
-
setEditingId(null);
|
|
1788
|
-
}, []);
|
|
1789
|
-
const handleSort = useCallback(
|
|
1790
|
-
(field) => {
|
|
1791
|
-
setSortConfig((prev) => {
|
|
1792
|
-
const newConfig = prev.field === field ? { ...prev, direction: prev.direction === "asc" ? "desc" : "asc" } : { field, direction: "asc" };
|
|
1793
|
-
onSortChange?.(newConfig);
|
|
1794
|
-
return newConfig;
|
|
1795
|
-
});
|
|
1796
|
-
},
|
|
1797
|
-
[onSortChange]
|
|
1798
|
-
);
|
|
1799
|
-
const handleDragStart = useCallback(
|
|
1800
|
-
(e, item) => {
|
|
1801
|
-
if (!selectedIds.has(item.id)) {
|
|
1802
|
-
const newSet = /* @__PURE__ */ new Set([item.id]);
|
|
1803
|
-
setSelectedIds(newSet);
|
|
1804
|
-
onSelectionChange?.(newSet, [item]);
|
|
1805
|
-
}
|
|
1806
|
-
e.dataTransfer.setData(
|
|
1807
|
-
"text/plain",
|
|
1808
|
-
JSON.stringify([...selectedIds])
|
|
1809
|
-
);
|
|
1810
|
-
},
|
|
1811
|
-
[selectedIds, onSelectionChange]
|
|
1812
|
-
);
|
|
1813
|
-
const handleDragOver = useCallback(
|
|
1814
|
-
(e, item) => {
|
|
1815
|
-
if (item.type === FileType.FOLDER && !selectedIds.has(item.id)) {
|
|
1816
|
-
setDragOverId(item.id);
|
|
1817
|
-
}
|
|
1818
|
-
},
|
|
1819
|
-
[selectedIds]
|
|
1820
|
-
);
|
|
1821
|
-
const handleDragLeave = useCallback(() => {
|
|
1822
|
-
setDragOverId(null);
|
|
1823
|
-
}, []);
|
|
1824
|
-
const handleDrop = useCallback(
|
|
1825
|
-
(e, targetItem) => {
|
|
1826
|
-
setDragOverId(null);
|
|
1827
|
-
if (targetItem.type !== FileType.FOLDER) return;
|
|
1828
|
-
const data = e.dataTransfer.getData("text/plain");
|
|
1829
|
-
if (!data) return;
|
|
1830
|
-
try {
|
|
1831
|
-
const draggedIds = JSON.parse(data);
|
|
1832
|
-
if (draggedIds.includes(targetItem.id)) return;
|
|
1833
|
-
onMove?.(draggedIds, targetItem.id);
|
|
1834
|
-
clearSelection();
|
|
1835
|
-
} catch (error) {
|
|
1836
|
-
console.error("\u62D6\u62FD\u89E3\u6790\u5931\u8D25:", error);
|
|
1837
|
-
}
|
|
1838
|
-
},
|
|
1839
|
-
[onMove, clearSelection]
|
|
1840
|
-
);
|
|
1841
|
-
const startRename = useCallback((id) => {
|
|
1842
|
-
setEditingId(id);
|
|
1843
|
-
}, []);
|
|
1844
|
-
const selectAll = useCallback(() => {
|
|
1845
|
-
const newSet = new Set(items.map((i) => i.id));
|
|
1846
|
-
setSelectedIds(newSet);
|
|
1847
|
-
onSelectionChange?.(newSet, items);
|
|
1848
|
-
}, [items, onSelectionChange]);
|
|
1849
|
-
useImperativeHandle(
|
|
1850
|
-
ref,
|
|
1851
|
-
() => ({
|
|
1852
|
-
clearSelection,
|
|
1853
|
-
startRename,
|
|
1854
|
-
selectAll,
|
|
1855
|
-
selectedIds,
|
|
1856
|
-
selectedItems
|
|
1857
|
-
}),
|
|
1858
|
-
[selectedIds, selectedItems, clearSelection, startRename, selectAll]
|
|
1859
|
-
);
|
|
1860
|
-
return /* @__PURE__ */ jsxs3(
|
|
1861
|
-
"div",
|
|
1862
|
-
{
|
|
1863
|
-
className: "file-list-view",
|
|
1864
|
-
onClick: handleEmptyClick,
|
|
1865
|
-
onContextMenu: (e) => {
|
|
1866
|
-
e.preventDefault();
|
|
1867
|
-
handleEmptyContextMenu(e);
|
|
1868
|
-
},
|
|
1869
|
-
children: [
|
|
1870
|
-
loading && /* @__PURE__ */ jsxs3("div", { className: "file-list-view-loading", children: [
|
|
1871
|
-
/* @__PURE__ */ jsx5("div", { className: "file-list-view-spinner" }),
|
|
1872
|
-
/* @__PURE__ */ jsx5("p", { children: "\u52A0\u8F7D\u4E2D..." })
|
|
1873
|
-
] }),
|
|
1874
|
-
!loading && items.length === 0 && /* @__PURE__ */ jsxs3("div", { className: "file-list-view-empty", children: [
|
|
1875
|
-
/* @__PURE__ */ jsx5(Icon3, { icon: "lucide:folder-open", width: 64, height: 64, className: "file-list-view-empty-icon" }),
|
|
1876
|
-
/* @__PURE__ */ jsx5("p", { children: "\u6587\u4EF6\u5939\u4E3A\u7A7A" })
|
|
1877
|
-
] }),
|
|
1878
|
-
!loading && items.length > 0 && viewMode === "grid" && /* @__PURE__ */ jsx5(
|
|
1879
|
-
FileGrid,
|
|
1880
|
-
{
|
|
1881
|
-
items,
|
|
1882
|
-
selectedIds,
|
|
1883
|
-
editingId,
|
|
1884
|
-
dragOverId,
|
|
1885
|
-
getAppIconUrl,
|
|
1886
|
-
onSelect: handleSelect,
|
|
1887
|
-
onOpen: handleOpen,
|
|
1888
|
-
onContextMenu: handleContextMenu,
|
|
1889
|
-
onContextMenuEmpty: handleEmptyContextMenuFromChild,
|
|
1890
|
-
onNameClick: handleNameClick,
|
|
1891
|
-
onRename: handleRename,
|
|
1892
|
-
onRenameCancel: handleRenameCancel,
|
|
1893
|
-
onDragStart: handleDragStart,
|
|
1894
|
-
onDragOver: handleDragOver,
|
|
1895
|
-
onDragLeave: handleDragLeave,
|
|
1896
|
-
onDrop: handleDrop
|
|
1897
|
-
}
|
|
1898
|
-
),
|
|
1899
|
-
!loading && items.length > 0 && viewMode === "list" && /* @__PURE__ */ jsx5(
|
|
1900
|
-
FileList,
|
|
1901
|
-
{
|
|
1902
|
-
items,
|
|
1903
|
-
selectedIds,
|
|
1904
|
-
editingId,
|
|
1905
|
-
dragOverId,
|
|
1906
|
-
sortConfig,
|
|
1907
|
-
onSelect: handleSelect,
|
|
1908
|
-
onOpen: handleOpen,
|
|
1909
|
-
onContextMenu: handleContextMenu,
|
|
1910
|
-
onContextMenuEmpty: handleEmptyContextMenuFromChild,
|
|
1911
|
-
onNameClick: handleNameClick,
|
|
1912
|
-
onRename: handleRename,
|
|
1913
|
-
onRenameCancel: handleRenameCancel,
|
|
1914
|
-
onSort: handleSort,
|
|
1915
|
-
onDragStart: handleDragStart,
|
|
1916
|
-
onDragOver: handleDragOver,
|
|
1917
|
-
onDragLeave: handleDragLeave,
|
|
1918
|
-
onDrop: handleDrop
|
|
1919
|
-
}
|
|
1920
|
-
)
|
|
1921
|
-
]
|
|
1922
|
-
}
|
|
1923
|
-
);
|
|
1924
|
-
}
|
|
1925
|
-
);
|
|
1926
|
-
FileListView.displayName = "FileListView";
|
|
1927
|
-
|
|
1928
|
-
// src/components/FileSidebar.tsx
|
|
1929
|
-
import { Icon as Icon4 } from "@iconify/react";
|
|
1930
|
-
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1931
|
-
function FileSidebar({ sections, activeId, onNavigate }) {
|
|
1932
|
-
const handleNavigate = (item) => {
|
|
1933
|
-
onNavigate?.(item);
|
|
1934
|
-
};
|
|
1935
|
-
const getIconName = (iconName) => {
|
|
1936
|
-
if (!iconName) return "mdi:folder";
|
|
1937
|
-
if (iconName.includes(":")) return iconName;
|
|
1938
|
-
return `lucide:${iconName.toLowerCase()}`;
|
|
1939
|
-
};
|
|
1940
|
-
return /* @__PURE__ */ jsx6("div", { className: "file-sidebar", children: sections.map((section) => /* @__PURE__ */ jsxs4("div", { className: "file-sidebar-section", children: [
|
|
1941
|
-
/* @__PURE__ */ jsx6("div", { className: "file-sidebar-section-title", children: section.title }),
|
|
1942
|
-
/* @__PURE__ */ jsx6("ul", { className: "file-sidebar-list", children: section.items.map((item) => {
|
|
1943
|
-
const isActive = activeId === item.id;
|
|
1944
|
-
return /* @__PURE__ */ jsxs4(
|
|
1945
|
-
"li",
|
|
1946
|
-
{
|
|
1947
|
-
onClick: () => handleNavigate(item),
|
|
1948
|
-
className: `file-sidebar-item ${isActive ? "file-sidebar-item--active" : ""}`,
|
|
1949
|
-
children: [
|
|
1950
|
-
/* @__PURE__ */ jsx6(
|
|
1951
|
-
Icon4,
|
|
1952
|
-
{
|
|
1953
|
-
icon: getIconName(item.icon),
|
|
1954
|
-
width: 18,
|
|
1955
|
-
height: 18,
|
|
1956
|
-
className: isActive ? "file-sidebar-item-icon--active" : "file-sidebar-item-icon"
|
|
1957
|
-
}
|
|
1958
|
-
),
|
|
1959
|
-
/* @__PURE__ */ jsx6("span", { children: item.label })
|
|
1960
|
-
]
|
|
1961
|
-
},
|
|
1962
|
-
item.id
|
|
1963
|
-
);
|
|
1964
|
-
}) })
|
|
1965
|
-
] }, section.id)) });
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
// src/components/Toolbar.tsx
|
|
1969
|
-
import { Icon as Icon6 } from "@iconify/react";
|
|
1970
|
-
|
|
1971
|
-
// src/components/Breadcrumb.tsx
|
|
1972
|
-
import { Icon as Icon5 } from "@iconify/react";
|
|
1973
|
-
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1974
|
-
function Breadcrumb({ items, onNavigate }) {
|
|
1975
|
-
const handleClick = (item, index) => {
|
|
1976
|
-
if (index < items.length - 1) {
|
|
1977
|
-
onNavigate?.(item, index);
|
|
1978
|
-
}
|
|
1979
|
-
};
|
|
1980
|
-
return /* @__PURE__ */ jsx7("div", { className: "file-breadcrumb", children: items.map((item, index) => /* @__PURE__ */ jsxs5("span", { className: "file-breadcrumb-item", children: [
|
|
1981
|
-
/* @__PURE__ */ jsx7(
|
|
1982
|
-
"span",
|
|
1983
|
-
{
|
|
1984
|
-
onClick: () => handleClick(item, index),
|
|
1985
|
-
className: `file-breadcrumb-link ${index === items.length - 1 ? "file-breadcrumb-link--current" : ""}`,
|
|
1986
|
-
children: item.name
|
|
1987
|
-
}
|
|
1988
|
-
),
|
|
1989
|
-
index < items.length - 1 && /* @__PURE__ */ jsx7(Icon5, { icon: "lucide:chevron-right", width: 14, height: 14, className: "file-breadcrumb-separator" })
|
|
1990
|
-
] }, item.id)) });
|
|
1991
|
-
}
|
|
1992
|
-
|
|
1993
|
-
// src/components/Toolbar.tsx
|
|
1994
|
-
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1995
|
-
function Toolbar({
|
|
1996
|
-
canGoBack = false,
|
|
1997
|
-
canGoForward = false,
|
|
1998
|
-
breadcrumbs = [],
|
|
1999
|
-
viewMode = "grid",
|
|
2000
|
-
searchQuery = "",
|
|
2001
|
-
showSearch = false,
|
|
2002
|
-
showViewToggle = true,
|
|
2003
|
-
draggable = false,
|
|
2004
|
-
onBack,
|
|
2005
|
-
onForward,
|
|
2006
|
-
onBreadcrumbNavigate,
|
|
2007
|
-
onViewModeChange,
|
|
2008
|
-
onSearchQueryChange,
|
|
2009
|
-
children,
|
|
2010
|
-
breadcrumbSlot,
|
|
2011
|
-
actionsSlot
|
|
2012
|
-
}) {
|
|
2013
|
-
return /* @__PURE__ */ jsxs6(
|
|
2014
|
-
"div",
|
|
2015
|
-
{
|
|
2016
|
-
className: `file-toolbar ${draggable ? "file-toolbar--draggable" : ""}`,
|
|
2017
|
-
children: [
|
|
2018
|
-
/* @__PURE__ */ jsxs6("div", { className: "file-toolbar-nav", children: [
|
|
2019
|
-
/* @__PURE__ */ jsx8(
|
|
2020
|
-
"button",
|
|
2021
|
-
{
|
|
2022
|
-
className: "file-toolbar-button",
|
|
2023
|
-
onClick: onBack,
|
|
2024
|
-
disabled: !canGoBack,
|
|
2025
|
-
title: "\u540E\u9000",
|
|
2026
|
-
children: /* @__PURE__ */ jsx8(Icon6, { icon: "lucide:chevron-left", width: 18, height: 18 })
|
|
2027
|
-
}
|
|
2028
|
-
),
|
|
2029
|
-
/* @__PURE__ */ jsx8(
|
|
2030
|
-
"button",
|
|
2031
|
-
{
|
|
2032
|
-
className: "file-toolbar-button",
|
|
2033
|
-
onClick: onForward,
|
|
2034
|
-
disabled: !canGoForward,
|
|
2035
|
-
title: "\u524D\u8FDB",
|
|
2036
|
-
children: /* @__PURE__ */ jsx8(Icon6, { icon: "lucide:chevron-right", width: 18, height: 18 })
|
|
2037
|
-
}
|
|
2038
|
-
)
|
|
2039
|
-
] }),
|
|
2040
|
-
/* @__PURE__ */ jsx8("div", { className: "file-toolbar-breadcrumb", children: breadcrumbSlot || breadcrumbs.length > 0 && /* @__PURE__ */ jsx8(
|
|
2041
|
-
Breadcrumb,
|
|
2042
|
-
{
|
|
2043
|
-
items: breadcrumbs,
|
|
2044
|
-
onNavigate: onBreadcrumbNavigate
|
|
2045
|
-
}
|
|
2046
|
-
) }),
|
|
2047
|
-
children && /* @__PURE__ */ jsx8("div", { className: "file-toolbar-custom", children }),
|
|
2048
|
-
/* @__PURE__ */ jsxs6("div", { className: "file-toolbar-actions", children: [
|
|
2049
|
-
showSearch && /* @__PURE__ */ jsxs6("div", { className: "file-toolbar-search", children: [
|
|
2050
|
-
/* @__PURE__ */ jsx8(Icon6, { icon: "lucide:search", width: 16, height: 16, className: "file-toolbar-search-icon" }),
|
|
2051
|
-
/* @__PURE__ */ jsx8(
|
|
2052
|
-
"input",
|
|
2053
|
-
{
|
|
2054
|
-
type: "text",
|
|
2055
|
-
value: searchQuery,
|
|
2056
|
-
onChange: (e) => onSearchQueryChange?.(e.target.value),
|
|
2057
|
-
placeholder: "\u641C\u7D22",
|
|
2058
|
-
className: "file-toolbar-search-input"
|
|
2059
|
-
}
|
|
2060
|
-
)
|
|
2061
|
-
] }),
|
|
2062
|
-
showViewToggle && /* @__PURE__ */ jsxs6("div", { className: "file-toolbar-view-toggle", children: [
|
|
2063
|
-
/* @__PURE__ */ jsx8(
|
|
2064
|
-
"button",
|
|
2065
|
-
{
|
|
2066
|
-
onClick: () => onViewModeChange?.("grid"),
|
|
2067
|
-
className: `file-toolbar-button ${viewMode === "grid" ? "file-toolbar-button--active" : ""}`,
|
|
2068
|
-
title: "\u7F51\u683C\u89C6\u56FE",
|
|
2069
|
-
children: /* @__PURE__ */ jsx8(Icon6, { icon: "lucide:layout-grid", width: 18, height: 18 })
|
|
2070
|
-
}
|
|
2071
|
-
),
|
|
2072
|
-
/* @__PURE__ */ jsx8(
|
|
2073
|
-
"button",
|
|
2074
|
-
{
|
|
2075
|
-
onClick: () => onViewModeChange?.("list"),
|
|
2076
|
-
className: `file-toolbar-button ${viewMode === "list" ? "file-toolbar-button--active" : ""}`,
|
|
2077
|
-
title: "\u5217\u8868\u89C6\u56FE",
|
|
2078
|
-
children: /* @__PURE__ */ jsx8(Icon6, { icon: "lucide:list", width: 18, height: 18 })
|
|
2079
|
-
}
|
|
2080
|
-
)
|
|
2081
|
-
] }),
|
|
2082
|
-
actionsSlot
|
|
2083
|
-
] })
|
|
2084
|
-
]
|
|
2085
|
-
}
|
|
2086
|
-
);
|
|
2087
|
-
}
|
|
2088
|
-
|
|
2089
|
-
// src/components/StatusBar.tsx
|
|
2090
|
-
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2091
|
-
function StatusBar({ itemCount = 0, selectedCount = 0, children }) {
|
|
2092
|
-
return /* @__PURE__ */ jsx9("div", { className: "file-status-bar", children: children || /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2093
|
-
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2094
|
-
itemCount,
|
|
2095
|
-
" \u4E2A\u9879\u76EE"
|
|
2096
|
-
] }),
|
|
2097
|
-
selectedCount > 0 && /* @__PURE__ */ jsxs7("span", { children: [
|
|
2098
|
-
" \u2022 \u5DF2\u9009\u62E9 ",
|
|
2099
|
-
selectedCount,
|
|
2100
|
-
" \u4E2A"
|
|
2101
|
-
] })
|
|
2102
|
-
] }) });
|
|
2103
|
-
}
|
|
2104
|
-
|
|
2105
|
-
// src/components/ContextMenu.tsx
|
|
2106
|
-
import { createPortal } from "react-dom";
|
|
2107
|
-
import { useMemo as useMemo3, useEffect, useRef as useRef3, useCallback as useCallback2, useState as useState2 } from "react";
|
|
2108
|
-
import { Icon as Icon7 } from "@iconify/react";
|
|
2109
|
-
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2110
|
-
var MARGIN = 8;
|
|
2111
|
-
var MENU_WIDTH = 220;
|
|
2112
|
-
var MENU_ITEM_HEIGHT = 32;
|
|
2113
|
-
var SEPARATOR_HEIGHT = 9;
|
|
2114
|
-
var MENU_PADDING = 8;
|
|
2115
|
-
var SUBMENU_GAP = 0;
|
|
2116
|
-
function estimateMenuHeight(items) {
|
|
2117
|
-
let height = MENU_PADDING;
|
|
2118
|
-
for (const item of items) {
|
|
2119
|
-
height += item.separator ? SEPARATOR_HEIGHT : MENU_ITEM_HEIGHT;
|
|
2120
|
-
}
|
|
2121
|
-
return height;
|
|
2122
|
-
}
|
|
2123
|
-
function calculateMenuPosition(clickX, clickY, menuHeight) {
|
|
2124
|
-
const viewportWidth = window.innerWidth;
|
|
2125
|
-
const viewportHeight = window.innerHeight;
|
|
2126
|
-
let adjustedX = clickX;
|
|
2127
|
-
let adjustedY = clickY;
|
|
2128
|
-
const spaceRight = viewportWidth - clickX;
|
|
2129
|
-
const spaceLeft = clickX;
|
|
2130
|
-
if (spaceRight < MENU_WIDTH + MARGIN) {
|
|
2131
|
-
if (spaceLeft >= MENU_WIDTH + MARGIN) {
|
|
2132
|
-
adjustedX = clickX - MENU_WIDTH;
|
|
2133
|
-
} else {
|
|
2134
|
-
if (spaceRight > spaceLeft) {
|
|
2135
|
-
adjustedX = viewportWidth - MENU_WIDTH - MARGIN;
|
|
2136
|
-
} else {
|
|
2137
|
-
adjustedX = MARGIN;
|
|
2138
|
-
}
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
const spaceBottom = viewportHeight - clickY;
|
|
2142
|
-
const spaceTop = clickY;
|
|
2143
|
-
if (spaceBottom < menuHeight + MARGIN) {
|
|
2144
|
-
if (spaceTop >= menuHeight + MARGIN) {
|
|
2145
|
-
adjustedY = clickY - menuHeight;
|
|
2146
|
-
} else {
|
|
2147
|
-
if (spaceBottom > spaceTop) {
|
|
2148
|
-
adjustedY = viewportHeight - menuHeight - MARGIN;
|
|
2149
|
-
} else {
|
|
2150
|
-
adjustedY = MARGIN;
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
}
|
|
2154
|
-
adjustedX = Math.max(MARGIN, Math.min(adjustedX, viewportWidth - MENU_WIDTH - MARGIN));
|
|
2155
|
-
adjustedY = Math.max(MARGIN, Math.min(adjustedY, viewportHeight - menuHeight - MARGIN));
|
|
2156
|
-
return { x: adjustedX, y: adjustedY };
|
|
2157
|
-
}
|
|
2158
|
-
function calculateSubmenuPosition(parentRect, submenuHeight) {
|
|
2159
|
-
const viewportWidth = window.innerWidth;
|
|
2160
|
-
const viewportHeight = window.innerHeight;
|
|
2161
|
-
const spaceRight = viewportWidth - parentRect.right;
|
|
2162
|
-
const spaceLeft = parentRect.left;
|
|
2163
|
-
let submenuX;
|
|
2164
|
-
let submenuY;
|
|
2165
|
-
if (spaceRight >= MENU_WIDTH + SUBMENU_GAP + MARGIN) {
|
|
2166
|
-
submenuX = parentRect.right + SUBMENU_GAP;
|
|
2167
|
-
} else if (spaceLeft >= MENU_WIDTH + SUBMENU_GAP + MARGIN) {
|
|
2168
|
-
submenuX = parentRect.left - MENU_WIDTH - SUBMENU_GAP;
|
|
2169
|
-
} else {
|
|
2170
|
-
if (spaceRight > spaceLeft) {
|
|
2171
|
-
submenuX = viewportWidth - MENU_WIDTH - MARGIN;
|
|
2172
|
-
} else {
|
|
2173
|
-
submenuX = MARGIN;
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
submenuY = parentRect.top;
|
|
2177
|
-
if (submenuY + submenuHeight > viewportHeight - MARGIN) {
|
|
2178
|
-
submenuY = viewportHeight - submenuHeight - MARGIN;
|
|
2179
|
-
}
|
|
2180
|
-
if (submenuY < MARGIN) {
|
|
2181
|
-
submenuY = MARGIN;
|
|
2182
|
-
}
|
|
2183
|
-
return { x: submenuX, y: submenuY };
|
|
2184
|
-
}
|
|
2185
|
-
function ContextMenu({
|
|
2186
|
-
visible,
|
|
2187
|
-
x,
|
|
2188
|
-
y,
|
|
2189
|
-
options,
|
|
2190
|
-
onClose,
|
|
2191
|
-
onSelect
|
|
2192
|
-
}) {
|
|
2193
|
-
const menuRef = useRef3(null);
|
|
2194
|
-
const [hoveredItemId, setHoveredItemId] = useState2(null);
|
|
2195
|
-
const [submenuPosition, setSubmenuPosition] = useState2(null);
|
|
2196
|
-
const itemRefs = useRef3(/* @__PURE__ */ new Map());
|
|
2197
|
-
const position = useMemo3(() => {
|
|
2198
|
-
const estimatedHeight = estimateMenuHeight(options);
|
|
2199
|
-
return calculateMenuPosition(x, y, estimatedHeight);
|
|
2200
|
-
}, [x, y, options]);
|
|
2201
|
-
const menuStyle = useMemo3(
|
|
2202
|
-
() => ({
|
|
2203
|
-
left: `${position.x}px`,
|
|
2204
|
-
top: `${position.y}px`
|
|
2205
|
-
}),
|
|
2206
|
-
[position]
|
|
2207
|
-
);
|
|
2208
|
-
const hoveredItem = useMemo3(() => {
|
|
2209
|
-
if (!hoveredItemId) return null;
|
|
2210
|
-
return options.find((opt) => opt.id === hoveredItemId && opt.children && opt.children.length > 0);
|
|
2211
|
-
}, [hoveredItemId, options]);
|
|
2212
|
-
useEffect(() => {
|
|
2213
|
-
if (!hoveredItemId || !hoveredItem) {
|
|
2214
|
-
setSubmenuPosition(null);
|
|
2215
|
-
return;
|
|
2216
|
-
}
|
|
2217
|
-
const itemEl = itemRefs.current.get(hoveredItemId);
|
|
2218
|
-
if (!itemEl) {
|
|
2219
|
-
setSubmenuPosition(null);
|
|
2220
|
-
return;
|
|
2221
|
-
}
|
|
2222
|
-
const rect = itemEl.getBoundingClientRect();
|
|
2223
|
-
const submenuHeight = estimateMenuHeight(hoveredItem.children || []);
|
|
2224
|
-
const pos = calculateSubmenuPosition(rect, submenuHeight);
|
|
2225
|
-
setSubmenuPosition(pos);
|
|
2226
|
-
}, [hoveredItemId, hoveredItem]);
|
|
2227
|
-
useEffect(() => {
|
|
2228
|
-
if (!visible) return;
|
|
2229
|
-
const handleClickOutside = (e) => {
|
|
2230
|
-
const target = e.target;
|
|
2231
|
-
const menuContainer = document.querySelector(".context-menu-container");
|
|
2232
|
-
if (menuContainer && menuContainer.contains(target)) {
|
|
2233
|
-
return;
|
|
2234
|
-
}
|
|
2235
|
-
onClose?.();
|
|
2236
|
-
};
|
|
2237
|
-
const handleEscape = (e) => {
|
|
2238
|
-
if (e.key === "Escape") {
|
|
2239
|
-
onClose?.();
|
|
2240
|
-
}
|
|
2241
|
-
};
|
|
2242
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
2243
|
-
document.addEventListener("keydown", handleEscape);
|
|
2244
|
-
return () => {
|
|
2245
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
2246
|
-
document.removeEventListener("keydown", handleEscape);
|
|
2247
|
-
};
|
|
2248
|
-
}, [visible, onClose]);
|
|
2249
|
-
useEffect(() => {
|
|
2250
|
-
if (!visible) {
|
|
2251
|
-
setHoveredItemId(null);
|
|
2252
|
-
setSubmenuPosition(null);
|
|
2253
|
-
}
|
|
2254
|
-
}, [visible]);
|
|
2255
|
-
const renderIcon = (iconName) => {
|
|
2256
|
-
if (!iconName) return null;
|
|
2257
|
-
return /* @__PURE__ */ jsx10(Icon7, { icon: iconName, width: 16, height: 16, className: "context-menu-item-icon" });
|
|
2258
|
-
};
|
|
2259
|
-
const handleOptionClick = useCallback2(
|
|
2260
|
-
(option) => {
|
|
2261
|
-
if (option.disabled) return;
|
|
2262
|
-
if (option.children && option.children.length > 0) {
|
|
2263
|
-
return;
|
|
2264
|
-
}
|
|
2265
|
-
if (option.action) {
|
|
2266
|
-
option.action();
|
|
2267
|
-
}
|
|
2268
|
-
onSelect?.(option);
|
|
2269
|
-
onClose?.();
|
|
2270
|
-
},
|
|
2271
|
-
[onClose, onSelect]
|
|
2272
|
-
);
|
|
2273
|
-
const handleItemMouseEnter = useCallback2((option) => {
|
|
2274
|
-
if (option.children && option.children.length > 0) {
|
|
2275
|
-
setHoveredItemId(option.id);
|
|
2276
|
-
} else {
|
|
2277
|
-
setHoveredItemId(null);
|
|
2278
|
-
}
|
|
2279
|
-
}, []);
|
|
2280
|
-
if (!visible) return null;
|
|
2281
|
-
return createPortal(
|
|
2282
|
-
/* @__PURE__ */ jsxs8("div", { className: "context-menu-container", children: [
|
|
2283
|
-
/* @__PURE__ */ jsx10("div", { ref: menuRef, className: "context-menu", style: menuStyle, children: options.map((option, index) => {
|
|
2284
|
-
if (option.separator) {
|
|
2285
|
-
return /* @__PURE__ */ jsx10("div", { className: "context-menu-separator" }, index);
|
|
2286
|
-
}
|
|
2287
|
-
const hasChildren = option.children && option.children.length > 0;
|
|
2288
|
-
const isHovered = hoveredItemId === option.id;
|
|
2289
|
-
return /* @__PURE__ */ jsxs8(
|
|
2290
|
-
"div",
|
|
2291
|
-
{
|
|
2292
|
-
ref: (el) => {
|
|
2293
|
-
if (el) {
|
|
2294
|
-
itemRefs.current.set(option.id, el);
|
|
2295
|
-
} else {
|
|
2296
|
-
itemRefs.current.delete(option.id);
|
|
2297
|
-
}
|
|
2298
|
-
},
|
|
2299
|
-
className: `context-menu-item ${option.disabled ? "context-menu-item--disabled" : ""} ${option.danger ? "context-menu-item--danger" : ""} ${hasChildren ? "context-menu-item--has-children" : ""} ${isHovered ? "context-menu-item--active" : ""}`,
|
|
2300
|
-
onClick: () => handleOptionClick(option),
|
|
2301
|
-
onMouseEnter: () => handleItemMouseEnter(option),
|
|
2302
|
-
children: [
|
|
2303
|
-
option.icon && renderIcon(option.icon),
|
|
2304
|
-
/* @__PURE__ */ jsx10("span", { className: "context-menu-item-label", children: option.label }),
|
|
2305
|
-
option.checked && /* @__PURE__ */ jsx10(Icon7, { icon: "lucide:check", width: 14, height: 14, className: "context-menu-item-check" }),
|
|
2306
|
-
option.shortcut && !hasChildren && /* @__PURE__ */ jsx10("span", { className: "context-menu-item-shortcut", children: option.shortcut }),
|
|
2307
|
-
hasChildren && /* @__PURE__ */ jsx10(Icon7, { icon: "lucide:chevron-right", width: 14, height: 14, className: "context-menu-item-arrow" })
|
|
2308
|
-
]
|
|
2309
|
-
},
|
|
2310
|
-
option.id || index
|
|
2311
|
-
);
|
|
2312
|
-
}) }),
|
|
2313
|
-
hoveredItem && submenuPosition && /* @__PURE__ */ jsx10(
|
|
2314
|
-
"div",
|
|
2315
|
-
{
|
|
2316
|
-
className: "context-menu context-menu-submenu",
|
|
2317
|
-
style: {
|
|
2318
|
-
left: `${submenuPosition.x}px`,
|
|
2319
|
-
top: `${submenuPosition.y}px`
|
|
2320
|
-
},
|
|
2321
|
-
onMouseEnter: () => setHoveredItemId(hoveredItem.id),
|
|
2322
|
-
onMouseLeave: () => setHoveredItemId(null),
|
|
2323
|
-
children: hoveredItem.children.map((child, childIndex) => {
|
|
2324
|
-
if (child.separator) {
|
|
2325
|
-
return /* @__PURE__ */ jsx10("div", { className: "context-menu-separator" }, `child-sep-${childIndex}`);
|
|
2326
|
-
}
|
|
2327
|
-
return /* @__PURE__ */ jsxs8(
|
|
2328
|
-
"div",
|
|
2329
|
-
{
|
|
2330
|
-
className: `context-menu-item ${child.disabled ? "context-menu-item--disabled" : ""} ${child.danger ? "context-menu-item--danger" : ""}`,
|
|
2331
|
-
onClick: () => handleOptionClick(child),
|
|
2332
|
-
children: [
|
|
2333
|
-
child.icon && renderIcon(child.icon),
|
|
2334
|
-
/* @__PURE__ */ jsx10("span", { className: "context-menu-item-label", children: child.label }),
|
|
2335
|
-
child.checked && /* @__PURE__ */ jsx10(Icon7, { icon: "lucide:check", width: 14, height: 14, className: "context-menu-item-check" }),
|
|
2336
|
-
child.shortcut && /* @__PURE__ */ jsx10("span", { className: "context-menu-item-shortcut", children: child.shortcut })
|
|
2337
|
-
]
|
|
2338
|
-
},
|
|
2339
|
-
child.id || childIndex
|
|
2340
|
-
);
|
|
2341
|
-
})
|
|
2342
|
-
}
|
|
2343
|
-
)
|
|
2344
|
-
] }),
|
|
2345
|
-
document.body
|
|
2346
|
-
);
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2349
|
-
// src/components/Window.tsx
|
|
2350
|
-
import { createPortal as createPortal2 } from "react-dom";
|
|
2351
|
-
import { useMemo as useMemo4, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
2352
|
-
import { Icon as Icon8 } from "@iconify/react";
|
|
2353
|
-
|
|
2354
|
-
// src/hooks/useWindowDrag.ts
|
|
2355
|
-
import { useState as useState3, useCallback as useCallback3, useEffect as useEffect2 } from "react";
|
|
2356
|
-
function useWindowDrag() {
|
|
2357
|
-
const [position, setPosition] = useState3({ x: 0, y: 0 });
|
|
2358
|
-
const [isDragging, setIsDragging] = useState3(false);
|
|
2359
|
-
const handleMouseMove = useCallback3((e) => {
|
|
2360
|
-
if (!isDragging) return;
|
|
2361
|
-
setPosition((prev) => ({
|
|
2362
|
-
x: prev.x + e.movementX,
|
|
2363
|
-
y: prev.y + e.movementY
|
|
2364
|
-
}));
|
|
2365
|
-
}, [isDragging]);
|
|
2366
|
-
const handleMouseUp = useCallback3(() => {
|
|
2367
|
-
setIsDragging(false);
|
|
2368
|
-
}, []);
|
|
2369
|
-
const startDrag = useCallback3((e) => {
|
|
2370
|
-
const target = e.target;
|
|
2371
|
-
if (target.closest(".draggable-area") && !target.closest("button")) {
|
|
2372
|
-
e.preventDefault();
|
|
2373
|
-
setIsDragging(true);
|
|
2374
|
-
}
|
|
2375
|
-
}, []);
|
|
2376
|
-
useEffect2(() => {
|
|
2377
|
-
if (isDragging) {
|
|
2378
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
2379
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
2380
|
-
return () => {
|
|
2381
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
2382
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
2383
|
-
};
|
|
2384
|
-
}
|
|
2385
|
-
}, [isDragging, handleMouseMove, handleMouseUp]);
|
|
2386
|
-
return {
|
|
2387
|
-
position,
|
|
2388
|
-
isDragging,
|
|
2389
|
-
startDrag
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
// src/hooks/useWindowResize.ts
|
|
2394
|
-
import { useState as useState4, useCallback as useCallback4, useEffect as useEffect3 } from "react";
|
|
2395
|
-
function useWindowResize(initialWidth, initialHeight, minWidth, minHeight, maxWidth, maxHeight) {
|
|
2396
|
-
const [width, setWidth] = useState4(initialWidth);
|
|
2397
|
-
const [height, setHeight] = useState4(initialHeight);
|
|
2398
|
-
const [isResizing, setIsResizing] = useState4(false);
|
|
2399
|
-
const [resizeDirection, setResizeDirection] = useState4(null);
|
|
2400
|
-
const [startX, setStartX] = useState4(0);
|
|
2401
|
-
const [startY, setStartY] = useState4(0);
|
|
2402
|
-
const [startWidth, setStartWidth] = useState4(0);
|
|
2403
|
-
const [startHeight, setStartHeight] = useState4(0);
|
|
2404
|
-
const handleMouseMove = useCallback4((e) => {
|
|
2405
|
-
if (!isResizing || !resizeDirection) return;
|
|
2406
|
-
const deltaX = e.clientX - startX;
|
|
2407
|
-
const deltaY = e.clientY - startY;
|
|
2408
|
-
let newWidth = startWidth;
|
|
2409
|
-
let newHeight = startHeight;
|
|
2410
|
-
const direction = resizeDirection;
|
|
2411
|
-
if (direction.includes("e")) {
|
|
2412
|
-
newWidth = Math.min(Math.max(startWidth + deltaX, minWidth), maxWidth);
|
|
2413
|
-
} else if (direction.includes("w")) {
|
|
2414
|
-
newWidth = Math.min(Math.max(startWidth - deltaX, minWidth), maxWidth);
|
|
2415
|
-
}
|
|
2416
|
-
if (direction.includes("s")) {
|
|
2417
|
-
newHeight = Math.min(Math.max(startHeight + deltaY, minHeight), maxHeight);
|
|
2418
|
-
} else if (direction.includes("n")) {
|
|
2419
|
-
newHeight = Math.min(Math.max(startHeight - deltaY, minHeight), maxHeight);
|
|
2420
|
-
}
|
|
2421
|
-
setWidth(newWidth);
|
|
2422
|
-
setHeight(newHeight);
|
|
2423
|
-
}, [isResizing, resizeDirection, startX, startY, startWidth, startHeight, minWidth, minHeight, maxWidth, maxHeight]);
|
|
2424
|
-
const handleMouseUp = useCallback4(() => {
|
|
2425
|
-
setIsResizing(false);
|
|
2426
|
-
setResizeDirection(null);
|
|
2427
|
-
}, []);
|
|
2428
|
-
const startResize = useCallback4((e, direction, currentWidth, currentHeight) => {
|
|
2429
|
-
e.preventDefault();
|
|
2430
|
-
e.stopPropagation();
|
|
2431
|
-
setIsResizing(true);
|
|
2432
|
-
setResizeDirection(direction);
|
|
2433
|
-
setStartX(e.clientX);
|
|
2434
|
-
setStartY(e.clientY);
|
|
2435
|
-
setStartWidth(currentWidth);
|
|
2436
|
-
setStartHeight(currentHeight);
|
|
2437
|
-
}, []);
|
|
2438
|
-
const getCursorForDirection = useCallback4((direction) => {
|
|
2439
|
-
const cursors = {
|
|
2440
|
-
n: "n-resize",
|
|
2441
|
-
s: "s-resize",
|
|
2442
|
-
e: "e-resize",
|
|
2443
|
-
w: "w-resize",
|
|
2444
|
-
ne: "ne-resize",
|
|
2445
|
-
nw: "nw-resize",
|
|
2446
|
-
se: "se-resize",
|
|
2447
|
-
sw: "sw-resize"
|
|
2448
|
-
};
|
|
2449
|
-
return cursors[direction];
|
|
2450
|
-
}, []);
|
|
2451
|
-
useEffect3(() => {
|
|
2452
|
-
if (isResizing) {
|
|
2453
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
2454
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
2455
|
-
document.body.style.cursor = getCursorForDirection(resizeDirection || "se");
|
|
2456
|
-
document.body.style.userSelect = "none";
|
|
2457
|
-
return () => {
|
|
2458
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
2459
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
2460
|
-
document.body.style.cursor = "";
|
|
2461
|
-
document.body.style.userSelect = "";
|
|
2462
|
-
};
|
|
2463
|
-
}
|
|
2464
|
-
}, [isResizing, resizeDirection, handleMouseMove, handleMouseUp, getCursorForDirection]);
|
|
2465
|
-
return {
|
|
2466
|
-
width,
|
|
2467
|
-
height,
|
|
2468
|
-
isResizing,
|
|
2469
|
-
startResize
|
|
2470
|
-
};
|
|
2471
|
-
}
|
|
2472
|
-
|
|
2473
|
-
// src/components/Window.tsx
|
|
2474
|
-
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2475
|
-
function Window({
|
|
2476
|
-
title,
|
|
2477
|
-
showTitleBar = true,
|
|
2478
|
-
showMinimize = false,
|
|
2479
|
-
showMaximize = false,
|
|
2480
|
-
draggable = true,
|
|
2481
|
-
resizable = true,
|
|
2482
|
-
closeOnBackdrop = true,
|
|
2483
|
-
width = "auto",
|
|
2484
|
-
height = "auto",
|
|
2485
|
-
minWidth = 300,
|
|
2486
|
-
minHeight = 200,
|
|
2487
|
-
maxWidth = "80vw",
|
|
2488
|
-
maxHeight = "80vh",
|
|
2489
|
-
fitContent = false,
|
|
2490
|
-
onClose,
|
|
2491
|
-
onMinimize,
|
|
2492
|
-
onMaximize,
|
|
2493
|
-
children,
|
|
2494
|
-
titleSlot,
|
|
2495
|
-
actionsSlot
|
|
2496
|
-
}) {
|
|
2497
|
-
const windowContainerRef = useRef4(null);
|
|
2498
|
-
const windowDrag = draggable ? useWindowDrag() : null;
|
|
2499
|
-
const isAutoSize = useMemo4(() => {
|
|
2500
|
-
return fitContent || width === "auto" || width === "fit-content" || height === "auto" || height === "fit-content";
|
|
2501
|
-
}, [fitContent, width, height]);
|
|
2502
|
-
const getInitialSize = () => {
|
|
2503
|
-
if (isAutoSize) {
|
|
2504
|
-
return { initialWidth: 0, initialHeight: 0 };
|
|
2505
|
-
}
|
|
2506
|
-
const defaultWidth = 600;
|
|
2507
|
-
const defaultHeight = 500;
|
|
2508
|
-
let initialWidth2 = defaultWidth;
|
|
2509
|
-
let initialHeight2 = defaultHeight;
|
|
2510
|
-
if (width !== "auto" && width !== "fit-content") {
|
|
2511
|
-
initialWidth2 = typeof width === "number" ? width : parseInt(width);
|
|
2512
|
-
}
|
|
2513
|
-
if (height !== "auto" && height !== "fit-content") {
|
|
2514
|
-
initialHeight2 = typeof height === "number" ? height : parseInt(height);
|
|
2515
|
-
}
|
|
2516
|
-
return { initialWidth: initialWidth2, initialHeight: initialHeight2 };
|
|
2517
|
-
};
|
|
2518
|
-
const parseSize = (size, defaultPx) => {
|
|
2519
|
-
if (typeof size === "number") return size;
|
|
2520
|
-
if (typeof size === "string") {
|
|
2521
|
-
if (size.endsWith("px")) return parseInt(size);
|
|
2522
|
-
if (size.endsWith("vw"))
|
|
2523
|
-
return parseInt(size) / 100 * window.innerWidth;
|
|
2524
|
-
if (size.endsWith("vh"))
|
|
2525
|
-
return parseInt(size) / 100 * window.innerHeight;
|
|
2526
|
-
}
|
|
2527
|
-
return defaultPx;
|
|
2528
|
-
};
|
|
2529
|
-
const { initialWidth, initialHeight } = getInitialSize();
|
|
2530
|
-
const minW = parseSize(minWidth, 500);
|
|
2531
|
-
const minH = parseSize(minHeight, 350);
|
|
2532
|
-
const maxW = parseSize(maxWidth, window.innerWidth * 0.8);
|
|
2533
|
-
const maxH = parseSize(maxHeight, window.innerHeight * 0.8);
|
|
2534
|
-
const windowResize = resizable ? useWindowResize(initialWidth, initialHeight, minW, minH, maxW, maxH) : null;
|
|
2535
|
-
const windowStyle = useMemo4(() => {
|
|
2536
|
-
const baseStyle = {
|
|
2537
|
-
left: "50%",
|
|
2538
|
-
top: "50%"
|
|
2539
|
-
};
|
|
2540
|
-
let translateX = "-50%";
|
|
2541
|
-
let translateY = "-50%";
|
|
2542
|
-
if (draggable && windowDrag) {
|
|
2543
|
-
translateX = `calc(-50% + ${windowDrag.position.x}px)`;
|
|
2544
|
-
translateY = `calc(-50% + ${windowDrag.position.y}px)`;
|
|
2545
|
-
}
|
|
2546
|
-
baseStyle.transform = `translate(${translateX}, ${translateY})`;
|
|
2547
|
-
baseStyle.transformOrigin = "center center";
|
|
2548
|
-
if (isAutoSize) {
|
|
2549
|
-
if (resizable && windowResize && windowResize.width > 0) {
|
|
2550
|
-
baseStyle.width = `${windowResize.width}px`;
|
|
2551
|
-
baseStyle.height = `${windowResize.height}px`;
|
|
2552
|
-
}
|
|
2553
|
-
} else {
|
|
2554
|
-
if (resizable && windowResize) {
|
|
2555
|
-
baseStyle.width = `${windowResize.width}px`;
|
|
2556
|
-
baseStyle.height = `${windowResize.height}px`;
|
|
2557
|
-
} else {
|
|
2558
|
-
if (width !== "auto" && width !== "fit-content") {
|
|
2559
|
-
baseStyle.width = typeof width === "number" ? `${width}px` : width;
|
|
2560
|
-
}
|
|
2561
|
-
if (height !== "auto" && height !== "fit-content") {
|
|
2562
|
-
baseStyle.height = typeof height === "number" ? `${height}px` : height;
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
if (minWidth) {
|
|
2567
|
-
baseStyle.minWidth = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
|
|
2568
|
-
}
|
|
2569
|
-
if (minHeight) {
|
|
2570
|
-
baseStyle.minHeight = typeof minHeight === "number" ? `${minHeight}px` : minHeight;
|
|
2571
|
-
}
|
|
2572
|
-
if (maxWidth) {
|
|
2573
|
-
baseStyle.maxWidth = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
|
|
2574
|
-
}
|
|
2575
|
-
if (maxHeight) {
|
|
2576
|
-
baseStyle.maxHeight = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
|
|
2577
|
-
}
|
|
2578
|
-
return baseStyle;
|
|
2579
|
-
}, [
|
|
2580
|
-
draggable,
|
|
2581
|
-
windowDrag,
|
|
2582
|
-
isAutoSize,
|
|
2583
|
-
resizable,
|
|
2584
|
-
windowResize,
|
|
2585
|
-
width,
|
|
2586
|
-
height,
|
|
2587
|
-
minWidth,
|
|
2588
|
-
minHeight,
|
|
2589
|
-
maxWidth,
|
|
2590
|
-
maxHeight
|
|
2591
|
-
]);
|
|
2592
|
-
const handleBackdropClick = (e) => {
|
|
2593
|
-
if (closeOnBackdrop && e.target === e.currentTarget) {
|
|
2594
|
-
onClose?.();
|
|
2595
|
-
}
|
|
2596
|
-
};
|
|
2597
|
-
const handleDragStart = (e) => {
|
|
2598
|
-
if (draggable && windowDrag) {
|
|
2599
|
-
windowDrag.startDrag(e);
|
|
2600
|
-
}
|
|
2601
|
-
};
|
|
2602
|
-
const handleResizeStart = (e, direction) => {
|
|
2603
|
-
if (!resizable || !windowResize || !windowContainerRef.current) return;
|
|
2604
|
-
const rect = windowContainerRef.current.getBoundingClientRect();
|
|
2605
|
-
const currentWidth = rect.width;
|
|
2606
|
-
const currentHeight = rect.height;
|
|
2607
|
-
windowResize.startResize(e, direction, currentWidth, currentHeight);
|
|
2608
|
-
};
|
|
2609
|
-
useEffect4(() => {
|
|
2610
|
-
const handleEsc = (e) => {
|
|
2611
|
-
if (e.key === "Escape") {
|
|
2612
|
-
e.preventDefault();
|
|
2613
|
-
onClose?.();
|
|
2614
|
-
}
|
|
2615
|
-
};
|
|
2616
|
-
window.addEventListener("keydown", handleEsc);
|
|
2617
|
-
return () => {
|
|
2618
|
-
window.removeEventListener("keydown", handleEsc);
|
|
2619
|
-
};
|
|
2620
|
-
}, [onClose]);
|
|
2621
|
-
return createPortal2(
|
|
2622
|
-
/* @__PURE__ */ jsx11("div", { className: "window-overlay", onClick: handleBackdropClick, children: /* @__PURE__ */ jsxs9(
|
|
2623
|
-
"div",
|
|
2624
|
-
{
|
|
2625
|
-
ref: windowContainerRef,
|
|
2626
|
-
className: "window-container",
|
|
2627
|
-
style: windowStyle,
|
|
2628
|
-
onClick: (e) => e.stopPropagation(),
|
|
2629
|
-
children: [
|
|
2630
|
-
showTitleBar && /* @__PURE__ */ jsxs9(
|
|
2631
|
-
"div",
|
|
2632
|
-
{
|
|
2633
|
-
className: "window-title-bar draggable-area",
|
|
2634
|
-
onMouseDown: handleDragStart,
|
|
2635
|
-
children: [
|
|
2636
|
-
/* @__PURE__ */ jsxs9("div", { className: "window-controls", children: [
|
|
2637
|
-
/* @__PURE__ */ jsx11(
|
|
2638
|
-
"button",
|
|
2639
|
-
{
|
|
2640
|
-
onClick: (e) => {
|
|
2641
|
-
e.stopPropagation();
|
|
2642
|
-
onClose?.();
|
|
2643
|
-
},
|
|
2644
|
-
className: "window-control-button window-control-button--close",
|
|
2645
|
-
children: /* @__PURE__ */ jsx11(Icon8, { icon: "lucide:x", width: 7, height: 7, className: "window-control-icon" })
|
|
2646
|
-
}
|
|
2647
|
-
),
|
|
2648
|
-
showMinimize && /* @__PURE__ */ jsx11(
|
|
2649
|
-
"button",
|
|
2650
|
-
{
|
|
2651
|
-
onClick: (e) => {
|
|
2652
|
-
e.stopPropagation();
|
|
2653
|
-
onMinimize?.();
|
|
2654
|
-
},
|
|
2655
|
-
className: "window-control-button window-control-button--minimize",
|
|
2656
|
-
children: /* @__PURE__ */ jsx11(Icon8, { icon: "lucide:minus", width: 7, height: 7, className: "window-control-icon" })
|
|
2657
|
-
}
|
|
2658
|
-
),
|
|
2659
|
-
showMaximize && /* @__PURE__ */ jsx11(
|
|
2660
|
-
"button",
|
|
2661
|
-
{
|
|
2662
|
-
onClick: (e) => {
|
|
2663
|
-
e.stopPropagation();
|
|
2664
|
-
onMaximize?.();
|
|
2665
|
-
},
|
|
2666
|
-
className: "window-control-button window-control-button--maximize",
|
|
2667
|
-
children: /* @__PURE__ */ jsx11(Icon8, { icon: "lucide:maximize-2", width: 7, height: 7, className: "window-control-icon" })
|
|
2668
|
-
}
|
|
2669
|
-
)
|
|
2670
|
-
] }),
|
|
2671
|
-
/* @__PURE__ */ jsx11("div", { className: "window-title-info", children: titleSlot || /* @__PURE__ */ jsx11("span", { className: "window-title-text", children: title }) }),
|
|
2672
|
-
/* @__PURE__ */ jsx11("div", { className: "window-title-actions", children: actionsSlot })
|
|
2673
|
-
]
|
|
2674
|
-
}
|
|
2675
|
-
),
|
|
2676
|
-
/* @__PURE__ */ jsx11("div", { className: "window-content", children }),
|
|
2677
|
-
resizable && /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
2678
|
-
/* @__PURE__ */ jsx11(
|
|
2679
|
-
"div",
|
|
2680
|
-
{
|
|
2681
|
-
className: "window-resize-handle window-resize-handle--n",
|
|
2682
|
-
onMouseDown: (e) => handleResizeStart(e, "n")
|
|
2683
|
-
}
|
|
2684
|
-
),
|
|
2685
|
-
/* @__PURE__ */ jsx11(
|
|
2686
|
-
"div",
|
|
2687
|
-
{
|
|
2688
|
-
className: "window-resize-handle window-resize-handle--s",
|
|
2689
|
-
onMouseDown: (e) => handleResizeStart(e, "s")
|
|
2690
|
-
}
|
|
2691
|
-
),
|
|
2692
|
-
/* @__PURE__ */ jsx11(
|
|
2693
|
-
"div",
|
|
2694
|
-
{
|
|
2695
|
-
className: "window-resize-handle window-resize-handle--e",
|
|
2696
|
-
onMouseDown: (e) => handleResizeStart(e, "e")
|
|
2697
|
-
}
|
|
2698
|
-
),
|
|
2699
|
-
/* @__PURE__ */ jsx11(
|
|
2700
|
-
"div",
|
|
2701
|
-
{
|
|
2702
|
-
className: "window-resize-handle window-resize-handle--w",
|
|
2703
|
-
onMouseDown: (e) => handleResizeStart(e, "w")
|
|
2704
|
-
}
|
|
2705
|
-
),
|
|
2706
|
-
/* @__PURE__ */ jsx11(
|
|
2707
|
-
"div",
|
|
2708
|
-
{
|
|
2709
|
-
className: "window-resize-handle window-resize-handle--ne",
|
|
2710
|
-
onMouseDown: (e) => handleResizeStart(e, "ne")
|
|
2711
|
-
}
|
|
2712
|
-
),
|
|
2713
|
-
/* @__PURE__ */ jsx11(
|
|
2714
|
-
"div",
|
|
2715
|
-
{
|
|
2716
|
-
className: "window-resize-handle window-resize-handle--nw",
|
|
2717
|
-
onMouseDown: (e) => handleResizeStart(e, "nw")
|
|
2718
|
-
}
|
|
2719
|
-
),
|
|
2720
|
-
/* @__PURE__ */ jsx11(
|
|
2721
|
-
"div",
|
|
2722
|
-
{
|
|
2723
|
-
className: "window-resize-handle window-resize-handle--se",
|
|
2724
|
-
onMouseDown: (e) => handleResizeStart(e, "se")
|
|
2725
|
-
}
|
|
2726
|
-
),
|
|
2727
|
-
/* @__PURE__ */ jsx11(
|
|
2728
|
-
"div",
|
|
2729
|
-
{
|
|
2730
|
-
className: "window-resize-handle window-resize-handle--sw",
|
|
2731
|
-
onMouseDown: (e) => handleResizeStart(e, "sw")
|
|
2732
|
-
}
|
|
2733
|
-
)
|
|
2734
|
-
] })
|
|
2735
|
-
]
|
|
2736
|
-
}
|
|
2737
|
-
) }),
|
|
2738
|
-
document.body
|
|
2739
|
-
);
|
|
2740
|
-
}
|
|
2741
|
-
|
|
2742
|
-
// src/components/CompressDialog.tsx
|
|
2743
|
-
import { useState as useState6, useMemo as useMemo5, useEffect as useEffect5 } from "react";
|
|
2744
|
-
import { createPortal as createPortal3 } from "react-dom";
|
|
2745
|
-
import { Icon as Icon9 } from "@iconify/react";
|
|
2746
|
-
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2747
|
-
var FORMAT_OPTIONS = [
|
|
2748
|
-
{ value: "zip", label: "ZIP", ext: ".zip" },
|
|
2749
|
-
{ value: "tgz", label: "TAR.GZ (gzip)", ext: ".tar.gz" },
|
|
2750
|
-
{ value: "tarbz2", label: "TAR.BZ2 (bzip2)", ext: ".tar.bz2" },
|
|
2751
|
-
{ value: "tar", label: "TAR (\u65E0\u538B\u7F29)", ext: ".tar" }
|
|
2752
|
-
];
|
|
2753
|
-
var LEVEL_OPTIONS = [
|
|
2754
|
-
{ value: "fast", label: "\u5FEB\u901F", desc: "\u538B\u7F29\u901F\u5EA6\u5FEB\uFF0C\u6587\u4EF6\u8F83\u5927" },
|
|
2755
|
-
{ value: "normal", label: "\u6807\u51C6", desc: "\u5E73\u8861\u901F\u5EA6\u548C\u5927\u5C0F" },
|
|
2756
|
-
{ value: "best", label: "\u6700\u4F73", desc: "\u6587\u4EF6\u6700\u5C0F\uFF0C\u901F\u5EA6\u8F83\u6162" }
|
|
2757
|
-
];
|
|
2758
|
-
function CompressDialog({
|
|
2759
|
-
visible,
|
|
2760
|
-
filePaths,
|
|
2761
|
-
outputDir,
|
|
2762
|
-
onConfirm,
|
|
2763
|
-
onCancel
|
|
2764
|
-
}) {
|
|
2765
|
-
const [format, setFormat] = useState6("zip");
|
|
2766
|
-
const [level, setLevel] = useState6("normal");
|
|
2767
|
-
const [outputName, setOutputName] = useState6("");
|
|
2768
|
-
const [deleteSource, setDeleteSource] = useState6(false);
|
|
2769
|
-
const [password, setPassword] = useState6("");
|
|
2770
|
-
const [showPassword, setShowPassword] = useState6(false);
|
|
2771
|
-
const defaultOutputName = useMemo5(() => {
|
|
2772
|
-
if (filePaths.length === 0) return "archive";
|
|
2773
|
-
if (filePaths.length === 1) {
|
|
2774
|
-
const name = filePaths[0].split("/").pop() || "archive";
|
|
2775
|
-
return name.replace(/\.[^.]+$/, "");
|
|
2776
|
-
}
|
|
2777
|
-
return "\u538B\u7F29\u6587\u4EF6";
|
|
2778
|
-
}, [filePaths]);
|
|
2779
|
-
useEffect5(() => {
|
|
2780
|
-
if (visible) {
|
|
2781
|
-
setOutputName(defaultOutputName);
|
|
2782
|
-
setFormat("zip");
|
|
2783
|
-
setLevel("normal");
|
|
2784
|
-
setDeleteSource(false);
|
|
2785
|
-
setPassword("");
|
|
2786
|
-
}
|
|
2787
|
-
}, [visible, defaultOutputName]);
|
|
2788
|
-
const currentExt = FORMAT_OPTIONS.find((f) => f.value === format)?.ext || ".zip";
|
|
2789
|
-
const fullOutputPath = `${outputDir}/${outputName}${currentExt}`;
|
|
2790
|
-
const handleConfirm = () => {
|
|
2791
|
-
onConfirm({
|
|
2792
|
-
format,
|
|
2793
|
-
level,
|
|
2794
|
-
outputName: outputName + currentExt,
|
|
2795
|
-
deleteSource
|
|
2796
|
-
});
|
|
2797
|
-
};
|
|
2798
|
-
const supportsPassword = false;
|
|
2799
|
-
if (!visible) return null;
|
|
2800
|
-
return createPortal3(
|
|
2801
|
-
/* @__PURE__ */ jsx12("div", { className: "compress-dialog-overlay", onClick: onCancel, children: /* @__PURE__ */ jsxs10("div", { className: "compress-dialog", onClick: (e) => e.stopPropagation(), children: [
|
|
2802
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-header", children: [
|
|
2803
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-title", children: [
|
|
2804
|
-
/* @__PURE__ */ jsx12(Icon9, { icon: "lucide:archive", width: 20, height: 20 }),
|
|
2805
|
-
/* @__PURE__ */ jsx12("span", { children: "\u538B\u7F29\u6587\u4EF6" })
|
|
2806
|
-
] }),
|
|
2807
|
-
/* @__PURE__ */ jsx12("button", { className: "compress-dialog-close", onClick: onCancel, children: /* @__PURE__ */ jsx12(Icon9, { icon: "lucide:x", width: 18, height: 18 }) })
|
|
2808
|
-
] }),
|
|
2809
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-content", children: [
|
|
2810
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-info", children: [
|
|
2811
|
-
/* @__PURE__ */ jsx12(Icon9, { icon: "lucide:file-archive", width: 16, height: 16 }),
|
|
2812
|
-
/* @__PURE__ */ jsx12("span", { children: filePaths.length === 1 ? filePaths[0].split("/").pop() : `${filePaths.length} \u4E2A\u9879\u76EE` })
|
|
2813
|
-
] }),
|
|
2814
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-field", children: [
|
|
2815
|
-
/* @__PURE__ */ jsx12("label", { children: "\u6587\u4EF6\u540D" }),
|
|
2816
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-input-group", children: [
|
|
2817
|
-
/* @__PURE__ */ jsx12(
|
|
2818
|
-
"input",
|
|
2819
|
-
{
|
|
2820
|
-
type: "text",
|
|
2821
|
-
value: outputName,
|
|
2822
|
-
onChange: (e) => setOutputName(e.target.value),
|
|
2823
|
-
placeholder: "\u8F93\u5165\u6587\u4EF6\u540D"
|
|
2824
|
-
}
|
|
2825
|
-
),
|
|
2826
|
-
/* @__PURE__ */ jsx12("span", { className: "compress-dialog-ext", children: currentExt })
|
|
2827
|
-
] })
|
|
2828
|
-
] }),
|
|
2829
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-field", children: [
|
|
2830
|
-
/* @__PURE__ */ jsx12("label", { children: "\u538B\u7F29\u683C\u5F0F" }),
|
|
2831
|
-
/* @__PURE__ */ jsx12("select", { value: format, onChange: (e) => setFormat(e.target.value), children: FORMAT_OPTIONS.map((opt) => /* @__PURE__ */ jsx12("option", { value: opt.value, children: opt.label }, opt.value)) })
|
|
2832
|
-
] }),
|
|
2833
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-field", children: [
|
|
2834
|
-
/* @__PURE__ */ jsx12("label", { children: "\u538B\u7F29\u7EA7\u522B" }),
|
|
2835
|
-
/* @__PURE__ */ jsx12("div", { className: "compress-dialog-levels", children: LEVEL_OPTIONS.map((opt) => /* @__PURE__ */ jsxs10("label", { className: "compress-dialog-level", children: [
|
|
2836
|
-
/* @__PURE__ */ jsx12(
|
|
2837
|
-
"input",
|
|
2838
|
-
{
|
|
2839
|
-
type: "radio",
|
|
2840
|
-
name: "level",
|
|
2841
|
-
value: opt.value,
|
|
2842
|
-
checked: level === opt.value,
|
|
2843
|
-
onChange: () => setLevel(opt.value)
|
|
2844
|
-
}
|
|
2845
|
-
),
|
|
2846
|
-
/* @__PURE__ */ jsx12("span", { className: "compress-dialog-level-label", children: opt.label }),
|
|
2847
|
-
/* @__PURE__ */ jsx12("span", { className: "compress-dialog-level-desc", children: opt.desc })
|
|
2848
|
-
] }, opt.value)) })
|
|
2849
|
-
] }),
|
|
2850
|
-
supportsPassword && /* @__PURE__ */ jsxs10("div", { className: "compress-dialog-field", children: [
|
|
2851
|
-
/* @__PURE__ */ jsx12("label", { children: "\u5BC6\u7801\u4FDD\u62A4\uFF08\u53EF\u9009\uFF09" }),
|
|
2852
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-input-group", children: [
|
|
2853
|
-
/* @__PURE__ */ jsx12(
|
|
2854
|
-
"input",
|
|
2855
|
-
{
|
|
2856
|
-
type: showPassword ? "text" : "password",
|
|
2857
|
-
value: password,
|
|
2858
|
-
onChange: (e) => setPassword(e.target.value),
|
|
2859
|
-
placeholder: "\u8BBE\u7F6E\u5BC6\u7801"
|
|
2860
|
-
}
|
|
2861
|
-
),
|
|
2862
|
-
/* @__PURE__ */ jsx12(
|
|
2863
|
-
"button",
|
|
2864
|
-
{
|
|
2865
|
-
type: "button",
|
|
2866
|
-
className: "compress-dialog-toggle-password",
|
|
2867
|
-
onClick: () => setShowPassword(!showPassword),
|
|
2868
|
-
children: showPassword ? "\u9690\u85CF" : "\u663E\u793A"
|
|
2869
|
-
}
|
|
2870
|
-
)
|
|
2871
|
-
] })
|
|
2872
|
-
] }),
|
|
2873
|
-
/* @__PURE__ */ jsx12("div", { className: "compress-dialog-field compress-dialog-checkbox", children: /* @__PURE__ */ jsxs10("label", { children: [
|
|
2874
|
-
/* @__PURE__ */ jsx12(
|
|
2875
|
-
"input",
|
|
2876
|
-
{
|
|
2877
|
-
type: "checkbox",
|
|
2878
|
-
checked: deleteSource,
|
|
2879
|
-
onChange: (e) => setDeleteSource(e.target.checked)
|
|
2880
|
-
}
|
|
2881
|
-
),
|
|
2882
|
-
/* @__PURE__ */ jsx12("span", { children: "\u538B\u7F29\u540E\u5220\u9664\u6E90\u6587\u4EF6" })
|
|
2883
|
-
] }) }),
|
|
2884
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-preview", children: [
|
|
2885
|
-
/* @__PURE__ */ jsx12("span", { className: "compress-dialog-preview-label", children: "\u8F93\u51FA\u4F4D\u7F6E:" }),
|
|
2886
|
-
/* @__PURE__ */ jsx12("span", { className: "compress-dialog-preview-path", children: fullOutputPath })
|
|
2887
|
-
] })
|
|
2888
|
-
] }),
|
|
2889
|
-
/* @__PURE__ */ jsxs10("div", { className: "compress-dialog-footer", children: [
|
|
2890
|
-
/* @__PURE__ */ jsx12("button", { className: "compress-dialog-btn compress-dialog-btn-cancel", onClick: onCancel, children: "\u53D6\u6D88" }),
|
|
2891
|
-
/* @__PURE__ */ jsx12(
|
|
2892
|
-
"button",
|
|
2893
|
-
{
|
|
2894
|
-
className: "compress-dialog-btn compress-dialog-btn-confirm",
|
|
2895
|
-
onClick: handleConfirm,
|
|
2896
|
-
disabled: !outputName.trim(),
|
|
2897
|
-
children: "\u538B\u7F29"
|
|
2898
|
-
}
|
|
2899
|
-
)
|
|
2900
|
-
] })
|
|
2901
|
-
] }) }),
|
|
2902
|
-
document.body
|
|
2903
|
-
);
|
|
2904
|
-
}
|
|
2905
|
-
|
|
2906
|
-
// src/components/ProgressDialog.tsx
|
|
2907
|
-
import { createPortal as createPortal4 } from "react-dom";
|
|
2908
|
-
import { Icon as Icon10 } from "@iconify/react";
|
|
2909
|
-
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2910
|
-
function ProgressDialog({
|
|
2911
|
-
visible,
|
|
2912
|
-
progress,
|
|
2913
|
-
onCancel,
|
|
2914
|
-
onClose,
|
|
2915
|
-
onOpenFolder
|
|
2916
|
-
}) {
|
|
2917
|
-
const { type, status, percent, currentFile, processedCount, totalCount, error, outputPath } = progress;
|
|
2918
|
-
const title = type === "compress" ? "\u538B\u7F29\u6587\u4EF6" : "\u89E3\u538B\u6587\u4EF6";
|
|
2919
|
-
const isCompleted = status === "success" || status === "error";
|
|
2920
|
-
const StatusIcon = () => {
|
|
2921
|
-
switch (status) {
|
|
2922
|
-
case "processing":
|
|
2923
|
-
return /* @__PURE__ */ jsx13(Icon10, { icon: "lucide:loader-2", width: 24, height: 24, className: "progress-dialog-icon-spin" });
|
|
2924
|
-
case "success":
|
|
2925
|
-
return /* @__PURE__ */ jsx13(Icon10, { icon: "lucide:check-circle", width: 24, height: 24, className: "progress-dialog-icon-success" });
|
|
2926
|
-
case "error":
|
|
2927
|
-
return /* @__PURE__ */ jsx13(Icon10, { icon: "lucide:x-circle", width: 24, height: 24, className: "progress-dialog-icon-error" });
|
|
2928
|
-
default:
|
|
2929
|
-
return /* @__PURE__ */ jsx13(Icon10, { icon: "lucide:archive", width: 24, height: 24 });
|
|
2930
|
-
}
|
|
2931
|
-
};
|
|
2932
|
-
const getStatusText = () => {
|
|
2933
|
-
switch (status) {
|
|
2934
|
-
case "pending":
|
|
2935
|
-
return "\u51C6\u5907\u4E2D...";
|
|
2936
|
-
case "processing":
|
|
2937
|
-
return type === "compress" ? "\u6B63\u5728\u538B\u7F29..." : "\u6B63\u5728\u89E3\u538B...";
|
|
2938
|
-
case "success":
|
|
2939
|
-
return type === "compress" ? "\u538B\u7F29\u5B8C\u6210" : "\u89E3\u538B\u5B8C\u6210";
|
|
2940
|
-
case "error":
|
|
2941
|
-
return "\u64CD\u4F5C\u5931\u8D25";
|
|
2942
|
-
default:
|
|
2943
|
-
return "";
|
|
2944
|
-
}
|
|
2945
|
-
};
|
|
2946
|
-
const handleClose = () => {
|
|
2947
|
-
if (isCompleted) {
|
|
2948
|
-
onClose?.();
|
|
2949
|
-
} else {
|
|
2950
|
-
onCancel?.();
|
|
2951
|
-
}
|
|
2952
|
-
};
|
|
2953
|
-
if (!visible) return null;
|
|
2954
|
-
return createPortal4(
|
|
2955
|
-
/* @__PURE__ */ jsx13("div", { className: "progress-dialog-overlay", children: /* @__PURE__ */ jsxs11("div", { className: "progress-dialog", children: [
|
|
2956
|
-
/* @__PURE__ */ jsxs11("div", { className: "progress-dialog-header", children: [
|
|
2957
|
-
/* @__PURE__ */ jsxs11("div", { className: "progress-dialog-title", children: [
|
|
2958
|
-
/* @__PURE__ */ jsx13(StatusIcon, {}),
|
|
2959
|
-
/* @__PURE__ */ jsx13("span", { children: title })
|
|
2960
|
-
] }),
|
|
2961
|
-
isCompleted && /* @__PURE__ */ jsx13("button", { className: "progress-dialog-close", onClick: handleClose, children: /* @__PURE__ */ jsx13(Icon10, { icon: "lucide:x", width: 18, height: 18 }) })
|
|
2962
|
-
] }),
|
|
2963
|
-
/* @__PURE__ */ jsxs11("div", { className: "progress-dialog-content", children: [
|
|
2964
|
-
/* @__PURE__ */ jsx13("div", { className: "progress-dialog-status", children: getStatusText() }),
|
|
2965
|
-
status === "processing" && /* @__PURE__ */ jsxs11("div", { className: "progress-dialog-bar-container", children: [
|
|
2966
|
-
/* @__PURE__ */ jsx13("div", { className: "progress-dialog-bar", children: /* @__PURE__ */ jsx13(
|
|
2967
|
-
"div",
|
|
2968
|
-
{
|
|
2969
|
-
className: "progress-dialog-bar-fill",
|
|
2970
|
-
style: { width: `${percent}%` }
|
|
2971
|
-
}
|
|
2972
|
-
) }),
|
|
2973
|
-
/* @__PURE__ */ jsxs11("span", { className: "progress-dialog-percent", children: [
|
|
2974
|
-
percent,
|
|
2975
|
-
"%"
|
|
2976
|
-
] })
|
|
2977
|
-
] }),
|
|
2978
|
-
currentFile && status === "processing" && /* @__PURE__ */ jsx13("div", { className: "progress-dialog-current-file", children: currentFile }),
|
|
2979
|
-
totalCount && totalCount > 0 && status === "processing" && /* @__PURE__ */ jsxs11("div", { className: "progress-dialog-count", children: [
|
|
2980
|
-
processedCount || 0,
|
|
2981
|
-
" / ",
|
|
2982
|
-
totalCount,
|
|
2983
|
-
" \u4E2A\u6587\u4EF6"
|
|
2984
|
-
] }),
|
|
2985
|
-
error && /* @__PURE__ */ jsx13("div", { className: "progress-dialog-error", children: error }),
|
|
2986
|
-
status === "success" && outputPath && /* @__PURE__ */ jsxs11("div", { className: "progress-dialog-output", children: [
|
|
2987
|
-
/* @__PURE__ */ jsx13("span", { className: "progress-dialog-output-label", children: "\u8F93\u51FA\u4F4D\u7F6E:" }),
|
|
2988
|
-
/* @__PURE__ */ jsx13("span", { className: "progress-dialog-output-path", children: outputPath })
|
|
2989
|
-
] })
|
|
2990
|
-
] }),
|
|
2991
|
-
/* @__PURE__ */ jsxs11("div", { className: "progress-dialog-footer", children: [
|
|
2992
|
-
status === "processing" && onCancel && /* @__PURE__ */ jsx13("button", { className: "progress-dialog-btn progress-dialog-btn-cancel", onClick: onCancel, children: "\u53D6\u6D88" }),
|
|
2993
|
-
status === "success" && outputPath && onOpenFolder && /* @__PURE__ */ jsxs11(
|
|
2994
|
-
"button",
|
|
2995
|
-
{
|
|
2996
|
-
className: "progress-dialog-btn progress-dialog-btn-folder",
|
|
2997
|
-
onClick: () => onOpenFolder(outputPath),
|
|
2998
|
-
children: [
|
|
2999
|
-
/* @__PURE__ */ jsx13(Icon10, { icon: "lucide:folder-open", width: 16, height: 16 }),
|
|
3000
|
-
"\u6253\u5F00\u6587\u4EF6\u5939"
|
|
3001
|
-
]
|
|
3002
|
-
}
|
|
3003
|
-
),
|
|
3004
|
-
isCompleted && /* @__PURE__ */ jsx13("button", { className: "progress-dialog-btn progress-dialog-btn-close", onClick: handleClose, children: "\u5173\u95ED" })
|
|
3005
|
-
] })
|
|
3006
|
-
] }) }),
|
|
3007
|
-
document.body
|
|
3008
|
-
);
|
|
3009
|
-
}
|
|
3010
|
-
|
|
3011
|
-
// src/components/FileInfoDialog.tsx
|
|
3012
|
-
import React from "react";
|
|
3013
|
-
import { Icon as Icon11 } from "@iconify/react";
|
|
3014
|
-
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3015
|
-
function getFileIcon(type, name) {
|
|
3016
|
-
if (type === FileType.FOLDER) {
|
|
3017
|
-
return /* @__PURE__ */ jsx14(Icon11, { icon: "ic:round-folder", width: 48, height: 48, className: "file-info-icon" });
|
|
3018
|
-
}
|
|
3019
|
-
if (name) {
|
|
3020
|
-
const iconName2 = getFileTypeIcon(name, type);
|
|
3021
|
-
return /* @__PURE__ */ jsx14(Icon11, { icon: iconName2, width: 48, height: 48, className: "file-info-icon" });
|
|
3022
|
-
}
|
|
3023
|
-
const iconMap = {
|
|
3024
|
-
[FileType.IMAGE]: "material-icon-theme:image",
|
|
3025
|
-
[FileType.VIDEO]: "material-icon-theme:video",
|
|
3026
|
-
[FileType.MUSIC]: "material-icon-theme:audio",
|
|
3027
|
-
[FileType.DOCUMENT]: "material-icon-theme:word",
|
|
3028
|
-
[FileType.CODE]: "material-icon-theme:javascript",
|
|
3029
|
-
[FileType.ARCHIVE]: "material-icon-theme:zip",
|
|
3030
|
-
[FileType.PDF]: "material-icon-theme:pdf",
|
|
3031
|
-
[FileType.TEXT]: "material-icon-theme:document",
|
|
3032
|
-
[FileType.APPLICATION]: "material-icon-theme:exe"
|
|
3033
|
-
};
|
|
3034
|
-
const iconName = iconMap[type] || "material-icon-theme:document";
|
|
3035
|
-
return /* @__PURE__ */ jsx14(Icon11, { icon: iconName, width: 48, height: 48, className: "file-info-icon" });
|
|
3036
|
-
}
|
|
3037
|
-
function getFileTypeName(type, extension) {
|
|
3038
|
-
switch (type) {
|
|
3039
|
-
case FileType.FOLDER:
|
|
3040
|
-
return "\u6587\u4EF6\u5939";
|
|
3041
|
-
case FileType.IMAGE:
|
|
3042
|
-
return `\u56FE\u7247${extension ? ` (${extension.toUpperCase()})` : ""}`;
|
|
3043
|
-
case FileType.VIDEO:
|
|
3044
|
-
return `\u89C6\u9891${extension ? ` (${extension.toUpperCase()})` : ""}`;
|
|
3045
|
-
case FileType.MUSIC:
|
|
3046
|
-
return `\u97F3\u9891${extension ? ` (${extension.toUpperCase()})` : ""}`;
|
|
3047
|
-
case FileType.DOCUMENT:
|
|
3048
|
-
return `\u6587\u6863${extension ? ` (${extension.toUpperCase()})` : ""}`;
|
|
3049
|
-
case FileType.CODE:
|
|
3050
|
-
return `\u4EE3\u7801\u6587\u4EF6${extension ? ` (${extension.toUpperCase()})` : ""}`;
|
|
3051
|
-
case FileType.ARCHIVE:
|
|
3052
|
-
return `\u538B\u7F29\u5305${extension ? ` (${extension.toUpperCase()})` : ""}`;
|
|
3053
|
-
default:
|
|
3054
|
-
return extension ? `${extension.toUpperCase()} \u6587\u4EF6` : "\u6587\u4EF6";
|
|
3055
|
-
}
|
|
3056
|
-
}
|
|
3057
|
-
function getExtension(filename) {
|
|
3058
|
-
const lastDot = filename.lastIndexOf(".");
|
|
3059
|
-
if (lastDot === -1 || lastDot === 0) return void 0;
|
|
3060
|
-
return filename.substring(lastDot + 1).toLowerCase();
|
|
3061
|
-
}
|
|
3062
|
-
function getDirectory(path) {
|
|
3063
|
-
const lastSlash = path.lastIndexOf("/");
|
|
3064
|
-
if (lastSlash === -1) return path;
|
|
3065
|
-
return path.substring(0, lastSlash) || "/";
|
|
3066
|
-
}
|
|
3067
|
-
function FileInfoDialog({ visible, item, onClose }) {
|
|
3068
|
-
if (!visible || !item) return null;
|
|
3069
|
-
const extension = getExtension(item.name);
|
|
3070
|
-
const directory = getDirectory(item.id);
|
|
3071
|
-
const handleBackdropClick = (e) => {
|
|
3072
|
-
if (e.target === e.currentTarget) {
|
|
3073
|
-
onClose();
|
|
3074
|
-
}
|
|
3075
|
-
};
|
|
3076
|
-
React.useEffect(() => {
|
|
3077
|
-
const handleKeyDown = (e) => {
|
|
3078
|
-
if (e.key === "Escape") {
|
|
3079
|
-
onClose();
|
|
3080
|
-
}
|
|
3081
|
-
};
|
|
3082
|
-
if (visible) {
|
|
3083
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
3084
|
-
}
|
|
3085
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
3086
|
-
}, [visible, onClose]);
|
|
3087
|
-
return /* @__PURE__ */ jsx14("div", { className: "file-info-dialog-overlay", onClick: handleBackdropClick, children: /* @__PURE__ */ jsxs12("div", { className: "file-info-dialog", children: [
|
|
3088
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-dialog-header", children: [
|
|
3089
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-dialog-title", children: [
|
|
3090
|
-
getFileIcon(item.type, item.name),
|
|
3091
|
-
/* @__PURE__ */ jsx14("span", { className: "file-info-dialog-name", title: item.name, children: item.name })
|
|
3092
|
-
] }),
|
|
3093
|
-
/* @__PURE__ */ jsx14("button", { className: "file-info-dialog-close", onClick: onClose, children: /* @__PURE__ */ jsx14(Icon11, { icon: "lucide:x", width: 18, height: 18 }) })
|
|
3094
|
-
] }),
|
|
3095
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-dialog-content", children: [
|
|
3096
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-row", children: [
|
|
3097
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-label", children: [
|
|
3098
|
-
/* @__PURE__ */ jsx14(Icon11, { icon: "lucide:file", width: 14, height: 14 }),
|
|
3099
|
-
/* @__PURE__ */ jsx14("span", { children: "\u7C7B\u578B" })
|
|
3100
|
-
] }),
|
|
3101
|
-
/* @__PURE__ */ jsx14("div", { className: "file-info-value", children: getFileTypeName(item.type, extension) })
|
|
3102
|
-
] }),
|
|
3103
|
-
item.type !== FileType.FOLDER && item.size && /* @__PURE__ */ jsxs12("div", { className: "file-info-row", children: [
|
|
3104
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-label", children: [
|
|
3105
|
-
/* @__PURE__ */ jsx14(Icon11, { icon: "lucide:hard-drive", width: 14, height: 14 }),
|
|
3106
|
-
/* @__PURE__ */ jsx14("span", { children: "\u5927\u5C0F" })
|
|
3107
|
-
] }),
|
|
3108
|
-
/* @__PURE__ */ jsx14("div", { className: "file-info-value", children: item.size })
|
|
3109
|
-
] }),
|
|
3110
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-row", children: [
|
|
3111
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-label", children: [
|
|
3112
|
-
/* @__PURE__ */ jsx14(Icon11, { icon: "lucide:map-pin", width: 14, height: 14 }),
|
|
3113
|
-
/* @__PURE__ */ jsx14("span", { children: "\u4F4D\u7F6E" })
|
|
3114
|
-
] }),
|
|
3115
|
-
/* @__PURE__ */ jsx14("div", { className: "file-info-value file-info-value--path", title: directory, children: directory })
|
|
3116
|
-
] }),
|
|
3117
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-row", children: [
|
|
3118
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-label", children: [
|
|
3119
|
-
/* @__PURE__ */ jsx14(Icon11, { icon: "lucide:map-pin", width: 14, height: 14 }),
|
|
3120
|
-
/* @__PURE__ */ jsx14("span", { children: "\u5B8C\u6574\u8DEF\u5F84" })
|
|
3121
|
-
] }),
|
|
3122
|
-
/* @__PURE__ */ jsx14("div", { className: "file-info-value file-info-value--path", title: item.id, children: item.id })
|
|
3123
|
-
] }),
|
|
3124
|
-
item.dateModified && /* @__PURE__ */ jsxs12("div", { className: "file-info-row", children: [
|
|
3125
|
-
/* @__PURE__ */ jsxs12("div", { className: "file-info-label", children: [
|
|
3126
|
-
/* @__PURE__ */ jsx14(Icon11, { icon: "lucide:clock", width: 14, height: 14 }),
|
|
3127
|
-
/* @__PURE__ */ jsx14("span", { children: "\u4FEE\u6539\u65F6\u95F4" })
|
|
3128
|
-
] }),
|
|
3129
|
-
/* @__PURE__ */ jsx14("div", { className: "file-info-value", children: item.dateModified })
|
|
3130
|
-
] })
|
|
3131
|
-
] }),
|
|
3132
|
-
/* @__PURE__ */ jsx14("div", { className: "file-info-dialog-footer", children: /* @__PURE__ */ jsx14("button", { className: "file-info-dialog-btn", onClick: onClose, children: "\u5173\u95ED" }) })
|
|
3133
|
-
] }) });
|
|
3134
|
-
}
|
|
3135
|
-
|
|
3136
|
-
// src/hooks/useSelection.ts
|
|
3137
|
-
import { useState as useState7, useCallback as useCallback5 } from "react";
|
|
3138
|
-
function useSelection() {
|
|
3139
|
-
const [selectedIds, setSelectedIds] = useState7(/* @__PURE__ */ new Set());
|
|
3140
|
-
const [lastSelectedId, setLastSelectedId] = useState7(null);
|
|
3141
|
-
const [editingId, setEditingId] = useState7(null);
|
|
3142
|
-
const clearSelection = useCallback5(() => {
|
|
3143
|
-
setSelectedIds(/* @__PURE__ */ new Set());
|
|
3144
|
-
setLastSelectedId(null);
|
|
3145
|
-
}, []);
|
|
3146
|
-
const selectItem = useCallback5((id, items, multi = false, range = false) => {
|
|
3147
|
-
if (!id) {
|
|
3148
|
-
clearSelection();
|
|
3149
|
-
return;
|
|
3150
|
-
}
|
|
3151
|
-
setSelectedIds((prev) => {
|
|
3152
|
-
setLastSelectedId((prevLast) => {
|
|
3153
|
-
if (range && prevLast) {
|
|
3154
|
-
const indexA = items.findIndex((i) => i.id === prevLast);
|
|
3155
|
-
const indexB = items.findIndex((i) => i.id === id);
|
|
3156
|
-
if (indexA !== -1 && indexB !== -1) {
|
|
3157
|
-
const start = Math.min(indexA, indexB);
|
|
3158
|
-
const end = Math.max(indexA, indexB);
|
|
3159
|
-
const newSet = new Set(multi ? prev : []);
|
|
3160
|
-
for (let i = start; i <= end; i++) {
|
|
3161
|
-
const item = items[i];
|
|
3162
|
-
if (item) {
|
|
3163
|
-
newSet.add(item.id);
|
|
3164
|
-
}
|
|
3165
|
-
}
|
|
3166
|
-
setSelectedIds(newSet);
|
|
3167
|
-
return id;
|
|
3168
|
-
}
|
|
3169
|
-
}
|
|
3170
|
-
if (multi) {
|
|
3171
|
-
const newSet = new Set(prev);
|
|
3172
|
-
if (newSet.has(id)) {
|
|
3173
|
-
newSet.delete(id);
|
|
3174
|
-
} else {
|
|
3175
|
-
newSet.add(id);
|
|
3176
|
-
}
|
|
3177
|
-
setSelectedIds(newSet);
|
|
3178
|
-
return id;
|
|
3179
|
-
}
|
|
3180
|
-
setSelectedIds(/* @__PURE__ */ new Set([id]));
|
|
3181
|
-
return id;
|
|
3182
|
-
});
|
|
3183
|
-
return prev;
|
|
3184
|
-
});
|
|
3185
|
-
}, [clearSelection]);
|
|
3186
|
-
const selectAll = useCallback5((items) => {
|
|
3187
|
-
setSelectedIds(new Set(items.map((i) => i.id)));
|
|
3188
|
-
}, []);
|
|
3189
|
-
const setEditing = useCallback5((id) => {
|
|
3190
|
-
setEditingId(id);
|
|
3191
|
-
}, []);
|
|
3192
|
-
const isSelected = useCallback5((id) => {
|
|
3193
|
-
return selectedIds.has(id);
|
|
3194
|
-
}, [selectedIds]);
|
|
3195
|
-
return {
|
|
3196
|
-
selectedIds,
|
|
3197
|
-
lastSelectedId,
|
|
3198
|
-
editingId,
|
|
3199
|
-
clearSelection,
|
|
3200
|
-
selectItem,
|
|
3201
|
-
selectAll,
|
|
3202
|
-
setEditing,
|
|
3203
|
-
isSelected
|
|
3204
|
-
};
|
|
3205
|
-
}
|
|
3206
|
-
|
|
3207
|
-
// src/hooks/useDragAndDrop.ts
|
|
3208
|
-
import { useState as useState8, useCallback as useCallback6 } from "react";
|
|
3209
|
-
function useDragAndDrop(getSelectedIds, onSelect, onMove) {
|
|
3210
|
-
const [dragOverId, setDragOverId] = useState8(null);
|
|
3211
|
-
const [isDragging, setIsDragging] = useState8(false);
|
|
3212
|
-
const handleDragStart = useCallback6((e, itemId) => {
|
|
3213
|
-
if (!e.dataTransfer) return;
|
|
3214
|
-
const selectedIds = getSelectedIds();
|
|
3215
|
-
if (!selectedIds.has(itemId)) {
|
|
3216
|
-
onSelect(itemId, false, false);
|
|
3217
|
-
}
|
|
3218
|
-
const draggedIds = selectedIds.has(itemId) ? selectedIds : /* @__PURE__ */ new Set([itemId]);
|
|
3219
|
-
e.dataTransfer.setData("text/plain", JSON.stringify([...draggedIds]));
|
|
3220
|
-
e.dataTransfer.effectAllowed = "move";
|
|
3221
|
-
setIsDragging(true);
|
|
3222
|
-
}, [getSelectedIds, onSelect]);
|
|
3223
|
-
const handleDragOver = useCallback6((e, item) => {
|
|
3224
|
-
if (!isDragging) return;
|
|
3225
|
-
if (item.type === FileType.FOLDER) {
|
|
3226
|
-
const selectedIds = getSelectedIds();
|
|
3227
|
-
if (!selectedIds.has(item.id)) {
|
|
3228
|
-
e.preventDefault();
|
|
3229
|
-
setDragOverId(item.id);
|
|
3230
|
-
}
|
|
3231
|
-
}
|
|
3232
|
-
}, [isDragging, getSelectedIds]);
|
|
3233
|
-
const handleDragLeave = useCallback6(() => {
|
|
3234
|
-
setDragOverId(null);
|
|
3235
|
-
}, []);
|
|
3236
|
-
const handleDrop = useCallback6((e, targetItem) => {
|
|
3237
|
-
setDragOverId(null);
|
|
3238
|
-
setIsDragging(false);
|
|
3239
|
-
if (!e.dataTransfer || targetItem.type !== FileType.FOLDER) return;
|
|
3240
|
-
const data = e.dataTransfer.getData("text/plain");
|
|
3241
|
-
if (!data) return;
|
|
3242
|
-
try {
|
|
3243
|
-
const draggedIds = JSON.parse(data);
|
|
3244
|
-
const itemIds = new Set(draggedIds);
|
|
3245
|
-
if (itemIds.has(targetItem.id)) return;
|
|
3246
|
-
onMove(targetItem.id, itemIds);
|
|
3247
|
-
} catch {
|
|
3248
|
-
}
|
|
3249
|
-
}, [onMove]);
|
|
3250
|
-
const handleDragEnd = useCallback6(() => {
|
|
3251
|
-
setDragOverId(null);
|
|
3252
|
-
setIsDragging(false);
|
|
3253
|
-
}, []);
|
|
3254
|
-
return {
|
|
3255
|
-
dragOverId,
|
|
3256
|
-
isDragging,
|
|
3257
|
-
handleDragStart,
|
|
3258
|
-
handleDragOver,
|
|
3259
|
-
handleDragLeave,
|
|
3260
|
-
handleDrop,
|
|
3261
|
-
handleDragEnd
|
|
3262
|
-
};
|
|
3263
|
-
}
|
|
3264
|
-
|
|
3265
|
-
// src/hooks/useMediaPlayer.ts
|
|
3266
|
-
import { useState as useState9, useCallback as useCallback7, useEffect as useEffect6 } from "react";
|
|
3267
|
-
function useMediaPlayer(mediaType, mediaRef) {
|
|
3268
|
-
const [isPlaying, setIsPlaying] = useState9(false);
|
|
3269
|
-
const [progress, setProgress] = useState9(0);
|
|
3270
|
-
const [currentTime, setCurrentTime] = useState9(0);
|
|
3271
|
-
const [duration, setDuration] = useState9(0);
|
|
3272
|
-
const [isMuted, setIsMuted] = useState9(false);
|
|
3273
|
-
const [volume, setVolume] = useState9(1);
|
|
3274
|
-
const [lastVolume, setLastVolume] = useState9(1);
|
|
3275
|
-
const [showControls, setShowControls] = useState9(false);
|
|
3276
|
-
const isAudio = mediaType === FileType.MUSIC;
|
|
3277
|
-
const updateProgress = useCallback7(() => {
|
|
3278
|
-
const media = mediaRef.current;
|
|
3279
|
-
if (media) {
|
|
3280
|
-
const curr = media.currentTime;
|
|
3281
|
-
const dur = media.duration;
|
|
3282
|
-
setCurrentTime(curr);
|
|
3283
|
-
if (dur && !isNaN(dur)) {
|
|
3284
|
-
setDuration(dur);
|
|
3285
|
-
setProgress(curr / dur * 100);
|
|
3286
|
-
}
|
|
3287
|
-
}
|
|
3288
|
-
}, [mediaRef]);
|
|
3289
|
-
const togglePlay = useCallback7(() => {
|
|
3290
|
-
const media = mediaRef.current;
|
|
3291
|
-
if (media) {
|
|
3292
|
-
if (isPlaying) {
|
|
3293
|
-
media.pause();
|
|
3294
|
-
setIsPlaying(false);
|
|
3295
|
-
} else {
|
|
3296
|
-
media.play();
|
|
3297
|
-
setIsPlaying(true);
|
|
3298
|
-
}
|
|
3299
|
-
}
|
|
3300
|
-
}, [isPlaying, mediaRef]);
|
|
3301
|
-
const toggleMute = useCallback7(() => {
|
|
3302
|
-
const media = mediaRef.current;
|
|
3303
|
-
if (media) {
|
|
3304
|
-
if (isMuted) {
|
|
3305
|
-
const volToRestore = lastVolume || 1;
|
|
3306
|
-
media.volume = volToRestore;
|
|
3307
|
-
media.muted = false;
|
|
3308
|
-
setVolume(volToRestore);
|
|
3309
|
-
setIsMuted(false);
|
|
3310
|
-
} else {
|
|
3311
|
-
setLastVolume(volume);
|
|
3312
|
-
media.volume = 0;
|
|
3313
|
-
media.muted = true;
|
|
3314
|
-
setVolume(0);
|
|
3315
|
-
setIsMuted(true);
|
|
3316
|
-
}
|
|
3317
|
-
}
|
|
3318
|
-
}, [isMuted, lastVolume, volume, mediaRef]);
|
|
3319
|
-
const handleVolumeChange = useCallback7((val) => {
|
|
3320
|
-
setVolume(val);
|
|
3321
|
-
const media = mediaRef.current;
|
|
3322
|
-
if (media) {
|
|
3323
|
-
media.volume = val;
|
|
3324
|
-
if (val === 0) {
|
|
3325
|
-
setIsMuted(true);
|
|
3326
|
-
media.muted = true;
|
|
3327
|
-
} else {
|
|
3328
|
-
setIsMuted(false);
|
|
3329
|
-
media.muted = false;
|
|
3330
|
-
}
|
|
3331
|
-
}
|
|
3332
|
-
}, [mediaRef]);
|
|
3333
|
-
const seekTo = useCallback7((time) => {
|
|
3334
|
-
const media = mediaRef.current;
|
|
3335
|
-
if (media && duration) {
|
|
3336
|
-
media.currentTime = time;
|
|
3337
|
-
setCurrentTime(time);
|
|
3338
|
-
setProgress(time / duration * 100);
|
|
3339
|
-
}
|
|
3340
|
-
}, [duration, mediaRef]);
|
|
3341
|
-
const formatTime = useCallback7((time) => {
|
|
3342
|
-
if (isNaN(time)) return "0:00";
|
|
3343
|
-
const minutes = Math.floor(time / 60);
|
|
3344
|
-
const seconds = Math.floor(time % 60);
|
|
3345
|
-
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
3346
|
-
}, []);
|
|
3347
|
-
const autoPlay = useCallback7(() => {
|
|
3348
|
-
const media = mediaRef.current;
|
|
3349
|
-
if ((mediaType === FileType.VIDEO || isAudio) && media) {
|
|
3350
|
-
media.volume = volume;
|
|
3351
|
-
media.play().catch(() => {
|
|
3352
|
-
});
|
|
3353
|
-
setIsPlaying(true);
|
|
3354
|
-
}
|
|
3355
|
-
}, [mediaType, isAudio, volume, mediaRef]);
|
|
3356
|
-
useEffect6(() => {
|
|
3357
|
-
const media = mediaRef.current;
|
|
3358
|
-
if (media) {
|
|
3359
|
-
media.addEventListener("timeupdate", updateProgress);
|
|
3360
|
-
media.addEventListener("loadedmetadata", updateProgress);
|
|
3361
|
-
media.addEventListener("ended", () => {
|
|
3362
|
-
setIsPlaying(false);
|
|
3363
|
-
});
|
|
3364
|
-
return () => {
|
|
3365
|
-
media.removeEventListener("timeupdate", updateProgress);
|
|
3366
|
-
media.removeEventListener("loadedmetadata", updateProgress);
|
|
3367
|
-
};
|
|
3368
|
-
}
|
|
3369
|
-
}, [mediaRef, updateProgress]);
|
|
3370
|
-
return {
|
|
3371
|
-
isPlaying,
|
|
3372
|
-
progress,
|
|
3373
|
-
currentTime,
|
|
3374
|
-
duration,
|
|
3375
|
-
isMuted,
|
|
3376
|
-
volume,
|
|
3377
|
-
showControls,
|
|
3378
|
-
isAudio,
|
|
3379
|
-
togglePlay,
|
|
3380
|
-
toggleMute,
|
|
3381
|
-
handleVolumeChange,
|
|
3382
|
-
seekTo,
|
|
3383
|
-
formatTime,
|
|
3384
|
-
autoPlay,
|
|
3385
|
-
updateProgress
|
|
3386
|
-
};
|
|
3387
|
-
}
|
|
3388
|
-
|
|
3389
|
-
// src/hooks/useApplicationIcon.ts
|
|
3390
|
-
import { useState as useState10, useCallback as useCallback8, useEffect as useEffect7 } from "react";
|
|
3391
|
-
function useApplicationIcon(items) {
|
|
3392
|
-
const appIconCache = /* @__PURE__ */ new Map();
|
|
3393
|
-
const [appIconUrls, setAppIconUrls] = useState10(/* @__PURE__ */ new Map());
|
|
3394
|
-
const loadApplicationIcon = useCallback8(async (item) => {
|
|
3395
|
-
if (item.type !== FileType.APPLICATION || !item.id) return;
|
|
3396
|
-
if (appIconCache.has(item.id)) {
|
|
3397
|
-
const cachedUrl = appIconCache.get(item.id);
|
|
3398
|
-
if (cachedUrl) {
|
|
3399
|
-
setAppIconUrls((prev) => new Map(prev).set(item.id, cachedUrl));
|
|
3400
|
-
}
|
|
3401
|
-
return;
|
|
3402
|
-
}
|
|
3403
|
-
if (appIconUrls.has(item.id)) {
|
|
3404
|
-
return;
|
|
3405
|
-
}
|
|
3406
|
-
if (typeof window.fileExplorerAPI !== "undefined" && window.fileExplorerAPI.getApplicationIcon) {
|
|
3407
|
-
try {
|
|
3408
|
-
const iconUrl = await window.fileExplorerAPI.getApplicationIcon(item.id);
|
|
3409
|
-
if (iconUrl) {
|
|
3410
|
-
appIconCache.set(item.id, iconUrl);
|
|
3411
|
-
setAppIconUrls((prev) => new Map(prev).set(item.id, iconUrl));
|
|
3412
|
-
}
|
|
3413
|
-
} catch (error) {
|
|
3414
|
-
console.error(`Failed to load application icon for ${item.name}:`, error);
|
|
3415
|
-
}
|
|
3416
|
-
}
|
|
3417
|
-
}, [appIconUrls]);
|
|
3418
|
-
useEffect7(() => {
|
|
3419
|
-
items.forEach((item) => {
|
|
3420
|
-
if (item.type === FileType.APPLICATION && !appIconUrls.has(item.id)) {
|
|
3421
|
-
loadApplicationIcon(item);
|
|
3422
|
-
}
|
|
3423
|
-
});
|
|
3424
|
-
}, [items, appIconUrls, loadApplicationIcon]);
|
|
3425
|
-
const getAppIconUrl = useCallback8((item) => {
|
|
3426
|
-
return appIconUrls.get(item.id);
|
|
3427
|
-
}, [appIconUrls]);
|
|
3428
|
-
return {
|
|
3429
|
-
getAppIconUrl,
|
|
3430
|
-
loadApplicationIcon
|
|
3431
|
-
};
|
|
3432
|
-
}
|
|
3433
|
-
export {
|
|
3434
|
-
Breadcrumb,
|
|
3435
|
-
CompressDialog,
|
|
3436
|
-
ContextMenu,
|
|
3437
|
-
FileGrid,
|
|
3438
|
-
FileIcon,
|
|
3439
|
-
FileInfoDialog,
|
|
3440
|
-
FileList,
|
|
3441
|
-
FileListView,
|
|
3442
|
-
FileSidebar,
|
|
3443
|
-
FileType,
|
|
3444
|
-
ProgressDialog,
|
|
3445
|
-
SortIndicator,
|
|
3446
|
-
StatusBar,
|
|
3447
|
-
Toolbar,
|
|
3448
|
-
Window,
|
|
3449
|
-
useApplicationIcon,
|
|
3450
|
-
useDragAndDrop,
|
|
3451
|
-
useMediaPlayer,
|
|
3452
|
-
useSelection,
|
|
3453
|
-
useWindowDrag,
|
|
3454
|
-
useWindowResize
|
|
3455
|
-
};
|
|
3456
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
var e={FOLDER:"folder",FILE:"file",IMAGE:"image",VIDEO:"video",MUSIC:"music",DOCUMENT:"document",CODE:"code",TEXT:"text",PDF:"pdf",ARCHIVE:"archive",APPLICATION:"application",UNKNOWN:"unknown"};import{useState as t,useCallback as i,useImperativeHandle as n,forwardRef as s}from"react";import{Icon as a}from"@iconify/react";import{useRef as o,useMemo as r}from"react";import{useMemo as l}from"react";import{Icon as c}from"@iconify/react";var d=new Set(["3d","actionscript","ada","adobe-illustrator","adobe-photoshop","android","angular","applescript","arduino","asciidoc","assembly","astro","audio","aurelia","babel","ballerina","bazel","biome","blender","bower","bun","c","cabal","caddy","cake","certificate","changelog","circleci","claude","clojure","cmake","cobol","coffee","command","conduct","contributing","controller","copilot","cpp","crystal","csharp","css","css-map","cucumber","cuda","cursor","cypress","d","dart","database","deno","dependabot","diff","django","docker","document","drawio","drizzle","editorconfig","ejs","elixir","elm","email","ember","epub","erlang","esbuild","eslint","excalidraw","exe","favicon","figma","firebase","flash","flow","font","forth","fortran","freemarker","fsharp","gamemaker","gatsby","gcp","gemfile","gemini","git","gitlab","gleam","go","go-mod","godot","gradle","graphql","groovy","grunt","gulp","h","haml","handlebars","hardhat","haskell","haxe","hcl","helm","hjson","hosts","hpp","html","http","husky","i18n","image","imba","ionic","jar","java","javaclass","javascript","javascript-map","jenkins","jest","jinja","jsconfig","json","julia","jupyter","just","karma","key","kotlin","kubernetes","laravel","lean","lefthook","lerna","less","lib","license","lighthouse","liquid","lisp","livescript","lock","log","lua","luau","makefile","markdown","markdownlint","matlab","maven","mdx","mercurial","mermaid","meson","minecraft","mjml","mocha","mojo","nest","netlify","next","nginx","nim","nix","nodejs","nodemon","npm","nuget","nunjucks","nuxt","nx","objective-c","objective-cpp","ocaml","odin","openapi","opentofu","pascal","pdf","perl","php","phpstan","phpunit","pipeline","playwright","pnpm","postcss","powerpoint","powershell","prettier","prisma","processing","prolog","proto","pug","puppet","purescript","python","pytorch","quasar","r","racket","razor","react","react-ts","readme","reason","remark","remix","renovate","replit","rescript","riot","roadmap","robot","robots","rollup","routing","rspec","rubocop","ruby","ruff","rust","salt","san","sas","sass","sbt","scala","scheme","search","sentry","sequelize","serverless","settings","shader","shellcheck","sketch","slim","slint","smarty","snakemake","snapcraft","snyk","solidity","spwn","stackblitz","stan","stencil","storybook","stryker","stylelint","stylus","sublime","subtitles","supabase","svelte","svg","svgo","swagger","swc","swift","tailwindcss","taskfile","tauri","tcl","teal","templ","template","terraform","test-js","test-jsx","test-ts","tex","todo","toml","travis","tree","tsconfig","tsdoc","turborepo","twig","typescript","typescript-def","unity","unocss","vagrant","vanilla-extract","vercel","verilog","video","vim","vite","vitest","vlang","vscode","vue","vue-config","wakatime","wallaby","webassembly","webhint","webpack","windicss","word","wrangler","wxt","xaml","xmake","xml","yaml","yarn","zig","zip"]),m={js:"javascript",mjs:"javascript",cjs:"javascript",jsx:"react",ts:"typescript",mts:"typescript",cts:"typescript",tsx:"react-ts",vue:"vue",svelte:"svelte",astro:"astro",py:"python",pyw:"python",pyi:"python",pyc:"python",java:"java",class:"javaclass",jar:"jar",c:"c",h:"h",cpp:"cpp",cc:"cpp",cxx:"cpp",hpp:"hpp",hh:"hpp",hxx:"hpp",cs:"csharp",csx:"csharp",go:"go",rs:"rust",php:"php",phtml:"php",rb:"ruby",rake:"ruby",swift:"swift",kt:"kotlin",kts:"kotlin",scala:"scala",dart:"dart",lua:"lua",luau:"luau",r:"r",rdata:"r",rds:"r",pl:"perl",pm:"perl",sh:"command",bash:"command",zsh:"command",fish:"command",ps1:"powershell",psm1:"powershell",psd1:"powershell",bat:"command",cmd:"command",css:"css",scss:"sass",sass:"sass",less:"less",styl:"stylus",html:"html",htm:"html",xhtml:"html",xml:"xml",xsl:"xml",xslt:"xml",json:"json",jsonc:"json",json5:"json",yaml:"yaml",yml:"yaml",toml:"toml",ini:"settings",conf:"settings",config:"settings",md:"markdown",markdown:"markdown",mdx:"mdx",txt:"document",pdf:"pdf",doc:"word",docx:"word",dot:"word",dotx:"word",odt:"word",xls:"table",xlsx:"table",xlsm:"table",ods:"table",csv:"table",ppt:"powerpoint",pptx:"powerpoint",odp:"powerpoint",jpg:"image",jpeg:"image",png:"image",gif:"image",webp:"image",ico:"image",bmp:"image",tiff:"image",tif:"image",heic:"image",heif:"image",svg:"svg",psd:"adobe-photoshop",ai:"adobe-illustrator",sketch:"sketch",fig:"figma",figma:"figma",mp4:"video",mov:"video",avi:"video",mkv:"video",webm:"video",flv:"video",wmv:"video",m4v:"video","3gp":"video",mpeg:"video",mpg:"video",mp3:"audio",wav:"audio",flac:"audio",aac:"audio",ogg:"audio",wma:"audio",m4a:"audio",aiff:"audio",zip:"zip",rar:"zip","7z":"zip",tar:"zip",gz:"zip",bz2:"zip",xz:"zip",tgz:"zip",tbz2:"zip",sql:"database",db:"database",sqlite:"database",sqlite3:"database",prisma:"prisma",log:"log",lock:"lock",env:"settings",graphql:"graphql",gql:"graphql",proto:"proto",wasm:"webassembly",zig:"zig",nim:"nim",nix:"nix",hcl:"hcl",tf:"terraform",sol:"solidity",ex:"elixir",exs:"elixir",erl:"erlang",hrl:"erlang",hs:"haskell",lhs:"haskell",ml:"ocaml",mli:"ocaml",clj:"clojure",cljs:"clojure",cljc:"clojure",lisp:"lisp",lsp:"lisp",el:"lisp",vim:"vim",dockerfile:"docker"},u={".gitignore":"git",".gitattributes":"git",".gitmodules":"git",".gitkeep":"git",".env":"settings",".env.local":"settings",".env.development":"settings",".env.production":"settings",".env.test":"settings",".env.example":"settings","package.json":"nodejs","package-lock.json":"npm","yarn.lock":"yarn",".yarnrc":"yarn",".yarnrc.yml":"yarn","pnpm-lock.yaml":"pnpm",".pnpmfile.cjs":"pnpm","bun.lockb":"bun","bunfig.toml":"bun","requirements.txt":"python",pipfile:"python","pipfile.lock":"python","pyproject.toml":"python","poetry.lock":"python","setup.py":"python","cargo.toml":"rust","cargo.lock":"rust","go.mod":"go-mod","go.sum":"go-mod","go.work":"go-mod","composer.json":"php","composer.lock":"php",gemfile:"gemfile","gemfile.lock":"gemfile",rakefile:"ruby",dockerfile:"docker","docker-compose.yml":"docker","docker-compose.yaml":"docker",".dockerignore":"docker",makefile:"makefile",gnumakefile:"makefile","cmakelists.txt":"cmake","build.gradle":"gradle","build.gradle.kts":"gradle","settings.gradle":"gradle","pom.xml":"maven","tsconfig.json":"tsconfig","jsconfig.json":"jsconfig",".prettierrc":"prettier",".prettierrc.json":"prettier",".prettierrc.js":"prettier",".prettierignore":"prettier","prettier.config.js":"prettier",".eslintrc":"eslint",".eslintrc.json":"eslint",".eslintrc.js":"eslint",".eslintignore":"eslint","eslint.config.js":"eslint","eslint.config.mjs":"eslint",".editorconfig":"editorconfig","vite.config.ts":"vite","vite.config.js":"vite","webpack.config.js":"webpack","webpack.config.ts":"webpack","rollup.config.js":"rollup","rollup.config.ts":"rollup","esbuild.config.js":"esbuild","tailwind.config.js":"tailwindcss","tailwind.config.ts":"tailwindcss","postcss.config.js":"postcss","postcss.config.cjs":"postcss","babel.config.js":"babel",".babelrc":"babel","jest.config.js":"jest","jest.config.ts":"jest","vitest.config.ts":"vitest","vitest.config.js":"vitest","playwright.config.ts":"playwright","playwright.config.js":"playwright","cypress.config.ts":"cypress","cypress.config.js":"cypress",".swcrc":"swc","swc.config.js":"swc","turbo.json":"turborepo","nx.json":"nx","biome.json":"biome",".nvmrc":"nodejs",".node-version":"nodejs","nuxt.config.ts":"nuxt","nuxt.config.js":"nuxt","next.config.js":"next","next.config.mjs":"next","next.config.ts":"next","svelte.config.js":"svelte","astro.config.mjs":"astro","astro.config.ts":"astro","vue.config.js":"vue-config","angular.json":"angular","nest-cli.json":"nest","tauri.conf.json":"tauri",".travis.yml":"travis",".gitlab-ci.yml":"gitlab","vercel.json":"vercel","netlify.toml":"netlify",license:"license","license.md":"license","license.txt":"license",readme:"readme","readme.md":"readme","readme.txt":"readme",changelog:"changelog","changelog.md":"changelog",".npmrc":"npm",".npmignore":"npm","robots.txt":"robots",".htaccess":"nginx",vagrantfile:"vagrant",".stylelintrc":"stylelint",".stylelintrc.json":"stylelint","nodemon.json":"nodemon",".huskyrc":"husky","renovate.json":"renovate",".snyk":"snyk","deno.json":"deno","deno.jsonc":"deno"};function p(t,i){const n=t.toLowerCase();if(u[n]){const e=u[n];if(d.has(e))return`material-icon-theme:${e}`}if("dockerfile"===n||n.startsWith("dockerfile."))return"material-icon-theme:docker";if(".env"===n||n.startsWith(".env."))return"material-icon-theme:settings";const s=t.lastIndexOf("."),a=s>0?t.substring(s+1).toLowerCase():"";if("ts"===a||"js"===a){const e=t.substring(0,s).toLowerCase();if(e.endsWith(".d"))return"material-icon-theme:typescript-def";if(e.endsWith(".test")||e.endsWith(".spec"))return"ts"===a?"material-icon-theme:test-ts":"material-icon-theme:test-js"}if("jsx"===a||"tsx"===a){const e=t.substring(0,s).toLowerCase();if(e.endsWith(".test")||e.endsWith(".spec"))return"tsx"===a?"material-icon-theme:test-ts":"material-icon-theme:test-jsx"}if(a&&m[a]){const e=m[a];if(d.has(e))return`material-icon-theme:${e}`}return i?function(t){switch(t){case e.IMAGE:return"material-icon-theme:image";case e.VIDEO:return"material-icon-theme:video";case e.MUSIC:return"material-icon-theme:audio";case e.CODE:return"material-icon-theme:javascript";case e.TEXT:return"material-icon-theme:document";case e.DOCUMENT:return"material-icon-theme:word";case e.PDF:return"material-icon-theme:pdf";case e.ARCHIVE:return"material-icon-theme:zip";case e.APPLICATION:return"material-icon-theme:exe";default:return"material-icon-theme:document"}}(i):"material-icon-theme:document"}var h=new Set(["admin","android","angular","animation","ansible","api","apollo","app","archive","astro","atom","attachment","audio","aurelia","aws","azure-pipelines","backup","base","batch","benchmark","bibliography","bicep","blender","bloc","bower","buildkite","cart","changesets","ci","circleci","class","claude","client","cline","cloud-functions","cloudflare","cluster","cobol","command","components","config","connection","console","constant","container","content","context","contract","controller","core","coverage","css","cue","cursor","custom","cypress","dal","dart","database","debug","decorators","delta","desktop","directive","dist","docker","docs","download","drizzle","dump","element","enum","environment","error","eslint","event","examples","expo","export","fastlane","favicon","features","filter","firebase","firestore","flow","flutter","font","forgejo","functions","gamemaker","generator","gh-workflows","git","gitea","github","gitlab","global","godot","gradle","graphql","guard","gulp","helm","helper","home","hook","husky","i18n","images","import","include","input","intellij","interceptor","interface","ios","java","javascript","jinja","job","json","jupyter","keys","kubernetes","kusto","layout","lefthook","less","lib","license","link","linux","liquibase","log","lottie","lua","luau","macos","mail","mappings","markdown","mercurial","messages","meta","metro","middleware","migrations","mjml","mobile","mock","mojo","molecule","moon","netlify","next","ngrx-store","node","nuxt","obsidian","organism","other","packages","pdf","pdm","php","phpmailer","pipe","plastic","plugin","policy","powershell","prisma","private","project","prompts","proto","public","python","pytorch","quasar","queue","react-components","redux-reducer","repository","resolver","resource","review","robot","routes","rules","rust","salt","sandbox","sass","scala","scons","scripts","secure","seeders","server","serverless","shader","shared","simulations","snapcraft","snippet","src","src-tauri","stack","stencil","store","storybook","stylus","sublime","supabase","svelte","svg","syntax","target","taskfile","tasks","television","temp","template","terraform","test","theme","toc","tools","trash","trigger","turborepo","typescript","ui","unity","update","upload","utils","vercel","verdaccio","video","views","vm","vscode","vue","vue-directives","vuepress","vuex-store","wakatime","webpack","windows","wordpress","yarn","zeabur"]),g={tests:"test",__tests__:"test",__test__:"test",spec:"test",specs:"test",script:"scripts",configs:"config",configuration:"config",configurations:"config",route:"routes",routing:"routes",stories:"storybook",story:"storybook",templates:"template",themes:"theme",videos:"video",imgs:"images",img:"images",image:"images",fonts:"font",styles:"css",style:"css",styling:"css",stylesheets:"css",view:"views",pages:"views",page:"views",layouts:"layout",models:"database",model:"database",modules:"lib",module:"lib",mods:"lib",plugins:"plugin",addons:"plugin",extensions:"plugin",middlewares:"middleware",helpers:"helper",utilities:"utils",util:"utils",tool:"tools",tooling:"tools",resources:"resource",res:"resource",assets:"resource",asset:"resource",hooks:"hook",composables:"hook",mocks:"mock",__mocks__:"mock",fixtures:"mock",__fixtures__:"mock",logs:"log",uploads:"upload",function:"functions",func:"functions",fns:"functions",services:"server",service:"server",component:"components",comp:"components",comps:"components",controllers:"controller",source:"src",sources:"src",distribution:"dist",build:"dist",builds:"dist",out:"dist",output:"dist",documentation:"docs",doc:"docs",document:"docs",documents:"docs",static:"public",statics:"public",publics:"public",libs:"lib",library:"lib",vendor:"lib",vendors:"lib",bin:"scripts",binaries:"scripts",tmp:"temp",temporary:"temp",cache:"temp",caches:"temp",".cache":"temp",".turbo":"temp",types:"typescript","@types":"typescript",typings:"typescript",dts:"typescript",locales:"i18n",locale:"i18n",lang:"i18n",languages:"i18n",translations:"i18n",db:"database",databases:"database",sql:"database",queries:"database",migration:"migrations",seeds:"seeders",seed:"seeders",".vscode":"vscode",".github":"github",".gitlab":"gitlab",".circleci":"circleci",".husky":"husky",".docker":"docker",node_modules:"node",scss:"sass",renderer:"client",frontend:"client",web:"client",webapp:"client",website:"client",backend:"server",main:"server",preload:"scripts",".idea":"intellij",".git":"git",k8s:"kubernetes",kube:"kubernetes",mongo:"database",mongodb:"database",mysql:"database",postgres:"database",api:"api",apis:"api",interfaces:"interface",notebook:"jupyter",notebooks:"jupyter",ipynb:"jupyter",notification:"messages",notifications:"messages",env:"environment",envs:"environment",redux:"redux-reducer",store:"store",stores:"store",electron:"desktop",tauri:"src-tauri"};import{jsx as f}from"react/jsx-runtime";function v({type:t,name:i,className:n="",size:s=24}){const a=l(()=>{if(t===e.FOLDER){const e=i?function(e){const t=(e||"").trim();if(!t)return;const i=t.replace(/[\\/]+$/,"").toLowerCase(),n=g[i]??i;return h.has(n)?`material-icon-theme:folder-${n}`:void 0}(i):void 0;return e??"ic:round-folder"}if(i)return p(i,t);switch(t){case e.IMAGE:return"material-icon-theme:image";case e.TEXT:return"material-icon-theme:document";case e.CODE:return"material-icon-theme:javascript";case e.MUSIC:return"material-icon-theme:audio";case e.VIDEO:return"material-icon-theme:video";case e.PDF:return"material-icon-theme:pdf";case e.DOCUMENT:return"material-icon-theme:word";case e.APPLICATION:return"material-icon-theme:exe";case e.ARCHIVE:return"material-icon-theme:zip";default:return"material-icon-theme:document"}},[t,i]),o=l(()=>{const i="file-icon";switch(t){case e.FOLDER:return`${i} file-icon--folder`;case e.IMAGE:return`${i} file-icon--image`;case e.TEXT:return`${i} file-icon--text`;case e.CODE:return`${i} file-icon--code`;case e.MUSIC:return`${i} file-icon--music`;case e.VIDEO:return`${i} file-icon--video`;case e.PDF:case e.DOCUMENT:return`${i} file-icon--pdf`;case e.APPLICATION:return`${i} file-icon--application`;case e.ARCHIVE:return`${i} file-icon--archive`;default:return`${i} file-icon--default`}},[t]);return f("div",{className:n,children:f(c,{icon:a,width:s,height:s,className:o})})}import{Fragment as b,jsx as w,jsxs as y}from"react/jsx-runtime";function x({name:e,isFolder:t,isSelected:i,onClick:n}){const{baseName:s,ext:a}=r(()=>function(e,t){if(t)return{baseName:e,ext:""};const i=e.lastIndexOf(".");return i<=0?{baseName:e,ext:""}:{baseName:e.substring(0,i),ext:e.substring(i)}}(e,t),[e,t]);return w("span",{onClick:n,className:"file-grid-item-name "+(i?"file-grid-item-name--selected":""),title:e,children:a?y(b,{children:[w("span",{className:"file-grid-item-name-base",children:s}),w("span",{className:"file-grid-item-name-ext",children:a})]}):w("span",{className:"file-grid-item-name-base file-grid-item-name-base--two-lines",children:s})})}function N({items:t,selectedIds:i,editingId:n,dragOverId:s,getAppIconUrl:a,onSelect:r,onOpen:l,onContextMenu:c,onContextMenuEmpty:d,onNameClick:m,onRename:u,onRenameCancel:p,onDragStart:h,onDragOver:g,onDragLeave:f,onDrop:b,onThumbnailError:N}){const k=o(null);return w("div",{className:"file-grid",onContextMenu:e=>{e.preventDefault(),(e=>{e.target.closest(".file-grid-item")||d?.(e)})(e)},children:t.map(o=>{const d=i.has(o.id),j=n===o.id,C=s===o.id,E=(t=>!(t.type!==e.APPLICATION||!a?.(t))||(t.type===e.IMAGE||t.type===e.VIDEO)&&!!t.thumbnailUrl)(o),I=o.type===e.APPLICATION?a?.(o):void 0;let D="file-grid-item";return D+=d&&!j?" file-grid-item--selected":C?" file-grid-item--drag-over":" file-grid-item--normal",y("div",{draggable:!j,onDragStart:e=>h?.(e,o),onDragOver:e=>{e.preventDefault(),g?.(e,o)},onDragLeave:e=>f?.(e),onDrop:e=>{e.preventDefault(),b?.(e,o)},onClick:e=>{e.stopPropagation(),r?.(o,e)},onDoubleClick:e=>{e.stopPropagation(),l?.(o)},onContextMenu:e=>{e.preventDefault(),e.stopPropagation(),c?.(o,e)},className:D,children:[y("div",{className:"file-grid-item-icon",children:[I&&w("img",{src:I,alt:o.name,className:"file-grid-item-thumbnail file-grid-item-thumbnail--application "+(d&&!j?"file-grid-item-thumbnail--selected":"")}),!I&&o.type===e.VIDEO&&o.thumbnailUrl&&E&&y("div",{className:"file-grid-item-thumbnail file-grid-item-thumbnail--video",children:[w("img",{src:o.thumbnailUrl,alt:o.name,className:"file-grid-item-thumbnail",onError:e=>N?.(o,e)}),w("div",{className:"file-grid-item-video-play",children:w("div",{className:"file-grid-item-video-play-icon"})})]}),!I&&o.type===e.IMAGE&&o.thumbnailUrl&&E&&w("img",{src:o.thumbnailUrl,alt:o.name,className:"file-grid-item-thumbnail",onError:e=>N?.(o,e)}),!I&&!E&&w(v,{type:o.type,name:o.name,size:48})]}),w("div",{className:"file-grid-item-name-wrapper",children:j?w("input",{ref:k,type:"text",className:"file-grid-item-rename-input",defaultValue:o.name,onBlur:e=>((e,t)=>{const i=t.target.value.trim();i&&i!==e.name?u?.(e,i):p?.(e)})(o,e),onKeyDown:e=>{"Enter"===e.key?(e=>{e.currentTarget.blur()})(e):"Escape"===e.key&&(e=>{const i=e.currentTarget,s=t.find(e=>e.id===n);s&&(i.value=s.name),i.blur()})(e)},autoFocus:!0}):w(x,{name:o.name,isFolder:o.type===e.FOLDER,isSelected:d,onClick:e=>{e.stopPropagation(),m?.(o,e)}})})]},o.id)})})}import{useRef as k}from"react";import{Icon as j}from"@iconify/react";import{jsx as C}from"react/jsx-runtime";function E({direction:e}){return C("span",{className:"sort-indicator",children:C(j,{icon:"asc"===e?"lucide:chevron-up":"lucide:chevron-down",width:12,height:12})})}import{jsx as I,jsxs as D}from"react/jsx-runtime";function M({items:t,selectedIds:i,sortConfig:n,editingId:s,dragOverId:a,onSelect:o,onOpen:r,onContextMenu:l,onContextMenuEmpty:c,onNameClick:d,onRename:m,onRenameCancel:u,onSort:p,onDragStart:h,onDragOver:g,onDragLeave:f,onDrop:b}){const w=k(null);return I("div",{className:"file-list",onContextMenu:e=>{e.preventDefault(),(e=>{e.target.closest("tr")||c?.(e)})(e)},children:D("table",{className:"file-list-table",children:[I("thead",{className:"file-list-header",children:D("tr",{children:[D("th",{className:"file-list-header-cell file-list-header-cell--name",onClick:()=>p?.("name"),children:["名称","name"===n?.field&&I(E,{direction:n.direction})]}),D("th",{className:"file-list-header-cell",onClick:()=>p?.("dateModified"),children:["修改日期","dateModified"===n?.field&&I(E,{direction:n.direction})]}),D("th",{className:"file-list-header-cell",onClick:()=>p?.("size"),children:["大小","size"===n?.field&&I(E,{direction:n.direction})]}),D("th",{className:"file-list-header-cell",onClick:()=>p?.("type"),children:["类型","type"===n?.field&&I(E,{direction:n.direction})]})]})}),I("tbody",{className:"file-list-body",children:t.map((n,c)=>{const p=i.has(n.id),y=s===n.id,x=a===n.id;let N="file-list-row";return N+=p?" file-list-row--selected":x?" file-list-row--drag-over":c%2==0?" file-list-row--even":" file-list-row--odd",D("tr",{draggable:!y,onDragStart:e=>h?.(e,n),onDragOver:e=>{e.preventDefault(),g?.(e,n)},onDragLeave:e=>f?.(e),onDrop:e=>{e.preventDefault(),b?.(e,n)},onClick:e=>{e.stopPropagation(),o?.(n,e)},onDoubleClick:e=>{e.stopPropagation(),r?.(n)},onContextMenu:e=>{e.preventDefault(),e.stopPropagation(),l?.(n,e)},className:N,children:[D("td",{className:"file-list-cell file-list-cell--name "+(p?"file-list-cell--selected":""),children:[I(v,{type:n.type,name:n.name,size:16}),y?I("input",{ref:w,type:"text",className:"file-list-rename-input",defaultValue:n.name,onBlur:e=>((e,t)=>{const i=t.target.value.trim();i&&i!==e.name?m?.(e,i):u?.(e)})(n,e),onKeyDown:e=>{"Enter"===e.key?(e=>{e.currentTarget.blur()})(e):"Escape"===e.key&&(e=>{const i=e.currentTarget,n=t.find(e=>e.id===s);n&&(i.value=n.name),i.blur()})(e)},autoFocus:!0}):I("span",{onClick:e=>{e.stopPropagation(),d?.(n,e)},className:"file-list-name "+(p?"file-list-name--selected":""),children:n.name})]}),I("td",{className:"file-list-cell "+(p?"file-list-cell--selected":""),children:n.dateModified||"--"}),I("td",{className:"file-list-cell file-list-cell--size "+(p?"file-list-cell--selected":""),children:n.size||"--"}),I("td",{className:"file-list-cell "+(p?"file-list-cell--selected":""),children:(k=n.type,{[e.FOLDER]:"文件夹",[e.FILE]:"文件",[e.IMAGE]:"图片",[e.VIDEO]:"视频",[e.MUSIC]:"音频",[e.DOCUMENT]:"文档",[e.CODE]:"代码",[e.TEXT]:"文本",[e.PDF]:"PDF",[e.ARCHIVE]:"压缩包",[e.APPLICATION]:"应用程序",[e.UNKNOWN]:"未知"}[k]||k)})]},n.id);var k})})]})})}import{jsx as z,jsxs as O}from"react/jsx-runtime";var S=s(({items:s,viewMode:o="grid",loading:r=!1,adapter:l,currentPath:c,getAppIconUrl:d,onOpen:m,onSelectionChange:u,onContextMenu:p,onContextMenuEmpty:h,onRename:g,onSortChange:f,onMove:v},b)=>{const[w,y]=t(new Set),[x,k]=t(null),[j,C]=t(null),[E,I]=t({field:"name",direction:"asc"}),D=s.filter(e=>w.has(e.id)),S=i((e,t)=>{if(t.metaKey||t.ctrlKey)y(t=>{const i=new Set(t);i.has(e.id)?i.delete(e.id):i.add(e.id);const n=s.filter(e=>i.has(e.id));return u?.(i,n),i});else if(t.shiftKey&&w.size>0){const t=Array.from(w).pop(),i=s.findIndex(e=>e.id===t),n=s.findIndex(t=>t.id===e.id),a=Math.min(i,n),o=Math.max(i,n),r=new Set;for(let e=a;e<=o;e++)r.add(s[e].id);y(r);const l=s.filter(e=>r.has(e.id));u?.(r,l)}else{const t=new Set([e.id]);y(t),u?.(t,[e])}},[s,w,u]),L=i(e=>{e.target===e.currentTarget&&P()},[]),P=i(()=>{y(new Set),u?.(new Set,[])},[u]),T=i(e=>{m?.(e)},[m]),$=i((e,t)=>{if(!w.has(e.id)){const t=new Set([e.id]);y(t),u?.(t,[e])}p?.(t,e)},[w,u,p]),A=i(e=>{const t=e.target;t.closest(".file-grid-item")||t.closest(".file-list-row")||(P(),h?.(e))},[P,h]),R=i(e=>{P(),h?.(e)},[P,h]),U=i((e,t)=>{w.has(e.id)&&1===w.size&&setTimeout(()=>{w.has(e.id)&&k(e.id)},500)},[w]),F=i((e,t)=>{t&&t!==e.name&&g?.(e,t),k(null)},[g]),V=i(()=>{k(null)},[]),W=i(e=>{I(t=>{const i=t.field===e?{...t,direction:"asc"===t.direction?"desc":"asc"}:{field:e,direction:"asc"};return f?.(i),i})},[f]),q=i((e,t)=>{if(!w.has(t.id)){const e=new Set([t.id]);y(e),u?.(e,[t])}e.dataTransfer.setData("text/plain",JSON.stringify([...w]))},[w,u]),H=i((t,i)=>{i.type!==e.FOLDER||w.has(i.id)||C(i.id)},[w]),_=i(()=>{C(null)},[]),G=i((t,i)=>{if(C(null),i.type!==e.FOLDER)return;const n=t.dataTransfer.getData("text/plain");if(n)try{const e=JSON.parse(n);if(e.includes(i.id))return;v?.(e,i.id),P()}catch(e){}},[v,P]),B=i(e=>{k(e)},[]),X=i(()=>{const e=new Set(s.map(e=>e.id));y(e),u?.(e,s)},[s,u]);return n(b,()=>({clearSelection:P,startRename:B,selectAll:X,selectedIds:w,selectedItems:D}),[w,D,P,B,X]),O("div",{className:"file-list-view",onClick:L,onContextMenu:e=>{e.preventDefault(),A(e)},children:[r&&O("div",{className:"file-list-view-loading",children:[z("div",{className:"file-list-view-spinner"}),z("p",{children:"加载中..."})]}),!r&&0===s.length&&O("div",{className:"file-list-view-empty",children:[z(a,{icon:"lucide:folder-open",width:64,height:64,className:"file-list-view-empty-icon"}),z("p",{children:"文件夹为空"})]}),!r&&s.length>0&&"grid"===o&&z(N,{items:s,selectedIds:w,editingId:x,dragOverId:j,getAppIconUrl:d,onSelect:S,onOpen:T,onContextMenu:$,onContextMenuEmpty:R,onNameClick:U,onRename:F,onRenameCancel:V,onDragStart:q,onDragOver:H,onDragLeave:_,onDrop:G}),!r&&s.length>0&&"list"===o&&z(M,{items:s,selectedIds:w,editingId:x,dragOverId:j,sortConfig:E,onSelect:S,onOpen:T,onContextMenu:$,onContextMenuEmpty:R,onNameClick:U,onRename:F,onRenameCancel:V,onSort:W,onDragStart:q,onDragOver:H,onDragLeave:_,onDrop:G})]})});S.displayName="FileListView";import{Icon as L}from"@iconify/react";import{jsx as P,jsxs as T}from"react/jsx-runtime";function $({sections:e,activeId:t,onNavigate:i}){return P("div",{className:"file-sidebar",children:e.map(e=>T("div",{className:"file-sidebar-section",children:[P("div",{className:"file-sidebar-section-title",children:e.title}),P("ul",{className:"file-sidebar-list",children:e.items.map(e=>{const n=t===e.id;return T("li",{onClick:()=>(e=>{i?.(e)})(e),className:"file-sidebar-item "+(n?"file-sidebar-item--active":""),children:[P(L,{icon:(s=e.icon,s?s.includes(":")?s:`lucide:${s.toLowerCase()}`:"mdi:folder"),width:18,height:18,className:n?"file-sidebar-item-icon--active":"file-sidebar-item-icon"}),P("span",{children:e.label})]},e.id);var s})})]},e.id))})}import{Icon as A}from"@iconify/react";import{Icon as R}from"@iconify/react";import{jsx as U,jsxs as F}from"react/jsx-runtime";function V({items:e,onNavigate:t}){return U("div",{className:"file-breadcrumb",children:e.map((i,n)=>F("span",{className:"file-breadcrumb-item",children:[U("span",{onClick:()=>((i,n)=>{n<e.length-1&&t?.(i,n)})(i,n),className:"file-breadcrumb-link "+(n===e.length-1?"file-breadcrumb-link--current":""),children:i.name}),n<e.length-1&&U(R,{icon:"lucide:chevron-right",width:14,height:14,className:"file-breadcrumb-separator"})]},i.id))})}import{jsx as W,jsxs as q}from"react/jsx-runtime";function H({canGoBack:e=!1,canGoForward:t=!1,breadcrumbs:i=[],viewMode:n="grid",searchQuery:s="",showSearch:a=!1,showViewToggle:o=!0,draggable:r=!1,onBack:l,onForward:c,onBreadcrumbNavigate:d,onViewModeChange:m,onSearchQueryChange:u,children:p,breadcrumbSlot:h,actionsSlot:g}){return q("div",{className:"file-toolbar "+(r?"file-toolbar--draggable":""),children:[q("div",{className:"file-toolbar-nav",children:[W("button",{className:"file-toolbar-button",onClick:l,disabled:!e,title:"后退",children:W(A,{icon:"lucide:chevron-left",width:18,height:18})}),W("button",{className:"file-toolbar-button",onClick:c,disabled:!t,title:"前进",children:W(A,{icon:"lucide:chevron-right",width:18,height:18})})]}),W("div",{className:"file-toolbar-breadcrumb",children:h||i.length>0&&W(V,{items:i,onNavigate:d})}),p&&W("div",{className:"file-toolbar-custom",children:p}),q("div",{className:"file-toolbar-actions",children:[a&&q("div",{className:"file-toolbar-search",children:[W(A,{icon:"lucide:search",width:16,height:16,className:"file-toolbar-search-icon"}),W("input",{type:"text",value:s,onChange:e=>u?.(e.target.value),placeholder:"搜索",className:"file-toolbar-search-input"})]}),o&&q("div",{className:"file-toolbar-view-toggle",children:[W("button",{onClick:()=>m?.("grid"),className:"file-toolbar-button "+("grid"===n?"file-toolbar-button--active":""),title:"网格视图",children:W(A,{icon:"lucide:layout-grid",width:18,height:18})}),W("button",{onClick:()=>m?.("list"),className:"file-toolbar-button "+("list"===n?"file-toolbar-button--active":""),title:"列表视图",children:W(A,{icon:"lucide:list",width:18,height:18})})]}),g]})]})}import{Fragment as _,jsx as G,jsxs as B}from"react/jsx-runtime";function X({itemCount:e=0,selectedCount:t=0,children:i}){return G("div",{className:"file-status-bar",children:i||B(_,{children:[B("span",{children:[e," 个项目"]}),t>0&&B("span",{children:[" • 已选择 ",t," 个"]})]})})}import{createPortal as K}from"react-dom";import{useMemo as J,useEffect as Y,useRef as Z,useCallback as Q,useState as ee}from"react";import{Icon as te}from"@iconify/react";import{jsx as ie,jsxs as ne}from"react/jsx-runtime";var se=220;function ae(e){let t=8;for(const i of e)t+=i.separator?9:32;return t}function oe({visible:e,x:t,y:i,options:n,onClose:s,onSelect:a}){const o=Z(null),[r,l]=ee(null),[c,d]=ee(null),m=Z(new Map),u=J(()=>{const e=ae(n);return function(e,t,i){const n=window.innerWidth,s=window.innerHeight;let a=e,o=t;const r=n-e;r<228&&(a=e>=228?e-se:r>e?n-se-8:8);const l=s-t;return l<i+8&&(o=t>=i+8?t-i:l>t?s-i-8:8),a=Math.max(8,Math.min(a,n-se-8)),o=Math.max(8,Math.min(o,s-i-8)),{x:a,y:o}}(t,i,e)},[t,i,n]),p=J(()=>({left:`${u.x}px`,top:`${u.y}px`}),[u]),h=J(()=>r?n.find(e=>e.id===r&&e.children&&e.children.length>0):null,[r,n]);Y(()=>{if(!r||!h)return void d(null);const e=m.current.get(r);if(!e)return void d(null);const t=function(e,t){const i=window.innerWidth,n=window.innerHeight,s=i-e.right,a=e.left;let o,r;return o=s>=228?e.right+0:a>=228?e.left-se-0:s>a?i-se-8:8,r=e.top,r+t>n-8&&(r=n-t-8),r<8&&(r=8),{x:o,y:r}}(e.getBoundingClientRect(),ae(h.children||[]));d(t)},[r,h]),Y(()=>{if(!e)return;const t=e=>{const t=e.target,i=document.querySelector(".context-menu-container");i&&i.contains(t)||s?.()},i=e=>{"Escape"===e.key&&s?.()};return document.addEventListener("mousedown",t),document.addEventListener("keydown",i),()=>{document.removeEventListener("mousedown",t),document.removeEventListener("keydown",i)}},[e,s]),Y(()=>{e||(l(null),d(null))},[e]);const g=e=>e?ie(te,{icon:e,width:16,height:16,className:"context-menu-item-icon"}):null,f=Q(e=>{e.disabled||e.children&&e.children.length>0||(e.action&&e.action(),a?.(e),s?.())},[s,a]),v=Q(e=>{e.children&&e.children.length>0?l(e.id):l(null)},[]);return e?K(ne("div",{className:"context-menu-container",children:[ie("div",{ref:o,className:"context-menu",style:p,children:n.map((e,t)=>{if(e.separator)return ie("div",{className:"context-menu-separator"},t);const i=e.children&&e.children.length>0,n=r===e.id;return ne("div",{ref:t=>{t?m.current.set(e.id,t):m.current.delete(e.id)},className:`context-menu-item ${e.disabled?"context-menu-item--disabled":""} ${e.danger?"context-menu-item--danger":""} ${i?"context-menu-item--has-children":""} ${n?"context-menu-item--active":""}`,onClick:()=>f(e),onMouseEnter:()=>v(e),children:[e.icon&&g(e.icon),ie("span",{className:"context-menu-item-label",children:e.label}),e.checked&&ie(te,{icon:"lucide:check",width:14,height:14,className:"context-menu-item-check"}),e.shortcut&&!i&&ie("span",{className:"context-menu-item-shortcut",children:e.shortcut}),i&&ie(te,{icon:"lucide:chevron-right",width:14,height:14,className:"context-menu-item-arrow"})]},e.id||t)})}),h&&c&&ie("div",{className:"context-menu context-menu-submenu",style:{left:`${c.x}px`,top:`${c.y}px`},onMouseEnter:()=>l(h.id),onMouseLeave:()=>l(null),children:h.children.map((e,t)=>e.separator?ie("div",{className:"context-menu-separator"},`child-sep-${t}`):ne("div",{className:`context-menu-item ${e.disabled?"context-menu-item--disabled":""} ${e.danger?"context-menu-item--danger":""}`,onClick:()=>f(e),children:[e.icon&&g(e.icon),ie("span",{className:"context-menu-item-label",children:e.label}),e.checked&&ie(te,{icon:"lucide:check",width:14,height:14,className:"context-menu-item-check"}),e.shortcut&&ie("span",{className:"context-menu-item-shortcut",children:e.shortcut})]},e.id||t))})]}),document.body):null}import{createPortal as re}from"react-dom";import{useMemo as le,useRef as ce,useEffect as de}from"react";import{Icon as me}from"@iconify/react";import{useState as ue,useCallback as pe,useEffect as he}from"react";function ge(){const[e,t]=ue({x:0,y:0}),[i,n]=ue(!1),s=pe(e=>{i&&t(t=>({x:t.x+e.movementX,y:t.y+e.movementY}))},[i]),a=pe(()=>{n(!1)},[]),o=pe(e=>{const t=e.target;t.closest(".draggable-area")&&!t.closest("button")&&(e.preventDefault(),n(!0))},[]);return he(()=>{if(i)return window.addEventListener("mousemove",s),window.addEventListener("mouseup",a),()=>{window.removeEventListener("mousemove",s),window.removeEventListener("mouseup",a)}},[i,s,a]),{position:e,isDragging:i,startDrag:o}}import{useState as fe,useCallback as ve,useEffect as be}from"react";function we(e,t,i,n,s,a){const[o,r]=fe(e),[l,c]=fe(t),[d,m]=fe(!1),[u,p]=fe(null),[h,g]=fe(0),[f,v]=fe(0),[b,w]=fe(0),[y,x]=fe(0),N=ve(e=>{if(!d||!u)return;const t=e.clientX-h,o=e.clientY-f;let l=b,m=y;const p=u;p.includes("e")?l=Math.min(Math.max(b+t,i),s):p.includes("w")&&(l=Math.min(Math.max(b-t,i),s)),p.includes("s")?m=Math.min(Math.max(y+o,n),a):p.includes("n")&&(m=Math.min(Math.max(y-o,n),a)),r(l),c(m)},[d,u,h,f,b,y,i,n,s,a]),k=ve(()=>{m(!1),p(null)},[]),j=ve((e,t,i,n)=>{e.preventDefault(),e.stopPropagation(),m(!0),p(t),g(e.clientX),v(e.clientY),w(i),x(n)},[]),C=ve(e=>({n:"n-resize",s:"s-resize",e:"e-resize",w:"w-resize",ne:"ne-resize",nw:"nw-resize",se:"se-resize",sw:"sw-resize"}[e]),[]);return be(()=>{if(d)return window.addEventListener("mousemove",N),window.addEventListener("mouseup",k),document.body.style.cursor=C(u||"se"),document.body.style.userSelect="none",()=>{window.removeEventListener("mousemove",N),window.removeEventListener("mouseup",k),document.body.style.cursor="",document.body.style.userSelect=""}},[d,u,N,k,C]),{width:o,height:l,isResizing:d,startResize:j}}import{Fragment as ye,jsx as xe,jsxs as Ne}from"react/jsx-runtime";function ke({title:e,showTitleBar:t=!0,showMinimize:i=!1,showMaximize:n=!1,draggable:s=!0,resizable:a=!0,closeOnBackdrop:o=!0,width:r="auto",height:l="auto",minWidth:c=300,minHeight:d=200,maxWidth:m="80vw",maxHeight:u="80vh",fitContent:p=!1,onClose:h,onMinimize:g,onMaximize:f,children:v,titleSlot:b,actionsSlot:w}){const y=ce(null),x=s?ge():null,N=le(()=>p||"auto"===r||"fit-content"===r||"auto"===l||"fit-content"===l,[p,r,l]),k=(e,t)=>{if("number"==typeof e)return e;if("string"==typeof e){if(e.endsWith("px"))return parseInt(e);if(e.endsWith("vw"))return parseInt(e)/100*window.innerWidth;if(e.endsWith("vh"))return parseInt(e)/100*window.innerHeight}return t},{initialWidth:j,initialHeight:C}=(()=>{if(N)return{initialWidth:0,initialHeight:0};let e=600,t=500;return"auto"!==r&&"fit-content"!==r&&(e="number"==typeof r?r:parseInt(r)),"auto"!==l&&"fit-content"!==l&&(t="number"==typeof l?l:parseInt(l)),{initialWidth:e,initialHeight:t}})(),E=k(c,500),I=k(d,350),D=k(m,.8*window.innerWidth),M=k(u,.8*window.innerHeight),z=a?we(j,C,E,I,D,M):null,O=le(()=>{const e={left:"50%",top:"50%"};let t="-50%",i="-50%";return s&&x&&(t=`calc(-50% + ${x.position.x}px)`,i=`calc(-50% + ${x.position.y}px)`),e.transform=`translate(${t}, ${i})`,e.transformOrigin="center center",N?a&&z&&z.width>0&&(e.width=`${z.width}px`,e.height=`${z.height}px`):a&&z?(e.width=`${z.width}px`,e.height=`${z.height}px`):("auto"!==r&&"fit-content"!==r&&(e.width="number"==typeof r?`${r}px`:r),"auto"!==l&&"fit-content"!==l&&(e.height="number"==typeof l?`${l}px`:l)),c&&(e.minWidth="number"==typeof c?`${c}px`:c),d&&(e.minHeight="number"==typeof d?`${d}px`:d),m&&(e.maxWidth="number"==typeof m?`${m}px`:m),u&&(e.maxHeight="number"==typeof u?`${u}px`:u),e},[s,x,N,a,z,r,l,c,d,m,u]),S=(e,t)=>{if(!a||!z||!y.current)return;const i=y.current.getBoundingClientRect(),n=i.width,s=i.height;z.startResize(e,t,n,s)};return de(()=>{const e=e=>{"Escape"===e.key&&(e.preventDefault(),h?.())};return window.addEventListener("keydown",e),()=>{window.removeEventListener("keydown",e)}},[h]),re(xe("div",{className:"window-overlay",onClick:e=>{o&&e.target===e.currentTarget&&h?.()},children:Ne("div",{ref:y,className:"window-container",style:O,onClick:e=>e.stopPropagation(),children:[t&&Ne("div",{className:"window-title-bar draggable-area",onMouseDown:e=>{s&&x&&x.startDrag(e)},children:[Ne("div",{className:"window-controls",children:[xe("button",{onClick:e=>{e.stopPropagation(),h?.()},className:"window-control-button window-control-button--close",children:xe(me,{icon:"lucide:x",width:7,height:7,className:"window-control-icon"})}),i&&xe("button",{onClick:e=>{e.stopPropagation(),g?.()},className:"window-control-button window-control-button--minimize",children:xe(me,{icon:"lucide:minus",width:7,height:7,className:"window-control-icon"})}),n&&xe("button",{onClick:e=>{e.stopPropagation(),f?.()},className:"window-control-button window-control-button--maximize",children:xe(me,{icon:"lucide:maximize-2",width:7,height:7,className:"window-control-icon"})})]}),xe("div",{className:"window-title-info",children:b||xe("span",{className:"window-title-text",children:e})}),xe("div",{className:"window-title-actions",children:w})]}),xe("div",{className:"window-content",children:v}),a&&Ne(ye,{children:[xe("div",{className:"window-resize-handle window-resize-handle--n",onMouseDown:e=>S(e,"n")}),xe("div",{className:"window-resize-handle window-resize-handle--s",onMouseDown:e=>S(e,"s")}),xe("div",{className:"window-resize-handle window-resize-handle--e",onMouseDown:e=>S(e,"e")}),xe("div",{className:"window-resize-handle window-resize-handle--w",onMouseDown:e=>S(e,"w")}),xe("div",{className:"window-resize-handle window-resize-handle--ne",onMouseDown:e=>S(e,"ne")}),xe("div",{className:"window-resize-handle window-resize-handle--nw",onMouseDown:e=>S(e,"nw")}),xe("div",{className:"window-resize-handle window-resize-handle--se",onMouseDown:e=>S(e,"se")}),xe("div",{className:"window-resize-handle window-resize-handle--sw",onMouseDown:e=>S(e,"sw")})]})]})}),document.body)}import{useState as je,useMemo as Ce,useEffect as Ee}from"react";import{createPortal as Ie}from"react-dom";import{Icon as De}from"@iconify/react";import{jsx as Me,jsxs as ze}from"react/jsx-runtime";var Oe=[{value:"zip",label:"ZIP",ext:".zip"},{value:"tgz",label:"TAR.GZ (gzip)",ext:".tar.gz"},{value:"tarbz2",label:"TAR.BZ2 (bzip2)",ext:".tar.bz2"},{value:"tar",label:"TAR (无压缩)",ext:".tar"}],Se=[{value:"fast",label:"快速",desc:"压缩速度快,文件较大"},{value:"normal",label:"标准",desc:"平衡速度和大小"},{value:"best",label:"最佳",desc:"文件最小,速度较慢"}];function Le({visible:e,filePaths:t,outputDir:i,onConfirm:n,onCancel:s}){const[a,o]=je("zip"),[r,l]=je("normal"),[c,d]=je(""),[m,u]=je(!1),[p,h]=je(""),[g,f]=je(!1),v=Ce(()=>{if(0===t.length)return"archive";if(1===t.length){return(t[0].split("/").pop()||"archive").replace(/\.[^.]+$/,"")}return"压缩文件"},[t]);Ee(()=>{e&&(d(v),o("zip"),l("normal"),u(!1),h(""))},[e,v]);const b=Oe.find(e=>e.value===a)?.ext||".zip",w=`${i}/${c}${b}`;return e?Ie(Me("div",{className:"compress-dialog-overlay",onClick:s,children:ze("div",{className:"compress-dialog",onClick:e=>e.stopPropagation(),children:[ze("div",{className:"compress-dialog-header",children:[ze("div",{className:"compress-dialog-title",children:[Me(De,{icon:"lucide:archive",width:20,height:20}),Me("span",{children:"压缩文件"})]}),Me("button",{className:"compress-dialog-close",onClick:s,children:Me(De,{icon:"lucide:x",width:18,height:18})})]}),ze("div",{className:"compress-dialog-content",children:[ze("div",{className:"compress-dialog-info",children:[Me(De,{icon:"lucide:file-archive",width:16,height:16}),Me("span",{children:1===t.length?t[0].split("/").pop():`${t.length} 个项目`})]}),ze("div",{className:"compress-dialog-field",children:[Me("label",{children:"文件名"}),ze("div",{className:"compress-dialog-input-group",children:[Me("input",{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"输入文件名"}),Me("span",{className:"compress-dialog-ext",children:b})]})]}),ze("div",{className:"compress-dialog-field",children:[Me("label",{children:"压缩格式"}),Me("select",{value:a,onChange:e=>o(e.target.value),children:Oe.map(e=>Me("option",{value:e.value,children:e.label},e.value))})]}),ze("div",{className:"compress-dialog-field",children:[Me("label",{children:"压缩级别"}),Me("div",{className:"compress-dialog-levels",children:Se.map(e=>ze("label",{className:"compress-dialog-level",children:[Me("input",{type:"radio",name:"level",value:e.value,checked:r===e.value,onChange:()=>l(e.value)}),Me("span",{className:"compress-dialog-level-label",children:e.label}),Me("span",{className:"compress-dialog-level-desc",children:e.desc})]},e.value))})]}),!1,Me("div",{className:"compress-dialog-field compress-dialog-checkbox",children:ze("label",{children:[Me("input",{type:"checkbox",checked:m,onChange:e=>u(e.target.checked)}),Me("span",{children:"压缩后删除源文件"})]})}),ze("div",{className:"compress-dialog-preview",children:[Me("span",{className:"compress-dialog-preview-label",children:"输出位置:"}),Me("span",{className:"compress-dialog-preview-path",children:w})]})]}),ze("div",{className:"compress-dialog-footer",children:[Me("button",{className:"compress-dialog-btn compress-dialog-btn-cancel",onClick:s,children:"取消"}),Me("button",{className:"compress-dialog-btn compress-dialog-btn-confirm",onClick:()=>{n({format:a,level:r,outputName:c+b,deleteSource:m})},disabled:!c.trim(),children:"压缩"})]})]})}),document.body):null}import{createPortal as Pe}from"react-dom";import{Icon as Te}from"@iconify/react";import{jsx as $e,jsxs as Ae}from"react/jsx-runtime";function Re({visible:e,progress:t,onCancel:i,onClose:n,onOpenFolder:s}){const{type:a,status:o,percent:r,currentFile:l,processedCount:c,totalCount:d,error:m,outputPath:u}=t,p="compress"===a?"压缩文件":"解压文件",h="success"===o||"error"===o,g=()=>{h?n?.():i?.()};return e?Pe($e("div",{className:"progress-dialog-overlay",children:Ae("div",{className:"progress-dialog",children:[Ae("div",{className:"progress-dialog-header",children:[Ae("div",{className:"progress-dialog-title",children:[$e(()=>{switch(o){case"processing":return $e(Te,{icon:"lucide:loader-2",width:24,height:24,className:"progress-dialog-icon-spin"});case"success":return $e(Te,{icon:"lucide:check-circle",width:24,height:24,className:"progress-dialog-icon-success"});case"error":return $e(Te,{icon:"lucide:x-circle",width:24,height:24,className:"progress-dialog-icon-error"});default:return $e(Te,{icon:"lucide:archive",width:24,height:24})}},{}),$e("span",{children:p})]}),h&&$e("button",{className:"progress-dialog-close",onClick:g,children:$e(Te,{icon:"lucide:x",width:18,height:18})})]}),Ae("div",{className:"progress-dialog-content",children:[$e("div",{className:"progress-dialog-status",children:(()=>{switch(o){case"pending":return"准备中...";case"processing":return"compress"===a?"正在压缩...":"正在解压...";case"success":return"compress"===a?"压缩完成":"解压完成";case"error":return"操作失败";default:return""}})()}),"processing"===o&&Ae("div",{className:"progress-dialog-bar-container",children:[$e("div",{className:"progress-dialog-bar",children:$e("div",{className:"progress-dialog-bar-fill",style:{width:`${r}%`}})}),Ae("span",{className:"progress-dialog-percent",children:[r,"%"]})]}),l&&"processing"===o&&$e("div",{className:"progress-dialog-current-file",children:l}),d&&d>0&&"processing"===o&&Ae("div",{className:"progress-dialog-count",children:[c||0," / ",d," 个文件"]}),m&&$e("div",{className:"progress-dialog-error",children:m}),"success"===o&&u&&Ae("div",{className:"progress-dialog-output",children:[$e("span",{className:"progress-dialog-output-label",children:"输出位置:"}),$e("span",{className:"progress-dialog-output-path",children:u})]})]}),Ae("div",{className:"progress-dialog-footer",children:["processing"===o&&i&&$e("button",{className:"progress-dialog-btn progress-dialog-btn-cancel",onClick:i,children:"取消"}),"success"===o&&u&&s&&Ae("button",{className:"progress-dialog-btn progress-dialog-btn-folder",onClick:()=>s(u),children:[$e(Te,{icon:"lucide:folder-open",width:16,height:16}),"打开文件夹"]}),h&&$e("button",{className:"progress-dialog-btn progress-dialog-btn-close",onClick:g,children:"关闭"})]})]})}),document.body):null}import Ue from"react";import{Icon as Fe}from"@iconify/react";import{jsx as Ve,jsxs as We}from"react/jsx-runtime";function qe(t,i){if(t===e.FOLDER)return Ve(Fe,{icon:"ic:round-folder",width:48,height:48,className:"file-info-icon"});if(i){const e=p(i,t);return Ve(Fe,{icon:e,width:48,height:48,className:"file-info-icon"})}return Ve(Fe,{icon:{[e.IMAGE]:"material-icon-theme:image",[e.VIDEO]:"material-icon-theme:video",[e.MUSIC]:"material-icon-theme:audio",[e.DOCUMENT]:"material-icon-theme:word",[e.CODE]:"material-icon-theme:javascript",[e.ARCHIVE]:"material-icon-theme:zip",[e.PDF]:"material-icon-theme:pdf",[e.TEXT]:"material-icon-theme:document",[e.APPLICATION]:"material-icon-theme:exe"}[t]||"material-icon-theme:document",width:48,height:48,className:"file-info-icon"})}function He(t,i){switch(t){case e.FOLDER:return"文件夹";case e.IMAGE:return"图片"+(i?` (${i.toUpperCase()})`:"");case e.VIDEO:return"视频"+(i?` (${i.toUpperCase()})`:"");case e.MUSIC:return"音频"+(i?` (${i.toUpperCase()})`:"");case e.DOCUMENT:return"文档"+(i?` (${i.toUpperCase()})`:"");case e.CODE:return"代码文件"+(i?` (${i.toUpperCase()})`:"");case e.ARCHIVE:return"压缩包"+(i?` (${i.toUpperCase()})`:"");default:return i?`${i.toUpperCase()} 文件`:"文件"}}function _e({visible:t,item:i,onClose:n}){if(!t||!i)return null;const s=function(e){const t=e.lastIndexOf(".");if(-1!==t&&0!==t)return e.substring(t+1).toLowerCase()}(i.name),a=function(e){const t=e.lastIndexOf("/");return-1===t?e:e.substring(0,t)||"/"}(i.id);return Ue.useEffect(()=>{const e=e=>{"Escape"===e.key&&n()};return t&&document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[t,n]),Ve("div",{className:"file-info-dialog-overlay",onClick:e=>{e.target===e.currentTarget&&n()},children:We("div",{className:"file-info-dialog",children:[We("div",{className:"file-info-dialog-header",children:[We("div",{className:"file-info-dialog-title",children:[qe(i.type,i.name),Ve("span",{className:"file-info-dialog-name",title:i.name,children:i.name})]}),Ve("button",{className:"file-info-dialog-close",onClick:n,children:Ve(Fe,{icon:"lucide:x",width:18,height:18})})]}),We("div",{className:"file-info-dialog-content",children:[We("div",{className:"file-info-row",children:[We("div",{className:"file-info-label",children:[Ve(Fe,{icon:"lucide:file",width:14,height:14}),Ve("span",{children:"类型"})]}),Ve("div",{className:"file-info-value",children:He(i.type,s)})]}),i.type!==e.FOLDER&&i.size&&We("div",{className:"file-info-row",children:[We("div",{className:"file-info-label",children:[Ve(Fe,{icon:"lucide:hard-drive",width:14,height:14}),Ve("span",{children:"大小"})]}),Ve("div",{className:"file-info-value",children:i.size})]}),We("div",{className:"file-info-row",children:[We("div",{className:"file-info-label",children:[Ve(Fe,{icon:"lucide:map-pin",width:14,height:14}),Ve("span",{children:"位置"})]}),Ve("div",{className:"file-info-value file-info-value--path",title:a,children:a})]}),We("div",{className:"file-info-row",children:[We("div",{className:"file-info-label",children:[Ve(Fe,{icon:"lucide:map-pin",width:14,height:14}),Ve("span",{children:"完整路径"})]}),Ve("div",{className:"file-info-value file-info-value--path",title:i.id,children:i.id})]}),i.dateModified&&We("div",{className:"file-info-row",children:[We("div",{className:"file-info-label",children:[Ve(Fe,{icon:"lucide:clock",width:14,height:14}),Ve("span",{children:"修改时间"})]}),Ve("div",{className:"file-info-value",children:i.dateModified})]})]}),Ve("div",{className:"file-info-dialog-footer",children:Ve("button",{className:"file-info-dialog-btn",onClick:n,children:"关闭"})})]})})}import{useState as Ge,useCallback as Be}from"react";function Xe(){const[e,t]=Ge(new Set),[i,n]=Ge(null),[s,a]=Ge(null),o=Be(()=>{t(new Set),n(null)},[]),r=Be((e,i,s=!1,a=!1)=>{e?t(o=>(n(n=>{if(a&&n){const a=i.findIndex(e=>e.id===n),r=i.findIndex(t=>t.id===e);if(-1!==a&&-1!==r){const n=Math.min(a,r),l=Math.max(a,r),c=new Set(s?o:[]);for(let e=n;e<=l;e++){const t=i[e];t&&c.add(t.id)}return t(c),e}}if(s){const i=new Set(o);return i.has(e)?i.delete(e):i.add(e),t(i),e}return t(new Set([e])),e}),o)):o()},[o]),l=Be(e=>{t(new Set(e.map(e=>e.id)))},[]),c=Be(e=>{a(e)},[]),d=Be(t=>e.has(t),[e]);return{selectedIds:e,lastSelectedId:i,editingId:s,clearSelection:o,selectItem:r,selectAll:l,setEditing:c,isSelected:d}}import{useState as Ke,useCallback as Je}from"react";function Ye(t,i,n){const[s,a]=Ke(null),[o,r]=Ke(!1),l=Je((e,n)=>{if(!e.dataTransfer)return;const s=t();s.has(n)||i(n,!1,!1);const a=s.has(n)?s:new Set([n]);e.dataTransfer.setData("text/plain",JSON.stringify([...a])),e.dataTransfer.effectAllowed="move",r(!0)},[t,i]),c=Je((i,n)=>{if(o&&n.type===e.FOLDER){t().has(n.id)||(i.preventDefault(),a(n.id))}},[o,t]),d=Je(()=>{a(null)},[]),m=Je((t,i)=>{if(a(null),r(!1),!t.dataTransfer||i.type!==e.FOLDER)return;const s=t.dataTransfer.getData("text/plain");if(s)try{const e=JSON.parse(s),t=new Set(e);if(t.has(i.id))return;n(i.id,t)}catch{}},[n]),u=Je(()=>{a(null),r(!1)},[]);return{dragOverId:s,isDragging:o,handleDragStart:l,handleDragOver:c,handleDragLeave:d,handleDrop:m,handleDragEnd:u}}import{useState as Ze,useCallback as Qe,useEffect as et}from"react";function tt(t,i){const[n,s]=Ze(!1),[a,o]=Ze(0),[r,l]=Ze(0),[c,d]=Ze(0),[m,u]=Ze(!1),[p,h]=Ze(1),[g,f]=Ze(1),[v,b]=Ze(!1),w=t===e.MUSIC,y=Qe(()=>{const e=i.current;if(e){const t=e.currentTime,i=e.duration;l(t),i&&!isNaN(i)&&(d(i),o(t/i*100))}},[i]),x=Qe(()=>{const e=i.current;e&&(n?(e.pause(),s(!1)):(e.play(),s(!0)))},[n,i]),N=Qe(()=>{const e=i.current;if(e)if(m){const t=g||1;e.volume=t,e.muted=!1,h(t),u(!1)}else f(p),e.volume=0,e.muted=!0,h(0),u(!0)},[m,g,p,i]),k=Qe(e=>{h(e);const t=i.current;t&&(t.volume=e,0===e?(u(!0),t.muted=!0):(u(!1),t.muted=!1))},[i]),j=Qe(e=>{const t=i.current;t&&c&&(t.currentTime=e,l(e),o(e/c*100))},[c,i]),C=Qe(e=>{if(isNaN(e))return"0:00";return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,"0")}`},[]),E=Qe(()=>{const n=i.current;(t===e.VIDEO||w)&&n&&(n.volume=p,n.play().catch(()=>{}),s(!0))},[t,w,p,i]);return et(()=>{const e=i.current;if(e)return e.addEventListener("timeupdate",y),e.addEventListener("loadedmetadata",y),e.addEventListener("ended",()=>{s(!1)}),()=>{e.removeEventListener("timeupdate",y),e.removeEventListener("loadedmetadata",y)}},[i,y]),{isPlaying:n,progress:a,currentTime:r,duration:c,isMuted:m,volume:p,showControls:v,isAudio:w,togglePlay:x,toggleMute:N,handleVolumeChange:k,seekTo:j,formatTime:C,autoPlay:E,updateProgress:y}}import{useState as it,useCallback as nt,useEffect as st}from"react";function at(t){const i=new Map,[n,s]=it(new Map),a=nt(async t=>{if(t.type===e.APPLICATION&&t.id){if(i.has(t.id)){const e=i.get(t.id);return void(e&&s(i=>new Map(i).set(t.id,e)))}if(!n.has(t.id)&&void 0!==window.fileExplorerAPI&&window.fileExplorerAPI.getApplicationIcon)try{const e=await window.fileExplorerAPI.getApplicationIcon(t.id);e&&(i.set(t.id,e),s(i=>new Map(i).set(t.id,e)))}catch(e){}}},[n]);st(()=>{t.forEach(t=>{t.type!==e.APPLICATION||n.has(t.id)||a(t)})},[t,n,a]);return{getAppIconUrl:nt(e=>n.get(e.id),[n]),loadApplicationIcon:a}}export{V as Breadcrumb,Le as CompressDialog,oe as ContextMenu,N as FileGrid,v as FileIcon,_e as FileInfoDialog,M as FileList,S as FileListView,$ as FileSidebar,e as FileType,Re as ProgressDialog,E as SortIndicator,X as StatusBar,H as Toolbar,ke as Window,at as useApplicationIcon,Ye as useDragAndDrop,tt as useMediaPlayer,Xe as useSelection,ge as useWindowDrag,we as useWindowResize};
|