@tutti-os/workspace-file-manager 0.0.230 → 0.0.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +809 -761
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -31,10 +31,10 @@ import {
|
|
|
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 useMemo4,
|
|
38
38
|
useRef as useRef7,
|
|
39
39
|
useState as useState8
|
|
40
40
|
} 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 useMemo3
|
|
1134
|
+
} from "react";
|
|
1135
|
+
|
|
1130
1136
|
// src/ui/WorkspaceFileManagerPanels.tsx
|
|
1131
1137
|
import {
|
|
1132
1138
|
ArrowRightIcon as ArrowRightIcon2,
|
|
@@ -1140,6 +1146,7 @@ import {
|
|
|
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";
|
|
1142
1148
|
import {
|
|
1149
|
+
memo,
|
|
1143
1150
|
useCallback as useCallback2,
|
|
1144
1151
|
useEffect as useEffect4,
|
|
1145
1152
|
useLayoutEffect as useLayoutEffect4,
|
|
@@ -2366,7 +2373,7 @@ function resolveWorkspaceFileManagerDateColumnLabel(copy, arrangeMode) {
|
|
|
2366
2373
|
return copy.t("modifiedLabel");
|
|
2367
2374
|
}
|
|
2368
2375
|
}
|
|
2369
|
-
|
|
2376
|
+
var EntryRow = memo(function EntryRow2({
|
|
2370
2377
|
arrangeMode,
|
|
2371
2378
|
canMove,
|
|
2372
2379
|
contextMenuActive,
|
|
@@ -2540,7 +2547,7 @@ function EntryRow({
|
|
|
2540
2547
|
]
|
|
2541
2548
|
}
|
|
2542
2549
|
);
|
|
2543
|
-
}
|
|
2550
|
+
});
|
|
2544
2551
|
function MoveDragPreview({
|
|
2545
2552
|
iconUrlByCacheKey,
|
|
2546
2553
|
preview,
|
|
@@ -2976,231 +2983,700 @@ function FeedbackState({ message }) {
|
|
|
2976
2983
|
return /* @__PURE__ */ jsx6("div", { className: "grid min-h-0 flex-1 place-items-center p-6 text-center text-sm text-[var(--text-tertiary)]", children: /* @__PURE__ */ jsx6("span", { className: "max-w-[34ch] [overflow-wrap:anywhere]", children: message }) });
|
|
2977
2984
|
}
|
|
2978
2985
|
|
|
2979
|
-
// src/ui/
|
|
2980
|
-
import {
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
DropdownMenuContent,
|
|
2988
|
-
DropdownMenuRadioGroup,
|
|
2989
|
-
DropdownMenuRadioItem,
|
|
2990
|
-
DropdownMenuSeparator,
|
|
2991
|
-
DropdownMenuTrigger,
|
|
2992
|
-
Input as Input2,
|
|
2993
|
-
LoadingIcon as LoadingIcon3,
|
|
2994
|
-
RefreshIcon,
|
|
2995
|
-
SearchIcon,
|
|
2996
|
-
Tooltip,
|
|
2997
|
-
TooltipContent,
|
|
2998
|
-
TooltipProvider,
|
|
2999
|
-
TooltipTrigger,
|
|
3000
|
-
ViewGridLinedIcon,
|
|
3001
|
-
ViewListLinedIcon,
|
|
3002
|
-
cn as cn5
|
|
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();
|
|
3034
|
-
};
|
|
3035
|
-
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: [
|
|
3036
|
-
/* @__PURE__ */ jsx7(
|
|
3037
|
-
ToolbarIconButton,
|
|
3038
|
-
{
|
|
3039
|
-
ariaLabel: copy.t("backLabel"),
|
|
3040
|
-
disabled: !canGoBack || isLoading || isBusy,
|
|
3041
|
-
title: copy.t("backLabel"),
|
|
3042
|
-
onClick: onGoBack,
|
|
3043
|
-
children: /* @__PURE__ */ jsx7(ArrowLeftIcon2, { className: "size-4" })
|
|
3044
|
-
}
|
|
3045
|
-
),
|
|
3046
|
-
/* @__PURE__ */ jsx7(
|
|
3047
|
-
ToolbarIconButton,
|
|
3048
|
-
{
|
|
3049
|
-
ariaLabel: copy.t("forwardLabel"),
|
|
3050
|
-
disabled: !canGoForward || isLoading || isBusy,
|
|
3051
|
-
title: copy.t("forwardLabel"),
|
|
3052
|
-
onClick: onGoForward,
|
|
3053
|
-
children: /* @__PURE__ */ jsx7(ArrowRightIcon3, { className: "size-4" })
|
|
3054
|
-
}
|
|
3055
|
-
),
|
|
3056
|
-
/* @__PURE__ */ jsx7(
|
|
3057
|
-
"nav",
|
|
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
|
-
)) })
|
|
3074
|
-
}
|
|
3075
|
-
),
|
|
3076
|
-
/* @__PURE__ */ jsxs6("div", { className: "@max-[600px]/workspace-file-manager:justify-end flex flex-none items-center gap-1.5", children: [
|
|
3077
|
-
/* @__PURE__ */ jsx7(
|
|
3078
|
-
LayoutModeToggle,
|
|
3079
|
-
{
|
|
3080
|
-
arrangeMode,
|
|
3081
|
-
copy,
|
|
3082
|
-
layoutMode,
|
|
3083
|
-
onArrangeModeChange,
|
|
3084
|
-
onLayoutModeChange
|
|
3085
|
-
}
|
|
3086
|
-
),
|
|
3087
|
-
/* @__PURE__ */ jsxs6(
|
|
3088
|
-
ToolbarActionButton,
|
|
3089
|
-
{
|
|
3090
|
-
disabled: isLoading || isMutating || isBusy,
|
|
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
|
-
]
|
|
3105
|
-
}
|
|
3106
|
-
),
|
|
3107
|
-
renderToolbarTrailingActions?.({
|
|
3108
|
-
currentDirectoryPath,
|
|
3109
|
-
isBusy,
|
|
3110
|
-
isLoading,
|
|
3111
|
-
isMutating
|
|
3112
|
-
}) ?? null,
|
|
3113
|
-
/* @__PURE__ */ jsx7(
|
|
3114
|
-
WorkspaceFileManagerToolbarSearch,
|
|
3115
|
-
{
|
|
3116
|
-
canSearch,
|
|
3117
|
-
copy,
|
|
3118
|
-
isSearching,
|
|
3119
|
-
searchQuery,
|
|
3120
|
-
onClear: onSearchClear,
|
|
3121
|
-
onSearchQueryChange
|
|
3122
|
-
}
|
|
3123
|
-
)
|
|
3124
|
-
] })
|
|
3125
|
-
] });
|
|
2986
|
+
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
2987
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo2, useState as useState4 } from "react";
|
|
2988
|
+
|
|
2989
|
+
// src/ui/workspaceFileEntryIconUrlQueue.ts
|
|
2990
|
+
var defaultMaxConcurrentIconRequests = 3;
|
|
2991
|
+
var imageThumbnailCacheKeyPrefix = "image-thumbnail:";
|
|
2992
|
+
function shouldKeepResolvedIconAfterViewportLeave(cacheKey) {
|
|
2993
|
+
return cacheKey.startsWith(imageThumbnailCacheKeyPrefix);
|
|
3126
2994
|
}
|
|
3127
|
-
function
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
const
|
|
3136
|
-
const
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
2995
|
+
function createWorkspaceFileEntryIconUrlQueue(options) {
|
|
2996
|
+
const maxConcurrent = Math.max(
|
|
2997
|
+
1,
|
|
2998
|
+
Math.floor(options.maxConcurrent ?? defaultMaxConcurrentIconRequests)
|
|
2999
|
+
);
|
|
3000
|
+
const iconUrlByCacheKey = /* @__PURE__ */ new Map();
|
|
3001
|
+
const inFlightCacheKeys = /* @__PURE__ */ new Set();
|
|
3002
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
3003
|
+
const queuedEntries = /* @__PURE__ */ new Map();
|
|
3004
|
+
const visibleReferenceCountByCacheKey = /* @__PURE__ */ new Map();
|
|
3005
|
+
let activeCount = 0;
|
|
3006
|
+
let disposed = false;
|
|
3007
|
+
let retainedCacheKeys = null;
|
|
3008
|
+
const policyOptions = {
|
|
3009
|
+
includeImageThumbnails: options.includeImageThumbnails
|
|
3010
|
+
};
|
|
3011
|
+
function publish() {
|
|
3012
|
+
for (const listener of listeners) {
|
|
3013
|
+
listener();
|
|
3143
3014
|
}
|
|
3144
|
-
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3015
|
+
}
|
|
3016
|
+
function isRetained(cacheKey) {
|
|
3017
|
+
return retainedCacheKeys === null || retainedCacheKeys.has(cacheKey);
|
|
3018
|
+
}
|
|
3019
|
+
function isVisible(cacheKey) {
|
|
3020
|
+
return (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) > 0;
|
|
3021
|
+
}
|
|
3022
|
+
function shouldResolveCacheKey(cacheKey) {
|
|
3023
|
+
return isVisible(cacheKey) || shouldKeepResolvedIconAfterViewportLeave(cacheKey);
|
|
3024
|
+
}
|
|
3025
|
+
function retainVisibleReference(cacheKey) {
|
|
3026
|
+
visibleReferenceCountByCacheKey.set(
|
|
3027
|
+
cacheKey,
|
|
3028
|
+
(visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) + 1
|
|
3029
|
+
);
|
|
3030
|
+
}
|
|
3031
|
+
function releaseVisibleReference(cacheKey) {
|
|
3032
|
+
const nextCount = (visibleReferenceCountByCacheKey.get(cacheKey) ?? 0) - 1;
|
|
3033
|
+
if (nextCount > 0) {
|
|
3034
|
+
visibleReferenceCountByCacheKey.set(cacheKey, nextCount);
|
|
3147
3035
|
return;
|
|
3148
3036
|
}
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
useEffect5(() => {
|
|
3152
|
-
if (isComposingRef.current) {
|
|
3037
|
+
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
3038
|
+
if (shouldKeepResolvedIconAfterViewportLeave(cacheKey)) {
|
|
3153
3039
|
return;
|
|
3154
3040
|
}
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
};
|
|
3161
|
-
const handleClear = () => {
|
|
3162
|
-
isComposingRef.current = false;
|
|
3163
|
-
setInputValue("");
|
|
3164
|
-
onClear();
|
|
3165
|
-
setExpanded(false);
|
|
3166
|
-
};
|
|
3167
|
-
if (!active) {
|
|
3168
|
-
return /* @__PURE__ */ jsx7(
|
|
3169
|
-
ToolbarIconButton,
|
|
3170
|
-
{
|
|
3171
|
-
ariaLabel: copy.t("searchPlaceholder"),
|
|
3172
|
-
disabled: !canSearch,
|
|
3173
|
-
title: copy.t("searchPlaceholder"),
|
|
3174
|
-
onClick: () => {
|
|
3175
|
-
setExpanded(true);
|
|
3176
|
-
},
|
|
3177
|
-
children: /* @__PURE__ */ jsx7(SearchIcon, { className: "size-4" })
|
|
3178
|
-
}
|
|
3179
|
-
);
|
|
3041
|
+
queuedEntries.delete(cacheKey);
|
|
3042
|
+
const hadCachedIcon = iconUrlByCacheKey.delete(cacheKey);
|
|
3043
|
+
if (hadCachedIcon) {
|
|
3044
|
+
publish();
|
|
3045
|
+
}
|
|
3180
3046
|
}
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3047
|
+
function drain() {
|
|
3048
|
+
if (disposed || !options.resolveEntryIconUrl) {
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
while (activeCount < maxConcurrent && queuedEntries.size > 0) {
|
|
3052
|
+
const next = queuedEntries.entries().next().value;
|
|
3053
|
+
if (!next) {
|
|
3054
|
+
return;
|
|
3055
|
+
}
|
|
3056
|
+
const [cacheKey, entry] = next;
|
|
3057
|
+
queuedEntries.delete(cacheKey);
|
|
3058
|
+
if (!shouldResolveCacheKey(cacheKey) || iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey)) {
|
|
3059
|
+
continue;
|
|
3060
|
+
}
|
|
3061
|
+
activeCount += 1;
|
|
3062
|
+
inFlightCacheKeys.add(cacheKey);
|
|
3063
|
+
void options.resolveEntryIconUrl(entry).then((iconUrl) => {
|
|
3064
|
+
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3065
|
+
if (shouldStore) {
|
|
3066
|
+
iconUrlByCacheKey.set(cacheKey, iconUrl?.trim() || null);
|
|
3067
|
+
publish();
|
|
3068
|
+
}
|
|
3069
|
+
}).catch(() => {
|
|
3070
|
+
const shouldStore = !disposed && isRetained(cacheKey) && shouldResolveCacheKey(cacheKey);
|
|
3071
|
+
if (shouldStore) {
|
|
3072
|
+
iconUrlByCacheKey.set(cacheKey, null);
|
|
3073
|
+
publish();
|
|
3074
|
+
}
|
|
3075
|
+
}).finally(() => {
|
|
3076
|
+
activeCount -= 1;
|
|
3077
|
+
inFlightCacheKeys.delete(cacheKey);
|
|
3078
|
+
drain();
|
|
3079
|
+
});
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
return {
|
|
3083
|
+
activate() {
|
|
3084
|
+
disposed = false;
|
|
3085
|
+
},
|
|
3086
|
+
dispose() {
|
|
3087
|
+
disposed = true;
|
|
3088
|
+
queuedEntries.clear();
|
|
3089
|
+
visibleReferenceCountByCacheKey.clear();
|
|
3090
|
+
listeners.clear();
|
|
3091
|
+
},
|
|
3092
|
+
leaveViewport(entry) {
|
|
3093
|
+
if (disposed || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3096
|
+
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3097
|
+
releaseVisibleReference(cacheKey);
|
|
3098
|
+
},
|
|
3099
|
+
enterViewport(entry) {
|
|
3100
|
+
if (disposed || !options.resolveEntryIconUrl || !shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)) {
|
|
3101
|
+
return;
|
|
3102
|
+
}
|
|
3103
|
+
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
3104
|
+
retainVisibleReference(cacheKey);
|
|
3105
|
+
if (iconUrlByCacheKey.has(cacheKey) || inFlightCacheKeys.has(cacheKey) || queuedEntries.has(cacheKey)) {
|
|
3106
|
+
return;
|
|
3107
|
+
}
|
|
3108
|
+
queuedEntries.set(cacheKey, entry);
|
|
3109
|
+
drain();
|
|
3110
|
+
},
|
|
3111
|
+
retainEntries(entries) {
|
|
3112
|
+
retainedCacheKeys = new Set(
|
|
3113
|
+
entries.filter(
|
|
3114
|
+
(entry) => shouldResolveWorkspaceFileEntryIcon(entry, policyOptions)
|
|
3115
|
+
).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry))
|
|
3116
|
+
);
|
|
3117
|
+
let changed = false;
|
|
3118
|
+
for (const cacheKey of iconUrlByCacheKey.keys()) {
|
|
3119
|
+
if (!isRetained(cacheKey)) {
|
|
3120
|
+
iconUrlByCacheKey.delete(cacheKey);
|
|
3121
|
+
changed = true;
|
|
3122
|
+
continue;
|
|
3123
|
+
}
|
|
3124
|
+
if (iconUrlByCacheKey.get(cacheKey) === null) {
|
|
3125
|
+
iconUrlByCacheKey.delete(cacheKey);
|
|
3126
|
+
changed = true;
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
for (const cacheKey of queuedEntries.keys()) {
|
|
3130
|
+
if (!isRetained(cacheKey)) {
|
|
3131
|
+
queuedEntries.delete(cacheKey);
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
for (const cacheKey of visibleReferenceCountByCacheKey.keys()) {
|
|
3135
|
+
if (!isRetained(cacheKey)) {
|
|
3136
|
+
visibleReferenceCountByCacheKey.delete(cacheKey);
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
if (changed) {
|
|
3140
|
+
publish();
|
|
3141
|
+
}
|
|
3142
|
+
},
|
|
3143
|
+
snapshot() {
|
|
3144
|
+
return new Map(iconUrlByCacheKey);
|
|
3145
|
+
},
|
|
3146
|
+
subscribe(listener) {
|
|
3147
|
+
if (disposed) {
|
|
3148
|
+
return () => {
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
listeners.add(listener);
|
|
3152
|
+
return () => {
|
|
3153
|
+
listeners.delete(listener);
|
|
3154
|
+
};
|
|
3155
|
+
}
|
|
3156
|
+
};
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
3160
|
+
function buildIconTargetSignature(entries, options) {
|
|
3161
|
+
return entries.filter((entry) => shouldResolveWorkspaceFileEntryIcon(entry, options)).map((entry) => resolveWorkspaceFileEntryIconCacheKey(entry)).join("\0");
|
|
3162
|
+
}
|
|
3163
|
+
function useWorkspaceFileEntryIconUrls(input) {
|
|
3164
|
+
const { entries, includeImageThumbnails, resolveEntryIconUrl } = input;
|
|
3165
|
+
const queue = useMemo2(
|
|
3166
|
+
() => createWorkspaceFileEntryIconUrlQueue({
|
|
3167
|
+
includeImageThumbnails,
|
|
3168
|
+
resolveEntryIconUrl
|
|
3169
|
+
}),
|
|
3170
|
+
[includeImageThumbnails, resolveEntryIconUrl]
|
|
3171
|
+
);
|
|
3172
|
+
const [iconUrlByCacheKey, setIconUrlByCacheKey] = useState4(() => queue.snapshot());
|
|
3173
|
+
const iconTargetSignature = useMemo2(
|
|
3174
|
+
() => buildIconTargetSignature(entries, { includeImageThumbnails }),
|
|
3175
|
+
[entries, includeImageThumbnails]
|
|
3176
|
+
);
|
|
3177
|
+
useEffect5(() => {
|
|
3178
|
+
queue.activate();
|
|
3179
|
+
return () => {
|
|
3180
|
+
queue.dispose();
|
|
3181
|
+
};
|
|
3182
|
+
}, [queue]);
|
|
3183
|
+
useEffect5(() => {
|
|
3184
|
+
queue.retainEntries(entries);
|
|
3185
|
+
}, [entries, iconTargetSignature, queue]);
|
|
3186
|
+
useEffect5(() => {
|
|
3187
|
+
setIconUrlByCacheKey(queue.snapshot());
|
|
3188
|
+
return queue.subscribe(() => {
|
|
3189
|
+
setIconUrlByCacheKey(queue.snapshot());
|
|
3190
|
+
});
|
|
3191
|
+
}, [queue]);
|
|
3192
|
+
const reportEntryIconViewportEnter = useCallback3(
|
|
3193
|
+
(entry) => {
|
|
3194
|
+
queue.enterViewport(entry);
|
|
3195
|
+
},
|
|
3196
|
+
[queue]
|
|
3197
|
+
);
|
|
3198
|
+
const reportEntryIconViewportLeave = useCallback3(
|
|
3199
|
+
(entry) => {
|
|
3200
|
+
queue.leaveViewport(entry);
|
|
3201
|
+
},
|
|
3202
|
+
[queue]
|
|
3203
|
+
);
|
|
3204
|
+
return {
|
|
3205
|
+
iconUrlByCacheKey,
|
|
3206
|
+
reportEntryIconViewportEnter,
|
|
3207
|
+
reportEntryIconViewportLeave
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
// src/ui/workspaceFileManagerVisibleTree.ts
|
|
3212
|
+
function buildWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3213
|
+
return appendWorkspaceFileManagerVisibleTreeRows({
|
|
3214
|
+
...input,
|
|
3215
|
+
depth: 0
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3218
|
+
function collectWorkspaceFileManagerVisibleTreeEntries(rows) {
|
|
3219
|
+
return rows.flatMap((row) => row.kind === "entry" ? [row.entry] : []);
|
|
3220
|
+
}
|
|
3221
|
+
function appendWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3222
|
+
const sortedEntries = sortWorkspaceFileEntriesForArrangeMode(
|
|
3223
|
+
input.entries,
|
|
3224
|
+
input.arrangeMode
|
|
3225
|
+
);
|
|
3226
|
+
const rows = [];
|
|
3227
|
+
for (const entry of sortedEntries) {
|
|
3228
|
+
const expandable = entry.kind === "directory" && entry.hasChildren;
|
|
3229
|
+
const expanded = expandable ? input.expandedDirectoryPaths[entry.path] === true : false;
|
|
3230
|
+
const childState = input.directoryExpansionByPath[entry.path];
|
|
3231
|
+
rows.push({
|
|
3232
|
+
depth: input.depth,
|
|
3233
|
+
entry,
|
|
3234
|
+
expanded,
|
|
3235
|
+
expandable,
|
|
3236
|
+
kind: "entry",
|
|
3237
|
+
loadingChildren: childState?.isLoading ?? false
|
|
3238
|
+
});
|
|
3239
|
+
if (!expanded) {
|
|
3240
|
+
continue;
|
|
3241
|
+
}
|
|
3242
|
+
if (!childState || childState.isLoading) {
|
|
3243
|
+
rows.push({
|
|
3244
|
+
depth: input.depth + 1,
|
|
3245
|
+
key: `${entry.path}:loading`,
|
|
3246
|
+
kind: "feedback",
|
|
3247
|
+
parentPath: entry.path,
|
|
3248
|
+
status: "loading"
|
|
3249
|
+
});
|
|
3250
|
+
continue;
|
|
3251
|
+
}
|
|
3252
|
+
if (childState.error) {
|
|
3253
|
+
rows.push({
|
|
3254
|
+
depth: input.depth + 1,
|
|
3255
|
+
key: `${entry.path}:error`,
|
|
3256
|
+
kind: "feedback",
|
|
3257
|
+
message: childState.error,
|
|
3258
|
+
parentPath: entry.path,
|
|
3259
|
+
status: "error"
|
|
3260
|
+
});
|
|
3261
|
+
continue;
|
|
3262
|
+
}
|
|
3263
|
+
if (childState.loaded && childState.entries.length === 0) {
|
|
3264
|
+
rows.push({
|
|
3265
|
+
depth: input.depth + 1,
|
|
3266
|
+
key: `${entry.path}:empty`,
|
|
3267
|
+
kind: "feedback",
|
|
3268
|
+
parentPath: entry.path,
|
|
3269
|
+
status: "empty"
|
|
3270
|
+
});
|
|
3271
|
+
continue;
|
|
3272
|
+
}
|
|
3273
|
+
rows.push(
|
|
3274
|
+
...appendWorkspaceFileManagerVisibleTreeRows({
|
|
3275
|
+
...input,
|
|
3276
|
+
depth: input.depth + 1,
|
|
3277
|
+
entries: childState.entries
|
|
3278
|
+
})
|
|
3279
|
+
);
|
|
3280
|
+
}
|
|
3281
|
+
return rows;
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
// src/ui/WorkspaceFileManagerPanelsContainer.tsx
|
|
3285
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
3286
|
+
function WorkspaceFileManagerPanelsContainer({
|
|
3287
|
+
arrangeMode,
|
|
3288
|
+
dateLocale,
|
|
3289
|
+
entryDragMode,
|
|
3290
|
+
i18n,
|
|
3291
|
+
layoutMode,
|
|
3292
|
+
onDirectoryExpanded,
|
|
3293
|
+
onEntryDragStart,
|
|
3294
|
+
onOpenContextMenu,
|
|
3295
|
+
resolveEntryIconUrl,
|
|
3296
|
+
session,
|
|
3297
|
+
showPreviewPanel
|
|
3298
|
+
}) {
|
|
3299
|
+
const { state, view } = useWorkspaceFileManagerPanelsView(session);
|
|
3300
|
+
const arrangedEntries = useMemo3(
|
|
3301
|
+
() => sortWorkspaceFileEntriesForArrangeMode(state.entries, arrangeMode),
|
|
3302
|
+
[arrangeMode, state.entries]
|
|
3303
|
+
);
|
|
3304
|
+
const searchEntries = useMemo3(
|
|
3305
|
+
() => view.searchEntries.map(workspaceFileSearchEntryToEntry),
|
|
3306
|
+
[view.searchEntries]
|
|
3307
|
+
);
|
|
3308
|
+
const searchEntryContextByPath = useMemo3(() => {
|
|
3309
|
+
const contextByPath = /* @__PURE__ */ new Map();
|
|
3310
|
+
for (const entry of view.searchEntries) {
|
|
3311
|
+
contextByPath.set(entry.path, entry.directoryPath);
|
|
3312
|
+
}
|
|
3313
|
+
return contextByPath;
|
|
3314
|
+
}, [view.searchEntries]);
|
|
3315
|
+
const treeRows = useMemo3(
|
|
3316
|
+
() => buildWorkspaceFileManagerVisibleTreeRows({
|
|
3317
|
+
arrangeMode,
|
|
3318
|
+
directoryExpansionByPath: state.directoryExpansionByPath,
|
|
3319
|
+
entries: arrangedEntries,
|
|
3320
|
+
expandedDirectoryPaths: state.expandedDirectoryPaths
|
|
3321
|
+
}),
|
|
3322
|
+
[
|
|
3323
|
+
arrangeMode,
|
|
3324
|
+
arrangedEntries,
|
|
3325
|
+
state.directoryExpansionByPath,
|
|
3326
|
+
state.expandedDirectoryPaths
|
|
3327
|
+
]
|
|
3328
|
+
);
|
|
3329
|
+
const searchTreeRows = useMemo3(
|
|
3330
|
+
() => searchEntries.map((entry) => ({
|
|
3331
|
+
depth: 0,
|
|
3332
|
+
entry,
|
|
3333
|
+
expanded: false,
|
|
3334
|
+
expandable: false,
|
|
3335
|
+
kind: "entry",
|
|
3336
|
+
loadingChildren: false
|
|
3337
|
+
})),
|
|
3338
|
+
[searchEntries]
|
|
3339
|
+
);
|
|
3340
|
+
const displayedEntries = view.isSearchMode ? searchEntries : arrangedEntries;
|
|
3341
|
+
const displayedTreeRows = view.isSearchMode ? searchTreeRows : treeRows;
|
|
3342
|
+
const visibleTreeEntries = useMemo3(
|
|
3343
|
+
() => collectWorkspaceFileManagerVisibleTreeEntries(displayedTreeRows),
|
|
3344
|
+
[displayedTreeRows]
|
|
3345
|
+
);
|
|
3346
|
+
const panelState = useMemo3(
|
|
3347
|
+
() => ({
|
|
3348
|
+
entries: displayedEntries,
|
|
3349
|
+
error: view.isSearchMode ? view.searchError : state.error,
|
|
3350
|
+
isLoading: view.isSearchMode ? view.isSearching : state.isLoading,
|
|
3351
|
+
isSearchMode: view.isSearchMode
|
|
3352
|
+
}),
|
|
3353
|
+
[
|
|
3354
|
+
displayedEntries,
|
|
3355
|
+
state.error,
|
|
3356
|
+
state.isLoading,
|
|
3357
|
+
view.isSearchMode,
|
|
3358
|
+
view.isSearching,
|
|
3359
|
+
view.searchError
|
|
3360
|
+
]
|
|
3361
|
+
);
|
|
3362
|
+
const {
|
|
3363
|
+
iconUrlByCacheKey,
|
|
3364
|
+
reportEntryIconViewportEnter,
|
|
3365
|
+
reportEntryIconViewportLeave
|
|
3366
|
+
} = useWorkspaceFileEntryIconUrls({
|
|
3367
|
+
entries: layoutMode === "list" ? visibleTreeEntries : displayedEntries,
|
|
3368
|
+
includeImageThumbnails: true,
|
|
3369
|
+
resolveEntryIconUrl
|
|
3370
|
+
});
|
|
3371
|
+
const handleBlankContextMenu = useCallback4(
|
|
3372
|
+
(event) => {
|
|
3373
|
+
onOpenContextMenu(event, null);
|
|
3374
|
+
},
|
|
3375
|
+
[onOpenContextMenu]
|
|
3376
|
+
);
|
|
3377
|
+
const handleCancelInlineRename = useCallback4(() => {
|
|
3378
|
+
session.cancelInlineRename();
|
|
3379
|
+
}, [session]);
|
|
3380
|
+
const handleClearInlineRenameValidation = useCallback4(() => {
|
|
3381
|
+
session.clearInlineRenameValidation();
|
|
3382
|
+
}, [session]);
|
|
3383
|
+
const handleConfirmInlineRename = useCallback4(
|
|
3384
|
+
(newName) => session.confirmInlineRename(newName),
|
|
3385
|
+
[session]
|
|
3386
|
+
);
|
|
3387
|
+
const handleMoveEntry = useCallback4(
|
|
3388
|
+
(entry, targetDirectoryPath) => {
|
|
3389
|
+
void session.moveEntry(entry, targetDirectoryPath);
|
|
3390
|
+
},
|
|
3391
|
+
[session]
|
|
3392
|
+
);
|
|
3393
|
+
const handleOpenEntry = useCallback4(
|
|
3394
|
+
(entry) => {
|
|
3395
|
+
if (entry.kind === "directory") {
|
|
3396
|
+
onDirectoryExpanded?.(entry.path);
|
|
3397
|
+
}
|
|
3398
|
+
void session.openEntry(entry);
|
|
3399
|
+
},
|
|
3400
|
+
[onDirectoryExpanded, session]
|
|
3401
|
+
);
|
|
3402
|
+
const handleSelect = useCallback4(
|
|
3403
|
+
(path) => {
|
|
3404
|
+
session.select(path);
|
|
3405
|
+
},
|
|
3406
|
+
[session]
|
|
3407
|
+
);
|
|
3408
|
+
const handleToggleDirectoryExpanded = useCallback4(
|
|
3409
|
+
(entry, expanded) => {
|
|
3410
|
+
if (!expanded) {
|
|
3411
|
+
onDirectoryExpanded?.(entry.path);
|
|
3412
|
+
}
|
|
3413
|
+
void session.toggleDirectoryExpanded(entry);
|
|
3414
|
+
},
|
|
3415
|
+
[onDirectoryExpanded, session]
|
|
3416
|
+
);
|
|
3417
|
+
return /* @__PURE__ */ jsx7(
|
|
3418
|
+
WorkspaceFileManagerPanels,
|
|
3419
|
+
{
|
|
3420
|
+
arrangeMode,
|
|
3421
|
+
canMove: view.isSearchMode ? false : view.canMove,
|
|
3422
|
+
contextMenuEntryPath: view.contextMenuEntryPath,
|
|
3423
|
+
copy: i18n,
|
|
3424
|
+
dateLocale,
|
|
3425
|
+
entryContextByPath: view.isSearchMode ? searchEntryContextByPath : null,
|
|
3426
|
+
entryDragMode,
|
|
3427
|
+
iconUrlByCacheKey,
|
|
3428
|
+
inlineRenameEntryPath: view.inlineRenameEntryPath,
|
|
3429
|
+
inlineRenameValidation: view.inlineRenameValidation,
|
|
3430
|
+
isRenaming: view.isRenaming,
|
|
3431
|
+
layoutMode,
|
|
3432
|
+
pendingDirectoryPath: view.pendingDirectoryPath,
|
|
3433
|
+
previewState: view.previewState,
|
|
3434
|
+
selectedEntry: view.selectedEntry,
|
|
3435
|
+
selectedPath: view.selectedPath,
|
|
3436
|
+
showPreviewPanel,
|
|
3437
|
+
state: panelState,
|
|
3438
|
+
treeRows: displayedTreeRows,
|
|
3439
|
+
onBlankContextMenu: handleBlankContextMenu,
|
|
3440
|
+
onCancelInlineRename: handleCancelInlineRename,
|
|
3441
|
+
onClearInlineRenameValidation: handleClearInlineRenameValidation,
|
|
3442
|
+
onConfirmInlineRename: handleConfirmInlineRename,
|
|
3443
|
+
onEntryContextMenu: onOpenContextMenu,
|
|
3444
|
+
onEntryDragStart,
|
|
3445
|
+
onEntryIconViewportEnter: reportEntryIconViewportEnter,
|
|
3446
|
+
onEntryIconViewportLeave: reportEntryIconViewportLeave,
|
|
3447
|
+
onMoveEntry: handleMoveEntry,
|
|
3448
|
+
onOpenEntry: handleOpenEntry,
|
|
3449
|
+
onSelect: handleSelect,
|
|
3450
|
+
onToggleDirectoryExpanded: handleToggleDirectoryExpanded
|
|
3451
|
+
}
|
|
3452
|
+
);
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3455
|
+
// src/ui/WorkspaceFileManagerToolbar.tsx
|
|
3456
|
+
import {
|
|
3457
|
+
ArrowLeftIcon as ArrowLeftIcon2,
|
|
3458
|
+
ArrowRightIcon as ArrowRightIcon3,
|
|
3459
|
+
Button as Button2,
|
|
3460
|
+
ChevronDownIcon,
|
|
3461
|
+
CloseIcon,
|
|
3462
|
+
DropdownMenu,
|
|
3463
|
+
DropdownMenuContent,
|
|
3464
|
+
DropdownMenuRadioGroup,
|
|
3465
|
+
DropdownMenuRadioItem,
|
|
3466
|
+
DropdownMenuSeparator,
|
|
3467
|
+
DropdownMenuTrigger,
|
|
3468
|
+
Input as Input2,
|
|
3469
|
+
LoadingIcon as LoadingIcon3,
|
|
3470
|
+
RefreshIcon,
|
|
3471
|
+
SearchIcon,
|
|
3472
|
+
Tooltip,
|
|
3473
|
+
TooltipContent,
|
|
3474
|
+
TooltipProvider,
|
|
3475
|
+
TooltipTrigger,
|
|
3476
|
+
ViewGridLinedIcon,
|
|
3477
|
+
ViewListLinedIcon,
|
|
3478
|
+
cn as cn5
|
|
3479
|
+
} from "@tutti-os/ui-system";
|
|
3480
|
+
import { useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
|
|
3481
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3482
|
+
function WorkspaceFileManagerToolbar({
|
|
3483
|
+
breadcrumbs,
|
|
3484
|
+
canSearch,
|
|
3485
|
+
canGoBack,
|
|
3486
|
+
canGoForward,
|
|
3487
|
+
copy,
|
|
3488
|
+
currentDirectoryPath,
|
|
3489
|
+
isBusy,
|
|
3490
|
+
isLoading,
|
|
3491
|
+
isMutating,
|
|
3492
|
+
isSearching,
|
|
3493
|
+
arrangeMode,
|
|
3494
|
+
layoutMode,
|
|
3495
|
+
renderToolbarTrailingActions,
|
|
3496
|
+
searchQuery,
|
|
3497
|
+
onGoBack,
|
|
3498
|
+
onGoForward,
|
|
3499
|
+
onArrangeModeChange,
|
|
3500
|
+
onLayoutModeChange,
|
|
3501
|
+
onLoadDirectory,
|
|
3502
|
+
onRefresh,
|
|
3503
|
+
onSearchClear,
|
|
3504
|
+
onSearchQueryChange
|
|
3505
|
+
}) {
|
|
3506
|
+
const [refreshAnimationKey, setRefreshAnimationKey] = useState5(0);
|
|
3507
|
+
const handleRefresh = () => {
|
|
3508
|
+
setRefreshAnimationKey((currentKey) => currentKey + 1);
|
|
3509
|
+
onRefresh();
|
|
3510
|
+
};
|
|
3511
|
+
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: [
|
|
3512
|
+
/* @__PURE__ */ jsx8(
|
|
3513
|
+
ToolbarIconButton,
|
|
3514
|
+
{
|
|
3515
|
+
ariaLabel: copy.t("backLabel"),
|
|
3516
|
+
disabled: !canGoBack || isLoading || isBusy,
|
|
3517
|
+
title: copy.t("backLabel"),
|
|
3518
|
+
onClick: onGoBack,
|
|
3519
|
+
children: /* @__PURE__ */ jsx8(ArrowLeftIcon2, { className: "size-4" })
|
|
3520
|
+
}
|
|
3521
|
+
),
|
|
3522
|
+
/* @__PURE__ */ jsx8(
|
|
3523
|
+
ToolbarIconButton,
|
|
3524
|
+
{
|
|
3525
|
+
ariaLabel: copy.t("forwardLabel"),
|
|
3526
|
+
disabled: !canGoForward || isLoading || isBusy,
|
|
3527
|
+
title: copy.t("forwardLabel"),
|
|
3528
|
+
onClick: onGoForward,
|
|
3529
|
+
children: /* @__PURE__ */ jsx8(ArrowRightIcon3, { className: "size-4" })
|
|
3530
|
+
}
|
|
3531
|
+
),
|
|
3532
|
+
/* @__PURE__ */ jsx8(
|
|
3533
|
+
"nav",
|
|
3534
|
+
{
|
|
3535
|
+
"aria-label": currentDirectoryPath,
|
|
3536
|
+
className: "@max-[600px]/workspace-file-manager:flex-auto flex min-w-0 flex-1 overflow-hidden pr-2",
|
|
3537
|
+
"data-workspace-file-manager-path": "",
|
|
3538
|
+
children: /* @__PURE__ */ jsx8("ol", { className: "flex min-w-0 max-w-full flex-1 items-center gap-2 overflow-hidden", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsx8(
|
|
3539
|
+
BreadcrumbButton,
|
|
3540
|
+
{
|
|
3541
|
+
active: index === breadcrumbs.length - 1,
|
|
3542
|
+
label: crumb.label,
|
|
3543
|
+
showSeparator: index > 0,
|
|
3544
|
+
onClick: () => {
|
|
3545
|
+
onLoadDirectory(crumb.path);
|
|
3546
|
+
}
|
|
3547
|
+
},
|
|
3548
|
+
crumb.path
|
|
3549
|
+
)) })
|
|
3550
|
+
}
|
|
3551
|
+
),
|
|
3552
|
+
/* @__PURE__ */ jsxs6("div", { className: "@max-[600px]/workspace-file-manager:justify-end flex flex-none items-center gap-1.5", children: [
|
|
3553
|
+
/* @__PURE__ */ jsx8(
|
|
3554
|
+
LayoutModeToggle,
|
|
3555
|
+
{
|
|
3556
|
+
arrangeMode,
|
|
3557
|
+
copy,
|
|
3558
|
+
layoutMode,
|
|
3559
|
+
onArrangeModeChange,
|
|
3560
|
+
onLayoutModeChange
|
|
3561
|
+
}
|
|
3562
|
+
),
|
|
3563
|
+
/* @__PURE__ */ jsxs6(
|
|
3564
|
+
ToolbarActionButton,
|
|
3565
|
+
{
|
|
3566
|
+
disabled: isLoading || isMutating || isBusy,
|
|
3567
|
+
onClick: handleRefresh,
|
|
3568
|
+
children: [
|
|
3569
|
+
isLoading ? /* @__PURE__ */ jsx8(LoadingIcon3, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx8(
|
|
3570
|
+
RefreshIcon,
|
|
3571
|
+
{
|
|
3572
|
+
className: cn5(
|
|
3573
|
+
"size-4",
|
|
3574
|
+
refreshAnimationKey > 0 && "motion-safe:animate-[spin_520ms_cubic-bezier(0.4,0,0.2,1)_1_reverse]"
|
|
3575
|
+
)
|
|
3576
|
+
},
|
|
3577
|
+
refreshAnimationKey
|
|
3578
|
+
),
|
|
3579
|
+
/* @__PURE__ */ jsx8("span", { className: "@max-[600px]/workspace-file-manager:hidden", children: copy.t("refreshLabel") })
|
|
3580
|
+
]
|
|
3581
|
+
}
|
|
3582
|
+
),
|
|
3583
|
+
renderToolbarTrailingActions?.({
|
|
3584
|
+
currentDirectoryPath,
|
|
3585
|
+
isBusy,
|
|
3586
|
+
isLoading,
|
|
3587
|
+
isMutating
|
|
3588
|
+
}) ?? null,
|
|
3589
|
+
/* @__PURE__ */ jsx8(
|
|
3590
|
+
WorkspaceFileManagerToolbarSearch,
|
|
3591
|
+
{
|
|
3592
|
+
canSearch,
|
|
3593
|
+
copy,
|
|
3594
|
+
isSearching,
|
|
3595
|
+
searchQuery,
|
|
3596
|
+
onClear: onSearchClear,
|
|
3597
|
+
onSearchQueryChange
|
|
3598
|
+
}
|
|
3599
|
+
)
|
|
3600
|
+
] })
|
|
3601
|
+
] });
|
|
3602
|
+
}
|
|
3603
|
+
function WorkspaceFileManagerToolbarSearch({
|
|
3604
|
+
canSearch,
|
|
3605
|
+
copy,
|
|
3606
|
+
isSearching,
|
|
3607
|
+
searchQuery,
|
|
3608
|
+
onClear,
|
|
3609
|
+
onSearchQueryChange
|
|
3610
|
+
}) {
|
|
3611
|
+
const [expanded, setExpanded] = useState5(searchQuery.trim().length > 0);
|
|
3612
|
+
const [inputValue, setInputValue] = useState5(searchQuery);
|
|
3613
|
+
const inputRef = useRef6(null);
|
|
3614
|
+
const isComposingRef = useRef6(false);
|
|
3615
|
+
const active = expanded || searchQuery.trim().length > 0;
|
|
3616
|
+
useEffect6(() => {
|
|
3617
|
+
if (searchQuery.trim().length > 0) {
|
|
3618
|
+
setExpanded(true);
|
|
3619
|
+
}
|
|
3620
|
+
}, [searchQuery]);
|
|
3621
|
+
useEffect6(() => {
|
|
3622
|
+
if (!expanded) {
|
|
3623
|
+
return;
|
|
3624
|
+
}
|
|
3625
|
+
inputRef.current?.focus();
|
|
3626
|
+
}, [expanded]);
|
|
3627
|
+
useEffect6(() => {
|
|
3628
|
+
if (isComposingRef.current) {
|
|
3629
|
+
return;
|
|
3630
|
+
}
|
|
3631
|
+
setInputValue(searchQuery);
|
|
3632
|
+
}, [searchQuery]);
|
|
3633
|
+
const commitInputValue = (value) => {
|
|
3634
|
+
setInputValue(value);
|
|
3635
|
+
onSearchQueryChange(value);
|
|
3636
|
+
};
|
|
3637
|
+
const handleClear = () => {
|
|
3638
|
+
isComposingRef.current = false;
|
|
3639
|
+
setInputValue("");
|
|
3640
|
+
onClear();
|
|
3641
|
+
setExpanded(false);
|
|
3642
|
+
};
|
|
3643
|
+
if (!active) {
|
|
3644
|
+
return /* @__PURE__ */ jsx8(
|
|
3645
|
+
ToolbarIconButton,
|
|
3646
|
+
{
|
|
3647
|
+
ariaLabel: copy.t("searchPlaceholder"),
|
|
3648
|
+
disabled: !canSearch,
|
|
3649
|
+
title: copy.t("searchPlaceholder"),
|
|
3650
|
+
onClick: () => {
|
|
3651
|
+
setExpanded(true);
|
|
3652
|
+
},
|
|
3653
|
+
children: /* @__PURE__ */ jsx8(SearchIcon, { className: "size-4" })
|
|
3654
|
+
}
|
|
3655
|
+
);
|
|
3656
|
+
}
|
|
3657
|
+
return /* @__PURE__ */ jsxs6(
|
|
3658
|
+
"div",
|
|
3659
|
+
{
|
|
3660
|
+
className: cn5(
|
|
3661
|
+
"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",
|
|
3662
|
+
"@max-[600px]/workspace-file-manager:w-[min(170px,42vw)]",
|
|
3663
|
+
!canSearch && "opacity-60"
|
|
3664
|
+
),
|
|
3665
|
+
children: [
|
|
3666
|
+
/* @__PURE__ */ jsx8(SearchIcon, { className: "pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 text-[var(--text-tertiary)]" }),
|
|
3667
|
+
/* @__PURE__ */ jsx8(
|
|
3668
|
+
Input2,
|
|
3669
|
+
{
|
|
3670
|
+
"aria-label": copy.t("searchPlaceholder"),
|
|
3671
|
+
className: "h-full border-0 bg-transparent pr-8 pl-8 text-sm shadow-none focus-visible:ring-0",
|
|
3672
|
+
disabled: !canSearch,
|
|
3673
|
+
placeholder: copy.t("searchPlaceholder"),
|
|
3674
|
+
ref: inputRef,
|
|
3675
|
+
value: inputValue,
|
|
3676
|
+
onBlur: (event) => {
|
|
3677
|
+
commitInputValue(event.currentTarget.value);
|
|
3678
|
+
},
|
|
3679
|
+
onChange: (event) => {
|
|
3204
3680
|
const nextValue = event.currentTarget.value;
|
|
3205
3681
|
if (isComposingRef.current) {
|
|
3206
3682
|
setInputValue(nextValue);
|
|
@@ -3227,14 +3703,14 @@ function WorkspaceFileManagerToolbarSearch({
|
|
|
3227
3703
|
}
|
|
3228
3704
|
}
|
|
3229
3705
|
),
|
|
3230
|
-
/* @__PURE__ */
|
|
3706
|
+
/* @__PURE__ */ jsx8(
|
|
3231
3707
|
"button",
|
|
3232
3708
|
{
|
|
3233
3709
|
"aria-label": copy.t("clearSearchLabel"),
|
|
3234
3710
|
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
3711
|
type: "button",
|
|
3236
3712
|
onClick: handleClear,
|
|
3237
|
-
children: isSearching ? /* @__PURE__ */
|
|
3713
|
+
children: isSearching ? /* @__PURE__ */ jsx8(LoadingIcon3, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx8(CloseIcon, { className: "size-3" })
|
|
3238
3714
|
}
|
|
3239
3715
|
)
|
|
3240
3716
|
]
|
|
@@ -3259,13 +3735,13 @@ function LayoutModeToggle({
|
|
|
3259
3735
|
{ label: copy.t("arrangeCreatedLabel"), mode: "created" },
|
|
3260
3736
|
{ label: copy.t("sizeLabel"), mode: "size" }
|
|
3261
3737
|
];
|
|
3262
|
-
return /* @__PURE__ */
|
|
3738
|
+
return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs6(
|
|
3263
3739
|
"div",
|
|
3264
3740
|
{
|
|
3265
3741
|
className: "flex items-center rounded-md border border-[var(--border-1)] bg-[var(--transparency-block)] p-0.5",
|
|
3266
3742
|
role: "group",
|
|
3267
3743
|
children: [
|
|
3268
|
-
/* @__PURE__ */
|
|
3744
|
+
/* @__PURE__ */ jsx8(
|
|
3269
3745
|
LayoutModeButton,
|
|
3270
3746
|
{
|
|
3271
3747
|
active: layoutMode === "icon",
|
|
@@ -3274,10 +3750,10 @@ function LayoutModeToggle({
|
|
|
3274
3750
|
onClick: () => {
|
|
3275
3751
|
onLayoutModeChange("icon");
|
|
3276
3752
|
},
|
|
3277
|
-
children: /* @__PURE__ */
|
|
3753
|
+
children: /* @__PURE__ */ jsx8(ViewGridLinedIcon, { className: "size-4" })
|
|
3278
3754
|
}
|
|
3279
3755
|
),
|
|
3280
|
-
/* @__PURE__ */
|
|
3756
|
+
/* @__PURE__ */ jsx8(
|
|
3281
3757
|
LayoutModeButton,
|
|
3282
3758
|
{
|
|
3283
3759
|
active: layoutMode === "list",
|
|
@@ -3286,12 +3762,12 @@ function LayoutModeToggle({
|
|
|
3286
3762
|
onClick: () => {
|
|
3287
3763
|
onLayoutModeChange("list");
|
|
3288
3764
|
},
|
|
3289
|
-
children: /* @__PURE__ */
|
|
3765
|
+
children: /* @__PURE__ */ jsx8(ViewListLinedIcon, { className: "size-4" })
|
|
3290
3766
|
}
|
|
3291
3767
|
),
|
|
3292
|
-
/* @__PURE__ */
|
|
3768
|
+
/* @__PURE__ */ jsx8("span", { className: "mx-0.5 h-4 w-px bg-[var(--border-1)]", "aria-hidden": true }),
|
|
3293
3769
|
/* @__PURE__ */ jsxs6(DropdownMenu, { children: [
|
|
3294
|
-
/* @__PURE__ */
|
|
3770
|
+
/* @__PURE__ */ jsx8(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx8(
|
|
3295
3771
|
Button2,
|
|
3296
3772
|
{
|
|
3297
3773
|
"aria-label": copy.t("arrangeMenuLabel"),
|
|
@@ -3299,17 +3775,17 @@ function LayoutModeToggle({
|
|
|
3299
3775
|
size: "icon-sm",
|
|
3300
3776
|
type: "button",
|
|
3301
3777
|
variant: "ghost",
|
|
3302
|
-
children: /* @__PURE__ */
|
|
3778
|
+
children: /* @__PURE__ */ jsx8(ChevronDownIcon, { className: "size-3.5" })
|
|
3303
3779
|
}
|
|
3304
3780
|
) }),
|
|
3305
|
-
/* @__PURE__ */
|
|
3781
|
+
/* @__PURE__ */ jsx8(
|
|
3306
3782
|
DropdownMenuContent,
|
|
3307
3783
|
{
|
|
3308
3784
|
align: "end",
|
|
3309
3785
|
className: "min-w-[236px] px-1 py-1",
|
|
3310
3786
|
sideOffset: 7,
|
|
3311
3787
|
style: { zIndex: "var(--z-panel-popover)" },
|
|
3312
|
-
children: /* @__PURE__ */
|
|
3788
|
+
children: /* @__PURE__ */ jsx8(
|
|
3313
3789
|
DropdownMenuRadioGroup,
|
|
3314
3790
|
{
|
|
3315
3791
|
value: arrangeMode,
|
|
@@ -3319,8 +3795,8 @@ function LayoutModeToggle({
|
|
|
3319
3795
|
);
|
|
3320
3796
|
},
|
|
3321
3797
|
children: arrangeOptions.map((option, index) => /* @__PURE__ */ jsxs6("div", { children: [
|
|
3322
|
-
index === 1 ? /* @__PURE__ */
|
|
3323
|
-
/* @__PURE__ */
|
|
3798
|
+
index === 1 ? /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}) : null,
|
|
3799
|
+
/* @__PURE__ */ jsx8(
|
|
3324
3800
|
DropdownMenuRadioItem,
|
|
3325
3801
|
{
|
|
3326
3802
|
className: "h-8 text-sm font-normal",
|
|
@@ -3346,7 +3822,7 @@ function LayoutModeButton({
|
|
|
3346
3822
|
tooltipLabel
|
|
3347
3823
|
}) {
|
|
3348
3824
|
return /* @__PURE__ */ jsxs6(Tooltip, { children: [
|
|
3349
|
-
/* @__PURE__ */
|
|
3825
|
+
/* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx8(
|
|
3350
3826
|
Button2,
|
|
3351
3827
|
{
|
|
3352
3828
|
"aria-label": ariaLabel,
|
|
@@ -3362,7 +3838,7 @@ function LayoutModeButton({
|
|
|
3362
3838
|
children
|
|
3363
3839
|
}
|
|
3364
3840
|
) }),
|
|
3365
|
-
/* @__PURE__ */
|
|
3841
|
+
/* @__PURE__ */ jsx8(TooltipContent, { side: "bottom", children: tooltipLabel })
|
|
3366
3842
|
] });
|
|
3367
3843
|
}
|
|
3368
3844
|
function ToolbarIconButton({
|
|
@@ -3372,7 +3848,7 @@ function ToolbarIconButton({
|
|
|
3372
3848
|
onClick,
|
|
3373
3849
|
title
|
|
3374
3850
|
}) {
|
|
3375
|
-
return /* @__PURE__ */
|
|
3851
|
+
return /* @__PURE__ */ jsx8(
|
|
3376
3852
|
Button2,
|
|
3377
3853
|
{
|
|
3378
3854
|
"aria-label": ariaLabel,
|
|
@@ -3392,7 +3868,7 @@ function ToolbarActionButton({
|
|
|
3392
3868
|
disabled,
|
|
3393
3869
|
onClick
|
|
3394
3870
|
}) {
|
|
3395
|
-
return /* @__PURE__ */
|
|
3871
|
+
return /* @__PURE__ */ jsx8(
|
|
3396
3872
|
Button2,
|
|
3397
3873
|
{
|
|
3398
3874
|
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",
|
|
@@ -3412,8 +3888,8 @@ function BreadcrumbButton({
|
|
|
3412
3888
|
showSeparator
|
|
3413
3889
|
}) {
|
|
3414
3890
|
return /* @__PURE__ */ jsxs6("li", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3415
|
-
showSeparator ? /* @__PURE__ */
|
|
3416
|
-
/* @__PURE__ */
|
|
3891
|
+
showSeparator ? /* @__PURE__ */ jsx8("span", { className: "flex-none text-[var(--text-tertiary)]", children: "/" }) : null,
|
|
3892
|
+
/* @__PURE__ */ jsx8(
|
|
3417
3893
|
"button",
|
|
3418
3894
|
{
|
|
3419
3895
|
className: cn5(
|
|
@@ -3439,7 +3915,7 @@ import {
|
|
|
3439
3915
|
TooltipTrigger as TooltipTrigger2,
|
|
3440
3916
|
cn as cn6
|
|
3441
3917
|
} from "@tutti-os/ui-system";
|
|
3442
|
-
import { jsx as
|
|
3918
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3443
3919
|
function WorkspaceFileManagerSidebar({
|
|
3444
3920
|
disabled,
|
|
3445
3921
|
locationSections,
|
|
@@ -3453,14 +3929,14 @@ function WorkspaceFileManagerSidebar({
|
|
|
3453
3929
|
if (visibleSections.length === 0) {
|
|
3454
3930
|
return null;
|
|
3455
3931
|
}
|
|
3456
|
-
return /* @__PURE__ */
|
|
3932
|
+
return /* @__PURE__ */ jsx9(
|
|
3457
3933
|
"aside",
|
|
3458
3934
|
{
|
|
3459
3935
|
className: "@max-[600px]/workspace-file-manager:hidden flex shrink-0 flex-col border-r border-[var(--border-1)] bg-[var(--background-panel)]",
|
|
3460
3936
|
style: { minWidth: width, width },
|
|
3461
|
-
children: /* @__PURE__ */
|
|
3462
|
-
/* @__PURE__ */
|
|
3463
|
-
/* @__PURE__ */
|
|
3937
|
+
children: /* @__PURE__ */ jsx9(ScrollArea2, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx9(TooltipProvider2, { delayDuration: 350, children: /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-3 px-2 py-3", children: visibleSections.map((section) => /* @__PURE__ */ jsxs7("section", { className: "min-w-0", children: [
|
|
3938
|
+
/* @__PURE__ */ jsx9("h2", { className: "mb-1 px-2 text-[11px] font-medium uppercase tracking-normal text-[var(--text-tertiary)]", children: section.label }),
|
|
3939
|
+
/* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-0.5", children: section.locations.map((location) => /* @__PURE__ */ jsx9(
|
|
3464
3940
|
WorkspaceFileManagerSidebarLocation,
|
|
3465
3941
|
{
|
|
3466
3942
|
active: location.id === selectedLocationId,
|
|
@@ -3496,8 +3972,8 @@ function WorkspaceFileManagerSidebarLocation({
|
|
|
3496
3972
|
onSelectLocation(location);
|
|
3497
3973
|
},
|
|
3498
3974
|
children: [
|
|
3499
|
-
location.kind === "external" && location.iconUrl ? /* @__PURE__ */
|
|
3500
|
-
/* @__PURE__ */
|
|
3975
|
+
location.kind === "external" && location.iconUrl ? /* @__PURE__ */ jsx9(ExternalLocationIcon, { location }) : /* @__PURE__ */ jsx9(Icon, { className: "size-4 flex-none" }),
|
|
3976
|
+
/* @__PURE__ */ jsx9("span", { className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap", children: location.label })
|
|
3501
3977
|
]
|
|
3502
3978
|
}
|
|
3503
3979
|
);
|
|
@@ -3505,14 +3981,14 @@ function WorkspaceFileManagerSidebarLocation({
|
|
|
3505
3981
|
return content;
|
|
3506
3982
|
}
|
|
3507
3983
|
return /* @__PURE__ */ jsxs7(Tooltip2, { children: [
|
|
3508
|
-
/* @__PURE__ */
|
|
3509
|
-
/* @__PURE__ */
|
|
3984
|
+
/* @__PURE__ */ jsx9(TooltipTrigger2, { asChild: true, children: content }),
|
|
3985
|
+
/* @__PURE__ */ jsx9(TooltipContent2, { side: "right", children: location.contextLabel })
|
|
3510
3986
|
] });
|
|
3511
3987
|
}
|
|
3512
3988
|
function ExternalLocationIcon({
|
|
3513
3989
|
location
|
|
3514
3990
|
}) {
|
|
3515
|
-
return /* @__PURE__ */
|
|
3991
|
+
return /* @__PURE__ */ jsx9(
|
|
3516
3992
|
"img",
|
|
3517
3993
|
{
|
|
3518
3994
|
alt: "",
|
|
@@ -3523,12 +3999,12 @@ function ExternalLocationIcon({
|
|
|
3523
3999
|
}
|
|
3524
4000
|
|
|
3525
4001
|
// src/ui/useWorkspaceFileManagerArrangeMode.ts
|
|
3526
|
-
import { useCallback as
|
|
4002
|
+
import { useCallback as useCallback5, useState as useState6 } from "react";
|
|
3527
4003
|
function useWorkspaceFileManagerArrangeMode() {
|
|
3528
|
-
const [arrangeMode, setArrangeModeState] =
|
|
4004
|
+
const [arrangeMode, setArrangeModeState] = useState6(
|
|
3529
4005
|
readWorkspaceFileManagerArrangeMode
|
|
3530
4006
|
);
|
|
3531
|
-
const setArrangeMode =
|
|
4007
|
+
const setArrangeMode = useCallback5(
|
|
3532
4008
|
(nextArrangeMode) => {
|
|
3533
4009
|
setArrangeModeState(nextArrangeMode);
|
|
3534
4010
|
writeWorkspaceFileManagerArrangeMode(nextArrangeMode);
|
|
@@ -3536,270 +4012,45 @@ function useWorkspaceFileManagerArrangeMode() {
|
|
|
3536
4012
|
[]
|
|
3537
4013
|
);
|
|
3538
4014
|
return { arrangeMode, setArrangeMode };
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
|
-
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
3542
|
-
import { useCallback as
|
|
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]
|
|
4015
|
+
}
|
|
4016
|
+
|
|
4017
|
+
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
4018
|
+
import { useCallback as useCallback6, useState as useState7 } from "react";
|
|
4019
|
+
|
|
4020
|
+
// src/ui/workspaceFileManagerLayoutMode.ts
|
|
4021
|
+
var workspaceFileManagerLayoutModeStorageKey = "tutti.workspace-file-manager.layout-mode";
|
|
4022
|
+
function readWorkspaceFileManagerLayoutMode() {
|
|
4023
|
+
if (typeof window === "undefined") {
|
|
4024
|
+
return "list";
|
|
4025
|
+
}
|
|
4026
|
+
const stored = window.localStorage.getItem(
|
|
4027
|
+
workspaceFileManagerLayoutModeStorageKey
|
|
3765
4028
|
);
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
4029
|
+
return stored === "icon" ? "icon" : "list";
|
|
4030
|
+
}
|
|
4031
|
+
function writeWorkspaceFileManagerLayoutMode(layoutMode) {
|
|
4032
|
+
if (typeof window === "undefined") {
|
|
4033
|
+
return;
|
|
4034
|
+
}
|
|
4035
|
+
window.localStorage.setItem(
|
|
4036
|
+
workspaceFileManagerLayoutModeStorageKey,
|
|
4037
|
+
layoutMode
|
|
3770
4038
|
);
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
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);
|
|
3789
|
-
},
|
|
3790
|
-
[queue]
|
|
4039
|
+
}
|
|
4040
|
+
|
|
4041
|
+
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
4042
|
+
function useWorkspaceFileManagerLayoutMode() {
|
|
4043
|
+
const [layoutMode, setLayoutModeState] = useState7(
|
|
4044
|
+
readWorkspaceFileManagerLayoutMode
|
|
3791
4045
|
);
|
|
3792
|
-
const
|
|
3793
|
-
(
|
|
3794
|
-
|
|
4046
|
+
const setLayoutMode = useCallback6(
|
|
4047
|
+
(nextLayoutMode) => {
|
|
4048
|
+
setLayoutModeState(nextLayoutMode);
|
|
4049
|
+
writeWorkspaceFileManagerLayoutMode(nextLayoutMode);
|
|
3795
4050
|
},
|
|
3796
|
-
[
|
|
4051
|
+
[]
|
|
3797
4052
|
);
|
|
3798
|
-
return {
|
|
3799
|
-
iconUrlByCacheKey,
|
|
3800
|
-
reportEntryIconViewportEnter,
|
|
3801
|
-
reportEntryIconViewportLeave
|
|
3802
|
-
};
|
|
4053
|
+
return { layoutMode, setLayoutMode };
|
|
3803
4054
|
}
|
|
3804
4055
|
|
|
3805
4056
|
// src/ui/workspaceFileManagerAnalytics.ts
|
|
@@ -3810,81 +4061,8 @@ function normalizeDirectoryPath(path) {
|
|
|
3810
4061
|
return path.trim().replaceAll("\\", "/").replace(/\/+$/u, "");
|
|
3811
4062
|
}
|
|
3812
4063
|
|
|
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
4064
|
// src/ui/WorkspaceFileManager.tsx
|
|
3887
|
-
import { Fragment as Fragment3, jsx as
|
|
4065
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3888
4066
|
var workspaceFileManagerSearchDebounceMs = 180;
|
|
3889
4067
|
function WorkspaceFileManager({
|
|
3890
4068
|
className,
|
|
@@ -3913,7 +4091,7 @@ function WorkspaceFileManager({
|
|
|
3913
4091
|
const { layoutMode, setLayoutMode } = useWorkspaceFileManagerLayoutMode();
|
|
3914
4092
|
const rootView = useWorkspaceFileManagerRootView(session);
|
|
3915
4093
|
const { state: panelsState, view: panelsView } = useWorkspaceFileManagerPanelsView(session);
|
|
3916
|
-
const selectedExternalLocation =
|
|
4094
|
+
const selectedExternalLocation = useMemo4(() => {
|
|
3917
4095
|
const location = findWorkspaceFileLocationById(
|
|
3918
4096
|
rootView.locationSections,
|
|
3919
4097
|
rootView.selectedLocationId
|
|
@@ -3926,7 +4104,7 @@ function WorkspaceFileManager({
|
|
|
3926
4104
|
containerWidth,
|
|
3927
4105
|
sidebarContentMinWidth
|
|
3928
4106
|
) : workspaceFileManagerSidebarDefaultWidth;
|
|
3929
|
-
const updateSidebarWidth =
|
|
4107
|
+
const updateSidebarWidth = useCallback7(
|
|
3930
4108
|
(width) => {
|
|
3931
4109
|
const nextWidth = clampWorkspaceFileManagerSidebarWidth({
|
|
3932
4110
|
containerWidth: rootRef.current?.getBoundingClientRect().width ?? 0,
|
|
@@ -3969,7 +4147,7 @@ function WorkspaceFileManager({
|
|
|
3969
4147
|
observer.disconnect();
|
|
3970
4148
|
};
|
|
3971
4149
|
}, [hasLocationSidebar, sidebarContentMinWidth]);
|
|
3972
|
-
const handleSidebarResizePointerDown =
|
|
4150
|
+
const handleSidebarResizePointerDown = useCallback7(
|
|
3973
4151
|
(event) => {
|
|
3974
4152
|
if (event.button !== 0) {
|
|
3975
4153
|
return;
|
|
@@ -3998,7 +4176,7 @@ function WorkspaceFileManager({
|
|
|
3998
4176
|
},
|
|
3999
4177
|
[sidebarWidth]
|
|
4000
4178
|
);
|
|
4001
|
-
const handleSidebarResizePointerMove =
|
|
4179
|
+
const handleSidebarResizePointerMove = useCallback7(
|
|
4002
4180
|
(event) => {
|
|
4003
4181
|
const resize = sidebarResizeRef.current;
|
|
4004
4182
|
if (!resize || resize.pointerId !== event.pointerId) {
|
|
@@ -4010,7 +4188,7 @@ function WorkspaceFileManager({
|
|
|
4010
4188
|
},
|
|
4011
4189
|
[updateSidebarWidth]
|
|
4012
4190
|
);
|
|
4013
|
-
const handleSidebarResizePointerEnd =
|
|
4191
|
+
const handleSidebarResizePointerEnd = useCallback7(
|
|
4014
4192
|
(event) => {
|
|
4015
4193
|
const resize = sidebarResizeRef.current;
|
|
4016
4194
|
if (!resize || resize.pointerId !== event.pointerId) {
|
|
@@ -4022,7 +4200,7 @@ function WorkspaceFileManager({
|
|
|
4022
4200
|
},
|
|
4023
4201
|
[]
|
|
4024
4202
|
);
|
|
4025
|
-
const handleSidebarResizeKeyDown =
|
|
4203
|
+
const handleSidebarResizeKeyDown = useCallback7(
|
|
4026
4204
|
(event) => {
|
|
4027
4205
|
let nextWidth = null;
|
|
4028
4206
|
if (event.key === "Home") {
|
|
@@ -4115,27 +4293,30 @@ function WorkspaceFileManager({
|
|
|
4115
4293
|
selectedExternalLocation,
|
|
4116
4294
|
session
|
|
4117
4295
|
]);
|
|
4118
|
-
|
|
4119
|
-
event
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4296
|
+
const openContextMenu = useCallback7(
|
|
4297
|
+
(event, entry) => {
|
|
4298
|
+
event.preventDefault();
|
|
4299
|
+
event.stopPropagation();
|
|
4300
|
+
const menuWidth = 220;
|
|
4301
|
+
const menuHeight = 280;
|
|
4302
|
+
const x = clampContextMenuCoordinate(
|
|
4303
|
+
event.clientX,
|
|
4304
|
+
window.innerWidth,
|
|
4305
|
+
menuWidth
|
|
4306
|
+
);
|
|
4307
|
+
const y = clampContextMenuCoordinate(
|
|
4308
|
+
event.clientY,
|
|
4309
|
+
window.innerHeight,
|
|
4310
|
+
menuHeight
|
|
4311
|
+
);
|
|
4312
|
+
session.openContextMenu({
|
|
4313
|
+
entryPath: entry?.path ?? null,
|
|
4314
|
+
x,
|
|
4315
|
+
y
|
|
4316
|
+
});
|
|
4317
|
+
},
|
|
4318
|
+
[session]
|
|
4319
|
+
);
|
|
4139
4320
|
return /* @__PURE__ */ jsxs8(
|
|
4140
4321
|
"section",
|
|
4141
4322
|
{
|
|
@@ -4154,7 +4335,7 @@ function WorkspaceFileManager({
|
|
|
4154
4335
|
"--workspace-file-manager-dialog-overlay-z-index": "20"
|
|
4155
4336
|
},
|
|
4156
4337
|
children: [
|
|
4157
|
-
hasLocationSidebar ? /* @__PURE__ */
|
|
4338
|
+
hasLocationSidebar ? /* @__PURE__ */ jsx10(
|
|
4158
4339
|
WorkspaceFileManagerSidebar,
|
|
4159
4340
|
{
|
|
4160
4341
|
disabled: rootView.isBusy || panelsState.isLoading,
|
|
@@ -4169,7 +4350,7 @@ function WorkspaceFileManager({
|
|
|
4169
4350
|
}
|
|
4170
4351
|
}
|
|
4171
4352
|
) : null,
|
|
4172
|
-
hasLocationSidebar ? /* @__PURE__ */
|
|
4353
|
+
hasLocationSidebar ? /* @__PURE__ */ jsx10(
|
|
4173
4354
|
"div",
|
|
4174
4355
|
{
|
|
4175
4356
|
"aria-label": i18n.t("resizeLocationsSidebar"),
|
|
@@ -4187,8 +4368,8 @@ function WorkspaceFileManager({
|
|
|
4187
4368
|
onPointerUp: handleSidebarResizePointerEnd
|
|
4188
4369
|
}
|
|
4189
4370
|
) : null,
|
|
4190
|
-
/* @__PURE__ */
|
|
4191
|
-
/* @__PURE__ */
|
|
4371
|
+
/* @__PURE__ */ jsx10("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: selectedExternalLocation ? renderExternalLocationContent?.(selectedExternalLocation) ?? null : /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4372
|
+
/* @__PURE__ */ jsx10(
|
|
4192
4373
|
WorkspaceFileManagerToolbarContainer,
|
|
4193
4374
|
{
|
|
4194
4375
|
i18n,
|
|
@@ -4201,7 +4382,7 @@ function WorkspaceFileManager({
|
|
|
4201
4382
|
session
|
|
4202
4383
|
}
|
|
4203
4384
|
),
|
|
4204
|
-
/* @__PURE__ */
|
|
4385
|
+
/* @__PURE__ */ jsx10("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__ */ jsx10(
|
|
4205
4386
|
WorkspaceFileManagerPanelsContainer,
|
|
4206
4387
|
{
|
|
4207
4388
|
dateLocale,
|
|
@@ -4219,8 +4400,8 @@ function WorkspaceFileManager({
|
|
|
4219
4400
|
) })
|
|
4220
4401
|
] }) }),
|
|
4221
4402
|
!selectedExternalLocation ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4222
|
-
/* @__PURE__ */
|
|
4223
|
-
/* @__PURE__ */
|
|
4403
|
+
/* @__PURE__ */ jsx10(WorkspaceFileManagerDialogsContainer, { i18n, session }),
|
|
4404
|
+
/* @__PURE__ */ jsx10(
|
|
4224
4405
|
WorkspaceFileManagerContextMenuContainer,
|
|
4225
4406
|
{
|
|
4226
4407
|
resolveContextMenu,
|
|
@@ -4245,7 +4426,7 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
4245
4426
|
const { view } = useWorkspaceFileManagerToolbarView(session, i18n);
|
|
4246
4427
|
const [searchQuery, setSearchQuery] = useState8(view.searchQuery);
|
|
4247
4428
|
const submittedSearchQueryRef = useRef7(view.searchQuery);
|
|
4248
|
-
const submitSearchQuery =
|
|
4429
|
+
const submitSearchQuery = useCallback7(
|
|
4249
4430
|
(query) => {
|
|
4250
4431
|
submittedSearchQueryRef.current = query;
|
|
4251
4432
|
void session.search(query);
|
|
@@ -4270,11 +4451,11 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
4270
4451
|
clearTimeout(timer);
|
|
4271
4452
|
};
|
|
4272
4453
|
}, [searchQuery, submitSearchQuery, view.canSearch]);
|
|
4273
|
-
const handleSearchClear =
|
|
4454
|
+
const handleSearchClear = useCallback7(() => {
|
|
4274
4455
|
setSearchQuery("");
|
|
4275
4456
|
submitSearchQuery("");
|
|
4276
4457
|
}, [submitSearchQuery]);
|
|
4277
|
-
return /* @__PURE__ */
|
|
4458
|
+
return /* @__PURE__ */ jsx10(
|
|
4278
4459
|
WorkspaceFileManagerToolbar,
|
|
4279
4460
|
{
|
|
4280
4461
|
breadcrumbs: view.breadcrumbs,
|
|
@@ -4316,146 +4497,13 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
4316
4497
|
}
|
|
4317
4498
|
);
|
|
4318
4499
|
}
|
|
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
4500
|
function WorkspaceFileManagerDialogsContainer({
|
|
4453
4501
|
i18n,
|
|
4454
4502
|
session
|
|
4455
4503
|
}) {
|
|
4456
4504
|
const { state, view } = useWorkspaceFileManagerDialogsView(session);
|
|
4457
4505
|
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4458
|
-
/* @__PURE__ */
|
|
4506
|
+
/* @__PURE__ */ jsx10(
|
|
4459
4507
|
WorkspaceFileManagerCreateDialog,
|
|
4460
4508
|
{
|
|
4461
4509
|
busy: view.isBusy && state.busyAction === "create",
|
|
@@ -4472,7 +4520,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
4472
4520
|
}
|
|
4473
4521
|
}
|
|
4474
4522
|
),
|
|
4475
|
-
/* @__PURE__ */
|
|
4523
|
+
/* @__PURE__ */ jsx10(
|
|
4476
4524
|
WorkspaceFileManagerDeleteDialog,
|
|
4477
4525
|
{
|
|
4478
4526
|
busy: view.isDeleting,
|
|
@@ -4486,7 +4534,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
4486
4534
|
}
|
|
4487
4535
|
}
|
|
4488
4536
|
),
|
|
4489
|
-
/* @__PURE__ */
|
|
4537
|
+
/* @__PURE__ */ jsx10(
|
|
4490
4538
|
WorkspaceFileManagerUnsupportedDialog,
|
|
4491
4539
|
{
|
|
4492
4540
|
copy: i18n,
|