@tutti-os/workspace-file-manager 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-MDBT2GS5.js → chunk-V2LNXNYT.js} +7 -1
- package/dist/chunk-V2LNXNYT.js.map +1 -0
- package/dist/{chunk-5C34NYLK.js → chunk-ZN7X24RU.js} +208 -9
- package/dist/chunk-ZN7X24RU.js.map +1 -0
- package/dist/{fileKinds-DxnVJkSm.d.ts → fileKinds-BVOQctXh.d.ts} +28 -3
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/{index-BMBoznj4.d.ts → index-BWspwoUn.d.ts} +3 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1214 -908
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +3 -3
- package/dist/services/index.js +2 -2
- package/package.json +4 -4
- package/dist/chunk-5C34NYLK.js.map +0 -1
- package/dist/chunk-MDBT2GS5.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
classifyWorkspaceFilePreviewKind,
|
|
4
4
|
createWorkspaceFileManagerService,
|
|
5
5
|
decodeWorkspaceTextFile,
|
|
6
|
+
findWorkspaceFileEntry,
|
|
6
7
|
formatWorkspaceFileBytes,
|
|
7
8
|
formatWorkspaceFileModifiedTime,
|
|
8
9
|
isWorkspaceApplicationBundle,
|
|
@@ -25,41 +26,35 @@ import {
|
|
|
25
26
|
workspaceFilePreviewMaxBytes,
|
|
26
27
|
workspaceFileTextMaxBytes,
|
|
27
28
|
writeWorkspaceFileManagerArrangeMode
|
|
28
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ZN7X24RU.js";
|
|
29
30
|
import {
|
|
30
31
|
createWorkspaceFileManagerI18nRuntime,
|
|
31
32
|
resolveRevealInFolderLabel,
|
|
32
33
|
workspaceFileManagerI18nNamespace,
|
|
33
34
|
workspaceFileManagerI18nResources
|
|
34
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-V2LNXNYT.js";
|
|
35
36
|
|
|
36
37
|
// src/ui/WorkspaceFileManager.tsx
|
|
37
|
-
import { useEffect as
|
|
38
|
+
import { useEffect as useEffect6, useMemo as useMemo3, useRef as useRef6 } from "react";
|
|
38
39
|
import { cn as cn6 } from "@tutti-os/ui-system";
|
|
39
40
|
|
|
40
|
-
// src/ui/
|
|
41
|
+
// src/ui/WorkspaceFileManagerContextMenuContainer.tsx
|
|
42
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
43
|
+
|
|
44
|
+
// src/ui/WorkspaceFileManagerContextMenu.tsx
|
|
41
45
|
import {
|
|
42
46
|
ArrowRightIcon,
|
|
43
|
-
Button,
|
|
44
|
-
ConfirmationDialog,
|
|
45
47
|
CopyIcon,
|
|
46
48
|
DeleteIcon,
|
|
47
49
|
DownloadIcon,
|
|
48
50
|
EditIcon,
|
|
49
|
-
Dialog,
|
|
50
|
-
DialogContent,
|
|
51
|
-
DialogDescription,
|
|
52
|
-
DialogFooter,
|
|
53
|
-
DialogHeader,
|
|
54
|
-
DialogTitle,
|
|
55
51
|
EyeIcon,
|
|
56
52
|
FileLinedIcon,
|
|
57
|
-
|
|
53
|
+
ImportLinedIcon as ImportIcon,
|
|
58
54
|
LaunchIcon,
|
|
59
55
|
LocateFolderIcon,
|
|
60
56
|
MenuSurface,
|
|
61
57
|
NewWorkspaceLinedIcon,
|
|
62
|
-
UploadIcon as ImportIcon,
|
|
63
58
|
ViewportMenuSurface,
|
|
64
59
|
WebIcon,
|
|
65
60
|
cn
|
|
@@ -93,6 +88,9 @@ function clampContextMenuPosition(input) {
|
|
|
93
88
|
}
|
|
94
89
|
function estimateOpenWithSubmenuHeight(input) {
|
|
95
90
|
let itemCount = 0;
|
|
91
|
+
if (input.showOpenInFileViewer) {
|
|
92
|
+
itemCount += 1;
|
|
93
|
+
}
|
|
96
94
|
if (input.showOpenInAppBrowser) {
|
|
97
95
|
itemCount += 1;
|
|
98
96
|
}
|
|
@@ -112,7 +110,7 @@ function estimateOpenWithSubmenuHeight(input) {
|
|
|
112
110
|
return itemCount * CONTEXT_MENU_ITEM_HEIGHT_PX + CONTEXT_MENU_PADDING_PX * 2;
|
|
113
111
|
}
|
|
114
112
|
|
|
115
|
-
// src/ui/
|
|
113
|
+
// src/ui/WorkspaceFileManagerContextMenu.tsx
|
|
116
114
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
117
115
|
function WorkspaceFileManagerContextMenu({
|
|
118
116
|
busy,
|
|
@@ -125,6 +123,7 @@ function WorkspaceFileManagerContextMenu({
|
|
|
125
123
|
showExportAction,
|
|
126
124
|
showOpenInAppBrowserAction,
|
|
127
125
|
showOpenInDefaultBrowserAction,
|
|
126
|
+
showOpenInFileViewerAction,
|
|
128
127
|
showOpenWithAction,
|
|
129
128
|
showOpenWithOtherAction,
|
|
130
129
|
showRevealInFolderAction,
|
|
@@ -143,6 +142,7 @@ function WorkspaceFileManagerContextMenu({
|
|
|
143
142
|
onOpen,
|
|
144
143
|
onOpenInAppBrowser,
|
|
145
144
|
onOpenInDefaultBrowser,
|
|
145
|
+
onOpenInFileViewer,
|
|
146
146
|
onOpenWithApplication,
|
|
147
147
|
onOpenWithOtherApplication,
|
|
148
148
|
onImport,
|
|
@@ -190,6 +190,7 @@ function WorkspaceFileManagerContextMenu({
|
|
|
190
190
|
showImportAction,
|
|
191
191
|
showOpenInAppBrowserAction,
|
|
192
192
|
showOpenInDefaultBrowserAction,
|
|
193
|
+
showOpenInFileViewerAction,
|
|
193
194
|
showOpenWithAction,
|
|
194
195
|
showOpenWithOtherAction,
|
|
195
196
|
showRevealInFolderAction,
|
|
@@ -339,10 +340,12 @@ function WorkspaceFileManagerContextMenu({
|
|
|
339
340
|
resolveOpenWithApplicationIcon,
|
|
340
341
|
showOpenInAppBrowser: showOpenInAppBrowserAction,
|
|
341
342
|
showOpenInDefaultBrowser: showOpenInDefaultBrowserAction,
|
|
343
|
+
showOpenInFileViewer: showOpenInFileViewerAction,
|
|
342
344
|
showOpenWithOther: showOpenWithOtherAction,
|
|
343
345
|
onClose,
|
|
344
346
|
onOpenInAppBrowser,
|
|
345
347
|
onOpenInDefaultBrowser,
|
|
348
|
+
onOpenInFileViewer,
|
|
346
349
|
onOpenWithApplication,
|
|
347
350
|
onOpenWithOtherApplication
|
|
348
351
|
}
|
|
@@ -429,10 +432,12 @@ function OpenWithMenuItem({
|
|
|
429
432
|
resolveOpenWithApplicationIcon,
|
|
430
433
|
showOpenInAppBrowser,
|
|
431
434
|
showOpenInDefaultBrowser,
|
|
435
|
+
showOpenInFileViewer,
|
|
432
436
|
showOpenWithOther,
|
|
433
437
|
onClose,
|
|
434
438
|
onOpenInAppBrowser,
|
|
435
439
|
onOpenInDefaultBrowser,
|
|
440
|
+
onOpenInFileViewer,
|
|
436
441
|
onOpenWithApplication,
|
|
437
442
|
onOpenWithOtherApplication
|
|
438
443
|
}) {
|
|
@@ -447,6 +452,7 @@ function OpenWithMenuItem({
|
|
|
447
452
|
showExternalSection,
|
|
448
453
|
showOpenInAppBrowser,
|
|
449
454
|
showOpenInDefaultBrowser,
|
|
455
|
+
showOpenInFileViewer,
|
|
450
456
|
showOpenWithOther
|
|
451
457
|
});
|
|
452
458
|
const cancelClose = useCallback(() => {
|
|
@@ -551,6 +557,18 @@ function OpenWithMenuItem({
|
|
|
551
557
|
onPointerEnter: openSubmenu,
|
|
552
558
|
onPointerLeave: scheduleClose,
|
|
553
559
|
children: [
|
|
560
|
+
showOpenInFileViewer ? /* @__PURE__ */ jsx(
|
|
561
|
+
ContextMenuActionButton,
|
|
562
|
+
{
|
|
563
|
+
disabled: busy,
|
|
564
|
+
icon: /* @__PURE__ */ jsx(EyeIcon, { className: "size-4" }),
|
|
565
|
+
label: copy.t("openInFileViewerLabel"),
|
|
566
|
+
onClick: () => {
|
|
567
|
+
onClose();
|
|
568
|
+
void onOpenInFileViewer();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
) : null,
|
|
554
572
|
showOpenInAppBrowser ? /* @__PURE__ */ jsx(
|
|
555
573
|
ContextMenuActionButton,
|
|
556
574
|
{
|
|
@@ -619,215 +637,604 @@ function OpenWithMenuItem({
|
|
|
619
637
|
}
|
|
620
638
|
);
|
|
621
639
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
Dialog,
|
|
635
|
-
{
|
|
636
|
-
open: true,
|
|
637
|
-
onOpenChange: (nextOpen) => {
|
|
638
|
-
if (!nextOpen) {
|
|
639
|
-
onClose();
|
|
640
|
-
}
|
|
641
|
-
},
|
|
642
|
-
children: /* @__PURE__ */ jsx(DialogContent, { "aria-busy": busy, showCloseButton: false, children: /* @__PURE__ */ jsxs(
|
|
643
|
-
"form",
|
|
644
|
-
{
|
|
645
|
-
className: "grid gap-3",
|
|
646
|
-
onSubmit: (event) => {
|
|
647
|
-
event.preventDefault();
|
|
648
|
-
onConfirm();
|
|
649
|
-
},
|
|
650
|
-
children: [
|
|
651
|
-
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: dialog.kind === "directory" ? copy.t("createDirectoryLabel") : copy.t("createFileLabel") }) }),
|
|
652
|
-
/* @__PURE__ */ jsx(
|
|
653
|
-
Input,
|
|
654
|
-
{
|
|
655
|
-
autoFocus: true,
|
|
656
|
-
placeholder: dialog.kind === "directory" ? copy.t("createDirectoryPlaceholder") : copy.t("createFilePlaceholder"),
|
|
657
|
-
value: dialog.name,
|
|
658
|
-
onChange: (event) => {
|
|
659
|
-
onNameChange(event.currentTarget.value);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
),
|
|
663
|
-
dialog.errorMessage ? /* @__PURE__ */ jsx("p", { className: "text-[13px] text-[var(--state-danger)]", children: dialog.errorMessage }) : null,
|
|
664
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
665
|
-
/* @__PURE__ */ jsx(
|
|
666
|
-
Button,
|
|
667
|
-
{
|
|
668
|
-
disabled: busy,
|
|
669
|
-
size: "dialog",
|
|
670
|
-
type: "button",
|
|
671
|
-
variant: "ghost",
|
|
672
|
-
onClick: onClose,
|
|
673
|
-
children: copy.t("cancelLabel")
|
|
674
|
-
}
|
|
675
|
-
),
|
|
676
|
-
/* @__PURE__ */ jsx(Button, { disabled: busy, size: "dialog", type: "submit", children: copy.t("createActionLabel") })
|
|
677
|
-
] })
|
|
678
|
-
]
|
|
679
|
-
}
|
|
680
|
-
) })
|
|
681
|
-
}
|
|
682
|
-
);
|
|
640
|
+
|
|
641
|
+
// src/ui/useWorkspaceFileManagerService.ts
|
|
642
|
+
import { useSnapshot } from "valtio";
|
|
643
|
+
|
|
644
|
+
// src/services/internal/workspaceFileManagerViewModel.ts
|
|
645
|
+
function resolveWorkspaceFileManagerRootViewState(input) {
|
|
646
|
+
const { state } = input;
|
|
647
|
+
return {
|
|
648
|
+
canImportFromDrop: state.capabilities.canImportFromDrop,
|
|
649
|
+
currentDirectoryPath: state.currentDirectoryPath,
|
|
650
|
+
isBusy: state.busyAction !== null
|
|
651
|
+
};
|
|
683
652
|
}
|
|
684
|
-
function
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
onConfirm
|
|
690
|
-
}) {
|
|
691
|
-
if (!entry) {
|
|
692
|
-
return null;
|
|
693
|
-
}
|
|
694
|
-
return /* @__PURE__ */ jsx(
|
|
695
|
-
ConfirmationDialog,
|
|
696
|
-
{
|
|
697
|
-
cancelLabel: copy.t("cancelLabel"),
|
|
698
|
-
confirmBusy: busy,
|
|
699
|
-
confirmLabel: busy ? copy.t("deletingLabel") : copy.t("deleteLabel"),
|
|
700
|
-
description: copy.t("deleteConfirmDescription", { name: entry.name }),
|
|
701
|
-
open: true,
|
|
702
|
-
title: copy.t("deleteLabel"),
|
|
703
|
-
tone: "destructive",
|
|
704
|
-
onConfirm,
|
|
705
|
-
onOpenChange: (nextOpen) => {
|
|
706
|
-
if (!nextOpen) {
|
|
707
|
-
onClose();
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
653
|
+
function resolveWorkspaceFileManagerToolbarViewState(input) {
|
|
654
|
+
const { copy, state } = input;
|
|
655
|
+
const currentDirectoryPath = normalizeWorkspaceFilePath(
|
|
656
|
+
state.currentDirectoryPath,
|
|
657
|
+
state.root
|
|
711
658
|
);
|
|
659
|
+
return {
|
|
660
|
+
breadcrumbs: buildWorkspaceFileBreadcrumbs(
|
|
661
|
+
currentDirectoryPath,
|
|
662
|
+
copy.t("breadcrumbRootLabel"),
|
|
663
|
+
state.root
|
|
664
|
+
),
|
|
665
|
+
canGoBack: currentDirectoryPath !== normalizeWorkspaceFilePath(state.root) && state.navigationBackStack.length > 0,
|
|
666
|
+
canGoForward: state.navigationForwardStack.length > 0,
|
|
667
|
+
currentDirectoryPath,
|
|
668
|
+
isBusy: state.busyAction !== null,
|
|
669
|
+
isLoading: state.isLoading,
|
|
670
|
+
isMutating: state.isMutating,
|
|
671
|
+
isImporting: state.busyAction === "import",
|
|
672
|
+
showImportAction: state.capabilities.canImportFromPicker
|
|
673
|
+
};
|
|
712
674
|
}
|
|
713
|
-
function
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
onOpenChange: (nextOpen) => {
|
|
731
|
-
if (!nextOpen) {
|
|
732
|
-
onClose();
|
|
733
|
-
}
|
|
734
|
-
},
|
|
735
|
-
children: /* @__PURE__ */ jsxs(
|
|
736
|
-
DialogContent,
|
|
737
|
-
{
|
|
738
|
-
showCloseButton: false,
|
|
739
|
-
onEscapeKeyDown: (event) => {
|
|
740
|
-
if (isViewing) {
|
|
741
|
-
event.preventDefault();
|
|
742
|
-
}
|
|
743
|
-
},
|
|
744
|
-
onInteractOutside: (event) => {
|
|
745
|
-
if (isViewing) {
|
|
746
|
-
event.preventDefault();
|
|
747
|
-
}
|
|
748
|
-
},
|
|
749
|
-
children: [
|
|
750
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
751
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
752
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: body })
|
|
753
|
-
] }),
|
|
754
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
755
|
-
/* @__PURE__ */ jsx(
|
|
756
|
-
Button,
|
|
757
|
-
{
|
|
758
|
-
disabled: isViewing,
|
|
759
|
-
size: "dialog",
|
|
760
|
-
type: "button",
|
|
761
|
-
variant: "ghost",
|
|
762
|
-
onClick: onClose,
|
|
763
|
-
children: copy.t("closeLabel")
|
|
764
|
-
}
|
|
765
|
-
),
|
|
766
|
-
actions.map((action) => /* @__PURE__ */ jsx(
|
|
767
|
-
Button,
|
|
768
|
-
{
|
|
769
|
-
disabled: isViewing,
|
|
770
|
-
size: "dialog",
|
|
771
|
-
type: "button",
|
|
772
|
-
className: "shadow-none",
|
|
773
|
-
onClick: () => {
|
|
774
|
-
onAction(action);
|
|
775
|
-
},
|
|
776
|
-
children: action.label ?? (action.kind === "download" ? copy.t("downloadLabel") : copy.t("openLabel"))
|
|
777
|
-
},
|
|
778
|
-
action.kind
|
|
779
|
-
))
|
|
780
|
-
] })
|
|
781
|
-
]
|
|
782
|
-
}
|
|
783
|
-
)
|
|
784
|
-
}
|
|
785
|
-
);
|
|
675
|
+
function resolveWorkspaceFileManagerPanelsViewState(input) {
|
|
676
|
+
const { state } = input;
|
|
677
|
+
return {
|
|
678
|
+
canMove: state.capabilities.canMove,
|
|
679
|
+
contextMenuEntryPath: state.contextMenuEntryPath,
|
|
680
|
+
entries: state.entries,
|
|
681
|
+
error: state.error,
|
|
682
|
+
inlineRenameEntryPath: state.inlineRenameEntryPath,
|
|
683
|
+
inlineRenameValidation: state.inlineRenameValidation,
|
|
684
|
+
isLoading: state.isLoading,
|
|
685
|
+
isRenaming: state.busyAction === "rename",
|
|
686
|
+
pendingDirectoryPath: state.pendingDirectoryPath,
|
|
687
|
+
previewState: state.previewState,
|
|
688
|
+
selectedEntry: findSelectedEntry(state),
|
|
689
|
+
selectedPath: state.selectedPath,
|
|
690
|
+
showDropOverlay: state.capabilities.canImportFromDrop && state.dragDepth > 0 && state.busyAction === null
|
|
691
|
+
};
|
|
786
692
|
}
|
|
787
|
-
function
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
693
|
+
function resolveWorkspaceFileManagerDialogsViewState(input) {
|
|
694
|
+
const { state } = input;
|
|
695
|
+
const unsupportedDialogEntry = state.unsupportedDialog?.entryPath ? findEntry(state, state.unsupportedDialog.entryPath) : null;
|
|
696
|
+
return {
|
|
697
|
+
createDialog: state.createDialog,
|
|
698
|
+
deleteDialogEntry: state.deleteDialog ? findEntry(state, state.deleteDialog.entryPath) : null,
|
|
699
|
+
isBusy: state.busyAction !== null,
|
|
700
|
+
isDeleting: state.busyAction === "delete",
|
|
701
|
+
isImporting: state.busyAction === "import",
|
|
702
|
+
isRenaming: state.busyAction === "rename",
|
|
703
|
+
isViewing: state.busyAction === "view",
|
|
704
|
+
unsupportedDialog: state.unsupportedDialog ? {
|
|
705
|
+
actions: state.unsupportedDialog.actions,
|
|
706
|
+
entry: unsupportedDialogEntry ?? void 0,
|
|
707
|
+
kind: state.unsupportedDialog.kind,
|
|
708
|
+
message: state.unsupportedDialog.message,
|
|
709
|
+
title: state.unsupportedDialog.title
|
|
710
|
+
} : null,
|
|
711
|
+
importConflictDialog: state.importConflictDialog
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function resolveWorkspaceFileManagerContextMenuViewState(input) {
|
|
715
|
+
const { state } = input;
|
|
716
|
+
const contextMenuEntry = state.contextMenu?.entryPath ? findEntry(state, state.contextMenu.entryPath) : null;
|
|
717
|
+
const isContextMenuFile = contextMenuEntry?.kind === "file";
|
|
718
|
+
return {
|
|
719
|
+
contextMenu: state.contextMenu ? {
|
|
720
|
+
entry: contextMenuEntry,
|
|
721
|
+
x: state.contextMenu.x,
|
|
722
|
+
y: state.contextMenu.y
|
|
723
|
+
} : null,
|
|
724
|
+
currentDirectoryPath: state.currentDirectoryPath,
|
|
725
|
+
isBusy: state.busyAction !== null,
|
|
726
|
+
isLoading: state.isLoading,
|
|
727
|
+
isMutating: state.isMutating,
|
|
728
|
+
showCopyAction: state.capabilities.canCopy,
|
|
729
|
+
showExportAction: state.capabilities.canExport,
|
|
730
|
+
showImportAction: state.capabilities.canImportFromPicker,
|
|
731
|
+
showMoveAction: state.capabilities.canMove,
|
|
732
|
+
showOpenInAppBrowserAction: state.capabilities.canOpenInAppBrowser,
|
|
733
|
+
showOpenInDefaultBrowserAction: state.capabilities.canOpenInDefaultBrowser,
|
|
734
|
+
showOpenInFileViewerAction: contextMenuEntry !== null && isContextMenuFile && resolveWorkspaceFileActivationTarget(contextMenuEntry) !== null,
|
|
735
|
+
showOpenWithAction: state.capabilities.canOpenWith && isContextMenuFile,
|
|
736
|
+
showOpenWithOtherAction: state.capabilities.canPickOtherOpenWithApplication && isContextMenuFile,
|
|
737
|
+
showRevealInFolderAction: state.capabilities.canRevealInFolder,
|
|
738
|
+
showRenameAction: state.capabilities.canRename
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function findSelectedEntry(state) {
|
|
742
|
+
return findWorkspaceFileEntry(state, state.selectedPath);
|
|
743
|
+
}
|
|
744
|
+
function findEntry(state, entryPath) {
|
|
745
|
+
return findWorkspaceFileEntry(state, entryPath);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// src/ui/useWorkspaceFileManagerService.ts
|
|
749
|
+
function useWorkspaceFileManagerRootView(session) {
|
|
750
|
+
const state = useSnapshot(
|
|
751
|
+
session.store
|
|
752
|
+
);
|
|
753
|
+
return resolveWorkspaceFileManagerRootViewState({ state });
|
|
754
|
+
}
|
|
755
|
+
function useWorkspaceFileManagerToolbarView(session, i18n) {
|
|
756
|
+
const state = useSnapshot(
|
|
757
|
+
session.store
|
|
758
|
+
);
|
|
759
|
+
return {
|
|
760
|
+
view: resolveWorkspaceFileManagerToolbarViewState({
|
|
761
|
+
copy: i18n,
|
|
762
|
+
state
|
|
763
|
+
})
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function useWorkspaceFileManagerPanelsView(session) {
|
|
767
|
+
const state = useSnapshot(
|
|
768
|
+
session.store
|
|
769
|
+
);
|
|
770
|
+
return {
|
|
771
|
+
state,
|
|
772
|
+
view: resolveWorkspaceFileManagerPanelsViewState({
|
|
773
|
+
state
|
|
774
|
+
})
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
function useWorkspaceFileManagerDialogsView(session) {
|
|
778
|
+
const state = useSnapshot(
|
|
779
|
+
session.store
|
|
780
|
+
);
|
|
781
|
+
return {
|
|
782
|
+
state,
|
|
783
|
+
view: resolveWorkspaceFileManagerDialogsViewState({
|
|
784
|
+
state
|
|
785
|
+
})
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
function useWorkspaceFileManagerContextMenuView(session) {
|
|
789
|
+
const state = useSnapshot(
|
|
790
|
+
session.store
|
|
791
|
+
);
|
|
792
|
+
return {
|
|
793
|
+
state,
|
|
794
|
+
view: resolveWorkspaceFileManagerContextMenuViewState({
|
|
795
|
+
state
|
|
796
|
+
})
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// src/ui/WorkspaceFileManagerContextMenuContainer.tsx
|
|
801
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
802
|
+
function WorkspaceFileManagerContextMenuContainer({
|
|
803
|
+
hostOs,
|
|
804
|
+
i18n,
|
|
805
|
+
onCopyEntry,
|
|
806
|
+
onCopyPath,
|
|
807
|
+
openInAppBrowserIcon,
|
|
808
|
+
resolveOpenWithApplicationIcon,
|
|
809
|
+
session
|
|
810
|
+
}) {
|
|
811
|
+
const contextMenuRef = useRef2(null);
|
|
812
|
+
const { view } = useWorkspaceFileManagerContextMenuView(session);
|
|
813
|
+
const [openWithApplications, setOpenWithApplications] = useState2([]);
|
|
814
|
+
const [openWithLoading, setOpenWithLoading] = useState2(false);
|
|
815
|
+
useEffect2(() => {
|
|
816
|
+
const entry = view.contextMenu?.entry;
|
|
817
|
+
if (!entry || !view.showOpenWithAction) {
|
|
818
|
+
setOpenWithApplications([]);
|
|
819
|
+
setOpenWithLoading(false);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const cachedApplications = session.getCachedOpenWithApplications(entry);
|
|
823
|
+
if (cachedApplications) {
|
|
824
|
+
setOpenWithApplications(cachedApplications);
|
|
825
|
+
setOpenWithLoading(false);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
let cancelled = false;
|
|
829
|
+
setOpenWithApplications([]);
|
|
830
|
+
setOpenWithLoading(true);
|
|
831
|
+
void session.listOpenWithApplications(entry).then((applications) => {
|
|
832
|
+
if (cancelled) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
setOpenWithApplications(applications);
|
|
836
|
+
setOpenWithLoading(false);
|
|
837
|
+
}).catch(() => {
|
|
838
|
+
if (cancelled) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
setOpenWithApplications([]);
|
|
842
|
+
setOpenWithLoading(false);
|
|
843
|
+
});
|
|
844
|
+
return () => {
|
|
845
|
+
cancelled = true;
|
|
846
|
+
};
|
|
847
|
+
}, [session, view.contextMenu?.entry?.path, view.showOpenWithAction]);
|
|
848
|
+
useCloseContextMenuOnOutsideInteraction({
|
|
849
|
+
contextMenuRef,
|
|
850
|
+
isOpen: view.contextMenu !== null,
|
|
851
|
+
session
|
|
852
|
+
});
|
|
853
|
+
return /* @__PURE__ */ jsx2(
|
|
854
|
+
WorkspaceFileManagerContextMenu,
|
|
855
|
+
{
|
|
856
|
+
busy: view.isBusy || view.isLoading || view.isMutating,
|
|
857
|
+
copy: i18n,
|
|
858
|
+
contextMenu: view.contextMenu,
|
|
859
|
+
contextMenuRef,
|
|
860
|
+
showCopyAction: view.showCopyAction,
|
|
861
|
+
showImportAction: view.showImportAction,
|
|
862
|
+
showExportAction: view.showExportAction,
|
|
863
|
+
showOpenInAppBrowserAction: view.showOpenInAppBrowserAction && !!view.contextMenu?.entry && isWorkspaceFileBrowserOpenable(view.contextMenu.entry),
|
|
864
|
+
showOpenInDefaultBrowserAction: view.showOpenInDefaultBrowserAction && !!view.contextMenu?.entry && isWorkspaceFileBrowserOpenable(view.contextMenu.entry),
|
|
865
|
+
showOpenInFileViewerAction: view.showOpenInFileViewerAction,
|
|
866
|
+
showOpenWithAction: view.showOpenWithAction,
|
|
867
|
+
showOpenWithOtherAction: view.showOpenWithOtherAction,
|
|
868
|
+
showRevealInFolderAction: view.showRevealInFolderAction,
|
|
869
|
+
showRenameAction: view.showRenameAction,
|
|
870
|
+
revealInFolderLabel: resolveRevealInFolderLabel(i18n, hostOs),
|
|
871
|
+
openInAppBrowserIcon,
|
|
872
|
+
openWithApplications,
|
|
873
|
+
openWithLoading,
|
|
874
|
+
resolveOpenWithApplicationIcon,
|
|
875
|
+
onClose: () => {
|
|
876
|
+
session.closeContextMenu();
|
|
877
|
+
},
|
|
878
|
+
onCreateDirectory: () => {
|
|
879
|
+
session.openCreateDirectoryDialog();
|
|
880
|
+
},
|
|
881
|
+
onCreateFile: () => {
|
|
882
|
+
session.openCreateFileDialog();
|
|
883
|
+
},
|
|
884
|
+
onCopy: async () => {
|
|
885
|
+
const entry = view.contextMenu?.entry;
|
|
886
|
+
if (!entry) {
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
session.closeContextMenu();
|
|
890
|
+
await session.copyToClipboard(entry);
|
|
891
|
+
if (onCopyEntry) {
|
|
892
|
+
await onCopyEntry();
|
|
893
|
+
}
|
|
894
|
+
},
|
|
895
|
+
onCopyPath: async () => {
|
|
896
|
+
const path = view.contextMenu?.entry?.path;
|
|
897
|
+
if (!path) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
session.closeContextMenu();
|
|
901
|
+
if (onCopyPath) {
|
|
902
|
+
await onCopyPath(path);
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
await navigator.clipboard.writeText(path);
|
|
906
|
+
},
|
|
907
|
+
onDelete: () => {
|
|
908
|
+
const entry = view.contextMenu?.entry;
|
|
909
|
+
if (!entry) {
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
session.openDeleteDialog(entry);
|
|
913
|
+
},
|
|
914
|
+
onRename: () => {
|
|
915
|
+
const entry = view.contextMenu?.entry;
|
|
916
|
+
if (!entry) {
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
session.startInlineRename(entry);
|
|
920
|
+
},
|
|
921
|
+
onExport: async () => {
|
|
922
|
+
const entry = view.contextMenu?.entry;
|
|
923
|
+
if (!entry) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
await session.exportEntry(entry);
|
|
927
|
+
},
|
|
928
|
+
onOpen: async () => {
|
|
929
|
+
const entry = view.contextMenu?.entry;
|
|
930
|
+
if (!entry) {
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
await session.openEntry(entry);
|
|
934
|
+
},
|
|
935
|
+
onOpenInAppBrowser: async () => {
|
|
936
|
+
const entry = view.contextMenu?.entry;
|
|
937
|
+
if (!entry) {
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
await session.openFileInAppBrowser(entry);
|
|
941
|
+
},
|
|
942
|
+
onOpenInDefaultBrowser: async () => {
|
|
943
|
+
const entry = view.contextMenu?.entry;
|
|
944
|
+
if (!entry) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
await session.openFileInDefaultBrowser(entry);
|
|
948
|
+
},
|
|
949
|
+
onOpenInFileViewer: async () => {
|
|
950
|
+
const entry = view.contextMenu?.entry;
|
|
951
|
+
if (!entry) {
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
await session.openFileInFileViewer(entry);
|
|
955
|
+
},
|
|
956
|
+
onOpenWithApplication: async (applicationPath) => {
|
|
957
|
+
const entry = view.contextMenu?.entry;
|
|
958
|
+
if (!entry) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
await session.openFileWithApplication(entry, applicationPath);
|
|
962
|
+
},
|
|
963
|
+
onOpenWithOtherApplication: async () => {
|
|
964
|
+
const entry = view.contextMenu?.entry;
|
|
965
|
+
if (!entry) {
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
await session.openFileWithOtherApplication(entry);
|
|
969
|
+
},
|
|
970
|
+
onRevealInFolder: async () => {
|
|
971
|
+
const entry = view.contextMenu?.entry;
|
|
972
|
+
if (!entry) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
await session.revealEntry(entry);
|
|
976
|
+
},
|
|
977
|
+
onImport: async () => {
|
|
978
|
+
session.closeContextMenu();
|
|
979
|
+
await session.importFiles(
|
|
980
|
+
view.contextMenu?.entry?.kind === "directory" ? view.contextMenu.entry.path : view.currentDirectoryPath
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
function useCloseContextMenuOnOutsideInteraction(input) {
|
|
987
|
+
const { contextMenuRef, isOpen, session } = input;
|
|
988
|
+
useEffect2(() => {
|
|
989
|
+
if (!isOpen) {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
function handlePointerDown(event) {
|
|
993
|
+
const target = event.target;
|
|
994
|
+
if (target instanceof Node && contextMenuRef.current?.contains(target)) {
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
if (target instanceof Element && target.closest("[data-workspace-file-manager-submenu]")) {
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
session.closeContextMenu();
|
|
1001
|
+
}
|
|
1002
|
+
function handleKeyDown(event) {
|
|
1003
|
+
if (event.key === "Escape") {
|
|
1004
|
+
session.closeContextMenu();
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
window.addEventListener("pointerdown", handlePointerDown);
|
|
1008
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
1009
|
+
return () => {
|
|
1010
|
+
window.removeEventListener("pointerdown", handlePointerDown);
|
|
1011
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
1012
|
+
};
|
|
1013
|
+
}, [contextMenuRef, isOpen, session]);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// src/ui/WorkspaceFileManagerMenus.tsx
|
|
1017
|
+
import {
|
|
1018
|
+
Button,
|
|
1019
|
+
ConfirmationDialog,
|
|
1020
|
+
Dialog,
|
|
1021
|
+
DialogContent,
|
|
1022
|
+
DialogDescription,
|
|
1023
|
+
DialogFooter,
|
|
1024
|
+
DialogHeader,
|
|
1025
|
+
DialogTitle,
|
|
1026
|
+
Input
|
|
1027
|
+
} from "@tutti-os/ui-system";
|
|
1028
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1029
|
+
function WorkspaceFileManagerCreateDialog({
|
|
1030
|
+
busy,
|
|
1031
|
+
copy,
|
|
1032
|
+
dialog,
|
|
1033
|
+
onClose,
|
|
1034
|
+
onConfirm,
|
|
1035
|
+
onNameChange
|
|
1036
|
+
}) {
|
|
1037
|
+
if (!dialog) {
|
|
1038
|
+
return null;
|
|
1039
|
+
}
|
|
1040
|
+
return /* @__PURE__ */ jsx3(
|
|
1041
|
+
Dialog,
|
|
1042
|
+
{
|
|
1043
|
+
open: true,
|
|
1044
|
+
onOpenChange: (nextOpen) => {
|
|
1045
|
+
if (!nextOpen) {
|
|
1046
|
+
onClose();
|
|
1047
|
+
}
|
|
1048
|
+
},
|
|
1049
|
+
children: /* @__PURE__ */ jsx3(DialogContent, { "aria-busy": busy, showCloseButton: false, children: /* @__PURE__ */ jsxs2(
|
|
1050
|
+
"form",
|
|
1051
|
+
{
|
|
1052
|
+
className: "grid gap-3",
|
|
1053
|
+
onSubmit: (event) => {
|
|
1054
|
+
event.preventDefault();
|
|
1055
|
+
onConfirm();
|
|
1056
|
+
},
|
|
1057
|
+
children: [
|
|
1058
|
+
/* @__PURE__ */ jsx3(DialogHeader, { children: /* @__PURE__ */ jsx3(DialogTitle, { children: dialog.kind === "directory" ? copy.t("createDirectoryLabel") : copy.t("createFileLabel") }) }),
|
|
1059
|
+
/* @__PURE__ */ jsx3(
|
|
1060
|
+
Input,
|
|
1061
|
+
{
|
|
1062
|
+
autoFocus: true,
|
|
1063
|
+
placeholder: dialog.kind === "directory" ? copy.t("createDirectoryPlaceholder") : copy.t("createFilePlaceholder"),
|
|
1064
|
+
value: dialog.name,
|
|
1065
|
+
onChange: (event) => {
|
|
1066
|
+
onNameChange(event.currentTarget.value);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
),
|
|
1070
|
+
dialog.errorMessage ? /* @__PURE__ */ jsx3("p", { className: "text-[13px] text-[var(--state-danger)]", children: dialog.errorMessage }) : null,
|
|
1071
|
+
/* @__PURE__ */ jsxs2(DialogFooter, { children: [
|
|
1072
|
+
/* @__PURE__ */ jsx3(
|
|
1073
|
+
Button,
|
|
1074
|
+
{
|
|
1075
|
+
disabled: busy,
|
|
1076
|
+
size: "dialog",
|
|
1077
|
+
type: "button",
|
|
1078
|
+
variant: "ghost",
|
|
1079
|
+
onClick: onClose,
|
|
1080
|
+
children: copy.t("cancelLabel")
|
|
1081
|
+
}
|
|
1082
|
+
),
|
|
1083
|
+
/* @__PURE__ */ jsx3(Button, { disabled: busy, size: "dialog", type: "submit", children: copy.t("createActionLabel") })
|
|
1084
|
+
] })
|
|
1085
|
+
]
|
|
1086
|
+
}
|
|
1087
|
+
) })
|
|
1088
|
+
}
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
function WorkspaceFileManagerDeleteDialog({
|
|
1092
|
+
busy,
|
|
1093
|
+
copy,
|
|
1094
|
+
entry,
|
|
1095
|
+
onClose,
|
|
1096
|
+
onConfirm
|
|
1097
|
+
}) {
|
|
1098
|
+
if (!entry) {
|
|
1099
|
+
return null;
|
|
1100
|
+
}
|
|
1101
|
+
return /* @__PURE__ */ jsx3(
|
|
1102
|
+
ConfirmationDialog,
|
|
1103
|
+
{
|
|
1104
|
+
cancelLabel: copy.t("cancelLabel"),
|
|
1105
|
+
confirmBusy: busy,
|
|
1106
|
+
confirmLabel: busy ? copy.t("deletingLabel") : copy.t("deleteLabel"),
|
|
1107
|
+
description: copy.t("deleteConfirmDescription", { name: entry.name }),
|
|
1108
|
+
open: true,
|
|
1109
|
+
title: copy.t("deleteLabel"),
|
|
1110
|
+
tone: "destructive",
|
|
1111
|
+
onConfirm,
|
|
1112
|
+
onOpenChange: (nextOpen) => {
|
|
1113
|
+
if (!nextOpen) {
|
|
1114
|
+
onClose();
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
function WorkspaceFileManagerUnsupportedDialog({
|
|
1121
|
+
copy,
|
|
1122
|
+
dialog,
|
|
1123
|
+
isViewing,
|
|
1124
|
+
onAction,
|
|
1125
|
+
onClose
|
|
1126
|
+
}) {
|
|
1127
|
+
if (!dialog) {
|
|
1128
|
+
return null;
|
|
1129
|
+
}
|
|
1130
|
+
const title = dialog.title ?? (dialog.kind === "import" ? copy.t("unsupportedImportTitle") : copy.t("unsupportedViewTitle"));
|
|
1131
|
+
const body = dialog.message ?? (dialog.kind === "import" ? copy.t("unsupportedImportBody") : copy.t("unsupportedViewBody", { name: dialog.entry?.name ?? "" }));
|
|
1132
|
+
const actions = dialog.actions?.filter((action) => action.kind !== "none") ?? [];
|
|
1133
|
+
return /* @__PURE__ */ jsx3(
|
|
1134
|
+
Dialog,
|
|
1135
|
+
{
|
|
1136
|
+
open: true,
|
|
1137
|
+
onOpenChange: (nextOpen) => {
|
|
1138
|
+
if (!nextOpen) {
|
|
1139
|
+
onClose();
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1143
|
+
DialogContent,
|
|
1144
|
+
{
|
|
1145
|
+
showCloseButton: false,
|
|
1146
|
+
onEscapeKeyDown: (event) => {
|
|
1147
|
+
if (isViewing) {
|
|
1148
|
+
event.preventDefault();
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1151
|
+
onInteractOutside: (event) => {
|
|
1152
|
+
if (isViewing) {
|
|
1153
|
+
event.preventDefault();
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
children: [
|
|
1157
|
+
/* @__PURE__ */ jsxs2(DialogHeader, { children: [
|
|
1158
|
+
/* @__PURE__ */ jsx3(DialogTitle, { children: title }),
|
|
1159
|
+
/* @__PURE__ */ jsx3(DialogDescription, { children: body })
|
|
1160
|
+
] }),
|
|
1161
|
+
/* @__PURE__ */ jsxs2(DialogFooter, { children: [
|
|
1162
|
+
/* @__PURE__ */ jsx3(
|
|
1163
|
+
Button,
|
|
1164
|
+
{
|
|
1165
|
+
disabled: isViewing,
|
|
1166
|
+
size: "dialog",
|
|
1167
|
+
type: "button",
|
|
1168
|
+
variant: "ghost",
|
|
1169
|
+
onClick: onClose,
|
|
1170
|
+
children: copy.t("closeLabel")
|
|
1171
|
+
}
|
|
1172
|
+
),
|
|
1173
|
+
actions.map((action) => /* @__PURE__ */ jsx3(
|
|
1174
|
+
Button,
|
|
1175
|
+
{
|
|
1176
|
+
disabled: isViewing,
|
|
1177
|
+
size: "dialog",
|
|
1178
|
+
type: "button",
|
|
1179
|
+
className: "shadow-none",
|
|
1180
|
+
onClick: () => {
|
|
1181
|
+
onAction(action);
|
|
1182
|
+
},
|
|
1183
|
+
children: action.label ?? (action.kind === "download" ? copy.t("downloadLabel") : copy.t("openLabel"))
|
|
1184
|
+
},
|
|
1185
|
+
action.kind
|
|
1186
|
+
))
|
|
1187
|
+
] })
|
|
1188
|
+
]
|
|
1189
|
+
}
|
|
1190
|
+
)
|
|
1191
|
+
}
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
function WorkspaceFileManagerImportConflictDialog({
|
|
1195
|
+
busy,
|
|
1196
|
+
copy,
|
|
1197
|
+
dialog,
|
|
1198
|
+
onClose,
|
|
1199
|
+
onConfirm
|
|
1200
|
+
}) {
|
|
1201
|
+
if (!dialog) {
|
|
1202
|
+
return null;
|
|
1203
|
+
}
|
|
1204
|
+
const hasBlockedConflict = dialog.conflicts.some(
|
|
1205
|
+
(conflict) => conflict.conflictKind === "type_mismatch"
|
|
1206
|
+
);
|
|
1207
|
+
return /* @__PURE__ */ jsxs2(
|
|
1208
|
+
ConfirmationDialog,
|
|
1209
|
+
{
|
|
1210
|
+
cancelLabel: hasBlockedConflict ? copy.t("closeLabel") : copy.t("cancelLabel"),
|
|
1211
|
+
className: "max-w-lg",
|
|
1212
|
+
confirmBusy: busy,
|
|
1213
|
+
confirmLabel: hasBlockedConflict ? copy.t("closeLabel") : copy.t("importConflictReplaceLabel"),
|
|
1214
|
+
description: hasBlockedConflict ? copy.t("importTypeConflictDescription", {
|
|
1215
|
+
count: dialog.conflicts.length
|
|
1216
|
+
}) : copy.t("importConflictDescription", {
|
|
1217
|
+
count: dialog.conflicts.length
|
|
1218
|
+
}),
|
|
1219
|
+
hideConfirmButton: hasBlockedConflict,
|
|
1220
|
+
open: true,
|
|
1221
|
+
title: hasBlockedConflict ? copy.t("importTypeConflictTitle") : copy.t("importConflictTitle"),
|
|
1222
|
+
tone: hasBlockedConflict ? "default" : "destructive",
|
|
1223
|
+
onConfirm: hasBlockedConflict ? onClose : onConfirm,
|
|
1224
|
+
onOpenChange: (nextOpen) => {
|
|
1225
|
+
if (!nextOpen) {
|
|
1226
|
+
onClose();
|
|
1227
|
+
}
|
|
1228
|
+
},
|
|
1229
|
+
children: [
|
|
1230
|
+
/* @__PURE__ */ jsx3(ImportConflictSummary, { copy, dialog }),
|
|
1231
|
+
/* @__PURE__ */ jsx3("div", { className: "max-h-60 overflow-auto rounded-lg border border-[var(--border-1)] bg-transparency-block", children: /* @__PURE__ */ jsx3("div", { className: "divide-y divide-[var(--border-1)]", children: dialog.conflicts.map((conflict) => /* @__PURE__ */ jsxs2(
|
|
1232
|
+
"div",
|
|
1233
|
+
{
|
|
1234
|
+
className: "flex flex-col gap-1 px-4 py-3 text-[13px]",
|
|
1235
|
+
children: [
|
|
1236
|
+
/* @__PURE__ */ jsx3("span", { className: "font-medium text-[var(--text-primary)]", children: conflict.name }),
|
|
1237
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-[11px] text-[var(--text-secondary)]", children: [
|
|
831
1238
|
copy.t("importConflictReviewLabel"),
|
|
832
1239
|
":",
|
|
833
1240
|
" ",
|
|
@@ -881,7 +1288,7 @@ function ImportConflictSummary({
|
|
|
881
1288
|
if (summaryItems.length === 0) {
|
|
882
1289
|
return null;
|
|
883
1290
|
}
|
|
884
|
-
return /* @__PURE__ */
|
|
1291
|
+
return /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-2 text-[11px] text-[var(--text-secondary)]", children: summaryItems.map((item) => /* @__PURE__ */ jsx3(
|
|
885
1292
|
"span",
|
|
886
1293
|
{
|
|
887
1294
|
className: "rounded-md border border-[var(--border-1)] px-2 py-1",
|
|
@@ -903,6 +1310,7 @@ function importSummaryReasonCopyKey(reason) {
|
|
|
903
1310
|
|
|
904
1311
|
// src/ui/WorkspaceFileManagerPanels.tsx
|
|
905
1312
|
import {
|
|
1313
|
+
ArrowRightIcon as ArrowRightIcon2,
|
|
906
1314
|
FileCodeIcon as FileCodeIcon2,
|
|
907
1315
|
FileTextIcon as FileTextIcon2,
|
|
908
1316
|
LoadingIcon as LoadingIcon2,
|
|
@@ -913,15 +1321,16 @@ import {
|
|
|
913
1321
|
import { WorkspaceFilePreviewSurface as SharedWorkspaceFilePreviewSurface } from "@tutti-os/workspace-file-preview/react";
|
|
914
1322
|
import {
|
|
915
1323
|
useCallback as useCallback2,
|
|
916
|
-
useEffect as
|
|
1324
|
+
useEffect as useEffect4,
|
|
917
1325
|
useLayoutEffect as useLayoutEffect3,
|
|
918
|
-
|
|
919
|
-
|
|
1326
|
+
useMemo,
|
|
1327
|
+
useRef as useRef5,
|
|
1328
|
+
useState as useState3
|
|
920
1329
|
} from "react";
|
|
921
1330
|
|
|
922
1331
|
// src/ui/WorkspaceFileManagerIconGrid.tsx
|
|
923
1332
|
import { cn as cn3 } from "@tutti-os/ui-system";
|
|
924
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
1333
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef4 } from "react";
|
|
925
1334
|
|
|
926
1335
|
// src/ui/WorkspaceFileEntryIcon.tsx
|
|
927
1336
|
import {
|
|
@@ -931,8 +1340,8 @@ import {
|
|
|
931
1340
|
VideoFileIcon,
|
|
932
1341
|
cn as cn2
|
|
933
1342
|
} from "@tutti-os/ui-system";
|
|
934
|
-
import { useEffect as
|
|
935
|
-
import { jsx as
|
|
1343
|
+
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
1344
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
936
1345
|
var workspaceArchiveFallbackIconUrl = new URL(
|
|
937
1346
|
"../assets/workspace-archive-fallback.png",
|
|
938
1347
|
import.meta.url
|
|
@@ -959,10 +1368,10 @@ function WorkspaceFileEntryIcon({
|
|
|
959
1368
|
const isAppBundle = isWorkspaceApplicationBundle(entry);
|
|
960
1369
|
const cacheKey = resolveWorkspaceFileEntryIconCacheKey(entry);
|
|
961
1370
|
const iconUrl = iconUrlByCacheKey?.get(cacheKey) ?? null;
|
|
962
|
-
const frameRef =
|
|
963
|
-
const visibleEntryRef =
|
|
964
|
-
const visibleEntryCacheKeyRef =
|
|
965
|
-
|
|
1371
|
+
const frameRef = useRef3(null);
|
|
1372
|
+
const visibleEntryRef = useRef3(null);
|
|
1373
|
+
const visibleEntryCacheKeyRef = useRef3(null);
|
|
1374
|
+
useEffect3(() => {
|
|
966
1375
|
function reportViewportLeave() {
|
|
967
1376
|
const visibleEntry = visibleEntryRef.current;
|
|
968
1377
|
if (!visibleEntry) {
|
|
@@ -1021,7 +1430,7 @@ function WorkspaceFileEntryIcon({
|
|
|
1021
1430
|
reportViewportLeave();
|
|
1022
1431
|
};
|
|
1023
1432
|
}, [cacheKey, entry, isEnteringDirectory, onViewportLeave, onViewportEnter]);
|
|
1024
|
-
return /* @__PURE__ */
|
|
1433
|
+
return /* @__PURE__ */ jsx4(
|
|
1025
1434
|
"span",
|
|
1026
1435
|
{
|
|
1027
1436
|
ref: frameRef,
|
|
@@ -1030,12 +1439,12 @@ function WorkspaceFileEntryIcon({
|
|
|
1030
1439
|
frameClassName,
|
|
1031
1440
|
isEnteringDirectory ? "text-[var(--text-tertiary)]" : entryIconColorClassName(visualKind, isAppBundle)
|
|
1032
1441
|
),
|
|
1033
|
-
children: isEnteringDirectory ? /* @__PURE__ */
|
|
1442
|
+
children: isEnteringDirectory ? /* @__PURE__ */ jsx4(
|
|
1034
1443
|
LoadingIcon,
|
|
1035
1444
|
{
|
|
1036
1445
|
className: cn2(loadingIconClassName ?? iconClassName, "animate-spin")
|
|
1037
1446
|
}
|
|
1038
|
-
) : iconUrl ? /* @__PURE__ */
|
|
1447
|
+
) : iconUrl ? /* @__PURE__ */ jsx4(
|
|
1039
1448
|
"img",
|
|
1040
1449
|
{
|
|
1041
1450
|
alt: "",
|
|
@@ -1048,7 +1457,7 @@ function WorkspaceFileEntryIcon({
|
|
|
1048
1457
|
loading: "lazy",
|
|
1049
1458
|
src: iconUrl
|
|
1050
1459
|
}
|
|
1051
|
-
) : /* @__PURE__ */
|
|
1460
|
+
) : /* @__PURE__ */ jsx4(
|
|
1052
1461
|
DefaultEntryIcon,
|
|
1053
1462
|
{
|
|
1054
1463
|
entry,
|
|
@@ -1079,13 +1488,13 @@ function DefaultEntryIcon({
|
|
|
1079
1488
|
}) {
|
|
1080
1489
|
const vectorIconClassName = vectorFallbackIconClassName(iconClassName);
|
|
1081
1490
|
if (isWorkspaceApplicationBundle(entry)) {
|
|
1082
|
-
return /* @__PURE__ */
|
|
1491
|
+
return /* @__PURE__ */ jsx4(FileTextIcon, { className: vectorIconClassName });
|
|
1083
1492
|
}
|
|
1084
1493
|
if (shouldUseWorkspaceFileArchiveIcon(entry)) {
|
|
1085
|
-
return /* @__PURE__ */
|
|
1494
|
+
return /* @__PURE__ */ jsx4(WorkspaceArchiveFallbackIcon, { className: iconClassName });
|
|
1086
1495
|
}
|
|
1087
1496
|
if (shouldUseWorkspaceFileExtensionDocumentIcon(entry)) {
|
|
1088
|
-
return /* @__PURE__ */
|
|
1497
|
+
return /* @__PURE__ */ jsx4(
|
|
1089
1498
|
ExtensionDocumentIcon,
|
|
1090
1499
|
{
|
|
1091
1500
|
entry,
|
|
@@ -1095,20 +1504,20 @@ function DefaultEntryIcon({
|
|
|
1095
1504
|
}
|
|
1096
1505
|
switch (visualKind) {
|
|
1097
1506
|
case "directory":
|
|
1098
|
-
return /* @__PURE__ */
|
|
1507
|
+
return /* @__PURE__ */ jsx4(WorkspaceFolderFallbackIcon, { className: iconClassName });
|
|
1099
1508
|
case "image":
|
|
1100
|
-
return /* @__PURE__ */
|
|
1509
|
+
return /* @__PURE__ */ jsx4(WorkspaceImageFallbackIcon, { className: iconClassName });
|
|
1101
1510
|
case "video":
|
|
1102
|
-
return /* @__PURE__ */
|
|
1511
|
+
return /* @__PURE__ */ jsx4(VideoFileIcon, { className: vectorIconClassName });
|
|
1103
1512
|
case "markdown":
|
|
1104
1513
|
case "document":
|
|
1105
|
-
return /* @__PURE__ */
|
|
1514
|
+
return /* @__PURE__ */ jsx4(FileTextIcon, { className: vectorIconClassName });
|
|
1106
1515
|
case "code":
|
|
1107
|
-
return /* @__PURE__ */
|
|
1516
|
+
return /* @__PURE__ */ jsx4(FileCodeIcon, { className: vectorIconClassName });
|
|
1108
1517
|
case "binary":
|
|
1109
|
-
return /* @__PURE__ */
|
|
1518
|
+
return /* @__PURE__ */ jsx4(FileTextIcon, { className: vectorIconClassName });
|
|
1110
1519
|
default:
|
|
1111
|
-
return /* @__PURE__ */
|
|
1520
|
+
return /* @__PURE__ */ jsx4(FileTextIcon, { className: vectorIconClassName });
|
|
1112
1521
|
}
|
|
1113
1522
|
}
|
|
1114
1523
|
function vectorFallbackIconClassName(iconClassName) {
|
|
@@ -1117,7 +1526,7 @@ function vectorFallbackIconClassName(iconClassName) {
|
|
|
1117
1526
|
function WorkspaceFolderFallbackIcon({
|
|
1118
1527
|
className
|
|
1119
1528
|
}) {
|
|
1120
|
-
return /* @__PURE__ */
|
|
1529
|
+
return /* @__PURE__ */ jsx4(
|
|
1121
1530
|
"img",
|
|
1122
1531
|
{
|
|
1123
1532
|
alt: "",
|
|
@@ -1132,7 +1541,7 @@ function WorkspaceFolderFallbackIcon({
|
|
|
1132
1541
|
function WorkspaceArchiveFallbackIcon({
|
|
1133
1542
|
className
|
|
1134
1543
|
}) {
|
|
1135
|
-
return /* @__PURE__ */
|
|
1544
|
+
return /* @__PURE__ */ jsx4(
|
|
1136
1545
|
"img",
|
|
1137
1546
|
{
|
|
1138
1547
|
alt: "",
|
|
@@ -1147,7 +1556,7 @@ function WorkspaceArchiveFallbackIcon({
|
|
|
1147
1556
|
function WorkspaceImageFallbackIcon({
|
|
1148
1557
|
className
|
|
1149
1558
|
}) {
|
|
1150
|
-
return /* @__PURE__ */
|
|
1559
|
+
return /* @__PURE__ */ jsx4(
|
|
1151
1560
|
"img",
|
|
1152
1561
|
{
|
|
1153
1562
|
alt: "",
|
|
@@ -1165,15 +1574,15 @@ function ExtensionDocumentIcon({
|
|
|
1165
1574
|
}) {
|
|
1166
1575
|
const extension = resolveWorkspaceFileExtension(entry.name).slice(0, 5).toUpperCase();
|
|
1167
1576
|
const showExtension = extension.length > 0 && !iconClassName.includes("size-4");
|
|
1168
|
-
return /* @__PURE__ */
|
|
1577
|
+
return /* @__PURE__ */ jsxs3(
|
|
1169
1578
|
"span",
|
|
1170
1579
|
{
|
|
1171
1580
|
"aria-hidden": "true",
|
|
1172
1581
|
className: cn2("relative inline-block overflow-visible", iconClassName),
|
|
1173
1582
|
children: [
|
|
1174
|
-
/* @__PURE__ */
|
|
1175
|
-
/* @__PURE__ */
|
|
1176
|
-
showExtension ? /* @__PURE__ */
|
|
1583
|
+
/* @__PURE__ */ jsx4("span", { className: "absolute inset-[5%] rounded-[6px] border border-black/10 bg-linear-to-br from-white via-[#f8f8f8] to-[#ececec]" }),
|
|
1584
|
+
/* @__PURE__ */ jsx4("span", { className: "absolute top-[5%] right-[5%] h-[28%] w-[28%] overflow-hidden rounded-tr-[6px]", children: /* @__PURE__ */ jsx4("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]" }) }),
|
|
1585
|
+
showExtension ? /* @__PURE__ */ jsx4("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
|
|
1177
1586
|
]
|
|
1178
1587
|
}
|
|
1179
1588
|
);
|
|
@@ -1202,7 +1611,7 @@ function workspaceFileManagerIconGridFrameClassName() {
|
|
|
1202
1611
|
}
|
|
1203
1612
|
|
|
1204
1613
|
// src/ui/WorkspaceFileManagerIconGrid.tsx
|
|
1205
|
-
import { jsx as
|
|
1614
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1206
1615
|
function WorkspaceFileManagerIconGrid({
|
|
1207
1616
|
contextMenuEntryPath,
|
|
1208
1617
|
copy,
|
|
@@ -1227,14 +1636,14 @@ function WorkspaceFileManagerIconGrid({
|
|
|
1227
1636
|
onEntryClick,
|
|
1228
1637
|
onEntryPointerDown
|
|
1229
1638
|
}) {
|
|
1230
|
-
return /* @__PURE__ */
|
|
1639
|
+
return /* @__PURE__ */ jsx5(
|
|
1231
1640
|
"div",
|
|
1232
1641
|
{
|
|
1233
1642
|
className: "grid auto-rows-min content-start items-start gap-x-2 gap-y-6 px-4 py-4",
|
|
1234
1643
|
style: {
|
|
1235
1644
|
gridTemplateColumns: `repeat(auto-fill, minmax(${workspaceFileManagerIconGridLayout.tileMinWidthPx}px, 1fr))`
|
|
1236
1645
|
},
|
|
1237
|
-
children: entries.map((entry) => /* @__PURE__ */
|
|
1646
|
+
children: entries.map((entry) => /* @__PURE__ */ jsx5(
|
|
1238
1647
|
WorkspaceFileManagerIconTile,
|
|
1239
1648
|
{
|
|
1240
1649
|
contextMenuActive: contextMenuEntryPath === entry.path,
|
|
@@ -1289,7 +1698,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1289
1698
|
onClick,
|
|
1290
1699
|
onPointerDown
|
|
1291
1700
|
}) {
|
|
1292
|
-
const buttonRef =
|
|
1701
|
+
const buttonRef = useRef4(null);
|
|
1293
1702
|
const nameParts = splitWorkspaceFileName(entry.name);
|
|
1294
1703
|
useLayoutEffect2(() => {
|
|
1295
1704
|
if (!selected) {
|
|
@@ -1308,7 +1717,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1308
1717
|
moveDragSource && "opacity-55",
|
|
1309
1718
|
moveDragTarget && "bg-[var(--accent-bg)] text-[var(--text-primary)] outline outline-1 -outline-offset-1 outline-[var(--border-focus)]"
|
|
1310
1719
|
);
|
|
1311
|
-
const iconGraphic = /* @__PURE__ */
|
|
1720
|
+
const iconGraphic = /* @__PURE__ */ jsx5(
|
|
1312
1721
|
WorkspaceFileEntryIcon,
|
|
1313
1722
|
{
|
|
1314
1723
|
entry,
|
|
@@ -1322,7 +1731,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1322
1731
|
}
|
|
1323
1732
|
);
|
|
1324
1733
|
if (isInlineRenaming) {
|
|
1325
|
-
return /* @__PURE__ */
|
|
1734
|
+
return /* @__PURE__ */ jsxs4(
|
|
1326
1735
|
"div",
|
|
1327
1736
|
{
|
|
1328
1737
|
"aria-label": entry.name,
|
|
@@ -1330,7 +1739,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1330
1739
|
"data-workspace-file-entry-path": entry.path,
|
|
1331
1740
|
children: [
|
|
1332
1741
|
iconGraphic,
|
|
1333
|
-
/* @__PURE__ */
|
|
1742
|
+
/* @__PURE__ */ jsx5(
|
|
1334
1743
|
IconTileRenameInput,
|
|
1335
1744
|
{
|
|
1336
1745
|
copy,
|
|
@@ -1346,7 +1755,7 @@ function WorkspaceFileManagerIconTile({
|
|
|
1346
1755
|
}
|
|
1347
1756
|
);
|
|
1348
1757
|
}
|
|
1349
|
-
return /* @__PURE__ */
|
|
1758
|
+
return /* @__PURE__ */ jsxs4(
|
|
1350
1759
|
"button",
|
|
1351
1760
|
{
|
|
1352
1761
|
"aria-label": entry.name,
|
|
@@ -1373,9 +1782,9 @@ function WorkspaceFileManagerIconTile({
|
|
|
1373
1782
|
},
|
|
1374
1783
|
children: [
|
|
1375
1784
|
iconGraphic,
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1378
|
-
nameParts.end ? /* @__PURE__ */
|
|
1785
|
+
/* @__PURE__ */ jsxs4("span", { className: "line-clamp-2 w-full break-all text-[13px] leading-[18px] text-[var(--text-primary)]", children: [
|
|
1786
|
+
/* @__PURE__ */ jsx5("span", { children: nameParts.start }),
|
|
1787
|
+
nameParts.end ? /* @__PURE__ */ jsx5("span", { children: nameParts.end }) : null
|
|
1379
1788
|
] })
|
|
1380
1789
|
]
|
|
1381
1790
|
}
|
|
@@ -1392,7 +1801,7 @@ function IconTileRenameInput({
|
|
|
1392
1801
|
}) {
|
|
1393
1802
|
const nameParts = splitWorkspaceFileName(entry.name);
|
|
1394
1803
|
const hasFileExtension = nameParts.end.length > 0 && nameParts.end.startsWith(".");
|
|
1395
|
-
const inputRef =
|
|
1804
|
+
const inputRef = useRef4(null);
|
|
1396
1805
|
useLayoutEffect2(() => {
|
|
1397
1806
|
const input = inputRef.current;
|
|
1398
1807
|
if (!input) {
|
|
@@ -1406,8 +1815,8 @@ function IconTileRenameInput({
|
|
|
1406
1815
|
}
|
|
1407
1816
|
}, [hasFileExtension, nameParts.start.length]);
|
|
1408
1817
|
const validationMessage = inlineRenameValidation === "required" ? copy.t("createNameRequired") : inlineRenameValidation === "invalid" ? copy.t("createNameInvalid") : null;
|
|
1409
|
-
return /* @__PURE__ */
|
|
1410
|
-
/* @__PURE__ */
|
|
1818
|
+
return /* @__PURE__ */ jsxs4("span", { className: "flex w-full min-w-0 flex-col gap-0.5", children: [
|
|
1819
|
+
/* @__PURE__ */ jsx5(
|
|
1411
1820
|
"input",
|
|
1412
1821
|
{
|
|
1413
1822
|
"aria-invalid": inlineRenameValidation !== null,
|
|
@@ -1438,12 +1847,12 @@ function IconTileRenameInput({
|
|
|
1438
1847
|
}
|
|
1439
1848
|
}
|
|
1440
1849
|
),
|
|
1441
|
-
validationMessage ? /* @__PURE__ */
|
|
1850
|
+
validationMessage ? /* @__PURE__ */ jsx5("span", { className: "text-[10px] leading-3 text-[var(--state-danger)]", children: validationMessage }) : null
|
|
1442
1851
|
] });
|
|
1443
1852
|
}
|
|
1444
1853
|
|
|
1445
1854
|
// src/ui/WorkspaceFileManagerPanels.tsx
|
|
1446
|
-
import { Fragment as Fragment2, jsx as
|
|
1855
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1447
1856
|
var workspaceFileManagerTableGridClassName = "grid-cols-[minmax(0,_1fr)_148px_96px]";
|
|
1448
1857
|
var workspaceFileManagerTableGridStyle = {
|
|
1449
1858
|
gridTemplateColumns: "minmax(0, 1fr) 148px 96px"
|
|
@@ -1485,6 +1894,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1485
1894
|
selectedPath,
|
|
1486
1895
|
state,
|
|
1487
1896
|
showDropOverlay,
|
|
1897
|
+
treeRows,
|
|
1488
1898
|
onBlankContextMenu,
|
|
1489
1899
|
onCancelInlineRename,
|
|
1490
1900
|
onClearInlineRenameValidation,
|
|
@@ -1493,23 +1903,28 @@ function WorkspaceFileManagerPanels({
|
|
|
1493
1903
|
onEntryDragStart,
|
|
1494
1904
|
onMoveEntry,
|
|
1495
1905
|
onOpenEntry,
|
|
1496
|
-
onSelect
|
|
1906
|
+
onSelect,
|
|
1907
|
+
onToggleDirectoryExpanded
|
|
1497
1908
|
}) {
|
|
1498
1909
|
const { rootRef } = useWorkspaceFileManagerStackedLayout(
|
|
1499
1910
|
workspaceFileManagerStackedBreakpoint
|
|
1500
1911
|
);
|
|
1501
|
-
const previewResizeRef =
|
|
1502
|
-
const [previewPaneWidth, setPreviewPaneWidth] =
|
|
1912
|
+
const previewResizeRef = useRef5(null);
|
|
1913
|
+
const [previewPaneWidth, setPreviewPaneWidth] = useState3(
|
|
1503
1914
|
workspaceFileManagerPreviewDefaultWidth
|
|
1504
1915
|
);
|
|
1505
|
-
const [moveDragPreview, setMoveDragPreview] =
|
|
1506
|
-
const lastEntryClickRef =
|
|
1916
|
+
const [moveDragPreview, setMoveDragPreview] = useState3(null);
|
|
1917
|
+
const lastEntryClickRef = useRef5(
|
|
1507
1918
|
null
|
|
1508
1919
|
);
|
|
1509
|
-
const moveDragAutoScrollRef =
|
|
1510
|
-
const moveDragRef =
|
|
1511
|
-
const suppressNextClickRef =
|
|
1512
|
-
const
|
|
1920
|
+
const moveDragAutoScrollRef = useRef5(null);
|
|
1921
|
+
const moveDragRef = useRef5(null);
|
|
1922
|
+
const suppressNextClickRef = useRef5(false);
|
|
1923
|
+
const moveTargetEntries = useMemo(
|
|
1924
|
+
() => layoutMode === "list" ? treeRows.flatMap((row) => row.kind === "entry" ? [row.entry] : []) : state.entries,
|
|
1925
|
+
[layoutMode, state.entries, treeRows]
|
|
1926
|
+
);
|
|
1927
|
+
const entriesRef = useRef5(moveTargetEntries);
|
|
1513
1928
|
const nativeEntryDragEnabled = onEntryDragStart !== void 0 && (entryDragMode === "external" || entryDragMode === void 0 && !canMove);
|
|
1514
1929
|
const internalMoveEnabled = canMove && !nativeEntryDragEnabled;
|
|
1515
1930
|
const dateColumnLabel = resolveWorkspaceFileManagerDateColumnLabel(
|
|
@@ -1623,11 +2038,11 @@ function WorkspaceFileManagerPanels({
|
|
|
1623
2038
|
},
|
|
1624
2039
|
[entrySelectionEnabled, onOpenEntry, onSelect, shouldSuppressEntryClick]
|
|
1625
2040
|
);
|
|
1626
|
-
|
|
2041
|
+
useEffect4(() => {
|
|
1627
2042
|
lastEntryClickRef.current = null;
|
|
1628
|
-
entriesRef.current =
|
|
1629
|
-
}, [
|
|
1630
|
-
|
|
2043
|
+
entriesRef.current = moveTargetEntries;
|
|
2044
|
+
}, [moveTargetEntries]);
|
|
2045
|
+
useEffect4(() => {
|
|
1631
2046
|
function handleDocumentPointerMove(event) {
|
|
1632
2047
|
const drag = moveDragRef.current;
|
|
1633
2048
|
if (!drag) {
|
|
@@ -1793,7 +2208,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1793
2208
|
},
|
|
1794
2209
|
[]
|
|
1795
2210
|
);
|
|
1796
|
-
const tablePanel = /* @__PURE__ */
|
|
2211
|
+
const tablePanel = /* @__PURE__ */ jsx6(
|
|
1797
2212
|
"div",
|
|
1798
2213
|
{
|
|
1799
2214
|
className: cn4(
|
|
@@ -1801,7 +2216,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1801
2216
|
useStackedPreview ? "h-[44%] max-h-[48%] flex-none" : "flex-1"
|
|
1802
2217
|
),
|
|
1803
2218
|
onContextMenu: handleTablePanelContextMenu,
|
|
1804
|
-
children: state.error ? /* @__PURE__ */
|
|
2219
|
+
children: state.error ? /* @__PURE__ */ jsx6(FeedbackState, { message: state.error }) : state.isLoading && state.entries.length === 0 ? /* @__PURE__ */ jsx6(FeedbackState, { message: copy.t("loading") }) : state.entries.length === 0 ? /* @__PURE__ */ jsx6(FeedbackState, { message: copy.t("emptyDirectory") }) : /* @__PURE__ */ jsx6(ScrollArea, { className: "min-h-0 flex-1 [&_[data-orientation=vertical][data-slot=scroll-area-scrollbar]]:opacity-100", children: layoutMode === "icon" ? /* @__PURE__ */ jsx6(
|
|
1805
2220
|
WorkspaceFileManagerIconGrid,
|
|
1806
2221
|
{
|
|
1807
2222
|
contextMenuEntryPath,
|
|
@@ -1827,8 +2242,8 @@ function WorkspaceFileManagerPanels({
|
|
|
1827
2242
|
onEntryClick: handleEntryClick,
|
|
1828
2243
|
onEntryPointerDown: handleEntryPointerDown
|
|
1829
2244
|
}
|
|
1830
|
-
) : /* @__PURE__ */
|
|
1831
|
-
/* @__PURE__ */
|
|
2245
|
+
) : /* @__PURE__ */ jsxs5("div", { className: "flex flex-col", children: [
|
|
2246
|
+
/* @__PURE__ */ jsxs5(
|
|
1832
2247
|
"div",
|
|
1833
2248
|
{
|
|
1834
2249
|
className: cn4(
|
|
@@ -1837,15 +2252,15 @@ function WorkspaceFileManagerPanels({
|
|
|
1837
2252
|
),
|
|
1838
2253
|
style: tableGridStyle,
|
|
1839
2254
|
children: [
|
|
1840
|
-
/* @__PURE__ */
|
|
1841
|
-
/* @__PURE__ */
|
|
2255
|
+
/* @__PURE__ */ jsx6("span", { className: tableCellPaddingClassName, children: copy.t("nameLabel") }),
|
|
2256
|
+
/* @__PURE__ */ jsx6(
|
|
1842
2257
|
"span",
|
|
1843
2258
|
{
|
|
1844
2259
|
className: cn4("whitespace-nowrap", tableCellPaddingClassName),
|
|
1845
2260
|
children: dateColumnLabel
|
|
1846
2261
|
}
|
|
1847
2262
|
),
|
|
1848
|
-
/* @__PURE__ */
|
|
2263
|
+
/* @__PURE__ */ jsx6(
|
|
1849
2264
|
"span",
|
|
1850
2265
|
{
|
|
1851
2266
|
className: cn4("whitespace-nowrap", tableCellPaddingClassName),
|
|
@@ -1855,44 +2270,63 @@ function WorkspaceFileManagerPanels({
|
|
|
1855
2270
|
]
|
|
1856
2271
|
}
|
|
1857
2272
|
),
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
2273
|
+
treeRows.map(
|
|
2274
|
+
(row) => row.kind === "feedback" ? /* @__PURE__ */ jsx6(
|
|
2275
|
+
TreeFeedbackRow,
|
|
2276
|
+
{
|
|
2277
|
+
copy,
|
|
2278
|
+
depth: row.depth,
|
|
2279
|
+
gridClassName: tableGridClassName,
|
|
2280
|
+
gridStyle: tableGridStyle,
|
|
2281
|
+
message: row.message,
|
|
2282
|
+
status: row.status,
|
|
2283
|
+
tableCellPaddingClassName
|
|
2284
|
+
},
|
|
2285
|
+
row.key
|
|
2286
|
+
) : /* @__PURE__ */ jsx6(
|
|
2287
|
+
EntryRow,
|
|
2288
|
+
{
|
|
2289
|
+
contextMenuActive: contextMenuEntryPath === row.entry.path,
|
|
2290
|
+
copy,
|
|
2291
|
+
arrangeMode,
|
|
2292
|
+
dateLocale,
|
|
2293
|
+
depth: row.depth,
|
|
2294
|
+
entry: row.entry,
|
|
2295
|
+
expanded: row.expanded,
|
|
2296
|
+
expandable: row.expandable,
|
|
2297
|
+
iconUrlByCacheKey,
|
|
2298
|
+
canMove: internalMoveEnabled,
|
|
2299
|
+
draggable: nativeEntryDragEnabled,
|
|
2300
|
+
gridClassName: tableGridClassName,
|
|
2301
|
+
gridStyle: tableGridStyle,
|
|
2302
|
+
inlineRenameValidation: inlineRenameEntryPath === row.entry.path ? inlineRenameValidation : null,
|
|
2303
|
+
isEnteringDirectory: pendingDirectoryPath === row.entry.path,
|
|
2304
|
+
isInlineRenaming: inlineRenameEntryPath === row.entry.path,
|
|
2305
|
+
isLoadingChildren: row.loadingChildren,
|
|
2306
|
+
isRenaming,
|
|
2307
|
+
moveDragActive: moveDragPreview !== null,
|
|
2308
|
+
moveDragSource: moveDragPreview?.entry.path === row.entry.path,
|
|
2309
|
+
moveDragTarget: moveDragPreview?.targetDirectoryPath === row.entry.path,
|
|
2310
|
+
tableCellPaddingClassName,
|
|
2311
|
+
selected: selectedPath === row.entry.path,
|
|
2312
|
+
onEntryIconViewportLeave,
|
|
2313
|
+
onEntryIconViewportEnter,
|
|
2314
|
+
onCancelInlineRename,
|
|
2315
|
+
onClearInlineRenameValidation,
|
|
2316
|
+
onConfirmInlineRename,
|
|
2317
|
+
onContextMenu: onEntryContextMenu,
|
|
2318
|
+
onDragStart: onEntryDragStart,
|
|
2319
|
+
onClick: handleEntryClick,
|
|
2320
|
+
onPointerDown: handleEntryPointerDown,
|
|
2321
|
+
onToggleDirectoryExpanded
|
|
2322
|
+
},
|
|
2323
|
+
row.entry.path
|
|
2324
|
+
)
|
|
2325
|
+
)
|
|
1892
2326
|
] }) })
|
|
1893
2327
|
}
|
|
1894
2328
|
);
|
|
1895
|
-
const previewPanel = showPreviewPanel ? /* @__PURE__ */
|
|
2329
|
+
const previewPanel = showPreviewPanel ? /* @__PURE__ */ jsx6(
|
|
1896
2330
|
"aside",
|
|
1897
2331
|
{
|
|
1898
2332
|
className: cn4(
|
|
@@ -1901,7 +2335,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1901
2335
|
previewPaneClassName
|
|
1902
2336
|
),
|
|
1903
2337
|
style: useStackedPreview ? void 0 : { width: previewPaneWidth },
|
|
1904
|
-
children: /* @__PURE__ */
|
|
2338
|
+
children: /* @__PURE__ */ jsx6(
|
|
1905
2339
|
PreviewPane,
|
|
1906
2340
|
{
|
|
1907
2341
|
copy,
|
|
@@ -1912,13 +2346,13 @@ function WorkspaceFileManagerPanels({
|
|
|
1912
2346
|
)
|
|
1913
2347
|
}
|
|
1914
2348
|
) : null;
|
|
1915
|
-
return /* @__PURE__ */
|
|
2349
|
+
return /* @__PURE__ */ jsxs5(
|
|
1916
2350
|
"div",
|
|
1917
2351
|
{
|
|
1918
2352
|
className: "relative min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
1919
2353
|
ref: rootRef,
|
|
1920
2354
|
children: [
|
|
1921
|
-
/* @__PURE__ */
|
|
2355
|
+
/* @__PURE__ */ jsxs5(
|
|
1922
2356
|
"div",
|
|
1923
2357
|
{
|
|
1924
2358
|
className: cn4(
|
|
@@ -1927,7 +2361,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1927
2361
|
),
|
|
1928
2362
|
children: [
|
|
1929
2363
|
tablePanel,
|
|
1930
|
-
showPreviewPanel && !useStackedPreview ? /* @__PURE__ */
|
|
2364
|
+
showPreviewPanel && !useStackedPreview ? /* @__PURE__ */ jsx6(
|
|
1931
2365
|
"div",
|
|
1932
2366
|
{
|
|
1933
2367
|
"aria-orientation": "vertical",
|
|
@@ -1946,7 +2380,7 @@ function WorkspaceFileManagerPanels({
|
|
|
1946
2380
|
]
|
|
1947
2381
|
}
|
|
1948
2382
|
),
|
|
1949
|
-
/* @__PURE__ */
|
|
2383
|
+
/* @__PURE__ */ jsx6(
|
|
1950
2384
|
"div",
|
|
1951
2385
|
{
|
|
1952
2386
|
"aria-hidden": "true",
|
|
@@ -1954,10 +2388,10 @@ function WorkspaceFileManagerPanels({
|
|
|
1954
2388
|
"pointer-events-none absolute inset-0 grid place-items-center rounded-[var(--workbench-window-radius,8px)] border border-dashed border-[var(--border-focus)] bg-[var(--accent-bg)] opacity-0 transition-opacity duration-150 ease-out",
|
|
1955
2389
|
showDropOverlay && "opacity-100"
|
|
1956
2390
|
),
|
|
1957
|
-
children: /* @__PURE__ */
|
|
2391
|
+
children: /* @__PURE__ */ jsx6("div", { className: "rounded-lg border border-[var(--border-1)] bg-[var(--background-fronted)] px-5 py-3 text-sm font-normal text-[var(--text-primary)] shadow-panel", children: copy.t("dropToImportLabel") })
|
|
1958
2392
|
}
|
|
1959
2393
|
),
|
|
1960
|
-
moveDragPreview ? /* @__PURE__ */
|
|
2394
|
+
moveDragPreview ? /* @__PURE__ */ jsx6(
|
|
1961
2395
|
MoveDragPreview,
|
|
1962
2396
|
{
|
|
1963
2397
|
iconUrlByCacheKey,
|
|
@@ -1971,8 +2405,8 @@ function WorkspaceFileManagerPanels({
|
|
|
1971
2405
|
);
|
|
1972
2406
|
}
|
|
1973
2407
|
function useWorkspaceFileManagerStackedLayout(breakpoint) {
|
|
1974
|
-
const rootRef =
|
|
1975
|
-
const [isStacked, setIsStacked] =
|
|
2408
|
+
const rootRef = useRef5(null);
|
|
2409
|
+
const [isStacked, setIsStacked] = useState3(false);
|
|
1976
2410
|
useLayoutEffect3(() => {
|
|
1977
2411
|
const element = rootRef.current;
|
|
1978
2412
|
if (!element) {
|
|
@@ -2018,14 +2452,18 @@ function EntryRow({
|
|
|
2018
2452
|
contextMenuActive,
|
|
2019
2453
|
copy,
|
|
2020
2454
|
dateLocale,
|
|
2455
|
+
depth,
|
|
2021
2456
|
draggable,
|
|
2022
2457
|
entry,
|
|
2458
|
+
expanded,
|
|
2459
|
+
expandable,
|
|
2023
2460
|
gridClassName,
|
|
2024
2461
|
gridStyle,
|
|
2025
2462
|
iconUrlByCacheKey,
|
|
2026
2463
|
inlineRenameValidation,
|
|
2027
2464
|
isEnteringDirectory,
|
|
2028
2465
|
isInlineRenaming,
|
|
2466
|
+
isLoadingChildren,
|
|
2029
2467
|
isRenaming,
|
|
2030
2468
|
moveDragActive,
|
|
2031
2469
|
moveDragSource,
|
|
@@ -2040,10 +2478,11 @@ function EntryRow({
|
|
|
2040
2478
|
onContextMenu,
|
|
2041
2479
|
onDragStart,
|
|
2042
2480
|
onClick,
|
|
2043
|
-
onPointerDown
|
|
2481
|
+
onPointerDown,
|
|
2482
|
+
onToggleDirectoryExpanded
|
|
2044
2483
|
}) {
|
|
2045
|
-
const buttonRowRef =
|
|
2046
|
-
const divRowRef =
|
|
2484
|
+
const buttonRowRef = useRef5(null);
|
|
2485
|
+
const divRowRef = useRef5(null);
|
|
2047
2486
|
useLayoutEffect3(() => {
|
|
2048
2487
|
if (!selected) {
|
|
2049
2488
|
return;
|
|
@@ -2073,7 +2512,7 @@ function EntryRow({
|
|
|
2073
2512
|
onContextMenu(event, entry);
|
|
2074
2513
|
}
|
|
2075
2514
|
};
|
|
2076
|
-
const nameCell = /* @__PURE__ */
|
|
2515
|
+
const nameCell = /* @__PURE__ */ jsx6("span", { className: tableCellPaddingClassName, children: /* @__PURE__ */ jsx6(
|
|
2077
2516
|
EntryNameCell,
|
|
2078
2517
|
{
|
|
2079
2518
|
copy,
|
|
@@ -2081,16 +2520,21 @@ function EntryRow({
|
|
|
2081
2520
|
iconUrlByCacheKey,
|
|
2082
2521
|
inlineRenameValidation,
|
|
2083
2522
|
isEnteringDirectory,
|
|
2523
|
+
isExpanded: expanded,
|
|
2524
|
+
isExpandable: expandable,
|
|
2084
2525
|
isInlineRenaming,
|
|
2526
|
+
isLoadingChildren,
|
|
2085
2527
|
isRenaming,
|
|
2528
|
+
treeDepth: depth,
|
|
2086
2529
|
onEntryIconViewportLeave,
|
|
2087
2530
|
onEntryIconViewportEnter,
|
|
2088
2531
|
onCancelInlineRename,
|
|
2089
2532
|
onClearInlineRenameValidation,
|
|
2090
|
-
onConfirmInlineRename
|
|
2533
|
+
onConfirmInlineRename,
|
|
2534
|
+
onToggleDirectoryExpanded
|
|
2091
2535
|
}
|
|
2092
2536
|
) });
|
|
2093
|
-
const modifiedCell = /* @__PURE__ */
|
|
2537
|
+
const modifiedCell = /* @__PURE__ */ jsx6(
|
|
2094
2538
|
"span",
|
|
2095
2539
|
{
|
|
2096
2540
|
className: cn4(
|
|
@@ -2103,7 +2547,7 @@ function EntryRow({
|
|
|
2103
2547
|
)
|
|
2104
2548
|
}
|
|
2105
2549
|
);
|
|
2106
|
-
const sizeCell = /* @__PURE__ */
|
|
2550
|
+
const sizeCell = /* @__PURE__ */ jsx6(
|
|
2107
2551
|
"span",
|
|
2108
2552
|
{
|
|
2109
2553
|
className: cn4(
|
|
@@ -2114,13 +2558,13 @@ function EntryRow({
|
|
|
2114
2558
|
}
|
|
2115
2559
|
);
|
|
2116
2560
|
if (isInlineRenaming) {
|
|
2117
|
-
return /* @__PURE__ */
|
|
2561
|
+
return /* @__PURE__ */ jsxs5("div", { ...rowProps, ref: divRowRef, children: [
|
|
2118
2562
|
nameCell,
|
|
2119
2563
|
modifiedCell,
|
|
2120
2564
|
sizeCell
|
|
2121
2565
|
] });
|
|
2122
2566
|
}
|
|
2123
|
-
return /* @__PURE__ */
|
|
2567
|
+
return /* @__PURE__ */ jsxs5(
|
|
2124
2568
|
"button",
|
|
2125
2569
|
{
|
|
2126
2570
|
...rowProps,
|
|
@@ -2153,7 +2597,7 @@ function MoveDragPreview({
|
|
|
2153
2597
|
onEntryIconViewportLeave,
|
|
2154
2598
|
onEntryIconViewportEnter
|
|
2155
2599
|
}) {
|
|
2156
|
-
return /* @__PURE__ */
|
|
2600
|
+
return /* @__PURE__ */ jsxs5(
|
|
2157
2601
|
"div",
|
|
2158
2602
|
{
|
|
2159
2603
|
"aria-hidden": "true",
|
|
@@ -2164,7 +2608,7 @@ function MoveDragPreview({
|
|
|
2164
2608
|
transform: "translate(12px, 12px)"
|
|
2165
2609
|
},
|
|
2166
2610
|
children: [
|
|
2167
|
-
/* @__PURE__ */
|
|
2611
|
+
/* @__PURE__ */ jsx6(
|
|
2168
2612
|
WorkspaceFileEntryIcon,
|
|
2169
2613
|
{
|
|
2170
2614
|
entry: preview.entry,
|
|
@@ -2175,7 +2619,7 @@ function MoveDragPreview({
|
|
|
2175
2619
|
onViewportEnter: onEntryIconViewportEnter
|
|
2176
2620
|
}
|
|
2177
2621
|
),
|
|
2178
|
-
/* @__PURE__ */
|
|
2622
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate", children: preview.entry.name })
|
|
2179
2623
|
]
|
|
2180
2624
|
}
|
|
2181
2625
|
);
|
|
@@ -2215,26 +2659,114 @@ function resolveMoveDragTargetEntry(entries, movedEntry, x, y) {
|
|
|
2215
2659
|
function canMoveEntryToDirectory(movedEntry, targetEntry) {
|
|
2216
2660
|
return movedEntry.kind !== "unknown" && targetEntry.kind === "directory" && movedEntry.path !== targetEntry.path && !targetEntry.path.startsWith(`${movedEntry.path}/`);
|
|
2217
2661
|
}
|
|
2662
|
+
function TreeFeedbackRow({
|
|
2663
|
+
copy,
|
|
2664
|
+
depth,
|
|
2665
|
+
gridClassName,
|
|
2666
|
+
gridStyle,
|
|
2667
|
+
message,
|
|
2668
|
+
status,
|
|
2669
|
+
tableCellPaddingClassName
|
|
2670
|
+
}) {
|
|
2671
|
+
const resolvedMessage = status === "loading" ? copy.t("loading") : status === "empty" ? copy.t("emptyDirectory") : message ?? copy.t("unknownErrorMessage");
|
|
2672
|
+
return /* @__PURE__ */ jsxs5(
|
|
2673
|
+
"div",
|
|
2674
|
+
{
|
|
2675
|
+
className: cn4(
|
|
2676
|
+
"grid min-h-9 w-full items-center gap-x-6 border-b border-[var(--border-1)] text-left text-xs text-[var(--text-tertiary)]",
|
|
2677
|
+
gridClassName
|
|
2678
|
+
),
|
|
2679
|
+
style: gridStyle,
|
|
2680
|
+
children: [
|
|
2681
|
+
/* @__PURE__ */ jsx6("span", { className: tableCellPaddingClassName, children: /* @__PURE__ */ jsxs5(
|
|
2682
|
+
"span",
|
|
2683
|
+
{
|
|
2684
|
+
className: "flex min-w-0 items-center gap-2",
|
|
2685
|
+
style: workspaceFileManagerTreeIndentStyle(depth),
|
|
2686
|
+
children: [
|
|
2687
|
+
/* @__PURE__ */ jsx6("span", { className: "size-5 shrink-0" }),
|
|
2688
|
+
status === "loading" ? /* @__PURE__ */ jsx6(LoadingIcon2, { className: "size-3.5 shrink-0 animate-spin" }) : null,
|
|
2689
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate", children: resolvedMessage })
|
|
2690
|
+
]
|
|
2691
|
+
}
|
|
2692
|
+
) }),
|
|
2693
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true" }),
|
|
2694
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true" })
|
|
2695
|
+
]
|
|
2696
|
+
}
|
|
2697
|
+
);
|
|
2698
|
+
}
|
|
2699
|
+
function DirectoryDisclosureButton({
|
|
2700
|
+
copy,
|
|
2701
|
+
entry,
|
|
2702
|
+
expanded,
|
|
2703
|
+
isLoading,
|
|
2704
|
+
show,
|
|
2705
|
+
onToggle
|
|
2706
|
+
}) {
|
|
2707
|
+
if (!show) {
|
|
2708
|
+
return /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", className: "size-5 shrink-0" });
|
|
2709
|
+
}
|
|
2710
|
+
return /* @__PURE__ */ jsx6(
|
|
2711
|
+
"button",
|
|
2712
|
+
{
|
|
2713
|
+
"aria-label": copy.t(
|
|
2714
|
+
expanded ? "collapseFolderLabel" : "expandFolderLabel"
|
|
2715
|
+
),
|
|
2716
|
+
"aria-expanded": expanded,
|
|
2717
|
+
className: "grid size-5 shrink-0 place-items-center rounded text-[var(--text-tertiary)] transition-colors hover:bg-transparency-block hover:text-[var(--text-primary)]",
|
|
2718
|
+
disabled: isLoading,
|
|
2719
|
+
type: "button",
|
|
2720
|
+
onClick: (event) => {
|
|
2721
|
+
event.preventDefault();
|
|
2722
|
+
event.stopPropagation();
|
|
2723
|
+
onToggle(entry, expanded);
|
|
2724
|
+
},
|
|
2725
|
+
onPointerDown: (event) => {
|
|
2726
|
+
event.stopPropagation();
|
|
2727
|
+
},
|
|
2728
|
+
children: isLoading ? /* @__PURE__ */ jsx6(LoadingIcon2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx6(
|
|
2729
|
+
ArrowRightIcon2,
|
|
2730
|
+
{
|
|
2731
|
+
className: cn4(
|
|
2732
|
+
"size-3.5 transition-transform",
|
|
2733
|
+
expanded && "rotate-90"
|
|
2734
|
+
)
|
|
2735
|
+
}
|
|
2736
|
+
)
|
|
2737
|
+
}
|
|
2738
|
+
);
|
|
2739
|
+
}
|
|
2740
|
+
function workspaceFileManagerTreeIndentStyle(depth) {
|
|
2741
|
+
return {
|
|
2742
|
+
paddingLeft: `${Math.max(0, depth) * 20}px`
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2218
2745
|
function EntryNameCell({
|
|
2219
2746
|
copy,
|
|
2220
2747
|
entry,
|
|
2221
2748
|
iconUrlByCacheKey,
|
|
2222
2749
|
inlineRenameValidation = null,
|
|
2223
2750
|
isEnteringDirectory = false,
|
|
2751
|
+
isExpanded = false,
|
|
2752
|
+
isExpandable = false,
|
|
2224
2753
|
isInlineRenaming = false,
|
|
2754
|
+
isLoadingChildren = false,
|
|
2225
2755
|
isRenaming = false,
|
|
2756
|
+
treeDepth = 0,
|
|
2226
2757
|
onEntryIconViewportLeave,
|
|
2227
2758
|
onEntryIconViewportEnter,
|
|
2228
2759
|
onCancelInlineRename,
|
|
2229
2760
|
onClearInlineRenameValidation,
|
|
2230
|
-
onConfirmInlineRename
|
|
2761
|
+
onConfirmInlineRename,
|
|
2762
|
+
onToggleDirectoryExpanded
|
|
2231
2763
|
}) {
|
|
2232
2764
|
const nameParts = splitWorkspaceFileName(entry.name);
|
|
2233
2765
|
const hasFileExtension = nameParts.end.length > 0 && nameParts.end.startsWith(".");
|
|
2234
|
-
const [name, setName] =
|
|
2235
|
-
const inputRef =
|
|
2236
|
-
const skipBlurRef =
|
|
2237
|
-
|
|
2766
|
+
const [name, setName] = useState3(entry.name);
|
|
2767
|
+
const inputRef = useRef5(null);
|
|
2768
|
+
const skipBlurRef = useRef5(false);
|
|
2769
|
+
useEffect4(() => {
|
|
2238
2770
|
if (!isInlineRenaming) {
|
|
2239
2771
|
return;
|
|
2240
2772
|
}
|
|
@@ -2253,99 +2785,135 @@ function EntryNameCell({
|
|
|
2253
2785
|
if (hasFileExtension) {
|
|
2254
2786
|
input.setSelectionRange(0, nameParts.start.length);
|
|
2255
2787
|
} else {
|
|
2256
|
-
input.select();
|
|
2257
|
-
}
|
|
2258
|
-
}, [hasFileExtension, isInlineRenaming, nameParts.start.length]);
|
|
2259
|
-
const validationMessage = inlineRenameValidation === "required" ? copy.t("createNameRequired") : inlineRenameValidation === "invalid" ? copy.t("createNameInvalid") : null;
|
|
2260
|
-
const handleConfirm = useCallback2(async () => {
|
|
2261
|
-
const confirmed = await onConfirmInlineRename(name);
|
|
2262
|
-
if (!confirmed) {
|
|
2263
|
-
inputRef.current?.focus();
|
|
2264
|
-
}
|
|
2265
|
-
}, [name, onConfirmInlineRename]);
|
|
2266
|
-
if (isInlineRenaming) {
|
|
2267
|
-
return /* @__PURE__ */
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
if (skipBlurRef.current) {
|
|
2294
|
-
skipBlurRef.current = false;
|
|
2295
|
-
return;
|
|
2296
|
-
}
|
|
2297
|
-
void handleConfirm();
|
|
2298
|
-
},
|
|
2299
|
-
onChange: (event) => {
|
|
2300
|
-
setName(event.currentTarget.value);
|
|
2301
|
-
onClearInlineRenameValidation();
|
|
2302
|
-
},
|
|
2303
|
-
onFocus: (event) => {
|
|
2304
|
-
if (hasFileExtension) {
|
|
2305
|
-
event.currentTarget.setSelectionRange(
|
|
2306
|
-
0,
|
|
2307
|
-
nameParts.start.length
|
|
2308
|
-
);
|
|
2309
|
-
} else {
|
|
2310
|
-
event.currentTarget.select();
|
|
2311
|
-
}
|
|
2312
|
-
},
|
|
2313
|
-
onKeyDown: (event) => {
|
|
2314
|
-
if (event.key === "Enter") {
|
|
2315
|
-
event.preventDefault();
|
|
2316
|
-
void handleConfirm();
|
|
2317
|
-
return;
|
|
2318
|
-
}
|
|
2319
|
-
if (event.key === "Escape") {
|
|
2320
|
-
event.preventDefault();
|
|
2321
|
-
skipBlurRef.current = true;
|
|
2322
|
-
onCancelInlineRename();
|
|
2323
|
-
}
|
|
2788
|
+
input.select();
|
|
2789
|
+
}
|
|
2790
|
+
}, [hasFileExtension, isInlineRenaming, nameParts.start.length]);
|
|
2791
|
+
const validationMessage = inlineRenameValidation === "required" ? copy.t("createNameRequired") : inlineRenameValidation === "invalid" ? copy.t("createNameInvalid") : null;
|
|
2792
|
+
const handleConfirm = useCallback2(async () => {
|
|
2793
|
+
const confirmed = await onConfirmInlineRename(name);
|
|
2794
|
+
if (!confirmed) {
|
|
2795
|
+
inputRef.current?.focus();
|
|
2796
|
+
}
|
|
2797
|
+
}, [name, onConfirmInlineRename]);
|
|
2798
|
+
if (isInlineRenaming) {
|
|
2799
|
+
return /* @__PURE__ */ jsxs5(
|
|
2800
|
+
"span",
|
|
2801
|
+
{
|
|
2802
|
+
className: "flex min-w-0 items-center gap-1.5",
|
|
2803
|
+
style: workspaceFileManagerTreeIndentStyle(treeDepth),
|
|
2804
|
+
children: [
|
|
2805
|
+
/* @__PURE__ */ jsx6(
|
|
2806
|
+
DirectoryDisclosureButton,
|
|
2807
|
+
{
|
|
2808
|
+
copy,
|
|
2809
|
+
entry,
|
|
2810
|
+
expanded: isExpanded,
|
|
2811
|
+
isLoading: isLoadingChildren,
|
|
2812
|
+
show: isExpandable,
|
|
2813
|
+
onToggle: onToggleDirectoryExpanded
|
|
2814
|
+
}
|
|
2815
|
+
),
|
|
2816
|
+
/* @__PURE__ */ jsx6(
|
|
2817
|
+
WorkspaceFileEntryIcon,
|
|
2818
|
+
{
|
|
2819
|
+
entry,
|
|
2820
|
+
frameClassName: "size-7",
|
|
2821
|
+
iconClassName: "size-6",
|
|
2822
|
+
iconUrlByCacheKey,
|
|
2823
|
+
onViewportLeave: onEntryIconViewportLeave,
|
|
2824
|
+
onViewportEnter: onEntryIconViewportEnter
|
|
2324
2825
|
}
|
|
2826
|
+
),
|
|
2827
|
+
/* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
2828
|
+
/* @__PURE__ */ jsx6(
|
|
2829
|
+
"input",
|
|
2830
|
+
{
|
|
2831
|
+
"aria-invalid": inlineRenameValidation !== null,
|
|
2832
|
+
"aria-label": copy.t("renameLabel"),
|
|
2833
|
+
className: cn4(
|
|
2834
|
+
"min-w-0 max-w-full rounded-md border border-transparent bg-[var(--transparency-block)] px-1.5 py-0.5 text-sm text-[var(--text-primary)] outline-none transition-colors duration-200 selection:bg-[var(--transparency-active)] selection:text-[var(--text-primary)] hover:bg-[var(--transparency-hover)] focus:bg-[var(--transparency-hover)] focus-visible:border-transparent focus-visible:bg-[var(--transparency-hover)] disabled:bg-[var(--transparency-block)] disabled:text-[var(--text-disabled)] disabled:opacity-100",
|
|
2835
|
+
inlineRenameValidation !== null && "border-[var(--state-danger)]"
|
|
2836
|
+
),
|
|
2837
|
+
disabled: isRenaming,
|
|
2838
|
+
ref: inputRef,
|
|
2839
|
+
value: name,
|
|
2840
|
+
onBlur: () => {
|
|
2841
|
+
if (skipBlurRef.current) {
|
|
2842
|
+
skipBlurRef.current = false;
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2845
|
+
void handleConfirm();
|
|
2846
|
+
},
|
|
2847
|
+
onChange: (event) => {
|
|
2848
|
+
setName(event.currentTarget.value);
|
|
2849
|
+
onClearInlineRenameValidation();
|
|
2850
|
+
},
|
|
2851
|
+
onFocus: (event) => {
|
|
2852
|
+
if (hasFileExtension) {
|
|
2853
|
+
event.currentTarget.setSelectionRange(
|
|
2854
|
+
0,
|
|
2855
|
+
nameParts.start.length
|
|
2856
|
+
);
|
|
2857
|
+
} else {
|
|
2858
|
+
event.currentTarget.select();
|
|
2859
|
+
}
|
|
2860
|
+
},
|
|
2861
|
+
onKeyDown: (event) => {
|
|
2862
|
+
if (event.key === "Enter") {
|
|
2863
|
+
event.preventDefault();
|
|
2864
|
+
void handleConfirm();
|
|
2865
|
+
return;
|
|
2866
|
+
}
|
|
2867
|
+
if (event.key === "Escape") {
|
|
2868
|
+
event.preventDefault();
|
|
2869
|
+
skipBlurRef.current = true;
|
|
2870
|
+
onCancelInlineRename();
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
),
|
|
2875
|
+
validationMessage ? /* @__PURE__ */ jsx6("span", { className: "text-xs text-[var(--state-danger)]", children: validationMessage }) : null
|
|
2876
|
+
] })
|
|
2877
|
+
]
|
|
2878
|
+
}
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
return /* @__PURE__ */ jsxs5(
|
|
2882
|
+
"span",
|
|
2883
|
+
{
|
|
2884
|
+
className: "flex min-w-0 items-center gap-1.5",
|
|
2885
|
+
style: workspaceFileManagerTreeIndentStyle(treeDepth),
|
|
2886
|
+
children: [
|
|
2887
|
+
/* @__PURE__ */ jsx6(
|
|
2888
|
+
DirectoryDisclosureButton,
|
|
2889
|
+
{
|
|
2890
|
+
copy,
|
|
2891
|
+
entry,
|
|
2892
|
+
expanded: isExpanded,
|
|
2893
|
+
isLoading: isLoadingChildren,
|
|
2894
|
+
show: isExpandable,
|
|
2895
|
+
onToggle: onToggleDirectoryExpanded
|
|
2325
2896
|
}
|
|
2326
2897
|
),
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
nameParts.end ? /* @__PURE__ */ jsx4("span", { className: "flex-none overflow-hidden text-ellipsis", children: nameParts.end }) : null
|
|
2347
|
-
] })
|
|
2348
|
-
] });
|
|
2898
|
+
/* @__PURE__ */ jsx6(
|
|
2899
|
+
WorkspaceFileEntryIcon,
|
|
2900
|
+
{
|
|
2901
|
+
entry,
|
|
2902
|
+
frameClassName: "size-7",
|
|
2903
|
+
iconClassName: "size-6",
|
|
2904
|
+
iconUrlByCacheKey,
|
|
2905
|
+
isEnteringDirectory,
|
|
2906
|
+
onViewportLeave: onEntryIconViewportLeave,
|
|
2907
|
+
onViewportEnter: onEntryIconViewportEnter
|
|
2908
|
+
}
|
|
2909
|
+
),
|
|
2910
|
+
/* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 max-w-full overflow-hidden whitespace-nowrap text-sm", children: [
|
|
2911
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 overflow-hidden text-ellipsis", children: nameParts.start }),
|
|
2912
|
+
nameParts.end ? /* @__PURE__ */ jsx6("span", { className: "flex-none overflow-hidden text-ellipsis", children: nameParts.end }) : null
|
|
2913
|
+
] })
|
|
2914
|
+
]
|
|
2915
|
+
}
|
|
2916
|
+
);
|
|
2349
2917
|
}
|
|
2350
2918
|
function EntryIcon({
|
|
2351
2919
|
className = "size-4",
|
|
@@ -2353,20 +2921,20 @@ function EntryIcon({
|
|
|
2353
2921
|
}) {
|
|
2354
2922
|
switch (visualKind) {
|
|
2355
2923
|
case "directory":
|
|
2356
|
-
return /* @__PURE__ */
|
|
2924
|
+
return /* @__PURE__ */ jsx6(WorkspaceFolderFallbackIcon, { className });
|
|
2357
2925
|
case "image":
|
|
2358
|
-
return /* @__PURE__ */
|
|
2926
|
+
return /* @__PURE__ */ jsx6(WorkspaceImageFallbackIcon, { className });
|
|
2359
2927
|
case "video":
|
|
2360
|
-
return /* @__PURE__ */
|
|
2928
|
+
return /* @__PURE__ */ jsx6(VideoFileIcon2, { className });
|
|
2361
2929
|
case "markdown":
|
|
2362
2930
|
case "document":
|
|
2363
|
-
return /* @__PURE__ */
|
|
2931
|
+
return /* @__PURE__ */ jsx6(FileTextIcon2, { className });
|
|
2364
2932
|
case "code":
|
|
2365
|
-
return /* @__PURE__ */
|
|
2933
|
+
return /* @__PURE__ */ jsx6(FileCodeIcon2, { className });
|
|
2366
2934
|
case "binary":
|
|
2367
|
-
return /* @__PURE__ */
|
|
2935
|
+
return /* @__PURE__ */ jsx6(FileTextIcon2, { className });
|
|
2368
2936
|
default:
|
|
2369
|
-
return /* @__PURE__ */
|
|
2937
|
+
return /* @__PURE__ */ jsx6(FileTextIcon2, { className });
|
|
2370
2938
|
}
|
|
2371
2939
|
}
|
|
2372
2940
|
function PreviewPane({
|
|
@@ -2376,24 +2944,24 @@ function PreviewPane({
|
|
|
2376
2944
|
previewState
|
|
2377
2945
|
}) {
|
|
2378
2946
|
if (!entry || previewState.status === "empty") {
|
|
2379
|
-
return /* @__PURE__ */
|
|
2947
|
+
return /* @__PURE__ */ jsx6("div", { className: "grid h-full min-h-[180px] place-items-center overflow-hidden p-8 text-center text-sm leading-5 text-[var(--text-tertiary)]", children: /* @__PURE__ */ jsx6("span", { className: "max-w-[24ch] [overflow-wrap:anywhere]", children: copy.t("previewEmptyLabel") }) });
|
|
2380
2948
|
}
|
|
2381
|
-
return /* @__PURE__ */
|
|
2382
|
-
/* @__PURE__ */
|
|
2383
|
-
/* @__PURE__ */
|
|
2384
|
-
/* @__PURE__ */
|
|
2385
|
-
/* @__PURE__ */
|
|
2386
|
-
/* @__PURE__ */
|
|
2949
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2950
|
+
/* @__PURE__ */ jsx6(PreviewSurface, { copy, previewState }),
|
|
2951
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-col gap-[14px]", children: [
|
|
2952
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-col gap-[3px]", children: [
|
|
2953
|
+
/* @__PURE__ */ jsx6("strong", { className: "min-w-0 truncate text-[15px] font-semibold text-[var(--text-primary)]", children: entry.name }),
|
|
2954
|
+
/* @__PURE__ */ jsx6("p", { className: "min-w-0 truncate text-xs text-[var(--text-secondary)]", children: entry.path })
|
|
2387
2955
|
] }),
|
|
2388
|
-
/* @__PURE__ */
|
|
2389
|
-
/* @__PURE__ */
|
|
2956
|
+
/* @__PURE__ */ jsxs5("dl", { className: "border-t border-[var(--border-1)]", children: [
|
|
2957
|
+
/* @__PURE__ */ jsx6(
|
|
2390
2958
|
PreviewDetail,
|
|
2391
2959
|
{
|
|
2392
2960
|
label: copy.t("modifiedLabel"),
|
|
2393
2961
|
value: formatWorkspaceFileModifiedTime(entry.mtimeMs, dateLocale)
|
|
2394
2962
|
}
|
|
2395
2963
|
),
|
|
2396
|
-
/* @__PURE__ */
|
|
2964
|
+
/* @__PURE__ */ jsx6(
|
|
2397
2965
|
PreviewDetail,
|
|
2398
2966
|
{
|
|
2399
2967
|
label: copy.t("sizeLabel"),
|
|
@@ -2408,7 +2976,7 @@ function PreviewSurface({
|
|
|
2408
2976
|
copy,
|
|
2409
2977
|
previewState
|
|
2410
2978
|
}) {
|
|
2411
|
-
return /* @__PURE__ */
|
|
2979
|
+
return /* @__PURE__ */ jsx6(
|
|
2412
2980
|
SharedWorkspaceFilePreviewSurface,
|
|
2413
2981
|
{
|
|
2414
2982
|
directoryMessage: copy.t("previewDirectoryLabel"),
|
|
@@ -2416,10 +2984,10 @@ function PreviewSurface({
|
|
|
2416
2984
|
frameClassName: "flex h-60 min-h-60 max-h-60 items-center justify-center overflow-hidden rounded-lg border border-[var(--border-1)] bg-[var(--transparency-block)]",
|
|
2417
2985
|
imageAlt: (entry) => entry.name,
|
|
2418
2986
|
imageFrameClassName: "p-4",
|
|
2419
|
-
loadingIndicator: /* @__PURE__ */
|
|
2987
|
+
loadingIndicator: /* @__PURE__ */ jsx6("span", { className: "mx-auto grid size-11 place-items-center rounded-lg bg-[var(--transparency-block)]", children: /* @__PURE__ */ jsx6(LoadingIcon2, { className: "size-4 animate-spin" }) }),
|
|
2420
2988
|
loadingMessage: copy.t("previewLoadingLabel"),
|
|
2421
2989
|
messageClassName: "max-w-[24ch] [overflow-wrap:anywhere]",
|
|
2422
|
-
renderIcon: (entry) => /* @__PURE__ */
|
|
2990
|
+
renderIcon: (entry) => /* @__PURE__ */ jsx6(
|
|
2423
2991
|
EntryIcon,
|
|
2424
2992
|
{
|
|
2425
2993
|
className: "mx-auto size-7",
|
|
@@ -2435,26 +3003,26 @@ function resolveWorkspaceFilePreviewIconKind(entry) {
|
|
|
2435
3003
|
if ("kind" in entry) {
|
|
2436
3004
|
return resolveWorkspaceFileVisualKind(entry);
|
|
2437
3005
|
}
|
|
2438
|
-
return entry.fileKind === "image" ? "image" : "document";
|
|
3006
|
+
return entry.fileKind === "image" ? "image" : entry.fileKind === "video" ? "video" : "document";
|
|
2439
3007
|
}
|
|
2440
3008
|
function PreviewDetail({
|
|
2441
3009
|
label,
|
|
2442
3010
|
value
|
|
2443
3011
|
}) {
|
|
2444
|
-
return /* @__PURE__ */
|
|
3012
|
+
return /* @__PURE__ */ jsxs5(
|
|
2445
3013
|
"div",
|
|
2446
3014
|
{
|
|
2447
3015
|
className: "@max-[600px]/workspace-file-manager:grid-cols-1 @max-[600px]/workspace-file-manager:gap-0.5 grid gap-2.5 border-b border-[var(--border-1)] py-2.5 text-xs",
|
|
2448
3016
|
style: workspaceFileManagerPreviewDetailGridStyle,
|
|
2449
3017
|
children: [
|
|
2450
|
-
/* @__PURE__ */
|
|
2451
|
-
/* @__PURE__ */
|
|
3018
|
+
/* @__PURE__ */ jsx6("dt", { className: "truncate text-[var(--text-secondary)]", children: label }),
|
|
3019
|
+
/* @__PURE__ */ jsx6("dd", { className: "@max-[600px]/workspace-file-manager:text-left truncate text-right text-[var(--text-primary)]", children: value })
|
|
2452
3020
|
]
|
|
2453
3021
|
}
|
|
2454
3022
|
);
|
|
2455
3023
|
}
|
|
2456
3024
|
function FeedbackState({ message }) {
|
|
2457
|
-
return /* @__PURE__ */
|
|
3025
|
+
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 }) });
|
|
2458
3026
|
}
|
|
2459
3027
|
function hasFileDragPayload(dataTransfer) {
|
|
2460
3028
|
return Array.from(dataTransfer.types).includes("Files");
|
|
@@ -2463,7 +3031,7 @@ function hasFileDragPayload(dataTransfer) {
|
|
|
2463
3031
|
// src/ui/WorkspaceFileManagerToolbar.tsx
|
|
2464
3032
|
import {
|
|
2465
3033
|
ArrowLeftIcon,
|
|
2466
|
-
ArrowRightIcon as
|
|
3034
|
+
ArrowRightIcon as ArrowRightIcon3,
|
|
2467
3035
|
Button as Button2,
|
|
2468
3036
|
ChevronDownIcon,
|
|
2469
3037
|
DropdownMenu,
|
|
@@ -2482,8 +3050,8 @@ import {
|
|
|
2482
3050
|
ViewListLinedIcon,
|
|
2483
3051
|
cn as cn5
|
|
2484
3052
|
} from "@tutti-os/ui-system";
|
|
2485
|
-
import { useState as
|
|
2486
|
-
import { jsx as
|
|
3053
|
+
import { useState as useState4 } from "react";
|
|
3054
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2487
3055
|
function WorkspaceFileManagerToolbar({
|
|
2488
3056
|
breadcrumbs,
|
|
2489
3057
|
canGoBack,
|
|
@@ -2502,39 +3070,39 @@ function WorkspaceFileManagerToolbar({
|
|
|
2502
3070
|
onLoadDirectory,
|
|
2503
3071
|
onRefresh
|
|
2504
3072
|
}) {
|
|
2505
|
-
const [refreshAnimationKey, setRefreshAnimationKey] =
|
|
3073
|
+
const [refreshAnimationKey, setRefreshAnimationKey] = useState4(0);
|
|
2506
3074
|
const handleRefresh = () => {
|
|
2507
3075
|
setRefreshAnimationKey((currentKey) => currentKey + 1);
|
|
2508
3076
|
onRefresh();
|
|
2509
3077
|
};
|
|
2510
|
-
return /* @__PURE__ */
|
|
2511
|
-
/* @__PURE__ */
|
|
3078
|
+
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: [
|
|
3079
|
+
/* @__PURE__ */ jsx7(
|
|
2512
3080
|
ToolbarIconButton,
|
|
2513
3081
|
{
|
|
2514
3082
|
ariaLabel: copy.t("backLabel"),
|
|
2515
3083
|
disabled: !canGoBack || isLoading || isBusy,
|
|
2516
3084
|
title: copy.t("backLabel"),
|
|
2517
3085
|
onClick: onGoBack,
|
|
2518
|
-
children: /* @__PURE__ */
|
|
3086
|
+
children: /* @__PURE__ */ jsx7(ArrowLeftIcon, { className: "size-4" })
|
|
2519
3087
|
}
|
|
2520
3088
|
),
|
|
2521
|
-
/* @__PURE__ */
|
|
3089
|
+
/* @__PURE__ */ jsx7(
|
|
2522
3090
|
ToolbarIconButton,
|
|
2523
3091
|
{
|
|
2524
3092
|
ariaLabel: copy.t("forwardLabel"),
|
|
2525
3093
|
disabled: !canGoForward || isLoading || isBusy,
|
|
2526
3094
|
title: copy.t("forwardLabel"),
|
|
2527
3095
|
onClick: onGoForward,
|
|
2528
|
-
children: /* @__PURE__ */
|
|
3096
|
+
children: /* @__PURE__ */ jsx7(ArrowRightIcon3, { className: "size-4" })
|
|
2529
3097
|
}
|
|
2530
3098
|
),
|
|
2531
|
-
/* @__PURE__ */
|
|
3099
|
+
/* @__PURE__ */ jsx7(
|
|
2532
3100
|
"nav",
|
|
2533
3101
|
{
|
|
2534
3102
|
"aria-label": currentDirectoryPath,
|
|
2535
3103
|
className: "@max-[600px]/workspace-file-manager:flex-auto flex min-w-0 flex-1 overflow-hidden pr-2",
|
|
2536
3104
|
"data-workspace-file-manager-path": "",
|
|
2537
|
-
children: /* @__PURE__ */
|
|
3105
|
+
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(
|
|
2538
3106
|
BreadcrumbButton,
|
|
2539
3107
|
{
|
|
2540
3108
|
active: index === breadcrumbs.length - 1,
|
|
@@ -2548,8 +3116,8 @@ function WorkspaceFileManagerToolbar({
|
|
|
2548
3116
|
)) })
|
|
2549
3117
|
}
|
|
2550
3118
|
),
|
|
2551
|
-
/* @__PURE__ */
|
|
2552
|
-
/* @__PURE__ */
|
|
3119
|
+
/* @__PURE__ */ jsxs6("div", { className: "@max-[600px]/workspace-file-manager:justify-end flex flex-none items-center gap-1.5", children: [
|
|
3120
|
+
/* @__PURE__ */ jsx7(
|
|
2553
3121
|
LayoutModeToggle,
|
|
2554
3122
|
{
|
|
2555
3123
|
arrangeMode,
|
|
@@ -2559,13 +3127,13 @@ function WorkspaceFileManagerToolbar({
|
|
|
2559
3127
|
onLayoutModeChange
|
|
2560
3128
|
}
|
|
2561
3129
|
),
|
|
2562
|
-
/* @__PURE__ */
|
|
3130
|
+
/* @__PURE__ */ jsxs6(
|
|
2563
3131
|
ToolbarActionButton,
|
|
2564
3132
|
{
|
|
2565
3133
|
disabled: isLoading || isMutating || isBusy,
|
|
2566
3134
|
onClick: handleRefresh,
|
|
2567
3135
|
children: [
|
|
2568
|
-
isLoading ? /* @__PURE__ */
|
|
3136
|
+
isLoading ? /* @__PURE__ */ jsx7(LoadingIcon3, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx7(
|
|
2569
3137
|
RefreshIcon,
|
|
2570
3138
|
{
|
|
2571
3139
|
className: cn5(
|
|
@@ -2575,7 +3143,7 @@ function WorkspaceFileManagerToolbar({
|
|
|
2575
3143
|
},
|
|
2576
3144
|
refreshAnimationKey
|
|
2577
3145
|
),
|
|
2578
|
-
/* @__PURE__ */
|
|
3146
|
+
/* @__PURE__ */ jsx7("span", { className: "@max-[600px]/workspace-file-manager:hidden", children: copy.t("refreshLabel") })
|
|
2579
3147
|
]
|
|
2580
3148
|
}
|
|
2581
3149
|
)
|
|
@@ -2600,13 +3168,13 @@ function LayoutModeToggle({
|
|
|
2600
3168
|
{ label: copy.t("arrangeCreatedLabel"), mode: "created" },
|
|
2601
3169
|
{ label: copy.t("sizeLabel"), mode: "size" }
|
|
2602
3170
|
];
|
|
2603
|
-
return /* @__PURE__ */
|
|
3171
|
+
return /* @__PURE__ */ jsx7(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs6(
|
|
2604
3172
|
"div",
|
|
2605
3173
|
{
|
|
2606
3174
|
className: "flex items-center rounded-md border border-[var(--border-1)] bg-[var(--transparency-block)] p-0.5",
|
|
2607
3175
|
role: "group",
|
|
2608
3176
|
children: [
|
|
2609
|
-
/* @__PURE__ */
|
|
3177
|
+
/* @__PURE__ */ jsx7(
|
|
2610
3178
|
LayoutModeButton,
|
|
2611
3179
|
{
|
|
2612
3180
|
active: layoutMode === "icon",
|
|
@@ -2615,10 +3183,10 @@ function LayoutModeToggle({
|
|
|
2615
3183
|
onClick: () => {
|
|
2616
3184
|
onLayoutModeChange("icon");
|
|
2617
3185
|
},
|
|
2618
|
-
children: /* @__PURE__ */
|
|
3186
|
+
children: /* @__PURE__ */ jsx7(ViewGridLinedIcon, { className: "size-4" })
|
|
2619
3187
|
}
|
|
2620
3188
|
),
|
|
2621
|
-
/* @__PURE__ */
|
|
3189
|
+
/* @__PURE__ */ jsx7(
|
|
2622
3190
|
LayoutModeButton,
|
|
2623
3191
|
{
|
|
2624
3192
|
active: layoutMode === "list",
|
|
@@ -2627,12 +3195,12 @@ function LayoutModeToggle({
|
|
|
2627
3195
|
onClick: () => {
|
|
2628
3196
|
onLayoutModeChange("list");
|
|
2629
3197
|
},
|
|
2630
|
-
children: /* @__PURE__ */
|
|
3198
|
+
children: /* @__PURE__ */ jsx7(ViewListLinedIcon, { className: "size-4" })
|
|
2631
3199
|
}
|
|
2632
3200
|
),
|
|
2633
|
-
/* @__PURE__ */
|
|
2634
|
-
/* @__PURE__ */
|
|
2635
|
-
/* @__PURE__ */
|
|
3201
|
+
/* @__PURE__ */ jsx7("span", { className: "mx-0.5 h-4 w-px bg-[var(--border-1)]", "aria-hidden": true }),
|
|
3202
|
+
/* @__PURE__ */ jsxs6(DropdownMenu, { children: [
|
|
3203
|
+
/* @__PURE__ */ jsx7(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
2636
3204
|
Button2,
|
|
2637
3205
|
{
|
|
2638
3206
|
"aria-label": copy.t("arrangeMenuLabel"),
|
|
@@ -2640,16 +3208,16 @@ function LayoutModeToggle({
|
|
|
2640
3208
|
size: "icon-sm",
|
|
2641
3209
|
type: "button",
|
|
2642
3210
|
variant: "ghost",
|
|
2643
|
-
children: /* @__PURE__ */
|
|
3211
|
+
children: /* @__PURE__ */ jsx7(ChevronDownIcon, { className: "size-3.5" })
|
|
2644
3212
|
}
|
|
2645
3213
|
) }),
|
|
2646
|
-
/* @__PURE__ */
|
|
3214
|
+
/* @__PURE__ */ jsx7(
|
|
2647
3215
|
DropdownMenuContent,
|
|
2648
3216
|
{
|
|
2649
3217
|
align: "end",
|
|
2650
3218
|
className: "min-w-[236px] px-1 py-1",
|
|
2651
3219
|
sideOffset: 7,
|
|
2652
|
-
children: /* @__PURE__ */
|
|
3220
|
+
children: /* @__PURE__ */ jsx7(
|
|
2653
3221
|
DropdownMenuRadioGroup,
|
|
2654
3222
|
{
|
|
2655
3223
|
value: arrangeMode,
|
|
@@ -2658,9 +3226,9 @@ function LayoutModeToggle({
|
|
|
2658
3226
|
nextMode
|
|
2659
3227
|
);
|
|
2660
3228
|
},
|
|
2661
|
-
children: arrangeOptions.map((option, index) => /* @__PURE__ */
|
|
2662
|
-
index === 1 ? /* @__PURE__ */
|
|
2663
|
-
/* @__PURE__ */
|
|
3229
|
+
children: arrangeOptions.map((option, index) => /* @__PURE__ */ jsxs6("div", { children: [
|
|
3230
|
+
index === 1 ? /* @__PURE__ */ jsx7(DropdownMenuSeparator, {}) : null,
|
|
3231
|
+
/* @__PURE__ */ jsx7(
|
|
2664
3232
|
DropdownMenuRadioItem,
|
|
2665
3233
|
{
|
|
2666
3234
|
className: "h-8 text-sm font-normal",
|
|
@@ -2685,8 +3253,8 @@ function LayoutModeButton({
|
|
|
2685
3253
|
onClick,
|
|
2686
3254
|
tooltipLabel
|
|
2687
3255
|
}) {
|
|
2688
|
-
return /* @__PURE__ */
|
|
2689
|
-
/* @__PURE__ */
|
|
3256
|
+
return /* @__PURE__ */ jsxs6(Tooltip, { children: [
|
|
3257
|
+
/* @__PURE__ */ jsx7(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
2690
3258
|
Button2,
|
|
2691
3259
|
{
|
|
2692
3260
|
"aria-label": ariaLabel,
|
|
@@ -2702,7 +3270,7 @@ function LayoutModeButton({
|
|
|
2702
3270
|
children
|
|
2703
3271
|
}
|
|
2704
3272
|
) }),
|
|
2705
|
-
/* @__PURE__ */
|
|
3273
|
+
/* @__PURE__ */ jsx7(TooltipContent, { side: "bottom", children: tooltipLabel })
|
|
2706
3274
|
] });
|
|
2707
3275
|
}
|
|
2708
3276
|
function ToolbarIconButton({
|
|
@@ -2712,7 +3280,7 @@ function ToolbarIconButton({
|
|
|
2712
3280
|
onClick,
|
|
2713
3281
|
title
|
|
2714
3282
|
}) {
|
|
2715
|
-
return /* @__PURE__ */
|
|
3283
|
+
return /* @__PURE__ */ jsx7(
|
|
2716
3284
|
Button2,
|
|
2717
3285
|
{
|
|
2718
3286
|
"aria-label": ariaLabel,
|
|
@@ -2732,7 +3300,7 @@ function ToolbarActionButton({
|
|
|
2732
3300
|
disabled,
|
|
2733
3301
|
onClick
|
|
2734
3302
|
}) {
|
|
2735
|
-
return /* @__PURE__ */
|
|
3303
|
+
return /* @__PURE__ */ jsx7(
|
|
2736
3304
|
Button2,
|
|
2737
3305
|
{
|
|
2738
3306
|
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",
|
|
@@ -2751,9 +3319,9 @@ function BreadcrumbButton({
|
|
|
2751
3319
|
onClick,
|
|
2752
3320
|
showSeparator
|
|
2753
3321
|
}) {
|
|
2754
|
-
return /* @__PURE__ */
|
|
2755
|
-
showSeparator ? /* @__PURE__ */
|
|
2756
|
-
/* @__PURE__ */
|
|
3322
|
+
return /* @__PURE__ */ jsxs6("li", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3323
|
+
showSeparator ? /* @__PURE__ */ jsx7("span", { className: "flex-none text-[var(--text-tertiary)]", children: "/" }) : null,
|
|
3324
|
+
/* @__PURE__ */ jsx7(
|
|
2757
3325
|
"button",
|
|
2758
3326
|
{
|
|
2759
3327
|
className: cn5(
|
|
@@ -2769,9 +3337,9 @@ function BreadcrumbButton({
|
|
|
2769
3337
|
}
|
|
2770
3338
|
|
|
2771
3339
|
// src/ui/useWorkspaceFileManagerArrangeMode.ts
|
|
2772
|
-
import { useCallback as useCallback3, useState as
|
|
3340
|
+
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
2773
3341
|
function useWorkspaceFileManagerArrangeMode() {
|
|
2774
|
-
const [arrangeMode, setArrangeModeState] =
|
|
3342
|
+
const [arrangeMode, setArrangeModeState] = useState5(
|
|
2775
3343
|
readWorkspaceFileManagerArrangeMode
|
|
2776
3344
|
);
|
|
2777
3345
|
const setArrangeMode = useCallback3(
|
|
@@ -2785,7 +3353,7 @@ function useWorkspaceFileManagerArrangeMode() {
|
|
|
2785
3353
|
}
|
|
2786
3354
|
|
|
2787
3355
|
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
2788
|
-
import { useCallback as useCallback4, useState as
|
|
3356
|
+
import { useCallback as useCallback4, useState as useState6 } from "react";
|
|
2789
3357
|
|
|
2790
3358
|
// src/ui/workspaceFileManagerLayoutMode.ts
|
|
2791
3359
|
var workspaceFileManagerLayoutModeStorageKey = "tutti.workspace-file-manager.layout-mode";
|
|
@@ -2810,7 +3378,7 @@ function writeWorkspaceFileManagerLayoutMode(layoutMode) {
|
|
|
2810
3378
|
|
|
2811
3379
|
// src/ui/useWorkspaceFileManagerLayoutMode.ts
|
|
2812
3380
|
function useWorkspaceFileManagerLayoutMode() {
|
|
2813
|
-
const [layoutMode, setLayoutModeState] =
|
|
3381
|
+
const [layoutMode, setLayoutModeState] = useState6(
|
|
2814
3382
|
readWorkspaceFileManagerLayoutMode
|
|
2815
3383
|
);
|
|
2816
3384
|
const setLayoutMode = useCallback4(
|
|
@@ -2824,7 +3392,7 @@ function useWorkspaceFileManagerLayoutMode() {
|
|
|
2824
3392
|
}
|
|
2825
3393
|
|
|
2826
3394
|
// src/ui/useWorkspaceFileEntryIconUrls.ts
|
|
2827
|
-
import { useCallback as useCallback5, useEffect as
|
|
3395
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useMemo as useMemo2, useState as useState7 } from "react";
|
|
2828
3396
|
|
|
2829
3397
|
// src/ui/workspaceFileEntryIconUrlQueue.ts
|
|
2830
3398
|
var defaultMaxConcurrentIconRequests = 3;
|
|
@@ -3002,28 +3570,28 @@ function buildIconTargetSignature(entries, options) {
|
|
|
3002
3570
|
}
|
|
3003
3571
|
function useWorkspaceFileEntryIconUrls(input) {
|
|
3004
3572
|
const { entries, includeImageThumbnails, resolveEntryIconUrl } = input;
|
|
3005
|
-
const queue =
|
|
3573
|
+
const queue = useMemo2(
|
|
3006
3574
|
() => createWorkspaceFileEntryIconUrlQueue({
|
|
3007
3575
|
includeImageThumbnails,
|
|
3008
3576
|
resolveEntryIconUrl
|
|
3009
3577
|
}),
|
|
3010
3578
|
[includeImageThumbnails, resolveEntryIconUrl]
|
|
3011
3579
|
);
|
|
3012
|
-
const [iconUrlByCacheKey, setIconUrlByCacheKey] =
|
|
3013
|
-
const iconTargetSignature =
|
|
3580
|
+
const [iconUrlByCacheKey, setIconUrlByCacheKey] = useState7(() => queue.snapshot());
|
|
3581
|
+
const iconTargetSignature = useMemo2(
|
|
3014
3582
|
() => buildIconTargetSignature(entries, { includeImageThumbnails }),
|
|
3015
3583
|
[entries, includeImageThumbnails]
|
|
3016
3584
|
);
|
|
3017
|
-
|
|
3585
|
+
useEffect5(() => {
|
|
3018
3586
|
queue.activate();
|
|
3019
3587
|
return () => {
|
|
3020
3588
|
queue.dispose();
|
|
3021
3589
|
};
|
|
3022
3590
|
}, [queue]);
|
|
3023
|
-
|
|
3591
|
+
useEffect5(() => {
|
|
3024
3592
|
queue.retainEntries(entries);
|
|
3025
3593
|
}, [entries, iconTargetSignature, queue]);
|
|
3026
|
-
|
|
3594
|
+
useEffect5(() => {
|
|
3027
3595
|
setIconUrlByCacheKey(queue.snapshot());
|
|
3028
3596
|
return queue.subscribe(() => {
|
|
3029
3597
|
setIconUrlByCacheKey(queue.snapshot());
|
|
@@ -3037,185 +3605,100 @@ function useWorkspaceFileEntryIconUrls(input) {
|
|
|
3037
3605
|
);
|
|
3038
3606
|
const reportEntryIconViewportLeave = useCallback5(
|
|
3039
3607
|
(entry) => {
|
|
3040
|
-
queue.leaveViewport(entry);
|
|
3041
|
-
},
|
|
3042
|
-
[queue]
|
|
3043
|
-
);
|
|
3044
|
-
return {
|
|
3045
|
-
iconUrlByCacheKey,
|
|
3046
|
-
reportEntryIconViewportEnter,
|
|
3047
|
-
reportEntryIconViewportLeave
|
|
3048
|
-
};
|
|
3049
|
-
}
|
|
3050
|
-
|
|
3051
|
-
// src/ui/workspaceFileManagerAnalytics.ts
|
|
3052
|
-
function shouldTrackDirectoryExpanded(input) {
|
|
3053
|
-
return normalizeDirectoryPath(input.currentDirectoryPath) !== normalizeDirectoryPath(input.nextDirectoryPath);
|
|
3054
|
-
}
|
|
3055
|
-
function normalizeDirectoryPath(path) {
|
|
3056
|
-
return path.trim().replaceAll("\\", "/").replace(/\/+$/u, "");
|
|
3057
|
-
}
|
|
3058
|
-
|
|
3059
|
-
// src/ui/useWorkspaceFileManagerService.ts
|
|
3060
|
-
import { useSnapshot } from "valtio";
|
|
3061
|
-
|
|
3062
|
-
// src/services/internal/workspaceFileManagerViewModel.ts
|
|
3063
|
-
function resolveWorkspaceFileManagerRootViewState(input) {
|
|
3064
|
-
const { state } = input;
|
|
3065
|
-
return {
|
|
3066
|
-
canImportFromDrop: state.capabilities.canImportFromDrop,
|
|
3067
|
-
currentDirectoryPath: state.currentDirectoryPath,
|
|
3068
|
-
isBusy: state.busyAction !== null
|
|
3069
|
-
};
|
|
3070
|
-
}
|
|
3071
|
-
function resolveWorkspaceFileManagerToolbarViewState(input) {
|
|
3072
|
-
const { copy, state } = input;
|
|
3073
|
-
const currentDirectoryPath = normalizeWorkspaceFilePath(
|
|
3074
|
-
state.currentDirectoryPath,
|
|
3075
|
-
state.root
|
|
3076
|
-
);
|
|
3077
|
-
return {
|
|
3078
|
-
breadcrumbs: buildWorkspaceFileBreadcrumbs(
|
|
3079
|
-
currentDirectoryPath,
|
|
3080
|
-
copy.t("breadcrumbRootLabel"),
|
|
3081
|
-
state.root
|
|
3082
|
-
),
|
|
3083
|
-
canGoBack: currentDirectoryPath !== normalizeWorkspaceFilePath(state.root) && state.navigationBackStack.length > 0,
|
|
3084
|
-
canGoForward: state.navigationForwardStack.length > 0,
|
|
3085
|
-
currentDirectoryPath,
|
|
3086
|
-
isBusy: state.busyAction !== null,
|
|
3087
|
-
isLoading: state.isLoading,
|
|
3088
|
-
isMutating: state.isMutating,
|
|
3089
|
-
isImporting: state.busyAction === "import",
|
|
3090
|
-
showImportAction: state.capabilities.canImportFromPicker
|
|
3091
|
-
};
|
|
3092
|
-
}
|
|
3093
|
-
function resolveWorkspaceFileManagerPanelsViewState(input) {
|
|
3094
|
-
const { state } = input;
|
|
3095
|
-
return {
|
|
3096
|
-
canMove: state.capabilities.canMove,
|
|
3097
|
-
contextMenuEntryPath: state.contextMenuEntryPath,
|
|
3098
|
-
entries: state.entries,
|
|
3099
|
-
error: state.error,
|
|
3100
|
-
inlineRenameEntryPath: state.inlineRenameEntryPath,
|
|
3101
|
-
inlineRenameValidation: state.inlineRenameValidation,
|
|
3102
|
-
isLoading: state.isLoading,
|
|
3103
|
-
isRenaming: state.busyAction === "rename",
|
|
3104
|
-
pendingDirectoryPath: state.pendingDirectoryPath,
|
|
3105
|
-
previewState: state.previewState,
|
|
3106
|
-
selectedEntry: findSelectedEntry(state),
|
|
3107
|
-
selectedPath: state.selectedPath,
|
|
3108
|
-
showDropOverlay: state.capabilities.canImportFromDrop && state.dragDepth > 0 && state.busyAction === null
|
|
3109
|
-
};
|
|
3110
|
-
}
|
|
3111
|
-
function resolveWorkspaceFileManagerDialogsViewState(input) {
|
|
3112
|
-
const { state } = input;
|
|
3113
|
-
const unsupportedDialogEntry = state.unsupportedDialog?.entryPath ? findEntry(state, state.unsupportedDialog.entryPath) : null;
|
|
3114
|
-
return {
|
|
3115
|
-
createDialog: state.createDialog,
|
|
3116
|
-
deleteDialogEntry: state.deleteDialog ? findEntry(state, state.deleteDialog.entryPath) : null,
|
|
3117
|
-
isBusy: state.busyAction !== null,
|
|
3118
|
-
isDeleting: state.busyAction === "delete",
|
|
3119
|
-
isImporting: state.busyAction === "import",
|
|
3120
|
-
isRenaming: state.busyAction === "rename",
|
|
3121
|
-
isViewing: state.busyAction === "view",
|
|
3122
|
-
unsupportedDialog: state.unsupportedDialog ? {
|
|
3123
|
-
actions: state.unsupportedDialog.actions,
|
|
3124
|
-
entry: unsupportedDialogEntry ?? void 0,
|
|
3125
|
-
kind: state.unsupportedDialog.kind,
|
|
3126
|
-
message: state.unsupportedDialog.message,
|
|
3127
|
-
title: state.unsupportedDialog.title
|
|
3128
|
-
} : null,
|
|
3129
|
-
importConflictDialog: state.importConflictDialog
|
|
3130
|
-
};
|
|
3131
|
-
}
|
|
3132
|
-
function resolveWorkspaceFileManagerContextMenuViewState(input) {
|
|
3133
|
-
const { state } = input;
|
|
3134
|
-
const contextMenuEntry = state.contextMenu?.entryPath ? findEntry(state, state.contextMenu.entryPath) : null;
|
|
3135
|
-
const isContextMenuFile = contextMenuEntry?.kind === "file";
|
|
3136
|
-
return {
|
|
3137
|
-
contextMenu: state.contextMenu ? {
|
|
3138
|
-
entry: contextMenuEntry,
|
|
3139
|
-
x: state.contextMenu.x,
|
|
3140
|
-
y: state.contextMenu.y
|
|
3141
|
-
} : null,
|
|
3142
|
-
currentDirectoryPath: state.currentDirectoryPath,
|
|
3143
|
-
isBusy: state.busyAction !== null,
|
|
3144
|
-
isLoading: state.isLoading,
|
|
3145
|
-
isMutating: state.isMutating,
|
|
3146
|
-
showCopyAction: state.capabilities.canCopy,
|
|
3147
|
-
showExportAction: state.capabilities.canExport,
|
|
3148
|
-
showImportAction: state.capabilities.canImportFromPicker,
|
|
3149
|
-
showMoveAction: state.capabilities.canMove,
|
|
3150
|
-
showOpenInAppBrowserAction: state.capabilities.canOpenInAppBrowser,
|
|
3151
|
-
showOpenInDefaultBrowserAction: state.capabilities.canOpenInDefaultBrowser,
|
|
3152
|
-
showOpenWithAction: state.capabilities.canOpenWith && isContextMenuFile,
|
|
3153
|
-
showOpenWithOtherAction: state.capabilities.canPickOtherOpenWithApplication && isContextMenuFile,
|
|
3154
|
-
showRevealInFolderAction: state.capabilities.canRevealInFolder,
|
|
3155
|
-
showRenameAction: state.capabilities.canRename
|
|
3156
|
-
};
|
|
3157
|
-
}
|
|
3158
|
-
function findSelectedEntry(state) {
|
|
3159
|
-
return state.entries.find((entry) => entry.path === state.selectedPath) ?? null;
|
|
3160
|
-
}
|
|
3161
|
-
function findEntry(state, entryPath) {
|
|
3162
|
-
return state.entries.find((entry) => entry.path === entryPath) ?? null;
|
|
3163
|
-
}
|
|
3164
|
-
|
|
3165
|
-
// src/ui/useWorkspaceFileManagerService.ts
|
|
3166
|
-
function useWorkspaceFileManagerRootView(session) {
|
|
3167
|
-
const state = useSnapshot(
|
|
3168
|
-
session.store
|
|
3169
|
-
);
|
|
3170
|
-
return resolveWorkspaceFileManagerRootViewState({ state });
|
|
3171
|
-
}
|
|
3172
|
-
function useWorkspaceFileManagerToolbarView(session, i18n) {
|
|
3173
|
-
const state = useSnapshot(
|
|
3174
|
-
session.store
|
|
3175
|
-
);
|
|
3176
|
-
return {
|
|
3177
|
-
view: resolveWorkspaceFileManagerToolbarViewState({
|
|
3178
|
-
copy: i18n,
|
|
3179
|
-
state
|
|
3180
|
-
})
|
|
3181
|
-
};
|
|
3182
|
-
}
|
|
3183
|
-
function useWorkspaceFileManagerPanelsView(session) {
|
|
3184
|
-
const state = useSnapshot(
|
|
3185
|
-
session.store
|
|
3186
|
-
);
|
|
3187
|
-
return {
|
|
3188
|
-
state,
|
|
3189
|
-
view: resolveWorkspaceFileManagerPanelsViewState({
|
|
3190
|
-
state
|
|
3191
|
-
})
|
|
3192
|
-
};
|
|
3193
|
-
}
|
|
3194
|
-
function useWorkspaceFileManagerDialogsView(session) {
|
|
3195
|
-
const state = useSnapshot(
|
|
3196
|
-
session.store
|
|
3197
|
-
);
|
|
3198
|
-
return {
|
|
3199
|
-
state,
|
|
3200
|
-
view: resolveWorkspaceFileManagerDialogsViewState({
|
|
3201
|
-
state
|
|
3202
|
-
})
|
|
3203
|
-
};
|
|
3204
|
-
}
|
|
3205
|
-
function useWorkspaceFileManagerContextMenuView(session) {
|
|
3206
|
-
const state = useSnapshot(
|
|
3207
|
-
session.store
|
|
3608
|
+
queue.leaveViewport(entry);
|
|
3609
|
+
},
|
|
3610
|
+
[queue]
|
|
3208
3611
|
);
|
|
3209
3612
|
return {
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
})
|
|
3613
|
+
iconUrlByCacheKey,
|
|
3614
|
+
reportEntryIconViewportEnter,
|
|
3615
|
+
reportEntryIconViewportLeave
|
|
3214
3616
|
};
|
|
3215
3617
|
}
|
|
3216
3618
|
|
|
3619
|
+
// src/ui/workspaceFileManagerAnalytics.ts
|
|
3620
|
+
function shouldTrackDirectoryExpanded(input) {
|
|
3621
|
+
return normalizeDirectoryPath(input.currentDirectoryPath) !== normalizeDirectoryPath(input.nextDirectoryPath);
|
|
3622
|
+
}
|
|
3623
|
+
function normalizeDirectoryPath(path) {
|
|
3624
|
+
return path.trim().replaceAll("\\", "/").replace(/\/+$/u, "");
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
// src/ui/workspaceFileManagerVisibleTree.ts
|
|
3628
|
+
function buildWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3629
|
+
return appendWorkspaceFileManagerVisibleTreeRows({
|
|
3630
|
+
...input,
|
|
3631
|
+
depth: 0
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
function collectWorkspaceFileManagerVisibleTreeEntries(rows) {
|
|
3635
|
+
return rows.flatMap((row) => row.kind === "entry" ? [row.entry] : []);
|
|
3636
|
+
}
|
|
3637
|
+
function appendWorkspaceFileManagerVisibleTreeRows(input) {
|
|
3638
|
+
const sortedEntries = sortWorkspaceFileEntriesForArrangeMode(
|
|
3639
|
+
input.entries,
|
|
3640
|
+
input.arrangeMode
|
|
3641
|
+
);
|
|
3642
|
+
const rows = [];
|
|
3643
|
+
for (const entry of sortedEntries) {
|
|
3644
|
+
const expandable = entry.kind === "directory" && entry.hasChildren;
|
|
3645
|
+
const expanded = expandable ? input.expandedDirectoryPaths[entry.path] === true : false;
|
|
3646
|
+
const childState = input.directoryExpansionByPath[entry.path];
|
|
3647
|
+
rows.push({
|
|
3648
|
+
depth: input.depth,
|
|
3649
|
+
entry,
|
|
3650
|
+
expanded,
|
|
3651
|
+
expandable,
|
|
3652
|
+
kind: "entry",
|
|
3653
|
+
loadingChildren: childState?.isLoading ?? false
|
|
3654
|
+
});
|
|
3655
|
+
if (!expanded) {
|
|
3656
|
+
continue;
|
|
3657
|
+
}
|
|
3658
|
+
if (!childState || childState.isLoading) {
|
|
3659
|
+
rows.push({
|
|
3660
|
+
depth: input.depth + 1,
|
|
3661
|
+
key: `${entry.path}:loading`,
|
|
3662
|
+
kind: "feedback",
|
|
3663
|
+
parentPath: entry.path,
|
|
3664
|
+
status: "loading"
|
|
3665
|
+
});
|
|
3666
|
+
continue;
|
|
3667
|
+
}
|
|
3668
|
+
if (childState.error) {
|
|
3669
|
+
rows.push({
|
|
3670
|
+
depth: input.depth + 1,
|
|
3671
|
+
key: `${entry.path}:error`,
|
|
3672
|
+
kind: "feedback",
|
|
3673
|
+
message: childState.error,
|
|
3674
|
+
parentPath: entry.path,
|
|
3675
|
+
status: "error"
|
|
3676
|
+
});
|
|
3677
|
+
continue;
|
|
3678
|
+
}
|
|
3679
|
+
if (childState.loaded && childState.entries.length === 0) {
|
|
3680
|
+
rows.push({
|
|
3681
|
+
depth: input.depth + 1,
|
|
3682
|
+
key: `${entry.path}:empty`,
|
|
3683
|
+
kind: "feedback",
|
|
3684
|
+
parentPath: entry.path,
|
|
3685
|
+
status: "empty"
|
|
3686
|
+
});
|
|
3687
|
+
continue;
|
|
3688
|
+
}
|
|
3689
|
+
rows.push(
|
|
3690
|
+
...appendWorkspaceFileManagerVisibleTreeRows({
|
|
3691
|
+
...input,
|
|
3692
|
+
depth: input.depth + 1,
|
|
3693
|
+
entries: childState.entries
|
|
3694
|
+
})
|
|
3695
|
+
);
|
|
3696
|
+
}
|
|
3697
|
+
return rows;
|
|
3698
|
+
}
|
|
3699
|
+
|
|
3217
3700
|
// src/ui/WorkspaceFileManager.tsx
|
|
3218
|
-
import { Fragment as Fragment3, jsx as
|
|
3701
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3219
3702
|
function WorkspaceFileManager({
|
|
3220
3703
|
className,
|
|
3221
3704
|
dateLocale,
|
|
@@ -3232,12 +3715,12 @@ function WorkspaceFileManager({
|
|
|
3232
3715
|
session,
|
|
3233
3716
|
surface = "card"
|
|
3234
3717
|
}) {
|
|
3235
|
-
const rootRef =
|
|
3718
|
+
const rootRef = useRef6(null);
|
|
3236
3719
|
const { arrangeMode, setArrangeMode } = useWorkspaceFileManagerArrangeMode();
|
|
3237
3720
|
const { layoutMode, setLayoutMode } = useWorkspaceFileManagerLayoutMode();
|
|
3238
3721
|
const rootView = useWorkspaceFileManagerRootView(session);
|
|
3239
3722
|
const { state: panelsState, view: panelsView } = useWorkspaceFileManagerPanelsView(session);
|
|
3240
|
-
|
|
3723
|
+
useEffect6(() => {
|
|
3241
3724
|
function handleCopyShortcut(event) {
|
|
3242
3725
|
if (!(event.metaKey || event.ctrlKey) || event.key !== "c" || event.shiftKey) {
|
|
3243
3726
|
return;
|
|
@@ -3266,7 +3749,7 @@ function WorkspaceFileManager({
|
|
|
3266
3749
|
window.removeEventListener("keydown", handleCopyShortcut);
|
|
3267
3750
|
};
|
|
3268
3751
|
}, [onCopyEntry, panelsState, panelsView.selectedEntry, session]);
|
|
3269
|
-
|
|
3752
|
+
useEffect6(() => {
|
|
3270
3753
|
function handleRenameShortcut(event) {
|
|
3271
3754
|
if (event.key !== "Enter" || event.metaKey || event.ctrlKey || event.altKey) {
|
|
3272
3755
|
return;
|
|
@@ -3292,7 +3775,7 @@ function WorkspaceFileManager({
|
|
|
3292
3775
|
window.removeEventListener("keydown", handleRenameShortcut);
|
|
3293
3776
|
};
|
|
3294
3777
|
}, [panelsState, panelsView.selectedEntry, session]);
|
|
3295
|
-
|
|
3778
|
+
useEffect6(() => {
|
|
3296
3779
|
function resetDropOverlay() {
|
|
3297
3780
|
session.resetDragDepth();
|
|
3298
3781
|
}
|
|
@@ -3375,7 +3858,7 @@ function WorkspaceFileManager({
|
|
|
3375
3858
|
rootView.currentDirectoryPath
|
|
3376
3859
|
);
|
|
3377
3860
|
}
|
|
3378
|
-
return /* @__PURE__ */
|
|
3861
|
+
return /* @__PURE__ */ jsxs7(
|
|
3379
3862
|
"section",
|
|
3380
3863
|
{
|
|
3381
3864
|
className: cn6(
|
|
@@ -3391,8 +3874,8 @@ function WorkspaceFileManager({
|
|
|
3391
3874
|
onDrop: handleDrop,
|
|
3392
3875
|
ref: rootRef,
|
|
3393
3876
|
children: [
|
|
3394
|
-
/* @__PURE__ */
|
|
3395
|
-
/* @__PURE__ */
|
|
3877
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
3878
|
+
/* @__PURE__ */ jsx8(
|
|
3396
3879
|
WorkspaceFileManagerToolbarContainer,
|
|
3397
3880
|
{
|
|
3398
3881
|
i18n,
|
|
@@ -3404,14 +3887,14 @@ function WorkspaceFileManager({
|
|
|
3404
3887
|
session
|
|
3405
3888
|
}
|
|
3406
3889
|
),
|
|
3407
|
-
/* @__PURE__ */
|
|
3890
|
+
/* @__PURE__ */ jsx8(
|
|
3408
3891
|
"div",
|
|
3409
3892
|
{
|
|
3410
3893
|
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",
|
|
3411
3894
|
style: {
|
|
3412
3895
|
"--workspace-file-manager-dialog-overlay-z-index": "20"
|
|
3413
3896
|
},
|
|
3414
|
-
children: /* @__PURE__ */
|
|
3897
|
+
children: /* @__PURE__ */ jsx8(
|
|
3415
3898
|
WorkspaceFileManagerPanelsContainer,
|
|
3416
3899
|
{
|
|
3417
3900
|
dateLocale,
|
|
@@ -3429,8 +3912,8 @@ function WorkspaceFileManager({
|
|
|
3429
3912
|
}
|
|
3430
3913
|
)
|
|
3431
3914
|
] }),
|
|
3432
|
-
/* @__PURE__ */
|
|
3433
|
-
/* @__PURE__ */
|
|
3915
|
+
/* @__PURE__ */ jsx8(WorkspaceFileManagerDialogsContainer, { i18n, session }),
|
|
3916
|
+
/* @__PURE__ */ jsx8(
|
|
3434
3917
|
WorkspaceFileManagerContextMenuContainer,
|
|
3435
3918
|
{
|
|
3436
3919
|
hostOs,
|
|
@@ -3456,7 +3939,7 @@ function WorkspaceFileManagerToolbarContainer({
|
|
|
3456
3939
|
session
|
|
3457
3940
|
}) {
|
|
3458
3941
|
const { view } = useWorkspaceFileManagerToolbarView(session, i18n);
|
|
3459
|
-
return /* @__PURE__ */
|
|
3942
|
+
return /* @__PURE__ */ jsx8(
|
|
3460
3943
|
WorkspaceFileManagerToolbar,
|
|
3461
3944
|
{
|
|
3462
3945
|
breadcrumbs: view.breadcrumbs,
|
|
@@ -3505,20 +3988,38 @@ function WorkspaceFileManagerPanelsContainer({
|
|
|
3505
3988
|
session
|
|
3506
3989
|
}) {
|
|
3507
3990
|
const { state, view } = useWorkspaceFileManagerPanelsView(session);
|
|
3508
|
-
const arrangedEntries =
|
|
3991
|
+
const arrangedEntries = useMemo3(
|
|
3509
3992
|
() => sortWorkspaceFileEntriesForArrangeMode(state.entries, arrangeMode),
|
|
3510
3993
|
[arrangeMode, state.entries]
|
|
3511
3994
|
);
|
|
3995
|
+
const treeRows = useMemo3(
|
|
3996
|
+
() => buildWorkspaceFileManagerVisibleTreeRows({
|
|
3997
|
+
arrangeMode,
|
|
3998
|
+
directoryExpansionByPath: state.directoryExpansionByPath,
|
|
3999
|
+
entries: arrangedEntries,
|
|
4000
|
+
expandedDirectoryPaths: state.expandedDirectoryPaths
|
|
4001
|
+
}),
|
|
4002
|
+
[
|
|
4003
|
+
arrangeMode,
|
|
4004
|
+
arrangedEntries,
|
|
4005
|
+
state.directoryExpansionByPath,
|
|
4006
|
+
state.expandedDirectoryPaths
|
|
4007
|
+
]
|
|
4008
|
+
);
|
|
4009
|
+
const visibleTreeEntries = useMemo3(
|
|
4010
|
+
() => collectWorkspaceFileManagerVisibleTreeEntries(treeRows),
|
|
4011
|
+
[treeRows]
|
|
4012
|
+
);
|
|
3512
4013
|
const {
|
|
3513
4014
|
iconUrlByCacheKey,
|
|
3514
4015
|
reportEntryIconViewportEnter,
|
|
3515
4016
|
reportEntryIconViewportLeave
|
|
3516
4017
|
} = useWorkspaceFileEntryIconUrls({
|
|
3517
|
-
entries: arrangedEntries,
|
|
4018
|
+
entries: layoutMode === "list" ? visibleTreeEntries : arrangedEntries,
|
|
3518
4019
|
includeImageThumbnails: true,
|
|
3519
4020
|
resolveEntryIconUrl
|
|
3520
4021
|
});
|
|
3521
|
-
return /* @__PURE__ */
|
|
4022
|
+
return /* @__PURE__ */ jsx8(
|
|
3522
4023
|
WorkspaceFileManagerPanels,
|
|
3523
4024
|
{
|
|
3524
4025
|
arrangeMode,
|
|
@@ -3534,6 +4035,7 @@ function WorkspaceFileManagerPanelsContainer({
|
|
|
3534
4035
|
layoutMode,
|
|
3535
4036
|
pendingDirectoryPath: view.pendingDirectoryPath,
|
|
3536
4037
|
previewState: view.previewState,
|
|
4038
|
+
treeRows,
|
|
3537
4039
|
onEntryIconViewportEnter: reportEntryIconViewportEnter,
|
|
3538
4040
|
onEntryIconViewportLeave: reportEntryIconViewportLeave,
|
|
3539
4041
|
selectedEntry: view.selectedEntry,
|
|
@@ -3569,6 +4071,12 @@ function WorkspaceFileManagerPanelsContainer({
|
|
|
3569
4071
|
},
|
|
3570
4072
|
onSelect: (path) => {
|
|
3571
4073
|
session.select(path);
|
|
4074
|
+
},
|
|
4075
|
+
onToggleDirectoryExpanded: (entry, expanded) => {
|
|
4076
|
+
if (!expanded) {
|
|
4077
|
+
onDirectoryExpanded?.(entry.path);
|
|
4078
|
+
}
|
|
4079
|
+
void session.toggleDirectoryExpanded(entry);
|
|
3572
4080
|
}
|
|
3573
4081
|
}
|
|
3574
4082
|
);
|
|
@@ -3578,8 +4086,8 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
3578
4086
|
session
|
|
3579
4087
|
}) {
|
|
3580
4088
|
const { state, view } = useWorkspaceFileManagerDialogsView(session);
|
|
3581
|
-
return /* @__PURE__ */
|
|
3582
|
-
/* @__PURE__ */
|
|
4089
|
+
return /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
4090
|
+
/* @__PURE__ */ jsx8(
|
|
3583
4091
|
WorkspaceFileManagerCreateDialog,
|
|
3584
4092
|
{
|
|
3585
4093
|
busy: view.isBusy && state.busyAction === "create",
|
|
@@ -3596,7 +4104,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
3596
4104
|
}
|
|
3597
4105
|
}
|
|
3598
4106
|
),
|
|
3599
|
-
/* @__PURE__ */
|
|
4107
|
+
/* @__PURE__ */ jsx8(
|
|
3600
4108
|
WorkspaceFileManagerDeleteDialog,
|
|
3601
4109
|
{
|
|
3602
4110
|
busy: view.isDeleting,
|
|
@@ -3610,7 +4118,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
3610
4118
|
}
|
|
3611
4119
|
}
|
|
3612
4120
|
),
|
|
3613
|
-
/* @__PURE__ */
|
|
4121
|
+
/* @__PURE__ */ jsx8(
|
|
3614
4122
|
WorkspaceFileManagerImportConflictDialog,
|
|
3615
4123
|
{
|
|
3616
4124
|
busy: view.isImporting,
|
|
@@ -3624,7 +4132,7 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
3624
4132
|
}
|
|
3625
4133
|
}
|
|
3626
4134
|
),
|
|
3627
|
-
/* @__PURE__ */
|
|
4135
|
+
/* @__PURE__ */ jsx8(
|
|
3628
4136
|
WorkspaceFileManagerUnsupportedDialog,
|
|
3629
4137
|
{
|
|
3630
4138
|
copy: i18n,
|
|
@@ -3640,208 +4148,6 @@ function WorkspaceFileManagerDialogsContainer({
|
|
|
3640
4148
|
)
|
|
3641
4149
|
] });
|
|
3642
4150
|
}
|
|
3643
|
-
function WorkspaceFileManagerContextMenuContainer({
|
|
3644
|
-
hostOs,
|
|
3645
|
-
i18n,
|
|
3646
|
-
onCopyEntry,
|
|
3647
|
-
onCopyPath,
|
|
3648
|
-
openInAppBrowserIcon,
|
|
3649
|
-
resolveOpenWithApplicationIcon,
|
|
3650
|
-
session
|
|
3651
|
-
}) {
|
|
3652
|
-
const contextMenuRef = useRef5(null);
|
|
3653
|
-
const { view } = useWorkspaceFileManagerContextMenuView(session);
|
|
3654
|
-
const [openWithApplications, setOpenWithApplications] = useState7([]);
|
|
3655
|
-
const [openWithLoading, setOpenWithLoading] = useState7(false);
|
|
3656
|
-
useEffect5(() => {
|
|
3657
|
-
const entry = view.contextMenu?.entry;
|
|
3658
|
-
if (!entry || !view.showOpenWithAction) {
|
|
3659
|
-
return;
|
|
3660
|
-
}
|
|
3661
|
-
const cachedApplications = session.getCachedOpenWithApplications(entry);
|
|
3662
|
-
if (cachedApplications) {
|
|
3663
|
-
setOpenWithApplications(cachedApplications);
|
|
3664
|
-
setOpenWithLoading(false);
|
|
3665
|
-
return;
|
|
3666
|
-
}
|
|
3667
|
-
let cancelled = false;
|
|
3668
|
-
setOpenWithLoading(true);
|
|
3669
|
-
void session.listOpenWithApplications(entry).then((applications) => {
|
|
3670
|
-
if (cancelled) {
|
|
3671
|
-
return;
|
|
3672
|
-
}
|
|
3673
|
-
setOpenWithApplications(applications);
|
|
3674
|
-
setOpenWithLoading(false);
|
|
3675
|
-
}).catch(() => {
|
|
3676
|
-
if (cancelled) {
|
|
3677
|
-
return;
|
|
3678
|
-
}
|
|
3679
|
-
setOpenWithApplications([]);
|
|
3680
|
-
setOpenWithLoading(false);
|
|
3681
|
-
});
|
|
3682
|
-
return () => {
|
|
3683
|
-
cancelled = true;
|
|
3684
|
-
};
|
|
3685
|
-
}, [session, view.contextMenu?.entry?.path, view.showOpenWithAction]);
|
|
3686
|
-
useCloseContextMenuOnOutsideInteraction({
|
|
3687
|
-
contextMenuRef,
|
|
3688
|
-
isOpen: view.contextMenu !== null,
|
|
3689
|
-
session
|
|
3690
|
-
});
|
|
3691
|
-
return /* @__PURE__ */ jsx6(
|
|
3692
|
-
WorkspaceFileManagerContextMenu,
|
|
3693
|
-
{
|
|
3694
|
-
busy: view.isBusy || view.isLoading || view.isMutating,
|
|
3695
|
-
copy: i18n,
|
|
3696
|
-
contextMenu: view.contextMenu,
|
|
3697
|
-
contextMenuRef,
|
|
3698
|
-
showCopyAction: view.showCopyAction,
|
|
3699
|
-
showImportAction: view.showImportAction,
|
|
3700
|
-
showExportAction: view.showExportAction,
|
|
3701
|
-
showOpenInAppBrowserAction: view.showOpenInAppBrowserAction && !!view.contextMenu?.entry && isWorkspaceFileBrowserOpenable(view.contextMenu.entry),
|
|
3702
|
-
showOpenInDefaultBrowserAction: view.showOpenInDefaultBrowserAction && !!view.contextMenu?.entry && isWorkspaceFileBrowserOpenable(view.contextMenu.entry),
|
|
3703
|
-
showOpenWithAction: view.showOpenWithAction,
|
|
3704
|
-
showOpenWithOtherAction: view.showOpenWithOtherAction,
|
|
3705
|
-
showRevealInFolderAction: view.showRevealInFolderAction,
|
|
3706
|
-
showRenameAction: view.showRenameAction,
|
|
3707
|
-
revealInFolderLabel: resolveRevealInFolderLabel(i18n, hostOs),
|
|
3708
|
-
openInAppBrowserIcon,
|
|
3709
|
-
openWithApplications,
|
|
3710
|
-
openWithLoading,
|
|
3711
|
-
resolveOpenWithApplicationIcon,
|
|
3712
|
-
onClose: () => {
|
|
3713
|
-
session.closeContextMenu();
|
|
3714
|
-
},
|
|
3715
|
-
onCreateDirectory: () => {
|
|
3716
|
-
session.openCreateDirectoryDialog();
|
|
3717
|
-
},
|
|
3718
|
-
onCreateFile: () => {
|
|
3719
|
-
session.openCreateFileDialog();
|
|
3720
|
-
},
|
|
3721
|
-
onCopy: async () => {
|
|
3722
|
-
const entry = view.contextMenu?.entry;
|
|
3723
|
-
if (!entry) {
|
|
3724
|
-
return;
|
|
3725
|
-
}
|
|
3726
|
-
session.closeContextMenu();
|
|
3727
|
-
await session.copyToClipboard(entry);
|
|
3728
|
-
if (onCopyEntry) {
|
|
3729
|
-
await onCopyEntry();
|
|
3730
|
-
}
|
|
3731
|
-
},
|
|
3732
|
-
onCopyPath: async () => {
|
|
3733
|
-
const path = view.contextMenu?.entry?.path;
|
|
3734
|
-
if (!path) {
|
|
3735
|
-
return;
|
|
3736
|
-
}
|
|
3737
|
-
session.closeContextMenu();
|
|
3738
|
-
if (onCopyPath) {
|
|
3739
|
-
await onCopyPath(path);
|
|
3740
|
-
return;
|
|
3741
|
-
}
|
|
3742
|
-
await navigator.clipboard.writeText(path);
|
|
3743
|
-
},
|
|
3744
|
-
onDelete: () => {
|
|
3745
|
-
const entry = view.contextMenu?.entry;
|
|
3746
|
-
if (!entry) {
|
|
3747
|
-
return;
|
|
3748
|
-
}
|
|
3749
|
-
session.openDeleteDialog(entry);
|
|
3750
|
-
},
|
|
3751
|
-
onRename: () => {
|
|
3752
|
-
const entry = view.contextMenu?.entry;
|
|
3753
|
-
if (!entry) {
|
|
3754
|
-
return;
|
|
3755
|
-
}
|
|
3756
|
-
session.startInlineRename(entry);
|
|
3757
|
-
},
|
|
3758
|
-
onExport: async () => {
|
|
3759
|
-
const entry = view.contextMenu?.entry;
|
|
3760
|
-
if (!entry) {
|
|
3761
|
-
return;
|
|
3762
|
-
}
|
|
3763
|
-
await session.exportEntry(entry);
|
|
3764
|
-
},
|
|
3765
|
-
onOpen: async () => {
|
|
3766
|
-
const entry = view.contextMenu?.entry;
|
|
3767
|
-
if (!entry) {
|
|
3768
|
-
return;
|
|
3769
|
-
}
|
|
3770
|
-
await session.openEntry(entry);
|
|
3771
|
-
},
|
|
3772
|
-
onOpenInAppBrowser: async () => {
|
|
3773
|
-
const entry = view.contextMenu?.entry;
|
|
3774
|
-
if (!entry) {
|
|
3775
|
-
return;
|
|
3776
|
-
}
|
|
3777
|
-
await session.openFileInAppBrowser(entry);
|
|
3778
|
-
},
|
|
3779
|
-
onOpenInDefaultBrowser: async () => {
|
|
3780
|
-
const entry = view.contextMenu?.entry;
|
|
3781
|
-
if (!entry) {
|
|
3782
|
-
return;
|
|
3783
|
-
}
|
|
3784
|
-
await session.openFileInDefaultBrowser(entry);
|
|
3785
|
-
},
|
|
3786
|
-
onOpenWithApplication: async (applicationPath) => {
|
|
3787
|
-
const entry = view.contextMenu?.entry;
|
|
3788
|
-
if (!entry) {
|
|
3789
|
-
return;
|
|
3790
|
-
}
|
|
3791
|
-
await session.openFileWithApplication(entry, applicationPath);
|
|
3792
|
-
},
|
|
3793
|
-
onOpenWithOtherApplication: async () => {
|
|
3794
|
-
const entry = view.contextMenu?.entry;
|
|
3795
|
-
if (!entry) {
|
|
3796
|
-
return;
|
|
3797
|
-
}
|
|
3798
|
-
await session.openFileWithOtherApplication(entry);
|
|
3799
|
-
},
|
|
3800
|
-
onRevealInFolder: async () => {
|
|
3801
|
-
const entry = view.contextMenu?.entry;
|
|
3802
|
-
if (!entry) {
|
|
3803
|
-
return;
|
|
3804
|
-
}
|
|
3805
|
-
await session.revealEntry(entry);
|
|
3806
|
-
},
|
|
3807
|
-
onImport: async () => {
|
|
3808
|
-
session.closeContextMenu();
|
|
3809
|
-
await session.importFiles(
|
|
3810
|
-
view.contextMenu?.entry?.kind === "directory" ? view.contextMenu.entry.path : view.currentDirectoryPath
|
|
3811
|
-
);
|
|
3812
|
-
}
|
|
3813
|
-
}
|
|
3814
|
-
);
|
|
3815
|
-
}
|
|
3816
|
-
function useCloseContextMenuOnOutsideInteraction(input) {
|
|
3817
|
-
const { contextMenuRef, isOpen, session } = input;
|
|
3818
|
-
useEffect5(() => {
|
|
3819
|
-
if (!isOpen) {
|
|
3820
|
-
return;
|
|
3821
|
-
}
|
|
3822
|
-
function handlePointerDown(event) {
|
|
3823
|
-
const target = event.target;
|
|
3824
|
-
if (target instanceof Node && contextMenuRef.current?.contains(target)) {
|
|
3825
|
-
return;
|
|
3826
|
-
}
|
|
3827
|
-
if (target instanceof Element && target.closest("[data-workspace-file-manager-submenu]")) {
|
|
3828
|
-
return;
|
|
3829
|
-
}
|
|
3830
|
-
session.closeContextMenu();
|
|
3831
|
-
}
|
|
3832
|
-
function handleKeyDown(event) {
|
|
3833
|
-
if (event.key === "Escape") {
|
|
3834
|
-
session.closeContextMenu();
|
|
3835
|
-
}
|
|
3836
|
-
}
|
|
3837
|
-
window.addEventListener("pointerdown", handlePointerDown);
|
|
3838
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
3839
|
-
return () => {
|
|
3840
|
-
window.removeEventListener("pointerdown", handlePointerDown);
|
|
3841
|
-
window.removeEventListener("keydown", handleKeyDown);
|
|
3842
|
-
};
|
|
3843
|
-
}, [contextMenuRef, isOpen, session]);
|
|
3844
|
-
}
|
|
3845
4151
|
function isEditableKeyboardTarget(target) {
|
|
3846
4152
|
if (!(target instanceof HTMLElement)) {
|
|
3847
4153
|
return false;
|