diff --git a/blocksuite/blocks/src/root-block/widgets/ai-panel/ai-panel.ts b/blocksuite/blocks/src/root-block/widgets/ai-panel/ai-panel.ts index f42a63ba46..2fbd034510 100644 --- a/blocksuite/blocks/src/root-block/widgets/ai-panel/ai-panel.ts +++ b/blocksuite/blocks/src/root-block/widgets/ai-panel/ai-panel.ts @@ -85,10 +85,6 @@ export class AffineAIPanelWidget extends WidgetComponent { private _answer: string | null = null; - private readonly _cancelCallback = () => { - this.focus(); - }; - private readonly _clearDiscardModal = () => { if (this._discardModalAbort) { this._discardModalAbort.abort(); @@ -97,25 +93,7 @@ export class AffineAIPanelWidget extends WidgetComponent { }; private readonly _clickOutside = () => { - switch (this.state) { - case 'hidden': - return; - case 'error': - case 'finished': - if (!this._answer) { - this.hide(); - } else { - this.discard(); - } - break; - default: - this.discard(); - } - }; - - private readonly _discardCallback = () => { - this.hide(); - this.config?.discardCallback?.(); + this._discardWithConfirmation(); }; private _discardModalAbort: AbortController | null = null; @@ -171,27 +149,27 @@ export class AffineAIPanelWidget extends WidgetComponent { ctx: unknown = null; - discard = () => { - if ((this.state === 'finished' || this.state === 'error') && !this.answer) { - this._discardCallback(); + private readonly _discardWithConfirmation = () => { + if (this.state === 'hidden') { return; } - if (this.state === 'input') { + if (this.state === 'input' || !this.answer) { this.hide(); return; } this.showDiscardModal() .then(discard => { - if (discard) { - this._discardCallback(); - } else { - this._cancelCallback(); - } - this.restoreSelection(); + discard && this.discard(); }) .catch(console.error); }; + discard = () => { + this.hide(); + this.restoreSelection(); + this.config?.discardCallback?.(); + }; + /** * You can evaluate this method multiple times to regenerate the answer. */ @@ -472,7 +450,7 @@ export class AffineAIPanelWidget extends WidgetComponent { 'input', () => html` { finish('success'); const aiPanel = getAIPanelWidget(this.host); - aiPanel.discard(); + aiPanel.hide(); extractSelectedContent(this.host) .then(context => { AIProvider.slots.requestSendWithChat.emit({ diff --git a/packages/frontend/core/src/blocksuite/presets/ai/entries/edgeless/index.ts b/packages/frontend/core/src/blocksuite/presets/ai/entries/edgeless/index.ts index 9007e53c60..aff9c2287c 100644 --- a/packages/frontend/core/src/blocksuite/presets/ai/entries/edgeless/index.ts +++ b/packages/frontend/core/src/blocksuite/presets/ai/entries/edgeless/index.ts @@ -47,7 +47,7 @@ export function setupEdgelessElementToolbarAIEntry( if (aiPanel.config) { aiPanel.config.generateAnswer = ({ finish, input }) => { finish('success'); - aiPanel.discard(); + aiPanel.hide(); extractSelectedContent(edgeless.host) .then(context => { AIProvider.slots.requestSendWithChat.emit({ diff --git a/tests/affine-cloud-copilot/e2e/copilot.spec.ts b/tests/affine-cloud-copilot/e2e/copilot.spec.ts index 44b800ac98..255836b93c 100644 --- a/tests/affine-cloud-copilot/e2e/copilot.spec.ts +++ b/tests/affine-cloud-copilot/e2e/copilot.spec.ts @@ -436,7 +436,7 @@ test.describe('chat panel', () => { expect(editorContent).toBe(content); }); - test('can be retry or discard chat in page mode', async ({ page }) => { + test('can regenerate chat in page mode', async ({ page }) => { await page.reload(); await clickSideBarAllPageButton(page); await page.waitForTimeout(200); @@ -467,13 +467,53 @@ test.describe('chat panel', () => { ).innerText() ).not.toBe(content); } + }); - // discard + test('can discard chat in page mode', async ({ page }) => { + await page.reload(); + await clickSideBarAllPageButton(page); + await page.waitForTimeout(200); + await createLocalWorkspace({ name: 'test' }, page); + await clickNewPageButton(page); + await focusToEditor(page); + await page.keyboard.type('/'); + await page.getByTestId('sub-menu-0').getByText('Ask AI').click(); + const input = await page.waitForSelector('ai-panel-input textarea'); + await input.fill('hello'); + await input.press('Enter'); + + // discard without confirm modal { const resp = await page.waitForSelector( 'ai-panel-answer .response-list-container:last-child' ); await (await resp.waitForSelector('.ai-item-discard')).click(); + const editorContent = await getEditorContent(page); + expect(editorContent).toBe(''); + } + }); + + test('can discard chat with confirm modal in edgeless mode', async ({ + page, + }) => { + await page.reload(); + await clickSideBarAllPageButton(page); + await page.waitForTimeout(200); + await createLocalWorkspace({ name: 'test' }, page); + await clickNewPageButton(page); + await focusToEditor(page); + await page.keyboard.type('/'); + await page.getByTestId('sub-menu-0').getByText('Ask AI').click(); + const input = await page.waitForSelector('ai-panel-input textarea'); + await input.fill('hello'); + await input.press('Enter'); + + // discard with confirm modal + { + await page.waitForSelector( + 'ai-panel-answer .response-list-container:last-child' + ); + await page.mouse.click(100, 100); await page.getByTestId('confirm-modal-confirm').click(); const editorContent = await getEditorContent(page); expect(editorContent).toBe('');