mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 08:38:34 +00:00
feat(editor): release callout (#13896)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## 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. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -33,6 +33,9 @@ node_modules
|
|||||||
!.vscode/launch.template.json
|
!.vscode/launch.template.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# Kiro
|
||||||
|
.kiro
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
/.sass-cache
|
/.sass-cache
|
||||||
/connect.lock
|
/connect.lock
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { focusBlockEnd } from '@blocksuite/affine-shared/commands';
|
import { focusBlockEnd } from '@blocksuite/affine-shared/commands';
|
||||||
import { FeatureFlagService } from '@blocksuite/affine-shared/services';
|
|
||||||
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
||||||
import { type SlashMenuConfig } from '@blocksuite/affine-widget-slash-menu';
|
import { type SlashMenuConfig } from '@blocksuite/affine-widget-slash-menu';
|
||||||
import { FontIcon } from '@blocksuite/icons/lit';
|
import { FontIcon } from '@blocksuite/icons/lit';
|
||||||
@@ -18,10 +17,11 @@ export const calloutSlashMenuConfig: SlashMenuConfig = {
|
|||||||
},
|
},
|
||||||
searchAlias: ['callout'],
|
searchAlias: ['callout'],
|
||||||
group: '0_Basic@9',
|
group: '0_Basic@9',
|
||||||
when: ({ std, model }) => {
|
when: ({ model }) => {
|
||||||
return (
|
return !isInsideBlockByFlavour(
|
||||||
std.get(FeatureFlagService).getFlag('enable_callout') &&
|
model.store,
|
||||||
!isInsideBlockByFlavour(model.store, model, 'affine:edgeless-text')
|
model,
|
||||||
|
'affine:edgeless-text'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
action: ({ model, std }) => {
|
action: ({ model, std }) => {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export interface BlockSuiteFlags {
|
|||||||
enable_mobile_linked_doc_menu: boolean;
|
enable_mobile_linked_doc_menu: boolean;
|
||||||
enable_mobile_database_editing: boolean;
|
enable_mobile_database_editing: boolean;
|
||||||
enable_block_meta: boolean;
|
enable_block_meta: boolean;
|
||||||
enable_callout: boolean;
|
|
||||||
enable_edgeless_scribbled_style: boolean;
|
enable_edgeless_scribbled_style: boolean;
|
||||||
enable_table_virtual_scroll: boolean;
|
enable_table_virtual_scroll: boolean;
|
||||||
enable_turbo_renderer: boolean;
|
enable_turbo_renderer: boolean;
|
||||||
@@ -43,7 +42,6 @@ export class FeatureFlagService extends StoreExtension {
|
|||||||
enable_mobile_linked_doc_menu: false,
|
enable_mobile_linked_doc_menu: false,
|
||||||
enable_block_meta: true,
|
enable_block_meta: true,
|
||||||
enable_mobile_database_editing: false,
|
enable_mobile_database_editing: false,
|
||||||
enable_callout: false,
|
|
||||||
enable_edgeless_scribbled_style: false,
|
enable_edgeless_scribbled_style: false,
|
||||||
enable_table_virtual_scroll: false,
|
enable_table_virtual_scroll: false,
|
||||||
enable_turbo_renderer: false,
|
enable_turbo_renderer: false,
|
||||||
|
|||||||
@@ -47,10 +47,7 @@ import {
|
|||||||
getTextSelectionCommand,
|
getTextSelectionCommand,
|
||||||
} from '@blocksuite/affine-shared/commands';
|
} from '@blocksuite/affine-shared/commands';
|
||||||
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
|
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
|
||||||
import {
|
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||||
FeatureFlagService,
|
|
||||||
TelemetryProvider,
|
|
||||||
} from '@blocksuite/affine-shared/services';
|
|
||||||
import type { AffineTextStyleAttributes } from '@blocksuite/affine-shared/types';
|
import type { AffineTextStyleAttributes } from '@blocksuite/affine-shared/types';
|
||||||
import {
|
import {
|
||||||
createDefaultDoc,
|
createDefaultDoc,
|
||||||
@@ -290,10 +287,11 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
|
|||||||
{
|
{
|
||||||
name: 'Callout',
|
name: 'Callout',
|
||||||
icon: FontIcon(),
|
icon: FontIcon(),
|
||||||
showWhen: ({ std, rootComponent: { model } }) => {
|
showWhen: ({ rootComponent: { model } }) => {
|
||||||
return (
|
return !isInsideBlockByFlavour(
|
||||||
std.get(FeatureFlagService).getFlag('enable_callout') &&
|
model.store,
|
||||||
!isInsideBlockByFlavour(model.store, model, 'affine:edgeless-text')
|
model,
|
||||||
|
'affine:edgeless-text'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
action: ({ rootComponent: { model }, std }) => {
|
action: ({ rootComponent: { model }, std }) => {
|
||||||
|
|||||||
@@ -95,16 +95,6 @@ export const AFFINE_FLAGS = {
|
|||||||
configurable: isCanaryBuild,
|
configurable: isCanaryBuild,
|
||||||
defaultState: true,
|
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: {
|
enable_emoji_folder_icon: {
|
||||||
category: 'affine',
|
category: 'affine',
|
||||||
|
|||||||
@@ -577,9 +577,10 @@ test.describe('slash search', () => {
|
|||||||
|
|
||||||
// search should active the first item
|
// search should active the first item
|
||||||
await type(page, 'co');
|
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(0).locator('.text')).toHaveText(['Copy']);
|
||||||
await expect(slashItems.nth(1).locator('.text')).toHaveText(['Code Block']);
|
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 expect(slashItems.nth(0)).toHaveAttribute('hover', 'true');
|
||||||
|
|
||||||
await type(page, 'p');
|
await type(page, 'p');
|
||||||
@@ -588,9 +589,10 @@ test.describe('slash search', () => {
|
|||||||
|
|
||||||
// assert backspace works
|
// assert backspace works
|
||||||
await pressBackspace(page);
|
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(0).locator('.text')).toHaveText(['Copy']);
|
||||||
await expect(slashItems.nth(1).locator('.text')).toHaveText(['Code Block']);
|
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 expect(slashItems.nth(0)).toHaveAttribute('hover', 'true');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -606,14 +608,15 @@ test.describe('slash search', () => {
|
|||||||
await expect(slashMenu).toBeVisible();
|
await expect(slashMenu).toBeVisible();
|
||||||
|
|
||||||
await type(page, 'c');
|
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(0).locator('.text')).toHaveText(['Copy']);
|
||||||
await expect(slashItems.nth(1).locator('.text')).toHaveText(['Italic']);
|
await expect(slashItems.nth(1).locator('.text')).toHaveText(['Italic']);
|
||||||
await expect(slashItems.nth(2).locator('.text')).toHaveText(['New Doc']);
|
await expect(slashItems.nth(2).locator('.text')).toHaveText(['Callout']);
|
||||||
await expect(slashItems.nth(3).locator('.text')).toHaveText(['Duplicate']);
|
await expect(slashItems.nth(3).locator('.text')).toHaveText(['New Doc']);
|
||||||
await expect(slashItems.nth(4).locator('.text')).toHaveText(['Code Block']);
|
await expect(slashItems.nth(4).locator('.text')).toHaveText(['Duplicate']);
|
||||||
await expect(slashItems.nth(5).locator('.text')).toHaveText(['Linked Doc']);
|
await expect(slashItems.nth(5).locator('.text')).toHaveText(['Code Block']);
|
||||||
await expect(slashItems.nth(6).locator('.text')).toHaveText(['Attachment']);
|
await expect(slashItems.nth(6).locator('.text')).toHaveText(['Linked Doc']);
|
||||||
|
await expect(slashItems.nth(7).locator('.text')).toHaveText(['Attachment']);
|
||||||
await type(page, 'b');
|
await type(page, 'b');
|
||||||
await expect(slashItems.nth(0).locator('.text')).toHaveText(['Code Block']);
|
await expect(slashItems.nth(0).locator('.text')).toHaveText(['Code Block']);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user