refactor(editor): image toolbar config extension (#11329)

Closes: [BS-2378](https://linear.app/affine-design/issue/BS-2378/image-toolbar-迁移)
This commit is contained in:
fundon
2025-04-01 10:04:28 +00:00
parent 032244ae61
commit 7af5e53838
26 changed files with 267 additions and 785 deletions

View File

@@ -92,7 +92,7 @@ export class AskAIButton extends WithDisposable(LitElement) {
return;
}
if (this._abortController) {
if (this._abortController && !this._abortController.signal.aborted) {
this._clearAbortController();
return;
}

View File

@@ -1,7 +1,11 @@
import '../../components/ask-ai-button';
import type { AffineImageToolbarWidget } from '@blocksuite/affine/blocks/root';
import { ImageSelection } from '@blocksuite/affine/shared/selection';
import { ImageBlockComponent } from '@blocksuite/affine/blocks/image';
import {
ActionPlacement,
type ToolbarModuleConfig,
} from '@blocksuite/affine/shared/services';
import { BlockSelection } from '@blocksuite/affine/std';
import { html } from 'lit';
import { buildAIImageItemGroups } from '../../_common/config';
@@ -14,40 +18,34 @@ const buttonOptions: AskAIButtonOptions = {
panelWidth: 300,
};
export function setupImageToolbarAIEntry(
imageToolbar: AffineImageToolbarWidget
) {
imageToolbar.addPrimaryItems(
[
export function imageToolbarAIEntryConfig(): ToolbarModuleConfig {
return {
actions: [
{
type: 'ask-ai',
when: ({ doc }) => !doc.readonly,
generate: ({ host, blockComponent }) => {
return {
action: () => {
const { selection } = host;
selection.setGroup('note', [
selection.create(ImageSelection, {
blockId: blockComponent.blockId,
placement: ActionPlacement.Start,
id: 'A.ai',
score: -1,
content: ctx => {
const block = ctx.getCurrentBlockByType(ImageBlockComponent);
if (!block) return null;
return html`<ask-ai-button
class="ask-ai inner-button"
.host=${ctx.host}
.actionGroups=${AIImageItemGroups}
.toggleType="${'click'}"
.options=${buttonOptions}
@click=${(e: MouseEvent) => {
e.stopPropagation();
ctx.selection.update(() => [
ctx.selection.create(BlockSelection, {
blockId: block.blockId,
}),
]);
},
render: item =>
html`<ask-ai-button
class="image-toolbar-button ask-ai"
.host=${host}
.actionGroups=${AIImageItemGroups}
.toggleType=${'click'}
.options=${buttonOptions}
@click=${(e: MouseEvent) => {
e.stopPropagation();
item.action();
}}
></ask-ai-button>`,
};
}}
></ask-ai-button>`;
},
},
],
0
);
};
}

View File

@@ -1,29 +1,14 @@
import { ImageBlockSpec } from '@blocksuite/affine/blocks/image';
import { AffineImageToolbarWidget } from '@blocksuite/affine/blocks/root';
import { LifeCycleWatcher } from '@blocksuite/affine/std';
import { ToolbarModuleExtension } from '@blocksuite/affine/shared/services';
import { BlockFlavourIdentifier } from '@blocksuite/affine/std';
import type { ExtensionType } from '@blocksuite/affine/store';
import { setupImageToolbarAIEntry } from '../entries/image-toolbar/setup-image-toolbar';
class AIImageBlockWatcher extends LifeCycleWatcher {
static override key = 'ai-image-block-watcher';
override mounted() {
super.mounted();
const { view } = this.std;
view.viewUpdated.subscribe(payload => {
if (payload.type !== 'widget' || payload.method !== 'add') {
return;
}
const component = payload.view;
if (component instanceof AffineImageToolbarWidget) {
setupImageToolbarAIEntry(component);
}
});
}
}
import { imageToolbarAIEntryConfig } from '../entries/image-toolbar/setup-image-toolbar';
export const AIImageBlockSpec: ExtensionType[] = [
...ImageBlockSpec,
AIImageBlockWatcher,
ToolbarModuleExtension({
id: BlockFlavourIdentifier('custom:affine:image'),
config: imageToolbarAIEntryConfig(),
}),
];

View File

@@ -3,7 +3,6 @@ import {
CodeBlockConfigExtension,
codeToolbarWidget,
} from '@blocksuite/affine/blocks/code';
import { imageToolbarWidget } from '@blocksuite/affine/blocks/image';
import { ParagraphBlockConfigExtension } from '@blocksuite/affine/blocks/paragraph';
import type {
Container,
@@ -134,7 +133,6 @@ export function enableMobileExtension(
framework: FrameworkProvider
): void {
specBuilder.omit(codeToolbarWidget);
specBuilder.omit(imageToolbarWidget);
specBuilder.omit(toolbarWidget);
specBuilder.omit(SlashMenuExtension);
specBuilder.extend([