fix(core): no pop-ups if user click discard menu item (#10317)

Fix issue [BS-2628](https://linear.app/affine-design/issue/BS-2628).
This commit is contained in:
akumatus
2025-02-20 13:29:28 +00:00
parent 007bbabce4
commit 126677d7ad
4 changed files with 56 additions and 38 deletions
@@ -85,10 +85,6 @@ export class AffineAIPanelWidget extends WidgetComponent {
private _answer: string | null = null; private _answer: string | null = null;
private readonly _cancelCallback = () => {
this.focus();
};
private readonly _clearDiscardModal = () => { private readonly _clearDiscardModal = () => {
if (this._discardModalAbort) { if (this._discardModalAbort) {
this._discardModalAbort.abort(); this._discardModalAbort.abort();
@@ -97,25 +93,7 @@ export class AffineAIPanelWidget extends WidgetComponent {
}; };
private readonly _clickOutside = () => { private readonly _clickOutside = () => {
switch (this.state) { this._discardWithConfirmation();
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?.();
}; };
private _discardModalAbort: AbortController | null = null; private _discardModalAbort: AbortController | null = null;
@@ -171,27 +149,27 @@ export class AffineAIPanelWidget extends WidgetComponent {
ctx: unknown = null; ctx: unknown = null;
discard = () => { private readonly _discardWithConfirmation = () => {
if ((this.state === 'finished' || this.state === 'error') && !this.answer) { if (this.state === 'hidden') {
this._discardCallback();
return; return;
} }
if (this.state === 'input') { if (this.state === 'input' || !this.answer) {
this.hide(); this.hide();
return; return;
} }
this.showDiscardModal() this.showDiscardModal()
.then(discard => { .then(discard => {
if (discard) { discard && this.discard();
this._discardCallback();
} else {
this._cancelCallback();
}
this.restoreSelection();
}) })
.catch(console.error); .catch(console.error);
}; };
discard = () => {
this.hide();
this.restoreSelection();
this.config?.discardCallback?.();
};
/** /**
* You can evaluate this method multiple times to regenerate the answer. * You can evaluate this method multiple times to regenerate the answer.
*/ */
@@ -472,7 +450,7 @@ export class AffineAIPanelWidget extends WidgetComponent {
'input', 'input',
() => () =>
html`<ai-panel-input html`<ai-panel-input
.onBlur=${this.discard} .onBlur=${this._discardWithConfirmation}
.onFinish=${this._inputFinish} .onFinish=${this._inputFinish}
.onInput=${this.onInput} .onInput=${this.onInput}
.networkSearchConfig=${config.networkSearchConfig} .networkSearchConfig=${config.networkSearchConfig}
@@ -74,7 +74,7 @@ export class AskAIToolbarButton extends WithDisposable(LitElement) {
({ finish, input }) => { ({ finish, input }) => {
finish('success'); finish('success');
const aiPanel = getAIPanelWidget(this.host); const aiPanel = getAIPanelWidget(this.host);
aiPanel.discard(); aiPanel.hide();
extractSelectedContent(this.host) extractSelectedContent(this.host)
.then(context => { .then(context => {
AIProvider.slots.requestSendWithChat.emit({ AIProvider.slots.requestSendWithChat.emit({
@@ -47,7 +47,7 @@ export function setupEdgelessElementToolbarAIEntry(
if (aiPanel.config) { if (aiPanel.config) {
aiPanel.config.generateAnswer = ({ finish, input }) => { aiPanel.config.generateAnswer = ({ finish, input }) => {
finish('success'); finish('success');
aiPanel.discard(); aiPanel.hide();
extractSelectedContent(edgeless.host) extractSelectedContent(edgeless.host)
.then(context => { .then(context => {
AIProvider.slots.requestSendWithChat.emit({ AIProvider.slots.requestSendWithChat.emit({
+42 -2
View File
@@ -436,7 +436,7 @@ test.describe('chat panel', () => {
expect(editorContent).toBe(content); 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 page.reload();
await clickSideBarAllPageButton(page); await clickSideBarAllPageButton(page);
await page.waitForTimeout(200); await page.waitForTimeout(200);
@@ -467,13 +467,53 @@ test.describe('chat panel', () => {
).innerText() ).innerText()
).not.toBe(content); ).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( const resp = await page.waitForSelector(
'ai-panel-answer .response-list-container:last-child' 'ai-panel-answer .response-list-container:last-child'
); );
await (await resp.waitForSelector('.ai-item-discard')).click(); 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(); await page.getByTestId('confirm-modal-confirm').click();
const editorContent = await getEditorContent(page); const editorContent = await getEditorContent(page);
expect(editorContent).toBe(''); expect(editorContent).toBe('');