@tutti-os/workspace-file-manager 0.0.11 → 0.0.13
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/assets/workspace-archive-fallback.png +0 -0
- package/dist/assets/workspace-folder-fallback.png +0 -0
- package/dist/assets/workspace-image-fallback.png +0 -0
- package/dist/{chunk-DXLDUMVG.js → chunk-G2T6CZ2T.js} +26 -11
- package/dist/{chunk-DXLDUMVG.js.map → chunk-G2T6CZ2T.js.map} +1 -1
- package/dist/{chunk-XOFPTWRV.js → chunk-MDBT2GS5.js} +7 -5
- package/dist/chunk-MDBT2GS5.js.map +1 -0
- package/dist/{fileKinds-Djl-phx5.d.ts → fileKinds-DxnVJkSm.d.ts} +1 -1
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/{index-6Z1LmfOL.d.ts → index-BMBoznj4.d.ts} +2 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +199 -87
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +9 -5
- package/dist/services/index.js +4 -2
- package/package.json +5 -5
- package/dist/chunk-XOFPTWRV.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -16,17 +16,18 @@ import {
|
|
|
16
16
|
resolveWorkspaceFileVisualKind,
|
|
17
17
|
resolveWorkspaceImageMimeType,
|
|
18
18
|
shouldResolveWorkspaceFileEntryIcon,
|
|
19
|
+
shouldUseWorkspaceFileArchiveIcon,
|
|
19
20
|
shouldUseWorkspaceFileExtensionDocumentIcon,
|
|
20
21
|
splitWorkspaceFileName,
|
|
21
22
|
workspaceFilePreviewMaxBytes,
|
|
22
23
|
workspaceFileTextMaxBytes
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-G2T6CZ2T.js";
|
|
24
25
|
import {
|
|
25
26
|
createWorkspaceFileManagerI18nRuntime,
|
|
26
27
|
resolveRevealInFolderLabel,
|
|
27
28
|
workspaceFileManagerI18nNamespace,
|
|
28
29
|
workspaceFileManagerI18nResources
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MDBT2GS5.js";
|
|
30
31
|
|
|
31
32
|
// src/ui/WorkspaceFileManager.tsx
|
|
32
33
|
import { useEffect as useEffect5, useMemo as useMemo2, useRef as useRef5, useState as useState7 } from "react";
|
|
@@ -900,8 +901,6 @@ function importSummaryReasonCopyKey(reason) {
|
|
|
900
901
|
import {
|
|
901
902
|
FileCodeIcon as FileCodeIcon2,
|
|
902
903
|
FileTextIcon as FileTextIcon2,
|
|
903
|
-
FolderFilledIcon as FolderFilledIcon2,
|
|
904
|
-
ImageFileIcon as ImageFileIcon2,
|
|
905
904
|
LoadingIcon as LoadingIcon2,
|
|
906
905
|
ScrollArea,
|
|
907
906
|
VideoFileIcon as VideoFileIcon2,
|
|
@@ -924,20 +923,31 @@ import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
|
|
|
924
923
|
import {
|
|
925
924
|
FileCodeIcon,
|
|
926
925
|
FileTextIcon,
|
|
927
|
-
FolderFilledIcon,
|
|
928
|
-
ImageFileIcon,
|
|
929
926
|
LoadingIcon,
|
|
930
927
|
VideoFileIcon,
|
|
931
928
|
cn as cn2
|
|
932
929
|
} from "@tutti-os/ui-system";
|
|
933
930
|
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
934
931
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
932
|
+
var workspaceArchiveFallbackIconUrl = new URL(
|
|
933
|
+
"../assets/workspace-archive-fallback.png",
|
|
934
|
+
import.meta.url
|
|
935
|
+
).toString();
|
|
936
|
+
var workspaceFolderFallbackIconUrl = new URL(
|
|
937
|
+
"../assets/workspace-folder-fallback.png",
|
|
938
|
+
import.meta.url
|
|
939
|
+
).toString();
|
|
940
|
+
var workspaceImageFallbackIconUrl = new URL(
|
|
941
|
+
"../assets/workspace-image-fallback.png",
|
|
942
|
+
import.meta.url
|
|
943
|
+
).toString();
|
|
935
944
|
function WorkspaceFileEntryIcon({
|
|
936
945
|
entry,
|
|
937
946
|
frameClassName,
|
|
938
947
|
iconClassName = "size-4",
|
|
939
948
|
iconUrlByCacheKey,
|
|
940
949
|
isEnteringDirectory = false,
|
|
950
|
+
loadingIconClassName,
|
|
941
951
|
onViewportLeave,
|
|
942
952
|
onViewportEnter
|
|
943
953
|
}) {
|
|
@@ -981,9 +991,10 @@ function WorkspaceFileEntryIcon({
|
|
|
981
991
|
const viewportRoot = resolveWorkspaceFileEntryIconViewport(element);
|
|
982
992
|
const observer = new IntersectionObserver(
|
|
983
993
|
(records) => {
|
|
984
|
-
|
|
994
|
+
const intersecting = records.some(
|
|
985
995
|
(record) => record.isIntersecting && record.intersectionRatio > 0
|
|
986
|
-
)
|
|
996
|
+
);
|
|
997
|
+
if (intersecting) {
|
|
987
998
|
reportViewportEnter();
|
|
988
999
|
return;
|
|
989
1000
|
}
|
|
@@ -992,7 +1003,11 @@ function WorkspaceFileEntryIcon({
|
|
|
992
1003
|
{ root: viewportRoot, rootMargin: "0px", threshold: 0 }
|
|
993
1004
|
);
|
|
994
1005
|
observer.observe(element);
|
|
995
|
-
|
|
1006
|
+
const initiallyVisible = isWorkspaceFileEntryIconVisible(
|
|
1007
|
+
element,
|
|
1008
|
+
viewportRoot
|
|
1009
|
+
);
|
|
1010
|
+
if (initiallyVisible) {
|
|
996
1011
|
reportViewportEnter();
|
|
997
1012
|
} else {
|
|
998
1013
|
reportViewportLeave();
|
|
@@ -1011,12 +1026,22 @@ function WorkspaceFileEntryIcon({
|
|
|
1011
1026
|
frameClassName,
|
|
1012
1027
|
isEnteringDirectory ? "text-[var(--text-tertiary)]" : entryIconColorClassName(visualKind, isAppBundle)
|
|
1013
1028
|
),
|
|
1014
|
-
children: isEnteringDirectory ? /* @__PURE__ */ jsx2(
|
|
1029
|
+
children: isEnteringDirectory ? /* @__PURE__ */ jsx2(
|
|
1030
|
+
LoadingIcon,
|
|
1031
|
+
{
|
|
1032
|
+
className: cn2(loadingIconClassName ?? iconClassName, "animate-spin")
|
|
1033
|
+
}
|
|
1034
|
+
) : iconUrl ? /* @__PURE__ */ jsx2(
|
|
1015
1035
|
"img",
|
|
1016
1036
|
{
|
|
1017
1037
|
alt: "",
|
|
1018
|
-
className: cn2(
|
|
1038
|
+
className: cn2(
|
|
1039
|
+
iconClassName,
|
|
1040
|
+
visualKind === "image" ? "rounded-[6px] border border-[var(--border-1)] bg-[var(--transparency-block)] object-contain" : "rounded-[4px] object-contain"
|
|
1041
|
+
),
|
|
1042
|
+
decoding: "async",
|
|
1019
1043
|
draggable: false,
|
|
1044
|
+
loading: "lazy",
|
|
1020
1045
|
src: iconUrl
|
|
1021
1046
|
}
|
|
1022
1047
|
) : /* @__PURE__ */ jsx2(
|
|
@@ -1048,44 +1073,102 @@ function DefaultEntryIcon({
|
|
|
1048
1073
|
iconClassName,
|
|
1049
1074
|
visualKind
|
|
1050
1075
|
}) {
|
|
1076
|
+
const vectorIconClassName = vectorFallbackIconClassName(iconClassName);
|
|
1051
1077
|
if (isWorkspaceApplicationBundle(entry)) {
|
|
1052
|
-
return /* @__PURE__ */ jsx2(FileTextIcon, { className:
|
|
1078
|
+
return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
|
|
1079
|
+
}
|
|
1080
|
+
if (shouldUseWorkspaceFileArchiveIcon(entry)) {
|
|
1081
|
+
return /* @__PURE__ */ jsx2(WorkspaceArchiveFallbackIcon, { className: iconClassName });
|
|
1053
1082
|
}
|
|
1054
1083
|
if (shouldUseWorkspaceFileExtensionDocumentIcon(entry)) {
|
|
1055
|
-
return /* @__PURE__ */ jsx2(
|
|
1084
|
+
return /* @__PURE__ */ jsx2(
|
|
1085
|
+
ExtensionDocumentIcon,
|
|
1086
|
+
{
|
|
1087
|
+
entry,
|
|
1088
|
+
iconClassName: vectorIconClassName
|
|
1089
|
+
}
|
|
1090
|
+
);
|
|
1056
1091
|
}
|
|
1057
1092
|
switch (visualKind) {
|
|
1058
1093
|
case "directory":
|
|
1059
|
-
return /* @__PURE__ */ jsx2(
|
|
1094
|
+
return /* @__PURE__ */ jsx2(WorkspaceFolderFallbackIcon, { className: iconClassName });
|
|
1060
1095
|
case "image":
|
|
1061
|
-
return /* @__PURE__ */ jsx2(
|
|
1096
|
+
return /* @__PURE__ */ jsx2(WorkspaceImageFallbackIcon, { className: iconClassName });
|
|
1062
1097
|
case "video":
|
|
1063
|
-
return /* @__PURE__ */ jsx2(VideoFileIcon, { className:
|
|
1098
|
+
return /* @__PURE__ */ jsx2(VideoFileIcon, { className: vectorIconClassName });
|
|
1064
1099
|
case "markdown":
|
|
1065
1100
|
case "document":
|
|
1066
|
-
return /* @__PURE__ */ jsx2(FileTextIcon, { className:
|
|
1101
|
+
return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
|
|
1067
1102
|
case "code":
|
|
1068
|
-
return /* @__PURE__ */ jsx2(FileCodeIcon, { className:
|
|
1103
|
+
return /* @__PURE__ */ jsx2(FileCodeIcon, { className: vectorIconClassName });
|
|
1069
1104
|
case "binary":
|
|
1070
|
-
return /* @__PURE__ */ jsx2(FileTextIcon, { className:
|
|
1105
|
+
return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
|
|
1071
1106
|
default:
|
|
1072
|
-
return /* @__PURE__ */ jsx2(FileTextIcon, { className:
|
|
1107
|
+
return /* @__PURE__ */ jsx2(FileTextIcon, { className: vectorIconClassName });
|
|
1073
1108
|
}
|
|
1074
1109
|
}
|
|
1110
|
+
function vectorFallbackIconClassName(iconClassName) {
|
|
1111
|
+
return iconClassName.includes("size-[84px]") ? "size-[64px]" : iconClassName;
|
|
1112
|
+
}
|
|
1113
|
+
function WorkspaceFolderFallbackIcon({
|
|
1114
|
+
className
|
|
1115
|
+
}) {
|
|
1116
|
+
return /* @__PURE__ */ jsx2(
|
|
1117
|
+
"img",
|
|
1118
|
+
{
|
|
1119
|
+
alt: "",
|
|
1120
|
+
"aria-hidden": "true",
|
|
1121
|
+
className: cn2("object-contain", className),
|
|
1122
|
+
decoding: "async",
|
|
1123
|
+
draggable: false,
|
|
1124
|
+
src: workspaceFolderFallbackIconUrl
|
|
1125
|
+
}
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
function WorkspaceArchiveFallbackIcon({
|
|
1129
|
+
className
|
|
1130
|
+
}) {
|
|
1131
|
+
return /* @__PURE__ */ jsx2(
|
|
1132
|
+
"img",
|
|
1133
|
+
{
|
|
1134
|
+
alt: "",
|
|
1135
|
+
"aria-hidden": "true",
|
|
1136
|
+
className: cn2("object-contain", className),
|
|
1137
|
+
decoding: "async",
|
|
1138
|
+
draggable: false,
|
|
1139
|
+
src: workspaceArchiveFallbackIconUrl
|
|
1140
|
+
}
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
function WorkspaceImageFallbackIcon({
|
|
1144
|
+
className
|
|
1145
|
+
}) {
|
|
1146
|
+
return /* @__PURE__ */ jsx2(
|
|
1147
|
+
"img",
|
|
1148
|
+
{
|
|
1149
|
+
alt: "",
|
|
1150
|
+
"aria-hidden": "true",
|
|
1151
|
+
className: cn2("object-contain", className),
|
|
1152
|
+
decoding: "async",
|
|
1153
|
+
draggable: false,
|
|
1154
|
+
src: workspaceImageFallbackIconUrl
|
|
1155
|
+
}
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1075
1158
|
function ExtensionDocumentIcon({
|
|
1076
1159
|
entry,
|
|
1077
1160
|
iconClassName
|
|
1078
1161
|
}) {
|
|
1079
1162
|
const extension = resolveWorkspaceFileExtension(entry.name).slice(0, 5).toUpperCase();
|
|
1080
|
-
const showExtension = extension.length > 0 && iconClassName.includes("
|
|
1163
|
+
const showExtension = extension.length > 0 && !iconClassName.includes("size-4");
|
|
1081
1164
|
return /* @__PURE__ */ jsxs2(
|
|
1082
1165
|
"span",
|
|
1083
1166
|
{
|
|
1084
1167
|
"aria-hidden": "true",
|
|
1085
1168
|
className: cn2("relative inline-block overflow-visible", iconClassName),
|
|
1086
1169
|
children: [
|
|
1087
|
-
/* @__PURE__ */ jsx2("span", { className: "absolute inset-[5%] rounded-[6px] border border-black/10 bg-linear-to-br from-white via-[#f8f8f8] to-[#ececec]
|
|
1088
|
-
/* @__PURE__ */ jsx2("span", { className: "absolute top-[5%] right-[5%] h-[28%] w-[28%] overflow-hidden rounded-tr-[6px]", children: /* @__PURE__ */ jsx2("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]
|
|
1170
|
+
/* @__PURE__ */ jsx2("span", { className: "absolute inset-[5%] rounded-[6px] border border-black/10 bg-linear-to-br from-white via-[#f8f8f8] to-[#ececec]" }),
|
|
1171
|
+
/* @__PURE__ */ jsx2("span", { className: "absolute top-[5%] right-[5%] h-[28%] w-[28%] overflow-hidden rounded-tr-[6px]", children: /* @__PURE__ */ jsx2("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]" }) }),
|
|
1089
1172
|
showExtension ? /* @__PURE__ */ jsx2("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
|
|
1090
1173
|
]
|
|
1091
1174
|
}
|
|
@@ -1099,19 +1182,19 @@ function entryIconColorClassName(visualKind, isAppBundle) {
|
|
|
1099
1182
|
}
|
|
1100
1183
|
|
|
1101
1184
|
// src/ui/workspaceFileManagerIconGridLayout.ts
|
|
1102
|
-
var workspaceFileManagerIconGridIconSizePx =
|
|
1103
|
-
var workspaceFileManagerIconGridTileMinWidthPx =
|
|
1104
|
-
var workspaceFileManagerIconGridTileMaxWidthPx =
|
|
1185
|
+
var workspaceFileManagerIconGridIconSizePx = 84;
|
|
1186
|
+
var workspaceFileManagerIconGridTileMinWidthPx = 136;
|
|
1187
|
+
var workspaceFileManagerIconGridTileMaxWidthPx = 148;
|
|
1105
1188
|
var workspaceFileManagerIconGridLayout = {
|
|
1106
1189
|
iconSizePx: workspaceFileManagerIconGridIconSizePx,
|
|
1107
1190
|
tileMaxWidthPx: workspaceFileManagerIconGridTileMaxWidthPx,
|
|
1108
1191
|
tileMinWidthPx: workspaceFileManagerIconGridTileMinWidthPx
|
|
1109
1192
|
};
|
|
1110
1193
|
function workspaceFileManagerIconGridIconClassName() {
|
|
1111
|
-
return "size-[
|
|
1194
|
+
return "size-[84px]";
|
|
1112
1195
|
}
|
|
1113
1196
|
function workspaceFileManagerIconGridFrameClassName() {
|
|
1114
|
-
return "size-[
|
|
1197
|
+
return "size-[92px]";
|
|
1115
1198
|
}
|
|
1116
1199
|
|
|
1117
1200
|
// src/ui/WorkspaceFileManagerIconGrid.tsx
|
|
@@ -1214,7 +1297,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1214
1297
|
});
|
|
1215
1298
|
}, [selected]);
|
|
1216
1299
|
const tileClassName = cn3(
|
|
1217
|
-
"flex min-w-0 max-w-[
|
|
1300
|
+
"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",
|
|
1218
1301
|
isInlineRenaming ? "cursor-default" : "cursor-pointer hover:bg-transparency-block",
|
|
1219
1302
|
moveDragActive && "cursor-grabbing",
|
|
1220
1303
|
selected || contextMenuActive || isInlineRenaming ? "border-[var(--border-focus)] bg-transparency-block text-[var(--text-primary)]" : "text-[var(--text-secondary)]",
|
|
@@ -1229,6 +1312,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1229
1312
|
iconClassName: workspaceFileManagerIconGridIconClassName(),
|
|
1230
1313
|
iconUrlByCacheKey,
|
|
1231
1314
|
isEnteringDirectory,
|
|
1315
|
+
loadingIconClassName: "size-7",
|
|
1232
1316
|
onViewportLeave: onEntryIconViewportLeave,
|
|
1233
1317
|
onViewportEnter: onEntryIconViewportEnter
|
|
1234
1318
|
}
|
|
@@ -1325,7 +1409,7 @@ function IconTileRenameInput({
|
|
|
1325
1409
|
"aria-invalid": inlineRenameValidation !== null,
|
|
1326
1410
|
"aria-label": copy.t("renameLabel"),
|
|
1327
1411
|
className: cn3(
|
|
1328
|
-
"w-full min-w-0 rounded-
|
|
1412
|
+
"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",
|
|
1329
1413
|
inlineRenameValidation !== null && "border-[var(--state-danger)]"
|
|
1330
1414
|
),
|
|
1331
1415
|
defaultValue: entry.name,
|
|
@@ -1365,8 +1449,7 @@ var workspaceFileManagerArrangeModes = /* @__PURE__ */ new Set([
|
|
|
1365
1449
|
"dateAdded",
|
|
1366
1450
|
"modified",
|
|
1367
1451
|
"created",
|
|
1368
|
-
"size"
|
|
1369
|
-
"tags"
|
|
1452
|
+
"size"
|
|
1370
1453
|
]);
|
|
1371
1454
|
function readWorkspaceFileManagerArrangeMode() {
|
|
1372
1455
|
if (typeof window === "undefined") {
|
|
@@ -1414,8 +1497,6 @@ function sortWorkspaceFileEntriesForArrangeMode(entries, arrangeMode) {
|
|
|
1414
1497
|
return compareDateDescending(left, right, "created") || compareEntryName(left, right);
|
|
1415
1498
|
case "size":
|
|
1416
1499
|
return compareSizeDescending(left, right) || compareEntryName(left, right);
|
|
1417
|
-
case "tags":
|
|
1418
|
-
return compareDirectoryFirst(left, right) || compareEntryName(left, right);
|
|
1419
1500
|
}
|
|
1420
1501
|
});
|
|
1421
1502
|
}
|
|
@@ -2198,8 +2279,8 @@ function MoveDragPreview({
|
|
|
2198
2279
|
WorkspaceFileEntryIcon,
|
|
2199
2280
|
{
|
|
2200
2281
|
entry: preview.entry,
|
|
2201
|
-
frameClassName: "size-
|
|
2202
|
-
iconClassName: "size-
|
|
2282
|
+
frameClassName: "size-7",
|
|
2283
|
+
iconClassName: "size-6",
|
|
2203
2284
|
iconUrlByCacheKey,
|
|
2204
2285
|
onViewportLeave: onEntryIconViewportLeave,
|
|
2205
2286
|
onViewportEnter: onEntryIconViewportEnter
|
|
@@ -2299,8 +2380,8 @@ function EntryNameCell({
|
|
|
2299
2380
|
WorkspaceFileEntryIcon,
|
|
2300
2381
|
{
|
|
2301
2382
|
entry,
|
|
2302
|
-
frameClassName: "size-
|
|
2303
|
-
iconClassName: "size-
|
|
2383
|
+
frameClassName: "size-7",
|
|
2384
|
+
iconClassName: "size-6",
|
|
2304
2385
|
iconUrlByCacheKey,
|
|
2305
2386
|
onViewportLeave: onEntryIconViewportLeave,
|
|
2306
2387
|
onViewportEnter: onEntryIconViewportEnter
|
|
@@ -2363,8 +2444,8 @@ function EntryNameCell({
|
|
|
2363
2444
|
WorkspaceFileEntryIcon,
|
|
2364
2445
|
{
|
|
2365
2446
|
entry,
|
|
2366
|
-
frameClassName: "size-
|
|
2367
|
-
iconClassName: "size-
|
|
2447
|
+
frameClassName: "size-7",
|
|
2448
|
+
iconClassName: "size-6",
|
|
2368
2449
|
iconUrlByCacheKey,
|
|
2369
2450
|
isEnteringDirectory,
|
|
2370
2451
|
onViewportLeave: onEntryIconViewportLeave,
|
|
@@ -2383,9 +2464,9 @@ function EntryIcon({
|
|
|
2383
2464
|
}) {
|
|
2384
2465
|
switch (visualKind) {
|
|
2385
2466
|
case "directory":
|
|
2386
|
-
return /* @__PURE__ */ jsx4(
|
|
2467
|
+
return /* @__PURE__ */ jsx4(WorkspaceFolderFallbackIcon, { className });
|
|
2387
2468
|
case "image":
|
|
2388
|
-
return /* @__PURE__ */ jsx4(
|
|
2469
|
+
return /* @__PURE__ */ jsx4(WorkspaceImageFallbackIcon, { className });
|
|
2389
2470
|
case "video":
|
|
2390
2471
|
return /* @__PURE__ */ jsx4(VideoFileIcon2, { className });
|
|
2391
2472
|
case "markdown":
|
|
@@ -2504,6 +2585,10 @@ import {
|
|
|
2504
2585
|
DropdownMenuTrigger,
|
|
2505
2586
|
LoadingIcon as LoadingIcon3,
|
|
2506
2587
|
RefreshIcon,
|
|
2588
|
+
Tooltip,
|
|
2589
|
+
TooltipContent,
|
|
2590
|
+
TooltipProvider,
|
|
2591
|
+
TooltipTrigger,
|
|
2507
2592
|
ViewGridLinedIcon,
|
|
2508
2593
|
ViewListLinedIcon,
|
|
2509
2594
|
cn as cn5
|
|
@@ -2624,10 +2709,9 @@ function LayoutModeToggle({
|
|
|
2624
2709
|
{ label: copy.t("arrangeDateAddedLabel"), mode: "dateAdded" },
|
|
2625
2710
|
{ label: copy.t("modifiedLabel"), mode: "modified" },
|
|
2626
2711
|
{ label: copy.t("arrangeCreatedLabel"), mode: "created" },
|
|
2627
|
-
{ label: copy.t("sizeLabel"), mode: "size" }
|
|
2628
|
-
{ label: copy.t("arrangeTagsLabel"), mode: "tags" }
|
|
2712
|
+
{ label: copy.t("sizeLabel"), mode: "size" }
|
|
2629
2713
|
];
|
|
2630
|
-
return /* @__PURE__ */ jsxs5(
|
|
2714
|
+
return /* @__PURE__ */ jsx5(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs5(
|
|
2631
2715
|
"div",
|
|
2632
2716
|
{
|
|
2633
2717
|
className: "flex items-center rounded-md border border-[var(--border-1)] bg-[var(--transparency-block)] p-0.5",
|
|
@@ -2638,6 +2722,7 @@ function LayoutModeToggle({
|
|
|
2638
2722
|
{
|
|
2639
2723
|
active: layoutMode === "icon",
|
|
2640
2724
|
ariaLabel: copy.t("layoutIconViewLabel"),
|
|
2725
|
+
tooltipLabel: copy.t("layoutIconViewTooltipLabel"),
|
|
2641
2726
|
onClick: () => {
|
|
2642
2727
|
onLayoutModeChange("icon");
|
|
2643
2728
|
},
|
|
@@ -2649,6 +2734,7 @@ function LayoutModeToggle({
|
|
|
2649
2734
|
{
|
|
2650
2735
|
active: layoutMode === "list",
|
|
2651
2736
|
ariaLabel: copy.t("layoutListViewLabel"),
|
|
2737
|
+
tooltipLabel: copy.t("layoutListViewTooltipLabel"),
|
|
2652
2738
|
onClick: () => {
|
|
2653
2739
|
onLayoutModeChange("list");
|
|
2654
2740
|
},
|
|
@@ -2663,7 +2749,6 @@ function LayoutModeToggle({
|
|
|
2663
2749
|
"aria-label": copy.t("arrangeMenuLabel"),
|
|
2664
2750
|
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",
|
|
2665
2751
|
size: "icon-sm",
|
|
2666
|
-
title: copy.t("arrangeMenuLabel"),
|
|
2667
2752
|
type: "button",
|
|
2668
2753
|
variant: "ghost",
|
|
2669
2754
|
children: /* @__PURE__ */ jsx5(ChevronDownIcon, { className: "size-3.5" })
|
|
@@ -2680,7 +2765,9 @@ function LayoutModeToggle({
|
|
|
2680
2765
|
{
|
|
2681
2766
|
value: arrangeMode,
|
|
2682
2767
|
onValueChange: (nextMode) => {
|
|
2683
|
-
onArrangeModeChange(
|
|
2768
|
+
onArrangeModeChange(
|
|
2769
|
+
nextMode
|
|
2770
|
+
);
|
|
2684
2771
|
},
|
|
2685
2772
|
children: arrangeOptions.map((option, index) => /* @__PURE__ */ jsxs5("div", { children: [
|
|
2686
2773
|
index === 1 ? /* @__PURE__ */ jsx5(DropdownMenuSeparator, {}) : null,
|
|
@@ -2700,31 +2787,34 @@ function LayoutModeToggle({
|
|
|
2700
2787
|
] })
|
|
2701
2788
|
]
|
|
2702
2789
|
}
|
|
2703
|
-
);
|
|
2790
|
+
) });
|
|
2704
2791
|
}
|
|
2705
2792
|
function LayoutModeButton({
|
|
2706
2793
|
active,
|
|
2707
2794
|
ariaLabel,
|
|
2708
2795
|
children,
|
|
2709
|
-
onClick
|
|
2796
|
+
onClick,
|
|
2797
|
+
tooltipLabel
|
|
2710
2798
|
}) {
|
|
2711
|
-
return /* @__PURE__ */
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2799
|
+
return /* @__PURE__ */ jsxs5(Tooltip, { children: [
|
|
2800
|
+
/* @__PURE__ */ jsx5(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx5(
|
|
2801
|
+
Button2,
|
|
2802
|
+
{
|
|
2803
|
+
"aria-label": ariaLabel,
|
|
2804
|
+
"aria-pressed": active,
|
|
2805
|
+
className: cn5(
|
|
2806
|
+
"size-6 min-w-6 rounded-[4px] p-0 text-text-secondary",
|
|
2807
|
+
active && "!bg-background-fronted text-foreground hover:!bg-background-fronted"
|
|
2808
|
+
),
|
|
2809
|
+
size: "icon-sm",
|
|
2810
|
+
type: "button",
|
|
2811
|
+
variant: "ghost",
|
|
2812
|
+
onClick,
|
|
2813
|
+
children
|
|
2814
|
+
}
|
|
2815
|
+
) }),
|
|
2816
|
+
/* @__PURE__ */ jsx5(TooltipContent, { side: "bottom", children: tooltipLabel })
|
|
2817
|
+
] });
|
|
2728
2818
|
}
|
|
2729
2819
|
function ToolbarIconButton({
|
|
2730
2820
|
ariaLabel,
|
|
@@ -2849,6 +2939,10 @@ import { useCallback as useCallback5, useEffect as useEffect4, useMemo, useState
|
|
|
2849
2939
|
|
|
2850
2940
|
// src/ui/workspaceFileEntryIconUrlQueue.ts
|
|
2851
2941
|
var defaultMaxConcurrentIconRequests = 3;
|
|
2942
|
+
var imageThumbnailCacheKeyPrefix = "image-thumbnail:";
|
|
2943
|
+
function shouldKeepResolvedIconAfterViewportLeave(cacheKey) {
|
|
2944
|
+
return cacheKey.startsWith(imageThumbnailCacheKeyPrefix);
|
|
2945
|
+
}
|
|
2852
2946
|
function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
2853
2947
|
const maxConcurrent = Math.max(
|
|
2854
2948
|
1,
|
|
@@ -2862,6 +2956,9 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2862
2956
|
let activeCount = 0;
|
|
2863
2957
|
let disposed = false;
|
|
2864
2958
|
let retainedCacheKeys = null;
|
|
2959
|
+
const policyOptions = {
|
|
2960
|
+
includeImageThumbnails: options.includeImageThumbnails
|
|
2961
|
+
};
|
|
2865
2962
|
function publish() {
|
|
2866
2963
|
for (const listener of listeners) {
|
|
2867
2964
|
listener();
|
|
@@ -2873,6 +2970,9 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2873
2970
|
function isVisible(cacheKey) {
|
|
2874
2971
|
return (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) > 0;
|
|
2875
2972
|
}
|
|
2973
|
+
function shouldResolveCacheKey(cacheKey) {
|
|
2974
|
+
return isVisible(cacheKey) || shouldKeepResolvedIconAfterViewportLeave(cacheKey);
|
|
2975
|
+
}
|
|
2876
2976
|
function retainVisibleReference(cacheKey) {
|
|
2877
2977
|
visibleReferenceCountByCacheKey.set(
|
|
2878
2978
|
cacheKey,
|
|
@@ -2883,15 +2983,17 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2883
2983
|
const nextCount = (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) - 1;
|
|
2884
2984
|
if (nextCount > 0) {
|
|
2885
2985
|
visibleReferenceCountByCacheKey.set(cacheKey, nextCount);
|
|
2886
|
-
return
|
|
2986
|
+
return;
|
|
2887
2987
|
}
|
|
2888
2988
|
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
2989
|
+
if (shouldKeepResolvedIconAfterViewportLeave(cacheKey)) {
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2889
2992
|
queuedEntries.delete(cacheKey);
|
|
2890
2993
|
const hadCachedIcon = iconUrlByCacheKey.delete(cacheKey);
|
|
2891
2994
|
if (hadCachedIcon) {
|
|
2892
2995
|
publish();
|
|
2893
2996
|
}
|
|
2894
|
-
return true;
|
|
2895
2997
|
}
|
|
2896
2998
|
function drain() {
|
|
2897
2999
|
if (disposed || !options.resolveEntryIconUrl) {
|
|
@@ -2904,18 +3006,20 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2904
3006
|
}
|
|
2905
3007
|
const [cacheKey, entry] = next;
|
|
2906
3008
|
queuedEntries.delete(cacheKey);
|
|
2907
|
-
if (!
|
|
3009
|
+
if (!shouldResolveCacheKey(cacheKey) || iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey)) {
|
|
2908
3010
|
continue;
|
|
2909
3011
|
}
|
|
2910
3012
|
activeCount += 1;
|
|
2911
3013
|
inFlightCacheKeys.add(cacheKey);
|
|
2912
3014
|
void options.resolveEntryIconUrl(entry).then((iconUrl) => {
|
|
2913
|
-
|
|
3015
|
+
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3016
|
+
if (shouldStore) {
|
|
2914
3017
|
iconUrlByCacheKey.set(cacheKey, iconUrl?.trim() || null);
|
|
2915
3018
|
publish();
|
|
2916
3019
|
}
|
|
2917
3020
|
}).catch(() => {
|
|
2918
|
-
|
|
3021
|
+
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3022
|
+
if (shouldStore) {
|
|
2919
3023
|
iconUrlByCacheKey.set(cacheKey, null);
|
|
2920
3024
|
publish();
|
|
2921
3025
|
}
|
|
@@ -2927,6 +3031,9 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2927
3031
|
}
|
|
2928
3032
|
}
|
|
2929
3033
|
return {
|
|
3034
|
+
activate() {
|
|
3035
|
+
disposed = false;
|
|
3036
|
+
},
|
|
2930
3037
|
dispose() {
|
|
2931
3038
|
disposed = true;
|
|
2932
3039
|
queuedEntries.clear();
|
|
@@ -2934,13 +3041,14 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2934
3041
|
listeners.clear();
|
|
2935
3042
|
},
|
|
2936
3043
|
leaveViewport(entry) {
|
|
2937
|
-
if (disposed || !shouldResolveWorkspaceFileEntryIcon(entry)) {
|
|
3044
|
+
if (disposed || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
2938
3045
|
return;
|
|
2939
3046
|
}
|
|
2940
|
-
|
|
3047
|
+
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3048
|
+
releaseVisibleReference(cacheKey);
|
|
2941
3049
|
},
|
|
2942
3050
|
enterViewport(entry) {
|
|
2943
|
-
if (disposed || !options.resolveEntryIconUrl || !shouldResolveWorkspaceFileEntryIcon(entry)) {
|
|
3051
|
+
if (disposed || !options.resolveEntryIconUrl || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
2944
3052
|
return;
|
|
2945
3053
|
}
|
|
2946
3054
|
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
@@ -2953,7 +3061,9 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2953
3061
|
},
|
|
2954
3062
|
retainEntries(entries) {
|
|
2955
3063
|
retainedCacheKeys = new Set(
|
|
2956
|
-
entries.filter(
|
|
3064
|
+
entries.filter(
|
|
3065
|
+
(entry) => shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)
|
|
3066
|
+
).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry))
|
|
2957
3067
|
);
|
|
2958
3068
|
let changed = false;
|
|
2959
3069
|
for (const cacheKey of iconUrlByCacheKey.keys()) {
|
|
@@ -2998,22 +3108,29 @@ function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
|
2998
3108
|
}
|
|
2999
3109
|
|
|
3000
3110
|
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
3001
|
-
function buildIconTargetSignature(entries) {
|
|
3002
|
-
return entries.filter(shouldResolveWorkspaceFileEntryIcon).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry)).join("\0");
|
|
3111
|
+
function buildIconTargetSignature(entries, options) {
|
|
3112
|
+
return entries.filter((entry) => shouldResolveWorkspaceFileEntryIcon(entry, options)).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry)).join("\0");
|
|
3003
3113
|
}
|
|
3004
3114
|
function useWorkspaceFileEntryIconUrls(input) {
|
|
3005
|
-
const { entries, resolveEntryIconUrl } = input;
|
|
3115
|
+
const { entries, includeImageThumbnails, resolveEntryIconUrl } = input;
|
|
3006
3116
|
const queue = useMemo(
|
|
3007
3117
|
() => createWorkspaceFileEntryIconUrlQueue({
|
|
3118
|
+
includeImageThumbnails,
|
|
3008
3119
|
resolveEntryIconUrl
|
|
3009
3120
|
}),
|
|
3010
|
-
[resolveEntryIconUrl]
|
|
3121
|
+
[includeImageThumbnails, resolveEntryIconUrl]
|
|
3011
3122
|
);
|
|
3012
3123
|
const [iconUrlByCacheKey, setIconUrlByCacheKey] = useState6(() => queue.snapshot());
|
|
3013
3124
|
const iconTargetSignature = useMemo(
|
|
3014
|
-
() => buildIconTargetSignature(entries),
|
|
3015
|
-
[entries]
|
|
3125
|
+
() => buildIconTargetSignature(entries, { includeImageThumbnails }),
|
|
3126
|
+
[entries, includeImageThumbnails]
|
|
3016
3127
|
);
|
|
3128
|
+
useEffect4(() => {
|
|
3129
|
+
queue.activate();
|
|
3130
|
+
return () => {
|
|
3131
|
+
queue.dispose();
|
|
3132
|
+
};
|
|
3133
|
+
}, [queue]);
|
|
3017
3134
|
useEffect4(() => {
|
|
3018
3135
|
queue.retainEntries(entries);
|
|
3019
3136
|
}, [entries, iconTargetSignature, queue]);
|
|
@@ -3023,12 +3140,6 @@ function useWorkspaceFileEntryIconUrls(input) {
|
|
|
3023
3140
|
setIconUrlByCacheKey(queue.snapshot());
|
|
3024
3141
|
});
|
|
3025
3142
|
}, [queue]);
|
|
3026
|
-
useEffect4(
|
|
3027
|
-
() => () => {
|
|
3028
|
-
queue.dispose();
|
|
3029
|
-
},
|
|
3030
|
-
[queue]
|
|
3031
|
-
);
|
|
3032
3143
|
const reportEntryIconViewportEnter = useCallback5(
|
|
3033
3144
|
(entry) => {
|
|
3034
3145
|
queue.enterViewport(entry);
|
|
@@ -3515,6 +3626,7 @@ function WorkspaceFileManagerPanelsContainer({
|
|
|
3515
3626
|
reportEntryIconViewportLeave
|
|
3516
3627
|
} = useWorkspaceFileEntryIconUrls({
|
|
3517
3628
|
entries: arrangedEntries,
|
|
3629
|
+
includeImageThumbnails: true,
|
|
3518
3630
|
resolveEntryIconUrl
|
|
3519
3631
|
});
|
|
3520
3632
|
return /* @__PURE__ */ jsx6(
|