@nextclaw/ui 0.14.4 → 0.15.0
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 +54 -0
- package/dist/assets/api-DLtsiBKm.js +13 -0
- package/dist/assets/appearance-settings-page-CtkeYXux.js +1 -0
- package/dist/assets/book-open-BQwWBDKb.js +1 -0
- package/dist/assets/channels-list-page-Cv8o9Hxg.js +8 -0
- package/dist/assets/chat-page-BtA7H1Ea.js +1 -0
- package/dist/assets/{config-split-page-CRhlZ_pH.js → config-split-page-EidRBpP2.js} +1 -1
- package/dist/assets/confirm-dialog-iIJFFp2T.js +5 -0
- package/dist/assets/desktop-update-config-C6n_TB1r.js +1 -0
- package/dist/assets/{dist-CikkhOlq.js → dist-CBxWOazz.js} +1 -1
- package/dist/assets/{dist-PVA_xL1D.js → dist-D2eZC3OR.js} +1 -1
- package/dist/assets/doc-browser-B76XOXmW.js +1 -0
- package/dist/assets/doc-browser-DBnj9UMB.js +1 -0
- package/dist/assets/{doc-browser-context-MTw4EvKd.js → doc-browser-context-Sv-044Cl.js} +1 -1
- package/dist/assets/{ellipsis-y6vDtq4M.js → ellipsis-2uzhypw5.js} +1 -1
- package/dist/assets/es2015-DhQo_oS6.js +41 -0
- package/dist/assets/{external-link-DVJIQf_G.js → external-link-CM5dnUI6.js} +1 -1
- package/dist/assets/host-capabilities-9bB_998Z.js +1 -0
- package/dist/assets/i18n-provider-di1waTGX.js +1 -0
- package/dist/assets/index-CBRP-7-a.css +1 -0
- package/dist/assets/index-Z1fYpbNd.js +104 -0
- package/dist/assets/loader-circle-BjmN5DeJ.js +1 -0
- package/dist/assets/mcp-marketplace-page-C_MVQUbT.js +9 -0
- package/dist/assets/mcp-marketplace-page-CoZIiD6G.js +1 -0
- package/dist/assets/model-config-page-Cdr9P6TQ.js +1 -0
- package/dist/assets/plus-3ztRZD_l.js +1 -0
- package/dist/assets/provider-scoped-model-input-g1WkGiJ8.js +1 -0
- package/dist/assets/providers-config-page-CWlO7J4A.js +1 -0
- package/dist/assets/{react-VNqT5Zp7.js → react-DjpzoZXB.js} +1 -1
- package/dist/assets/refresh-cw-DaTv3zxE.js +1 -0
- package/dist/assets/remote-CKWZfVVB.js +1 -0
- package/dist/assets/rotate-cw-CHcaRUDz.js +1 -0
- package/dist/assets/runtime-config-page-CfTqh1nv.js +1 -0
- package/dist/assets/{save-BOJ477H-.js → save-BZof1uie.js} +1 -1
- package/dist/assets/{search-BEti5beA.js → search-MxAarS_g.js} +1 -1
- package/dist/assets/search-config-page-Dm8daYny.js +1 -0
- package/dist/assets/{secrets-config-page--IzrIOid.js → secrets-config-page-D8AbcR05.js} +2 -2
- package/dist/assets/security-config-Ds0LsJmo.js +1 -0
- package/dist/assets/select-D7GcNP0z.js +1 -0
- package/dist/assets/setting-row-CuozlnJd.js +1 -0
- package/dist/assets/side-dock-BcLau5S_.js +3 -0
- package/dist/assets/skeleton-shfmXuYp.js +1 -0
- package/dist/assets/switch-C1BWMU5c.js +1 -0
- package/dist/assets/tag-chip-DCUrQUCP.js +1 -0
- package/dist/assets/tooltip-DfAHHA76.js +1 -0
- package/dist/assets/use-config-DAdbT5QJ.js +1 -0
- package/dist/assets/use-confirm-dialog-eWcJ6V-s.js +1 -0
- package/dist/assets/x-DqL1mYLC.js +1 -0
- package/dist/index.html +53 -17
- package/index.html +25 -2
- package/package.json +9 -9
- package/src/app/components/layout/__tests__/app-layout.test.tsx +27 -0
- package/src/app/components/layout/__tests__/settings-entry-page.test.tsx +9 -1
- package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +6 -3
- package/src/app/components/layout/app-layout.tsx +10 -3
- package/src/app/components/layout/sidebar-items.tsx +8 -8
- package/src/app/components/layout/sidebar-rail.styles.ts +4 -2
- package/src/app/components/layout/sidebar.tsx +21 -28
- package/src/app/configs/app-navigation.config.ts +11 -5
- package/src/app/index.tsx +8 -0
- package/src/app/managers/__tests__/viewport-layout.manager.test.ts +59 -0
- package/src/app/managers/viewport-layout.manager.ts +39 -0
- package/src/app/presenters/app.presenter.ts +25 -2
- package/src/app/styles/design-system.css +91 -4
- package/src/features/chat/components/conversation/__tests__/chat-conversation-content.test.tsx +86 -0
- package/src/features/chat/components/conversation/chat-conversation-content.tsx +47 -17
- package/src/features/chat/components/layout/__tests__/chat-sidebar-read-state.test.tsx +7 -0
- package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +9 -5
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +5 -5
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +51 -2
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +170 -1
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +23 -1
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +24 -7
- package/src/features/chat/features/conversation/components/session-queued-input-rows.tsx +96 -0
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +181 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +351 -89
- package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +29 -4
- package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +28 -3
- package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +108 -8
- package/src/features/chat/features/input/input-surface-plugins/panel-app-reference-plugin.utils.ts +50 -14
- package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +77 -6
- package/src/features/chat/features/message/components/__tests__/chat-inline-panel-app-card.test.tsx +21 -12
- package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +166 -0
- package/src/features/chat/features/message/components/chat-inline-panel-app-card.tsx +19 -11
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +38 -64
- package/src/features/chat/features/message/utils/__tests__/chat-message-process-summary.utils.test.ts +59 -0
- package/src/features/chat/features/message/utils/__tests__/chat-message-show-content-tool-card.utils.test.ts +56 -1
- package/src/features/chat/features/message/utils/chat-inline-panel-app-card.utils.ts +0 -2
- package/src/features/chat/features/message/utils/chat-message-process-summary.utils.ts +80 -0
- package/src/features/chat/features/message/utils/chat-message-show-content-tool-card.utils.ts +12 -3
- package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +60 -0
- package/src/features/chat/features/message/utils/chat-message.utils.ts +3 -0
- package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime.test.tsx +39 -0
- package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +2 -2
- package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +3 -1
- package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +270 -115
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumb-browser.tsx +121 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +75 -20
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +70 -5
- package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +83 -0
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +79 -1
- package/src/features/chat/managers/__tests__/chat-ui.manager.test.ts +2 -0
- package/src/features/chat/managers/chat-thread.manager.ts +9 -3
- package/src/features/chat/managers/chat-ui.manager.ts +5 -1
- package/src/features/chat/presenters/chat.presenter.ts +2 -1
- package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +4 -0
- package/src/features/chat/stores/chat-thread.store.ts +6 -64
- package/src/features/chat/types/chat-message.types.ts +4 -0
- package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +33 -26
- package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +1 -0
- package/src/features/marketplace/components/curated-shelves/__tests__/marketplace-curated-scene-route.test.tsx +1 -0
- package/src/features/marketplace/components/detail-doc/__tests__/marketplace-detail-doc.test.tsx +115 -0
- package/src/features/marketplace/components/marketplace-detail-doc.tsx +441 -0
- package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +3 -3
- package/src/features/marketplace/components/mcp/mcp-marketplace-doc.ts +0 -60
- package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +64 -29
- package/src/features/marketplace/hooks/use-marketplace-item-detail.ts +42 -31
- package/src/features/marketplace/index.ts +3 -0
- package/src/features/marketplace/stores/marketplace-detail-doc.store.ts +38 -0
- package/src/features/panel-apps/components/__tests__/panel-apps-list.test.tsx +32 -2
- package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +11 -0
- package/src/features/pwa/managers/pwa-shell-theme.manager.ts +8 -3
- package/src/features/settings/pages/__tests__/appearance-settings-page.test.tsx +25 -0
- package/src/features/settings/pages/appearance-settings-page.tsx +40 -0
- package/src/features/side-dock/components/__tests__/side-dock.test.tsx +44 -2
- package/src/features/side-dock/components/side-dock.tsx +100 -13
- package/src/features/side-dock/configs/side-dock-built-in-items.config.ts +10 -0
- package/src/features/side-dock/managers/__tests__/side-dock.manager.test.ts +32 -2
- package/src/features/side-dock/managers/side-dock.manager.ts +17 -7
- package/src/features/side-dock/stores/side-dock.store.ts +9 -0
- package/src/features/side-dock/types/side-dock.types.ts +10 -3
- package/src/features/side-dock/utils/side-dock-item.utils.ts +15 -2
- package/src/index.css +501 -27
- package/src/platforms/desktop/components/desktop-window-chrome.tsx +1 -1
- package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +30 -1
- package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +206 -38
- package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +34 -11
- package/src/shared/components/doc-browser/doc-browser-renderer.types.ts +1 -1
- package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +23 -5
- package/src/shared/components/doc-browser/doc-browser.tsx +128 -75
- package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +9 -1
- package/src/shared/components/doc-browser/utils/doc-browser-floating-panel.utils.ts +83 -0
- package/src/shared/components/ui/__tests__/dialog.test.tsx +27 -0
- package/src/shared/components/ui/actions/icon-action-button.tsx +14 -2
- package/src/shared/components/ui/dialog.tsx +2 -2
- package/src/shared/components/ui/popover.tsx +1 -1
- package/src/shared/components/ui/select.tsx +1 -1
- package/src/shared/components/ui/switch.tsx +4 -3
- package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +54 -0
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +4 -5
- package/src/shared/components/ui/tooltip.tsx +1 -1
- package/src/shared/lib/api/utils/server-path.utils.ts +27 -1
- package/src/shared/lib/i18n/locales/en-US/chat.json +15 -6
- package/src/shared/lib/i18n/locales/en-US/core.json +2 -0
- package/src/shared/lib/i18n/locales/en-US/doc-browser.json +11 -0
- package/src/shared/lib/i18n/locales/en-US/marketplace.json +5 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +15 -6
- package/src/shared/lib/i18n/locales/zh-CN/core.json +2 -0
- package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -0
- package/src/shared/lib/i18n/locales/zh-CN/marketplace.json +5 -0
- package/src/shared/lib/session-project/__tests__/workspace-file-breadcrumb.test.ts +14 -0
- package/src/shared/lib/session-project/index.ts +1 -1
- package/src/shared/lib/session-project/{workspace-file-breadcrumb.ts → workspace-file-breadcrumb.utils.ts} +62 -8
- package/src/shared/lib/theme/index.ts +51 -13
- package/dist/assets/api-BP_8IaxB.js +0 -13
- package/dist/assets/channels-list-page-DEh5Jjqx.js +0 -8
- package/dist/assets/chat-page-BRB0N5WW.js +0 -105
- package/dist/assets/confirm-dialog-DsivFJ4r.js +0 -5
- package/dist/assets/desktop-update-config-B0w9p2ep.js +0 -1
- package/dist/assets/doc-browser-BoNJ7-tE.js +0 -1
- package/dist/assets/doc-browser-CdJ_d4ik.js +0 -1
- package/dist/assets/index-BiE-K8-q.css +0 -1
- package/dist/assets/index-D9BAE_L_.js +0 -105
- package/dist/assets/mcp-marketplace-page-B1SZNY5m.js +0 -40
- package/dist/assets/mcp-marketplace-page-Cq_Tw42T.js +0 -1
- package/dist/assets/model-config-page-DotaTUHb.js +0 -1
- package/dist/assets/plus-BbZqquJe.js +0 -1
- package/dist/assets/provider-scoped-model-input-DsFRuWJH.js +0 -1
- package/dist/assets/providers-config-page-DW4tQSLN.js +0 -1
- package/dist/assets/remote-B8TiUfwW.js +0 -1
- package/dist/assets/rotate-cw-DjHDTkCv.js +0 -1
- package/dist/assets/runtime-config-page-S6ErRHR8.js +0 -1
- package/dist/assets/search-config-page-DGj5am03.js +0 -1
- package/dist/assets/select-hoj8dK4K.js +0 -41
- package/dist/assets/tag-chip-T8-h-die.js +0 -1
- package/dist/assets/use-config-CjRV2hwL.js +0 -1
- package/dist/assets/x-D9PXs_xP.js +0 -1
- package/src/features/marketplace/components/detail-doc/__tests__/marketplace-detail-doc.test.ts +0 -40
- package/src/features/marketplace/components/detail-doc/marketplace-detail-doc-renderer.ts +0 -201
- package/src/features/marketplace/components/marketplace-detail-doc.ts +0 -142
- /package/dist/assets/{config-hints-BkYBc7z0.js → config-hints-fGnUjDe9.js} +0 -0
- /package/dist/assets/{middleware-CkFT3R4v.js → middleware-BILWbJE4.js} +0 -0
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
getSideDockBuiltInItems,
|
|
4
|
+
SIDE_DOCK_GITHUB_PROJECT_ITEM_ID,
|
|
5
|
+
SIDE_DOCK_GITHUB_PROJECT_URL,
|
|
6
|
+
} from '@/features/side-dock/configs/side-dock-built-in-items.config';
|
|
2
7
|
import { SideDockManager } from '@/features/side-dock/managers/side-dock.manager';
|
|
3
8
|
import { useSideDockStore } from '@/features/side-dock/stores/side-dock.store';
|
|
4
9
|
import type { SideDockItem } from '@/features/side-dock/types/side-dock.types';
|
|
5
10
|
import type { DocBrowserManager } from '@/shared/components/doc-browser/managers/doc-browser.manager';
|
|
6
11
|
|
|
12
|
+
const mocks = vi.hoisted(() => ({
|
|
13
|
+
openExternalUrl: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
vi.mock('@/shared/lib/host-capabilities', () => ({
|
|
17
|
+
hostCapabilityManager: {
|
|
18
|
+
openExternalUrl: mocks.openExternalUrl,
|
|
19
|
+
},
|
|
20
|
+
}));
|
|
21
|
+
|
|
7
22
|
const customItem: SideDockItem = {
|
|
8
23
|
builtIn: false,
|
|
9
24
|
icon: { type: 'builtin', name: 'docs' },
|
|
@@ -16,14 +31,17 @@ const customItem: SideDockItem = {
|
|
|
16
31
|
describe('SideDockManager', () => {
|
|
17
32
|
beforeEach(() => {
|
|
18
33
|
window.localStorage.clear();
|
|
34
|
+
mocks.openExternalUrl.mockReset();
|
|
35
|
+
mocks.openExternalUrl.mockResolvedValue({ opened: true });
|
|
36
|
+
useSideDockStore.getState().setVisible(true);
|
|
19
37
|
useSideDockStore.getState().setPinnedItems([]);
|
|
20
38
|
});
|
|
21
39
|
|
|
22
|
-
it('opens right panel resource items through DocBrowserManager', () => {
|
|
40
|
+
it('opens right panel resource items through DocBrowserManager', async () => {
|
|
23
41
|
const open = vi.fn();
|
|
24
42
|
const manager = new SideDockManager({ open } as unknown as DocBrowserManager);
|
|
25
43
|
|
|
26
|
-
manager.openItem(customItem);
|
|
44
|
+
await manager.openItem(customItem);
|
|
27
45
|
|
|
28
46
|
expect(open).toHaveBeenCalledWith('nextclaw://docs/custom', {
|
|
29
47
|
dockIcon: { type: 'builtin', name: 'docs' },
|
|
@@ -31,6 +49,18 @@ describe('SideDockManager', () => {
|
|
|
31
49
|
});
|
|
32
50
|
});
|
|
33
51
|
|
|
52
|
+
it('opens the GitHub project shortcut through host capabilities', async () => {
|
|
53
|
+
const open = vi.fn();
|
|
54
|
+
const manager = new SideDockManager({ open } as unknown as DocBrowserManager);
|
|
55
|
+
const githubItem = getSideDockBuiltInItems().find((item) => item.id === SIDE_DOCK_GITHUB_PROJECT_ITEM_ID);
|
|
56
|
+
|
|
57
|
+
expect(githubItem).toBeTruthy();
|
|
58
|
+
await manager.openItem(githubItem as SideDockItem);
|
|
59
|
+
|
|
60
|
+
expect(open).not.toHaveBeenCalled();
|
|
61
|
+
expect(mocks.openExternalUrl).toHaveBeenCalledWith(SIDE_DOCK_GITHUB_PROJECT_URL);
|
|
62
|
+
});
|
|
63
|
+
|
|
34
64
|
it('pins removable items and keeps built-in items immutable', () => {
|
|
35
65
|
const manager = new SideDockManager({ open: vi.fn() } as unknown as DocBrowserManager);
|
|
36
66
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
createPinnedSideDockItem,
|
|
11
11
|
mergeSideDockItems,
|
|
12
12
|
} from '@/features/side-dock/utils/side-dock-item.utils';
|
|
13
|
+
import { hostCapabilityManager } from '@/shared/lib/host-capabilities';
|
|
13
14
|
import type { DocBrowserManager } from '@/shared/components/doc-browser/managers/doc-browser.manager';
|
|
14
15
|
import type {
|
|
15
16
|
DocBrowserDockIcon,
|
|
@@ -20,6 +21,7 @@ const SIDE_DOCK_PINNED_ITEM_ID_PREFIX = 'pinned';
|
|
|
20
21
|
const SIDE_DOCK_ICON_NAMES = new Set<SideDockIconName>([
|
|
21
22
|
'apps',
|
|
22
23
|
'docs',
|
|
24
|
+
'github',
|
|
23
25
|
'new-tab',
|
|
24
26
|
'panel-app',
|
|
25
27
|
'service-apps',
|
|
@@ -78,12 +80,16 @@ export class SideDockManager {
|
|
|
78
80
|
useSideDockStore.getState().pinnedItems,
|
|
79
81
|
);
|
|
80
82
|
|
|
81
|
-
openItem = (item: Pick<SideDockItem, 'icon' | 'label' | 'target'>): void => {
|
|
83
|
+
openItem = async (item: Pick<SideDockItem, 'icon' | 'label' | 'target'>): Promise<void> => {
|
|
82
84
|
if (item.target.type === 'right-panel-resource') {
|
|
83
85
|
this.docBrowserManager.open(item.target.uri, {
|
|
84
86
|
dockIcon: item.icon,
|
|
85
87
|
title: item.label,
|
|
86
88
|
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (item.target.type === 'external-url') {
|
|
92
|
+
await hostCapabilityManager.openExternalUrl(item.target.url);
|
|
87
93
|
}
|
|
88
94
|
};
|
|
89
95
|
|
|
@@ -130,18 +136,19 @@ export class SideDockManager {
|
|
|
130
136
|
};
|
|
131
137
|
|
|
132
138
|
pinItem = (item: SideDockItem, createdAt: string = new Date().toISOString()): void => {
|
|
133
|
-
if (!item.removable) {
|
|
139
|
+
if (!item.removable || item.target.type !== 'right-panel-resource') {
|
|
134
140
|
return;
|
|
135
141
|
}
|
|
136
142
|
const uri = normalizeSideDockResourceUri(item.target.uri);
|
|
143
|
+
const resourceItem = {
|
|
144
|
+
...item,
|
|
145
|
+
target: { type: 'right-panel-resource' as const, uri },
|
|
146
|
+
};
|
|
137
147
|
this.setPinnedItems((items) => {
|
|
138
148
|
if (items.some((pinnedItem) => pinnedItem.id === item.id || normalizeSideDockResourceUri(pinnedItem.target.uri) === uri)) {
|
|
139
149
|
return items;
|
|
140
150
|
}
|
|
141
|
-
return [...items, createPinnedSideDockItem(
|
|
142
|
-
...item,
|
|
143
|
-
target: { ...item.target, uri },
|
|
144
|
-
}, createdAt)];
|
|
151
|
+
return [...items, createPinnedSideDockItem(resourceItem, createdAt)];
|
|
145
152
|
});
|
|
146
153
|
};
|
|
147
154
|
|
|
@@ -176,6 +183,9 @@ export class SideDockManager {
|
|
|
176
183
|
|
|
177
184
|
private findItemByUri = (uri: string): SideDockItem | undefined => {
|
|
178
185
|
const normalized = normalizeSideDockResourceUri(uri);
|
|
179
|
-
return this.getItems().find((item) =>
|
|
186
|
+
return this.getItems().find((item) => (
|
|
187
|
+
item.target.type === 'right-panel-resource'
|
|
188
|
+
&& normalizeSideDockResourceUri(item.target.uri) === normalized
|
|
189
|
+
));
|
|
180
190
|
};
|
|
181
191
|
}
|
|
@@ -7,7 +7,9 @@ const SIDE_DOCK_STORAGE_KEY = 'nextclaw.side-dock.state';
|
|
|
7
7
|
const SIDE_DOCK_STORAGE_VERSION = 1;
|
|
8
8
|
|
|
9
9
|
type SideDockStore = {
|
|
10
|
+
isVisible: boolean;
|
|
10
11
|
pinnedItems: SideDockPinnedItem[];
|
|
12
|
+
setVisible: (isVisible: boolean) => void;
|
|
11
13
|
setPinnedItems: (items: SideDockPinnedItem[]) => void;
|
|
12
14
|
};
|
|
13
15
|
|
|
@@ -18,7 +20,9 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
18
20
|
export const useSideDockStore = create<SideDockStore>()(
|
|
19
21
|
persist(
|
|
20
22
|
(set) => ({
|
|
23
|
+
isVisible: true,
|
|
21
24
|
pinnedItems: [],
|
|
25
|
+
setVisible: (isVisible) => set({ isVisible }),
|
|
22
26
|
setPinnedItems: (items) => set({ pinnedItems: normalizeSideDockPinnedItems(items) }),
|
|
23
27
|
}),
|
|
24
28
|
{
|
|
@@ -26,14 +30,19 @@ export const useSideDockStore = create<SideDockStore>()(
|
|
|
26
30
|
version: SIDE_DOCK_STORAGE_VERSION,
|
|
27
31
|
storage: createJSONStorage(() => window.localStorage),
|
|
28
32
|
partialize: (state) => ({
|
|
33
|
+
isVisible: state.isVisible,
|
|
29
34
|
pinnedItems: state.pinnedItems,
|
|
30
35
|
}),
|
|
31
36
|
merge: (persistedState, currentState) => {
|
|
32
37
|
const pinnedItems = isRecord(persistedState)
|
|
33
38
|
? normalizeSideDockPinnedItems(persistedState.pinnedItems)
|
|
34
39
|
: [];
|
|
40
|
+
const isVisible = isRecord(persistedState) && typeof persistedState.isVisible === 'boolean'
|
|
41
|
+
? persistedState.isVisible
|
|
42
|
+
: true;
|
|
35
43
|
return {
|
|
36
44
|
...currentState,
|
|
45
|
+
isVisible,
|
|
37
46
|
pinnedItems,
|
|
38
47
|
};
|
|
39
48
|
},
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
export type SideDockItemId = string;
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type SideDockResourceItemTarget = {
|
|
4
4
|
type: 'right-panel-resource';
|
|
5
5
|
uri: string;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type SideDockExternalUrlTarget = {
|
|
9
|
+
type: 'external-url';
|
|
10
|
+
url: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SideDockItemTarget = SideDockResourceItemTarget | SideDockExternalUrlTarget;
|
|
14
|
+
|
|
15
|
+
export type SideDockIconName = 'apps' | 'docs' | 'github' | 'new-tab' | 'panel-app' | 'service-apps';
|
|
9
16
|
|
|
10
17
|
export type SideDockItemIcon =
|
|
11
18
|
| { type: 'builtin'; name: SideDockIconName }
|
|
@@ -26,7 +33,7 @@ export type SideDockPinnedItem = {
|
|
|
26
33
|
icon: SideDockItemIcon;
|
|
27
34
|
id: SideDockItemId;
|
|
28
35
|
label: string;
|
|
29
|
-
target:
|
|
36
|
+
target: SideDockResourceItemTarget;
|
|
30
37
|
};
|
|
31
38
|
|
|
32
39
|
export type SideDockResourceDockState = {
|
|
@@ -3,11 +3,13 @@ import type {
|
|
|
3
3
|
SideDockItem,
|
|
4
4
|
SideDockItemIcon,
|
|
5
5
|
SideDockPinnedItem,
|
|
6
|
+
SideDockResourceItemTarget,
|
|
6
7
|
} from '@/features/side-dock/types/side-dock.types';
|
|
7
8
|
|
|
8
9
|
const SIDE_DOCK_BUILTIN_ICON_NAMES: SideDockIconName[] = [
|
|
9
10
|
'apps',
|
|
10
11
|
'docs',
|
|
12
|
+
'github',
|
|
11
13
|
'new-tab',
|
|
12
14
|
'panel-app',
|
|
13
15
|
'service-apps',
|
|
@@ -99,7 +101,10 @@ export function normalizeSideDockPinnedItems(value: unknown): SideDockPinnedItem
|
|
|
99
101
|
return Array.from(itemsById.values());
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
export function createPinnedSideDockItem(
|
|
104
|
+
export function createPinnedSideDockItem(
|
|
105
|
+
item: SideDockItem & { target: SideDockResourceItemTarget },
|
|
106
|
+
createdAt: string,
|
|
107
|
+
): SideDockPinnedItem {
|
|
103
108
|
return {
|
|
104
109
|
createdAt,
|
|
105
110
|
icon: item.icon,
|
|
@@ -109,6 +114,10 @@ export function createPinnedSideDockItem(item: SideDockItem, createdAt: string):
|
|
|
109
114
|
};
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
function getSideDockResourceUri(item: SideDockItem | SideDockPinnedItem): string | null {
|
|
118
|
+
return item.target.type === 'right-panel-resource' ? item.target.uri : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
112
121
|
export function createSideDockItemFromPinnedItem(item: SideDockPinnedItem): SideDockItem {
|
|
113
122
|
return {
|
|
114
123
|
builtIn: false,
|
|
@@ -125,7 +134,11 @@ export function mergeSideDockItems(
|
|
|
125
134
|
pinnedItems: SideDockPinnedItem[],
|
|
126
135
|
): SideDockItem[] {
|
|
127
136
|
const seenIds = new Set(builtInItems.map((item) => item.id));
|
|
128
|
-
const seenUris = new Set(
|
|
137
|
+
const seenUris = new Set(
|
|
138
|
+
builtInItems
|
|
139
|
+
.map(getSideDockResourceUri)
|
|
140
|
+
.filter((uri): uri is string => uri !== null),
|
|
141
|
+
);
|
|
129
142
|
const customItems = pinnedItems
|
|
130
143
|
.filter((item) => !seenIds.has(item.id) && !seenUris.has(item.target.uri))
|
|
131
144
|
.map(createSideDockItemFromPinnedItem);
|