From 6ec1948f62cbc3eb165ef63a300b4d2e48be62c6 Mon Sep 17 00:00:00 2001 From: 3720 Date: Wed, 12 Nov 2025 14:46:18 +0800 Subject: [PATCH] feat(editor): release callout (#13896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary by CodeRabbit * **Refactor** * Callout is no longer gated as an experimental option — it now consistently appears in the editor’s slash menu and toolbar where applicable. * **Tests** * End-to-end slash-menu tests updated to expect the Callout item in search results and adjusted item ordering. * **Chores** * Repository ignore rules updated to exclude .kiro files. --- .gitignore | 3 +++ .../blocks/callout/src/configs/slash-menu.ts | 10 +++++----- .../src/services/feature-flag-service.ts | 2 -- .../widgets/keyboard-toolbar/src/config.ts | 14 ++++++-------- .../core/src/modules/feature-flag/constant.ts | 10 ---------- tests/blocksuite/e2e/slash-menu.spec.ts | 19 +++++++++++-------- 6 files changed, 25 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index d58d487e4f..c5e7bc90a2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ node_modules !.vscode/launch.template.json !.vscode/extensions.json +# Kiro +.kiro + # misc /.sass-cache /connect.lock diff --git a/blocksuite/affine/blocks/callout/src/configs/slash-menu.ts b/blocksuite/affine/blocks/callout/src/configs/slash-menu.ts index 65eb0d0e08..567ee39006 100644 --- a/blocksuite/affine/blocks/callout/src/configs/slash-menu.ts +++ b/blocksuite/affine/blocks/callout/src/configs/slash-menu.ts @@ -1,5 +1,4 @@ import { focusBlockEnd } from '@blocksuite/affine-shared/commands'; -import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils'; import { type SlashMenuConfig } from '@blocksuite/affine-widget-slash-menu'; import { FontIcon } from '@blocksuite/icons/lit'; @@ -18,10 +17,11 @@ export const calloutSlashMenuConfig: SlashMenuConfig = { }, searchAlias: ['callout'], group: '0_Basic@9', - when: ({ std, model }) => { - return ( - std.get(FeatureFlagService).getFlag('enable_callout') && - !isInsideBlockByFlavour(model.store, model, 'affine:edgeless-text') + when: ({ model }) => { + return !isInsideBlockByFlavour( + model.store, + model, + 'affine:edgeless-text' ); }, action: ({ model, std }) => { diff --git a/blocksuite/affine/shared/src/services/feature-flag-service.ts b/blocksuite/affine/shared/src/services/feature-flag-service.ts index d31050d16b..c0ecf54803 100644 --- a/blocksuite/affine/shared/src/services/feature-flag-service.ts +++ b/blocksuite/affine/shared/src/services/feature-flag-service.ts @@ -17,7 +17,6 @@ export interface BlockSuiteFlags { enable_mobile_linked_doc_menu: boolean; enable_mobile_database_editing: boolean; enable_block_meta: boolean; - enable_callout: boolean; enable_edgeless_scribbled_style: boolean; enable_table_virtual_scroll: boolean; enable_turbo_renderer: boolean; @@ -43,7 +42,6 @@ export class FeatureFlagService extends StoreExtension { enable_mobile_linked_doc_menu: false, enable_block_meta: true, enable_mobile_database_editing: false, - enable_callout: false, enable_edgeless_scribbled_style: false, enable_table_virtual_scroll: false, enable_turbo_renderer: false, diff --git a/blocksuite/affine/widgets/keyboard-toolbar/src/config.ts b/blocksuite/affine/widgets/keyboard-toolbar/src/config.ts index 9cdf72e564..51aa7df3aa 100644 --- a/blocksuite/affine/widgets/keyboard-toolbar/src/config.ts +++ b/blocksuite/affine/widgets/keyboard-toolbar/src/config.ts @@ -47,10 +47,7 @@ import { getTextSelectionCommand, } from '@blocksuite/affine-shared/commands'; import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts'; -import { - FeatureFlagService, - TelemetryProvider, -} from '@blocksuite/affine-shared/services'; +import { TelemetryProvider } from '@blocksuite/affine-shared/services'; import type { AffineTextStyleAttributes } from '@blocksuite/affine-shared/types'; import { createDefaultDoc, @@ -290,10 +287,11 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [ { name: 'Callout', icon: FontIcon(), - showWhen: ({ std, rootComponent: { model } }) => { - return ( - std.get(FeatureFlagService).getFlag('enable_callout') && - !isInsideBlockByFlavour(model.store, model, 'affine:edgeless-text') + showWhen: ({ rootComponent: { model } }) => { + return !isInsideBlockByFlavour( + model.store, + model, + 'affine:edgeless-text' ); }, action: ({ rootComponent: { model }, std }) => { diff --git a/packages/frontend/core/src/modules/feature-flag/constant.ts b/packages/frontend/core/src/modules/feature-flag/constant.ts index 162fc7ad77..c1a212cb67 100644 --- a/packages/frontend/core/src/modules/feature-flag/constant.ts +++ b/packages/frontend/core/src/modules/feature-flag/constant.ts @@ -95,16 +95,6 @@ export const AFFINE_FLAGS = { configurable: isCanaryBuild, defaultState: true, }, - enable_callout: { - category: 'blocksuite', - bsFlag: 'enable_callout', - displayName: - 'com.affine.settings.workspace.experimental-features.enable-callout.name', - description: - 'com.affine.settings.workspace.experimental-features.enable-callout.description', - configurable: isCanaryBuild, - defaultState: isCanaryBuild, - }, enable_emoji_folder_icon: { category: 'affine', diff --git a/tests/blocksuite/e2e/slash-menu.spec.ts b/tests/blocksuite/e2e/slash-menu.spec.ts index ea5925d51c..e7c38748af 100644 --- a/tests/blocksuite/e2e/slash-menu.spec.ts +++ b/tests/blocksuite/e2e/slash-menu.spec.ts @@ -577,9 +577,10 @@ test.describe('slash search', () => { // search should active the first item await type(page, 'co'); - await expect(slashItems).toHaveCount(3); + await expect(slashItems).toHaveCount(4); await expect(slashItems.nth(0).locator('.text')).toHaveText(['Copy']); await expect(slashItems.nth(1).locator('.text')).toHaveText(['Code Block']); + await expect(slashItems.nth(2).locator('.text')).toHaveText(['Callout']); await expect(slashItems.nth(0)).toHaveAttribute('hover', 'true'); await type(page, 'p'); @@ -588,9 +589,10 @@ test.describe('slash search', () => { // assert backspace works await pressBackspace(page); - await expect(slashItems).toHaveCount(3); + await expect(slashItems).toHaveCount(4); await expect(slashItems.nth(0).locator('.text')).toHaveText(['Copy']); await expect(slashItems.nth(1).locator('.text')).toHaveText(['Code Block']); + await expect(slashItems.nth(2).locator('.text')).toHaveText(['Callout']); await expect(slashItems.nth(0)).toHaveAttribute('hover', 'true'); }); @@ -606,14 +608,15 @@ test.describe('slash search', () => { await expect(slashMenu).toBeVisible(); await type(page, 'c'); - await expect(slashItems).toHaveCount(9); + await expect(slashItems).toHaveCount(10); await expect(slashItems.nth(0).locator('.text')).toHaveText(['Copy']); await expect(slashItems.nth(1).locator('.text')).toHaveText(['Italic']); - await expect(slashItems.nth(2).locator('.text')).toHaveText(['New Doc']); - await expect(slashItems.nth(3).locator('.text')).toHaveText(['Duplicate']); - await expect(slashItems.nth(4).locator('.text')).toHaveText(['Code Block']); - await expect(slashItems.nth(5).locator('.text')).toHaveText(['Linked Doc']); - await expect(slashItems.nth(6).locator('.text')).toHaveText(['Attachment']); + await expect(slashItems.nth(2).locator('.text')).toHaveText(['Callout']); + await expect(slashItems.nth(3).locator('.text')).toHaveText(['New Doc']); + await expect(slashItems.nth(4).locator('.text')).toHaveText(['Duplicate']); + await expect(slashItems.nth(5).locator('.text')).toHaveText(['Code Block']); + await expect(slashItems.nth(6).locator('.text')).toHaveText(['Linked Doc']); + await expect(slashItems.nth(7).locator('.text')).toHaveText(['Attachment']); await type(page, 'b'); await expect(slashItems.nth(0).locator('.text')).toHaveText(['Code Block']); });