refactor(editor): remove dependency of command global types (#9903)

Closes: [BS-2216](https://linear.app/affine-design/issue/BS-2216/remove-global-types-in-command)
This commit is contained in:
Saul-Mirone
2025-01-27 12:28:46 +00:00
parent 4b549e0484
commit 17bf75e843
170 changed files with 1461 additions and 2124 deletions

View File

@@ -1,3 +1,4 @@
import { deleteTextCommand } from '@blocksuite/affine-components/rich-text';
import {
AttachmentAdapter,
copyMiddleware,
@@ -7,6 +8,18 @@ import {
NotionTextAdapter,
pasteMiddleware,
} from '@blocksuite/affine-shared/adapters';
import {
clearAndSelectFirstModelCommand,
copySelectedModelsCommand,
deleteSelectedModelsCommand,
draftSelectedModelsCommand,
getBlockIndexCommand,
getBlockSelectionsCommand,
getImageSelectionsCommand,
getSelectedModelsCommand,
getTextSelectionCommand,
retainFirstModelCommand,
} from '@blocksuite/affine-shared/commands';
import type { BlockComponent, UIEventHandler } from '@blocksuite/block-std';
import { DisposableGroup } from '@blocksuite/global/utils';
import type { BlockSnapshot, Store } from '@blocksuite/store';
@@ -23,9 +36,9 @@ export class PageClipboard {
return this._std.command
.chain()
.with({ onCopy })
.getSelectedModels()
.draftSelectedModels()
.copySelectedModels();
.pipe(getSelectedModelsCommand)
.pipe(draftSelectedModelsCommand)
.pipe(copySelectedModelsCommand);
};
protected _disposables = new DisposableGroup();
@@ -126,9 +139,9 @@ export class PageClipboard {
this._copySelected(() => {
this._std.command
.chain()
.try(cmd => [
cmd.getTextSelection().deleteText(),
cmd.getSelectedModels().deleteSelectedModels(),
.try<{}>(cmd => [
cmd.pipe(getTextSelectionCommand).pipe(deleteTextCommand),
cmd.pipe(getSelectedModelsCommand).pipe(deleteSelectedModelsCommand),
])
.run();
}).run();
@@ -142,22 +155,22 @@ export class PageClipboard {
this._std.command
.chain()
.try(cmd => [
cmd.getTextSelection(),
cmd.pipe(getTextSelectionCommand),
cmd
.getSelectedModels()
.clearAndSelectFirstModel()
.retainFirstModel()
.deleteSelectedModels(),
.pipe(getSelectedModelsCommand)
.pipe(clearAndSelectFirstModelCommand)
.pipe(retainFirstModelCommand)
.pipe(deleteSelectedModelsCommand),
])
.try(cmd => [
cmd.getTextSelection().inline<'currentSelectionPath'>((ctx, next) => {
.try<{ currentSelectionPath: string }>(cmd => [
cmd.pipe(getTextSelectionCommand).pipe((ctx, next) => {
const textSelection = ctx.currentTextSelection;
if (!textSelection) {
return;
}
next({ currentSelectionPath: textSelection.from.blockId });
}),
cmd.getBlockSelections().inline<'currentSelectionPath'>((ctx, next) => {
cmd.pipe(getBlockSelectionsCommand).pipe((ctx, next) => {
const currentBlockSelections = ctx.currentBlockSelections;
if (!currentBlockSelections) {
return;
@@ -168,7 +181,7 @@ export class PageClipboard {
}
next({ currentSelectionPath: blockSelection.blockId });
}),
cmd.getImageSelections().inline<'currentSelectionPath'>((ctx, next) => {
cmd.pipe(getImageSelectionsCommand).pipe((ctx, next) => {
const currentImageSelections = ctx.currentImageSelections;
if (!currentImageSelections) {
return;
@@ -180,8 +193,8 @@ export class PageClipboard {
next({ currentSelectionPath: imageSelection.blockId });
}),
])
.getBlockIndex()
.inline((ctx, next) => {
.pipe(getBlockIndexCommand)
.pipe((ctx, next) => {
if (!ctx.parentBlock) {
return;
}

View File

@@ -1,34 +0,0 @@
import {
getSelectedPeekableBlocksCommand,
peekSelectedBlockCommand,
} from '@blocksuite/affine-components/peek';
import { textCommands } from '@blocksuite/affine-components/rich-text';
import {
clearAndSelectFirstModelCommand,
copySelectedModelsCommand,
deleteSelectedModelsCommand,
draftSelectedModelsCommand,
duplicateSelectedModelsCommand,
getSelectedModelsCommand,
getSelectionRectsCommand,
retainFirstModelCommand,
} from '@blocksuite/affine-shared/commands';
import type { BlockCommands } from '@blocksuite/block-std';
export const commands: BlockCommands = {
// models
clearAndSelectFirstModel: clearAndSelectFirstModelCommand,
copySelectedModels: copySelectedModelsCommand,
deleteSelectedModels: deleteSelectedModelsCommand,
draftSelectedModels: draftSelectedModelsCommand,
duplicateSelectedModels: duplicateSelectedModelsCommand,
getSelectedModels: getSelectedModelsCommand,
retainFirstModel: retainFirstModelCommand,
// text
...textCommands,
// peekable
peekSelectedBlock: peekSelectedBlockCommand,
getSelectedPeekableBlocks: getSelectedPeekableBlocksCommand,
// rect
getSelectionRects: getSelectionRectsCommand,
};

View File

@@ -1,3 +1,4 @@
import { insertEdgelessTextCommand } from '@blocksuite/affine-block-edgeless-text';
import {
CanvasElementType,
EdgelessCRUDIdentifier,
@@ -254,10 +255,13 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
.get(FeatureFlagService)
.getFlag('enable_edgeless_text');
if (textFlag) {
const { textId } = this.edgeless.std.command.exec('insertEdgelessText', {
x: bound.x,
y: bound.y,
});
const [_, { textId }] = this.edgeless.std.command.exec(
insertEdgelessTextCommand,
{
x: bound.x,
y: bound.y,
}
);
if (!textId) return;
const textElement = this.crud.getElementById(textId);

View File

@@ -1,3 +1,4 @@
import { insertLinkByQuickSearchCommand } from '@blocksuite/affine-block-bookmark';
import { menu } from '@blocksuite/affine-components/context-menu';
import { LinkIcon } from '@blocksuite/affine-components/icons';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
@@ -9,8 +10,8 @@ export const buildLinkDenseMenu: DenseMenuBuilder = edgeless =>
name: 'Link',
prefix: LinkIcon,
select: () => {
const { insertedLinkType } = edgeless.std.command.exec(
'insertLinkByQuickSearch'
const [_, { insertedLinkType }] = edgeless.std.command.exec(
insertLinkByQuickSearchCommand
);
insertedLinkType

View File

@@ -1,3 +1,4 @@
import { insertLinkByQuickSearchCommand } from '@blocksuite/affine-block-bookmark';
import { LinkIcon } from '@blocksuite/affine-components/icons';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
import { css, html, LitElement } from 'lit';
@@ -17,8 +18,8 @@ export class EdgelessLinkToolButton extends QuickToolMixin(LitElement) {
override type = 'default' as const;
private _onClick() {
const { insertedLinkType } = this.edgeless.std.command.exec(
'insertLinkByQuickSearch'
const [_, { insertedLinkType }] = this.edgeless.std.command.exec(
insertLinkByQuickSearchCommand
);
insertedLinkType
?.then(type => {

View File

@@ -1,3 +1,4 @@
import { insertEdgelessTextCommand } from '@blocksuite/affine-block-edgeless-text';
import { CanvasElementType } from '@blocksuite/affine-block-surface';
import { type MindmapStyle, TextElementModel } from '@blocksuite/affine-model';
import {
@@ -111,10 +112,13 @@ export const textRender: DraggableTool['render'] = (
.getFlag('enable_edgeless_text');
let id: string;
if (flag) {
const { textId } = edgeless.std.command.exec('insertEdgelessText', {
x: bound.x,
y: vCenter - h / 2,
});
const [_, { textId }] = edgeless.std.command.exec(
insertEdgelessTextCommand,
{
x: bound.x,
y: vCenter - h / 2,
}
);
id = textId!;
} else {
id = service.crud.addElement(CanvasElementType.TEXT, {

View File

@@ -1,4 +1,5 @@
import { addAttachments } from '@blocksuite/affine-block-attachment';
import { insertLinkByQuickSearchCommand } from '@blocksuite/affine-block-bookmark';
import { addImages, LoadedImageIcon } from '@blocksuite/affine-block-image';
import { AttachmentIcon, LinkIcon } from '@blocksuite/affine-components/icons';
import { MAX_IMAGE_WIDTH } from '@blocksuite/affine-model';
@@ -65,8 +66,8 @@ export class EdgelessNoteMenu extends EdgelessToolbarToolMixin(LitElement) {
}
private _onHandleLinkButtonClick() {
const { insertedLinkType } = this.edgeless.service.std.command.exec(
'insertLinkByQuickSearch'
const [_, { insertedLinkType }] = this.edgeless.service.std.command.exec(
insertLinkByQuickSearchCommand
);
insertedLinkType

View File

@@ -1,3 +1,4 @@
import { insertLinkByQuickSearchCommand } from '@blocksuite/affine-block-bookmark';
import { EdgelessTextBlockComponent } from '@blocksuite/affine-block-edgeless-text';
import { toast } from '@blocksuite/affine-components/toast';
import {
@@ -182,8 +183,8 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {
) {
return;
}
const { insertedLinkType } = std.command.exec(
'insertLinkByQuickSearch'
const [_, { insertedLinkType }] = std.command.exec(
insertLinkByQuickSearchCommand
);
insertedLinkType

View File

@@ -16,7 +16,6 @@ import { AFFINE_SCROLL_ANCHORING_WIDGET } from '@blocksuite/affine-widget-scroll
import {
BlockServiceWatcher,
BlockViewExtension,
CommandExtension,
FlavourExtension,
WidgetViewMapExtension,
} from '@blocksuite/block-std';
@@ -26,7 +25,6 @@ import { literal, unsafeStatic } from 'lit/static-html.js';
import { ExportManagerExtension } from '../../_common/export-manager/export-manager.js';
import { RootBlockAdapterExtensions } from '../adapters/extension.js';
import { commands } from '../commands/index.js';
import { AFFINE_EDGELESS_AUTO_CONNECT_WIDGET } from '../widgets/edgeless-auto-connect/edgeless-auto-connect.js';
import { AFFINE_EDGELESS_ZOOM_TOOLBAR_WIDGET } from '../widgets/edgeless-zoom-toolbar/index.js';
import { EDGELESS_ELEMENT_TOOLBAR_WIDGET } from '../widgets/element-toolbar/index.js';
@@ -93,7 +91,6 @@ const EdgelessCommonExtension: ExtensionType[] = [
DocModeService,
ThemeService,
EmbedOptionService,
CommandExtension(commands),
ExportManagerExtension,
ToolController,
DNDAPIExtension,

View File

@@ -1,3 +1,4 @@
import { insertEdgelessTextCommand } from '@blocksuite/affine-block-edgeless-text';
import {
ConnectorUtils,
OverlayIdentifier,
@@ -792,7 +793,7 @@ export class DefaultTool extends BaseTool {
if (textFlag) {
const [x, y] = this.gfx.viewport.toModelCoord(e.x, e.y);
this.std.command.exec('insertEdgelessText', { x, y });
this.std.command.exec(insertEdgelessTextCommand, { x, y });
} else {
addText(this._edgeless, e);
}

View File

@@ -1,3 +1,4 @@
import { insertEdgelessTextCommand } from '@blocksuite/affine-block-edgeless-text';
import type { TextElementModel } from '@blocksuite/affine-model';
import {
FeatureFlagService,
@@ -47,7 +48,7 @@ export class TextTool extends BaseTool {
if (textFlag) {
const [x, y] = this.gfx.viewport.toModelCoord(e.x, e.y);
this.gfx.std.command.exec('insertEdgelessText', { x, y });
this.gfx.std.command.exec(insertEdgelessTextCommand, { x, y });
this.gfx.tool.setTool('default');
} else {
addText(this.gfx, e);

View File

@@ -5,6 +5,10 @@ import {
promptDocTitle,
} from '@blocksuite/affine-block-embed';
import { ParagraphBlockComponent } from '@blocksuite/affine-block-paragraph';
import {
draftSelectedModelsCommand,
getSelectedModelsCommand,
} from '@blocksuite/affine-shared/commands';
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import {
type BlockComponent,
@@ -120,11 +124,11 @@ export class PageKeyboardManager {
const rootComponent = this.rootComponent;
const [_, ctx] = this.rootComponent.std.command
.chain()
.getSelectedModels({
.pipe(getSelectedModelsCommand, {
types: ['block'],
mode: 'highest',
})
.draftSelectedModels()
.pipe(draftSelectedModelsCommand)
.run();
const selectedModels = ctx.selectedModels?.filter(
block =>

View File

@@ -11,7 +11,6 @@ import { AFFINE_DOC_REMOTE_SELECTION_WIDGET } from '@blocksuite/affine-widget-re
import { AFFINE_SCROLL_ANCHORING_WIDGET } from '@blocksuite/affine-widget-scroll-anchoring';
import {
BlockViewExtension,
CommandExtension,
FlavourExtension,
WidgetViewMapExtension,
} from '@blocksuite/block-std';
@@ -20,7 +19,6 @@ import { literal, unsafeStatic } from 'lit/static-html.js';
import { ExportManagerExtension } from '../../_common/export-manager/export-manager.js';
import { RootBlockAdapterExtensions } from '../adapters/extension.js';
import { commands } from '../commands/index.js';
import { AFFINE_EMBED_CARD_TOOLBAR_WIDGET } from '../widgets/embed-card-toolbar/embed-card-toolbar.js';
import { AFFINE_FORMAT_BAR_WIDGET } from '../widgets/format-bar/format-bar.js';
import { AFFINE_INNER_MODAL_WIDGET } from '../widgets/inner-modal/inner-modal.js';
@@ -75,7 +73,6 @@ const PageCommonExtension: ExtensionType[] = [
export const PageRootBlockSpec: ExtensionType[] = [
...PageCommonExtension,
BlockViewExtension('affine:page', literal`affine-page-root`),
CommandExtension(commands),
WidgetViewMapExtension('affine:page', pageRootWidgetViewMap),
ExportManagerExtension,
DNDAPIExtension,

View File

@@ -1,4 +1,10 @@
import { RootBlockSchema } from '@blocksuite/affine-model';
import {
getBlockSelectionsCommand,
getImageSelectionsCommand,
getSelectedBlocksCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import type { BlockComponent } from '@blocksuite/block-std';
import { BlockService } from '@blocksuite/block-std';
@@ -23,12 +29,12 @@ export abstract class RootService extends BlockService {
this.std.command
.chain()
.tryAll(chain => [
chain.getTextSelection(),
chain.getImageSelections(),
chain.getBlockSelections(),
chain.pipe(getTextSelectionCommand),
chain.pipe(getImageSelectionsCommand),
chain.pipe(getBlockSelectionsCommand),
])
.getSelectedBlocks()
.inline(({ selectedBlocks }) => {
.pipe(getSelectedBlocksCommand)
.pipe(({ selectedBlocks }) => {
if (!selectedBlocks) return;
result = selectedBlocks;
})

View File

@@ -1,4 +1,6 @@
import {
autoArrangeElementsCommand,
autoResizeElementsCommand,
EdgelessCRUDIdentifier,
updateXYWH,
} from '@blocksuite/affine-block-surface';
@@ -134,10 +136,10 @@ export class EdgelessAlignButton extends WithDisposable(LitElement) {
this._alignDistributeVertically();
break;
case Alignment.AutoArrange:
this.edgeless.std.command.exec('autoArrangeElements');
this.edgeless.std.command.exec(autoArrangeElementsCommand);
break;
case Alignment.AutoResize:
this.edgeless.std.command.exec('autoResizeElements');
this.edgeless.std.command.exec(autoResizeElementsCommand);
break;
}
}

View File

@@ -10,7 +10,10 @@ import {
getDocContentWithMaxLength,
getEmbedCardIcons,
} from '@blocksuite/affine-block-embed';
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
import {
EdgelessCRUDIdentifier,
reassociateConnectorsCommand,
} from '@blocksuite/affine-block-surface';
import {
CaptionIcon,
CopyIcon,
@@ -164,7 +167,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
this.edgeless.surface.model
);
this.std.command.exec('reassociateConnectors', {
this.std.command.exec(reassociateConnectorsCommand, {
oldId: id,
newId,
});
@@ -220,7 +223,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
);
if (!newId) return;
this.std.command.exec('reassociateConnectors', {
this.std.command.exec(reassociateConnectorsCommand, {
oldId: id,
newId,
});

View File

@@ -1,3 +1,4 @@
import { changeNoteDisplayMode } from '@blocksuite/affine-block-note';
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
import type {
EdgelessColorPickerButton,
@@ -195,7 +196,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
}
private _setDisplayMode(note: NoteBlockModel, newMode: NoteDisplayMode) {
this.edgeless.std.command.exec('changeNoteDisplayMode', {
this.edgeless.std.command.exec(changeNoteDisplayMode, {
noteId: note.id,
mode: newMode,
stopCapture: true,

View File

@@ -1,5 +1,6 @@
import type { SurfaceBlockComponent } from '@blocksuite/affine-block-surface';
import { MenuContext } from '@blocksuite/affine-components/toolbar';
import { getSelectedModelsCommand } from '@blocksuite/affine-shared/commands';
import {
GfxPrimitiveElementModel,
type GfxSelectionManager,
@@ -47,10 +48,9 @@ export class ElementToolbarMoreMenuContext extends MenuContext {
}
get selectedBlockModels() {
const [result, { selectedModels }] = this.std.command
.chain()
.getSelectedModels()
.run();
const [result, { selectedModels }] = this.std.command.exec(
getSelectedModelsCommand
);
if (!result) return [];

View File

@@ -5,6 +5,15 @@ import {
TextBackgroundDuotoneIcon,
TextForegroundDuotoneIcon,
} from '@blocksuite/affine-components/icons';
import {
formatBlockCommand,
formatNativeCommand,
formatTextCommand,
} from '@blocksuite/affine-components/rich-text';
import {
getBlockSelectionsCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
import type { EditorHost } from '@blocksuite/block-std';
import { assertExists } from '@blocksuite/global/utils';
@@ -41,9 +50,9 @@ const updateHighlight = (
host.std.command
.chain()
.try(chain => [
chain.getTextSelection().formatText(payload),
chain.getBlockSelections().formatBlock(payload),
chain.formatNative(payload),
chain.pipe(getTextSelectionCommand).pipe(formatTextCommand, payload),
chain.pipe(getBlockSelectionsCommand).pipe(formatBlockCommand, payload),
chain.pipe(formatNativeCommand, payload),
])
.run();
};

View File

@@ -33,13 +33,33 @@ import {
TextIcon,
UnderlineIcon,
} from '@blocksuite/affine-components/icons';
import {
deleteTextCommand,
toggleBold,
toggleCode,
toggleItalic,
toggleLink,
toggleStrike,
toggleUnderline,
} from '@blocksuite/affine-components/rich-text';
import { toast } from '@blocksuite/affine-components/toast';
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
import { renderGroups } from '@blocksuite/affine-components/toolbar';
import {
copySelectedModelsCommand,
deleteSelectedModelsCommand,
draftSelectedModelsCommand,
getBlockIndexCommand,
getBlockSelectionsCommand,
getImageSelectionsCommand,
getSelectedBlocksCommand,
getSelectedModelsCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
import type {
BlockComponent,
Chain,
CommandKeyToData,
InitCommandCtx,
} from '@blocksuite/block-std';
import { tableViewMeta } from '@blocksuite/data-view/view-presets';
@@ -109,32 +129,32 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
.addDivider()
.addTextStyleToggle({
key: 'bold',
action: chain => chain.toggleBold().run(),
action: chain => chain.pipe(toggleBold).run(),
icon: BoldIcon,
})
.addTextStyleToggle({
key: 'italic',
action: chain => chain.toggleItalic().run(),
action: chain => chain.pipe(toggleItalic).run(),
icon: ItalicIcon,
})
.addTextStyleToggle({
key: 'underline',
action: chain => chain.toggleUnderline().run(),
action: chain => chain.pipe(toggleUnderline).run(),
icon: UnderlineIcon,
})
.addTextStyleToggle({
key: 'strike',
action: chain => chain.toggleStrike().run(),
action: chain => chain.pipe(toggleStrike).run(),
icon: StrikethroughIcon,
})
.addTextStyleToggle({
key: 'code',
action: chain => chain.toggleCode().run(),
action: chain => chain.pipe(toggleCode).run(),
icon: CodeIcon,
})
.addTextStyleToggle({
key: 'link',
action: chain => chain.toggleLink().run(),
action: chain => chain.pipe(toggleLink).run(),
icon: LinkIcon,
})
.addDivider()
@@ -151,7 +171,7 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
showWhen: chain => {
const middleware = (count = 0) => {
return (
ctx: CommandKeyToData<'selectedBlocks'>,
ctx: { selectedBlocks: BlockComponent[] },
next: () => void
) => {
const { selectedBlocks } = ctx;
@@ -166,24 +186,24 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
};
};
let [result] = chain
.getTextSelection()
.getSelectedBlocks({
.pipe(getTextSelectionCommand)
.pipe(getSelectedBlocksCommand, {
types: ['text'],
})
.inline(middleware(1))
.pipe(middleware(1))
.run();
if (result) return true;
[result] = chain
.tryAll(chain => [
chain.getBlockSelections(),
chain.getImageSelections(),
chain.pipe(getBlockSelectionsCommand),
chain.pipe(getImageSelectionsCommand),
])
.getSelectedBlocks({
.pipe(getSelectedBlocksCommand, {
types: ['block', 'image'],
})
.inline(middleware(0))
.pipe(middleware(0))
.run();
return result;
@@ -197,11 +217,11 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
isActive: () => false,
action: (chain, formatBar) => {
const [_, ctx] = chain
.getSelectedModels({
.pipe(getSelectedModelsCommand, {
types: ['block', 'text'],
mode: 'flat',
})
.draftSelectedModels()
.pipe(draftSelectedModelsCommand)
.run();
const { draftedModels, selectedModels, std } = ctx;
if (!selectedModels?.length || !draftedModels) return;
@@ -238,7 +258,7 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
},
showWhen: chain => {
const [_, ctx] = chain
.getSelectedModels({
.pipe(getSelectedModelsCommand, {
types: ['block', 'text'],
mode: 'highest',
})
@@ -332,14 +352,14 @@ export const BUILT_IN_GROUPS: MenuItemGroup<FormatBarContext>[] = [
action: c => {
c.std.command
.chain()
.getSelectedModels()
.pipe(getSelectedModelsCommand)
.with({
onCopy: () => {
toast(c.host, 'Copied to clipboard');
},
})
.draftSelectedModels()
.copySelectedModels()
.pipe(draftSelectedModelsCommand)
.pipe(copySelectedModelsCommand)
.run();
},
},
@@ -352,35 +372,27 @@ export const BUILT_IN_GROUPS: MenuItemGroup<FormatBarContext>[] = [
c.doc.captureSync();
c.std.command
.chain()
.try(cmd => [
cmd
.getTextSelection()
.inline<'currentSelectionPath'>((ctx, next) => {
const textSelection = ctx.currentTextSelection;
assertExists(textSelection);
const end = textSelection.to ?? textSelection.from;
next({ currentSelectionPath: end.blockId });
}),
cmd
.getBlockSelections()
.inline<'currentSelectionPath'>((ctx, next) => {
const currentBlockSelections = ctx.currentBlockSelections;
assertExists(currentBlockSelections);
const blockSelection = currentBlockSelections.at(-1);
if (!blockSelection) {
return;
}
next({ currentSelectionPath: blockSelection.blockId });
}),
.try<{ currentSelectionPath: string }>(cmd => [
cmd.pipe(getTextSelectionCommand).pipe((ctx, next) => {
const textSelection = ctx.currentTextSelection;
assertExists(textSelection);
const end = textSelection.to ?? textSelection.from;
next({ currentSelectionPath: end.blockId });
}),
cmd.pipe(getBlockSelectionsCommand).pipe((ctx, next) => {
const currentBlockSelections = ctx.currentBlockSelections;
assertExists(currentBlockSelections);
const blockSelection = currentBlockSelections.at(-1);
if (!blockSelection) {
return;
}
next({ currentSelectionPath: blockSelection.blockId });
}),
])
.getBlockIndex()
.getSelectedModels()
.draftSelectedModels()
.inline((ctx, next) => {
if (!ctx.draftedModels) {
return next();
}
.pipe(getBlockIndexCommand)
.pipe(getSelectedModelsCommand)
.pipe(draftSelectedModelsCommand)
.pipe((ctx, next) => {
ctx.draftedModels
.then(models => {
const slice = Slice.fromModels(ctx.std.store, models);
@@ -412,8 +424,8 @@ export const BUILT_IN_GROUPS: MenuItemGroup<FormatBarContext>[] = [
// remove text
const [result] = c.std.command
.chain()
.getTextSelection()
.deleteText()
.pipe(getTextSelectionCommand)
.pipe(deleteTextCommand)
.run();
if (result) {
@@ -424,11 +436,11 @@ export const BUILT_IN_GROUPS: MenuItemGroup<FormatBarContext>[] = [
c.std.command
.chain()
.tryAll(chain => [
chain.getBlockSelections(),
chain.getImageSelections(),
chain.pipe(getBlockSelectionsCommand),
chain.pipe(getImageSelectionsCommand),
])
.getSelectedModels()
.deleteSelectedModels()
.pipe(getSelectedModelsCommand)
.pipe(deleteSelectedModelsCommand)
.run();
c.toolbar.reset();

View File

@@ -1,4 +1,10 @@
import { MenuContext } from '@blocksuite/affine-components/toolbar';
import {
getBlockSelectionsCommand,
getImageSelectionsCommand,
getSelectedModelsCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import type { AffineFormatBarWidget } from './format-bar.js';
@@ -15,11 +21,11 @@ export class FormatBarContext extends MenuContext {
const [success, result] = this.std.command
.chain()
.tryAll(chain => [
chain.getTextSelection(),
chain.getBlockSelections(),
chain.getImageSelections(),
chain.pipe(getTextSelectionCommand),
chain.pipe(getBlockSelectionsCommand),
chain.pipe(getImageSelectionsCommand),
])
.getSelectedModels({
.pipe(getSelectedModelsCommand, {
mode: 'highest',
})
.run();

View File

@@ -1,6 +1,8 @@
import { updateBlockType } from '@blocksuite/affine-block-note';
import { HoverController } from '@blocksuite/affine-components/hover';
import {
isFormatSupported,
isTextStyleActive,
type RichText,
} from '@blocksuite/affine-components/rich-text';
import {
@@ -8,6 +10,10 @@ import {
getMoreMenuConfig,
type MenuItemGroup,
} from '@blocksuite/affine-components/toolbar';
import {
getSelectedBlocksCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import {
@@ -167,11 +173,11 @@ export class AffineFormatBarWidget extends WidgetComponent {
if (!rootComponent.std.range) return;
this.host.std.command
.chain()
.getTextSelection()
.getSelectedBlocks({
.pipe(getTextSelectionCommand)
.pipe(getSelectedBlocksCommand, {
types: ['text'],
})
.inline(ctx => {
.pipe(ctx => {
const { selectedBlocks } = ctx;
if (!selectedBlocks) return;
this._selectedBlocks = selectedBlocks;
@@ -422,7 +428,7 @@ export class AffineFormatBarWidget extends WidgetComponent {
name: config.name ?? camelCaseToWords(type ?? flavour),
action: chain => {
chain
.updateBlockType({
.pipe(updateBlockType, {
flavour,
props: type != null ? { type } : undefined,
})
@@ -479,7 +485,7 @@ export class AffineFormatBarWidget extends WidgetComponent {
name: camelCaseToWords(key),
icon: config.icon,
isActive: chain => {
const [result] = chain.isTextStyleActive({ key }).run();
const [result] = chain.pipe(isTextStyleActive, { key }).run();
return result;
},
action: config.action,

View File

@@ -1,12 +1,49 @@
import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment';
import { toggleEmbedCardCreateModal } from '@blocksuite/affine-block-bookmark';
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
import { insertDatabaseBlockCommand } from '@blocksuite/affine-block-database';
import { insertImagesCommand } from '@blocksuite/affine-block-image';
import { insertLatexBlockCommand } from '@blocksuite/affine-block-latex';
import {
canDedentListCommand,
canIndentListCommand,
dedentListCommand,
indentListCommand,
} from '@blocksuite/affine-block-list';
import { updateBlockType } from '@blocksuite/affine-block-note';
import {
canDedentParagraphCommand,
canIndentParagraphCommand,
dedentParagraphCommand,
indentParagraphCommand,
} from '@blocksuite/affine-block-paragraph';
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
import { insertSurfaceRefBlockCommand } from '@blocksuite/affine-block-surface-ref';
import {
formatBlockCommand,
formatNativeCommand,
formatTextCommand,
getInlineEditorByModel,
getTextStyle,
insertContent,
insertInlineLatex,
toggleBold,
toggleCode,
toggleItalic,
toggleLink,
toggleStrike,
toggleUnderline,
} from '@blocksuite/affine-components/rich-text';
import { toast } from '@blocksuite/affine-components/toast';
import type { FrameBlockModel } from '@blocksuite/affine-model';
import {
copySelectedModelsCommand,
deleteSelectedModelsCommand,
draftSelectedModelsCommand,
duplicateSelectedModelsCommand,
getBlockSelectionsCommand,
getSelectedModelsCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
import {
@@ -157,7 +194,7 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:paragraph'),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:paragraph',
props: { type: 'text' },
});
@@ -169,7 +206,7 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
showWhen: ({ std }: KeyboardToolbarContext) =>
std.store.schema.flavourSchemaMap.has('affine:paragraph'),
action: ({ std }: KeyboardToolbarContext) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:paragraph',
props: { type: `h${i}` },
});
@@ -180,7 +217,7 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
showWhen: ({ std }) => std.store.schema.flavourSchemaMap.has('affine:code'),
icon: CodeBlockIcon(),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:code',
});
},
@@ -191,7 +228,7 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
std.store.schema.flavourSchemaMap.has('affine:paragraph'),
icon: QuoteIcon(),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:paragraph',
props: { type: 'quote' },
});
@@ -203,7 +240,7 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:divider'),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:divider',
props: { type: 'divider' },
});
@@ -215,7 +252,11 @@ const textToolActionItems: KeyboardToolbarActionItem[] = [
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:paragraph'),
action: ({ std }) => {
std.command.chain().getTextSelection().insertInlineLatex().run();
std.command
.chain()
.pipe(getTextSelectionCommand)
.pipe(insertInlineLatex)
.run();
},
},
];
@@ -226,7 +267,7 @@ const listToolActionItems: KeyboardToolbarActionItem[] = [
icon: BulletedListIcon(),
showWhen: ({ std }) => std.store.schema.flavourSchemaMap.has('affine:list'),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:list',
props: {
type: 'bulleted',
@@ -239,7 +280,7 @@ const listToolActionItems: KeyboardToolbarActionItem[] = [
icon: NumberedListIcon(),
showWhen: ({ std }) => std.store.schema.flavourSchemaMap.has('affine:list'),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:list',
props: {
type: 'numbered',
@@ -252,7 +293,7 @@ const listToolActionItems: KeyboardToolbarActionItem[] = [
icon: CheckBoxCheckLinearIcon(),
showWhen: ({ std }) => std.store.schema.flavourSchemaMap.has('affine:list'),
action: ({ std }) => {
std.command.exec('updateBlockType', {
std.command.exec(updateBlockType, {
flavour: 'affine:list',
props: {
type: 'todo',
@@ -273,8 +314,8 @@ const pageToolGroup: KeyboardToolPanelGroup = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.inline(({ selectedModels }) => {
.pipe(getSelectedModelsCommand)
.pipe(({ selectedModels }) => {
const newDoc = createDefaultDoc(std.store.workspace);
if (!selectedModels?.length) return;
insertContent(std.host, selectedModels[0], REFERENCE_NODE, {
@@ -313,8 +354,8 @@ const pageToolGroup: KeyboardToolPanelGroup = {
std.command
.chain()
.getSelectedModels()
.inline(ctx => {
.pipe(getSelectedModelsCommand)
.pipe(ctx => {
const { selectedModels } = ctx;
if (!selectedModels?.length) return;
@@ -348,8 +389,8 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertImages({ removeEmptyLine: true })
.pipe(getSelectedModelsCommand)
.pipe(insertImagesCommand, { removeEmptyLine: true })
.run();
},
},
@@ -359,7 +400,9 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:bookmark'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -384,7 +427,9 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:attachment'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -409,7 +454,9 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:embed-youtube'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -434,7 +481,9 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:embed-github'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -459,7 +508,9 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:embed-figma'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -485,7 +536,9 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:embed-loom'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -512,8 +565,8 @@ const contentMediaToolGroup: KeyboardToolPanelGroup = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertLatexBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertLatexBlockCommand, {
place: 'after',
removeEmptyLine: true,
})
@@ -538,8 +591,8 @@ const documentGroupFrameToolGroup: DynamicKeyboardToolPanelGroup = ({
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertSurfaceRefBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertSurfaceRefBlockCommand, {
reference: frameModel.id,
place: 'after',
removeEmptyLine: true,
@@ -560,8 +613,8 @@ const documentGroupFrameToolGroup: DynamicKeyboardToolPanelGroup = ({
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertSurfaceRefBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertSurfaceRefBlockCommand, {
reference: group.id,
place: 'after',
removeEmptyLine: true,
@@ -587,7 +640,9 @@ const dateToolGroup: KeyboardToolPanelGroup = {
name: 'Today',
icon: TodayIcon(),
action: ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -598,7 +653,9 @@ const dateToolGroup: KeyboardToolPanelGroup = {
name: 'Tomorrow',
icon: TomorrowIcon(),
action: ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -611,7 +668,9 @@ const dateToolGroup: KeyboardToolPanelGroup = {
name: 'Yesterday',
icon: YesterdayIcon(),
action: ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -624,7 +683,9 @@ const dateToolGroup: KeyboardToolPanelGroup = {
name: 'Now',
icon: NowIcon(),
action: ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -645,8 +706,8 @@ const databaseToolGroup: KeyboardToolPanelGroup = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertDatabaseBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertDatabaseBlockCommand, {
viewType: viewPresets.tableViewMeta.type,
place: 'after',
removeEmptyLine: true,
@@ -662,8 +723,8 @@ const databaseToolGroup: KeyboardToolPanelGroup = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertDatabaseBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertDatabaseBlockCommand, {
viewType: viewPresets.kanbanViewMeta.type,
place: 'after',
removeEmptyLine: true,
@@ -706,73 +767,73 @@ const textStyleToolItems: KeyboardToolbarItem[] = [
name: 'Bold',
icon: BoldIcon(),
background: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
return textStyle?.bold ? '#00000012' : '';
},
action: ({ std }) => {
std.command.exec('toggleBold');
std.command.exec(toggleBold);
},
},
{
name: 'Italic',
icon: ItalicIcon(),
background: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
return textStyle?.italic ? '#00000012' : '';
},
action: ({ std }) => {
std.command.exec('toggleItalic');
std.command.exec(toggleItalic);
},
},
{
name: 'UnderLine',
icon: UnderLineIcon(),
background: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
return textStyle?.underline ? '#00000012' : '';
},
action: ({ std }) => {
std.command.exec('toggleUnderline');
std.command.exec(toggleUnderline);
},
},
{
name: 'StrikeThrough',
icon: StrikeThroughIcon(),
background: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
return textStyle?.strike ? '#00000012' : '';
},
action: ({ std }) => {
std.command.exec('toggleStrike');
std.command.exec(toggleStrike);
},
},
{
name: 'Code',
icon: CodeIcon(),
background: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
return textStyle?.code ? '#00000012' : '';
},
action: ({ std }) => {
std.command.exec('toggleCode');
std.command.exec(toggleCode);
},
},
{
name: 'Link',
icon: LinkIcon(),
background: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
return textStyle?.link ? '#00000012' : '';
},
action: ({ std }) => {
std.command.exec('toggleLink');
std.command.exec(toggleLink);
},
},
];
const highlightToolPanel: KeyboardToolPanelConfig = {
icon: ({ std }) => {
const { textStyle } = std.command.exec('getTextStyle');
const [_, { textStyle }] = std.command.exec(getTextStyle);
if (textStyle?.color) {
return HighLightDuotoneIcon(textStyle.color);
} else {
@@ -810,9 +871,13 @@ const highlightToolPanel: KeyboardToolPanelConfig = {
std.command
.chain()
.try(chain => [
chain.getTextSelection().formatText(payload),
chain.getBlockSelections().formatBlock(payload),
chain.formatNative(payload),
chain
.pipe(getTextSelectionCommand)
.pipe(formatTextCommand, payload),
chain
.pipe(getBlockSelectionsCommand)
.pipe(formatBlockCommand, payload),
chain.pipe(formatNativeCommand, payload),
])
.run();
},
@@ -851,9 +916,13 @@ const highlightToolPanel: KeyboardToolPanelConfig = {
std.command
.chain()
.try(chain => [
chain.getTextSelection().formatText(payload),
chain.getBlockSelections().formatBlock(payload),
chain.formatNative(payload),
chain
.pipe(getTextSelectionCommand)
.pipe(formatTextCommand, payload),
chain
.pipe(getBlockSelectionsCommand)
.pipe(formatBlockCommand, payload),
chain.pipe(formatNativeCommand, payload),
])
.run();
},
@@ -872,15 +941,20 @@ const textSubToolbarConfig: KeyboardSubToolbarConfig = {
name: 'InlineTex',
icon: TeXIcon(),
action: ({ std }) => {
std.command.chain().getTextSelection().insertInlineLatex().run();
std.command
.chain()
.pipe(getTextSelectionCommand)
.pipe(insertInlineLatex)
.run();
},
},
highlightToolPanel,
],
autoShow: ({ std }) => {
return computed(() => {
const selection =
std.command.exec('getTextSelection').currentTextSelection;
const [_, { currentTextSelection: selection }] = std.command.exec(
getTextSelectionCommand
);
return selection ? !selection.isCollapsed() : false;
});
},
@@ -900,8 +974,8 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.insertImages({ removeEmptyLine: true })
.pipe(getSelectedModelsCommand)
.pipe(insertImagesCommand, { removeEmptyLine: true })
.run();
},
},
@@ -911,7 +985,9 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
showWhen: ({ std }) =>
std.store.schema.flavourSchemaMap.has('affine:attachment'),
action: async ({ std }) => {
const { selectedModels } = std.command.exec('getSelectedModels');
const [_, { selectedModels }] = std.command.exec(
getSelectedModelsCommand
);
const model = selectedModels?.[0];
if (!model) return;
@@ -950,7 +1026,10 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
disableWhen: ({ std }) => {
const [success] = std.command
.chain()
.tryAll(chain => [chain.canIndentParagraph(), chain.canIndentList()])
.tryAll(chain => [
chain.pipe(canIndentParagraphCommand),
chain.pipe(canIndentListCommand),
])
.run();
return !success;
},
@@ -958,8 +1037,8 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
std.command
.chain()
.tryAll(chain => [
chain.canIndentParagraph().indentParagraph(),
chain.canIndentList().indentList(),
chain.pipe(canIndentParagraphCommand).pipe(indentParagraphCommand),
chain.pipe(canIndentListCommand).pipe(indentListCommand),
])
.run();
},
@@ -972,7 +1051,10 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
disableWhen: ({ std }) => {
const [success] = std.command
.chain()
.tryAll(chain => [chain.canDedentParagraph(), chain.canDedentList()])
.tryAll(chain => [
chain.pipe(canDedentParagraphCommand),
chain.pipe(canDedentListCommand),
])
.run();
return !success;
},
@@ -980,8 +1062,8 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
std.command
.chain()
.tryAll(chain => [
chain.canDedentParagraph().dedentParagraph(),
chain.canDedentList().dedentList(),
chain.pipe(canDedentParagraphCommand).pipe(dedentParagraphCommand),
chain.pipe(canDedentListCommand).pipe(dedentListCommand),
])
.run();
},
@@ -992,14 +1074,14 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.pipe(getSelectedModelsCommand)
.with({
onCopy: () => {
toast(std.host, 'Copied to clipboard');
},
})
.draftSelectedModels()
.copySelectedModels()
.pipe(draftSelectedModelsCommand)
.pipe(copySelectedModelsCommand)
.run();
},
},
@@ -1009,9 +1091,9 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
action: ({ std }) => {
std.command
.chain()
.getSelectedModels()
.draftSelectedModels()
.duplicateSelectedModels()
.pipe(getSelectedModelsCommand)
.pipe(draftSelectedModelsCommand)
.pipe(duplicateSelectedModelsCommand)
.run();
},
},
@@ -1019,7 +1101,11 @@ export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
name: 'Delete',
icon: DeleteIcon(),
action: ({ std }) => {
std.command.chain().getSelectedModels().deleteSelectedModels().run();
std.command
.chain()
.pipe(getSelectedModelsCommand)
.pipe(deleteSelectedModelsCommand)
.run();
},
},
],

View File

@@ -2,6 +2,7 @@ import {
VirtualKeyboardController,
type VirtualKeyboardControllerConfig,
} from '@blocksuite/affine-components/virtual-keyboard';
import { getSelectedModelsCommand } from '@blocksuite/affine-shared/commands';
import {
PropTypes,
requiredProperties,
@@ -94,8 +95,8 @@ export class AffineKeyboardToolbar extends SignalWatcher(
const { std } = this.rootComponent;
std.command
.chain()
.getSelectedModels()
.inline(({ selectedModels }) => {
.pipe(getSelectedModelsCommand)
.pipe(({ selectedModels }) => {
if (!selectedModels?.length) return;
const block = std.view.getBlock(selectedModels[0].id);

View File

@@ -1,13 +1,18 @@
import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment';
import { toggleEmbedCardCreateModal } from '@blocksuite/affine-block-bookmark';
import type { DataViewBlockComponent } from '@blocksuite/affine-block-data-view';
import { insertDatabaseBlockCommand } from '@blocksuite/affine-block-database';
import {
FigmaIcon,
GithubIcon,
LoomIcon,
YoutubeIcon,
} from '@blocksuite/affine-block-embed';
import { insertImagesCommand } from '@blocksuite/affine-block-image';
import { insertLatexBlockCommand } from '@blocksuite/affine-block-latex';
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
import { insertSurfaceRefBlockCommand } from '@blocksuite/affine-block-surface-ref';
import { insertTableBlockCommand } from '@blocksuite/affine-block-table';
import {
ArrowDownBigIcon,
ArrowUpBigIcon,
@@ -30,6 +35,7 @@ import {
import {
getInlineEditorByModel,
insertContent,
insertInlineLatex,
textConversionConfigs,
textFormatConfigs,
} from '@blocksuite/affine-components/rich-text';
@@ -38,6 +44,10 @@ import type {
FrameBlockModel,
ParagraphBlockModel,
} from '@blocksuite/affine-model';
import {
getSelectedModelsCommand,
getTextSelectionCommand,
} from '@blocksuite/affine-shared/commands';
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
import {
FeatureFlagService,
@@ -165,8 +175,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.getTextSelection()
.insertInlineLatex()
.pipe(getTextSelectionCommand)
.pipe(insertInlineLatex)
.run();
},
},
@@ -255,8 +265,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.getSelectedModels()
.insertTableBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertTableBlockCommand, {
place: 'after',
removeEmptyLine: true,
})
@@ -273,8 +283,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: async ({ rootComponent }) => {
const [success, ctx] = rootComponent.std.command
.chain()
.getSelectedModels()
.insertImages({ removeEmptyLine: true })
.pipe(getSelectedModelsCommand)
.pipe(insertImagesCommand, { removeEmptyLine: true })
.run();
if (success) await ctx.insertedImageIds;
@@ -429,8 +439,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.getSelectedModels()
.insertLatexBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertLatexBlockCommand, {
place: 'after',
removeEmptyLine: true,
})
@@ -460,8 +470,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.getSelectedModels()
.insertSurfaceRefBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertSurfaceRefBlockCommand, {
reference: frameModel.id,
place: 'after',
removeEmptyLine: true,
@@ -477,8 +487,8 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: () => {
rootComponent.std.command
.chain()
.getSelectedModels()
.insertSurfaceRefBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertSurfaceRefBlockCommand, {
reference: group.id,
place: 'after',
removeEmptyLine: true,
@@ -568,13 +578,13 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.getSelectedModels()
.insertDatabaseBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertDatabaseBlockCommand, {
viewType: viewPresets.tableViewMeta.type,
place: 'after',
removeEmptyLine: true,
})
.inline(({ insertedDatabaseBlockId }) => {
.pipe(({ insertedDatabaseBlockId }) => {
if (insertedDatabaseBlockId) {
const telemetry =
rootComponent.std.getOptional(TelemetryProvider);
@@ -631,13 +641,13 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.getSelectedModels()
.insertDatabaseBlock({
.pipe(getSelectedModelsCommand)
.pipe(insertDatabaseBlockCommand, {
viewType: viewPresets.kanbanViewMeta.type,
place: 'after',
removeEmptyLine: true,
})
.inline(({ insertedDatabaseBlockId }) => {
.pipe(({ insertedDatabaseBlockId }) => {
if (insertedDatabaseBlockId) {
const telemetry =
rootComponent.std.getOptional(TelemetryProvider);

View File

@@ -1,6 +1,8 @@
import type {
TextConversionConfig,
TextFormatConfig,
import { updateBlockType } from '@blocksuite/affine-block-note';
import {
formatBlockCommand,
type TextConversionConfig,
type TextFormatConfig,
} from '@blocksuite/affine-components/rich-text';
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
import { BlockSelection } from '@blocksuite/block-std';
@@ -102,13 +104,10 @@ export function createConversionItem(
tooltip: slashMenuToolTips[name],
showWhen: ({ model }) => model.doc.schema.flavourSchemaMap.has(flavour),
action: ({ rootComponent }) => {
rootComponent.std.command
.chain()
.updateBlockType({
flavour,
props: { type },
})
.run();
rootComponent.std.command.exec(updateBlockType, {
flavour,
props: { type },
});
},
};
}
@@ -125,17 +124,14 @@ export function createTextFormatItem(
const { std, host } = rootComponent;
if (model.text?.length !== 0) {
std.command
.chain()
.formatBlock({
blockSelections: [
std.selection.create(BlockSelection, {
blockId: model.id,
}),
],
styles: { [id]: true },
})
.run();
std.command.exec(formatBlockCommand, {
blockSelections: [
std.selection.create(BlockSelection, {
blockId: model.id,
}),
],
styles: { [id]: true },
});
} else {
// like format bar when the line is empty
action(host);