diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts index 2b06f654c..b7a3c3c7c 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts @@ -1,5 +1,6 @@ import './chat-panel-messages'; +import type { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; import type { ContextEmbedStatus, CopilotSessionType } from '@affine/graphql'; import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit'; @@ -241,6 +242,9 @@ export class ChatPanel extends SignalWatcher( @property({ attribute: false }) accessor affineFeatureFlagService!: FeatureFlagService; + @property({ attribute: false }) + accessor affineWorkspaceDialogService!: WorkspaceDialogService; + @state() accessor isLoading = false; @@ -481,6 +485,7 @@ export class ChatPanel extends SignalWatcher( .playgroundConfig=${this.playgroundConfig} .docDisplayConfig=${this.docDisplayConfig} .searchMenuConfig=${this.searchMenuConfig} + .affineWorkspaceDialogService=${this.affineWorkspaceDialogService} .trackOptions=${{ where: 'chat-panel', control: 'chat-send', diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts index 5b5d8bfe3..7e1cdfb33 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts @@ -1,5 +1,6 @@ import './ai-chat-composer-tip'; +import type { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import type { ContextEmbedStatus, ContextWorkspaceEmbeddingStatus, @@ -104,11 +105,11 @@ export class AIChatComposer extends SignalWatcher( @property({ attribute: false }) accessor panelWidth: Signal = signal(undefined); - @state() - accessor chips: ChatChip[] = []; + @property({ attribute: false }) + accessor affineWorkspaceDialogService!: WorkspaceDialogService; @state() - accessor embeddingProgressText = 'Loading embedding status...'; + accessor chips: ChatChip[] = []; @state() accessor embeddingCompleted = false; @@ -160,7 +161,8 @@ export class AIChatComposer extends SignalWatcher( this.embeddingCompleted ? null : html``, ].filter(Boolean)} .loop=${false} @@ -348,24 +350,20 @@ export class AIChatComposer extends SignalWatcher( this.host.std.workspace.id, (status: ContextWorkspaceEmbeddingStatus) => { if (!status) { - this.embeddingProgressText = 'Loading embedding status...'; this.embeddingCompleted = false; return; } const completed = status.embedded === status.total; this.embeddingCompleted = completed; if (completed) { - this.embeddingProgressText = - 'Embedding finished. You are getting the best results!'; + this.embeddingCompleted = true; } else { - this.embeddingProgressText = - 'File not embedded yet. Results will improve after embedding.'; + this.embeddingCompleted = false; } }, signal ); } catch { - this.embeddingProgressText = 'Failed to load embedding status...'; this.embeddingCompleted = false; } }; diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/embedding-status-tooltip.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/embedding-status-tooltip.ts index d57ebccda..5a68c5aeb 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/embedding-status-tooltip.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/embedding-status-tooltip.ts @@ -1,7 +1,9 @@ +import type { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { SignalWatcher } from '@blocksuite/affine/global/lit'; import { unsafeCSSVar } from '@blocksuite/affine/shared/theme'; import { css, html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; +import { debounce } from 'lodash-es'; export class AIChatEmbeddingStatusTooltip extends SignalWatcher(LitElement) { static override styles = css` @@ -34,7 +36,21 @@ export class AIChatEmbeddingStatusTooltip extends SignalWatcher(LitElement) { `; @property({ attribute: false }) - accessor progressText = 'Loading embedding status...'; + accessor affineWorkspaceDialogService!: WorkspaceDialogService; + + override connectedCallback() { + super.connectedCallback(); + } + + private readonly _handleCheckStatusClick = debounce( + () => { + this.affineWorkspaceDialogService.open('setting', { + activeTab: 'workspace:embedding', + }); + }, + 1000, + { leading: true } + ); override render() { return html` @@ -48,11 +64,9 @@ export class AIChatEmbeddingStatusTooltip extends SignalWatcher(LitElement) {
Check status - ${this.progressText}
`; diff --git a/packages/frontend/core/src/blocksuite/ai/peek-view/chat-block-peek-view.ts b/packages/frontend/core/src/blocksuite/ai/peek-view/chat-block-peek-view.ts index 177f7773c..735049bb5 100644 --- a/packages/frontend/core/src/blocksuite/ai/peek-view/chat-block-peek-view.ts +++ b/packages/frontend/core/src/blocksuite/ai/peek-view/chat-block-peek-view.ts @@ -1,3 +1,4 @@ +import type { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; import type { ContextEmbedStatus } from '@affine/graphql'; import { @@ -593,6 +594,7 @@ export class AIChatBlockPeekView extends LitElement { .networkSearchConfig=${networkSearchConfig} .docDisplayConfig=${this.docDisplayConfig} .searchMenuConfig=${this.searchMenuConfig} + .affineWorkspaceDialogService=${this.affineWorkspaceDialogService} .onChatSuccess=${this._onChatSuccess} .trackOptions=${{ where: 'ai-chat-block', @@ -628,6 +630,9 @@ export class AIChatBlockPeekView extends LitElement { @property({ attribute: false }) accessor affineFeatureFlagService!: FeatureFlagService; + @property({ attribute: false }) + accessor affineWorkspaceDialogService!: WorkspaceDialogService; + @state() accessor _historyMessages: ChatMessage[] = []; @@ -657,7 +662,8 @@ export const AIChatBlockPeekViewTemplate = ( searchMenuConfig: SearchMenuConfig, networkSearchConfig: AINetworkSearchConfig, reasoningConfig: AIReasoningConfig, - affineFeatureFlagService: FeatureFlagService + affineFeatureFlagService: FeatureFlagService, + affineWorkspaceDialogService: WorkspaceDialogService ) => { return html``; }; diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx index ed599c1c5..13301d335 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx @@ -1,6 +1,7 @@ import { ChatPanel } from '@affine/core/blocksuite/ai'; import type { AffineEditorContainer } from '@affine/core/blocksuite/block-suite-editor'; import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { FeatureFlagService } from '@affine/core/modules/feature-flag'; import { WorkbenchService } from '@affine/core/modules/workbench'; import { ViewExtensionManagerIdentifier } from '@blocksuite/affine/ext-loader'; @@ -80,6 +81,9 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( .get('preview-page'); chatPanelRef.current.affineFeatureFlagService = framework.get(FeatureFlagService); + chatPanelRef.current.affineWorkspaceDialogService = framework.get( + WorkspaceDialogService + ); containerRef.current?.append(chatPanelRef.current); } else { diff --git a/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx b/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx index 209ac972d..2dba510b7 100644 --- a/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx +++ b/packages/frontend/core/src/modules/peek-view/view/ai-chat-block-peek-view/index.tsx @@ -2,6 +2,7 @@ import { toReactNode } from '@affine/component'; import { AIChatBlockPeekViewTemplate } from '@affine/core/blocksuite/ai'; import type { AIChatBlockModel } from '@affine/core/blocksuite/ai/blocks/ai-chat-block/model/ai-chat-model'; import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { FeatureFlagService } from '@affine/core/modules/feature-flag'; import type { EditorHost } from '@blocksuite/affine/std'; import { useFramework } from '@toeverything/infra'; @@ -25,6 +26,7 @@ export const AIChatBlockPeekView = ({ const framework = useFramework(); const affineFeatureFlagService = framework.get(FeatureFlagService); + const affineWorkspaceDialogService = framework.get(WorkspaceDialogService); return useMemo(() => { const template = AIChatBlockPeekViewTemplate( @@ -34,7 +36,8 @@ export const AIChatBlockPeekView = ({ searchMenuConfig, networkSearchConfig, reasoningConfig, - affineFeatureFlagService + affineFeatureFlagService, + affineWorkspaceDialogService ); return toReactNode(template); }, [ @@ -45,5 +48,6 @@ export const AIChatBlockPeekView = ({ networkSearchConfig, reasoningConfig, affineFeatureFlagService, + affineWorkspaceDialogService, ]); }; diff --git a/tests/affine-cloud-copilot/e2e/basic/chat.spec.ts b/tests/affine-cloud-copilot/e2e/basic/chat.spec.ts index c7260398f..78924b9b2 100644 --- a/tests/affine-cloud-copilot/e2e/basic/chat.spec.ts +++ b/tests/affine-cloud-copilot/e2e/basic/chat.spec.ts @@ -17,7 +17,7 @@ test.describe('AIBasic/Chat', () => { await expect(page.getByTestId('ai-onboarding')).toBeVisible(); }); - test('should display embedding status tooltip', async ({ + test('should open embedding settings when clicking check status button', async ({ loggedInPage: page, utils, }) => { @@ -32,12 +32,8 @@ test.describe('AIBasic/Chat', () => { ); await expect(check).toBeVisible({ timeout: 50 * 1000 }); - await check.hover(); - const tooltip = await page.getByTestId('ai-chat-embedding-status-tooltip'); - await expect(tooltip).toBeVisible(); - await expect(tooltip).toHaveText( - /Results will improve after embedding|Embedding finished/ - ); + await check.click(); + await expect(page.getByTestId('workspace-setting:embedding')).toBeVisible(); }); test(`should send message and receive AI response: