mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-16 13:57:02 +08:00
feat(core): show stop modal if clickoutside during generating (#12227)
### TL;DR feat: show stop model if click-outside during ai generating >CLOSE AI-89 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a confirmation dialog when attempting to stop AI content generation by clicking outside the panel, ensuring users can confirm or cancel the stop action. - **Tests** - Introduced an end-to-end test to verify the confirmation dialog appears and AI generation stops as expected when clicking outside during generation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -113,7 +113,11 @@ export class AffineAIPanelWidget extends WidgetComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly _clickOutside = () => {
|
private readonly _clickOutside = () => {
|
||||||
this._discardWithConfirmation();
|
if (this.state === 'generating') {
|
||||||
|
this._stopWithConfirmation();
|
||||||
|
} else {
|
||||||
|
this._discardWithConfirmation();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private _discardModalAbort: AbortController | null = null;
|
private _discardModalAbort: AbortController | null = null;
|
||||||
@@ -169,6 +173,16 @@ export class AffineAIPanelWidget extends WidgetComponent {
|
|||||||
|
|
||||||
ctx: unknown = null;
|
ctx: unknown = null;
|
||||||
|
|
||||||
|
private readonly _stopWithConfirmation = () => {
|
||||||
|
this.showStopModal()
|
||||||
|
.then(stop => {
|
||||||
|
if (stop) {
|
||||||
|
this.stopGenerating();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
};
|
||||||
|
|
||||||
private readonly _discardWithConfirmation = () => {
|
private readonly _discardWithConfirmation = () => {
|
||||||
if (this.state === 'hidden') {
|
if (this.state === 'hidden') {
|
||||||
return;
|
return;
|
||||||
@@ -275,6 +289,24 @@ export class AffineAIPanelWidget extends WidgetComponent {
|
|||||||
this._autoUpdatePosition(reference);
|
this._autoUpdatePosition(reference);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
showStopModal = () => {
|
||||||
|
const notification = this.host.std.getOptional(NotificationProvider);
|
||||||
|
if (!notification) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
this._clearDiscardModal();
|
||||||
|
this._discardModalAbort = new AbortController();
|
||||||
|
return notification
|
||||||
|
.confirm({
|
||||||
|
title: 'Stop generating',
|
||||||
|
message: 'AI is generating content. Do you want to stop generating?',
|
||||||
|
cancelText: 'Cancel',
|
||||||
|
confirmText: 'Stop',
|
||||||
|
abort: this._abortController.signal,
|
||||||
|
})
|
||||||
|
.finally(() => (this._discardModalAbort = null));
|
||||||
|
};
|
||||||
|
|
||||||
showDiscardModal = () => {
|
showDiscardModal = () => {
|
||||||
const notification = this.host.std.getOptional(NotificationProvider);
|
const notification = this.host.std.getOptional(NotificationProvider);
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
|
|||||||
@@ -21,6 +21,21 @@ test.describe('AIChatWith/Text', () => {
|
|||||||
await expect(page.getByTestId('ai-generating')).not.toBeVisible();
|
await expect(page.getByTestId('ai-generating')).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should support stop generating when click outside', async ({
|
||||||
|
loggedInPage: page,
|
||||||
|
utils,
|
||||||
|
}) => {
|
||||||
|
await utils.editor.askAIWithText(page, 'Panda');
|
||||||
|
await page.getByTestId('action-generate-image').click();
|
||||||
|
await expect(page.getByTestId('ai-generating')).toBeVisible();
|
||||||
|
await page.mouse.click(0, 0);
|
||||||
|
await expect(
|
||||||
|
page.getByText('AI is generating content. Do you want to stop generating')
|
||||||
|
).toBeVisible();
|
||||||
|
await page.getByTestId('confirm-modal-confirm').click();
|
||||||
|
await expect(page.getByTestId('ai-generating')).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
test('should support copy answer', async ({ loggedInPage: page, utils }) => {
|
test('should support copy answer', async ({ loggedInPage: page, utils }) => {
|
||||||
const { translate } = await utils.editor.askAIWithText(page, 'Apple');
|
const { translate } = await utils.editor.askAIWithText(page, 'Apple');
|
||||||
const { answer } = await translate('German');
|
const { answer } = await translate('German');
|
||||||
|
|||||||
Reference in New Issue
Block a user