@nextclaw/ui 0.15.17 → 0.15.19
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 +31 -0
- package/dist/assets/api-O5yEgzBt.js +13 -0
- package/dist/assets/app-presenter-provider-DXTYtH78.js +106 -0
- package/dist/assets/appearance-settings-page-BuGxSvlJ.js +1 -0
- package/dist/assets/{book-open-WsEnuW9P.js → book-open-HtUSPwoS.js} +1 -1
- package/dist/assets/card-GkBc-UMw.js +1 -0
- package/dist/assets/{channels-list-page-CAWuTHSM.js → channels-list-page-Bspr1Jp4.js} +2 -2
- package/dist/assets/chat-page-BKQ89f4s.js +1 -0
- package/dist/assets/config-split-page-CvLXSFSC.js +1 -0
- package/dist/assets/confirm-dialog-BVH7haN0.js +5 -0
- package/dist/assets/desktop-update-config-C9ZUI8UW.js +1 -0
- package/dist/assets/{dist-Ca-jiFrK.js → dist-CZx9Q6jc.js} +1 -1
- package/dist/assets/doc-browser-B4l0Xu7u.js +1 -0
- package/dist/assets/doc-browser-DsVF1DrS.js +1 -0
- package/dist/assets/doc-browser-context-Dy7EhLI8.js +1 -0
- package/dist/assets/{eye-B30J471A.js → eye-DU7p1-7X.js} +1 -1
- package/dist/assets/form-actions-aM9_jSJC.js +1 -0
- package/dist/assets/index-6pHX0DZH.js +2 -0
- package/dist/assets/index-DN6KM7WD.css +1 -0
- package/dist/assets/loader-circle-Dd6jw700.js +1 -0
- package/dist/assets/logo-badge-2-iV1pkr.js +1 -0
- package/dist/assets/mcp-marketplace-page-C-d0RMfg.js +1 -0
- package/dist/assets/mcp-marketplace-page-Dg03SZX1.js +9 -0
- package/dist/assets/model-config-page-DOBqLZoQ.js +1 -0
- package/dist/assets/{navigation-link-qPPUiLt0.js → navigation-link-Ct6xtnVM.js} +1 -1
- package/dist/assets/plus-CsgeRId8.js +1 -0
- package/dist/assets/{popover-DHx55dbc.js → popover-C2oIpGBF.js} +1 -1
- package/dist/assets/provider-scoped-model-input-DDqCdnTU.js +1 -0
- package/dist/assets/{providers-config-page-BwHtHIPe.js → providers-config-page-BAVPJKpx.js} +1 -1
- package/dist/assets/react-CeMr9V52.js +8 -0
- package/dist/assets/{refresh-cw-C7bynrWX.js → refresh-cw-BZ8giusN.js} +1 -1
- package/dist/assets/remote-C-r0SHcz.js +1 -0
- package/dist/assets/rotate-cw-DVdRfMSO.js +1 -0
- package/dist/assets/{runtime-config-page-CbSrKeJt.js → runtime-config-page-D0244uxJ.js} +1 -1
- package/dist/assets/{save-CsRsFtHS.js → save-CSzFGRse.js} +1 -1
- package/dist/assets/{search-D0HtJIL-.js → search-BmSWsiG2.js} +1 -1
- package/dist/assets/{search-config-page-n1GElgij.js → search-config-page-CrL1pUzy.js} +1 -1
- package/dist/assets/{secrets-config-page-DbUc3Ggi.js → secrets-config-page-BlgsD0-L.js} +2 -2
- package/dist/assets/security-config-cDrdpMJW.js +1 -0
- package/dist/assets/{select-C1zfp9zM.js → select-CklWb6Rs.js} +1 -1
- package/dist/assets/{settings-2-Ba3cLSN2.js → settings-2-BSZf8327.js} +1 -1
- package/dist/assets/skeleton-DG9u1BmA.js +1 -0
- package/dist/assets/{tabs-DmKgMKzb.js → tabs-Cah5klko.js} +1 -1
- package/dist/assets/{tag-chip-2vwlVUwM.js → tag-chip-DcrirDgN.js} +1 -1
- package/dist/assets/{trash-2-CUpWjNHu.js → trash-2-BLQOULWD.js} +1 -1
- package/dist/assets/use-config-CuFIsUVG.js +1 -0
- package/dist/assets/use-confirm-dialog-CcySmkWp.js +1 -0
- package/dist/assets/{use-viewport-layout-DaKJ-kap.js → use-viewport-layout-DU29bUJS.js} +1 -1
- package/dist/assets/x-BVoeXny1.js +1 -0
- package/dist/index.html +28 -28
- package/package.json +9 -9
- package/src/features/chat/components/conversation/__tests__/chat-conversation-content.test.tsx +11 -0
- package/src/features/chat/components/conversation/chat-conversation-content.tsx +7 -1
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +50 -4
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +25 -1
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +3 -0
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +41 -0
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-slash-commands.test.tsx +28 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts +1 -1
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +0 -1
- package/src/features/chat/features/conversation/hooks/use-session-conversation-preference-actions.ts +10 -11
- package/src/features/chat/features/conversation/hooks/use-session-conversation-slash-commands.ts +5 -2
- package/src/features/chat/features/message/components/__tests__/chat-inline-panel-app-card.test.tsx +35 -0
- package/src/features/chat/features/message/components/chat-inline-file-preview.tsx +3 -1
- package/src/features/chat/features/message/components/chat-inline-panel-app-card.tsx +13 -5
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +13 -9
- package/src/features/chat/features/message/utils/__tests__/chat-message-show-content-tool-card.utils.test.ts +9 -0
- package/src/features/chat/features/message/utils/chat-inline-panel-app-card.utils.ts +4 -1
- package/src/features/chat/features/message/utils/chat-message-show-content-tool-card.utils.ts +29 -0
- package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
- package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +122 -1
- package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime-queue.test.tsx +31 -6
- package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime.test.tsx +107 -1
- package/src/features/chat/features/workspace/components/__tests__/workspace-file-content-preview.test.tsx +41 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +4 -0
- package/src/features/chat/features/workspace/components/workspace-file-content-preview.tsx +15 -2
- package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +11 -0
- package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +1 -0
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +11 -8
- package/src/features/chat/managers/__tests__/chat-ui.manager.test.ts +6 -0
- package/src/features/chat/managers/chat-thread.manager.ts +2 -0
- package/src/features/chat/managers/chat-ui.manager.ts +10 -4
- package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +4 -0
- package/src/features/chat/stores/chat-thread.store.ts +6 -1
- package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +32 -0
- package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +2 -0
- package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +20 -38
- package/src/shared/components/doc-browser/types/doc-browser.types.ts +5 -0
- package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +63 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +1 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +1 -0
- package/dist/assets/api-D5UCLVE_.js +0 -13
- package/dist/assets/app-presenter-provider-C9AcZKKs.js +0 -106
- package/dist/assets/appearance-settings-page-CiD9Ey8f.js +0 -1
- package/dist/assets/card-xVrS1b1T.js +0 -1
- package/dist/assets/chat-page-B0cC3jsB.js +0 -1
- package/dist/assets/config-split-page-xj0UtMow.js +0 -1
- package/dist/assets/confirm-dialog-e2YCUzt1.js +0 -5
- package/dist/assets/desktop-update-config-D5NIaimo.js +0 -1
- package/dist/assets/doc-browser-B2tNEKrJ.js +0 -1
- package/dist/assets/doc-browser-CZX6I6CU.js +0 -1
- package/dist/assets/doc-browser-context-CGz0LULR.js +0 -1
- package/dist/assets/form-actions-CnSzu3WD.js +0 -1
- package/dist/assets/index-QveCjxCj.css +0 -1
- package/dist/assets/index-bOqpao-w.js +0 -2
- package/dist/assets/loader-circle-DjwSRQHW.js +0 -1
- package/dist/assets/logo-badge-CISsltAo.js +0 -1
- package/dist/assets/mcp-marketplace-page-BZa7p7Qf.js +0 -1
- package/dist/assets/mcp-marketplace-page-CPcPzMUQ.js +0 -9
- package/dist/assets/model-config-page-D6ex3_NM.js +0 -1
- package/dist/assets/plus-C45awBb1.js +0 -1
- package/dist/assets/provider-scoped-model-input-1TJxAhx6.js +0 -1
- package/dist/assets/react-DerwD2EA.js +0 -8
- package/dist/assets/remote-B0nlynVp.js +0 -1
- package/dist/assets/rotate-cw-Bhx0XkQP.js +0 -1
- package/dist/assets/security-config-n2WHhHXV.js +0 -1
- package/dist/assets/skeleton-DL5npsVL.js +0 -1
- package/dist/assets/use-config-BvxDWV-M.js +0 -1
- package/dist/assets/use-confirm-dialog-CeUEE4p5.js +0 -1
- package/dist/assets/x-DGdYT7rH.js +0 -1
|
@@ -88,6 +88,9 @@ describe('ChatUiManager content display', () => {
|
|
|
88
88
|
type: 'panel_app',
|
|
89
89
|
payload: {
|
|
90
90
|
appId: 'reader',
|
|
91
|
+
params: {
|
|
92
|
+
file: { path: '/tmp/photo.png' },
|
|
93
|
+
},
|
|
91
94
|
},
|
|
92
95
|
},
|
|
93
96
|
title: 'Reader',
|
|
@@ -95,6 +98,9 @@ describe('ChatUiManager content display', () => {
|
|
|
95
98
|
|
|
96
99
|
expect(docBrowserManager.openTarget).toHaveBeenCalledWith({
|
|
97
100
|
dedupeKey: 'panel-app:encoded-reader',
|
|
101
|
+
contentParams: {
|
|
102
|
+
file: { path: '/tmp/photo.png' },
|
|
103
|
+
},
|
|
98
104
|
historyPolicy: 'managed',
|
|
99
105
|
kind: 'panel-app',
|
|
100
106
|
resourceUri: 'nextclaw://panel-app/encoded-reader',
|
|
@@ -347,6 +347,7 @@ export class ChatThreadManager {
|
|
|
347
347
|
previewViewer: nextViewer,
|
|
348
348
|
line: sourceTab.line ?? undefined,
|
|
349
349
|
column: sourceTab.column ?? undefined,
|
|
350
|
+
params: sourceTab.params ?? undefined,
|
|
350
351
|
rawText: sourceTab.rawText ?? undefined,
|
|
351
352
|
contentUrl: sourceTab.contentUrl ?? undefined,
|
|
352
353
|
mimeType: sourceTab.mimeType ?? undefined,
|
|
@@ -419,6 +420,7 @@ export class ChatThreadManager {
|
|
|
419
420
|
previewViewer: request.target.payload.viewer,
|
|
420
421
|
line: request.target.payload.line,
|
|
421
422
|
column: request.target.payload.column,
|
|
423
|
+
params: request.target.payload.params,
|
|
422
424
|
});
|
|
423
425
|
return;
|
|
424
426
|
}
|
|
@@ -96,21 +96,27 @@ export class ChatUiManager {
|
|
|
96
96
|
});
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
|
-
const { appId, path } = target.payload;
|
|
99
|
+
const { appId, params: contentParams, path } = target.payload;
|
|
100
100
|
if (path) {
|
|
101
101
|
this.docBrowserManager.open(createPanelAppResourceUri(appId, path), {
|
|
102
|
+
contentParams,
|
|
102
103
|
title,
|
|
103
104
|
});
|
|
104
105
|
return;
|
|
105
106
|
}
|
|
106
107
|
const entry = await this.resolvePanelAppEntry(appId);
|
|
107
108
|
if (entry) {
|
|
108
|
-
this.docBrowserManager.openTarget(
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
this.docBrowserManager.openTarget(
|
|
110
|
+
{
|
|
111
|
+
...createPanelAppRightPanelResourceTarget(entry),
|
|
112
|
+
contentParams,
|
|
113
|
+
},
|
|
114
|
+
{ title },
|
|
115
|
+
);
|
|
111
116
|
return;
|
|
112
117
|
}
|
|
113
118
|
this.docBrowserManager.open(createPanelAppResourceUri(appId), {
|
|
119
|
+
contentParams,
|
|
114
120
|
title,
|
|
115
121
|
});
|
|
116
122
|
};
|
|
@@ -60,6 +60,7 @@ describe('chat thread workspace panel persistence', () => {
|
|
|
60
60
|
label: 'README.md',
|
|
61
61
|
viewMode: 'preview',
|
|
62
62
|
previewViewer: 'rendered',
|
|
63
|
+
params: { chart: { series: [3, 5, 8] } },
|
|
63
64
|
rawText: '# Hello',
|
|
64
65
|
fullLines: [],
|
|
65
66
|
},
|
|
@@ -98,6 +99,9 @@ describe('chat thread workspace panel persistence', () => {
|
|
|
98
99
|
expect(persisted.state.snapshot.isSending).toBeUndefined();
|
|
99
100
|
expect(persisted.state.snapshot.workspaceFileTabs[0].rawText).toBe('# Hello');
|
|
100
101
|
expect(persisted.state.snapshot.workspaceFileTabs[0].previewViewer).toBe('rendered');
|
|
102
|
+
expect(persisted.state.snapshot.workspaceFileTabs[0].params).toEqual({
|
|
103
|
+
chart: { series: [3, 5, 8] },
|
|
104
|
+
});
|
|
101
105
|
expect(persisted.state.snapshot.workspaceFileTabs[0].fullLines).toBeUndefined();
|
|
102
106
|
});
|
|
103
107
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { create } from 'zustand';
|
|
2
2
|
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
3
3
|
import type { NcpMessage } from '@nextclaw/ncp';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ChatContentParams,
|
|
6
|
+
ChatFileOperationLineViewModel,
|
|
7
|
+
ChatFilePreviewViewer,
|
|
8
|
+
} from '@nextclaw/agent-chat-ui';
|
|
5
9
|
import type {
|
|
6
10
|
SessionContextWindowView,
|
|
7
11
|
SessionTypeIconView
|
|
@@ -38,6 +42,7 @@ export type ChatWorkspaceFileTab = {
|
|
|
38
42
|
previewViewer?: ChatFilePreviewViewer | null;
|
|
39
43
|
line?: number | null;
|
|
40
44
|
column?: number | null;
|
|
45
|
+
params?: ChatContentParams | null;
|
|
41
46
|
rawText?: string | null;
|
|
42
47
|
/** Attachment/binary content URL for workspace-native media preview. */
|
|
43
48
|
contentUrl?: string | null;
|
|
@@ -269,6 +269,9 @@ describe('DocBrowserProvider panel app resources', () => {
|
|
|
269
269
|
|
|
270
270
|
act(() => {
|
|
271
271
|
result.current.openTarget({
|
|
272
|
+
contentParams: {
|
|
273
|
+
file: { path: '/tmp/photo.png' },
|
|
274
|
+
},
|
|
272
275
|
dedupeKey: 'panel-app:demo',
|
|
273
276
|
dockIcon: { type: 'url', url: '/api/panel-apps/demo/assets/icon.png' },
|
|
274
277
|
historyPolicy: 'managed',
|
|
@@ -281,6 +284,9 @@ describe('DocBrowserProvider panel app resources', () => {
|
|
|
281
284
|
|
|
282
285
|
expect(result.current.currentTab).toMatchObject({
|
|
283
286
|
currentUrl: '/api/panel-apps/demo/content',
|
|
287
|
+
contentParams: {
|
|
288
|
+
file: { path: '/tmp/photo.png' },
|
|
289
|
+
},
|
|
284
290
|
dedupeKey: 'panel-app:demo',
|
|
285
291
|
dockIcon: { type: 'url', url: '/api/panel-apps/demo/assets/icon.png' },
|
|
286
292
|
kind: 'panel-app',
|
|
@@ -288,6 +294,32 @@ describe('DocBrowserProvider panel app resources', () => {
|
|
|
288
294
|
title: 'Demo Panel App',
|
|
289
295
|
});
|
|
290
296
|
});
|
|
297
|
+
|
|
298
|
+
it('reloads a reused Panel App tab when its params change', () => {
|
|
299
|
+
const { result } = renderHook(() => useDocBrowser(), { wrapper });
|
|
300
|
+
const openPanelApp = (path: string) => {
|
|
301
|
+
result.current.openTarget({
|
|
302
|
+
contentParams: { file: { path } },
|
|
303
|
+
dedupeKey: 'panel-app:demo',
|
|
304
|
+
historyPolicy: 'managed',
|
|
305
|
+
kind: 'panel-app',
|
|
306
|
+
resourceUri: 'nextclaw://panel-app/demo',
|
|
307
|
+
title: 'Demo Panel App',
|
|
308
|
+
url: '/api/panel-apps/demo/content',
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
act(() => openPanelApp('/tmp/first.png'));
|
|
313
|
+
const firstNavVersion = result.current.currentTab?.navVersion;
|
|
314
|
+
act(() => openPanelApp('/tmp/second.png'));
|
|
315
|
+
|
|
316
|
+
expect(result.current.currentTab).toMatchObject({
|
|
317
|
+
contentParams: {
|
|
318
|
+
file: { path: '/tmp/second.png' },
|
|
319
|
+
},
|
|
320
|
+
navVersion: (firstNavVersion ?? 0) + 1,
|
|
321
|
+
});
|
|
322
|
+
});
|
|
291
323
|
});
|
|
292
324
|
|
|
293
325
|
describe('DocBrowserProvider managed history', () => {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
|
|
11
11
|
import { NavigationLink } from '@/shared/components/actions/navigation-link';
|
|
12
12
|
import { t } from '@/shared/lib/i18n';
|
|
13
|
+
import { createUiContentParamsWindowName } from '@nextclaw/shared';
|
|
13
14
|
|
|
14
15
|
type DocBrowserAddressToolbarProps = {
|
|
15
16
|
isVisible: boolean;
|
|
@@ -86,6 +87,7 @@ export function DocBrowserFrameContent({
|
|
|
86
87
|
ref={iframeRef}
|
|
87
88
|
key={iframeInstanceId}
|
|
88
89
|
src={currentUrl}
|
|
90
|
+
name={createUiContentParamsWindowName(currentTab?.contentParams)}
|
|
89
91
|
className="absolute inset-0 w-full h-full border-0"
|
|
90
92
|
title={currentTab?.title || 'NextClaw Docs'}
|
|
91
93
|
sandbox={iframeSandbox}
|
|
@@ -8,10 +8,12 @@ import type {
|
|
|
8
8
|
DocBrowserTab,
|
|
9
9
|
} from '@/shared/components/doc-browser/types/doc-browser.types';
|
|
10
10
|
import {
|
|
11
|
+
appendManualNavigation,
|
|
11
12
|
createDocBrowserActiveHistoryEntry,
|
|
12
13
|
createDefaultDocBrowserState,
|
|
13
14
|
createDocBrowserTab,
|
|
14
15
|
normalizeDocBrowserDockedWidth,
|
|
16
|
+
updateTabForOpen,
|
|
15
17
|
} from '@/shared/components/doc-browser/utils/doc-browser-state.utils';
|
|
16
18
|
import {
|
|
17
19
|
DOC_BROWSER_HOME_TAB_KIND,
|
|
@@ -45,14 +47,6 @@ function updateActiveTab(state: DocBrowserState, updater: (tab: DocBrowserTab) =
|
|
|
45
47
|
return updateTab(state, state.activeTabId, updater);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
function appendManualNavigation(tab: DocBrowserTab, url: string): Pick<DocBrowserTab, 'history' | 'historyIndex'> {
|
|
49
|
-
const history = [...tab.history.slice(0, tab.historyIndex + 1), url];
|
|
50
|
-
return {
|
|
51
|
-
history,
|
|
52
|
-
historyIndex: history.length - 1,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
50
|
function areActiveHistoryEntriesEquivalent(
|
|
57
51
|
routeResolver: DocBrowserRouteResolver,
|
|
58
52
|
current: DocBrowserActiveHistoryEntry,
|
|
@@ -140,34 +134,6 @@ function restoreActiveHistoryEntry(
|
|
|
140
134
|
);
|
|
141
135
|
}
|
|
142
136
|
|
|
143
|
-
function updateTabForOpen(
|
|
144
|
-
routeResolver: DocBrowserRouteResolver,
|
|
145
|
-
tab: DocBrowserTab,
|
|
146
|
-
target: DocBrowserRouteTarget,
|
|
147
|
-
options?: DocBrowserOpenOptions,
|
|
148
|
-
dedupeKey?: string,
|
|
149
|
-
): DocBrowserTab {
|
|
150
|
-
const baseTab = {
|
|
151
|
-
...tab,
|
|
152
|
-
title: options?.title || target.title || tab.title,
|
|
153
|
-
kind: target.kind,
|
|
154
|
-
resourceUri: target.resourceUri ?? target.url,
|
|
155
|
-
dockIcon: options?.dockIcon ?? target.dockIcon,
|
|
156
|
-
dedupeKey,
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
if (routeResolver.areUrlsEquivalent(tab.currentUrl, target.url, tab.kind, target.kind)) {
|
|
160
|
-
return baseTab;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
...baseTab,
|
|
165
|
-
currentUrl: target.url,
|
|
166
|
-
...appendManualNavigation(tab, target.url),
|
|
167
|
-
navVersion: tab.navVersion + 1,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
137
|
function isClosedDefaultHomeState(state: DocBrowserState, activeTab?: DocBrowserTab): boolean {
|
|
172
138
|
return !state.isOpen
|
|
173
139
|
&& state.tabs.length === 1
|
|
@@ -213,7 +179,15 @@ function openResolvedDocBrowserState(
|
|
|
213
179
|
}
|
|
214
180
|
|
|
215
181
|
if (shouldForceNewTab || dedupeKey || !activeTab || activeTab.kind !== target.kind) {
|
|
216
|
-
const newTab = createDocBrowserTab(
|
|
182
|
+
const newTab = createDocBrowserTab(
|
|
183
|
+
target.url,
|
|
184
|
+
target.kind,
|
|
185
|
+
title ?? target.title,
|
|
186
|
+
dedupeKey,
|
|
187
|
+
target.resourceUri ?? target.url,
|
|
188
|
+
options?.dockIcon ?? target.dockIcon,
|
|
189
|
+
target.contentParams,
|
|
190
|
+
);
|
|
217
191
|
if (isClosedDefaultHomeState(prev, activeTab)) {
|
|
218
192
|
const nextState = {
|
|
219
193
|
...prev,
|
|
@@ -257,7 +231,15 @@ function openDocBrowserState(
|
|
|
257
231
|
kind: options?.kind,
|
|
258
232
|
url,
|
|
259
233
|
});
|
|
260
|
-
return openResolvedDocBrowserState(
|
|
234
|
+
return openResolvedDocBrowserState(
|
|
235
|
+
routeResolver,
|
|
236
|
+
prev,
|
|
237
|
+
{
|
|
238
|
+
...target,
|
|
239
|
+
contentParams: options?.contentParams,
|
|
240
|
+
},
|
|
241
|
+
options,
|
|
242
|
+
);
|
|
261
243
|
}
|
|
262
244
|
|
|
263
245
|
export class DocBrowserManager {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { UiContentParams } from '@nextclaw/shared';
|
|
2
|
+
|
|
1
3
|
export type DocBrowserMode = 'floating' | 'docked';
|
|
2
4
|
export type DocBrowserTabKind = 'docs' | 'content' | (string & {});
|
|
3
5
|
|
|
@@ -7,6 +9,7 @@ export type DocBrowserTab = {
|
|
|
7
9
|
title: string;
|
|
8
10
|
currentUrl: string;
|
|
9
11
|
resourceUri?: string;
|
|
12
|
+
contentParams?: UiContentParams;
|
|
10
13
|
dockIcon?: DocBrowserDockIcon;
|
|
11
14
|
dedupeKey?: string;
|
|
12
15
|
history: string[];
|
|
@@ -21,6 +24,7 @@ export type DocBrowserRouteTarget = {
|
|
|
21
24
|
historyPolicy: 'managed' | 'none';
|
|
22
25
|
kind: DocBrowserTabKind;
|
|
23
26
|
resourceUri?: string;
|
|
27
|
+
contentParams?: UiContentParams;
|
|
24
28
|
title: string;
|
|
25
29
|
url: string;
|
|
26
30
|
};
|
|
@@ -71,6 +75,7 @@ export type DocBrowserOpenOptions = {
|
|
|
71
75
|
newTab?: boolean;
|
|
72
76
|
title?: string;
|
|
73
77
|
kind?: DocBrowserTabKind;
|
|
78
|
+
contentParams?: UiContentParams;
|
|
74
79
|
};
|
|
75
80
|
|
|
76
81
|
export type DocBrowserState = {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DocBrowserActiveHistoryEntry,
|
|
3
3
|
DocBrowserDockIcon,
|
|
4
|
+
DocBrowserOpenOptions,
|
|
5
|
+
DocBrowserRouteResolver,
|
|
6
|
+
DocBrowserRouteTarget,
|
|
4
7
|
DocBrowserState,
|
|
5
8
|
DocBrowserTab,
|
|
6
9
|
DocBrowserTabKind,
|
|
@@ -11,6 +14,10 @@ import {
|
|
|
11
14
|
inferTabTitle,
|
|
12
15
|
} from './doc-browser-url.utils';
|
|
13
16
|
import { t } from '@/shared/lib/i18n';
|
|
17
|
+
import {
|
|
18
|
+
createUiContentParamsWindowName,
|
|
19
|
+
type UiContentParams,
|
|
20
|
+
} from '@nextclaw/shared';
|
|
14
21
|
|
|
15
22
|
export const DOC_BROWSER_DOCKED_DEFAULT_WIDTH = 420;
|
|
16
23
|
export const DOC_BROWSER_DOCKED_MIN_WIDTH = 320;
|
|
@@ -36,6 +43,7 @@ export function createDocBrowserTab(
|
|
|
36
43
|
dedupeKey?: string,
|
|
37
44
|
resourceUri?: string,
|
|
38
45
|
dockIcon?: DocBrowserDockIcon,
|
|
46
|
+
contentParams?: UiContentParams,
|
|
39
47
|
): DocBrowserTab {
|
|
40
48
|
const tabTitle = title?.trim() || inferTabTitle(url, kind, kind === 'docs' ? t('docBrowserHelp') : 'Detail');
|
|
41
49
|
const normalizedResourceUri = resourceUri?.trim();
|
|
@@ -46,6 +54,7 @@ export function createDocBrowserTab(
|
|
|
46
54
|
title: tabTitle,
|
|
47
55
|
currentUrl: url,
|
|
48
56
|
resourceUri: normalizedResourceUri ? normalizedResourceUri : undefined,
|
|
57
|
+
contentParams,
|
|
49
58
|
dockIcon,
|
|
50
59
|
dedupeKey,
|
|
51
60
|
history: [url],
|
|
@@ -54,6 +63,60 @@ export function createDocBrowserTab(
|
|
|
54
63
|
};
|
|
55
64
|
}
|
|
56
65
|
|
|
66
|
+
export function appendManualNavigation(
|
|
67
|
+
tab: DocBrowserTab,
|
|
68
|
+
url: string,
|
|
69
|
+
): Pick<DocBrowserTab, 'history' | 'historyIndex'> {
|
|
70
|
+
const history = [...tab.history.slice(0, tab.historyIndex + 1), url];
|
|
71
|
+
return {
|
|
72
|
+
history,
|
|
73
|
+
historyIndex: history.length - 1,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function updateTabForOpen(
|
|
78
|
+
routeResolver: DocBrowserRouteResolver,
|
|
79
|
+
tab: DocBrowserTab,
|
|
80
|
+
target: DocBrowserRouteTarget,
|
|
81
|
+
options?: DocBrowserOpenOptions,
|
|
82
|
+
dedupeKey?: string,
|
|
83
|
+
): DocBrowserTab {
|
|
84
|
+
const baseTab = {
|
|
85
|
+
...tab,
|
|
86
|
+
title: options?.title || target.title || tab.title,
|
|
87
|
+
kind: target.kind,
|
|
88
|
+
resourceUri: target.resourceUri ?? target.url,
|
|
89
|
+
dockIcon: options?.dockIcon ?? target.dockIcon,
|
|
90
|
+
dedupeKey,
|
|
91
|
+
contentParams: target.contentParams,
|
|
92
|
+
};
|
|
93
|
+
const hasSameUrl = routeResolver.areUrlsEquivalent(
|
|
94
|
+
tab.currentUrl,
|
|
95
|
+
target.url,
|
|
96
|
+
tab.kind,
|
|
97
|
+
target.kind,
|
|
98
|
+
);
|
|
99
|
+
if (
|
|
100
|
+
hasSameUrl &&
|
|
101
|
+
createUiContentParamsWindowName(tab.contentParams) ===
|
|
102
|
+
createUiContentParamsWindowName(target.contentParams)
|
|
103
|
+
) {
|
|
104
|
+
return baseTab;
|
|
105
|
+
}
|
|
106
|
+
if (hasSameUrl) {
|
|
107
|
+
return {
|
|
108
|
+
...baseTab,
|
|
109
|
+
navVersion: tab.navVersion + 1,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
...baseTab,
|
|
114
|
+
currentUrl: target.url,
|
|
115
|
+
...appendManualNavigation(tab, target.url),
|
|
116
|
+
navVersion: tab.navVersion + 1,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
57
120
|
export function createDocBrowserActiveHistoryEntry(tab: DocBrowserTab): DocBrowserActiveHistoryEntry {
|
|
58
121
|
return {
|
|
59
122
|
kind: tab.kind,
|
|
@@ -388,6 +388,7 @@
|
|
|
388
388
|
"chatMessageCopy": "Copy",
|
|
389
389
|
"chatMessageCopied": "Copied",
|
|
390
390
|
"chatMermaidDiagram": "Diagram",
|
|
391
|
+
"chatMermaidExpand": "Expand diagram",
|
|
391
392
|
"chatMermaidLoading": "Rendering diagram…",
|
|
392
393
|
"chatMermaidRenderError": "Diagram could not be rendered; showing source instead",
|
|
393
394
|
"chatSidebarNewTask": "New Task",
|