@michengai/dsh-archive-manager 0.1.41 → 0.1.43
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/CHANGELOG.md +24 -0
- package/CHANGELOG.zh-CN.md +24 -0
- package/README.md +11 -5
- package/README.zh-CN.md +11 -5
- package/cordis.patch.yml +7 -0
- package/lib/archive-experience.js +7 -2
- package/lib/client.js +369 -139
- package/lib/workspace.js +143 -188
- package/package.json +41 -41
package/lib/client.js
CHANGED
|
@@ -11,11 +11,15 @@
|
|
|
11
11
|
return error instanceof ArchiveNavigationError ? t(`archives.${error.code}`) : String(error?.message ?? error);
|
|
12
12
|
}
|
|
13
13
|
async function openArchivedConversation(actions, sessionId, restore, isActive = () => true) {
|
|
14
|
-
if (restore)
|
|
14
|
+
if (restore) {
|
|
15
|
+
if (typeof actions.prepare === "function") await actions.prepare(sessionId);
|
|
16
|
+
if (!isActive()) return;
|
|
17
|
+
await actions.restore(sessionId);
|
|
18
|
+
}
|
|
15
19
|
if (isActive()) await actions.open(sessionId);
|
|
16
20
|
}
|
|
17
21
|
function allowArchivedNavigation(navigation, sessions, workspaces, { onOpened = () => {
|
|
18
|
-
}, warn = (...args) => console.warn(...args) } = {}) {
|
|
22
|
+
}, beginNavigation, warn = (...args) => console.warn(...args) } = {}) {
|
|
19
23
|
let allowed;
|
|
20
24
|
const original = navigation?.clearArchivedCurrent;
|
|
21
25
|
const descriptor = navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent");
|
|
@@ -42,6 +46,7 @@
|
|
|
42
46
|
warn("archive-manager: \u5F52\u6863\u5BFC\u822A\u9002\u914D\u4E0D\u53EF\u7528\u6216\u5DF2\u88AB\u66FF\u6362\u3002");
|
|
43
47
|
throw new ArchiveNavigationError("navigationUnavailable");
|
|
44
48
|
}
|
|
49
|
+
beginNavigation?.();
|
|
45
50
|
sessions.open(id);
|
|
46
51
|
if (sessions.list.getSnapshot().current !== id) {
|
|
47
52
|
warn("archive-manager: \u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\u3002", { cleanupAvailable: typeof original === "function" });
|
|
@@ -468,12 +473,6 @@
|
|
|
468
473
|
return value;
|
|
469
474
|
}
|
|
470
475
|
};
|
|
471
|
-
const workspaceIdSchema = {
|
|
472
|
-
parse(value) {
|
|
473
|
-
if (typeof value !== "string" || value.length === 0) throw new TypeError(`workspaceId must be a non-empty string, got ${String(value)}`);
|
|
474
|
-
return value;
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
476
|
const archivedSetSchema = {
|
|
478
477
|
parse(value) {
|
|
479
478
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
@@ -497,22 +496,6 @@
|
|
|
497
496
|
throw new TypeError("target.scope must be all, ungrouped, workspace with a non-empty workspaceId, or sessions with non-empty sessionIds");
|
|
498
497
|
}
|
|
499
498
|
};
|
|
500
|
-
const unarchivedBatchSchema = {
|
|
501
|
-
parse(value) {
|
|
502
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
503
|
-
if (!Array.isArray(value.archivedSessionIds) || value.archivedSessionIds.some((id) => typeof id !== "string")) throw new TypeError("archivedSessionIds must be a string array");
|
|
504
|
-
if (!Array.isArray(value.unarchivedSessionIds) || value.unarchivedSessionIds.some((id) => typeof id !== "string")) throw new TypeError("unarchivedSessionIds must be a string array");
|
|
505
|
-
return value;
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
const archivedWorkspaceBatchSchema = {
|
|
509
|
-
parse(value) {
|
|
510
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
511
|
-
if (!Array.isArray(value.archivedSessionIds) || value.archivedSessionIds.some((id) => typeof id !== "string")) throw new TypeError("archivedSessionIds must be a string array");
|
|
512
|
-
if (!Array.isArray(value.archivedSessionIdsAdded) || value.archivedSessionIdsAdded.some((id) => typeof id !== "string")) throw new TypeError("archivedSessionIdsAdded must be a string array");
|
|
513
|
-
return value;
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
499
|
const deletedBatchSchema = {
|
|
517
500
|
parse(value) {
|
|
518
501
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
@@ -572,44 +555,6 @@
|
|
|
572
555
|
},
|
|
573
556
|
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
574
557
|
},
|
|
575
|
-
{
|
|
576
|
-
id: "@michengai/dsh-archive-manager#workspaceRegistry/unarchiveSessions",
|
|
577
|
-
service: "workspaceRegistry",
|
|
578
|
-
namespace: "workspaceRegistry",
|
|
579
|
-
method: "unarchiveSessions",
|
|
580
|
-
invocation: { kind: "direct" },
|
|
581
|
-
parameters: [{
|
|
582
|
-
name: "target",
|
|
583
|
-
wire: "target",
|
|
584
|
-
source: "json",
|
|
585
|
-
codec: { mode: "strict", typeSymbol: "@michengai/dsh-archive-manager/types#ArchivedBatchTarget", schema: archivedBatchTargetSchema }
|
|
586
|
-
}],
|
|
587
|
-
result: {
|
|
588
|
-
mode: "strict",
|
|
589
|
-
typeSymbol: "@michengai/dsh-archive-manager/types#UnarchivedBatch",
|
|
590
|
-
schema: unarchivedBatchSchema
|
|
591
|
-
},
|
|
592
|
-
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
id: "@michengai/dsh-archive-manager#workspaceRegistry/archiveWorkspaceSessions",
|
|
596
|
-
service: "workspaceRegistry",
|
|
597
|
-
namespace: "workspaceRegistry",
|
|
598
|
-
method: "archiveWorkspaceSessions",
|
|
599
|
-
invocation: { kind: "direct" },
|
|
600
|
-
parameters: [{
|
|
601
|
-
name: "workspaceId",
|
|
602
|
-
wire: "workspaceId",
|
|
603
|
-
source: "json",
|
|
604
|
-
codec: { mode: "strict", typeSymbol: "@deepseek-ai/dsh-workspace/types#WorkspaceId", schema: workspaceIdSchema }
|
|
605
|
-
}],
|
|
606
|
-
result: {
|
|
607
|
-
mode: "strict",
|
|
608
|
-
typeSymbol: "@michengai/dsh-archive-manager/types#ArchivedWorkspaceBatch",
|
|
609
|
-
schema: archivedWorkspaceBatchSchema
|
|
610
|
-
},
|
|
611
|
-
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
612
|
-
},
|
|
613
558
|
{
|
|
614
559
|
id: "@michengai/dsh-archive-manager#workspaceRegistry/deleteArchivedSessions",
|
|
615
560
|
service: "workspaceRegistry",
|
|
@@ -686,7 +631,23 @@
|
|
|
686
631
|
return indexed;
|
|
687
632
|
}
|
|
688
633
|
const FLAT_SESSION_ORDER_KEY = "__flat_session_order__";
|
|
634
|
+
const WORKSPACE_VIEW_PERSIST_KEY = "dsh.archive-manager.workspace.view.v1";
|
|
635
|
+
const LEGACY_WORKSPACE_VIEW_PERSIST_KEY = "dsh.workspace.view.v5";
|
|
636
|
+
function migrateWorkspaceViewPersist(storage) {
|
|
637
|
+
const target = storage ?? globalThis.localStorage;
|
|
638
|
+
if (target == null || typeof target.getItem !== "function" || typeof target.setItem !== "function") return false;
|
|
639
|
+
try {
|
|
640
|
+
if (target.getItem(WORKSPACE_VIEW_PERSIST_KEY) != null) return false;
|
|
641
|
+
const legacy = target.getItem(LEGACY_WORKSPACE_VIEW_PERSIST_KEY);
|
|
642
|
+
if (legacy == null) return false;
|
|
643
|
+
target.setItem(WORKSPACE_VIEW_PERSIST_KEY, legacy);
|
|
644
|
+
return true;
|
|
645
|
+
} catch {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
689
649
|
function createWorkspaceViewStore() {
|
|
650
|
+
migrateWorkspaceViewPersist();
|
|
690
651
|
return (0, _deepseek_ai_dsh_client_store.defineStore)({
|
|
691
652
|
init: () => ({
|
|
692
653
|
groupBy: "workspace",
|
|
@@ -696,7 +657,7 @@
|
|
|
696
657
|
sessionOrderByAccount: {},
|
|
697
658
|
sessionUpdatedAtByAccount: {}
|
|
698
659
|
}),
|
|
699
|
-
persist:
|
|
660
|
+
persist: WORKSPACE_VIEW_PERSIST_KEY,
|
|
700
661
|
actions: {
|
|
701
662
|
setGroupBy: (d, mode) => {
|
|
702
663
|
d.groupBy = mode;
|
|
@@ -729,9 +690,27 @@
|
|
|
729
690
|
function GithubMark16() {
|
|
730
691
|
return (0, react_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", width: 16, height: 16, "aria-hidden": true, focusable: "false", children: (0, react_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M8 0a8 8 0 0 0-2.53 15.59c.4.074.547-.173.547-.385 0-.19-.007-.693-.01-1.36-2.226.484-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.726-.496.055-.486.055-.486.803.056 1.225.824 1.225.824.714 1.223 1.872.87 2.328.665.072-.517.28-.87.508-1.07-1.777-.202-3.645-.888-3.645-3.956 0-.874.31-1.588.823-2.148-.083-.202-.357-1.017.078-2.12 0 0 .672-.215 2.2.82A7.65 7.65 0 0 1 8 4.8c.68.003 1.365.092 2.004.27 1.527-1.035 2.197-.82 2.197-.82.437 1.103.162 1.918.08 2.12.513.56.822 1.274.822 2.148 0 3.076-1.872 3.752-3.654 3.95.288.248.544.735.544 1.482 0 1.07-.01 1.932-.01 2.195 0 .214.144.463.55.384A8.001 8.001 0 0 0 8 0Z" }) });
|
|
731
692
|
}
|
|
732
|
-
function ArchivedSessionsSection({ sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, openConversation, viewState, close, t }) {
|
|
693
|
+
function ArchivedSessionsSection({ archiveSessions, sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, openConversation, focusSessionWorkspace, viewState, close, t }) {
|
|
733
694
|
const sessions = (0, react.useSyncExternalStore)(sessionStore.subscribe, sessionStore.getSnapshot);
|
|
734
695
|
const workspaceState = (0, react.useSyncExternalStore)(workspaceStore.subscribe, workspaceStore.getSnapshot);
|
|
696
|
+
const [archiveTab, setArchiveTab] = (0, react.useState)("archived");
|
|
697
|
+
const isArchived = archiveTab === "archived";
|
|
698
|
+
const [archiveTarget, setArchiveTarget] = (0, react.useState)(null);
|
|
699
|
+
const [archiveGroup, setArchiveGroup] = (0, react.useState)(null);
|
|
700
|
+
const requestArchive = (ids, group = null) => {
|
|
701
|
+
setError(null);
|
|
702
|
+
setNotice(null);
|
|
703
|
+
setArchiveGroup(group);
|
|
704
|
+
setArchiveTarget(ids);
|
|
705
|
+
};
|
|
706
|
+
const closeArchive = () => {
|
|
707
|
+
if (!busy) {
|
|
708
|
+
setArchiveTarget(null);
|
|
709
|
+
setArchiveGroup(null);
|
|
710
|
+
setError(null);
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
const archiveBusy = (0, react.useRef)(false);
|
|
735
714
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(null);
|
|
736
715
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
737
716
|
const [error, setError] = (0, react.useState)(null);
|
|
@@ -756,13 +735,29 @@
|
|
|
756
735
|
navigationPending.current = true;
|
|
757
736
|
setBusy(true);
|
|
758
737
|
setError(null);
|
|
738
|
+
let restored = false;
|
|
759
739
|
try {
|
|
760
|
-
await openArchivedConversation({
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
740
|
+
await openArchivedConversation({
|
|
741
|
+
prepare: restore ? async (id) => {
|
|
742
|
+
await focusSessionWorkspace?.(id);
|
|
743
|
+
} : void 0,
|
|
744
|
+
restore: async (id) => {
|
|
745
|
+
await unarchiveSession(id);
|
|
746
|
+
restored = true;
|
|
747
|
+
},
|
|
748
|
+
open: async (id) => {
|
|
749
|
+
await openConversation(id);
|
|
750
|
+
if (navigationActive.current) close?.();
|
|
751
|
+
}
|
|
752
|
+
}, session.id, restore, () => navigationActive.current);
|
|
764
753
|
} catch (reason) {
|
|
765
|
-
if (navigationActive.current)
|
|
754
|
+
if (!navigationActive.current) return;
|
|
755
|
+
if (restored) {
|
|
756
|
+
setArchiveTab("unarchived");
|
|
757
|
+
const group = groups.find((item) => item.sessions.some((row) => row.id === session.id));
|
|
758
|
+
if (group !== void 0) setProject(group.key);
|
|
759
|
+
}
|
|
760
|
+
setError(formatArchiveNavigationError(reason, t));
|
|
766
761
|
} finally {
|
|
767
762
|
navigationPending.current = false;
|
|
768
763
|
if (navigationActive.current) setBusy(false);
|
|
@@ -771,7 +766,42 @@
|
|
|
771
766
|
(0, react.useEffect)(() => {
|
|
772
767
|
if (viewState) Object.assign(viewState, { query, project, sortBy });
|
|
773
768
|
}, [query, project, sortBy, viewState]);
|
|
774
|
-
const
|
|
769
|
+
const eligibleIds = (0, react.useMemo)(() => isArchived ? workspaceState.archivedSessionIds : unarchivedSessionIds(sessions.byId, workspaceState.archivedSessionIds), [isArchived, sessions.byId, workspaceState.archivedSessionIds]);
|
|
770
|
+
const groups = (0, react.useMemo)(() => deriveArchivedGroups(sessions.byId, workspaceState.items, eligibleIds, t("group.ungrouped")), [sessions.byId, workspaceState, eligibleIds, t]);
|
|
771
|
+
const switchTab = (tab) => {
|
|
772
|
+
if (busy || unarchivingSessionIdsRef.current.size > 0) return;
|
|
773
|
+
setArchiveTab(tab);
|
|
774
|
+
setSelectedSessionIds([]);
|
|
775
|
+
setArchiveTarget(null);
|
|
776
|
+
setArchiveGroup(null);
|
|
777
|
+
setError(null);
|
|
778
|
+
setNotice(null);
|
|
779
|
+
setProject("all");
|
|
780
|
+
setQuery("");
|
|
781
|
+
if (tab === "unarchived" && sortBy === "created") setSortBy("updated");
|
|
782
|
+
};
|
|
783
|
+
const confirmArchive = async () => {
|
|
784
|
+
if (archiveBusy.current || busy || !archiveTarget?.length) return;
|
|
785
|
+
archiveBusy.current = true;
|
|
786
|
+
setBusy(true);
|
|
787
|
+
setError(null);
|
|
788
|
+
setNotice(null);
|
|
789
|
+
try {
|
|
790
|
+
const result = await archiveSessions(archiveTarget);
|
|
791
|
+
setSelectedSessionIds([]);
|
|
792
|
+
setArchiveTab("archived");
|
|
793
|
+
setProject("all");
|
|
794
|
+
setQuery("");
|
|
795
|
+
setNotice(t("archives.archiveSuccess", { n: result.archivedSessionIdsAdded.length }));
|
|
796
|
+
setArchiveTarget(null);
|
|
797
|
+
setArchiveGroup(null);
|
|
798
|
+
} catch (reason) {
|
|
799
|
+
setError(t("archives.archiveBatchFailed", { detail: reason instanceof Error ? reason.message : String(reason) }));
|
|
800
|
+
} finally {
|
|
801
|
+
archiveBusy.current = false;
|
|
802
|
+
setBusy(false);
|
|
803
|
+
}
|
|
804
|
+
};
|
|
775
805
|
const sortedGroups = (0, react.useMemo)(() => sortArchivedGroups(groups, sortBy, createdAtById, t), [groups, sortBy, createdAtById, t]);
|
|
776
806
|
(0, react.useEffect)(() => {
|
|
777
807
|
let cancelled = false;
|
|
@@ -801,8 +831,8 @@
|
|
|
801
831
|
const allBatchTarget = { scope: "all" };
|
|
802
832
|
const allBatchSessionIds = (0, react.useMemo)(() => deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, allBatchTarget), [workspaceState.archivedSessionIds, workspaceState.items]);
|
|
803
833
|
(0, react.useEffect)(() => {
|
|
804
|
-
setSelectedSessionIds((current) => pruneArchivedSelection(current,
|
|
805
|
-
}, [
|
|
834
|
+
setSelectedSessionIds((current) => pruneArchivedSelection(current, eligibleIds));
|
|
835
|
+
}, [eligibleIds]);
|
|
806
836
|
const toggleSessionSelection = (sessionId, checked) => {
|
|
807
837
|
setSelectedSessionIds((current) => toggleArchivedSelection(current, [sessionId], checked));
|
|
808
838
|
};
|
|
@@ -892,20 +922,45 @@
|
|
|
892
922
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
893
923
|
className: "dsham_settings",
|
|
894
924
|
"aria-label": t("archives.title"),
|
|
895
|
-
children: [(0, react_jsx_runtime.jsx)("style", { children: ARCHIVE_SETTINGS_CSS + ARCHIVE_SETTINGS_BATCH_CSS + ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS + ARCHIVE_SETTINGS_SELECTION_CSS + ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS }), (0, react_jsx_runtime.jsxs)("
|
|
925
|
+
children: [(0, react_jsx_runtime.jsx)("style", { children: ARCHIVE_TABS_CSS + ARCHIVE_SETTINGS_CSS + ARCHIVE_SETTINGS_BATCH_CSS + ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS + ARCHIVE_SETTINGS_SELECTION_CSS + ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS + ARCHIVE_WORKSPACE_CONFIRM_CSS }), (0, react_jsx_runtime.jsxs)("div", {
|
|
926
|
+
// 设置页使用独立布局容器,避免被 Codex UI 的会话 header 页签适配器识别。
|
|
896
927
|
className: "dsham_settingsHeader",
|
|
897
928
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
898
929
|
children: [(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsTitleRow", children: [(0, react_jsx_runtime.jsx)("h2", { children: t("archives.title") }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsLinks", children: [(0, react_jsx_runtime.jsxs)("a", { className: "dsham_settingsExternalLink", href: "https://github.com/MichengAI/dsh-archive-manager", target: "_blank", rel: "noreferrer", "aria-label": t("archives.viewProject"), children: [(0, react_jsx_runtime.jsx)(GithubMark16, {}), t("archives.viewProject")] }), (0, react_jsx_runtime.jsxs)("a", { className: "dsham_settingsExternalLink", href: "https://github.com/MichengAI/dsh-archive-manager/issues", target: "_blank", rel: "noreferrer", "aria-label": t("archives.feedback"), children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconListPenOutline16, {}), t("archives.feedback")] })] })] }), (0, react_jsx_runtime.jsx)("p", { className: "dsham_settingsIntro", children: t("archives.description") })]
|
|
899
|
-
}), (0, react_jsx_runtime.
|
|
930
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
931
|
+
className: "dsham_archiveTabs",
|
|
932
|
+
role: "tablist",
|
|
933
|
+
"aria-label": t("archives.title"),
|
|
934
|
+
children: ["archived", "unarchived"].map((tab) => (0, react_jsx_runtime.jsx)("button", {
|
|
935
|
+
type: "button",
|
|
936
|
+
role: "tab",
|
|
937
|
+
className: "dsham_archiveTab",
|
|
938
|
+
id: "dsham-tab-" + tab,
|
|
939
|
+
"aria-controls": "dsham-archive-panel",
|
|
940
|
+
"aria-selected": archiveTab === tab,
|
|
941
|
+
tabIndex: archiveTab === tab ? 0 : -1,
|
|
942
|
+
disabled: busy || unarchivingSessionIds.size > 0,
|
|
943
|
+
onClick: () => switchTab(tab),
|
|
944
|
+
onKeyDown: (event) => {
|
|
945
|
+
if (["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) {
|
|
946
|
+
event.preventDefault();
|
|
947
|
+
const next = event.key === "Home" ? "archived" : event.key === "End" ? "unarchived" : isArchived ? "unarchived" : "archived";
|
|
948
|
+
switchTab(next);
|
|
949
|
+
event.currentTarget.parentElement.querySelector("#dsham-tab-" + next)?.focus();
|
|
950
|
+
}
|
|
951
|
+
},
|
|
952
|
+
children: t("archives.tab." + tab)
|
|
953
|
+
}, tab))
|
|
954
|
+
}), isArchived && (0, react_jsx_runtime.jsxs)("div", {
|
|
900
955
|
className: "dsham_settingsHeaderActions",
|
|
901
956
|
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsRestoreAll", disabled: busy || allBatchSessionIds.length === 0, onClick: () => onBatchUnarchive(allBatchTarget), children: t("archives.restoreAll") }), (0, react_jsx_runtime.jsxs)("button", { type: "button", className: "dsham_settingsDanger", disabled: busy || allBatchSessionIds.length === 0, onClick: () => setDeleteTarget({ kind: "batch", target: allBatchTarget, title: t("archives.allProjects"), count: allBatchSessionIds.length }), children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}), t("archives.deleteAll")] })]
|
|
902
957
|
})]
|
|
903
|
-
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
958
|
+
}), (0, react_jsx_runtime.jsxs)("div", { id: "dsham-archive-panel", role: "tabpanel", "aria-labelledby": "dsham-tab-" + archiveTab, children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
904
959
|
className: "dsham_settingsToolbar",
|
|
905
960
|
children: [(0, react_jsx_runtime.jsxs)("label", {
|
|
906
961
|
className: "dsham_settingsSearch",
|
|
907
|
-
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, {}), (0, react_jsx_runtime.jsx)("input", { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: t("archives.searchPlaceholder"), "aria-label": t("archives.searchPlaceholder") })]
|
|
908
|
-
}), (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-sort-filter", value: sortBy, options: [{ value: "updated", label: t("archives.sortUpdated") }, { value: "created", label: t("archives.sortCreated") }, { value: "alphabetical", label: t("archives.sortAlphabetical") }], onChange: setSortBy, "aria-label": t("archives.sortBy") }), (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-project-filter", value: project, options: [{ value: "all", label: t("archives.allProjects") }, ...sortedGroups.map((group) => ({ value: group.key, label: group.title }))], onChange: setProject, "aria-label": t("archives.projectFilter") })]
|
|
962
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, {}), (0, react_jsx_runtime.jsx)("input", { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: t(isArchived ? "archives.searchPlaceholder" : "archives.searchUnarchived"), "aria-label": t(isArchived ? "archives.searchPlaceholder" : "archives.searchUnarchived") })]
|
|
963
|
+
}), (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-sort-filter", value: sortBy, options: [{ value: "updated", label: t("archives.sortUpdated") }, ...isArchived ? [{ value: "created", label: t("archives.sortCreated") }] : [], { value: "alphabetical", label: t("archives.sortAlphabetical") }], onChange: setSortBy, "aria-label": t("archives.sortBy") }), (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-project-filter", value: project, options: [{ value: "all", label: t("archives.allProjects") }, ...sortedGroups.map((group) => ({ value: group.key, label: group.title }))], onChange: setProject, "aria-label": t("archives.projectFilter") })]
|
|
909
964
|
}), groups.length > 0 && (0, react_jsx_runtime.jsx)(ArchiveSelectionToolbar, {
|
|
910
965
|
selectedCount: selectedSessionIds.length,
|
|
911
966
|
hiddenCount: selectedSessionIds.length - selectedVisibleCount,
|
|
@@ -916,28 +971,41 @@
|
|
|
916
971
|
t,
|
|
917
972
|
onToggle: toggleVisibleSelection,
|
|
918
973
|
onClear: () => setSelectedSessionIds([]),
|
|
974
|
+
onArchive: isArchived ? void 0 : () => requestArchive([...selectedSessionIds]),
|
|
919
975
|
onRestore: onSelectedUnarchive,
|
|
920
976
|
onDelete: () => setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: selectedSessionIds }, count: selectedSessionIds.length })
|
|
921
|
-
}), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.empty") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
977
|
+
}), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t(isArchived ? "archives.empty" : "archives.emptyUnarchived") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
922
978
|
const target = archivedBatchTargetForGroup(group.key);
|
|
923
|
-
const
|
|
979
|
+
const groupSessionIds = groups.find((item) => item.key === group.key)?.sessions.map((session) => session.id) ?? [];
|
|
980
|
+
const count = isArchived ? deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target).length : groupSessionIds.length;
|
|
924
981
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
925
982
|
className: "dsham_settingsGroup",
|
|
926
983
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
927
984
|
className: "dsham_settingsGroupHeading",
|
|
928
|
-
children: [(0, react_jsx_runtime.jsxs)("h3", { className: "dsham_settingsGroupTitle", children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}), group.title] }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsGroupMeta", children: [(0, react_jsx_runtime.jsx)("span", { className: "dsham_settingsCount", children: t("archives.sessionCount", { n: count }) }), (0, react_jsx_runtime.jsx)(ArchivedGroupActions, { group, busy, onRestore: () => onBatchUnarchive(target), onDelete: () => setDeleteTarget({ kind: "batch", target, title: group.title, count }), t })] })]
|
|
985
|
+
children: [(0, react_jsx_runtime.jsxs)("h3", { className: "dsham_settingsGroupTitle", children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}), group.title] }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsGroupMeta", children: [(0, react_jsx_runtime.jsx)("span", { className: "dsham_settingsCount", children: t("archives.sessionCount", { n: count }) }), (0, react_jsx_runtime.jsx)(ArchivedGroupActions, { group, busy, onArchive: isArchived ? void 0 : () => requestArchive(groupSessionIds, group), onRestore: () => onBatchUnarchive(target), onDelete: () => setDeleteTarget({ kind: "batch", target, title: group.title, count }), t })] })]
|
|
929
986
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
930
987
|
className: "dsham_settingsList",
|
|
931
988
|
children: group.sessions.map((session) => (0, react_jsx_runtime.jsxs)("article", {
|
|
932
989
|
className: "dsham_settingsRow",
|
|
933
990
|
children: [(0, react_jsx_runtime.jsx)(ArchiveSelectionCheckbox, { checked: selectedSessionIdSet.has(session.id), disabled: busy, label: t("archives.selectSession", { name: displayTitle(session, t) }), onChange: (event) => toggleSessionSelection(session.id, event.target.checked) }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsContent", children: [(0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsTitle", children: displayTitle(session, t) }), (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsMeta", children: archiveTimeLabel(session.updatedAt, t) })] }), (0, react_jsx_runtime.jsxs)("div", {
|
|
934
991
|
className: "dsham_settingsActions",
|
|
935
|
-
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => viewConversation(session), children: t("archives.
|
|
992
|
+
children: !isArchived ? [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: () => viewConversation(session), children: t("archives.openSession") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: () => requestArchive([session.id]), children: t("archives.archiveSelected") })] : [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => viewConversation(session), children: t("archives.openSession") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => viewConversation(session, true), children: t("archives.restoreOpen") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => onUnarchive(session.id), children: t("archives.restore") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsDelete", disabled: busy || unarchivingSessionIds.has(session.id), "aria-label": t("menu.deleteSession"), onClick: () => setDeleteTarget({ kind: "session", session }), children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}) })]
|
|
936
993
|
})]
|
|
937
994
|
}, session.id))
|
|
938
995
|
})]
|
|
939
996
|
}, group.key);
|
|
940
|
-
}), error !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsError", role: "alert", children: error }), notice !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsStatus", role: "status", children: notice }), (0, react_jsx_runtime.
|
|
997
|
+
}), archiveTarget === null && error !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsError", role: "alert", children: error }), notice !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsStatus", role: "status", children: notice }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
998
|
+
open: archiveTarget !== null,
|
|
999
|
+
onClose: closeArchive,
|
|
1000
|
+
closeLabel: t("close"),
|
|
1001
|
+
title: t("archives.archiveTitle", { n: archiveTarget?.length ?? 0 }),
|
|
1002
|
+
description: archiveGroup === null ? t("archives.archiveSelectedDesc") : t(archiveGroup.key === ARCHIVE_UNGROUPED_KEY ? "archives.archiveUngroupedDesc" : "archives.archiveProjectDesc", { name: archiveGroup.title, n: archiveTarget?.length ?? 0 }),
|
|
1003
|
+
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1004
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: closeArchive, children: t("cancel") }),
|
|
1005
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsham_archiveWorkspaceConfirm", disabled: busy, onClick: confirmArchive, children: t("archives.archiveSelected") })
|
|
1006
|
+
] }),
|
|
1007
|
+
children: error !== null ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsError", role: "alert", children: error }) : busy ? t("archiveWorkspace.pending") : null
|
|
1008
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
941
1009
|
open: deleteTarget !== null,
|
|
942
1010
|
onClose: closeDelete,
|
|
943
1011
|
closeLabel: t("close"),
|
|
@@ -945,7 +1013,7 @@
|
|
|
945
1013
|
...deleteDialogDescription === void 0 ? {} : { description: deleteDialogDescription },
|
|
946
1014
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: closeDelete, children: t("cancel") }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsham_settingsDeleteConfirm", disabled: busy, onClick: confirmDelete, children: deleteConfirmLabel })] }),
|
|
947
1015
|
children: busy && (0, react_jsx_runtime.jsx)("div", { role: "status", children: deleteTarget?.kind === "batch" ? t("archives.deleteBatchPending") : t("deleteSession.pending") })
|
|
948
|
-
})]
|
|
1016
|
+
})] })]
|
|
949
1017
|
});
|
|
950
1018
|
}
|
|
951
1019
|
function r(e) {
|
|
@@ -1516,7 +1584,7 @@
|
|
|
1516
1584
|
})]
|
|
1517
1585
|
});
|
|
1518
1586
|
}
|
|
1519
|
-
function SessionNodeItem({ node, currentId, now, onOpen, onRename, onFork, onArchive, onUnarchive, onDeleteSession, drag, flat = false, t }) {
|
|
1587
|
+
function SessionNodeItem({ node, currentId, now, onOpen, onRename, onFork, onArchive, onUnarchive, onDeleteSession, onReveal, drag, flat = false, t }) {
|
|
1520
1588
|
const row = node;
|
|
1521
1589
|
const title = displayTitle(node, t);
|
|
1522
1590
|
const selected = node.id === currentId;
|
|
@@ -1524,6 +1592,12 @@
|
|
|
1524
1592
|
const statuses = sessionStatuses(node, t);
|
|
1525
1593
|
const showStatus = statuses[0].state !== "done" || row.completed;
|
|
1526
1594
|
const [menuOpen, setMenuOpen] = (0, react.useState)(false);
|
|
1595
|
+
const rowRef = (0, react.useRef)(null);
|
|
1596
|
+
(0, react.useEffect)(() => {
|
|
1597
|
+
if (onReveal === void 0) return;
|
|
1598
|
+
rowRef.current?.scrollIntoView({ block: "nearest" });
|
|
1599
|
+
onReveal();
|
|
1600
|
+
}, [onReveal]);
|
|
1527
1601
|
const sessionMenuItems = archived ? [
|
|
1528
1602
|
{
|
|
1529
1603
|
id: "unarchive",
|
|
@@ -1561,6 +1635,7 @@
|
|
|
1561
1635
|
];
|
|
1562
1636
|
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.HoverCard, {
|
|
1563
1637
|
anchor: (0, react_jsx_runtime.jsxs)("div", {
|
|
1638
|
+
ref: rowRef,
|
|
1564
1639
|
className: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, flat && !showStatus && Rows_module_css_default.flatSessionRowWithoutStatus, archived && ARCHIVED_CLASSES.row, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),
|
|
1565
1640
|
role: "treeitem",
|
|
1566
1641
|
"aria-selected": selected,
|
|
@@ -2010,7 +2085,7 @@
|
|
|
2010
2085
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
2011
2086
|
return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
2012
2087
|
}
|
|
2013
|
-
function SessionTree({ useSessions, useSessionPendingInteraction, startSession, open, forkSession, workspaces, archivedSessionIds, showArchived, onRenameRequest, onArchiveRequest, onDeleteRequest, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
|
|
2088
|
+
function SessionTree({ useSessions, useSessionPendingInteraction, startSession, open, forkSession, workspaces, archivedSessionIds, showArchived, onRenameRequest, onArchiveRequest, onDeleteRequest, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed }) {
|
|
2014
2089
|
const list = useSessions((s) => s);
|
|
2015
2090
|
const pendingInteractions = useSessionPendingInteraction((s) => s);
|
|
2016
2091
|
const current = list.current;
|
|
@@ -2022,6 +2097,7 @@
|
|
|
2022
2097
|
const previousOrderBy = (0, react.useRef)(orderBy);
|
|
2023
2098
|
useNativeDragAcceptance(drag !== null || workspaceDrag !== null);
|
|
2024
2099
|
const currentGroup = current === void 0 ? void 0 : workspaces.find((w) => w.sessionIds.includes(current))?.workspaceId ?? "";
|
|
2100
|
+
const revealGroup = revealSessionId === void 0 ? void 0 : workspaces.find((w) => w.sessionIds.includes(revealSessionId))?.workspaceId ?? "";
|
|
2025
2101
|
(0, react.useEffect)(() => {
|
|
2026
2102
|
if (current === void 0 || currentGroup === void 0 || Object.hasOwn(groupExpansion, currentGroup)) return;
|
|
2027
2103
|
setGroupExpanded(currentGroup, true);
|
|
@@ -2031,6 +2107,14 @@
|
|
|
2031
2107
|
setGroupExpanded,
|
|
2032
2108
|
groupExpansion
|
|
2033
2109
|
]);
|
|
2110
|
+
(0, react.useEffect)(() => {
|
|
2111
|
+
if (revealGroup === void 0 || groupExpansion[revealGroup] === true) return;
|
|
2112
|
+
setGroupExpanded(revealGroup, true);
|
|
2113
|
+
}, [
|
|
2114
|
+
groupExpansion,
|
|
2115
|
+
revealGroup,
|
|
2116
|
+
setGroupExpanded
|
|
2117
|
+
]);
|
|
2034
2118
|
const expandedGroups = (0, react.useMemo)(() => Object.entries(groupExpansion).filter(([, expanded]) => expanded).map(([key]) => key), [groupExpansion]);
|
|
2035
2119
|
const ungroupedSessionIds = (0, react.useMemo)(() => {
|
|
2036
2120
|
const accounted = new Set(workspaces.flatMap((workspace) => workspace.sessionIds));
|
|
@@ -2057,7 +2141,7 @@
|
|
|
2057
2141
|
orderBy,
|
|
2058
2142
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2059
2143
|
});
|
|
2060
|
-
if (next.changed) syncSessionOrderAccount(key, next.order.map((id) => id), next.updatedAt);
|
|
2144
|
+
if (next.changed && typeof syncSessionOrderAccount === "function") syncSessionOrderAccount(key, next.order.map((id) => id), next.updatedAt);
|
|
2061
2145
|
}
|
|
2062
2146
|
}, [
|
|
2063
2147
|
list,
|
|
@@ -2092,6 +2176,17 @@
|
|
|
2092
2176
|
expandedGroups,
|
|
2093
2177
|
sessionOrderByAccount
|
|
2094
2178
|
]);
|
|
2179
|
+
(0, react.useEffect)(() => {
|
|
2180
|
+
if (revealSessionId === void 0 || revealGroup === void 0) return;
|
|
2181
|
+
const group = groups.find((candidate) => candidate.key === revealGroup);
|
|
2182
|
+
if (group === void 0 || !group.expanded || !group.sessions.some((row) => row.id === revealSessionId)) return;
|
|
2183
|
+
if (group.sessions.slice(0, COLLAPSED_SESSION_LIMIT).some((row) => row.id === revealSessionId)) return;
|
|
2184
|
+
setExpandedSessionGroups((keys) => keys.includes(revealGroup) ? keys : [...keys, revealGroup]);
|
|
2185
|
+
}, [
|
|
2186
|
+
groups,
|
|
2187
|
+
revealGroup,
|
|
2188
|
+
revealSessionId
|
|
2189
|
+
]);
|
|
2095
2190
|
const now = Date.now();
|
|
2096
2191
|
const commitSessionDrag = (activeDrag, over) => {
|
|
2097
2192
|
if (sessionDropCommitted.current) return;
|
|
@@ -2238,6 +2333,9 @@
|
|
|
2238
2333
|
onArchive: onSessionArchive,
|
|
2239
2334
|
onUnarchive: onSessionUnarchive,
|
|
2240
2335
|
onDeleteSession: onSessionDelete,
|
|
2336
|
+
onReveal: node.id === revealSessionId && group.key === revealGroup ? () => {
|
|
2337
|
+
onSessionRevealed?.(node.id);
|
|
2338
|
+
} : void 0,
|
|
2241
2339
|
drag: {
|
|
2242
2340
|
start: () => {
|
|
2243
2341
|
sessionDropCommitted.current = false;
|
|
@@ -2291,7 +2389,7 @@
|
|
|
2291
2389
|
]
|
|
2292
2390
|
});
|
|
2293
2391
|
}
|
|
2294
|
-
function FlatList({ useSessions, useSessionPendingInteraction, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
|
|
2392
|
+
function FlatList({ useSessions, useSessionPendingInteraction, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed }) {
|
|
2295
2393
|
const list = useSessions((s) => s);
|
|
2296
2394
|
const pendingInteractions = useSessionPendingInteraction((s) => s);
|
|
2297
2395
|
const baseRows = (0, react.useMemo)(() => deriveFlat(list, archivedSessionIds, pendingInteractions, showArchived), [
|
|
@@ -2381,6 +2479,9 @@
|
|
|
2381
2479
|
onArchive: onSessionArchive,
|
|
2382
2480
|
onUnarchive: onSessionUnarchive,
|
|
2383
2481
|
onDeleteSession: onSessionDelete,
|
|
2482
|
+
onReveal: node.id === revealSessionId ? () => {
|
|
2483
|
+
onSessionRevealed?.(node.id);
|
|
2484
|
+
} : void 0,
|
|
2384
2485
|
flat: true,
|
|
2385
2486
|
drag: {
|
|
2386
2487
|
start: () => {
|
|
@@ -2481,6 +2582,18 @@
|
|
|
2481
2582
|
}), (0, react_jsx_runtime.jsx)("span", { className: WorkspaceBrowser_module_css_default.fade })]
|
|
2482
2583
|
});
|
|
2483
2584
|
}
|
|
2585
|
+
const sidebarReveal = {
|
|
2586
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
2587
|
+
request(sessionId) {
|
|
2588
|
+
for (const listener of this.listeners) listener(sessionId);
|
|
2589
|
+
},
|
|
2590
|
+
subscribe(listener) {
|
|
2591
|
+
this.listeners.add(listener);
|
|
2592
|
+
return () => {
|
|
2593
|
+
this.listeners.delete(listener);
|
|
2594
|
+
};
|
|
2595
|
+
}
|
|
2596
|
+
};
|
|
2484
2597
|
function WorkspaceBrowser({ wide, expandSidebar, useSessions, useSessionPendingInteraction, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, archiveWorkspaceSessions, unarchiveSession, deleteSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, renderSlot, t }) {
|
|
2485
2598
|
const useEffectiveSessionPendingInteraction = useSessionPendingInteraction ?? useEmptySessionPendingInteraction;
|
|
2486
2599
|
const workspaces = useWorkspaces((state) => state.items);
|
|
@@ -2495,6 +2608,11 @@
|
|
|
2495
2608
|
const sessionOrderByAccount = useStore((s) => s.sessionOrderByAccount);
|
|
2496
2609
|
const sessionUpdatedAtByAccount = useStore((s) => s.sessionUpdatedAtByAccount);
|
|
2497
2610
|
const archivedSet = (0, react.useMemo)(() => new Set(archivedSessionIds), [archivedSessionIds]);
|
|
2611
|
+
const [revealSessionId, setRevealSessionId] = (0, react.useState)(void 0);
|
|
2612
|
+
(0, react.useEffect)(() => sidebarReveal.subscribe((sessionId) => setRevealSessionId(sessionId)), []);
|
|
2613
|
+
const acknowledgeSessionReveal = (sessionId) => {
|
|
2614
|
+
setRevealSessionId((current) => current === sessionId ? void 0 : current);
|
|
2615
|
+
};
|
|
2498
2616
|
const [archivedToast, setArchivedToast] = (0, react.useState)(null);
|
|
2499
2617
|
const archivedToastSeq = (0, react.useRef)(0);
|
|
2500
2618
|
const showArchivedToast2 = (text) => {
|
|
@@ -2902,7 +3020,12 @@
|
|
|
2902
3020
|
children: wide && (normalizedQuery !== "" ? (0, react_jsx_runtime.jsx)(SearchResults, {
|
|
2903
3021
|
useSessions,
|
|
2904
3022
|
useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
|
|
2905
|
-
open:
|
|
3023
|
+
open: (sessionId) => {
|
|
3024
|
+
setRevealSessionId(sessionId);
|
|
3025
|
+
setQuery("");
|
|
3026
|
+
setSearchExpanded(false);
|
|
3027
|
+
guardedOpen(sessionId);
|
|
3028
|
+
},
|
|
2906
3029
|
workspaces,
|
|
2907
3030
|
archivedSessionIds,
|
|
2908
3031
|
showArchived,
|
|
@@ -2914,6 +3037,8 @@
|
|
|
2914
3037
|
useSessions,
|
|
2915
3038
|
useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
|
|
2916
3039
|
open: guardedOpen,
|
|
3040
|
+
revealSessionId,
|
|
3041
|
+
onSessionRevealed: acknowledgeSessionReveal,
|
|
2917
3042
|
forkSession,
|
|
2918
3043
|
onSessionRename,
|
|
2919
3044
|
onSessionArchive,
|
|
@@ -2933,6 +3058,8 @@
|
|
|
2933
3058
|
}) : (0, react_jsx_runtime.jsx)(SessionTree, {
|
|
2934
3059
|
useSessions,
|
|
2935
3060
|
useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
|
|
3061
|
+
revealSessionId,
|
|
3062
|
+
onSessionRevealed: acknowledgeSessionReveal,
|
|
2936
3063
|
onSessionRename,
|
|
2937
3064
|
onSessionArchive,
|
|
2938
3065
|
onSessionUnarchive,
|
|
@@ -3170,12 +3297,13 @@
|
|
|
3170
3297
|
]
|
|
3171
3298
|
});
|
|
3172
3299
|
}
|
|
3300
|
+
const ARCHIVE_TABS_CSS = ".dsham_archiveTabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_archiveTab{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;padding:12px 2px;border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-weight:600;cursor:pointer}.dsham_archiveTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary)}.dsham_archiveTab:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dsham_archiveTab:disabled{opacity:.5;cursor:not-allowed}@container(max-width:520px){.dsham_archiveTabs{gap:16px}}";
|
|
3173
3301
|
const ARCHIVE_SETTINGS_CSS = ".dsham_settings{container-type:inline-size;min-width:0;box-sizing:border-box;width:min(100%,760px);margin:0 auto;padding:0 0 32px;color:var(--dsw-alias-label-primary)}.dsham_settingsHeader{display:flex;flex-direction:column;align-items:stretch;gap:16px;margin-bottom:16px}.dsham_settings h2{margin:0;font-size:24px;line-height:32px;font-weight:600;letter-spacing:-.4px;white-space:nowrap}.dsham_settingsIntro{margin:12px 0 0;max-width:42em;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px}.dsham_settingsDanger{display:inline-flex;align-items:center;gap:6px;min-height:32px;padding:0 12px;color:var(--dsw-alias-state-error-primary);background:transparent;border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsDanger:hover{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)}.dsham_settingsToolbar{display:flex;gap:8px;margin-bottom:16px}.dsham_settingsSearch{display:flex;align-items:center;gap:8px;min-width:0;flex:1;height:32px;padding:0 12px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-button-elevated-fill));border:1px solid var(--dsw-alias-border-l2);border-radius:8px}.dsham_settingsSearch:focus-within{border-color:var(--dsw-alias-label-tertiary)}.dsham_settingsSearch input{width:100%;min-width:0;padding:0;color:var(--dsw-alias-label-primary);background:transparent;border:0;outline:0;font:inherit;font-size:12px}.dsham_settingsSearch input::placeholder{color:var(--dsw-alias-label-tertiary)}.dsham_settingsFilter{position:relative;min-width:168px;flex:none}.dsham_selectTrigger{box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:32px;padding:0 10px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-button-elevated-fill));border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;line-height:20px;text-align:left}.dsham_selectTrigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_selectTrigger:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dsham_selectTrigger[aria-expanded='true']{border-color:var(--dsw-alias-state-success-primary)}.dsham_selectValue{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsham_selectCaret{flex:none;width:12px;height:12px;color:var(--dsw-alias-label-tertiary)}.dsham_selectMenu{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:30;box-sizing:border-box;min-width:100%;max-height:280px;overflow:auto;padding:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3)}.dsham_selectOption{box-sizing:border-box;display:flex;align-items:center;width:100%;min-height:32px;padding:0 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;text-align:left;cursor:pointer}.dsham_selectOption:hover,.dsham_selectOption[data-active='true']{background:var(--dsw-alias-interactive-bg-hover)}.dsham_selectOption[aria-selected='true']{color:var(--dsw-alias-state-success-primary)}.dsham_settingsGroup{margin:0 0 20px}.dsham_settingsGroupHeading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 14px}.dsham_settingsGroupTitle{display:flex;align-items:center;gap:8px;min-width:0;margin:0;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.dsham_settingsGroupTitle svg{flex:none;color:var(--dsw-alias-label-secondary)}.dsham_settingsCount{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px}.dsham_settingsList{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-button-elevated-fill))}.dsham_settingsRow{display:flex;align-items:center;gap:12px;min-height:60px;padding:10px 16px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsRow:last-child{border-bottom:0}.dsham_settingsContent{min-width:0;flex:1}.dsham_settingsTitle{overflow:hidden;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.dsham_settingsMeta{margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.dsham_settingsActions{display:flex;align-items:center;gap:8px}.dsham_settingsAction{min-height:32px;padding:0 12px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsAction:hover{filter:brightness(1.12)}.dsham_settingsDelete{display:flex;align-items:center;justify-content:center;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:transparent;border:0;border-radius:8px;cursor:pointer}.dsham_settingsDelete:hover{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsEmpty{padding:28px 8px;color:var(--dsw-alias-label-secondary);text-align:center}.dsham_settingsError{margin-top:10px;color:var(--dsw-alias-state-error-primary);font-size:12px}@container(max-width:520px){.dsham_settingsHeader{margin-bottom:16px}.dsham_settingsToolbar{flex-wrap:wrap;margin-bottom:28px}.dsham_settingsSearch{flex-basis:100%}.dsham_settingsFilter{flex:1;min-width:0}.dsham_settingsGroup{margin-bottom:32px}.dsham_settingsRow{padding:10px 12px}.dsham_settingsActions{gap:4px}}";
|
|
3174
3302
|
const ARCHIVE_SETTINGS_BATCH_CSS = ".dsham_settingsHeaderActions,.dsham_settingsGroupMeta{display:flex;align-items:center;gap:8px;flex:none;flex-wrap:wrap}.dsham_settingsRestoreAll{display:inline-flex;align-items:center;min-height:32px;padding:0 12px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsRestoreAll:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsRestoreAll:disabled,.dsham_settingsDanger:disabled,.dsham_settingsGroupMenu:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsGroupMenu{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;color:var(--dsw-alias-label-tertiary);background:transparent;border:0;border-radius:8px;cursor:pointer}.dsham_settingsGroupMenu:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsStatus{margin-top:10px;color:var(--dsw-alias-label-secondary);font-size:12px}@media(max-width:720px){.dsham_settingsHeader{flex-direction:column}.dsham_settingsHeaderActions{align-self:flex-start}}";
|
|
3175
3303
|
const ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS = ".dsham_settingsTitleRow{display:flex;align-items:center;gap:8px 12px;min-width:0;flex-wrap:wrap}.dsham_settingsLinks{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.dsham_settingsExternalLink{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dsham_settingsExternalLink:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsExternalLink:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dsham_settingsExternalLink svg{flex:none}@media(max-width:720px){.dsham_settingsTitleRow{flex-wrap:wrap}}";
|
|
3176
3304
|
const ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS = ".dsham_settingsDeleteConfirm{color:var(--dsw-alias-state-error-primary)!important;background:transparent!important;border-color:var(--dsw-alias-state-error-primary)!important}.dsham_settingsDeleteConfirm:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)!important}.dsham_settingsDeleteConfirm:focus-visible{outline:2px solid var(--dsw-alias-state-error-secondary);outline-offset:2px}.dsham_settingsDeleteConfirm:disabled{cursor:not-allowed;opacity:.5}";
|
|
3177
3305
|
const ARCHIVE_WORKSPACE_CONFIRM_CSS = ".dsham_archiveWorkspaceConfirm{color:var(--dsw-alias-state-error-primary)!important;background:transparent!important;border-color:var(--dsw-alias-state-error-primary)!important}.dsham_archiveWorkspaceConfirm:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)!important}.dsham_archiveWorkspaceConfirm:focus-visible{outline:2px solid var(--dsw-alias-state-error-secondary);outline-offset:2px}.dsham_archiveWorkspaceConfirm:disabled{cursor:not-allowed;opacity:.5}";
|
|
3178
|
-
const ARCHIVE_SETTINGS_SELECTION_CSS = ".dsham_settingsSelection{margin:-8px 0 16px;padding:4px 0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsSelectionMain{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;min-height:36px}.dsham_settingsSelectionSummary{display:flex;flex-wrap:wrap;align-items:center;gap:12px;min-width:0;max-width:100%}.dsham_settingsSelectionToggle{display:inline-flex;flex:none;white-space:nowrap;align-items:center;gap:12px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;cursor:pointer}.dsham_settingsCheckbox{flex:none;width:16px;height:16px;margin:0;accent-color:var(--dsw-alias-state-business-primary,#3b82f6)}.dsham_settingsSelectionClear{flex:none;min-height:28px;padding:0 0 0 12px;border:0;border-left:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-state-business-primary,#3b82f6);font:inherit;font-size:13px;white-space:nowrap;cursor:pointer}.dsham_settingsSelectionClear:hover:not(:disabled){text-decoration:underline}.dsham_settingsSelectionActions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px;max-width:100%;margin-left:auto}.dsham_settingsSelectionAction{flex:none;white-space:nowrap;min-height:32px;padding:0 14px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsSelectionAction:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsSelectionDelete{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}.dsham_settingsSelectionScope{margin:8px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow-wrap:anywhere}.dsham_settingsSelectionAction:disabled,.dsham_settingsSelectionClear:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsSelectionAction:focus-visible,.dsham_settingsSelectionClear:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#3b82f6);outline-offset:3px}";
|
|
3306
|
+
const ARCHIVE_SETTINGS_SELECTION_CSS = ".dsham_settingsSelection{margin:-8px 0 16px;padding:4px 0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsSelectionMain{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;min-height:36px}.dsham_settingsSelectionSummary{display:flex;flex-wrap:wrap;align-items:center;gap:12px;min-width:0;max-width:100%}.dsham_settingsSelectionToggle{display:inline-flex;flex:none;white-space:nowrap;align-items:center;gap:12px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;cursor:pointer}.dsham_settingsCheckbox{flex:none;width:16px;height:16px;margin:0;accent-color:var(--dsw-alias-state-business-primary,#3b82f6)}.dsham_settingsSelectionClear{flex:none;min-height:28px;padding:0 0 0 12px;border:0;border-left:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-state-business-primary,#3b82f6);font:inherit;font-size:13px;white-space:nowrap;cursor:pointer}.dsham_settingsSelectionClear:hover:not(:disabled){text-decoration:underline}.dsham_settingsSelectionActions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px;max-width:100%;margin-left:auto}.dsham_settingsSelectionAction{flex:none;white-space:nowrap;min-height:32px;padding:0 14px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsSelectionAction:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsSelectionArchive,.dsham_settingsSelectionDelete{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}.dsham_settingsSelectionScope{margin:8px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow-wrap:anywhere}.dsham_settingsSelectionAction:disabled,.dsham_settingsSelectionClear:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsSelectionAction:focus-visible,.dsham_settingsSelectionClear:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#3b82f6);outline-offset:3px}";
|
|
3179
3307
|
const ARCHIVE_SETTINGS_LAYOUT_OVERRIDE = ".dsham_settings{margin:0 auto!important}@media(max-width:720px){.dsham_settings{margin:0 auto!important}}";
|
|
3180
3308
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify("dsh-archive-manager/ArchiveSettings.layout.css") + "]") === null) {
|
|
3181
3309
|
const tag = document.createElement("style");
|
|
@@ -3315,7 +3443,7 @@
|
|
|
3315
3443
|
}) : null]
|
|
3316
3444
|
});
|
|
3317
3445
|
}
|
|
3318
|
-
function ArchiveSelectionToolbar({ selectedCount, hiddenCount, allVisibleSelected, selectedVisibleCount, visibleCount, busy, t, onToggle, onClear, onRestore, onDelete }) {
|
|
3446
|
+
function ArchiveSelectionToolbar({ selectedCount, hiddenCount, allVisibleSelected, selectedVisibleCount, visibleCount, busy, t, onToggle, onClear, onRestore, onDelete, onArchive }) {
|
|
3319
3447
|
const hasSelection = selectedCount > 0;
|
|
3320
3448
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
3321
3449
|
className: "dsham_settingsSelection",
|
|
@@ -3336,7 +3464,7 @@
|
|
|
3336
3464
|
}), hasSelection && (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionClear", disabled: busy, "aria-label": t("archives.clearSelection"), onClick: onClear, children: t("archives.clearSelectionShort") })]
|
|
3337
3465
|
}), hasSelection && (0, react_jsx_runtime.jsxs)("div", {
|
|
3338
3466
|
className: "dsham_settingsSelectionActions",
|
|
3339
|
-
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction", disabled: busy, "aria-label": t("archives.restoreSelected"), onClick: onRestore, children: t("archives.
|
|
3467
|
+
children: onArchive ? [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction dsham_settingsSelectionArchive", disabled: busy, onClick: onArchive, children: t("archives.archiveSelected") })] : [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction", disabled: busy, "aria-label": t("archives.restoreSelected"), onClick: onRestore, children: t("archives.restore") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction dsham_settingsSelectionDelete", disabled: busy, "aria-label": t("archives.deleteSelected"), onClick: onDelete, children: t("archives.deleteSelectionShort") })]
|
|
3340
3468
|
})]
|
|
3341
3469
|
}), hiddenCount > 0 && (0, react_jsx_runtime.jsx)("p", { className: "dsham_settingsSelectionScope", role: "status", children: t("archives.selectionHiddenHint", { hidden: hiddenCount }) })]
|
|
3342
3470
|
});
|
|
@@ -3356,10 +3484,15 @@
|
|
|
3356
3484
|
onChange
|
|
3357
3485
|
});
|
|
3358
3486
|
}
|
|
3359
|
-
function ArchivedGroupActions({ group, busy, onRestore, onDelete, t }) {
|
|
3487
|
+
function ArchivedGroupActions({ group, busy, onArchive, onRestore, onDelete, t }) {
|
|
3360
3488
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3361
3489
|
const ungrouped = group.key === ARCHIVE_UNGROUPED_KEY;
|
|
3362
|
-
const items = [{
|
|
3490
|
+
const items = onArchive ? [{
|
|
3491
|
+
id: "archive",
|
|
3492
|
+
label: t(ungrouped ? "archives.archiveUngrouped" : "archives.archiveProject"),
|
|
3493
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: 16 }),
|
|
3494
|
+
danger: true
|
|
3495
|
+
}] : [{
|
|
3363
3496
|
id: "restore",
|
|
3364
3497
|
label: t(ungrouped ? "archives.restoreUngrouped" : "archives.restoreProject"),
|
|
3365
3498
|
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16, {})
|
|
@@ -3375,7 +3508,9 @@
|
|
|
3375
3508
|
items,
|
|
3376
3509
|
onSelect: (id) => {
|
|
3377
3510
|
setOpen(false);
|
|
3378
|
-
if (
|
|
3511
|
+
if (busy) return;
|
|
3512
|
+
if (id === "archive") onArchive?.();
|
|
3513
|
+
else if (id === "restore") onRestore();
|
|
3379
3514
|
else if (id === "delete") onDelete();
|
|
3380
3515
|
},
|
|
3381
3516
|
portal: true,
|
|
@@ -3439,6 +3574,10 @@
|
|
|
3439
3574
|
};
|
|
3440
3575
|
return { kind: "notice", message: t("archives.deleteSuccess", { n: deleted }) };
|
|
3441
3576
|
}
|
|
3577
|
+
function unarchivedSessionIds(byId, archivedSessionIds) {
|
|
3578
|
+
const archived = new Set(archivedSessionIds);
|
|
3579
|
+
return Object.values(byId).filter((session) => session.origin !== "subagent" && !session.blank && !archived.has(session.id)).map((session) => session.id);
|
|
3580
|
+
}
|
|
3442
3581
|
function deriveArchivedGroups(byId, items, archivedSessionIds, ungroupedLabel) {
|
|
3443
3582
|
const byWorkspace = items.map((workspace) => ({
|
|
3444
3583
|
key: workspace.workspaceId,
|
|
@@ -3480,14 +3619,27 @@
|
|
|
3480
3619
|
});
|
|
3481
3620
|
}
|
|
3482
3621
|
const zh = {
|
|
3483
|
-
"archives.
|
|
3622
|
+
"archives.archiveProject": "\u5F52\u6863\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
3623
|
+
"archives.archiveUngrouped": "\u5F52\u6863\u5168\u90E8\u672A\u5206\u7EC4\u804A\u5929",
|
|
3624
|
+
"archives.archiveProjectDesc": "\u5C06\u201C{name}\u201D\u4E2D\u5168\u90E8 {n} \u6761\u672A\u5F52\u6863\u4F1A\u8BDD\u5F52\u6863\uFF0C\u4E0D\u53D7\u5F53\u524D\u641C\u7D22\u7B5B\u9009\u5F71\u54CD\u3002\u4E4B\u540E\u53EF\u5728\u201C\u5DF2\u5F52\u6863\u201D\u4E2D\u6062\u590D\u3002",
|
|
3625
|
+
"archives.archiveUngroupedDesc": "\u5C06\u5168\u90E8 {n} \u6761\u672A\u5206\u7EC4\u7684\u672A\u5F52\u6863\u4F1A\u8BDD\u5F52\u6863\uFF0C\u4E0D\u53D7\u5F53\u524D\u641C\u7D22\u7B5B\u9009\u5F71\u54CD\u3002\u4E4B\u540E\u53EF\u5728\u201C\u5DF2\u5F52\u6863\u201D\u4E2D\u6062\u590D\u3002",
|
|
3626
|
+
"archives.tab.archived": "\u5DF2\u5F52\u6863",
|
|
3627
|
+
"archives.tab.unarchived": "\u672A\u5F52\u6863",
|
|
3628
|
+
"archives.searchUnarchived": "\u641C\u7D22\u672A\u5F52\u6863\u804A\u5929",
|
|
3629
|
+
"archives.emptyUnarchived": "\u6682\u65E0\u672A\u5F52\u6863\u4F1A\u8BDD\u3002",
|
|
3630
|
+
"archives.archiveSelected": "\u5F52\u6863",
|
|
3631
|
+
"archives.openSession": "\u6253\u5F00\u4F1A\u8BDD",
|
|
3632
|
+
"archives.archiveSelectedDesc": "\u5C06\u9009\u4E2D\u7684\u4F1A\u8BDD\u5F52\u6863\uFF0C\u5305\u542B\u5F53\u524D\u7B5B\u9009\u9690\u85CF\u7684\u5DF2\u9009\u9879\u3002\u4E4B\u540E\u53EF\u5728\u201C\u5DF2\u5F52\u6863\u201D\u4E2D\u67E5\u770B\u548C\u6062\u590D\u3002",
|
|
3633
|
+
"archives.archiveSuccess": "\u5DF2\u5F52\u6863 {n} \u6761\u4F1A\u8BDD\u3002",
|
|
3634
|
+
"archives.archiveBatchFailed": "\u6279\u91CF\u5F52\u6863\u5931\u8D25\uFF1A{detail}",
|
|
3484
3635
|
"archives.navigationUnavailable": "\u5F53\u524D\u5BBF\u4E3B\u65E0\u6CD5\u4FDD\u6301\u5F52\u6863\u5BF9\u8BDD\uFF0C\u8BF7\u4F7F\u7528\u201C\u6062\u590D\u5E76\u6253\u5F00\u201D\u3002",
|
|
3485
3636
|
"archives.sessionNotRetained": "\u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6216\u6062\u590D\u540E\u518D\u8BD5\u3002",
|
|
3486
3637
|
"archives.restoreOpen": "\u6062\u590D\u5E76\u6253\u5F00",
|
|
3487
3638
|
"archives.selectedCount": "\u5DF2\u9009 {n} \u6761",
|
|
3488
3639
|
"archives.selectionHiddenHint": "\u542B\u5F53\u524D\u672A\u663E\u793A\u7684 {hidden} \u6761\uFF0C\u4E5F\u5C06\u53C2\u4E0E\u64CD\u4F5C",
|
|
3489
3640
|
"archives.clearSelectionShort": "\u6E05\u7A7A",
|
|
3490
|
-
"archives.
|
|
3641
|
+
"archives.restore": "\u6062\u590D",
|
|
3642
|
+
"archives.archiveTitle": "\u5F52\u6863 {n} \u4E2A\u804A\u5929\uFF1F",
|
|
3491
3643
|
"archives.deleteSelectionShort": "\u5220\u9664",
|
|
3492
3644
|
"archives.clearSelection": "\u6E05\u7A7A\u9009\u62E9",
|
|
3493
3645
|
"group.ungrouped": "\u672A\u5206\u7EC4",
|
|
@@ -3519,7 +3671,7 @@
|
|
|
3519
3671
|
"archived.badge": "\u5F52\u6863\u4F1A\u8BDD",
|
|
3520
3672
|
"archived.notOpenable": "\u5DF2\u5F52\u6863\uFF0C\u53D6\u6D88\u5F52\u6863\u540E\u53EF\u7EE7\u7EED\u5BF9\u8BDD",
|
|
3521
3673
|
"archives.title": "\u5F52\u6863\u4F1A\u8BDD",
|
|
3522
|
-
"archives.description": "\u7BA1\u7406\u5DF2\u5F52\u6863\
|
|
3674
|
+
"archives.description": "\u7BA1\u7406\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF0C\u6216\u9009\u62E9\u672A\u5F52\u6863\u4F1A\u8BDD\u8FDB\u884C\u6279\u91CF\u5F52\u6863\u3002",
|
|
3523
3675
|
"archives.viewProject": "GitHub",
|
|
3524
3676
|
"archives.feedback": "\u95EE\u9898\u53CD\u9988",
|
|
3525
3677
|
"archives.empty": "\u6682\u65E0\u5DF2\u5F52\u6863\u4F1A\u8BDD",
|
|
@@ -3615,14 +3767,27 @@
|
|
|
3615
3767
|
"time.ago": "{t}\u524D"
|
|
3616
3768
|
};
|
|
3617
3769
|
const en = {
|
|
3618
|
-
"archives.
|
|
3770
|
+
"archives.archiveProject": "Archive all chats in this project",
|
|
3771
|
+
"archives.archiveUngrouped": "Archive all ungrouped chats",
|
|
3772
|
+
"archives.archiveProjectDesc": "Archive all {n} unarchived sessions in \u201C{name}\u201D, regardless of the current search filter. You can restore them in Archived.",
|
|
3773
|
+
"archives.archiveUngroupedDesc": "Archive all {n} ungrouped, unarchived sessions, regardless of the current search filter. You can restore them in Archived.",
|
|
3774
|
+
"archives.tab.archived": "Archived",
|
|
3775
|
+
"archives.tab.unarchived": "Unarchived",
|
|
3776
|
+
"archives.searchUnarchived": "Search unarchived chats",
|
|
3777
|
+
"archives.emptyUnarchived": "No unarchived sessions.",
|
|
3778
|
+
"archives.archiveSelected": "Archive",
|
|
3779
|
+
"archives.openSession": "Open session",
|
|
3780
|
+
"archives.archiveSelectedDesc": "Archive the selected sessions, including selections hidden by the current filter. You can view and restore them in Archived.",
|
|
3781
|
+
"archives.archiveSuccess": "Archived {n} sessions.",
|
|
3782
|
+
"archives.archiveBatchFailed": "Batch archive failed: {detail}",
|
|
3619
3783
|
"archives.navigationUnavailable": "This host cannot keep the conversation archived while opening it. Use \u201CRestore and open\u201D instead.",
|
|
3620
3784
|
"archives.sessionNotRetained": "The host did not keep the requested conversation open. Try again, or restore it before opening.",
|
|
3621
3785
|
"archives.restoreOpen": "Restore and open",
|
|
3622
3786
|
"archives.selectedCount": "{n} selected",
|
|
3623
3787
|
"archives.selectionHiddenHint": "Includes {hidden} hidden by the current filter; actions apply to them too.",
|
|
3624
3788
|
"archives.clearSelectionShort": "Clear",
|
|
3625
|
-
"archives.
|
|
3789
|
+
"archives.restore": "Restore",
|
|
3790
|
+
"archives.archiveTitle": "Archive {n} chats?",
|
|
3626
3791
|
"archives.deleteSelectionShort": "Delete",
|
|
3627
3792
|
"archives.clearSelection": "Clear selection",
|
|
3628
3793
|
"group.ungrouped": "Ungrouped",
|
|
@@ -3654,7 +3819,7 @@
|
|
|
3654
3819
|
"archived.badge": "Archived sessions",
|
|
3655
3820
|
"archived.notOpenable": "This session is archived. Unarchive it to continue the conversation.",
|
|
3656
3821
|
"archives.title": "Archived sessions",
|
|
3657
|
-
"archives.description": "Manage archived sessions.",
|
|
3822
|
+
"archives.description": "Manage archived sessions or select unarchived sessions to archive in bulk.",
|
|
3658
3823
|
"archives.viewProject": "GitHub",
|
|
3659
3824
|
"archives.feedback": "Issues",
|
|
3660
3825
|
"archives.empty": "No archived sessions.",
|
|
@@ -3757,8 +3922,7 @@
|
|
|
3757
3922
|
"workspaces",
|
|
3758
3923
|
"locale",
|
|
3759
3924
|
"remote",
|
|
3760
|
-
"typert"
|
|
3761
|
-
...hasSplitClientStore ? ["uiWorkspace"] : []
|
|
3925
|
+
"typert"
|
|
3762
3926
|
];
|
|
3763
3927
|
function bindObservable(source) {
|
|
3764
3928
|
return {
|
|
@@ -3766,18 +3930,58 @@
|
|
|
3766
3930
|
subscribe: source.subscribe.bind(source)
|
|
3767
3931
|
};
|
|
3768
3932
|
}
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3933
|
+
function createUnarchiveSession(workspaces, getRegistry) {
|
|
3934
|
+
return async (sessionId) => {
|
|
3935
|
+
if (typeof workspaces?.unarchiveSession === "function") {
|
|
3936
|
+
await workspaces.unarchiveSession(sessionId);
|
|
3937
|
+
return;
|
|
3938
|
+
}
|
|
3939
|
+
const registry = typeof getRegistry === "function" ? getRegistry() : getRegistry;
|
|
3940
|
+
if (registry === void 0) throw new Error("archive-manager remote service is unavailable");
|
|
3941
|
+
const result = await registry.unarchiveSession(sessionId);
|
|
3942
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
3943
|
+
return result.value;
|
|
3944
|
+
};
|
|
3945
|
+
}
|
|
3946
|
+
async function archiveSessionsViaOfficial(workspaces, sessionIds, refresh) {
|
|
3947
|
+
const before = new Set(workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []);
|
|
3948
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3949
|
+
for (const sessionId of sessionIds) {
|
|
3950
|
+
if (typeof sessionId !== "string" || sessionId.length === 0 || seen.has(sessionId)) continue;
|
|
3951
|
+
seen.add(sessionId);
|
|
3952
|
+
await workspaces.archiveSession(sessionId);
|
|
3953
|
+
}
|
|
3954
|
+
if (typeof refresh === "function") await refresh();
|
|
3955
|
+
const archivedSessionIds = [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
3956
|
+
return {
|
|
3957
|
+
archivedSessionIds,
|
|
3958
|
+
archivedSessionIdsAdded: archivedSessionIds.filter((id) => !before.has(id))
|
|
3959
|
+
};
|
|
3960
|
+
}
|
|
3961
|
+
async function unarchiveSessionsViaOfficial(workspaces, sessionIds, refresh, unarchive) {
|
|
3962
|
+
const before = new Set(workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []);
|
|
3963
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3964
|
+
const run = typeof unarchive === "function" ? unarchive : (id) => workspaces.unarchiveSession(id);
|
|
3965
|
+
let archivedSessionIds;
|
|
3966
|
+
for (const sessionId of sessionIds) {
|
|
3967
|
+
if (typeof sessionId !== "string" || sessionId.length === 0 || seen.has(sessionId)) continue;
|
|
3968
|
+
seen.add(sessionId);
|
|
3969
|
+
const value = await run(sessionId);
|
|
3970
|
+
if (Array.isArray(value?.archivedSessionIds)) archivedSessionIds = [...value.archivedSessionIds];
|
|
3971
|
+
}
|
|
3972
|
+
if (typeof refresh === "function") await refresh();
|
|
3973
|
+
archivedSessionIds ??= [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
3974
|
+
return {
|
|
3975
|
+
archivedSessionIds,
|
|
3976
|
+
unarchivedSessionIds: [...before].filter((id) => !archivedSessionIds.includes(id))
|
|
3977
|
+
};
|
|
3774
3978
|
}
|
|
3775
3979
|
async function apply(ctx) {
|
|
3980
|
+
applyWorkspaceBrowser(ctx);
|
|
3776
3981
|
const remote = ctx.get("remote");
|
|
3777
3982
|
let disposeRemote = () => {
|
|
3778
3983
|
};
|
|
3779
3984
|
if (remote !== void 0) disposeRemote = await remote.$mount(ARCHIVE_MANAGER_REMOTE);
|
|
3780
|
-
applyWorkspaceBrowser(ctx);
|
|
3781
3985
|
return async () => {
|
|
3782
3986
|
await disposeRemote();
|
|
3783
3987
|
};
|
|
@@ -3799,13 +4003,24 @@
|
|
|
3799
4003
|
const uiWorkspaceAt = () => ctx.get("uiWorkspace");
|
|
3800
4004
|
const archiveViewState = {};
|
|
3801
4005
|
let archiveNavigation;
|
|
3802
|
-
|
|
3803
|
-
archiveNavigation = allowArchivedNavigation(
|
|
3804
|
-
onOpened: () => ctx.get("layout")?.selectPanel(null)
|
|
4006
|
+
const attachArchiveNavigation = (navigation) => {
|
|
4007
|
+
archiveNavigation = allowArchivedNavigation(navigation, ctx.sessions, ctx.workspaces, {
|
|
4008
|
+
onOpened: () => ctx.get("layout")?.selectPanel(null),
|
|
4009
|
+
beginNavigation: () => ctx.get("layout")?.beginNavigation?.()
|
|
3805
4010
|
});
|
|
3806
4011
|
return () => archiveNavigation.dispose();
|
|
3807
|
-
}
|
|
3808
|
-
|
|
4012
|
+
};
|
|
4013
|
+
if (typeof ctx.inject === "function") ctx.inject(["uiWorkspace"], (ready) => attachArchiveNavigation(ready.uiWorkspace ?? uiWorkspaceAt()));
|
|
4014
|
+
else ctx.effect(() => attachArchiveNavigation(uiWorkspaceAt()), "archive-manager: explicit archived navigation");
|
|
4015
|
+
const openConversation = (sessionId) => {
|
|
4016
|
+
if (archiveNavigation === void 0) throw new ArchiveNavigationError("navigationUnavailable");
|
|
4017
|
+
sidebarReveal.request(sessionId);
|
|
4018
|
+
return archiveNavigation.open(sessionId);
|
|
4019
|
+
};
|
|
4020
|
+
const focusSessionWorkspace = async (sessionId) => {
|
|
4021
|
+
ctx.get("layout")?.beginNavigation?.();
|
|
4022
|
+
sidebarReveal.request(sessionId);
|
|
4023
|
+
};
|
|
3809
4024
|
const searchSessions = async (query, signal) => {
|
|
3810
4025
|
const result = await ctx.sessions.search(query, signal);
|
|
3811
4026
|
if (!result.ok) throw new Error(result.error.message);
|
|
@@ -3824,17 +4039,16 @@
|
|
|
3824
4039
|
console.warn("archive-manager: restored archived sessions but session list refresh failed:", error);
|
|
3825
4040
|
}
|
|
3826
4041
|
};
|
|
4042
|
+
const unarchiveOne = createUnarchiveSession(ctx.workspaces, () => ctx.get("remote.workspaceRegistry"));
|
|
3827
4043
|
const unarchiveSession = async (sessionId) => {
|
|
3828
|
-
|
|
3829
|
-
if (registry === void 0) throw new Error("archive-manager remote service is unavailable");
|
|
3830
|
-
const result = await registry.unarchiveSession(sessionId);
|
|
3831
|
-
if (!result.ok) throw new Error(result.error.message);
|
|
4044
|
+
await unarchiveOne(sessionId);
|
|
3832
4045
|
await refreshSessionList();
|
|
3833
4046
|
};
|
|
3834
4047
|
const archiveWorkspaceSessions = async (workspaceId) => {
|
|
3835
|
-
const
|
|
3836
|
-
|
|
3837
|
-
|
|
4048
|
+
const items = ctx.workspaces.list?.getSnapshot?.()?.items ?? [];
|
|
4049
|
+
const workspace = items.find((item) => item.workspaceId === workspaceId);
|
|
4050
|
+
if (workspace === void 0) throw new Error(`unknown workspace "${workspaceId}"`);
|
|
4051
|
+
return archiveSessionsViaOfficial(ctx.workspaces, workspace.sessionIds, refreshSessionList);
|
|
3838
4052
|
};
|
|
3839
4053
|
const deleteSession = async (sessionId) => {
|
|
3840
4054
|
const registry = ctx.get("remote.workspaceRegistry");
|
|
@@ -3843,13 +4057,11 @@
|
|
|
3843
4057
|
if (!result.ok) throw new Error(result.error.message);
|
|
3844
4058
|
await refreshSessionList();
|
|
3845
4059
|
};
|
|
4060
|
+
const archiveSessions = async (sessionIds) => archiveSessionsViaOfficial(ctx.workspaces, sessionIds, refreshSessionList);
|
|
3846
4061
|
const unarchiveSessions = async (target) => {
|
|
3847
|
-
const
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
if (!result.ok) throw new Error(result.error.message);
|
|
3851
|
-
await refreshSessionList();
|
|
3852
|
-
return result.value;
|
|
4062
|
+
const snapshot = ctx.workspaces.list?.getSnapshot?.() ?? { archivedSessionIds: [], items: [] };
|
|
4063
|
+
const sessionIds = deriveArchivedBatchIds(snapshot.archivedSessionIds, snapshot.items, target);
|
|
4064
|
+
return unarchiveSessionsViaOfficial(ctx.workspaces, sessionIds, refreshSessionList, unarchiveOne);
|
|
3853
4065
|
};
|
|
3854
4066
|
const deleteArchivedSessions = async (target) => {
|
|
3855
4067
|
const registry = ctx.get("remote.workspaceRegistry");
|
|
@@ -3920,18 +4132,28 @@
|
|
|
3920
4132
|
createWorkspace: (input) => ctx.workspaces.create(input),
|
|
3921
4133
|
hooks: { directoryFlow: browserFlowSource }
|
|
3922
4134
|
});
|
|
3923
|
-
ctx.slots.inject("sidebar.workspaces", () =>
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
4135
|
+
ctx.slots.inject("sidebar.workspaces", () => {
|
|
4136
|
+
const common = {
|
|
4137
|
+
name: "sidebar.workspaces",
|
|
4138
|
+
// 低于官方 0,高于 Codex -1:必须盖住官方三项菜单才能露出删除。
|
|
4139
|
+
priority: -0.5,
|
|
4140
|
+
store: createWorkspaceViewStore(),
|
|
4141
|
+
inject: browserInjected,
|
|
4142
|
+
locale: NS
|
|
4143
|
+
};
|
|
4144
|
+
try {
|
|
4145
|
+
return ctx.slots.register({
|
|
4146
|
+
...common,
|
|
4147
|
+
children: { [DIRECTORY_FLOW_SLOT]: {
|
|
4148
|
+
kind: "single",
|
|
4149
|
+
scope: "root"
|
|
4150
|
+
} }
|
|
4151
|
+
}, WorkspaceBrowser);
|
|
4152
|
+
} catch (error) {
|
|
4153
|
+
console.warn("archive-manager: sidebar registration with directory child failed, retrying without children", error);
|
|
4154
|
+
return ctx.slots.register(common, WorkspaceBrowser);
|
|
4155
|
+
}
|
|
4156
|
+
});
|
|
3935
4157
|
mirrorDirectoryFlow(ctx, DIRECTORY_FLOW_SLOT);
|
|
3936
4158
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
3937
4159
|
name: "settings.section",
|
|
@@ -3941,6 +4163,7 @@
|
|
|
3941
4163
|
icon: "archive",
|
|
3942
4164
|
locale: NS,
|
|
3943
4165
|
inject: () => ({
|
|
4166
|
+
archiveSessions,
|
|
3944
4167
|
sessionStore: bindObservable(ctx.sessions.list),
|
|
3945
4168
|
workspaceStore: bindObservable(ctx.workspaces.list),
|
|
3946
4169
|
unarchiveSession,
|
|
@@ -3949,12 +4172,14 @@
|
|
|
3949
4172
|
deleteArchivedSessions,
|
|
3950
4173
|
archivedSessionMetadata,
|
|
3951
4174
|
openConversation,
|
|
4175
|
+
focusSessionWorkspace,
|
|
3952
4176
|
viewState: archiveViewState,
|
|
3953
4177
|
t: ctx.locale.bind(NS)
|
|
3954
4178
|
})
|
|
3955
4179
|
}, ArchivedSessionsSection));
|
|
3956
4180
|
}
|
|
3957
4181
|
exports.__test = {
|
|
4182
|
+
unarchivedSessionIds,
|
|
3958
4183
|
ArchiveSelectionToolbar,
|
|
3959
4184
|
ArchivedSessionsSection,
|
|
3960
4185
|
zh,
|
|
@@ -3975,8 +4200,13 @@
|
|
|
3975
4200
|
archiveableWorkspaceSessionCount,
|
|
3976
4201
|
archiveWorkspaceDialogTarget,
|
|
3977
4202
|
archiveWorkspaceDialogFailureState,
|
|
3978
|
-
|
|
4203
|
+
archiveSessionsViaOfficial,
|
|
4204
|
+
unarchiveSessionsViaOfficial,
|
|
4205
|
+
createUnarchiveSession,
|
|
3979
4206
|
createWorkspaceViewStore,
|
|
4207
|
+
migrateWorkspaceViewPersist,
|
|
4208
|
+
WORKSPACE_VIEW_PERSIST_KEY,
|
|
4209
|
+
LEGACY_WORKSPACE_VIEW_PERSIST_KEY,
|
|
3980
4210
|
bindObservable,
|
|
3981
4211
|
hasSplitClientStore,
|
|
3982
4212
|
groupByWorkspace,
|