@tutti-os/workspace-file-manager 0.0.230 → 0.0.232
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/{chunk-KCYTFKPY.js → chunk-GYODJICC.js} +21 -7
- package/dist/chunk-GYODJICC.js.map +1 -0
- package/dist/{chunk-EI4ICYY4.js → chunk-MWVVTZD5.js} +5 -1
- package/dist/chunk-MWVVTZD5.js.map +1 -0
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/{index-D0k_jjaw.d.ts → index-BV2DWijX.d.ts} +2 -0
- package/dist/index.d.ts +33 -6
- package/dist/index.js +1080 -817
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +3 -3
- package/dist/services/index.js +2 -2
- package/dist/{workspaceFileManagerLocations-BwRMCnUY.d.ts → workspaceFileManagerLocations-CzEKi2T1.d.ts} +4 -3
- package/package.json +5 -5
- package/dist/chunk-EI4ICYY4.js.map +0 -1
- package/dist/chunk-KCYTFKPY.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -21,24 +21,24 @@ import {
|
|
|
21
21
|
splitWorkspaceFileName,
|
|
22
22
|
workspaceFileSearchEntryToEntry,
|
|
23
23
|
writeWorkspaceFileManagerArrangeMode
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-GYODJICC.js";
|
|
25
25
|
import {
|
|
26
26
|
createWorkspaceFileManagerI18nRuntime,
|
|
27
27
|
resolveRevealInFolderLabel,
|
|
28
28
|
workspaceFileManagerI18nNamespace,
|
|
29
29
|
workspaceFileManagerI18nResources
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MWVVTZD5.js";
|
|
31
31
|
|
|
32
32
|
// src/ui/WorkspaceFileManager.tsx
|
|
33
33
|
import {
|
|
34
|
-
useCallback as
|
|
34
|
+
useCallback as useCallback7,
|
|
35
35
|
useEffect as useEffect7,
|
|
36
36
|
useLayoutEffect as useLayoutEffect5,
|
|
37
|
-
useMemo as
|
|
37
|
+
useMemo as useMemo5,
|
|
38
38
|
useRef as useRef7,
|
|
39
39
|
useState as useState8
|
|
40
40
|
} from "react";
|
|
41
|
-
import { cn as
|
|
41
|
+
import { cn as cn8 } from "@tutti-os/ui-system";
|
|
42
42
|
|
|
43
43
|
// src/ui/WorkspaceFileManagerContextMenuContainer.tsx
|
|
44
44
|
import { useEffect as useEffect2, useLayoutEffect as useLayoutEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
@@ -1127,6 +1127,12 @@ function WorkspaceFileManagerUnsupportedDialog({
|
|
|
1127
1127
|
);
|
|
1128
1128
|
}
|
|
1129
1129
|
|
|
1130
|
+
// src/ui/WorkspaceFileManagerPanelsContainer.tsx
|
|
1131
|
+
import {
|
|
1132
|
+
useCallback as useCallback4,
|
|
1133
|
+
useMemo as useMemo4
|
|
1134
|
+
} from "react";
|
|
1135
|
+
|
|
1130
1136
|
// src/ui/WorkspaceFileManagerPanels.tsx
|
|
1131
1137
|
import {
|
|
1132
1138
|
ArrowRightIcon as ArrowRightIcon2,
|
|
@@ -1135,11 +1141,51 @@ import {
|
|
|
1135
1141
|
LoadingIcon as LoadingIcon2,
|
|
1136
1142
|
ScrollArea,
|
|
1137
1143
|
VideoFileIcon as VideoFileIcon2,
|
|
1138
|
-
cn as
|
|
1144
|
+
cn as cn5
|
|
1139
1145
|
} from "@tutti-os/ui-system";
|
|
1140
1146
|
import { resolveWorkspaceFileVisualKind as resolveWorkspaceFileVisualKind2 } from "@tutti-os/workspace-file-preview";
|
|
1141
1147
|
import { WorkspaceFilePreviewSurface as SharedWorkspaceFilePreviewSurface } from "@tutti-os/workspace-file-preview/react";
|
|
1148
|
+
|
|
1149
|
+
// src/ui/WorkspaceFileManagerPreviewActionBar.tsx
|
|
1150
|
+
import { Button as Button2, cn as cn2 } from "@tutti-os/ui-system";
|
|
1151
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1152
|
+
function WorkspaceFileManagerPreviewActionBar({
|
|
1153
|
+
actions,
|
|
1154
|
+
className,
|
|
1155
|
+
label
|
|
1156
|
+
}) {
|
|
1157
|
+
if (actions.length === 0) {
|
|
1158
|
+
return null;
|
|
1159
|
+
}
|
|
1160
|
+
return /* @__PURE__ */ jsx4(
|
|
1161
|
+
"div",
|
|
1162
|
+
{
|
|
1163
|
+
"aria-label": label,
|
|
1164
|
+
className: cn2("flex flex-none items-center gap-1", className),
|
|
1165
|
+
role: "group",
|
|
1166
|
+
children: actions.map((action) => /* @__PURE__ */ jsx4(
|
|
1167
|
+
Button2,
|
|
1168
|
+
{
|
|
1169
|
+
"aria-label": action.label,
|
|
1170
|
+
className: "size-7 min-w-7 rounded-sm p-0 text-[var(--text-primary)]",
|
|
1171
|
+
"data-testid": `workspace-file-manager-preview-action-${action.id}`,
|
|
1172
|
+
disabled: action.disabled,
|
|
1173
|
+
size: "icon-sm",
|
|
1174
|
+
title: action.label,
|
|
1175
|
+
type: "button",
|
|
1176
|
+
variant: "ghost",
|
|
1177
|
+
onClick: action.onSelect,
|
|
1178
|
+
children: action.icon
|
|
1179
|
+
},
|
|
1180
|
+
action.id
|
|
1181
|
+
))
|
|
1182
|
+
}
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/ui/WorkspaceFileManagerPanels.tsx
|
|
1142
1187
|
import {
|
|
1188
|
+
memo,
|
|
1143
1189
|
useCallback as useCallback2,
|
|
1144
1190
|
useEffect as useEffect4,
|
|
1145
1191
|
useLayoutEffect as useLayoutEffect4,
|
|
@@ -1149,7 +1195,7 @@ import {
|
|
|
1149
1195
|
} from "react";
|
|
1150
1196
|
|
|
1151
1197
|
// src/ui/WorkspaceFileManagerIconGrid.tsx
|
|
1152
|
-
import { cn as
|
|
1198
|
+
import { cn as cn4 } from "@tutti-os/ui-system";
|
|
1153
1199
|
import { useLayoutEffect as useLayoutEffect3, useRef as useRef4 } from "react";
|
|
1154
1200
|
|
|
1155
1201
|
// src/ui/WorkspaceFileEntryIcon.tsx
|
|
@@ -1161,14 +1207,14 @@ import {
|
|
|
1161
1207
|
ImageFileIcon,
|
|
1162
1208
|
LoadingIcon,
|
|
1163
1209
|
VideoFileIcon,
|
|
1164
|
-
cn as
|
|
1210
|
+
cn as cn3
|
|
1165
1211
|
} from "@tutti-os/ui-system";
|
|
1166
1212
|
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
1167
1213
|
import {
|
|
1168
1214
|
resolveWorkspaceFileExtension,
|
|
1169
1215
|
resolveWorkspaceFileVisualKind
|
|
1170
1216
|
} from "@tutti-os/workspace-file-preview";
|
|
1171
|
-
import { jsx as
|
|
1217
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1172
1218
|
function WorkspaceFileEntryIcon({
|
|
1173
1219
|
entry,
|
|
1174
1220
|
frameClassName,
|
|
@@ -1245,25 +1291,25 @@ function WorkspaceFileEntryIcon({
|
|
|
1245
1291
|
reportViewportLeave();
|
|
1246
1292
|
};
|
|
1247
1293
|
}, [cacheKey, entry, isEnteringDirectory, onViewportLeave, onViewportEnter]);
|
|
1248
|
-
return /* @__PURE__ */
|
|
1294
|
+
return /* @__PURE__ */ jsx5(
|
|
1249
1295
|
"span",
|
|
1250
1296
|
{
|
|
1251
1297
|
ref: frameRef,
|
|
1252
|
-
className:
|
|
1298
|
+
className: cn3(
|
|
1253
1299
|
"grid flex-none place-items-center overflow-hidden",
|
|
1254
1300
|
frameClassName,
|
|
1255
1301
|
isEnteringDirectory ? "text-[var(--text-tertiary)]" : entryIconColorClassName(visualKind, isAppBundle)
|
|
1256
1302
|
),
|
|
1257
|
-
children: isEnteringDirectory ? /* @__PURE__ */
|
|
1303
|
+
children: isEnteringDirectory ? /* @__PURE__ */ jsx5(
|
|
1258
1304
|
LoadingIcon,
|
|
1259
1305
|
{
|
|
1260
|
-
className:
|
|
1306
|
+
className: cn3(loadingIconClassName ?? iconClassName, "animate-spin")
|
|
1261
1307
|
}
|
|
1262
|
-
) : iconUrl ? /* @__PURE__ */
|
|
1308
|
+
) : iconUrl ? /* @__PURE__ */ jsx5(
|
|
1263
1309
|
"img",
|
|
1264
1310
|
{
|
|
1265
1311
|
alt: "",
|
|
1266
|
-
className:
|
|
1312
|
+
className: cn3(
|
|
1267
1313
|
iconClassName,
|
|
1268
1314
|
visualKind === "image" ? "rounded-[6px] border border-[var(--border-1)] bg-[var(--transparency-block)] object-contain" : "rounded-[4px] object-contain"
|
|
1269
1315
|
),
|
|
@@ -1272,7 +1318,7 @@ function WorkspaceFileEntryIcon({
|
|
|
1272
1318
|
loading: "lazy",
|
|
1273
1319
|
src: iconUrl
|
|
1274
1320
|
}
|
|
1275
|
-
) : /* @__PURE__ */
|
|
1321
|
+
) : /* @__PURE__ */ jsx5(
|
|
1276
1322
|
DefaultEntryIcon,
|
|
1277
1323
|
{
|
|
1278
1324
|
entry,
|
|
@@ -1303,13 +1349,13 @@ function DefaultEntryIcon({
|
|
|
1303
1349
|
}) {
|
|
1304
1350
|
const vectorIconClassName = vectorFallbackIconClassName(iconClassName);
|
|
1305
1351
|
if (isWorkspaceApplicationBundle(entry)) {
|
|
1306
|
-
return /* @__PURE__ */
|
|
1352
|
+
return /* @__PURE__ */ jsx5(FileTextIcon, { className: vectorIconClassName });
|
|
1307
1353
|
}
|
|
1308
1354
|
if (shouldUseWorkspaceFileArchiveIcon(entry)) {
|
|
1309
|
-
return /* @__PURE__ */
|
|
1355
|
+
return /* @__PURE__ */ jsx5(WorkspaceArchiveFallbackIcon, { className: iconClassName });
|
|
1310
1356
|
}
|
|
1311
1357
|
if (shouldUseWorkspaceFileExtensionDocumentIcon(entry)) {
|
|
1312
|
-
return /* @__PURE__ */
|
|
1358
|
+
return /* @__PURE__ */ jsx5(
|
|
1313
1359
|
ExtensionDocumentIcon,
|
|
1314
1360
|
{
|
|
1315
1361
|
entry,
|
|
@@ -1319,20 +1365,20 @@ function DefaultEntryIcon({
|
|
|
1319
1365
|
}
|
|
1320
1366
|
switch (visualKind) {
|
|
1321
1367
|
case "directory":
|
|
1322
|
-
return /* @__PURE__ */
|
|
1368
|
+
return /* @__PURE__ */ jsx5(WorkspaceFolderFallbackIcon, { className: iconClassName });
|
|
1323
1369
|
case "image":
|
|
1324
|
-
return /* @__PURE__ */
|
|
1370
|
+
return /* @__PURE__ */ jsx5(WorkspaceImageFallbackIcon, { className: iconClassName });
|
|
1325
1371
|
case "video":
|
|
1326
|
-
return /* @__PURE__ */
|
|
1372
|
+
return /* @__PURE__ */ jsx5(VideoFileIcon, { className: vectorIconClassName });
|
|
1327
1373
|
case "markdown":
|
|
1328
1374
|
case "document":
|
|
1329
|
-
return /* @__PURE__ */
|
|
1375
|
+
return /* @__PURE__ */ jsx5(FileTextIcon, { className: vectorIconClassName });
|
|
1330
1376
|
case "code":
|
|
1331
|
-
return /* @__PURE__ */
|
|
1377
|
+
return /* @__PURE__ */ jsx5(FileCodeIcon, { className: vectorIconClassName });
|
|
1332
1378
|
case "binary":
|
|
1333
|
-
return /* @__PURE__ */
|
|
1379
|
+
return /* @__PURE__ */ jsx5(FileTextIcon, { className: vectorIconClassName });
|
|
1334
1380
|
default:
|
|
1335
|
-
return /* @__PURE__ */
|
|
1381
|
+
return /* @__PURE__ */ jsx5(FileTextIcon, { className: vectorIconClassName });
|
|
1336
1382
|
}
|
|
1337
1383
|
}
|
|
1338
1384
|
function vectorFallbackIconClassName(iconClassName) {
|
|
@@ -1341,17 +1387,17 @@ function vectorFallbackIconClassName(iconClassName) {
|
|
|
1341
1387
|
function WorkspaceFolderFallbackIcon({
|
|
1342
1388
|
className
|
|
1343
1389
|
}) {
|
|
1344
|
-
return /* @__PURE__ */
|
|
1390
|
+
return /* @__PURE__ */ jsx5(FolderFilledIcon, { className: vectorFallbackIconClassName(className) });
|
|
1345
1391
|
}
|
|
1346
1392
|
function WorkspaceArchiveFallbackIcon({
|
|
1347
1393
|
className
|
|
1348
1394
|
}) {
|
|
1349
|
-
return /* @__PURE__ */
|
|
1395
|
+
return /* @__PURE__ */ jsx5(FileArchiveIcon, { className: vectorFallbackIconClassName(className) });
|
|
1350
1396
|
}
|
|
1351
1397
|
function WorkspaceImageFallbackIcon({
|
|
1352
1398
|
className
|
|
1353
1399
|
}) {
|
|
1354
|
-
return /* @__PURE__ */
|
|
1400
|
+
return /* @__PURE__ */ jsx5(ImageFileIcon, { className: vectorFallbackIconClassName(className) });
|
|
1355
1401
|
}
|
|
1356
1402
|
function ExtensionDocumentIcon({
|
|
1357
1403
|
entry,
|
|
@@ -1363,11 +1409,11 @@ function ExtensionDocumentIcon({
|
|
|
1363
1409
|
"span",
|
|
1364
1410
|
{
|
|
1365
1411
|
"aria-hidden": "true",
|
|
1366
|
-
className:
|
|
1412
|
+
className: cn3("relative inline-block overflow-visible", iconClassName),
|
|
1367
1413
|
children: [
|
|
1368
|
-
/* @__PURE__ */
|
|
1369
|
-
/* @__PURE__ */
|
|
1370
|
-
showExtension ? /* @__PURE__ */
|
|
1414
|
+
/* @__PURE__ */ jsx5("span", { className: "absolute inset-[5%] rounded-[6px] border border-black/10 bg-linear-to-br from-white via-[#f8f8f8] to-[#ececec]" }),
|
|
1415
|
+
/* @__PURE__ */ jsx5("span", { className: "absolute top-[5%] right-[5%] h-[28%] w-[28%] overflow-hidden rounded-tr-[6px]", children: /* @__PURE__ */ jsx5("span", { className: "absolute top-0 right-0 h-full w-full origin-top-right -skew-x-3 rounded-bl-[4px] border-b border-l border-black/10 bg-linear-to-br from-white to-[#d9d9d9]" }) }),
|
|
1416
|
+
showExtension ? /* @__PURE__ */ jsx5("span", { className: "absolute right-[12%] bottom-[14%] left-[12%] truncate text-center text-[10px] leading-none font-semibold tracking-wide text-[#7a7a7a]", children: extension }) : null
|
|
1371
1417
|
]
|
|
1372
1418
|
}
|
|
1373
1419
|
);
|
|
@@ -1396,7 +1442,7 @@ function workspaceFileManagerIconGridFrameClassName() {
|
|
|
1396
1442
|
}
|
|
1397
1443
|
|
|
1398
1444
|
// src/ui/WorkspaceFileManagerIconGrid.tsx
|
|
1399
|
-
import { jsx as
|
|
1445
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1400
1446
|
function WorkspaceFileManagerIconGrid({
|
|
1401
1447
|
contextMenuEntryPath,
|
|
1402
1448
|
copy,
|
|
@@ -1421,14 +1467,14 @@ function WorkspaceFileManagerIconGrid({
|
|
|
1421
1467
|
onEntryClick,
|
|
1422
1468
|
onEntryPointerDown
|
|
1423
1469
|
}) {
|
|
1424
|
-
return /* @__PURE__ */
|
|
1470
|
+
return /* @__PURE__ */ jsx6(
|
|
1425
1471
|
"div",
|
|
1426
1472
|
{
|
|
1427
1473
|
className: "grid auto-rows-min content-start items-start gap-x-2 gap-y-6 px-4 py-4",
|
|
1428
1474
|
style: {
|
|
1429
1475
|
gridTemplateColumns: `repeat(auto-fill, minmax(${workspaceFileManagerIconGridLayout.tileMinWidthPx}px, 1fr))`
|
|
1430
1476
|
},
|
|
1431
|
-
children: entries.map((entry) => /* @__PURE__ */
|
|
1477
|
+
children: entries.map((entry) => /* @__PURE__ */ jsx6(
|
|
1432
1478
|
WorkspaceFileManagerIconTile,
|
|
1433
1479
|
{
|
|
1434
1480
|
contextMenuActive: contextMenuEntryPath === entry.path,
|
|
@@ -1494,7 +1540,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1494
1540
|
inline: "nearest"
|
|
1495
1541
|
});
|
|
1496
1542
|
}, [selected]);
|
|
1497
|
-
const tileClassName =
|
|
1543
|
+
const tileClassName = cn4(
|
|
1498
1544
|
"flex min-w-0 max-w-[148px] flex-col items-center gap-1.5 rounded-md border border-transparent px-2 py-2 text-center transition-colors",
|
|
1499
1545
|
isInlineRenaming ? "cursor-default" : "cursor-pointer hover:bg-transparency-hover active:bg-[var(--transparency-active)]",
|
|
1500
1546
|
moveDragActive && "cursor-grabbing",
|
|
@@ -1502,7 +1548,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1502
1548
|
moveDragSource && "opacity-55",
|
|
1503
1549
|
moveDragTarget && "bg-[var(--accent-bg)] text-[var(--text-primary)] outline outline-1 -outline-offset-1 outline-[var(--border-focus)]"
|
|
1504
1550
|
);
|
|
1505
|
-
const iconGraphic = /* @__PURE__ */
|
|
1551
|
+
const iconGraphic = /* @__PURE__ */ jsx6(
|
|
1506
1552
|
WorkspaceFileEntryIcon,
|
|
1507
1553
|
{
|
|
1508
1554
|
entry,
|
|
@@ -1524,7 +1570,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1524
1570
|
"data-workspace-file-entry-path": entry.path,
|
|
1525
1571
|
children: [
|
|
1526
1572
|
iconGraphic,
|
|
1527
|
-
/* @__PURE__ */
|
|
1573
|
+
/* @__PURE__ */ jsx6(
|
|
1528
1574
|
IconTileRenameInput,
|
|
1529
1575
|
{
|
|
1530
1576
|
copy,
|
|
@@ -1568,8 +1614,8 @@ function WorkspaceFileManagerIconTile({
|
|
|
1568
1614
|
children: [
|
|
1569
1615
|
iconGraphic,
|
|
1570
1616
|
/* @__PURE__ */ jsxs4("span", { className: "line-clamp-2 w-full break-all text-[13px] leading-[18px] text-[var(--text-primary)]", children: [
|
|
1571
|
-
/* @__PURE__ */
|
|
1572
|
-
nameParts.end ? /* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsx6("span", { children: nameParts.start }),
|
|
1618
|
+
nameParts.end ? /* @__PURE__ */ jsx6("span", { children: nameParts.end }) : null
|
|
1573
1619
|
] })
|
|
1574
1620
|
]
|
|
1575
1621
|
}
|
|
@@ -1601,12 +1647,12 @@ function IconTileRenameInput({
|
|
|
1601
1647
|
}, [hasFileExtension, nameParts.start.length]);
|
|
1602
1648
|
const validationMessage = inlineRenameValidation === "required" ? copy.t("createNameRequired") : inlineRenameValidation === "invalid" ? copy.t("createNameInvalid") : null;
|
|
1603
1649
|
return /* @__PURE__ */ jsxs4("span", { className: "flex w-full min-w-0 flex-col gap-0.5", children: [
|
|
1604
|
-
/* @__PURE__ */
|
|
1650
|
+
/* @__PURE__ */ jsx6(
|
|
1605
1651
|
"input",
|
|
1606
1652
|
{
|
|
1607
1653
|
"aria-invalid": inlineRenameValidation !== null,
|
|
1608
1654
|
"aria-label": copy.t("renameLabel"),
|
|
1609
|
-
className:
|
|
1655
|
+
className: cn4(
|
|
1610
1656
|
"w-full min-w-0 rounded-[4px] border border-transparent bg-[var(--transparency-block)] px-1 py-0.5 text-center text-xs text-[var(--text-primary)] outline-none",
|
|
1611
1657
|
inlineRenameValidation !== null && "border-[var(--state-danger)]"
|
|
1612
1658
|
),
|
|
@@ -1632,7 +1678,7 @@ function IconTileRenameInput({
|
|
|
1632
1678
|
}
|
|
1633
1679
|
}
|
|
1634
1680
|
),
|
|
1635
|
-
validationMessage ? /* @__PURE__ */
|
|
1681
|
+
validationMessage ? /* @__PURE__ */ jsx6("span", { className: "text-[10px] leading-3 text-[var(--state-danger)]", children: validationMessage }) : null
|
|
1636
1682
|
] });
|
|
1637
1683
|
}
|
|
1638
1684
|
|
|
@@ -1725,7 +1771,7 @@ function resolveWorkspaceFileManagerPreservedNameColumnWidth(width) {
|
|
|
1725
1771
|
}
|
|
1726
1772
|
|
|
1727
1773
|
// src/ui/WorkspaceFileManagerPanels.tsx
|
|
1728
|
-
import { Fragment as Fragment2, jsx as
|
|
1774
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1729
1775
|
var workspaceFileManagerTableGridStyle = {
|
|
1730
1776
|
gridTemplateColumns: workspaceFileManagerTableGridTemplate
|
|
1731
1777
|
};
|
|
@@ -1758,6 +1804,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1758
1804
|
isRenaming,
|
|
1759
1805
|
layoutMode,
|
|
1760
1806
|
pendingDirectoryPath,
|
|
1807
|
+
previewActions,
|
|
1761
1808
|
previewState,
|
|
1762
1809
|
onEntryIconViewportLeave,
|
|
1763
1810
|
onEntryIconViewportEnter,
|
|
@@ -2115,22 +2162,22 @@ function WorkspaceFileManagerPanels({
|
|
|
2115
2162
|
},
|
|
2116
2163
|
[clampPreviewPaneWidth, previewPaneMaxWidth, previewPaneWidth]
|
|
2117
2164
|
);
|
|
2118
|
-
const tablePanel = /* @__PURE__ */
|
|
2165
|
+
const tablePanel = /* @__PURE__ */ jsx7(
|
|
2119
2166
|
"div",
|
|
2120
2167
|
{
|
|
2121
|
-
className:
|
|
2168
|
+
className: cn5(
|
|
2122
2169
|
"flex min-h-0 min-w-0 flex-col overflow-hidden",
|
|
2123
2170
|
useStackedPreview ? "h-[44%] max-h-[48%] flex-none" : "flex-1"
|
|
2124
2171
|
),
|
|
2125
2172
|
onContextMenu: handleTablePanelContextMenu,
|
|
2126
|
-
children: state.error ? /* @__PURE__ */
|
|
2173
|
+
children: state.error ? /* @__PURE__ */ jsx7(FeedbackState, { message: state.error }) : state.isLoading && state.entries.length === 0 ? /* @__PURE__ */ jsx7(FeedbackState, { message: copy.t("loading") }) : state.entries.length === 0 ? /* @__PURE__ */ jsx7(
|
|
2127
2174
|
FeedbackState,
|
|
2128
2175
|
{
|
|
2129
2176
|
message: copy.t(
|
|
2130
2177
|
state.isSearchMode ? "noSearchResults" : "emptyDirectory"
|
|
2131
2178
|
)
|
|
2132
2179
|
}
|
|
2133
|
-
) : /* @__PURE__ */
|
|
2180
|
+
) : /* @__PURE__ */ jsx7(ScrollArea, { className: "min-h-0 flex-1 [&_[data-orientation=vertical][data-slot=scroll-area-scrollbar]]:opacity-100", children: layoutMode === "icon" ? /* @__PURE__ */ jsx7(
|
|
2134
2181
|
WorkspaceFileManagerIconGrid,
|
|
2135
2182
|
{
|
|
2136
2183
|
contextMenuEntryPath,
|
|
@@ -2160,16 +2207,16 @@ function WorkspaceFileManagerPanels({
|
|
|
2160
2207
|
/* @__PURE__ */ jsxs5(
|
|
2161
2208
|
"div",
|
|
2162
2209
|
{
|
|
2163
|
-
className:
|
|
2210
|
+
className: cn5(
|
|
2164
2211
|
"grid h-9 min-h-9 items-center gap-x-6 border-b border-[var(--border-1)] text-xs font-normal text-[var(--text-secondary)]",
|
|
2165
2212
|
tableGridClassName
|
|
2166
2213
|
),
|
|
2167
2214
|
style: tableGridStyle,
|
|
2168
2215
|
children: [
|
|
2169
|
-
/* @__PURE__ */
|
|
2216
|
+
/* @__PURE__ */ jsx7(
|
|
2170
2217
|
"span",
|
|
2171
2218
|
{
|
|
2172
|
-
className:
|
|
2219
|
+
className: cn5(
|
|
2173
2220
|
"min-w-0 overflow-hidden",
|
|
2174
2221
|
tableCellPaddingClassName
|
|
2175
2222
|
),
|
|
@@ -2177,17 +2224,17 @@ function WorkspaceFileManagerPanels({
|
|
|
2177
2224
|
children: copy.t("nameLabel")
|
|
2178
2225
|
}
|
|
2179
2226
|
),
|
|
2180
|
-
/* @__PURE__ */
|
|
2227
|
+
/* @__PURE__ */ jsx7(
|
|
2181
2228
|
"span",
|
|
2182
2229
|
{
|
|
2183
|
-
className:
|
|
2230
|
+
className: cn5("min-w-0 truncate", tableCellPaddingClassName),
|
|
2184
2231
|
children: dateColumnLabel
|
|
2185
2232
|
}
|
|
2186
2233
|
),
|
|
2187
|
-
/* @__PURE__ */
|
|
2234
|
+
/* @__PURE__ */ jsx7(
|
|
2188
2235
|
"span",
|
|
2189
2236
|
{
|
|
2190
|
-
className:
|
|
2237
|
+
className: cn5("min-w-0 truncate", tableCellPaddingClassName),
|
|
2191
2238
|
children: copy.t("sizeLabel")
|
|
2192
2239
|
}
|
|
2193
2240
|
)
|
|
@@ -2195,7 +2242,7 @@ function WorkspaceFileManagerPanels({
|
|
|
2195
2242
|
}
|
|
2196
2243
|
),
|
|
2197
2244
|
treeRows.map(
|
|
2198
|
-
(row) => row.kind === "feedback" ? /* @__PURE__ */
|
|
2245
|
+
(row) => row.kind === "feedback" ? /* @__PURE__ */ jsx7(
|
|
2199
2246
|
TreeFeedbackRow,
|
|
2200
2247
|
{
|
|
2201
2248
|
copy,
|
|
@@ -2207,7 +2254,7 @@ function WorkspaceFileManagerPanels({
|
|
|
2207
2254
|
tableCellPaddingClassName
|
|
2208
2255
|
},
|
|
2209
2256
|
row.key
|
|
2210
|
-
) : /* @__PURE__ */
|
|
2257
|
+
) : /* @__PURE__ */ jsx7(
|
|
2211
2258
|
EntryRow,
|
|
2212
2259
|
{
|
|
2213
2260
|
contextMenuActive: contextMenuEntryPath === row.entry.path,
|
|
@@ -2251,21 +2298,22 @@ function WorkspaceFileManagerPanels({
|
|
|
2251
2298
|
] }) })
|
|
2252
2299
|
}
|
|
2253
2300
|
);
|
|
2254
|
-
const previewPanel = showPreviewPanel ? /* @__PURE__ */
|
|
2301
|
+
const previewPanel = showPreviewPanel ? /* @__PURE__ */ jsx7(
|
|
2255
2302
|
"aside",
|
|
2256
2303
|
{
|
|
2257
|
-
className:
|
|
2304
|
+
className: cn5(
|
|
2258
2305
|
"relative flex h-full min-h-0 flex-col gap-[14px] overflow-auto p-4",
|
|
2259
2306
|
useStackedPreview ? "max-h-[44%] flex-none" : "flex-none",
|
|
2260
2307
|
previewPaneClassName
|
|
2261
2308
|
),
|
|
2262
2309
|
style: useStackedPreview ? void 0 : { width: previewPaneWidth },
|
|
2263
|
-
children: /* @__PURE__ */
|
|
2310
|
+
children: /* @__PURE__ */ jsx7(
|
|
2264
2311
|
PreviewPane,
|
|
2265
2312
|
{
|
|
2266
2313
|
copy,
|
|
2267
2314
|
dateLocale,
|
|
2268
2315
|
entry: selectedEntry,
|
|
2316
|
+
previewActions,
|
|
2269
2317
|
previewState
|
|
2270
2318
|
}
|
|
2271
2319
|
)
|
|
@@ -2280,13 +2328,13 @@ function WorkspaceFileManagerPanels({
|
|
|
2280
2328
|
/* @__PURE__ */ jsxs5(
|
|
2281
2329
|
"div",
|
|
2282
2330
|
{
|
|
2283
|
-
className:
|
|
2331
|
+
className: cn5(
|
|
2284
2332
|
"h-full min-h-0 min-w-0 bg-transparent",
|
|
2285
2333
|
useStackedPreview ? "flex flex-col gap-3" : "flex"
|
|
2286
2334
|
),
|
|
2287
2335
|
children: [
|
|
2288
2336
|
tablePanel,
|
|
2289
|
-
showPreviewPanel && !useStackedPreview ? /* @__PURE__ */
|
|
2337
|
+
showPreviewPanel && !useStackedPreview ? /* @__PURE__ */ jsx7(
|
|
2290
2338
|
"div",
|
|
2291
2339
|
{
|
|
2292
2340
|
"aria-label": copy.t("resizePreviewPanel"),
|
|
@@ -2311,7 +2359,7 @@ function WorkspaceFileManagerPanels({
|
|
|
2311
2359
|
]
|
|
2312
2360
|
}
|
|
2313
2361
|
),
|
|
2314
|
-
moveDragPreview ? /* @__PURE__ */
|
|
2362
|
+
moveDragPreview ? /* @__PURE__ */ jsx7(
|
|
2315
2363
|
MoveDragPreview,
|
|
2316
2364
|
{
|
|
2317
2365
|
iconUrlByCacheKey,
|
|
@@ -2366,7 +2414,7 @@ function resolveWorkspaceFileManagerDateColumnLabel(copy, arrangeMode) {
|
|
|
2366
2414
|
return copy.t("modifiedLabel");
|
|
2367
2415
|
}
|
|
2368
2416
|
}
|
|
2369
|
-
|
|
2417
|
+
var EntryRow = memo(function EntryRow2({
|
|
2370
2418
|
arrangeMode,
|
|
2371
2419
|
canMove,
|
|
2372
2420
|
contextMenuActive,
|
|
@@ -2413,7 +2461,7 @@ function EntryRow({
|
|
|
2413
2461
|
inline: "nearest"
|
|
2414
2462
|
});
|
|
2415
2463
|
}, [selected]);
|
|
2416
|
-
const rowClassName =
|
|
2464
|
+
const rowClassName = cn5(
|
|
2417
2465
|
"relative grid min-h-10 w-full items-center gap-x-6 border-b border-[var(--border-1)] px-0 text-left transition-colors",
|
|
2418
2466
|
gridClassName,
|
|
2419
2467
|
isInlineRenaming ? "cursor-default" : "cursor-pointer hover:bg-transparency-hover active:bg-[var(--transparency-active)]",
|
|
@@ -2431,15 +2479,15 @@ function EntryRow({
|
|
|
2431
2479
|
onContextMenu(event, entry);
|
|
2432
2480
|
}
|
|
2433
2481
|
};
|
|
2434
|
-
const nameCell = /* @__PURE__ */
|
|
2482
|
+
const nameCell = /* @__PURE__ */ jsx7(
|
|
2435
2483
|
"span",
|
|
2436
2484
|
{
|
|
2437
|
-
className:
|
|
2485
|
+
className: cn5(
|
|
2438
2486
|
"min-w-0 overflow-hidden",
|
|
2439
2487
|
!isInlineRenaming && "pointer-events-none relative z-[1]",
|
|
2440
2488
|
tableCellPaddingClassName
|
|
2441
2489
|
),
|
|
2442
|
-
children: /* @__PURE__ */
|
|
2490
|
+
children: /* @__PURE__ */ jsx7(
|
|
2443
2491
|
EntryNameCell,
|
|
2444
2492
|
{
|
|
2445
2493
|
copy,
|
|
@@ -2464,10 +2512,10 @@ function EntryRow({
|
|
|
2464
2512
|
)
|
|
2465
2513
|
}
|
|
2466
2514
|
);
|
|
2467
|
-
const modifiedCell = /* @__PURE__ */
|
|
2515
|
+
const modifiedCell = /* @__PURE__ */ jsx7(
|
|
2468
2516
|
"span",
|
|
2469
2517
|
{
|
|
2470
|
-
className:
|
|
2518
|
+
className: cn5(
|
|
2471
2519
|
"truncate text-xs text-[var(--text-secondary)]",
|
|
2472
2520
|
!isInlineRenaming && "pointer-events-none relative z-[1]",
|
|
2473
2521
|
tableCellPaddingClassName
|
|
@@ -2478,10 +2526,10 @@ function EntryRow({
|
|
|
2478
2526
|
)
|
|
2479
2527
|
}
|
|
2480
2528
|
);
|
|
2481
|
-
const sizeCell = /* @__PURE__ */
|
|
2529
|
+
const sizeCell = /* @__PURE__ */ jsx7(
|
|
2482
2530
|
"span",
|
|
2483
2531
|
{
|
|
2484
|
-
className:
|
|
2532
|
+
className: cn5(
|
|
2485
2533
|
"truncate text-xs text-[var(--text-secondary)]",
|
|
2486
2534
|
!isInlineRenaming && "pointer-events-none relative z-[1]",
|
|
2487
2535
|
tableCellPaddingClassName
|
|
@@ -2519,7 +2567,7 @@ function EntryRow({
|
|
|
2519
2567
|
onDragStart?.(entry, event.dataTransfer);
|
|
2520
2568
|
},
|
|
2521
2569
|
children: [
|
|
2522
|
-
/* @__PURE__ */
|
|
2570
|
+
/* @__PURE__ */ jsx7(
|
|
2523
2571
|
"button",
|
|
2524
2572
|
{
|
|
2525
2573
|
"aria-label": entry.name,
|
|
@@ -2540,7 +2588,7 @@ function EntryRow({
|
|
|
2540
2588
|
]
|
|
2541
2589
|
}
|
|
2542
2590
|
);
|
|
2543
|
-
}
|
|
2591
|
+
});
|
|
2544
2592
|
function MoveDragPreview({
|
|
2545
2593
|
iconUrlByCacheKey,
|
|
2546
2594
|
preview,
|
|
@@ -2558,7 +2606,7 @@ function MoveDragPreview({
|
|
|
2558
2606
|
transform: "translate(12px, 12px)"
|
|
2559
2607
|
},
|
|
2560
2608
|
children: [
|
|
2561
|
-
/* @__PURE__ */
|
|
2609
|
+
/* @__PURE__ */ jsx7(
|
|
2562
2610
|
WorkspaceFileEntryIcon,
|
|
2563
2611
|
{
|
|
2564
2612
|
entry: preview.entry,
|
|
@@ -2569,7 +2617,7 @@ function MoveDragPreview({
|
|
|
2569
2617
|
onViewportEnter: onEntryIconViewportEnter
|
|
2570
2618
|
}
|
|
2571
2619
|
),
|
|
2572
|
-
/* @__PURE__ */
|
|
2620
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: preview.entry.name })
|
|
2573
2621
|
]
|
|
2574
2622
|
}
|
|
2575
2623
|
);
|
|
@@ -2622,26 +2670,26 @@ function TreeFeedbackRow({
|
|
|
2622
2670
|
return /* @__PURE__ */ jsxs5(
|
|
2623
2671
|
"div",
|
|
2624
2672
|
{
|
|
2625
|
-
className:
|
|
2673
|
+
className: cn5(
|
|
2626
2674
|
"grid min-h-9 w-full items-center gap-x-6 border-b border-[var(--border-1)] text-left text-xs text-[var(--text-tertiary)]",
|
|
2627
2675
|
gridClassName
|
|
2628
2676
|
),
|
|
2629
2677
|
style: gridStyle,
|
|
2630
2678
|
children: [
|
|
2631
|
-
/* @__PURE__ */
|
|
2679
|
+
/* @__PURE__ */ jsx7("span", { className: tableCellPaddingClassName, children: /* @__PURE__ */ jsxs5(
|
|
2632
2680
|
"span",
|
|
2633
2681
|
{
|
|
2634
2682
|
className: "flex min-w-0 items-center gap-2",
|
|
2635
2683
|
style: workspaceFileManagerTreeIndentStyle(depth),
|
|
2636
2684
|
children: [
|
|
2637
|
-
/* @__PURE__ */
|
|
2638
|
-
status === "loading" ? /* @__PURE__ */
|
|
2639
|
-
/* @__PURE__ */
|
|
2685
|
+
/* @__PURE__ */ jsx7("span", { className: "size-5 shrink-0" }),
|
|
2686
|
+
status === "loading" ? /* @__PURE__ */ jsx7(LoadingIcon2, { className: "size-3.5 shrink-0 animate-spin" }) : null,
|
|
2687
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: resolvedMessage })
|
|
2640
2688
|
]
|
|
2641
2689
|
}
|
|
2642
2690
|
) }),
|
|
2643
|
-
/* @__PURE__ */
|
|
2644
|
-
/* @__PURE__ */
|
|
2691
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true" }),
|
|
2692
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true" })
|
|
2645
2693
|
]
|
|
2646
2694
|
}
|
|
2647
2695
|
);
|
|
@@ -2655,9 +2703,9 @@ function DirectoryDisclosureButton({
|
|
|
2655
2703
|
onToggle
|
|
2656
2704
|
}) {
|
|
2657
2705
|
if (!show) {
|
|
2658
|
-
return /* @__PURE__ */
|
|
2706
|
+
return /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", className: "size-5 shrink-0" });
|
|
2659
2707
|
}
|
|
2660
|
-
return /* @__PURE__ */
|
|
2708
|
+
return /* @__PURE__ */ jsx7(
|
|
2661
2709
|
"button",
|
|
2662
2710
|
{
|
|
2663
2711
|
"aria-label": copy.t(
|
|
@@ -2675,10 +2723,10 @@ function DirectoryDisclosureButton({
|
|
|
2675
2723
|
onPointerDown: (event) => {
|
|
2676
2724
|
event.stopPropagation();
|
|
2677
2725
|
},
|
|
2678
|
-
children: isLoading ? /* @__PURE__ */
|
|
2726
|
+
children: isLoading ? /* @__PURE__ */ jsx7(LoadingIcon2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx7(
|
|
2679
2727
|
ArrowRightIcon2,
|
|
2680
2728
|
{
|
|
2681
|
-
className:
|
|
2729
|
+
className: cn5(
|
|
2682
2730
|
"size-3.5 transition-transform",
|
|
2683
2731
|
expanded && "rotate-90"
|
|
2684
2732
|
)
|
|
@@ -2753,7 +2801,7 @@ function EntryNameCell({
|
|
|
2753
2801
|
className: "flex min-w-0 items-center gap-1.5",
|
|
2754
2802
|
style: workspaceFileManagerTreeIndentStyle(treeDepth),
|
|
2755
2803
|
children: [
|
|
2756
|
-
/* @__PURE__ */
|
|
2804
|
+
/* @__PURE__ */ jsx7(
|
|
2757
2805
|
DirectoryDisclosureButton,
|
|
2758
2806
|
{
|
|
2759
2807
|
copy,
|
|
@@ -2764,7 +2812,7 @@ function EntryNameCell({
|
|
|
2764
2812
|
onToggle: onToggleDirectoryExpanded
|
|
2765
2813
|
}
|
|
2766
2814
|
),
|
|
2767
|
-
/* @__PURE__ */
|
|
2815
|
+
/* @__PURE__ */ jsx7(
|
|
2768
2816
|
WorkspaceFileEntryIcon,
|
|
2769
2817
|
{
|
|
2770
2818
|
entry,
|
|
@@ -2776,12 +2824,12 @@ function EntryNameCell({
|
|
|
2776
2824
|
}
|
|
2777
2825
|
),
|
|
2778
2826
|
/* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
2779
|
-
/* @__PURE__ */
|
|
2827
|
+
/* @__PURE__ */ jsx7(
|
|
2780
2828
|
"input",
|
|
2781
2829
|
{
|
|
2782
2830
|
"aria-invalid": inlineRenameValidation !== null,
|
|
2783
2831
|
"aria-label": copy.t("renameLabel"),
|
|
2784
|
-
className:
|
|
2832
|
+
className: cn5(
|
|
2785
2833
|
"min-w-0 max-w-full rounded-md border border-transparent bg-[var(--transparency-block)] px-1.5 py-0.5 text-sm text-[var(--text-primary)] outline-none transition-colors duration-200 selection:bg-[var(--transparency-active)] selection:text-[var(--text-primary)] hover:bg-[var(--transparency-hover)] focus:bg-[var(--transparency-hover)] focus-visible:border-transparent focus-visible:bg-[var(--transparency-hover)] disabled:bg-[var(--transparency-block)] disabled:text-[var(--text-disabled)] disabled:opacity-100",
|
|
2786
2834
|
inlineRenameValidation !== null && "border-[var(--state-danger)]"
|
|
2787
2835
|
),
|
|
@@ -2823,7 +2871,7 @@ function EntryNameCell({
|
|
|
2823
2871
|
}
|
|
2824
2872
|
}
|
|
2825
2873
|
),
|
|
2826
|
-
validationMessage ? /* @__PURE__ */
|
|
2874
|
+
validationMessage ? /* @__PURE__ */ jsx7("span", { className: "text-xs text-[var(--state-danger)]", children: validationMessage }) : null
|
|
2827
2875
|
] })
|
|
2828
2876
|
]
|
|
2829
2877
|
}
|
|
@@ -2835,7 +2883,7 @@ function EntryNameCell({
|
|
|
2835
2883
|
className: "flex min-w-0 items-center gap-1.5",
|
|
2836
2884
|
style: workspaceFileManagerTreeIndentStyle(treeDepth),
|
|
2837
2885
|
children: [
|
|
2838
|
-
/* @__PURE__ */
|
|
2886
|
+
/* @__PURE__ */ jsx7(
|
|
2839
2887
|
DirectoryDisclosureButton,
|
|
2840
2888
|
{
|
|
2841
2889
|
copy,
|
|
@@ -2846,7 +2894,7 @@ function EntryNameCell({
|
|
|
2846
2894
|
onToggle: onToggleDirectoryExpanded
|
|
2847
2895
|
}
|
|
2848
2896
|
),
|
|
2849
|
-
/* @__PURE__ */
|
|
2897
|
+
/* @__PURE__ */ jsx7(
|
|
2850
2898
|
WorkspaceFileEntryIcon,
|
|
2851
2899
|
{
|
|
2852
2900
|
entry,
|
|
@@ -2860,10 +2908,10 @@ function EntryNameCell({
|
|
|
2860
2908
|
),
|
|
2861
2909
|
/* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
2862
2910
|
/* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 max-w-full overflow-hidden whitespace-nowrap text-sm", children: [
|
|
2863
|
-
/* @__PURE__ */
|
|
2864
|
-
nameParts.end ? /* @__PURE__ */
|
|
2911
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-0 overflow-hidden text-ellipsis", children: nameParts.start }),
|
|
2912
|
+
nameParts.end ? /* @__PURE__ */ jsx7("span", { className: "flex-none overflow-hidden text-ellipsis", children: nameParts.end }) : null
|
|
2865
2913
|
] }),
|
|
2866
|
-
contextLabel ? /* @__PURE__ */
|
|
2914
|
+
contextLabel ? /* @__PURE__ */ jsx7("span", { className: "block max-w-full truncate text-[11px] leading-3 text-[var(--text-tertiary)]", children: contextLabel }) : null
|
|
2867
2915
|
] })
|
|
2868
2916
|
]
|
|
2869
2917
|
}
|
|
@@ -2875,47 +2923,55 @@ function EntryIcon({
|
|
|
2875
2923
|
}) {
|
|
2876
2924
|
switch (visualKind) {
|
|
2877
2925
|
case "directory":
|
|
2878
|
-
return /* @__PURE__ */
|
|
2926
|
+
return /* @__PURE__ */ jsx7(WorkspaceFolderFallbackIcon, { className });
|
|
2879
2927
|
case "image":
|
|
2880
|
-
return /* @__PURE__ */
|
|
2928
|
+
return /* @__PURE__ */ jsx7(WorkspaceImageFallbackIcon, { className });
|
|
2881
2929
|
case "video":
|
|
2882
|
-
return /* @__PURE__ */
|
|
2930
|
+
return /* @__PURE__ */ jsx7(VideoFileIcon2, { className });
|
|
2883
2931
|
case "markdown":
|
|
2884
2932
|
case "document":
|
|
2885
|
-
return /* @__PURE__ */
|
|
2933
|
+
return /* @__PURE__ */ jsx7(FileTextIcon2, { className });
|
|
2886
2934
|
case "code":
|
|
2887
|
-
return /* @__PURE__ */
|
|
2935
|
+
return /* @__PURE__ */ jsx7(FileCodeIcon2, { className });
|
|
2888
2936
|
case "binary":
|
|
2889
|
-
return /* @__PURE__ */
|
|
2937
|
+
return /* @__PURE__ */ jsx7(FileTextIcon2, { className });
|
|
2890
2938
|
default:
|
|
2891
|
-
return /* @__PURE__ */
|
|
2939
|
+
return /* @__PURE__ */ jsx7(FileTextIcon2, { className });
|
|
2892
2940
|
}
|
|
2893
2941
|
}
|
|
2894
2942
|
function PreviewPane({
|
|
2895
2943
|
copy,
|
|
2896
2944
|
dateLocale,
|
|
2897
2945
|
entry,
|
|
2946
|
+
previewActions,
|
|
2898
2947
|
previewState
|
|
2899
2948
|
}) {
|
|
2900
2949
|
if (!entry || previewState.status === "empty") {
|
|
2901
|
-
return /* @__PURE__ */
|
|
2950
|
+
return /* @__PURE__ */ jsx7("div", { className: "grid h-full min-h-[180px] place-items-center overflow-hidden p-8 text-center text-sm leading-5 text-[var(--text-tertiary)]", children: /* @__PURE__ */ jsx7("span", { className: "max-w-[24ch] [overflow-wrap:anywhere]", children: copy.t("previewEmptyLabel") }) });
|
|
2902
2951
|
}
|
|
2903
2952
|
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2904
|
-
/* @__PURE__ */
|
|
2953
|
+
/* @__PURE__ */ jsx7(PreviewSurface, { copy, previewState }),
|
|
2954
|
+
/* @__PURE__ */ jsx7(
|
|
2955
|
+
WorkspaceFileManagerPreviewActionBar,
|
|
2956
|
+
{
|
|
2957
|
+
actions: previewActions ?? [],
|
|
2958
|
+
label: copy.t("previewActionsLabel")
|
|
2959
|
+
}
|
|
2960
|
+
),
|
|
2905
2961
|
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-col gap-[14px]", children: [
|
|
2906
2962
|
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-col gap-[3px]", children: [
|
|
2907
|
-
/* @__PURE__ */
|
|
2908
|
-
/* @__PURE__ */
|
|
2963
|
+
/* @__PURE__ */ jsx7("strong", { className: "min-w-0 truncate text-[15px] font-semibold text-[var(--text-primary)]", children: entry.name }),
|
|
2964
|
+
/* @__PURE__ */ jsx7("p", { className: "min-w-0 truncate text-xs text-[var(--text-secondary)]", children: entry.path })
|
|
2909
2965
|
] }),
|
|
2910
2966
|
/* @__PURE__ */ jsxs5("dl", { className: "border-t border-[var(--border-1)]", children: [
|
|
2911
|
-
/* @__PURE__ */
|
|
2967
|
+
/* @__PURE__ */ jsx7(
|
|
2912
2968
|
PreviewDetail,
|
|
2913
2969
|
{
|
|
2914
2970
|
label: copy.t("modifiedLabel"),
|
|
2915
2971
|
value: formatWorkspaceFileModifiedTime(entry.mtimeMs, dateLocale)
|
|
2916
2972
|
}
|
|
2917
2973
|
),
|
|
2918
|
-
/* @__PURE__ */
|
|
2974
|
+
/* @__PURE__ */ jsx7(
|
|
2919
2975
|
PreviewDetail,
|
|
2920
2976
|
{
|
|
2921
2977
|
label: copy.t("sizeLabel"),
|
|
@@ -2930,15 +2986,15 @@ function PreviewSurface({
|
|
|
2930
2986
|
copy,
|
|
2931
2987
|
previewState
|
|
2932
2988
|
}) {
|
|
2933
|
-
return /* @__PURE__ */
|
|
2989
|
+
return /* @__PURE__ */ jsx7(
|
|
2934
2990
|
SharedWorkspaceFilePreviewSurface,
|
|
2935
2991
|
{
|
|
2936
2992
|
directoryMessage: copy.t("previewDirectoryLabel"),
|
|
2937
2993
|
emptyMessage: copy.t("previewEmptyLabel"),
|
|
2938
2994
|
imageAlt: (entry) => entry.name,
|
|
2939
|
-
loadingIndicator: /* @__PURE__ */
|
|
2995
|
+
loadingIndicator: /* @__PURE__ */ jsx7("span", { className: "mx-auto grid size-11 place-items-center rounded-lg bg-[var(--transparency-block)]", children: /* @__PURE__ */ jsx7(LoadingIcon2, { className: "size-4 animate-spin" }) }),
|
|
2940
2996
|
loadingMessage: copy.t("previewLoadingLabel"),
|
|
2941
|
-
renderIcon: (entry) => /* @__PURE__ */
|
|
2997
|
+
renderIcon: (entry) => /* @__PURE__ */ jsx7(
|
|
2942
2998
|
EntryIcon,
|
|
2943
2999
|
{
|
|
2944
3000
|
className: "mx-auto size-7",
|
|
@@ -2966,153 +3022,784 @@ function PreviewDetail({
|
|
|
2966
3022
|
className: "@max-[600px]/workspace-file-manager:grid-cols-1 @max-[600px]/workspace-file-manager:gap-0.5 grid gap-2.5 border-b border-[var(--border-1)] py-2.5 text-xs",
|
|
2967
3023
|
style: workspaceFileManagerPreviewDetailGridStyle,
|
|
2968
3024
|
children: [
|
|
2969
|
-
/* @__PURE__ */
|
|
2970
|
-
/* @__PURE__ */
|
|
3025
|
+
/* @__PURE__ */ jsx7("dt", { className: "truncate text-[var(--text-secondary)]", children: label }),
|
|
3026
|
+
/* @__PURE__ */ jsx7("dd", { className: "@max-[600px]/workspace-file-manager:text-left truncate text-right text-[var(--text-primary)]", children: value })
|
|
2971
3027
|
]
|
|
2972
3028
|
}
|
|
2973
3029
|
);
|
|
2974
3030
|
}
|
|
2975
3031
|
function FeedbackState({ message }) {
|
|
2976
|
-
return /* @__PURE__ */
|
|
3032
|
+
return /* @__PURE__ */ jsx7("div", { className: "grid min-h-0 flex-1 place-items-center p-6 text-center text-sm text-[var(--text-tertiary)]", children: /* @__PURE__ */ jsx7("span", { className: "max-w-[34ch] [overflow-wrap:anywhere]", children: message }) });
|
|
2977
3033
|
}
|
|
2978
3034
|
|
|
2979
|
-
// src/ui/
|
|
2980
|
-
import {
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
} from "@tutti-os/ui-system";
|
|
3004
|
-
import { useEffect as useEffect5, useRef as useRef6, useState as useState4 } from "react";
|
|
3005
|
-
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3006
|
-
function WorkspaceFileManagerToolbar({
|
|
3007
|
-
breadcrumbs,
|
|
3008
|
-
canSearch,
|
|
3009
|
-
canGoBack,
|
|
3010
|
-
canGoForward,
|
|
3011
|
-
copy,
|
|
3012
|
-
currentDirectoryPath,
|
|
3013
|
-
isBusy,
|
|
3014
|
-
isLoading,
|
|
3015
|
-
isMutating,
|
|
3016
|
-
isSearching,
|
|
3017
|
-
arrangeMode,
|
|
3018
|
-
layoutMode,
|
|
3019
|
-
renderToolbarTrailingActions,
|
|
3020
|
-
searchQuery,
|
|
3021
|
-
onGoBack,
|
|
3022
|
-
onGoForward,
|
|
3023
|
-
onArrangeModeChange,
|
|
3024
|
-
onLayoutModeChange,
|
|
3025
|
-
onLoadDirectory,
|
|
3026
|
-
onRefresh,
|
|
3027
|
-
onSearchClear,
|
|
3028
|
-
onSearchQueryChange
|
|
3029
|
-
}) {
|
|
3030
|
-
const [refreshAnimationKey, setRefreshAnimationKey] = useState4(0);
|
|
3031
|
-
const handleRefresh = () => {
|
|
3032
|
-
setRefreshAnimationKey((currentKey) => currentKey + 1);
|
|
3033
|
-
onRefresh();
|
|
3035
|
+
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
3036
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo2, useState as useState4 } from "react";
|
|
3037
|
+
|
|
3038
|
+
// src/ui/workspaceFileEntryIconUrlQueue.ts
|
|
3039
|
+
var defaultMaxConcurrentIconRequests = 3;
|
|
3040
|
+
var imageThumbnailCacheKeyPrefix = "image-thumbnail:";
|
|
3041
|
+
function shouldKeepResolvedIconAfterViewportLeave(cacheKey) {
|
|
3042
|
+
return cacheKey.startsWith(imageThumbnailCacheKeyPrefix);
|
|
3043
|
+
}
|
|
3044
|
+
function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
3045
|
+
const maxConcurrent = Math.max(
|
|
3046
|
+
1,
|
|
3047
|
+
Math.floor(options.maxConcurrent ?? defaultMaxConcurrentIconRequests)
|
|
3048
|
+
);
|
|
3049
|
+
const iconUrlByCacheKey = /* @__PURE__ */ new Map();
|
|
3050
|
+
const inFlightCacheKeys = /* @__PURE__ */ new Set();
|
|
3051
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
3052
|
+
const queuedEntries = /* @__PURE__ */ new Map();
|
|
3053
|
+
const visibleReferenceCountByCacheKey = /* @__PURE__ */ new Map();
|
|
3054
|
+
let activeCount = 0;
|
|
3055
|
+
let disposed = false;
|
|
3056
|
+
let retainedCacheKeys = null;
|
|
3057
|
+
const policyOptions = {
|
|
3058
|
+
includeImageThumbnails: options.includeImageThumbnails
|
|
3034
3059
|
};
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3060
|
+
function publish() {
|
|
3061
|
+
for (const listener of listeners) {
|
|
3062
|
+
listener();
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
function isRetained(cacheKey) {
|
|
3066
|
+
return retainedCacheKeys === null || retainedCacheKeys.has(cacheKey);
|
|
3067
|
+
}
|
|
3068
|
+
function isVisible(cacheKey) {
|
|
3069
|
+
return (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) > 0;
|
|
3070
|
+
}
|
|
3071
|
+
function shouldResolveCacheKey(cacheKey) {
|
|
3072
|
+
return isVisible(cacheKey) || shouldKeepResolvedIconAfterViewportLeave(cacheKey);
|
|
3073
|
+
}
|
|
3074
|
+
function retainVisibleReference(cacheKey) {
|
|
3075
|
+
visibleReferenceCountByCacheKey.set(
|
|
3076
|
+
cacheKey,
|
|
3077
|
+
(visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) + 1
|
|
3078
|
+
);
|
|
3079
|
+
}
|
|
3080
|
+
function releaseVisibleReference(cacheKey) {
|
|
3081
|
+
const nextCount = (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) - 1;
|
|
3082
|
+
if (nextCount > 0) {
|
|
3083
|
+
visibleReferenceCountByCacheKey.set(cacheKey, nextCount);
|
|
3084
|
+
return;
|
|
3085
|
+
}
|
|
3086
|
+
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
3087
|
+
if (shouldKeepResolvedIconAfterViewportLeave(cacheKey)) {
|
|
3088
|
+
return;
|
|
3089
|
+
}
|
|
3090
|
+
queuedEntries.delete(cacheKey);
|
|
3091
|
+
const hadCachedIcon = iconUrlByCacheKey.delete(cacheKey);
|
|
3092
|
+
if (hadCachedIcon) {
|
|
3093
|
+
publish();
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
function drain() {
|
|
3097
|
+
if (disposed || !options.resolveEntryIconUrl) {
|
|
3098
|
+
return;
|
|
3099
|
+
}
|
|
3100
|
+
while (activeCount < maxConcurrent && queuedEntries.size > 0) {
|
|
3101
|
+
const next = queuedEntries.entries().next().value;
|
|
3102
|
+
if (!next) {
|
|
3103
|
+
return;
|
|
3054
3104
|
}
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
"aria-label": currentDirectoryPath,
|
|
3060
|
-
className: "@max-[600px]/workspace-file-manager:flex-auto flex min-w-0 flex-1 overflow-hidden pr-2",
|
|
3061
|
-
"data-workspace-file-manager-path": "",
|
|
3062
|
-
children: /* @__PURE__ */ jsx7("ol", { className: "flex min-w-0 max-w-full flex-1 items-center gap-2 overflow-hidden", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsx7(
|
|
3063
|
-
BreadcrumbButton,
|
|
3064
|
-
{
|
|
3065
|
-
active: index === breadcrumbs.length - 1,
|
|
3066
|
-
label: crumb.label,
|
|
3067
|
-
showSeparator: index > 0,
|
|
3068
|
-
onClick: () => {
|
|
3069
|
-
onLoadDirectory(crumb.path);
|
|
3070
|
-
}
|
|
3071
|
-
},
|
|
3072
|
-
crumb.path
|
|
3073
|
-
)) })
|
|
3105
|
+
const [cacheKey, entry] = next;
|
|
3106
|
+
queuedEntries.delete(cacheKey);
|
|
3107
|
+
if (!shouldResolveCacheKey(cacheKey) || iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey)) {
|
|
3108
|
+
continue;
|
|
3074
3109
|
}
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
{
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
layoutMode,
|
|
3083
|
-
onArrangeModeChange,
|
|
3084
|
-
onLayoutModeChange
|
|
3110
|
+
activeCount += 1;
|
|
3111
|
+
inFlightCacheKeys.add(cacheKey);
|
|
3112
|
+
void options.resolveEntryIconUrl(entry).then((iconUrl) => {
|
|
3113
|
+
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3114
|
+
if (shouldStore) {
|
|
3115
|
+
iconUrlByCacheKey.set(cacheKey, iconUrl?.trim() || null);
|
|
3116
|
+
publish();
|
|
3085
3117
|
}
|
|
3086
|
-
)
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
onClick: handleRefresh,
|
|
3092
|
-
children: [
|
|
3093
|
-
isLoading ? /* @__PURE__ */ jsx7(LoadingIcon3, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx7(
|
|
3094
|
-
RefreshIcon,
|
|
3095
|
-
{
|
|
3096
|
-
className: cn5(
|
|
3097
|
-
"size-4",
|
|
3098
|
-
refreshAnimationKey > 0 && "motion-safe:animate-[spin_520ms_cubic-bezier(0.4,0,0.2,1)_1_reverse]"
|
|
3099
|
-
)
|
|
3100
|
-
},
|
|
3101
|
-
refreshAnimationKey
|
|
3102
|
-
),
|
|
3103
|
-
/* @__PURE__ */ jsx7("span", { className: "@max-[600px]/workspace-file-manager:hidden", children: copy.t("refreshLabel") })
|
|
3104
|
-
]
|
|
3118
|
+
}).catch(() => {
|
|
3119
|
+
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3120
|
+
if (shouldStore) {
|
|
3121
|
+
iconUrlByCacheKey.set(cacheKey, null);
|
|
3122
|
+
publish();
|
|
3105
3123
|
}
|
|
3106
|
-
)
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3124
|
+
}).finally(() => {
|
|
3125
|
+
activeCount -= 1;
|
|
3126
|
+
inFlightCacheKeys.delete(cacheKey);
|
|
3127
|
+
drain();
|
|
3128
|
+
});
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
return {
|
|
3132
|
+
activate() {
|
|
3133
|
+
disposed = false;
|
|
3134
|
+
},
|
|
3135
|
+
dispose() {
|
|
3136
|
+
disposed = true;
|
|
3137
|
+
queuedEntries.clear();
|
|
3138
|
+
visibleReferenceCountByCacheKey.clear();
|
|
3139
|
+
listeners.clear();
|
|
3140
|
+
},
|
|
3141
|
+
leaveViewport(entry) {
|
|
3142
|
+
if (disposed || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
3143
|
+
return;
|
|
3144
|
+
}
|
|
3145
|
+
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3146
|
+
releaseVisibleReference(cacheKey);
|
|
3147
|
+
},
|
|
3148
|
+
enterViewport(entry) {
|
|
3149
|
+
if (disposed || !options.resolveEntryIconUrl || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3153
|
+
retainVisibleReference(cacheKey);
|
|
3154
|
+
if (iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey) || queuedEntries.has(cacheKey)) {
|
|
3155
|
+
return;
|
|
3156
|
+
}
|
|
3157
|
+
queuedEntries.set(cacheKey, entry);
|
|
3158
|
+
drain();
|
|
3159
|
+
},
|
|
3160
|
+
retainEntries(entries) {
|
|
3161
|
+
retainedCacheKeys = new Set(
|
|
3162
|
+
entries.filter(
|
|
3163
|
+
(entry) => shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)
|
|
3164
|
+
).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry))
|
|
3165
|
+
);
|
|
3166
|
+
let changed = false;
|
|
3167
|
+
for (const cacheKey of iconUrlByCacheKey.keys()) {
|
|
3168
|
+
if (!isRetained(cacheKey)) {
|
|
3169
|
+
iconUrlByCacheKey.delete(cacheKey);
|
|
3170
|
+
changed = true;
|
|
3171
|
+
continue;
|
|
3172
|
+
}
|
|
3173
|
+
if (iconUrlByCacheKey.get(cacheKey) === null) {
|
|
3174
|
+
iconUrlByCacheKey.delete(cacheKey);
|
|
3175
|
+
changed = true;
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
for (const cacheKey of queuedEntries.keys()) {
|
|
3179
|
+
if (!isRetained(cacheKey)) {
|
|
3180
|
+
queuedEntries.delete(cacheKey);
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
for (const cacheKey of visibleReferenceCountByCacheKey.keys()) {
|
|
3184
|
+
if (!isRetained(cacheKey)) {
|
|
3185
|
+
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
if (changed) {
|
|
3189
|
+
publish();
|
|
3190
|
+
}
|
|
3191
|
+
},
|
|
3192
|
+
snapshot() {
|
|
3193
|
+
return new Map(iconUrlByCacheKey);
|
|
3194
|
+
},
|
|
3195
|
+
subscribe(listener) {
|
|
3196
|
+
if (disposed) {
|
|
3197
|
+
return () => {
|
|
3198
|
+
};
|
|
3199
|
+
}
|
|
3200
|
+
listeners.add(listener);
|
|
3201
|
+
return () => {
|
|
3202
|
+
listeners.delete(listener);
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
3205
|
+
};
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
3209
|
+
function buildIconTargetSignature(entries, options) {
|
|
3210
|
+
return entries.filter((entry) => shouldResolveWorkspaceFileEntryIcon(entry, options)).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry)).join("\0");
|
|
3211
|
+
}
|
|
3212
|
+
function useWorkspaceFileEntryIconUrls(input) {
|
|
3213
|
+
const { entries, includeImageThumbnails, resolveEntryIconUrl } = input;
|
|
3214
|
+
const queue = useMemo2(
|
|
3215
|
+
() => createWorkspaceFileEntryIconUrlQueue({
|
|
3216
|
+
includeImageThumbnails,
|
|
3217
|
+
resolveEntryIconUrl
|
|
3218
|
+
}),
|
|
3219
|
+
[includeImageThumbnails, resolveEntryIconUrl]
|
|
3220
|
+
);
|
|
3221
|
+
const [iconUrlByCacheKey, setIconUrlByCacheKey] = useState4(() => queue.snapshot());
|
|
3222
|
+
const iconTargetSignature = useMemo2(
|
|
3223
|
+
() => buildIconTargetSignature(entries, { includeImageThumbnails }),
|
|
3224
|
+
[entries, includeImageThumbnails]
|
|
3225
|
+
);
|
|
3226
|
+
useEffect5(() => {
|
|
3227
|
+
queue.activate();
|
|
3228
|
+
return () => {
|
|
3229
|
+
queue.dispose();
|
|
3230
|
+
};
|
|
3231
|
+
}, [queue]);
|
|
3232
|
+
useEffect5(() => {
|
|
3233
|
+
queue.retainEntries(entries);
|
|
3234
|
+
}, [entries, iconTargetSignature, queue]);
|
|
3235
|
+
useEffect5(() => {
|
|
3236
|
+
setIconUrlByCacheKey(queue.snapshot());
|
|
3237
|
+
return queue.subscribe(() => {
|
|
3238
|
+
setIconUrlByCacheKey(queue.snapshot());
|
|
3239
|
+
});
|
|
3240
|
+
}, [queue]);
|
|
3241
|
+
const reportEntryIconViewportEnter = useCallback3(
|
|
3242
|
+
(entry) => {
|
|
3243
|
+
queue.enterViewport(entry);
|
|
3244
|
+
},
|
|
3245
|
+
[queue]
|
|
3246
|
+
);
|
|
3247
|
+
const reportEntryIconViewportLeave = useCallback3(
|
|
3248
|
+
(entry) => {
|
|
3249
|
+
queue.leaveViewport(entry);
|
|
3250
|
+
},
|
|
3251
|
+
[queue]
|
|
3252
|
+
);
|
|
3253
|
+
return {
|
|
3254
|
+
iconUrlByCacheKey,
|
|
3255
|
+
reportEntryIconViewportEnter,
|
|
3256
|
+
reportEntryIconViewportLeave
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
// src/ui/useWorkspaceFileManagerPreviewActions.tsx
|
|
3261
|
+
import { useMemo as useMemo3 } from "react";
|
|
3262
|
+
import {
|
|
3263
|
+
CopyIcon,
|
|
3264
|
+
DownloadIcon,
|
|
3265
|
+
EyeIcon,
|
|
3266
|
+
ShareLinedIcon
|
|
3267
|
+
} from "@tutti-os/ui-system/icons";
|
|
3268
|
+
|
|
3269
|
+
// src/ui/workspaceFileManagerPreviewActionTypes.ts
|
|
3270
|
+
var workspaceFileManagerPreviewActionOrder = [
|
|
3271
|
+
"copy",
|
|
3272
|
+
"open",
|
|
3273
|
+
"download",
|
|
3274
|
+
"share"
|
|
3275
|
+
];
|
|
3276
|
+
|
|
3277
|
+
// src/ui/useWorkspaceFileManagerPreviewActions.tsx
|
|
3278
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
3279
|
+
var previewActionIconClassName = "size-4";
|
|
3280
|
+
function useWorkspaceFileManagerPreviewActions({
|
|
3281
|
+
config,
|
|
3282
|
+
copy,
|
|
3283
|
+
entry,
|
|
3284
|
+
onCopyEntry,
|
|
3285
|
+
session,
|
|
3286
|
+
state
|
|
3287
|
+
}) {
|
|
3288
|
+
const { busyAction, capabilities, isLoading, isMutating } = state;
|
|
3289
|
+
const isExternalLocation = isWorkspaceFileExternalLocation(
|
|
3290
|
+
findWorkspaceFileLocationById(
|
|
3291
|
+
state.locationSections,
|
|
3292
|
+
state.selectedLocationId
|
|
3293
|
+
)
|
|
3294
|
+
);
|
|
3295
|
+
return useMemo3(() => {
|
|
3296
|
+
if (!config || !entry) {
|
|
3297
|
+
return [];
|
|
3298
|
+
}
|
|
3299
|
+
const disabled = busyAction !== null || isLoading || isMutating;
|
|
3300
|
+
const order = config.order ?? workspaceFileManagerPreviewActionOrder;
|
|
3301
|
+
const actions = [];
|
|
3302
|
+
for (const id of order) {
|
|
3303
|
+
const action = buildPreviewAction({
|
|
3304
|
+
config,
|
|
3305
|
+
copy,
|
|
3306
|
+
disabled,
|
|
3307
|
+
entry,
|
|
3308
|
+
id,
|
|
3309
|
+
isExternalLocation,
|
|
3310
|
+
onCopyEntry,
|
|
3311
|
+
session,
|
|
3312
|
+
canCopy: capabilities.canCopy
|
|
3313
|
+
});
|
|
3314
|
+
if (action) {
|
|
3315
|
+
actions.push(action);
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
return actions;
|
|
3319
|
+
}, [
|
|
3320
|
+
busyAction,
|
|
3321
|
+
capabilities.canCopy,
|
|
3322
|
+
config,
|
|
3323
|
+
copy,
|
|
3324
|
+
entry,
|
|
3325
|
+
isExternalLocation,
|
|
3326
|
+
isLoading,
|
|
3327
|
+
isMutating,
|
|
3328
|
+
onCopyEntry,
|
|
3329
|
+
session
|
|
3330
|
+
]);
|
|
3331
|
+
}
|
|
3332
|
+
function buildPreviewAction({
|
|
3333
|
+
canCopy,
|
|
3334
|
+
config,
|
|
3335
|
+
copy,
|
|
3336
|
+
disabled,
|
|
3337
|
+
entry,
|
|
3338
|
+
id,
|
|
3339
|
+
isExternalLocation,
|
|
3340
|
+
onCopyEntry,
|
|
3341
|
+
session
|
|
3342
|
+
}) {
|
|
3343
|
+
switch (id) {
|
|
3344
|
+
case "copy": {
|
|
3345
|
+
if (config.copy !== true || !canCopy || isExternalLocation) {
|
|
3346
|
+
return null;
|
|
3347
|
+
}
|
|
3348
|
+
return {
|
|
3349
|
+
disabled,
|
|
3350
|
+
icon: /* @__PURE__ */ jsx8(CopyIcon, { className: previewActionIconClassName }),
|
|
3351
|
+
id,
|
|
3352
|
+
label: copy.t("copyLabel"),
|
|
3353
|
+
onSelect: () => {
|
|
3354
|
+
void (async () => {
|
|
3355
|
+
if (await session.copyToClipboard(entry)) {
|
|
3356
|
+
await onCopyEntry?.();
|
|
3357
|
+
}
|
|
3358
|
+
})();
|
|
3359
|
+
}
|
|
3360
|
+
};
|
|
3361
|
+
}
|
|
3362
|
+
case "open": {
|
|
3363
|
+
if (config.open !== true) {
|
|
3364
|
+
return null;
|
|
3365
|
+
}
|
|
3366
|
+
return {
|
|
3367
|
+
disabled,
|
|
3368
|
+
icon: /* @__PURE__ */ jsx8(EyeIcon, { className: previewActionIconClassName }),
|
|
3369
|
+
id,
|
|
3370
|
+
label: copy.t("openLabel"),
|
|
3371
|
+
onSelect: () => {
|
|
3372
|
+
void session.openEntry(entry);
|
|
3373
|
+
}
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
case "download": {
|
|
3377
|
+
const onDownload = config.onDownload;
|
|
3378
|
+
if (!onDownload) {
|
|
3379
|
+
return null;
|
|
3380
|
+
}
|
|
3381
|
+
return {
|
|
3382
|
+
disabled,
|
|
3383
|
+
icon: /* @__PURE__ */ jsx8(DownloadIcon, { className: previewActionIconClassName }),
|
|
3384
|
+
id,
|
|
3385
|
+
label: copy.t("downloadLabel"),
|
|
3386
|
+
onSelect: () => {
|
|
3387
|
+
void onDownload(entry);
|
|
3388
|
+
}
|
|
3389
|
+
};
|
|
3390
|
+
}
|
|
3391
|
+
case "share": {
|
|
3392
|
+
const onShare = config.onShare;
|
|
3393
|
+
if (!onShare) {
|
|
3394
|
+
return null;
|
|
3395
|
+
}
|
|
3396
|
+
return {
|
|
3397
|
+
disabled,
|
|
3398
|
+
icon: /* @__PURE__ */ jsx8(ShareLinedIcon, { className: previewActionIconClassName }),
|
|
3399
|
+
id,
|
|
3400
|
+
label: copy.t("shareLabel"),
|
|
3401
|
+
onSelect: () => {
|
|
3402
|
+
void onShare(entry);
|
|
3403
|
+
}
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
default:
|
|
3407
|
+
return null;
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
|
|
3411
|
+
// src/ui/workspaceFileManagerVisibleTree.ts
|
|
3412
|
+
function buildWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3413
|
+
return appendWorkspaceFileManagerVisibleTreeRows({
|
|
3414
|
+
...input,
|
|
3415
|
+
depth: 0
|
|
3416
|
+
});
|
|
3417
|
+
}
|
|
3418
|
+
function collectWorkspaceFileManagerVisibleTreeEntries(rows) {
|
|
3419
|
+
return rows.flatMap((row) => row.kind === "entry" ? [row.entry] : []);
|
|
3420
|
+
}
|
|
3421
|
+
function appendWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3422
|
+
const sortedEntries = sortWorkspaceFileEntriesForArrangeMode(
|
|
3423
|
+
input.entries,
|
|
3424
|
+
input.arrangeMode
|
|
3425
|
+
);
|
|
3426
|
+
const rows = [];
|
|
3427
|
+
for (const entry of sortedEntries) {
|
|
3428
|
+
const expandable = entry.kind === "directory" && entry.hasChildren;
|
|
3429
|
+
const expanded = expandable ? input.expandedDirectoryPaths[entry.path] === true : false;
|
|
3430
|
+
const childState = input.directoryExpansionByPath[entry.path];
|
|
3431
|
+
rows.push({
|
|
3432
|
+
depth: input.depth,
|
|
3433
|
+
entry,
|
|
3434
|
+
expanded,
|
|
3435
|
+
expandable,
|
|
3436
|
+
kind: "entry",
|
|
3437
|
+
loadingChildren: childState?.isLoading ?? false
|
|
3438
|
+
});
|
|
3439
|
+
if (!expanded) {
|
|
3440
|
+
continue;
|
|
3441
|
+
}
|
|
3442
|
+
if (!childState || childState.isLoading) {
|
|
3443
|
+
rows.push({
|
|
3444
|
+
depth: input.depth + 1,
|
|
3445
|
+
key: `${entry.path}:loading`,
|
|
3446
|
+
kind: "feedback",
|
|
3447
|
+
parentPath: entry.path,
|
|
3448
|
+
status: "loading"
|
|
3449
|
+
});
|
|
3450
|
+
continue;
|
|
3451
|
+
}
|
|
3452
|
+
if (childState.error) {
|
|
3453
|
+
rows.push({
|
|
3454
|
+
depth: input.depth + 1,
|
|
3455
|
+
key: `${entry.path}:error`,
|
|
3456
|
+
kind: "feedback",
|
|
3457
|
+
message: childState.error,
|
|
3458
|
+
parentPath: entry.path,
|
|
3459
|
+
status: "error"
|
|
3460
|
+
});
|
|
3461
|
+
continue;
|
|
3462
|
+
}
|
|
3463
|
+
if (childState.loaded && childState.entries.length === 0) {
|
|
3464
|
+
rows.push({
|
|
3465
|
+
depth: input.depth + 1,
|
|
3466
|
+
key: `${entry.path}:empty`,
|
|
3467
|
+
kind: "feedback",
|
|
3468
|
+
parentPath: entry.path,
|
|
3469
|
+
status: "empty"
|
|
3470
|
+
});
|
|
3471
|
+
continue;
|
|
3472
|
+
}
|
|
3473
|
+
rows.push(
|
|
3474
|
+
...appendWorkspaceFileManagerVisibleTreeRows({
|
|
3475
|
+
...input,
|
|
3476
|
+
depth: input.depth + 1,
|
|
3477
|
+
entries: childState.entries
|
|
3478
|
+
})
|
|
3479
|
+
);
|
|
3480
|
+
}
|
|
3481
|
+
return rows;
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
// src/ui/WorkspaceFileManagerPanelsContainer.tsx
|
|
3485
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
3486
|
+
function WorkspaceFileManagerPanelsContainer({
|
|
3487
|
+
arrangeMode,
|
|
3488
|
+
dateLocale,
|
|
3489
|
+
entryDragMode,
|
|
3490
|
+
i18n,
|
|
3491
|
+
layoutMode,
|
|
3492
|
+
onCopyEntry,
|
|
3493
|
+
onDirectoryExpanded,
|
|
3494
|
+
onEntryDragStart,
|
|
3495
|
+
onOpenContextMenu,
|
|
3496
|
+
previewActions,
|
|
3497
|
+
resolveEntryIconUrl,
|
|
3498
|
+
session,
|
|
3499
|
+
showPreviewPanel
|
|
3500
|
+
}) {
|
|
3501
|
+
const { state, view } = useWorkspaceFileManagerPanelsView(session);
|
|
3502
|
+
const arrangedEntries = useMemo4(
|
|
3503
|
+
() => sortWorkspaceFileEntriesForArrangeMode(state.entries, arrangeMode),
|
|
3504
|
+
[arrangeMode, state.entries]
|
|
3505
|
+
);
|
|
3506
|
+
const searchEntries = useMemo4(
|
|
3507
|
+
() => view.searchEntries.map(workspaceFileSearchEntryToEntry),
|
|
3508
|
+
[view.searchEntries]
|
|
3509
|
+
);
|
|
3510
|
+
const searchEntryContextByPath = useMemo4(() => {
|
|
3511
|
+
const contextByPath = /* @__PURE__ */ new Map();
|
|
3512
|
+
for (const entry of view.searchEntries) {
|
|
3513
|
+
contextByPath.set(entry.path, entry.directoryPath);
|
|
3514
|
+
}
|
|
3515
|
+
return contextByPath;
|
|
3516
|
+
}, [view.searchEntries]);
|
|
3517
|
+
const treeRows = useMemo4(
|
|
3518
|
+
() => buildWorkspaceFileManagerVisibleTreeRows({
|
|
3519
|
+
arrangeMode,
|
|
3520
|
+
directoryExpansionByPath: state.directoryExpansionByPath,
|
|
3521
|
+
entries: arrangedEntries,
|
|
3522
|
+
expandedDirectoryPaths: state.expandedDirectoryPaths
|
|
3523
|
+
}),
|
|
3524
|
+
[
|
|
3525
|
+
arrangeMode,
|
|
3526
|
+
arrangedEntries,
|
|
3527
|
+
state.directoryExpansionByPath,
|
|
3528
|
+
state.expandedDirectoryPaths
|
|
3529
|
+
]
|
|
3530
|
+
);
|
|
3531
|
+
const searchTreeRows = useMemo4(
|
|
3532
|
+
() => searchEntries.map((entry) => ({
|
|
3533
|
+
depth: 0,
|
|
3534
|
+
entry,
|
|
3535
|
+
expanded: false,
|
|
3536
|
+
expandable: false,
|
|
3537
|
+
kind: "entry",
|
|
3538
|
+
loadingChildren: false
|
|
3539
|
+
})),
|
|
3540
|
+
[searchEntries]
|
|
3541
|
+
);
|
|
3542
|
+
const displayedEntries = view.isSearchMode ? searchEntries : arrangedEntries;
|
|
3543
|
+
const displayedTreeRows = view.isSearchMode ? searchTreeRows : treeRows;
|
|
3544
|
+
const visibleTreeEntries = useMemo4(
|
|
3545
|
+
() => collectWorkspaceFileManagerVisibleTreeEntries(displayedTreeRows),
|
|
3546
|
+
[displayedTreeRows]
|
|
3547
|
+
);
|
|
3548
|
+
const panelState = useMemo4(
|
|
3549
|
+
() => ({
|
|
3550
|
+
entries: displayedEntries,
|
|
3551
|
+
error: view.isSearchMode ? view.searchError : state.error,
|
|
3552
|
+
isLoading: view.isSearchMode ? view.isSearching : state.isLoading,
|
|
3553
|
+
isSearchMode: view.isSearchMode
|
|
3554
|
+
}),
|
|
3555
|
+
[
|
|
3556
|
+
displayedEntries,
|
|
3557
|
+
state.error,
|
|
3558
|
+
state.isLoading,
|
|
3559
|
+
view.isSearchMode,
|
|
3560
|
+
view.isSearching,
|
|
3561
|
+
view.searchError
|
|
3562
|
+
]
|
|
3563
|
+
);
|
|
3564
|
+
const {
|
|
3565
|
+
iconUrlByCacheKey,
|
|
3566
|
+
reportEntryIconViewportEnter,
|
|
3567
|
+
reportEntryIconViewportLeave
|
|
3568
|
+
} = useWorkspaceFileEntryIconUrls({
|
|
3569
|
+
entries: layoutMode === "list" ? visibleTreeEntries : displayedEntries,
|
|
3570
|
+
includeImageThumbnails: true,
|
|
3571
|
+
resolveEntryIconUrl
|
|
3572
|
+
});
|
|
3573
|
+
const resolvedPreviewActions = useWorkspaceFileManagerPreviewActions({
|
|
3574
|
+
config: previewActions,
|
|
3575
|
+
copy: i18n,
|
|
3576
|
+
entry: view.selectedEntry,
|
|
3577
|
+
onCopyEntry,
|
|
3578
|
+
session,
|
|
3579
|
+
state
|
|
3580
|
+
});
|
|
3581
|
+
const handleBlankContextMenu = useCallback4(
|
|
3582
|
+
(event) => {
|
|
3583
|
+
onOpenContextMenu(event, null);
|
|
3584
|
+
},
|
|
3585
|
+
[onOpenContextMenu]
|
|
3586
|
+
);
|
|
3587
|
+
const handleCancelInlineRename = useCallback4(() => {
|
|
3588
|
+
session.cancelInlineRename();
|
|
3589
|
+
}, [session]);
|
|
3590
|
+
const handleClearInlineRenameValidation = useCallback4(() => {
|
|
3591
|
+
session.clearInlineRenameValidation();
|
|
3592
|
+
}, [session]);
|
|
3593
|
+
const handleConfirmInlineRename = useCallback4(
|
|
3594
|
+
(newName) => session.confirmInlineRename(newName),
|
|
3595
|
+
[session]
|
|
3596
|
+
);
|
|
3597
|
+
const handleMoveEntry = useCallback4(
|
|
3598
|
+
(entry, targetDirectoryPath) => {
|
|
3599
|
+
void session.moveEntry(entry, targetDirectoryPath);
|
|
3600
|
+
},
|
|
3601
|
+
[session]
|
|
3602
|
+
);
|
|
3603
|
+
const handleOpenEntry = useCallback4(
|
|
3604
|
+
(entry) => {
|
|
3605
|
+
if (entry.kind === "directory") {
|
|
3606
|
+
onDirectoryExpanded?.(entry.path);
|
|
3607
|
+
}
|
|
3608
|
+
void session.openEntry(entry);
|
|
3609
|
+
},
|
|
3610
|
+
[onDirectoryExpanded, session]
|
|
3611
|
+
);
|
|
3612
|
+
const handleSelect = useCallback4(
|
|
3613
|
+
(path) => {
|
|
3614
|
+
session.select(path);
|
|
3615
|
+
},
|
|
3616
|
+
[session]
|
|
3617
|
+
);
|
|
3618
|
+
const handleToggleDirectoryExpanded = useCallback4(
|
|
3619
|
+
(entry, expanded) => {
|
|
3620
|
+
if (!expanded) {
|
|
3621
|
+
onDirectoryExpanded?.(entry.path);
|
|
3622
|
+
}
|
|
3623
|
+
void session.toggleDirectoryExpanded(entry);
|
|
3624
|
+
},
|
|
3625
|
+
[onDirectoryExpanded, session]
|
|
3626
|
+
);
|
|
3627
|
+
return /* @__PURE__ */ jsx9(
|
|
3628
|
+
WorkspaceFileManagerPanels,
|
|
3629
|
+
{
|
|
3630
|
+
arrangeMode,
|
|
3631
|
+
canMove: view.isSearchMode ? false : view.canMove,
|
|
3632
|
+
contextMenuEntryPath: view.contextMenuEntryPath,
|
|
3633
|
+
copy: i18n,
|
|
3634
|
+
dateLocale,
|
|
3635
|
+
entryContextByPath: view.isSearchMode ? searchEntryContextByPath : null,
|
|
3636
|
+
entryDragMode,
|
|
3637
|
+
iconUrlByCacheKey,
|
|
3638
|
+
inlineRenameEntryPath: view.inlineRenameEntryPath,
|
|
3639
|
+
inlineRenameValidation: view.inlineRenameValidation,
|
|
3640
|
+
isRenaming: view.isRenaming,
|
|
3641
|
+
layoutMode,
|
|
3642
|
+
pendingDirectoryPath: view.pendingDirectoryPath,
|
|
3643
|
+
previewActions: resolvedPreviewActions,
|
|
3644
|
+
previewState: view.previewState,
|
|
3645
|
+
selectedEntry: view.selectedEntry,
|
|
3646
|
+
selectedPath: view.selectedPath,
|
|
3647
|
+
showPreviewPanel,
|
|
3648
|
+
state: panelState,
|
|
3649
|
+
treeRows: displayedTreeRows,
|
|
3650
|
+
onBlankContextMenu: handleBlankContextMenu,
|
|
3651
|
+
onCancelInlineRename: handleCancelInlineRename,
|
|
3652
|
+
onClearInlineRenameValidation: handleClearInlineRenameValidation,
|
|
3653
|
+
onConfirmInlineRename: handleConfirmInlineRename,
|
|
3654
|
+
onEntryContextMenu: onOpenContextMenu,
|
|
3655
|
+
onEntryDragStart,
|
|
3656
|
+
onEntryIconViewportEnter: reportEntryIconViewportEnter,
|
|
3657
|
+
onEntryIconViewportLeave: reportEntryIconViewportLeave,
|
|
3658
|
+
onMoveEntry: handleMoveEntry,
|
|
3659
|
+
onOpenEntry: handleOpenEntry,
|
|
3660
|
+
onSelect: handleSelect,
|
|
3661
|
+
onToggleDirectoryExpanded: handleToggleDirectoryExpanded
|
|
3662
|
+
}
|
|
3663
|
+
);
|
|
3664
|
+
}
|
|
3665
|
+
|
|
3666
|
+
// src/ui/WorkspaceFileManagerToolbar.tsx
|
|
3667
|
+
import {
|
|
3668
|
+
ArrowLeftIcon as ArrowLeftIcon2,
|
|
3669
|
+
ArrowRightIcon as ArrowRightIcon3,
|
|
3670
|
+
Button as Button3,
|
|
3671
|
+
ChevronDownIcon,
|
|
3672
|
+
CloseIcon,
|
|
3673
|
+
DropdownMenu,
|
|
3674
|
+
DropdownMenuContent,
|
|
3675
|
+
DropdownMenuRadioGroup,
|
|
3676
|
+
DropdownMenuRadioItem,
|
|
3677
|
+
DropdownMenuSeparator,
|
|
3678
|
+
DropdownMenuTrigger,
|
|
3679
|
+
Input as Input2,
|
|
3680
|
+
LoadingIcon as LoadingIcon3,
|
|
3681
|
+
RefreshIcon,
|
|
3682
|
+
SearchIcon,
|
|
3683
|
+
Tooltip,
|
|
3684
|
+
TooltipContent,
|
|
3685
|
+
TooltipProvider,
|
|
3686
|
+
TooltipTrigger,
|
|
3687
|
+
ViewGridLinedIcon,
|
|
3688
|
+
ViewListLinedIcon,
|
|
3689
|
+
cn as cn6
|
|
3690
|
+
} from "@tutti-os/ui-system";
|
|
3691
|
+
import { useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
|
|
3692
|
+
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3693
|
+
function WorkspaceFileManagerToolbar({
|
|
3694
|
+
breadcrumbs,
|
|
3695
|
+
canSearch,
|
|
3696
|
+
canGoBack,
|
|
3697
|
+
canGoForward,
|
|
3698
|
+
copy,
|
|
3699
|
+
currentDirectoryPath,
|
|
3700
|
+
isBusy,
|
|
3701
|
+
isLoading,
|
|
3702
|
+
isMutating,
|
|
3703
|
+
isSearching,
|
|
3704
|
+
arrangeMode,
|
|
3705
|
+
layoutMode,
|
|
3706
|
+
renderToolbarTrailingActions,
|
|
3707
|
+
searchQuery,
|
|
3708
|
+
onGoBack,
|
|
3709
|
+
onGoForward,
|
|
3710
|
+
onArrangeModeChange,
|
|
3711
|
+
onLayoutModeChange,
|
|
3712
|
+
onLoadDirectory,
|
|
3713
|
+
onRefresh,
|
|
3714
|
+
onSearchClear,
|
|
3715
|
+
onSearchQueryChange
|
|
3716
|
+
}) {
|
|
3717
|
+
const [refreshAnimationKey, setRefreshAnimationKey] = useState5(0);
|
|
3718
|
+
const handleRefresh = () => {
|
|
3719
|
+
setRefreshAnimationKey((currentKey) => currentKey + 1);
|
|
3720
|
+
onRefresh();
|
|
3721
|
+
};
|
|
3722
|
+
return /* @__PURE__ */ jsxs6("header", { className: "@max-[600px]/workspace-file-manager:flex-nowrap flex h-10 min-h-10 w-full min-w-0 items-center gap-2 border-b border-[var(--border-1)] px-2 py-1", children: [
|
|
3723
|
+
/* @__PURE__ */ jsx10(
|
|
3724
|
+
ToolbarIconButton,
|
|
3725
|
+
{
|
|
3726
|
+
ariaLabel: copy.t("backLabel"),
|
|
3727
|
+
disabled: !canGoBack || isLoading || isBusy,
|
|
3728
|
+
title: copy.t("backLabel"),
|
|
3729
|
+
onClick: onGoBack,
|
|
3730
|
+
children: /* @__PURE__ */ jsx10(ArrowLeftIcon2, { className: "size-4" })
|
|
3731
|
+
}
|
|
3732
|
+
),
|
|
3733
|
+
/* @__PURE__ */ jsx10(
|
|
3734
|
+
ToolbarIconButton,
|
|
3735
|
+
{
|
|
3736
|
+
ariaLabel: copy.t("forwardLabel"),
|
|
3737
|
+
disabled: !canGoForward || isLoading || isBusy,
|
|
3738
|
+
title: copy.t("forwardLabel"),
|
|
3739
|
+
onClick: onGoForward,
|
|
3740
|
+
children: /* @__PURE__ */ jsx10(ArrowRightIcon3, { className: "size-4" })
|
|
3741
|
+
}
|
|
3742
|
+
),
|
|
3743
|
+
/* @__PURE__ */ jsx10(
|
|
3744
|
+
"nav",
|
|
3745
|
+
{
|
|
3746
|
+
"aria-label": currentDirectoryPath,
|
|
3747
|
+
className: "@max-[600px]/workspace-file-manager:flex-auto flex min-w-0 flex-1 overflow-hidden pr-2",
|
|
3748
|
+
"data-workspace-file-manager-path": "",
|
|
3749
|
+
children: /* @__PURE__ */ jsx10("ol", { className: "flex min-w-0 max-w-full flex-1 items-center gap-2 overflow-hidden", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsx10(
|
|
3750
|
+
BreadcrumbButton,
|
|
3751
|
+
{
|
|
3752
|
+
active: index === breadcrumbs.length - 1,
|
|
3753
|
+
label: crumb.label,
|
|
3754
|
+
showSeparator: index > 0,
|
|
3755
|
+
onClick: () => {
|
|
3756
|
+
onLoadDirectory(crumb.path);
|
|
3757
|
+
}
|
|
3758
|
+
},
|
|
3759
|
+
crumb.path
|
|
3760
|
+
)) })
|
|
3761
|
+
}
|
|
3762
|
+
),
|
|
3763
|
+
/* @__PURE__ */ jsxs6("div", { className: "@max-[600px]/workspace-file-manager:justify-end flex flex-none items-center gap-1.5", children: [
|
|
3764
|
+
/* @__PURE__ */ jsx10(
|
|
3765
|
+
LayoutModeToggle,
|
|
3766
|
+
{
|
|
3767
|
+
arrangeMode,
|
|
3768
|
+
copy,
|
|
3769
|
+
layoutMode,
|
|
3770
|
+
onArrangeModeChange,
|
|
3771
|
+
onLayoutModeChange
|
|
3772
|
+
}
|
|
3773
|
+
),
|
|
3774
|
+
/* @__PURE__ */ jsxs6(
|
|
3775
|
+
ToolbarActionButton,
|
|
3776
|
+
{
|
|
3777
|
+
disabled: isLoading || isMutating || isBusy,
|
|
3778
|
+
onClick: handleRefresh,
|
|
3779
|
+
children: [
|
|
3780
|
+
isLoading ? /* @__PURE__ */ jsx10(LoadingIcon3, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx10(
|
|
3781
|
+
RefreshIcon,
|
|
3782
|
+
{
|
|
3783
|
+
className: cn6(
|
|
3784
|
+
"size-4",
|
|
3785
|
+
refreshAnimationKey > 0 && "motion-safe:animate-[spin_520ms_cubic-bezier(0.4,0,0.2,1)_1_reverse]"
|
|
3786
|
+
)
|
|
3787
|
+
},
|
|
3788
|
+
refreshAnimationKey
|
|
3789
|
+
),
|
|
3790
|
+
/* @__PURE__ */ jsx10("span", { className: "@max-[600px]/workspace-file-manager:hidden", children: copy.t("refreshLabel") })
|
|
3791
|
+
]
|
|
3792
|
+
}
|
|
3793
|
+
),
|
|
3794
|
+
renderToolbarTrailingActions?.({
|
|
3795
|
+
currentDirectoryPath,
|
|
3796
|
+
isBusy,
|
|
3797
|
+
isLoading,
|
|
3798
|
+
isMutating
|
|
3799
|
+
}) ?? null,
|
|
3800
|
+
/* @__PURE__ */ jsx10(
|
|
3801
|
+
WorkspaceFileManagerToolbarSearch,
|
|
3802
|
+
{
|
|
3116
3803
|
canSearch,
|
|
3117
3804
|
copy,
|
|
3118
3805
|
isSearching,
|
|
@@ -3132,23 +3819,23 @@ function WorkspaceFileManagerToolbarSearch({
|
|
|
3132
3819
|
onClear,
|
|
3133
3820
|
onSearchQueryChange
|
|
3134
3821
|
}) {
|
|
3135
|
-
const [expanded, setExpanded] =
|
|
3136
|
-
const [inputValue, setInputValue] =
|
|
3822
|
+
const [expanded, setExpanded] = useState5(searchQuery.trim().length > 0);
|
|
3823
|
+
const [inputValue, setInputValue] = useState5(searchQuery);
|
|
3137
3824
|
const inputRef = useRef6(null);
|
|
3138
3825
|
const isComposingRef = useRef6(false);
|
|
3139
3826
|
const active = expanded || searchQuery.trim().length > 0;
|
|
3140
|
-
|
|
3827
|
+
useEffect6(() => {
|
|
3141
3828
|
if (searchQuery.trim().length > 0) {
|
|
3142
3829
|
setExpanded(true);
|
|
3143
3830
|
}
|
|
3144
3831
|
}, [searchQuery]);
|
|
3145
|
-
|
|
3832
|
+
useEffect6(() => {
|
|
3146
3833
|
if (!expanded) {
|
|
3147
3834
|
return;
|
|
3148
3835
|
}
|
|
3149
3836
|
inputRef.current?.focus();
|
|
3150
3837
|
}, [expanded]);
|
|
3151
|
-
|
|
3838
|
+
useEffect6(() => {
|
|
3152
3839
|
if (isComposingRef.current) {
|
|
3153
3840
|
return;
|
|
3154
3841
|
}
|
|
@@ -3165,7 +3852,7 @@ function WorkspaceFileManagerToolbarSearch({
|
|
|
3165
3852
|
setExpanded(false);
|
|
3166
3853
|
};
|
|
3167
3854
|
if (!active) {
|
|
3168
|
-
return /* @__PURE__ */
|
|
3855
|
+
return /* @__PURE__ */ jsx10(
|
|
3169
3856
|
ToolbarIconButton,
|
|
3170
3857
|
{
|
|
3171
3858
|
ariaLabel: copy.t("searchPlaceholder"),
|
|
@@ -3174,21 +3861,21 @@ function WorkspaceFileManagerToolbarSearch({
|
|
|
3174
3861
|
onClick: () => {
|
|
3175
3862
|
setExpanded(true);
|
|
3176
3863
|
},
|
|
3177
|
-
children: /* @__PURE__ */
|
|
3864
|
+
children: /* @__PURE__ */ jsx10(SearchIcon, { className: "size-4" })
|
|
3178
3865
|
}
|
|
3179
3866
|
);
|
|
3180
3867
|
}
|
|
3181
3868
|
return /* @__PURE__ */ jsxs6(
|
|
3182
3869
|
"div",
|
|
3183
3870
|
{
|
|
3184
|
-
className:
|
|
3871
|
+
className: cn6(
|
|
3185
3872
|
"relative h-7 w-[min(220px,34vw)] flex-none overflow-hidden rounded-md bg-[var(--transparency-block)] transition-[width,opacity,background-color] duration-200 ease-out",
|
|
3186
3873
|
"@max-[600px]/workspace-file-manager:w-[min(170px,42vw)]",
|
|
3187
3874
|
!canSearch && "opacity-60"
|
|
3188
3875
|
),
|
|
3189
3876
|
children: [
|
|
3190
|
-
/* @__PURE__ */
|
|
3191
|
-
/* @__PURE__ */
|
|
3877
|
+
/* @__PURE__ */ jsx10(SearchIcon, { className: "pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 text-[var(--text-tertiary)]" }),
|
|
3878
|
+
/* @__PURE__ */ jsx10(
|
|
3192
3879
|
Input2,
|
|
3193
3880
|
{
|
|
3194
3881
|
"aria-label": copy.t("searchPlaceholder"),
|
|
@@ -3227,14 +3914,14 @@ function WorkspaceFileManagerToolbarSearch({
|
|
|
3227
3914
|
}
|
|
3228
3915
|
}
|
|
3229
3916
|
),
|
|
3230
|
-
/* @__PURE__ */
|
|
3917
|
+
/* @__PURE__ */ jsx10(
|
|
3231
3918
|
"button",
|
|
3232
3919
|
{
|
|
3233
3920
|
"aria-label": copy.t("clearSearchLabel"),
|
|
3234
3921
|
className: "absolute top-1/2 right-1 grid size-5 -translate-y-1/2 place-items-center rounded-[4px] text-[var(--text-tertiary)] transition-colors hover:bg-[var(--transparency-hover)] hover:text-[var(--text-primary)]",
|
|
3235
3922
|
type: "button",
|
|
3236
3923
|
onClick: handleClear,
|
|
3237
|
-
children: isSearching ? /* @__PURE__ */
|
|
3924
|
+
children: isSearching ? /* @__PURE__ */ jsx10(LoadingIcon3, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx10(CloseIcon, { className: "size-3" })
|
|
3238
3925
|
}
|
|
3239
3926
|
)
|
|
3240
3927
|
]
|
|
@@ -3259,13 +3946,13 @@ function LayoutModeToggle({
|
|
|
3259
3946
|
{ label: copy.t("arrangeCreatedLabel"), mode: "created" },
|
|
3260
3947
|
{ label: copy.t("sizeLabel"), mode: "size" }
|
|
3261
3948
|
];
|
|
3262
|
-
return /* @__PURE__ */
|
|
3949
|
+
return /* @__PURE__ */ jsx10(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs6(
|
|
3263
3950
|
"div",
|
|
3264
3951
|
{
|
|
3265
3952
|
className: "flex items-center rounded-md border border-[var(--border-1)] bg-[var(--transparency-block)] p-0.5",
|
|
3266
3953
|
role: "group",
|
|
3267
3954
|
children: [
|
|
3268
|
-
/* @__PURE__ */
|
|
3955
|
+
/* @__PURE__ */ jsx10(
|
|
3269
3956
|
LayoutModeButton,
|
|
3270
3957
|
{
|
|
3271
3958
|
active: layoutMode === "icon",
|
|
@@ -3274,10 +3961,10 @@ function LayoutModeToggle({
|
|
|
3274
3961
|
onClick: () => {
|
|
3275
3962
|
onLayoutModeChange("icon");
|
|
3276
3963
|
},
|
|
3277
|
-
children: /* @__PURE__ */
|
|
3964
|
+
children: /* @__PURE__ */ jsx10(ViewGridLinedIcon, { className: "size-4" })
|
|
3278
3965
|
}
|
|
3279
3966
|
),
|
|
3280
|
-
/* @__PURE__ */
|
|
3967
|
+
/* @__PURE__ */ jsx10(
|
|
3281
3968
|
LayoutModeButton,
|
|
3282
3969
|
{
|
|
3283
3970
|
active: layoutMode === "list",
|
|
@@ -3286,30 +3973,30 @@ function LayoutModeToggle({
|
|
|
3286
3973
|
onClick: () => {
|
|
3287
3974
|
onLayoutModeChange("list");
|
|
3288
3975
|
},
|
|
3289
|
-
children: /* @__PURE__ */
|
|
3976
|
+
children: /* @__PURE__ */ jsx10(ViewListLinedIcon, { className: "size-4" })
|
|
3290
3977
|
}
|
|
3291
3978
|
),
|
|
3292
|
-
/* @__PURE__ */
|
|
3979
|
+
/* @__PURE__ */ jsx10("span", { className: "mx-0.5 h-4 w-px bg-[var(--border-1)]", "aria-hidden": true }),
|
|
3293
3980
|
/* @__PURE__ */ jsxs6(DropdownMenu, { children: [
|
|
3294
|
-
/* @__PURE__ */
|
|
3295
|
-
|
|
3981
|
+
/* @__PURE__ */ jsx10(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
|
|
3982
|
+
Button3,
|
|
3296
3983
|
{
|
|
3297
3984
|
"aria-label": copy.t("arrangeMenuLabel"),
|
|
3298
3985
|
className: "size-6 min-w-6 rounded-[4px] p-0 text-[var(--text-secondary)] data-[state=open]:bg-[var(--background-fronted)] data-[state=open]:text-[var(--text-primary)] data-[state=open]:shadow-sm",
|
|
3299
3986
|
size: "icon-sm",
|
|
3300
3987
|
type: "button",
|
|
3301
3988
|
variant: "ghost",
|
|
3302
|
-
children: /* @__PURE__ */
|
|
3989
|
+
children: /* @__PURE__ */ jsx10(ChevronDownIcon, { className: "size-3.5" })
|
|
3303
3990
|
}
|
|
3304
3991
|
) }),
|
|
3305
|
-
/* @__PURE__ */
|
|
3992
|
+
/* @__PURE__ */ jsx10(
|
|
3306
3993
|
DropdownMenuContent,
|
|
3307
3994
|
{
|
|
3308
3995
|
align: "end",
|
|
3309
3996
|
className: "min-w-[236px] px-1 py-1",
|
|
3310
3997
|
sideOffset: 7,
|
|
3311
3998
|
style: { zIndex: "var(--z-panel-popover)" },
|
|
3312
|
-
children: /* @__PURE__ */
|
|
3999
|
+
children: /* @__PURE__ */ jsx10(
|
|
3313
4000
|
DropdownMenuRadioGroup,
|
|
3314
4001
|
{
|
|
3315
4002
|
value: arrangeMode,
|
|
@@ -3319,8 +4006,8 @@ function LayoutModeToggle({
|
|
|
3319
4006
|
);
|
|
3320
4007
|
},
|
|
3321
4008
|
children: arrangeOptions.map((option, index) => /* @__PURE__ */ jsxs6("div", { children: [
|
|
3322
|
-
index === 1 ? /* @__PURE__ */
|
|
3323
|
-
/* @__PURE__ */
|
|
4009
|
+
index === 1 ? /* @__PURE__ */ jsx10(DropdownMenuSeparator, {}) : null,
|
|
4010
|
+
/* @__PURE__ */ jsx10(
|
|
3324
4011
|
DropdownMenuRadioItem,
|
|
3325
4012
|
{
|
|
3326
4013
|
className: "h-8 text-sm font-normal",
|
|
@@ -3346,12 +4033,12 @@ function LayoutModeButton({
|
|
|
3346
4033
|
tooltipLabel
|
|
3347
4034
|
}) {
|
|
3348
4035
|
return /* @__PURE__ */ jsxs6(Tooltip, { children: [
|
|
3349
|
-
/* @__PURE__ */
|
|
3350
|
-
|
|
4036
|
+
/* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
|
|
4037
|
+
Button3,
|
|
3351
4038
|
{
|
|
3352
4039
|
"aria-label": ariaLabel,
|
|
3353
4040
|
"aria-pressed": active,
|
|
3354
|
-
className:
|
|
4041
|
+
className: cn6(
|
|
3355
4042
|
"size-6 min-w-6 rounded-[4px] p-0 text-text-secondary",
|
|
3356
4043
|
active && "!bg-background-fronted text-foreground hover:!bg-background-fronted"
|
|
3357
4044
|
),
|
|
@@ -3362,7 +4049,7 @@ function LayoutModeButton({
|
|
|
3362
4049
|
children
|
|
3363
4050
|
}
|
|
3364
4051
|
) }),
|
|
3365
|
-
/* @__PURE__ */
|
|
4052
|
+
/* @__PURE__ */ jsx10(TooltipContent, { side: "bottom", children: tooltipLabel })
|
|
3366
4053
|
] });
|
|
3367
4054
|
}
|
|
3368
4055
|
function ToolbarIconButton({
|
|
@@ -3372,8 +4059,8 @@ function ToolbarIconButton({
|
|
|
3372
4059
|
onClick,
|
|
3373
4060
|
title
|
|
3374
4061
|
}) {
|
|
3375
|
-
return /* @__PURE__ */
|
|
3376
|
-
|
|
4062
|
+
return /* @__PURE__ */ jsx10(
|
|
4063
|
+
Button3,
|
|
3377
4064
|
{
|
|
3378
4065
|
"aria-label": ariaLabel,
|
|
3379
4066
|
className: "size-7 min-w-7 rounded-sm p-0 text-[var(--text-primary)]",
|
|
@@ -3392,8 +4079,8 @@ function ToolbarActionButton({
|
|
|
3392
4079
|
disabled,
|
|
3393
4080
|
onClick
|
|
3394
4081
|
}) {
|
|
3395
|
-
return /* @__PURE__ */
|
|
3396
|
-
|
|
4082
|
+
return /* @__PURE__ */ jsx10(
|
|
4083
|
+
Button3,
|
|
3397
4084
|
{
|
|
3398
4085
|
className: "@max-[600px]/workspace-file-manager:size-7 @max-[600px]/workspace-file-manager:min-w-7 @max-[600px]/workspace-file-manager:px-0 cursor-pointer",
|
|
3399
4086
|
disabled,
|
|
@@ -3412,11 +4099,11 @@ function BreadcrumbButton({
|
|
|
3412
4099
|
showSeparator
|
|
3413
4100
|
}) {
|
|
3414
4101
|
return /* @__PURE__ */ jsxs6("li", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3415
|
-
showSeparator ? /* @__PURE__ */
|
|
3416
|
-
/* @__PURE__ */
|
|
4102
|
+
showSeparator ? /* @__PURE__ */ jsx10("span", { className: "flex-none text-[var(--text-tertiary)]", children: "/" }) : null,
|
|
4103
|
+
/* @__PURE__ */ jsx10(
|
|
3417
4104
|
"button",
|
|
3418
4105
|
{
|
|
3419
|
-
className:
|
|
4106
|
+
className: cn6(
|
|
3420
4107
|
"min-w-0 overflow-hidden text-ellipsis whitespace-nowrap border-0 bg-transparent text-sm font-normal transition-colors",
|
|
3421
4108
|
active ? "font-semibold text-[var(--text-primary)]" : "text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
|
|
3422
4109
|
),
|
|
@@ -3437,9 +4124,9 @@ import {
|
|
|
3437
4124
|
TooltipContent as TooltipContent2,
|
|
3438
4125
|
TooltipProvider as TooltipProvider2,
|
|
3439
4126
|
TooltipTrigger as TooltipTrigger2,
|
|
3440
|
-
cn as
|
|
4127
|
+
cn as cn7
|
|
3441
4128
|
} from "@tutti-os/ui-system";
|
|
3442
|
-
import { jsx as
|
|
4129
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3443
4130
|
function WorkspaceFileManagerSidebar({
|
|
3444
4131
|
disabled,
|
|
3445
4132
|
locationSections,
|
|
@@ -3453,14 +4140,14 @@ function WorkspaceFileManagerSidebar({
|
|
|
3453
4140
|
if (visibleSections.length === 0) {
|
|
3454
4141
|
return null;
|
|
3455
4142
|
}
|
|
3456
|
-
return /* @__PURE__ */
|
|
4143
|
+
return /* @__PURE__ */ jsx11(
|
|
3457
4144
|
"aside",
|
|
3458
4145
|
{
|
|
3459
4146
|
className: "@max-[600px]/workspace-file-manager:hidden flex shrink-0 flex-col border-r border-[var(--border-1)] bg-[var(--background-panel)]",
|
|
3460
4147
|
style: { minWidth: width, width },
|
|
3461
|
-
children: /* @__PURE__ */
|
|
3462
|
-
/* @__PURE__ */
|
|
3463
|
-
/* @__PURE__ */
|
|
4148
|
+
children: /* @__PURE__ */ jsx11(ScrollArea2, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx11(TooltipProvider2, { delayDuration: 350, children: /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-3 px-2 py-3", children: visibleSections.map((section) => /* @__PURE__ */ jsxs7("section", { className: "min-w-0", children: [
|
|
4149
|
+
/* @__PURE__ */ jsx11("h2", { className: "mb-1 px-2 text-[11px] font-medium uppercase tracking-normal text-[var(--text-tertiary)]", children: section.label }),
|
|
4150
|
+
/* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-0.5", children: section.locations.map((location) => /* @__PURE__ */ jsx11(
|
|
3464
4151
|
WorkspaceFileManagerSidebarLocation,
|
|
3465
4152
|
{
|
|
3466
4153
|
active: location.id === selectedLocationId,
|
|
@@ -3485,7 +4172,7 @@ function WorkspaceFileManagerSidebarLocation({
|
|
|
3485
4172
|
"button",
|
|
3486
4173
|
{
|
|
3487
4174
|
"aria-current": active ? "page" : void 0,
|
|
3488
|
-
className:
|
|
4175
|
+
className: cn7(
|
|
3489
4176
|
"flex h-8 min-w-0 items-center gap-2 rounded-md border border-transparent px-2 text-left text-sm text-[var(--text-secondary)] transition-colors",
|
|
3490
4177
|
active ? "border-[var(--line-2)] bg-[var(--background-fronted)] text-[var(--text-primary)] shadow-none" : "hover:bg-[var(--transparency-block)] hover:text-[var(--text-primary)]",
|
|
3491
4178
|
disabled && "pointer-events-none opacity-60"
|
|
@@ -3496,8 +4183,8 @@ function WorkspaceFileManagerSidebarLocation({
|
|
|
3496
4183
|
onSelectLocation(location);
|
|
3497
4184
|
},
|
|
3498
4185
|
children: [
|
|
3499
|
-
location.kind === "external" && location.iconUrl ? /* @__PURE__ */
|
|
3500
|
-
/* @__PURE__ */
|
|
4186
|
+
location.kind === "external" && location.iconUrl ? /* @__PURE__ */ jsx11(ExternalLocationIcon, { location }) : /* @__PURE__ */ jsx11(Icon, { className: "size-4 flex-none" }),
|
|
4187
|
+
/* @__PURE__ */ jsx11("span", { className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap", children: location.label })
|
|
3501
4188
|
]
|
|
3502
4189
|
}
|
|
3503
4190
|
);
|
|
@@ -3505,14 +4192,14 @@ function WorkspaceFileManagerSidebarLocation({
|
|
|
3505
4192
|
return content;
|
|
3506
4193
|
}
|
|
3507
4194
|
return /* @__PURE__ */ jsxs7(Tooltip2, { children: [
|
|
3508
|
-
/* @__PURE__ */
|
|
3509
|
-
/* @__PURE__ */
|
|
4195
|
+
/* @__PURE__ */ jsx11(TooltipTrigger2, { asChild: true, children: content }),
|
|
4196
|
+
/* @__PURE__ */ jsx11(TooltipContent2, { side: "right", children: location.contextLabel })
|
|
3510
4197
|
] });
|
|
3511
4198
|
}
|
|
3512
4199
|
function ExternalLocationIcon({
|
|
3513
4200
|
location
|
|
3514
4201
|
}) {
|
|
3515
|
-
return /* @__PURE__ */
|
|
4202
|
+
return /* @__PURE__ */ jsx11(
|
|
3516
4203
|
"img",
|
|
3517
4204
|
{
|
|
3518
4205
|
alt: "",
|
|
@@ -3523,283 +4210,58 @@ function ExternalLocationIcon({
|
|
|
3523
4210
|
}
|
|
3524
4211
|
|
|
3525
4212
|
// src/ui/useWorkspaceFileManagerArrangeMode.ts
|
|
3526
|
-
import { useCallback as
|
|
4213
|
+
import { useCallback as useCallback5, useState as useState6 } from "react";
|
|
3527
4214
|
function useWorkspaceFileManagerArrangeMode() {
|
|
3528
|
-
const [arrangeMode, setArrangeModeState] =
|
|
4215
|
+
const [arrangeMode, setArrangeModeState] = useState6(
|
|
3529
4216
|
readWorkspaceFileManagerArrangeMode
|
|
3530
4217
|
);
|
|
3531
|
-
const setArrangeMode =
|
|
3532
|
-
(nextArrangeMode) => {
|
|
3533
|
-
setArrangeModeState(nextArrangeMode);
|
|
3534
|
-
writeWorkspaceFileManagerArrangeMode(nextArrangeMode);
|
|
3535
|
-
},
|
|
3536
|
-
[]
|
|
3537
|
-
);
|
|
3538
|
-
return { arrangeMode, setArrangeMode };
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
|
-
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
3542
|
-
import { useCallback as useCallback4, useState as useState6 } from "react";
|
|
3543
|
-
|
|
3544
|
-
// src/ui/workspaceFileManagerLayoutMode.ts
|
|
3545
|
-
var workspaceFileManagerLayoutModeStorageKey = "tutti.workspace-file-manager.layout-mode";
|
|
3546
|
-
function readWorkspaceFileManagerLayoutMode() {
|
|
3547
|
-
if (typeof window === "undefined") {
|
|
3548
|
-
return "list";
|
|
3549
|
-
}
|
|
3550
|
-
const stored = window.localStorage.getItem(
|
|
3551
|
-
workspaceFileManagerLayoutModeStorageKey
|
|
3552
|
-
);
|
|
3553
|
-
return stored === "icon" ? "icon" : "list";
|
|
3554
|
-
}
|
|
3555
|
-
function writeWorkspaceFileManagerLayoutMode(layoutMode) {
|
|
3556
|
-
if (typeof window === "undefined") {
|
|
3557
|
-
return;
|
|
3558
|
-
}
|
|
3559
|
-
window.localStorage.setItem(
|
|
3560
|
-
workspaceFileManagerLayoutModeStorageKey,
|
|
3561
|
-
layoutMode
|
|
3562
|
-
);
|
|
3563
|
-
}
|
|
3564
|
-
|
|
3565
|
-
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
3566
|
-
function useWorkspaceFileManagerLayoutMode() {
|
|
3567
|
-
const [layoutMode, setLayoutModeState] = useState6(
|
|
3568
|
-
readWorkspaceFileManagerLayoutMode
|
|
3569
|
-
);
|
|
3570
|
-
const setLayoutMode = useCallback4(
|
|
3571
|
-
(nextLayoutMode) => {
|
|
3572
|
-
setLayoutModeState(nextLayoutMode);
|
|
3573
|
-
writeWorkspaceFileManagerLayoutMode(nextLayoutMode);
|
|
3574
|
-
},
|
|
3575
|
-
[]
|
|
3576
|
-
);
|
|
3577
|
-
return { layoutMode, setLayoutMode };
|
|
3578
|
-
}
|
|
3579
|
-
|
|
3580
|
-
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
3581
|
-
import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo2, useState as useState7 } from "react";
|
|
3582
|
-
|
|
3583
|
-
// src/ui/workspaceFileEntryIconUrlQueue.ts
|
|
3584
|
-
var defaultMaxConcurrentIconRequests = 3;
|
|
3585
|
-
var imageThumbnailCacheKeyPrefix = "image-thumbnail:";
|
|
3586
|
-
function shouldKeepResolvedIconAfterViewportLeave(cacheKey) {
|
|
3587
|
-
return cacheKey.startsWith(imageThumbnailCacheKeyPrefix);
|
|
3588
|
-
}
|
|
3589
|
-
function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
3590
|
-
const maxConcurrent = Math.max(
|
|
3591
|
-
1,
|
|
3592
|
-
Math.floor(options.maxConcurrent ?? defaultMaxConcurrentIconRequests)
|
|
3593
|
-
);
|
|
3594
|
-
const iconUrlByCacheKey = /* @__PURE__ */ new Map();
|
|
3595
|
-
const inFlightCacheKeys = /* @__PURE__ */ new Set();
|
|
3596
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
3597
|
-
const queuedEntries = /* @__PURE__ */ new Map();
|
|
3598
|
-
const visibleReferenceCountByCacheKey = /* @__PURE__ */ new Map();
|
|
3599
|
-
let activeCount = 0;
|
|
3600
|
-
let disposed = false;
|
|
3601
|
-
let retainedCacheKeys = null;
|
|
3602
|
-
const policyOptions = {
|
|
3603
|
-
includeImageThumbnails: options.includeImageThumbnails
|
|
3604
|
-
};
|
|
3605
|
-
function publish() {
|
|
3606
|
-
for (const listener of listeners) {
|
|
3607
|
-
listener();
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
function isRetained(cacheKey) {
|
|
3611
|
-
return retainedCacheKeys === null || retainedCacheKeys.has(cacheKey);
|
|
3612
|
-
}
|
|
3613
|
-
function isVisible(cacheKey) {
|
|
3614
|
-
return (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) > 0;
|
|
3615
|
-
}
|
|
3616
|
-
function shouldResolveCacheKey(cacheKey) {
|
|
3617
|
-
return isVisible(cacheKey) || shouldKeepResolvedIconAfterViewportLeave(cacheKey);
|
|
3618
|
-
}
|
|
3619
|
-
function retainVisibleReference(cacheKey) {
|
|
3620
|
-
visibleReferenceCountByCacheKey.set(
|
|
3621
|
-
cacheKey,
|
|
3622
|
-
(visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) + 1
|
|
3623
|
-
);
|
|
3624
|
-
}
|
|
3625
|
-
function releaseVisibleReference(cacheKey) {
|
|
3626
|
-
const nextCount = (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) - 1;
|
|
3627
|
-
if (nextCount > 0) {
|
|
3628
|
-
visibleReferenceCountByCacheKey.set(cacheKey, nextCount);
|
|
3629
|
-
return;
|
|
3630
|
-
}
|
|
3631
|
-
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
3632
|
-
if (shouldKeepResolvedIconAfterViewportLeave(cacheKey)) {
|
|
3633
|
-
return;
|
|
3634
|
-
}
|
|
3635
|
-
queuedEntries.delete(cacheKey);
|
|
3636
|
-
const hadCachedIcon = iconUrlByCacheKey.delete(cacheKey);
|
|
3637
|
-
if (hadCachedIcon) {
|
|
3638
|
-
publish();
|
|
3639
|
-
}
|
|
3640
|
-
}
|
|
3641
|
-
function drain() {
|
|
3642
|
-
if (disposed || !options.resolveEntryIconUrl) {
|
|
3643
|
-
return;
|
|
3644
|
-
}
|
|
3645
|
-
while (activeCount < maxConcurrent && queuedEntries.size > 0) {
|
|
3646
|
-
const next = queuedEntries.entries().next().value;
|
|
3647
|
-
if (!next) {
|
|
3648
|
-
return;
|
|
3649
|
-
}
|
|
3650
|
-
const [cacheKey, entry] = next;
|
|
3651
|
-
queuedEntries.delete(cacheKey);
|
|
3652
|
-
if (!shouldResolveCacheKey(cacheKey) || iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey)) {
|
|
3653
|
-
continue;
|
|
3654
|
-
}
|
|
3655
|
-
activeCount += 1;
|
|
3656
|
-
inFlightCacheKeys.add(cacheKey);
|
|
3657
|
-
void options.resolveEntryIconUrl(entry).then((iconUrl) => {
|
|
3658
|
-
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3659
|
-
if (shouldStore) {
|
|
3660
|
-
iconUrlByCacheKey.set(cacheKey, iconUrl?.trim() || null);
|
|
3661
|
-
publish();
|
|
3662
|
-
}
|
|
3663
|
-
}).catch(() => {
|
|
3664
|
-
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3665
|
-
if (shouldStore) {
|
|
3666
|
-
iconUrlByCacheKey.set(cacheKey, null);
|
|
3667
|
-
publish();
|
|
3668
|
-
}
|
|
3669
|
-
}).finally(() => {
|
|
3670
|
-
activeCount -= 1;
|
|
3671
|
-
inFlightCacheKeys.delete(cacheKey);
|
|
3672
|
-
drain();
|
|
3673
|
-
});
|
|
3674
|
-
}
|
|
3675
|
-
}
|
|
3676
|
-
return {
|
|
3677
|
-
activate() {
|
|
3678
|
-
disposed = false;
|
|
3679
|
-
},
|
|
3680
|
-
dispose() {
|
|
3681
|
-
disposed = true;
|
|
3682
|
-
queuedEntries.clear();
|
|
3683
|
-
visibleReferenceCountByCacheKey.clear();
|
|
3684
|
-
listeners.clear();
|
|
3685
|
-
},
|
|
3686
|
-
leaveViewport(entry) {
|
|
3687
|
-
if (disposed || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
3688
|
-
return;
|
|
3689
|
-
}
|
|
3690
|
-
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3691
|
-
releaseVisibleReference(cacheKey);
|
|
3692
|
-
},
|
|
3693
|
-
enterViewport(entry) {
|
|
3694
|
-
if (disposed || !options.resolveEntryIconUrl || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
3695
|
-
return;
|
|
3696
|
-
}
|
|
3697
|
-
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3698
|
-
retainVisibleReference(cacheKey);
|
|
3699
|
-
if (iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey) || queuedEntries.has(cacheKey)) {
|
|
3700
|
-
return;
|
|
3701
|
-
}
|
|
3702
|
-
queuedEntries.set(cacheKey, entry);
|
|
3703
|
-
drain();
|
|
3704
|
-
},
|
|
3705
|
-
retainEntries(entries) {
|
|
3706
|
-
retainedCacheKeys = new Set(
|
|
3707
|
-
entries.filter(
|
|
3708
|
-
(entry) => shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)
|
|
3709
|
-
).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry))
|
|
3710
|
-
);
|
|
3711
|
-
let changed = false;
|
|
3712
|
-
for (const cacheKey of iconUrlByCacheKey.keys()) {
|
|
3713
|
-
if (!isRetained(cacheKey)) {
|
|
3714
|
-
iconUrlByCacheKey.delete(cacheKey);
|
|
3715
|
-
changed = true;
|
|
3716
|
-
continue;
|
|
3717
|
-
}
|
|
3718
|
-
if (iconUrlByCacheKey.get(cacheKey) === null) {
|
|
3719
|
-
iconUrlByCacheKey.delete(cacheKey);
|
|
3720
|
-
changed = true;
|
|
3721
|
-
}
|
|
3722
|
-
}
|
|
3723
|
-
for (const cacheKey of queuedEntries.keys()) {
|
|
3724
|
-
if (!isRetained(cacheKey)) {
|
|
3725
|
-
queuedEntries.delete(cacheKey);
|
|
3726
|
-
}
|
|
3727
|
-
}
|
|
3728
|
-
for (const cacheKey of visibleReferenceCountByCacheKey.keys()) {
|
|
3729
|
-
if (!isRetained(cacheKey)) {
|
|
3730
|
-
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
3731
|
-
}
|
|
3732
|
-
}
|
|
3733
|
-
if (changed) {
|
|
3734
|
-
publish();
|
|
3735
|
-
}
|
|
3736
|
-
},
|
|
3737
|
-
snapshot() {
|
|
3738
|
-
return new Map(iconUrlByCacheKey);
|
|
3739
|
-
},
|
|
3740
|
-
subscribe(listener) {
|
|
3741
|
-
if (disposed) {
|
|
3742
|
-
return () => {
|
|
3743
|
-
};
|
|
3744
|
-
}
|
|
3745
|
-
listeners.add(listener);
|
|
3746
|
-
return () => {
|
|
3747
|
-
listeners.delete(listener);
|
|
3748
|
-
};
|
|
3749
|
-
}
|
|
3750
|
-
};
|
|
3751
|
-
}
|
|
3752
|
-
|
|
3753
|
-
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
3754
|
-
function buildIconTargetSignature(entries, options) {
|
|
3755
|
-
return entries.filter((entry) => shouldResolveWorkspaceFileEntryIcon(entry, options)).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry)).join("\0");
|
|
3756
|
-
}
|
|
3757
|
-
function useWorkspaceFileEntryIconUrls(input) {
|
|
3758
|
-
const { entries, includeImageThumbnails, resolveEntryIconUrl } = input;
|
|
3759
|
-
const queue = useMemo2(
|
|
3760
|
-
() => createWorkspaceFileEntryIconUrlQueue({
|
|
3761
|
-
includeImageThumbnails,
|
|
3762
|
-
resolveEntryIconUrl
|
|
3763
|
-
}),
|
|
3764
|
-
[includeImageThumbnails, resolveEntryIconUrl]
|
|
3765
|
-
);
|
|
3766
|
-
const [iconUrlByCacheKey, setIconUrlByCacheKey] = useState7(() => queue.snapshot());
|
|
3767
|
-
const iconTargetSignature = useMemo2(
|
|
3768
|
-
() => buildIconTargetSignature(entries, { includeImageThumbnails }),
|
|
3769
|
-
[entries, includeImageThumbnails]
|
|
3770
|
-
);
|
|
3771
|
-
useEffect6(() => {
|
|
3772
|
-
queue.activate();
|
|
3773
|
-
return () => {
|
|
3774
|
-
queue.dispose();
|
|
3775
|
-
};
|
|
3776
|
-
}, [queue]);
|
|
3777
|
-
useEffect6(() => {
|
|
3778
|
-
queue.retainEntries(entries);
|
|
3779
|
-
}, [entries, iconTargetSignature, queue]);
|
|
3780
|
-
useEffect6(() => {
|
|
3781
|
-
setIconUrlByCacheKey(queue.snapshot());
|
|
3782
|
-
return queue.subscribe(() => {
|
|
3783
|
-
setIconUrlByCacheKey(queue.snapshot());
|
|
3784
|
-
});
|
|
3785
|
-
}, [queue]);
|
|
3786
|
-
const reportEntryIconViewportEnter = useCallback5(
|
|
3787
|
-
(entry) => {
|
|
3788
|
-
queue.enterViewport(entry);
|
|
4218
|
+
const setArrangeMode = useCallback5(
|
|
4219
|
+
(nextArrangeMode) => {
|
|
4220
|
+
setArrangeModeState(nextArrangeMode);
|
|
4221
|
+
writeWorkspaceFileManagerArrangeMode(nextArrangeMode);
|
|
3789
4222
|
},
|
|
3790
|
-
[
|
|
4223
|
+
[]
|
|
3791
4224
|
);
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
4225
|
+
return { arrangeMode, setArrangeMode };
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
4229
|
+
import { useCallback as useCallback6, useState as useState7 } from "react";
|
|
4230
|
+
|
|
4231
|
+
// src/ui/workspaceFileManagerLayoutMode.ts
|
|
4232
|
+
var workspaceFileManagerLayoutModeStorageKey = "tutti.workspace-file-manager.layout-mode";
|
|
4233
|
+
function readWorkspaceFileManagerLayoutMode() {
|
|
4234
|
+
if (typeof window === "undefined") {
|
|
4235
|
+
return "list";
|
|
4236
|
+
}
|
|
4237
|
+
const stored = window.localStorage.getItem(
|
|
4238
|
+
workspaceFileManagerLayoutModeStorageKey
|
|
4239
|
+
);
|
|
4240
|
+
return stored === "icon" ? "icon" : "list";
|
|
4241
|
+
}
|
|
4242
|
+
function writeWorkspaceFileManagerLayoutMode(layoutMode) {
|
|
4243
|
+
if (typeof window === "undefined") {
|
|
4244
|
+
return;
|
|
4245
|
+
}
|
|
4246
|
+
window.localStorage.setItem(
|
|
4247
|
+
workspaceFileManagerLayoutModeStorageKey,
|
|
4248
|
+
layoutMode
|
|
4249
|
+
);
|
|
4250
|
+
}
|
|
4251
|
+
|
|
4252
|
+
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
4253
|
+
function useWorkspaceFileManagerLayoutMode() {
|
|
4254
|
+
const [layoutMode, setLayoutModeState] = useState7(
|
|
4255
|
+
readWorkspaceFileManagerLayoutMode
|
|
4256
|
+
);
|
|
4257
|
+
const setLayoutMode = useCallback6(
|
|
4258
|
+
(nextLayoutMode) => {
|
|
4259
|
+
setLayoutModeState(nextLayoutMode);
|
|
4260
|
+
writeWorkspaceFileManagerLayoutMode(nextLayoutMode);
|
|
3795
4261
|
},
|
|
3796
|
-
[
|
|
4262
|
+
[]
|
|
3797
4263
|
);
|
|
3798
|
-
return {
|
|
3799
|
-
iconUrlByCacheKey,
|
|
3800
|
-
reportEntryIconViewportEnter,
|
|
3801
|
-
reportEntryIconViewportLeave
|
|
3802
|
-
};
|
|
4264
|
+
return { layoutMode, setLayoutMode };
|
|
3803
4265
|
}
|
|
3804
4266
|
|
|
3805
4267
|
// src/ui/workspaceFileManagerAnalytics.ts
|
|
@@ -3810,81 +4272,8 @@ function normalizeDirectoryPath(path) {
|
|
|
3810
4272
|
return path.trim().replaceAll("\\", "/").replace(/\/+$/u, "");
|
|
3811
4273
|
}
|
|
3812
4274
|
|
|
3813
|
-
// src/ui/workspaceFileManagerVisibleTree.ts
|
|
3814
|
-
function buildWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3815
|
-
return appendWorkspaceFileManagerVisibleTreeRows({
|
|
3816
|
-
...input,
|
|
3817
|
-
depth: 0
|
|
3818
|
-
});
|
|
3819
|
-
}
|
|
3820
|
-
function collectWorkspaceFileManagerVisibleTreeEntries(rows) {
|
|
3821
|
-
return rows.flatMap((row) => row.kind === "entry" ? [row.entry] : []);
|
|
3822
|
-
}
|
|
3823
|
-
function appendWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3824
|
-
const sortedEntries = sortWorkspaceFileEntriesForArrangeMode(
|
|
3825
|
-
input.entries,
|
|
3826
|
-
input.arrangeMode
|
|
3827
|
-
);
|
|
3828
|
-
const rows = [];
|
|
3829
|
-
for (const entry of sortedEntries) {
|
|
3830
|
-
const expandable = entry.kind === "directory" && entry.hasChildren;
|
|
3831
|
-
const expanded = expandable ? input.expandedDirectoryPaths[entry.path] === true : false;
|
|
3832
|
-
const childState = input.directoryExpansionByPath[entry.path];
|
|
3833
|
-
rows.push({
|
|
3834
|
-
depth: input.depth,
|
|
3835
|
-
entry,
|
|
3836
|
-
expanded,
|
|
3837
|
-
expandable,
|
|
3838
|
-
kind: "entry",
|
|
3839
|
-
loadingChildren: childState?.isLoading ?? false
|
|
3840
|
-
});
|
|
3841
|
-
if (!expanded) {
|
|
3842
|
-
continue;
|
|
3843
|
-
}
|
|
3844
|
-
if (!childState || childState.isLoading) {
|
|
3845
|
-
rows.push({
|
|
3846
|
-
depth: input.depth + 1,
|
|
3847
|
-
key: `${entry.path}:loading`,
|
|
3848
|
-
kind: "feedback",
|
|
3849
|
-
parentPath: entry.path,
|
|
3850
|
-
status: "loading"
|
|
3851
|
-
});
|
|
3852
|
-
continue;
|
|
3853
|
-
}
|
|
3854
|
-
if (childState.error) {
|
|
3855
|
-
rows.push({
|
|
3856
|
-
depth: input.depth + 1,
|
|
3857
|
-
key: `${entry.path}:error`,
|
|
3858
|
-
kind: "feedback",
|
|
3859
|
-
message: childState.error,
|
|
3860
|
-
parentPath: entry.path,
|
|
3861
|
-
status: "error"
|
|
3862
|
-
});
|
|
3863
|
-
continue;
|
|
3864
|
-
}
|
|
3865
|
-
if (childState.loaded && childState.entries.length === 0) {
|
|
3866
|
-
rows.push({
|
|
3867
|
-
depth: input.depth + 1,
|
|
3868
|
-
key: `${entry.path}:empty`,
|
|
3869
|
-
kind: "feedback",
|
|
3870
|
-
parentPath: entry.path,
|
|
3871
|
-
status: "empty"
|
|
3872
|
-
});
|
|
3873
|
-
continue;
|
|
3874
|
-
}
|
|
3875
|
-
rows.push(
|
|
3876
|
-
...appendWorkspaceFileManagerVisibleTreeRows({
|
|
3877
|
-
...input,
|
|
3878
|
-
depth: input.depth + 1,
|
|
3879
|
-
entries: childState.entries
|
|
3880
|
-
})
|
|
3881
|
-
);
|
|
3882
|
-
}
|
|
3883
|
-
return rows;
|
|
3884
|
-
}
|
|
3885
|
-
|
|
3886
4275
|
// src/ui/WorkspaceFileManager.tsx
|
|
3887
|
-
import { Fragment as Fragment3, jsx as
|
|
4276
|
+
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3888
4277
|
var workspaceFileManagerSearchDebounceMs = 180;
|
|
3889
4278
|
function WorkspaceFileManager({
|
|
3890
4279
|
className,
|
|
@@ -3894,6 +4283,7 @@ function WorkspaceFileManager({
|
|
|
3894
4283
|
onCopyEntry,
|
|
3895
4284
|
onDirectoryExpanded,
|
|
3896
4285
|
onEntryDragStart,
|
|
4286
|
+
previewActions,
|
|
3897
4287
|
resolveContextMenu,
|
|
3898
4288
|
resolveEntryIconUrl,
|
|
3899
4289
|
renderExternalLocationContent,
|
|
@@ -3913,7 +4303,7 @@ function WorkspaceFileManager({
|
|
|
3913
4303
|
const { layoutMode, setLayoutMode } = useWorkspaceFileManagerLayoutMode();
|
|
3914
4304
|
const rootView = useWorkspaceFileManagerRootView(session);
|
|
3915
4305
|
const { state: panelsState, view: panelsView } = useWorkspaceFileManagerPanelsView(session);
|
|
3916
|
-
const selectedExternalLocation =
|
|
4306
|
+
const selectedExternalLocation = useMemo5(() => {
|
|
3917
4307
|
const location = findWorkspaceFileLocationById(
|
|
3918
4308
|
rootView.locationSections,
|
|
3919
4309
|
rootView.selectedLocationId
|
|
@@ -3926,7 +4316,7 @@ function WorkspaceFileManager({
|
|
|
3926
4316
|
containerWidth,
|
|
3927
4317
|
sidebarContentMinWidth
|
|
3928
4318
|
) : workspaceFileManagerSidebarDefaultWidth;
|
|
3929
|
-
const updateSidebarWidth =
|
|
4319
|
+
const updateSidebarWidth = useCallback7(
|
|
3930
4320
|
(width) => {
|
|
3931
4321
|
const nextWidth = clampWorkspaceFileManagerSidebarWidth({
|
|
3932
4322
|
containerWidth: rootRef.current?.getBoundingClientRect().width ?? 0,
|
|
@@ -3969,7 +4359,7 @@ function WorkspaceFileManager({
|
|
|
3969
4359
|
observer.disconnect();
|
|
3970
4360
|
};
|
|
3971
4361
|
}, [hasLocationSidebar, sidebarContentMinWidth]);
|
|
3972
|
-
const handleSidebarResizePointerDown =
|
|
4362
|
+
const handleSidebarResizePointerDown = useCallback7(
|
|
3973
4363
|
(event) => {
|
|
3974
4364
|
if (event.button !== 0) {
|
|
3975
4365
|
return;
|
|
@@ -3998,7 +4388,7 @@ function WorkspaceFileManager({
|
|
|
3998
4388
|
},
|
|
3999
4389
|
[sidebarWidth]
|
|
4000
4390
|
);
|
|
4001
|
-
const handleSidebarResizePointerMove =
|
|
4391
|
+
const handleSidebarResizePointerMove = useCallback7(
|
|
4002
4392
|
(event) => {
|
|
4003
4393
|
const resize = sidebarResizeRef.current;
|
|
4004
4394
|
if (!resize || resize.pointerId !== event.pointerId) {
|
|
@@ -4010,7 +4400,7 @@ function WorkspaceFileManager({
|
|
|
4010
4400
|
},
|
|
4011
4401
|
[updateSidebarWidth]
|
|
4012
4402
|
);
|
|
4013
|
-
const handleSidebarResizePointerEnd =
|
|
4403
|
+
const handleSidebarResizePointerEnd = useCallback7(
|
|
4014
4404
|
(event) => {
|
|
4015
4405
|
const resize = sidebarResizeRef.current;
|
|
4016
4406
|
if (!resize || resize.pointerId !== event.pointerId) {
|
|
@@ -4022,7 +4412,7 @@ function WorkspaceFileManager({
|
|
|
4022
4412
|
},
|
|
4023
4413
|
[]
|
|
4024
4414
|
);
|
|
4025
|
-
const handleSidebarResizeKeyDown =
|
|
4415
|
+
const handleSidebarResizeKeyDown = useCallback7(
|
|
4026
4416
|
(event) => {
|
|
4027
4417
|
let nextWidth = null;
|
|
4028
4418
|
if (event.key === "Home") {
|
|
@@ -4066,8 +4456,9 @@ function WorkspaceFileManager({
|
|
|
4066
4456
|
}
|
|
4067
4457
|
event.preventDefault();
|
|
4068
4458
|
void (async () => {
|
|
4069
|
-
await session.copyToClipboard(entry)
|
|
4070
|
-
|
|
4459
|
+
if (await session.copyToClipboard(entry)) {
|
|
4460
|
+
await onCopyEntry?.();
|
|
4461
|
+
}
|
|
4071
4462
|
})();
|
|
4072
4463
|
}
|
|
4073
4464
|
window.addEventListener("keydown", handleCopyShortcut);
|
|
@@ -4115,31 +4506,34 @@ function WorkspaceFileManager({
|
|
|
4115
4506
|
selectedExternalLocation,
|
|
4116
4507
|
session
|
|
4117
4508
|
]);
|
|
4118
|
-
|
|
4119
|
-
event
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4509
|
+
const openContextMenu = useCallback7(
|
|
4510
|
+
(event, entry) => {
|
|
4511
|
+
event.preventDefault();
|
|
4512
|
+
event.stopPropagation();
|
|
4513
|
+
const menuWidth = 220;
|
|
4514
|
+
const menuHeight = 280;
|
|
4515
|
+
const x = clampContextMenuCoordinate(
|
|
4516
|
+
event.clientX,
|
|
4517
|
+
window.innerWidth,
|
|
4518
|
+
menuWidth
|
|
4519
|
+
);
|
|
4520
|
+
const y = clampContextMenuCoordinate(
|
|
4521
|
+
event.clientY,
|
|
4522
|
+
window.innerHeight,
|
|
4523
|
+
menuHeight
|
|
4524
|
+
);
|
|
4525
|
+
session.openContextMenu({
|
|
4526
|
+
entryPath: entry?.path ?? null,
|
|
4527
|
+
x,
|
|
4528
|
+
y
|
|
4529
|
+
});
|
|
4530
|
+
},
|
|
4531
|
+
[session]
|
|
4532
|
+
);
|
|
4139
4533
|
return /* @__PURE__ */ jsxs8(
|
|
4140
4534
|
"section",
|
|
4141
4535
|
{
|
|
4142
|
-
className:
|
|
4536
|
+
className: cn8(
|
|
4143
4537
|
"@container/workspace-file-manager relative flex h-full min-h-0 w-full overflow-hidden text-[14px] text-[var(--text-primary)]",
|
|
4144
4538
|
surface === "card" ? "rounded-lg border border-[var(--border-1)] bg-[var(--background-panel)]" : "rounded-none border-0 bg-transparent",
|
|
4145
4539
|
className
|
|
@@ -4154,7 +4548,7 @@ function WorkspaceFileManager({
|
|
|
4154
4548
|
"--workspace-file-manager-dialog-overlay-z-index": "20"
|
|
4155
4549
|
},
|
|
4156
4550
|
children: [
|
|
4157
|
-
hasLocationSidebar ? /* @__PURE__ */
|
|
4551
|
+
hasLocationSidebar ? /* @__PURE__ */ jsx12(
|
|
4158
4552
|
WorkspaceFileManagerSidebar,
|
|
4159
4553
|
{
|
|
4160
4554
|
disabled: rootView.isBusy || panelsState.isLoading,
|
|
@@ -4169,7 +4563,7 @@ function WorkspaceFileManager({
|
|
|
4169
4563
|
}
|
|
4170
4564
|
}
|
|
4171
4565
|
) : null,
|
|
4172
|
-
hasLocationSidebar ? /* @__PURE__ */
|
|
4566
|
+
hasLocationSidebar ? /* @__PURE__ */ jsx12(
|
|
4173
4567
|
"div",
|
|
4174
4568
|
{
|
|
4175
4569
|
"aria-label": i18n.t("resizeLocationsSidebar"),
|
|
@@ -4187,8 +4581,8 @@ function WorkspaceFileManager({
|
|
|
4187
4581
|
onPointerUp: handleSidebarResizePointerEnd
|
|
4188
4582
|
}
|
|
4189
4583
|
) : null,
|
|
4190
|
-
/* @__PURE__ */
|
|
4191
|
-
/* @__PURE__ */
|
|
4584
|
+
/* @__PURE__ */ jsx12("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: selectedExternalLocation ? renderExternalLocationContent?.(selectedExternalLocation) ?? null : /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4585
|
+
/* @__PURE__ */ jsx12(
|
|
4192
4586
|
WorkspaceFileManagerToolbarContainer,
|
|
4193
4587
|
{
|
|
4194
4588
|
i18n,
|
|
@@ -4201,7 +4595,7 @@ function WorkspaceFileManager({
|
|
|
4201
4595
|
session
|
|
4202
4596
|
}
|
|
4203
4597
|
),
|
|
4204
|
-
/* @__PURE__ */
|
|
4598
|
+
/* @__PURE__ */ jsx12("div", { className: "@max-[600px]/workspace-file-manager:flex-col @max-[600px]/workspace-file-manager:gap-3 flex min-h-0 min-w-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx12(
|
|
4205
4599
|
WorkspaceFileManagerPanelsContainer,
|
|
4206
4600
|
{
|
|
4207
4601
|
dateLocale,
|
|
@@ -4209,9 +4603,11 @@ function WorkspaceFileManager({
|
|
|
4209
4603
|
arrangeMode,
|
|
4210
4604
|
i18n,
|
|
4211
4605
|
layoutMode,
|
|
4606
|
+
onCopyEntry,
|
|
4212
4607
|
onDirectoryExpanded,
|
|
4213
4608
|
onEntryDragStart,
|
|
4214
4609
|
onOpenContextMenu: openContextMenu,
|
|
4610
|
+
previewActions,
|
|
4215
4611
|
resolveEntryIconUrl,
|
|
4216
4612
|
session,
|
|
4217
4613
|
showPreviewPanel
|
|
@@ -4219,8 +4615,8 @@ function WorkspaceFileManager({
|
|
|
4219
4615
|
) })
|
|
4220
4616
|
] }) }),
|
|
4221
4617
|
!selectedExternalLocation ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4222
|
-
/* @__PURE__ */
|
|
4223
|
-
/* @__PURE__ */
|
|
4618
|
+
/* @__PURE__ */ jsx12(WorkspaceFileManagerDialogsContainer, { i18n, session }),
|
|
4619
|
+
/* @__PURE__ */ jsx12(
|
|
4224
4620
|
WorkspaceFileManagerContextMenuContainer,
|
|
4225
4621
|
{
|
|
4226
4622
|
resolveContextMenu,
|
|
@@ -4245,7 +4641,7 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
4245
4641
|
const { view } = useWorkspaceFileManagerToolbarView(session, i18n);
|
|
4246
4642
|
const [searchQuery, setSearchQuery] = useState8(view.searchQuery);
|
|
4247
4643
|
const submittedSearchQueryRef = useRef7(view.searchQuery);
|
|
4248
|
-
const submitSearchQuery =
|
|
4644
|
+
const submitSearchQuery = useCallback7(
|
|
4249
4645
|
(query) => {
|
|
4250
4646
|
submittedSearchQueryRef.current = query;
|
|
4251
4647
|
void session.search(query);
|
|
@@ -4270,11 +4666,11 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
4270
4666
|
clearTimeout(timer);
|
|
4271
4667
|
};
|
|
4272
4668
|
}, [searchQuery, submitSearchQuery, view.canSearch]);
|
|
4273
|
-
const handleSearchClear =
|
|
4669
|
+
const handleSearchClear = useCallback7(() => {
|
|
4274
4670
|
setSearchQuery("");
|
|
4275
4671
|
submitSearchQuery("");
|
|
4276
4672
|
}, [submitSearchQuery]);
|
|
4277
|
-
return /* @__PURE__ */
|
|
4673
|
+
return /* @__PURE__ */ jsx12(
|
|
4278
4674
|
WorkspaceFileManagerToolbar,
|
|
4279
4675
|
{
|
|
4280
4676
|
breadcrumbs: view.breadcrumbs,
|
|
@@ -4316,146 +4712,13 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
4316
4712
|
}
|
|
4317
4713
|
);
|
|
4318
4714
|
}
|
|
4319
|
-
function WorkspaceFileManagerPanelsContainer({
|
|
4320
|
-
arrangeMode,
|
|
4321
|
-
dateLocale,
|
|
4322
|
-
entryDragMode,
|
|
4323
|
-
i18n,
|
|
4324
|
-
layoutMode,
|
|
4325
|
-
onDirectoryExpanded,
|
|
4326
|
-
onEntryDragStart,
|
|
4327
|
-
onOpenContextMenu,
|
|
4328
|
-
resolveEntryIconUrl,
|
|
4329
|
-
session,
|
|
4330
|
-
showPreviewPanel
|
|
4331
|
-
}) {
|
|
4332
|
-
const { state, view } = useWorkspaceFileManagerPanelsView(session);
|
|
4333
|
-
const arrangedEntries = useMemo3(
|
|
4334
|
-
() => sortWorkspaceFileEntriesForArrangeMode(state.entries, arrangeMode),
|
|
4335
|
-
[arrangeMode, state.entries]
|
|
4336
|
-
);
|
|
4337
|
-
const searchEntries = useMemo3(
|
|
4338
|
-
() => view.searchEntries.map(workspaceFileSearchEntryToEntry),
|
|
4339
|
-
[view.searchEntries]
|
|
4340
|
-
);
|
|
4341
|
-
const searchEntryContextByPath = useMemo3(() => {
|
|
4342
|
-
const contextByPath = /* @__PURE__ */ new Map();
|
|
4343
|
-
for (const entry of view.searchEntries) {
|
|
4344
|
-
contextByPath.set(entry.path, entry.directoryPath);
|
|
4345
|
-
}
|
|
4346
|
-
return contextByPath;
|
|
4347
|
-
}, [view.searchEntries]);
|
|
4348
|
-
const treeRows = useMemo3(
|
|
4349
|
-
() => buildWorkspaceFileManagerVisibleTreeRows({
|
|
4350
|
-
arrangeMode,
|
|
4351
|
-
directoryExpansionByPath: state.directoryExpansionByPath,
|
|
4352
|
-
entries: arrangedEntries,
|
|
4353
|
-
expandedDirectoryPaths: state.expandedDirectoryPaths
|
|
4354
|
-
}),
|
|
4355
|
-
[
|
|
4356
|
-
arrangeMode,
|
|
4357
|
-
arrangedEntries,
|
|
4358
|
-
state.directoryExpansionByPath,
|
|
4359
|
-
state.expandedDirectoryPaths
|
|
4360
|
-
]
|
|
4361
|
-
);
|
|
4362
|
-
const searchTreeRows = useMemo3(
|
|
4363
|
-
() => searchEntries.map((entry) => ({
|
|
4364
|
-
depth: 0,
|
|
4365
|
-
entry,
|
|
4366
|
-
expanded: false,
|
|
4367
|
-
expandable: false,
|
|
4368
|
-
kind: "entry",
|
|
4369
|
-
loadingChildren: false
|
|
4370
|
-
})),
|
|
4371
|
-
[searchEntries]
|
|
4372
|
-
);
|
|
4373
|
-
const displayedEntries = view.isSearchMode ? searchEntries : arrangedEntries;
|
|
4374
|
-
const displayedTreeRows = view.isSearchMode ? searchTreeRows : treeRows;
|
|
4375
|
-
const visibleTreeEntries = useMemo3(
|
|
4376
|
-
() => collectWorkspaceFileManagerVisibleTreeEntries(displayedTreeRows),
|
|
4377
|
-
[displayedTreeRows]
|
|
4378
|
-
);
|
|
4379
|
-
const {
|
|
4380
|
-
iconUrlByCacheKey,
|
|
4381
|
-
reportEntryIconViewportEnter,
|
|
4382
|
-
reportEntryIconViewportLeave
|
|
4383
|
-
} = useWorkspaceFileEntryIconUrls({
|
|
4384
|
-
entries: layoutMode === "list" ? visibleTreeEntries : displayedEntries,
|
|
4385
|
-
includeImageThumbnails: true,
|
|
4386
|
-
resolveEntryIconUrl
|
|
4387
|
-
});
|
|
4388
|
-
return /* @__PURE__ */ jsx9(
|
|
4389
|
-
WorkspaceFileManagerPanels,
|
|
4390
|
-
{
|
|
4391
|
-
arrangeMode,
|
|
4392
|
-
canMove: view.isSearchMode ? false : view.canMove,
|
|
4393
|
-
contextMenuEntryPath: view.contextMenuEntryPath,
|
|
4394
|
-
copy: i18n,
|
|
4395
|
-
dateLocale,
|
|
4396
|
-
entryDragMode,
|
|
4397
|
-
iconUrlByCacheKey,
|
|
4398
|
-
inlineRenameEntryPath: view.inlineRenameEntryPath,
|
|
4399
|
-
inlineRenameValidation: view.inlineRenameValidation,
|
|
4400
|
-
isRenaming: view.isRenaming,
|
|
4401
|
-
layoutMode,
|
|
4402
|
-
pendingDirectoryPath: view.pendingDirectoryPath,
|
|
4403
|
-
previewState: view.previewState,
|
|
4404
|
-
entryContextByPath: view.isSearchMode ? searchEntryContextByPath : null,
|
|
4405
|
-
treeRows: displayedTreeRows,
|
|
4406
|
-
onEntryIconViewportEnter: reportEntryIconViewportEnter,
|
|
4407
|
-
onEntryIconViewportLeave: reportEntryIconViewportLeave,
|
|
4408
|
-
selectedEntry: view.selectedEntry,
|
|
4409
|
-
selectedPath: view.selectedPath,
|
|
4410
|
-
showPreviewPanel,
|
|
4411
|
-
state: {
|
|
4412
|
-
entries: displayedEntries,
|
|
4413
|
-
error: view.isSearchMode ? view.searchError : state.error,
|
|
4414
|
-
isLoading: view.isSearchMode ? view.isSearching : state.isLoading,
|
|
4415
|
-
isSearchMode: view.isSearchMode
|
|
4416
|
-
},
|
|
4417
|
-
onBlankContextMenu: (event) => {
|
|
4418
|
-
onOpenContextMenu(event, null);
|
|
4419
|
-
},
|
|
4420
|
-
onCancelInlineRename: () => {
|
|
4421
|
-
session.cancelInlineRename();
|
|
4422
|
-
},
|
|
4423
|
-
onClearInlineRenameValidation: () => {
|
|
4424
|
-
session.clearInlineRenameValidation();
|
|
4425
|
-
},
|
|
4426
|
-
onConfirmInlineRename: (newName) => {
|
|
4427
|
-
return session.confirmInlineRename(newName);
|
|
4428
|
-
},
|
|
4429
|
-
onEntryContextMenu: onOpenContextMenu,
|
|
4430
|
-
onEntryDragStart,
|
|
4431
|
-
onMoveEntry: (entry, targetDirectoryPath) => {
|
|
4432
|
-
void session.moveEntry(entry, targetDirectoryPath);
|
|
4433
|
-
},
|
|
4434
|
-
onOpenEntry: (entry) => {
|
|
4435
|
-
if (entry.kind === "directory") {
|
|
4436
|
-
onDirectoryExpanded?.(entry.path);
|
|
4437
|
-
}
|
|
4438
|
-
void session.openEntry(entry);
|
|
4439
|
-
},
|
|
4440
|
-
onSelect: (path) => {
|
|
4441
|
-
session.select(path);
|
|
4442
|
-
},
|
|
4443
|
-
onToggleDirectoryExpanded: (entry, expanded) => {
|
|
4444
|
-
if (!expanded) {
|
|
4445
|
-
onDirectoryExpanded?.(entry.path);
|
|
4446
|
-
}
|
|
4447
|
-
void session.toggleDirectoryExpanded(entry);
|
|
4448
|
-
}
|
|
4449
|
-
}
|
|
4450
|
-
);
|
|
4451
|
-
}
|
|
4452
4715
|
function WorkspaceFileManagerDialogsContainer({
|
|
4453
4716
|
i18n,
|
|
4454
4717
|
session
|
|
4455
4718
|
}) {
|
|
4456
4719
|
const { state, view } = useWorkspaceFileManagerDialogsView(session);
|
|
4457
4720
|
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4458
|
-
/* @__PURE__ */
|
|
4721
|
+
/* @__PURE__ */ jsx12(
|
|
4459
4722
|
WorkspaceFileManagerCreateDialog,
|
|
4460
4723
|
{
|
|
4461
4724
|
busy: view.isBusy && state.busyAction === "create",
|
|
@@ -4472,7 +4735,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
4472
4735
|
}
|
|
4473
4736
|
}
|
|
4474
4737
|
),
|
|
4475
|
-
/* @__PURE__ */
|
|
4738
|
+
/* @__PURE__ */ jsx12(
|
|
4476
4739
|
WorkspaceFileManagerDeleteDialog,
|
|
4477
4740
|
{
|
|
4478
4741
|
busy: view.isDeleting,
|
|
@@ -4486,7 +4749,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
4486
4749
|
}
|
|
4487
4750
|
}
|
|
4488
4751
|
),
|
|
4489
|
-
/* @__PURE__ */
|
|
4752
|
+
/* @__PURE__ */ jsx12(
|
|
4490
4753
|
WorkspaceFileManagerUnsupportedDialog,
|
|
4491
4754
|
{
|
|
4492
4755
|
copy: i18n,
|