diff --git a/blocksuite/affine/blocks/root/src/clipboard/page-clipboard.ts b/blocksuite/affine/blocks/root/src/clipboard/page-clipboard.ts index c0fcd74fc8..e92a3d5e4e 100644 --- a/blocksuite/affine/blocks/root/src/clipboard/page-clipboard.ts +++ b/blocksuite/affine/blocks/root/src/clipboard/page-clipboard.ts @@ -65,7 +65,7 @@ export class PageClipboard extends ReadOnlyClipboard { const e = ctx.get('clipboardState').raw; e.preventDefault(); - this._copySelected(() => { + this._copySelectedInPage(() => { this.std.command .chain() .try<{}>(cmd => [ diff --git a/blocksuite/affine/blocks/root/src/clipboard/readonly-clipboard.ts b/blocksuite/affine/blocks/root/src/clipboard/readonly-clipboard.ts index 3e8e24ef10..46cd327bd4 100644 --- a/blocksuite/affine/blocks/root/src/clipboard/readonly-clipboard.ts +++ b/blocksuite/affine/blocks/root/src/clipboard/readonly-clipboard.ts @@ -84,11 +84,11 @@ export const clipboardConfigs: ExtensionType[] = [ export class ReadOnlyClipboard extends LifeCycleWatcher { static override key = 'affine-readonly-clipboard'; - protected readonly _copySelected = (onCopy?: () => void) => { + protected readonly _copySelectedInPage = (onCopy?: () => void) => { return this.std.command .chain() .with({ onCopy }) - .pipe(getSelectedModelsCommand) + .pipe(getSelectedModelsCommand, { types: ['block', 'text', 'image'] }) .pipe(draftSelectedModelsCommand) .pipe(copySelectedModelsCommand); }; @@ -118,7 +118,7 @@ export class ReadOnlyClipboard extends LifeCycleWatcher { const e = ctx.get('clipboardState').raw; e.preventDefault(); - this._copySelected().run(); + this._copySelectedInPage().run(); }; override mounted(): void { diff --git a/blocksuite/affine/shared/src/commands/block-crud/get-selected-blocks.ts b/blocksuite/affine/shared/src/commands/block-crud/get-selected-blocks.ts index d9a793f7ac..fa10ca6f4f 100644 --- a/blocksuite/affine/shared/src/commands/block-crud/get-selected-blocks.ts +++ b/blocksuite/affine/shared/src/commands/block-crud/get-selected-blocks.ts @@ -1,4 +1,9 @@ -import type { BlockSelection, Command, TextSelection } from '@blocksuite/std'; +import type { + BlockSelection, + Command, + SurfaceSelection, + TextSelection, +} from '@blocksuite/std'; import { BlockComponent } from '@blocksuite/std'; import type { RoleType } from '@blocksuite/store'; @@ -9,11 +14,13 @@ export const getSelectedBlocksCommand: Command< currentTextSelection?: TextSelection; currentBlockSelections?: BlockSelection[]; currentImageSelections?: ImageSelection[]; + currentSurfaceSelection?: SurfaceSelection; textSelection?: TextSelection; blockSelections?: BlockSelection[]; imageSelections?: ImageSelection[]; + surfaceSelection?: SurfaceSelection; filter?: (el: BlockComponent) => boolean; - types?: Array<'image' | 'text' | 'block'>; + types?: Array<'image' | 'text' | 'block' | 'surface'>; roles?: RoleType[]; mode?: 'all' | 'flat' | 'highest'; }, @@ -22,7 +29,7 @@ export const getSelectedBlocksCommand: Command< } > = (ctx, next) => { const { - types = ['block', 'text', 'image'], + types = ['block', 'text', 'image', 'surface'], roles = ['content'], mode = 'flat', } = ctx; @@ -109,6 +116,15 @@ export const getSelectedBlocksCommand: Command< dirtyResult.push(...selectedBlocks); } + const surfaceSelection = ctx.surfaceSelection ?? ctx.currentSurfaceSelection; + if (types.includes('surface') && surfaceSelection) { + const viewStore = ctx.std.view; + const selectedBlocks = surfaceSelection.elements + .map(id => viewStore.getBlock(id)) + .filter(block => !!block); + dirtyResult.push(...selectedBlocks); + } + if (ctx.filter) { dirtyResult = dirtyResult.filter(ctx.filter); } diff --git a/blocksuite/affine/shared/src/commands/model-crud/get-selected-models.ts b/blocksuite/affine/shared/src/commands/model-crud/get-selected-models.ts index 1664798ec8..e54353fbce 100644 --- a/blocksuite/affine/shared/src/commands/model-crud/get-selected-models.ts +++ b/blocksuite/affine/shared/src/commands/model-crud/get-selected-models.ts @@ -5,6 +5,7 @@ import { getSelectedBlocksCommand } from '../block-crud/get-selected-blocks'; import { getBlockSelectionsCommand, getImageSelectionsCommand, + getSurfaceSelectionCommand, getTextSelectionCommand, } from '../selection'; @@ -12,7 +13,7 @@ import { * Retrieves the selected models based on the provided selection types and mode. * * @param ctx - The command context, which includes the types of selections to be retrieved and the mode of the selection. - * @param ctx.types - The selection types to be retrieved. Can be an array of 'block', 'text', or 'image'. + * @param ctx.types - The selection types to be retrieved. Can be an array of 'block', 'text', 'image', or 'surface'. * @param ctx.mode - The mode of the selection. Can be 'all', 'flat', or 'highest'. * @example * // Assuming `commandContext` is an instance of the command context @@ -37,14 +38,14 @@ import { */ export const getSelectedModelsCommand: Command< { - types?: Array<'image' | 'text' | 'block'>; + types?: Array<'image' | 'text' | 'block' | 'surface'>; mode?: 'all' | 'flat' | 'highest'; }, { selectedModels: BlockModel[]; } > = (ctx, next) => { - const types = ctx.types ?? ['block', 'text', 'image']; + const types = ctx.types ?? ['block', 'text', 'image', 'surface']; const mode = ctx.mode ?? 'flat'; const selectedModels: BlockModel[] = []; ctx.std.command @@ -53,6 +54,7 @@ export const getSelectedModelsCommand: Command< chain.pipe(getTextSelectionCommand), chain.pipe(getBlockSelectionsCommand), chain.pipe(getImageSelectionsCommand), + chain.pipe(getSurfaceSelectionCommand), ]) .pipe(getSelectedBlocksCommand, { types, mode }) .pipe(ctx => { diff --git a/blocksuite/affine/shared/src/commands/selection/get-surface-selection.ts b/blocksuite/affine/shared/src/commands/selection/get-surface-selection.ts new file mode 100644 index 0000000000..5814dfab63 --- /dev/null +++ b/blocksuite/affine/shared/src/commands/selection/get-surface-selection.ts @@ -0,0 +1,10 @@ +import { SurfaceSelection } from '@blocksuite/std'; + +import type { GetSelectionCommand } from './types'; + +export const getSurfaceSelectionCommand: GetSelectionCommand = (ctx, next) => { + const currentSurfaceSelection = ctx.std.selection.filter(SurfaceSelection)[0]; + if (!currentSurfaceSelection) return; + + next({ currentSurfaceSelection }); +}; diff --git a/blocksuite/affine/shared/src/commands/selection/index.ts b/blocksuite/affine/shared/src/commands/selection/index.ts index 99731e7959..b06c065f1f 100644 --- a/blocksuite/affine/shared/src/commands/selection/index.ts +++ b/blocksuite/affine/shared/src/commands/selection/index.ts @@ -7,5 +7,6 @@ export { getSelectionRectsCommand, type SelectionRect, } from './get-selection-rects'; +export { getSurfaceSelectionCommand } from './get-surface-selection'; export { getTextSelectionCommand } from './get-text-selection.js'; export { isNothingSelectedCommand } from './is-nothing-selected.js'; diff --git a/blocksuite/affine/shared/src/commands/selection/types.ts b/blocksuite/affine/shared/src/commands/selection/types.ts index d60b1bac12..8c6303b3b2 100644 --- a/blocksuite/affine/shared/src/commands/selection/types.ts +++ b/blocksuite/affine/shared/src/commands/selection/types.ts @@ -1,4 +1,9 @@ -import type { BlockSelection, Command, TextSelection } from '@blocksuite/std'; +import type { + BlockSelection, + Command, + SurfaceSelection, + TextSelection, +} from '@blocksuite/std'; import type { ImageSelection } from '../../selection/image'; @@ -8,5 +13,6 @@ export type GetSelectionCommand = Command< currentTextSelection?: TextSelection; currentBlockSelections?: BlockSelection[]; currentImageSelections?: ImageSelection[]; + currentSurfaceSelection?: SurfaceSelection; } >;