mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 13:25:12 +00:00
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:
@@ -3,12 +3,18 @@ import {
|
||||
focusTextModel,
|
||||
onModelTextUpdated,
|
||||
} from '@blocksuite/affine-components/rich-text';
|
||||
import {
|
||||
getBlockSelectionsCommand,
|
||||
getSelectedBlocksCommand,
|
||||
getTextSelectionCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import {
|
||||
matchFlavours,
|
||||
mergeToCodeModel,
|
||||
transformModel,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
type BlockComponent,
|
||||
BlockSelection,
|
||||
type Command,
|
||||
TextSelection,
|
||||
@@ -21,9 +27,12 @@ type UpdateBlockConfig = {
|
||||
};
|
||||
|
||||
export const updateBlockType: Command<
|
||||
'selectedBlocks',
|
||||
'updatedBlocks',
|
||||
UpdateBlockConfig
|
||||
UpdateBlockConfig & {
|
||||
selectedBlocks?: BlockComponent[];
|
||||
},
|
||||
{
|
||||
updatedBlocks: BlockModel[];
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
const { std, flavour, props } = ctx;
|
||||
const host = std.host;
|
||||
@@ -35,8 +44,11 @@ export const updateBlockType: Command<
|
||||
if (selectedBlocks == null) {
|
||||
const [result, ctx] = std.command
|
||||
.chain()
|
||||
.tryAll(chain => [chain.getTextSelection(), chain.getBlockSelections()])
|
||||
.getSelectedBlocks({ types: ['text', 'block'] })
|
||||
.tryAll(chain => [
|
||||
chain.pipe(getTextSelectionCommand),
|
||||
chain.pipe(getBlockSelectionsCommand),
|
||||
])
|
||||
.pipe(getSelectedBlocksCommand, { types: ['text', 'block'] })
|
||||
.run();
|
||||
if (result) {
|
||||
selectedBlocks = ctx.selectedBlocks;
|
||||
@@ -60,7 +72,10 @@ export const updateBlockType: Command<
|
||||
);
|
||||
}
|
||||
|
||||
const mergeToCode: Command<never, 'updatedBlocks'> = (_, next) => {
|
||||
const mergeToCode: Command<{}, { updatedBlocks: BlockModel[] }> = (
|
||||
_,
|
||||
next
|
||||
) => {
|
||||
if (flavour !== 'affine:code') return;
|
||||
const id = mergeToCodeModel(blockModels);
|
||||
if (!id) return;
|
||||
@@ -72,7 +87,10 @@ export const updateBlockType: Command<
|
||||
}).catch(console.error);
|
||||
return next({ updatedBlocks: [model] });
|
||||
};
|
||||
const appendDivider: Command<never, 'updatedBlocks'> = (_, next) => {
|
||||
const appendDivider: Command<{}, { updatedBlocks: BlockModel[] }> = (
|
||||
_,
|
||||
next
|
||||
) => {
|
||||
if (flavour !== 'affine:divider') {
|
||||
return false;
|
||||
}
|
||||
@@ -99,7 +117,7 @@ export const updateBlockType: Command<
|
||||
return next({ updatedBlocks: [newModel] });
|
||||
};
|
||||
|
||||
const focusText: Command<'updatedBlocks'> = (ctx, next) => {
|
||||
const focusText: Command<{ updatedBlocks: BlockModel[] }> = (ctx, next) => {
|
||||
const { updatedBlocks } = ctx;
|
||||
if (!updatedBlocks || updatedBlocks.length === 0) {
|
||||
return false;
|
||||
@@ -139,7 +157,7 @@ export const updateBlockType: Command<
|
||||
return next();
|
||||
};
|
||||
|
||||
const focusBlock: Command<'updatedBlocks'> = (ctx, next) => {
|
||||
const focusBlock: Command<{ updatedBlocks: BlockModel[] }> = (ctx, next) => {
|
||||
const { updatedBlocks } = ctx;
|
||||
if (!updatedBlocks || updatedBlocks.length === 0) {
|
||||
return false;
|
||||
@@ -165,15 +183,15 @@ export const updateBlockType: Command<
|
||||
|
||||
const [result, resultCtx] = std.command
|
||||
.chain()
|
||||
.inline((_, next) => {
|
||||
.pipe((_, next) => {
|
||||
doc.captureSync();
|
||||
return next();
|
||||
})
|
||||
// update block type
|
||||
.try<'updatedBlocks'>(chain => [
|
||||
chain.inline<'updatedBlocks'>(mergeToCode),
|
||||
chain.inline<'updatedBlocks'>(appendDivider),
|
||||
chain.inline<'updatedBlocks'>((_, next) => {
|
||||
.try<{ updatedBlocks: BlockModel[] }>(chain => [
|
||||
chain.pipe(mergeToCode),
|
||||
chain.pipe(appendDivider),
|
||||
chain.pipe((_, next) => {
|
||||
const newModels: BlockModel[] = [];
|
||||
blockModels.forEach(model => {
|
||||
if (
|
||||
@@ -204,15 +222,15 @@ export const updateBlockType: Command<
|
||||
])
|
||||
// focus
|
||||
.try(chain => [
|
||||
chain.inline((_, next) => {
|
||||
chain.pipe((_, next) => {
|
||||
if (['affine:code', 'affine:divider'].includes(flavour)) {
|
||||
return next();
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
chain.inline(focusText),
|
||||
chain.inline(focusBlock),
|
||||
chain.inline((_, next) => next()),
|
||||
chain.pipe(focusText),
|
||||
chain.pipe(focusBlock),
|
||||
chain.pipe((_, next) => next()),
|
||||
])
|
||||
.run();
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import { NoteDisplayMode } from '@blocksuite/affine-model';
|
||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||
import type { Command } from '@blocksuite/block-std';
|
||||
|
||||
export const changeNoteDisplayMode: Command<
|
||||
never,
|
||||
never,
|
||||
{ noteId: string; mode: NoteDisplayMode; stopCapture?: boolean }
|
||||
> = (ctx, next) => {
|
||||
export const changeNoteDisplayMode: Command<{
|
||||
noteId: string;
|
||||
mode: NoteDisplayMode;
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
const { std, noteId, mode, stopCapture } = ctx;
|
||||
|
||||
const noteBlockModel = std.store.getBlock(noteId)?.model;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||
import type { Command } from '@blocksuite/block-std';
|
||||
|
||||
export const dedentBlockToRoot: Command<
|
||||
never,
|
||||
never,
|
||||
{
|
||||
blockId?: string;
|
||||
stopCapture?: boolean;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
import { dedentBlock } from './dedent-block';
|
||||
|
||||
export const dedentBlockToRoot: Command<{
|
||||
blockId?: string;
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
let { blockId } = ctx;
|
||||
const { std, stopCapture = true } = ctx;
|
||||
const { store } = std;
|
||||
@@ -27,7 +25,7 @@ export const dedentBlockToRoot: Command<
|
||||
if (stopCapture) store.captureSync();
|
||||
changed = true;
|
||||
}
|
||||
std.command.exec('dedentBlock', { blockId: model.id, stopCapture: true });
|
||||
std.command.exec(dedentBlock, { blockId: model.id, stopCapture: true });
|
||||
parent = store.getParent(model);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,14 +20,10 @@ import type { Command } from '@blocksuite/block-std';
|
||||
* - ddd
|
||||
* - eee
|
||||
*/
|
||||
export const dedentBlock: Command<
|
||||
never,
|
||||
never,
|
||||
{
|
||||
blockId?: string;
|
||||
stopCapture?: boolean;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
export const dedentBlock: Command<{
|
||||
blockId?: string;
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
let { blockId } = ctx;
|
||||
const { std, stopCapture = true } = ctx;
|
||||
const { store } = std;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||
|
||||
export const dedentBlocksToRoot: Command<
|
||||
never,
|
||||
never,
|
||||
{
|
||||
blockIds?: string[];
|
||||
stopCapture?: boolean;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
import { dedentBlockToRoot } from './dedent-block-to-root';
|
||||
|
||||
export const dedentBlocksToRoot: Command<{
|
||||
blockIds?: string[];
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
let { blockIds } = ctx;
|
||||
const { std, stopCapture = true } = ctx;
|
||||
const { store } = std;
|
||||
@@ -33,7 +31,7 @@ export const dedentBlocksToRoot: Command<
|
||||
const model = blockIds[i];
|
||||
const parent = store.getParent(model);
|
||||
if (parent && !matchFlavours(parent, ['affine:note'])) {
|
||||
std.command.exec('dedentBlockToRoot', {
|
||||
std.command.exec(dedentBlockToRoot, {
|
||||
blockId: model,
|
||||
stopCapture: false,
|
||||
});
|
||||
|
||||
@@ -4,14 +4,12 @@ import {
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||
|
||||
export const dedentBlocks: Command<
|
||||
never,
|
||||
never,
|
||||
{
|
||||
blockIds?: string[];
|
||||
stopCapture?: boolean;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
import { dedentBlock } from './dedent-block';
|
||||
|
||||
export const dedentBlocks: Command<{
|
||||
blockIds?: string[];
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
let { blockIds } = ctx;
|
||||
const { std, stopCapture = true } = ctx;
|
||||
const { store, selection, range, host } = std;
|
||||
@@ -72,7 +70,7 @@ export const dedentBlocks: Command<
|
||||
.slice(firstDedentIndex)
|
||||
.filter(id => !collapsedIds.includes(id));
|
||||
dedentIds.reverse().forEach(id => {
|
||||
std.command.exec('dedentBlock', { blockId: id, stopCapture: false });
|
||||
std.command.exec(dedentBlock, { blockId: id, stopCapture: false });
|
||||
});
|
||||
|
||||
const textSelection = selection.find(TextSelection);
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||
import {
|
||||
type BlockComponent,
|
||||
type Command,
|
||||
TextSelection,
|
||||
} from '@blocksuite/block-std';
|
||||
|
||||
export const focusBlockEnd: Command<'focusBlock'> = (ctx, next) => {
|
||||
export const focusBlockEnd: Command<{
|
||||
focusBlock?: BlockComponent;
|
||||
}> = (ctx, next) => {
|
||||
const { focusBlock, std } = ctx;
|
||||
if (!focusBlock || !focusBlock.model.text) return;
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||
import {
|
||||
type BlockComponent,
|
||||
type Command,
|
||||
TextSelection,
|
||||
} from '@blocksuite/block-std';
|
||||
|
||||
export const focusBlockStart: Command<'focusBlock'> = (ctx, next) => {
|
||||
export const focusBlockStart: Command<{
|
||||
focusBlock?: BlockComponent;
|
||||
}> = (ctx, next) => {
|
||||
const { focusBlock, std } = ctx;
|
||||
if (!focusBlock || !focusBlock.model.text) return;
|
||||
|
||||
|
||||
@@ -21,14 +21,10 @@ import type { Command } from '@blocksuite/block-std';
|
||||
* - ddd
|
||||
* - eee
|
||||
*/
|
||||
export const indentBlock: Command<
|
||||
never,
|
||||
never,
|
||||
{
|
||||
blockId?: string;
|
||||
stopCapture?: boolean;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
export const indentBlock: Command<{
|
||||
blockId?: string;
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
let { blockId } = ctx;
|
||||
const { std, stopCapture = true } = ctx;
|
||||
const { store } = std;
|
||||
|
||||
@@ -5,14 +5,12 @@ import {
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||
|
||||
export const indentBlocks: Command<
|
||||
never,
|
||||
never,
|
||||
{
|
||||
blockIds?: string[];
|
||||
stopCapture?: boolean;
|
||||
}
|
||||
> = (ctx, next) => {
|
||||
import { indentBlock } from './indent-block';
|
||||
|
||||
export const indentBlocks: Command<{
|
||||
blockIds?: string[];
|
||||
stopCapture?: boolean;
|
||||
}> = (ctx, next) => {
|
||||
let { blockIds } = ctx;
|
||||
const { std, stopCapture = true } = ctx;
|
||||
const { store, selection, range, host } = std;
|
||||
@@ -95,7 +93,7 @@ export const indentBlocks: Command<
|
||||
}
|
||||
|
||||
indentIds.forEach(id => {
|
||||
std.command.exec('indentBlock', { blockId: id, stopCapture: false });
|
||||
std.command.exec(indentBlock, { blockId: id, stopCapture: false });
|
||||
});
|
||||
|
||||
{
|
||||
|
||||
@@ -1,42 +1,12 @@
|
||||
import {
|
||||
getBlockIndexCommand,
|
||||
getBlockSelectionsCommand,
|
||||
getNextBlockCommand,
|
||||
getPrevBlockCommand,
|
||||
getSelectedBlocksCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import type { BlockCommands } from '@blocksuite/block-std';
|
||||
|
||||
import { updateBlockType } from './block-type.js';
|
||||
import { changeNoteDisplayMode } from './change-note-display-mode.js';
|
||||
import { dedentBlock } from './dedent-block.js';
|
||||
import { dedentBlockToRoot } from './dedent-block-to-root.js';
|
||||
import { dedentBlocks } from './dedent-blocks.js';
|
||||
import { dedentBlocksToRoot } from './dedent-blocks-to-root.js';
|
||||
import { focusBlockEnd } from './focus-block-end.js';
|
||||
import { focusBlockStart } from './focus-block-start.js';
|
||||
import { indentBlock } from './indent-block.js';
|
||||
import { indentBlocks } from './indent-blocks.js';
|
||||
import { selectBlock } from './select-block.js';
|
||||
import { selectBlocksBetween } from './select-blocks-between.js';
|
||||
|
||||
export const commands: BlockCommands = {
|
||||
// block
|
||||
getBlockIndex: getBlockIndexCommand,
|
||||
getPrevBlock: getPrevBlockCommand,
|
||||
getNextBlock: getNextBlockCommand,
|
||||
getSelectedBlocks: getSelectedBlocksCommand,
|
||||
getBlockSelections: getBlockSelectionsCommand,
|
||||
selectBlock,
|
||||
selectBlocksBetween,
|
||||
focusBlockStart,
|
||||
focusBlockEnd,
|
||||
updateBlockType,
|
||||
indentBlock,
|
||||
dedentBlock,
|
||||
indentBlocks,
|
||||
dedentBlocks,
|
||||
dedentBlockToRoot,
|
||||
dedentBlocksToRoot,
|
||||
changeNoteDisplayMode,
|
||||
};
|
||||
export { updateBlockType } from './block-type.js';
|
||||
export { changeNoteDisplayMode } from './change-note-display-mode.js';
|
||||
export { dedentBlock } from './dedent-block.js';
|
||||
export { dedentBlockToRoot } from './dedent-block-to-root.js';
|
||||
export { dedentBlocks } from './dedent-blocks.js';
|
||||
export { dedentBlocksToRoot } from './dedent-blocks-to-root.js';
|
||||
export { focusBlockEnd } from './focus-block-end.js';
|
||||
export { focusBlockStart } from './focus-block-start.js';
|
||||
export { indentBlock } from './indent-block.js';
|
||||
export { indentBlocks } from './indent-blocks.js';
|
||||
export { selectBlock } from './select-block.js';
|
||||
export { selectBlocksBetween } from './select-blocks-between.js';
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { BlockSelection, type Command } from '@blocksuite/block-std';
|
||||
import {
|
||||
type BlockComponent,
|
||||
BlockSelection,
|
||||
type Command,
|
||||
} from '@blocksuite/block-std';
|
||||
|
||||
export const selectBlock: Command<'focusBlock'> = (ctx, next) => {
|
||||
export const selectBlock: Command<{
|
||||
focusBlock?: BlockComponent;
|
||||
}> = (ctx, next) => {
|
||||
const { focusBlock, std } = ctx;
|
||||
if (!focusBlock) {
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { BlockSelection, type Command } from '@blocksuite/block-std';
|
||||
import {
|
||||
type BlockComponent,
|
||||
BlockSelection,
|
||||
type Command,
|
||||
} from '@blocksuite/block-std';
|
||||
|
||||
export const selectBlocksBetween: Command<
|
||||
'focusBlock' | 'anchorBlock',
|
||||
never,
|
||||
{ tail: boolean }
|
||||
> = (ctx, next) => {
|
||||
export const selectBlocksBetween: Command<{
|
||||
focusBlock?: BlockComponent;
|
||||
anchorBlock?: BlockComponent;
|
||||
tail: boolean;
|
||||
}> = (ctx, next) => {
|
||||
const { focusBlock, anchorBlock, tail } = ctx;
|
||||
if (!focusBlock || !anchorBlock) {
|
||||
return;
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
import type { BlockComponent } from '@blocksuite/block-std';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
|
||||
import type { updateBlockType } from './commands/block-type';
|
||||
import type { changeNoteDisplayMode } from './commands/change-note-display-mode';
|
||||
import type { dedentBlock } from './commands/dedent-block';
|
||||
import type { dedentBlockToRoot } from './commands/dedent-block-to-root';
|
||||
import type { dedentBlocks } from './commands/dedent-blocks';
|
||||
import type { dedentBlocksToRoot } from './commands/dedent-blocks-to-root';
|
||||
import type { focusBlockEnd } from './commands/focus-block-end';
|
||||
import type { focusBlockStart } from './commands/focus-block-start';
|
||||
import type { indentBlock } from './commands/indent-block';
|
||||
import type { indentBlocks } from './commands/indent-blocks';
|
||||
import type { selectBlock } from './commands/select-block';
|
||||
import type { selectBlocksBetween } from './commands/select-blocks-between';
|
||||
import type { NoteConfig } from './config';
|
||||
import { NoteBlockComponent } from './note-block';
|
||||
import {
|
||||
@@ -29,25 +14,6 @@ export function effects() {
|
||||
|
||||
declare global {
|
||||
namespace BlockSuite {
|
||||
interface Commands {
|
||||
selectBlock: typeof selectBlock;
|
||||
selectBlocksBetween: typeof selectBlocksBetween;
|
||||
focusBlockStart: typeof focusBlockStart;
|
||||
focusBlockEnd: typeof focusBlockEnd;
|
||||
indentBlocks: typeof indentBlocks;
|
||||
dedentBlock: typeof dedentBlock;
|
||||
dedentBlocksToRoot: typeof dedentBlocksToRoot;
|
||||
dedentBlocks: typeof dedentBlocks;
|
||||
indentBlock: typeof indentBlock;
|
||||
updateBlockType: typeof updateBlockType;
|
||||
dedentBlockToRoot: typeof dedentBlockToRoot;
|
||||
changeNoteDisplayMode: typeof changeNoteDisplayMode;
|
||||
}
|
||||
interface CommandContext {
|
||||
focusBlock?: BlockComponent | null;
|
||||
anchorBlock?: BlockComponent | null;
|
||||
updatedBlocks?: BlockModel[];
|
||||
}
|
||||
interface BlockServices {
|
||||
'affine:note': NoteBlockService;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,34 @@
|
||||
import { textConversionConfigs } from '@blocksuite/affine-components/rich-text';
|
||||
import { NoteBlockSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
getBlockSelectionsCommand,
|
||||
getNextBlockCommand,
|
||||
getPrevBlockCommand,
|
||||
getTextSelectionCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
type BlockComponent,
|
||||
BlockSelection,
|
||||
BlockService,
|
||||
type BlockStdScope,
|
||||
type Chain,
|
||||
TextSelection,
|
||||
type UIEventHandler,
|
||||
type UIEventStateContext,
|
||||
} from '@blocksuite/block-std';
|
||||
import type { BaseSelection, BlockModel } from '@blocksuite/store';
|
||||
|
||||
import {
|
||||
dedentBlocks,
|
||||
dedentBlocksToRoot,
|
||||
focusBlockEnd,
|
||||
focusBlockStart,
|
||||
indentBlocks,
|
||||
selectBlock,
|
||||
selectBlocksBetween,
|
||||
updateBlockType,
|
||||
} from './commands';
|
||||
import { moveBlockConfigs } from './move-block';
|
||||
import { quickActionConfig } from './quick-action';
|
||||
|
||||
@@ -76,13 +93,13 @@ export class NoteBlockService extends BlockService {
|
||||
ctx.get('defaultState').event.preventDefault();
|
||||
const [result] = this._std.command
|
||||
.chain()
|
||||
.updateBlockType({
|
||||
.pipe(updateBlockType, {
|
||||
flavour: item.flavour,
|
||||
props: {
|
||||
type: item.type,
|
||||
},
|
||||
})
|
||||
.inline((ctx, next) => {
|
||||
.pipe((ctx, next) => {
|
||||
const newModels = ctx.updatedBlocks;
|
||||
if (!newModels) {
|
||||
return;
|
||||
@@ -145,7 +162,7 @@ export class NoteBlockService extends BlockService {
|
||||
|
||||
const [result] = this._std.command
|
||||
.chain()
|
||||
.inline((_, next) => {
|
||||
.pipe((_, next) => {
|
||||
this._reset();
|
||||
return next();
|
||||
})
|
||||
@@ -154,16 +171,16 @@ export class NoteBlockService extends BlockService {
|
||||
// 1. is paragraph, list, code block - follow the default behavior
|
||||
// 2. is not - select the next block (use block selection instead of text selection)
|
||||
cmd
|
||||
.getTextSelection()
|
||||
.inline<'currentSelectionPath'>((ctx, next) => {
|
||||
.pipe(getTextSelectionCommand)
|
||||
.pipe<{ currentSelectionPath: string }>((ctx, next) => {
|
||||
const currentTextSelection = ctx.currentTextSelection;
|
||||
if (!currentTextSelection) {
|
||||
return;
|
||||
}
|
||||
return next({ currentSelectionPath: currentTextSelection.blockId });
|
||||
})
|
||||
.getNextBlock()
|
||||
.inline((ctx, next) => {
|
||||
.pipe(getNextBlockCommand)
|
||||
.pipe((ctx, next) => {
|
||||
const { nextBlock } = ctx;
|
||||
|
||||
if (!nextBlock) {
|
||||
@@ -177,13 +194,9 @@ export class NoteBlockService extends BlockService {
|
||||
'affine:code',
|
||||
])
|
||||
) {
|
||||
this._std.command
|
||||
.chain()
|
||||
.with({
|
||||
focusBlock: nextBlock,
|
||||
})
|
||||
.selectBlock()
|
||||
.run();
|
||||
this._std.command.exec(selectBlock, {
|
||||
focusBlock: nextBlock,
|
||||
});
|
||||
}
|
||||
|
||||
return next({});
|
||||
@@ -193,8 +206,8 @@ export class NoteBlockService extends BlockService {
|
||||
// 1. is paragraph, list, code block - focus it
|
||||
// 2. is not - select it using block selection
|
||||
cmd
|
||||
.getBlockSelections()
|
||||
.inline<'currentSelectionPath'>((ctx, next) => {
|
||||
.pipe(getBlockSelectionsCommand)
|
||||
.pipe<{ currentSelectionPath: string }>((ctx, next) => {
|
||||
const currentBlockSelections = ctx.currentBlockSelections;
|
||||
const blockSelection = currentBlockSelections?.at(-1);
|
||||
if (!blockSelection) {
|
||||
@@ -202,8 +215,8 @@ export class NoteBlockService extends BlockService {
|
||||
}
|
||||
return next({ currentSelectionPath: blockSelection.blockId });
|
||||
})
|
||||
.getNextBlock()
|
||||
.inline<'focusBlock'>((ctx, next) => {
|
||||
.pipe(getNextBlockCommand)
|
||||
.pipe<{ focusBlock: BlockComponent }>((ctx, next) => {
|
||||
const { nextBlock } = ctx;
|
||||
if (!nextBlock) {
|
||||
return;
|
||||
@@ -217,18 +230,15 @@ export class NoteBlockService extends BlockService {
|
||||
'affine:code',
|
||||
])
|
||||
) {
|
||||
this._std.command
|
||||
.chain()
|
||||
.focusBlockStart({ focusBlock: nextBlock })
|
||||
.run();
|
||||
this._std.command.exec(focusBlockStart, {
|
||||
focusBlock: nextBlock,
|
||||
});
|
||||
return next();
|
||||
}
|
||||
|
||||
this._std.command
|
||||
.chain()
|
||||
.with({ focusBlock: nextBlock })
|
||||
.selectBlock()
|
||||
.run();
|
||||
this._std.command.exec(selectBlock, {
|
||||
focusBlock: nextBlock,
|
||||
});
|
||||
return next();
|
||||
}),
|
||||
])
|
||||
@@ -242,7 +252,7 @@ export class NoteBlockService extends BlockService {
|
||||
|
||||
const [result] = this._std.command
|
||||
.chain()
|
||||
.inline((_, next) => {
|
||||
.pipe((_, next) => {
|
||||
this._reset();
|
||||
return next();
|
||||
})
|
||||
@@ -251,16 +261,16 @@ export class NoteBlockService extends BlockService {
|
||||
// 1. is paragraph, list, code block - follow the default behavior
|
||||
// 2. is not - select the previous block (use block selection instead of text selection)
|
||||
cmd
|
||||
.getTextSelection()
|
||||
.inline<'currentSelectionPath'>((ctx, next) => {
|
||||
.pipe(getTextSelectionCommand)
|
||||
.pipe<{ currentSelectionPath: string }>((ctx, next) => {
|
||||
const currentTextSelection = ctx.currentTextSelection;
|
||||
if (!currentTextSelection) {
|
||||
return;
|
||||
}
|
||||
return next({ currentSelectionPath: currentTextSelection.blockId });
|
||||
})
|
||||
.getPrevBlock()
|
||||
.inline((ctx, next) => {
|
||||
.pipe(getPrevBlockCommand)
|
||||
.pipe((ctx, next) => {
|
||||
const { prevBlock } = ctx;
|
||||
|
||||
if (!prevBlock) {
|
||||
@@ -274,23 +284,19 @@ export class NoteBlockService extends BlockService {
|
||||
'affine:code',
|
||||
])
|
||||
) {
|
||||
this._std.command
|
||||
.chain()
|
||||
.with({
|
||||
focusBlock: prevBlock,
|
||||
})
|
||||
.selectBlock()
|
||||
.run();
|
||||
this._std.command.exec(selectBlock, {
|
||||
focusBlock: prevBlock,
|
||||
});
|
||||
}
|
||||
|
||||
return next({});
|
||||
return next();
|
||||
}),
|
||||
// block selection - select the previous block
|
||||
// 1. is paragraph, list, code block - focus it
|
||||
// 2. is not - select it using block selection
|
||||
cmd
|
||||
.getBlockSelections()
|
||||
.inline<'currentSelectionPath'>((ctx, next) => {
|
||||
.pipe(getBlockSelectionsCommand)
|
||||
.pipe<{ currentSelectionPath: string }>((ctx, next) => {
|
||||
const currentBlockSelections = ctx.currentBlockSelections;
|
||||
const blockSelection = currentBlockSelections?.at(-1);
|
||||
if (!blockSelection) {
|
||||
@@ -298,8 +304,8 @@ export class NoteBlockService extends BlockService {
|
||||
}
|
||||
return next({ currentSelectionPath: blockSelection.blockId });
|
||||
})
|
||||
.getPrevBlock()
|
||||
.inline<'focusBlock'>((ctx, next) => {
|
||||
.pipe(getPrevBlockCommand)
|
||||
.pipe((ctx, next) => {
|
||||
const { prevBlock } = ctx;
|
||||
if (!prevBlock) {
|
||||
return;
|
||||
@@ -313,18 +319,15 @@ export class NoteBlockService extends BlockService {
|
||||
])
|
||||
) {
|
||||
event.preventDefault();
|
||||
this._std.command
|
||||
.chain()
|
||||
.focusBlockEnd({ focusBlock: prevBlock })
|
||||
.run();
|
||||
this._std.command.exec(focusBlockEnd, {
|
||||
focusBlock: prevBlock,
|
||||
});
|
||||
return next();
|
||||
}
|
||||
|
||||
this._std.command
|
||||
.chain()
|
||||
.with({ focusBlock: prevBlock })
|
||||
.selectBlock()
|
||||
.run();
|
||||
this._std.command.exec(selectBlock, {
|
||||
focusBlock: prevBlock,
|
||||
});
|
||||
return next();
|
||||
}),
|
||||
])
|
||||
@@ -333,34 +336,36 @@ export class NoteBlockService extends BlockService {
|
||||
return result;
|
||||
};
|
||||
|
||||
private readonly _onBlockShiftDown = (cmd: BlockSuite.CommandChain) => {
|
||||
private readonly _onBlockShiftDown = (cmd: Chain) => {
|
||||
return cmd
|
||||
.getBlockSelections()
|
||||
.inline<'currentSelectionPath' | 'anchorBlock'>((ctx, next) => {
|
||||
const blockSelections = ctx.currentBlockSelections;
|
||||
if (!blockSelections) {
|
||||
return;
|
||||
}
|
||||
.pipe(getBlockSelectionsCommand)
|
||||
.pipe<{ currentSelectionPath: string; anchorBlock: BlockComponent }>(
|
||||
(ctx, next) => {
|
||||
const blockSelections = ctx.currentBlockSelections;
|
||||
if (!blockSelections) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._anchorSel) {
|
||||
this._anchorSel = blockSelections.at(-1) ?? null;
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
return;
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
this._anchorSel = blockSelections.at(-1) ?? null;
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
return;
|
||||
}
|
||||
|
||||
const anchorBlock = ctx.std.view.getBlock(this._anchorSel.blockId);
|
||||
if (!anchorBlock) {
|
||||
return;
|
||||
const anchorBlock = ctx.std.view.getBlock(this._anchorSel.blockId);
|
||||
if (!anchorBlock) {
|
||||
return;
|
||||
}
|
||||
return next({
|
||||
anchorBlock,
|
||||
currentSelectionPath:
|
||||
this._focusBlock?.blockId ?? anchorBlock?.blockId,
|
||||
});
|
||||
}
|
||||
return next({
|
||||
anchorBlock,
|
||||
currentSelectionPath:
|
||||
this._focusBlock?.blockId ?? anchorBlock?.blockId,
|
||||
});
|
||||
})
|
||||
.getNextBlock({})
|
||||
.inline<'focusBlock'>((ctx, next) => {
|
||||
)
|
||||
.pipe(getNextBlockCommand)
|
||||
.pipe<{ focusBlock: BlockComponent }>((ctx, next) => {
|
||||
const nextBlock = ctx.nextBlock;
|
||||
if (!nextBlock) {
|
||||
return;
|
||||
@@ -370,35 +375,37 @@ export class NoteBlockService extends BlockService {
|
||||
focusBlock: this._focusBlock,
|
||||
});
|
||||
})
|
||||
.selectBlocksBetween({ tail: true });
|
||||
.pipe(selectBlocksBetween, { tail: true });
|
||||
};
|
||||
|
||||
private readonly _onBlockShiftUp = (cmd: BlockSuite.CommandChain) => {
|
||||
private readonly _onBlockShiftUp = (cmd: Chain) => {
|
||||
return cmd
|
||||
.getBlockSelections()
|
||||
.inline<'currentSelectionPath' | 'anchorBlock'>((ctx, next) => {
|
||||
const blockSelections = ctx.currentBlockSelections;
|
||||
if (!blockSelections) {
|
||||
return;
|
||||
.pipe(getBlockSelectionsCommand)
|
||||
.pipe<{ currentSelectionPath: string; anchorBlock: BlockComponent }>(
|
||||
(ctx, next) => {
|
||||
const blockSelections = ctx.currentBlockSelections;
|
||||
if (!blockSelections) {
|
||||
return;
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
this._anchorSel = blockSelections.at(0) ?? null;
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
return;
|
||||
}
|
||||
const anchorBlock = ctx.std.view.getBlock(this._anchorSel.blockId);
|
||||
if (!anchorBlock) {
|
||||
return;
|
||||
}
|
||||
return next({
|
||||
anchorBlock,
|
||||
currentSelectionPath:
|
||||
this._focusBlock?.blockId ?? anchorBlock?.blockId,
|
||||
});
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
this._anchorSel = blockSelections.at(0) ?? null;
|
||||
}
|
||||
if (!this._anchorSel) {
|
||||
return;
|
||||
}
|
||||
const anchorBlock = ctx.std.view.getBlock(this._anchorSel.blockId);
|
||||
if (!anchorBlock) {
|
||||
return;
|
||||
}
|
||||
return next({
|
||||
anchorBlock,
|
||||
currentSelectionPath:
|
||||
this._focusBlock?.blockId ?? anchorBlock?.blockId,
|
||||
});
|
||||
})
|
||||
.getPrevBlock({})
|
||||
.inline((ctx, next) => {
|
||||
)
|
||||
.pipe(getPrevBlockCommand)
|
||||
.pipe((ctx, next) => {
|
||||
const prevBlock = ctx.prevBlock;
|
||||
if (!prevBlock) {
|
||||
return;
|
||||
@@ -408,15 +415,15 @@ export class NoteBlockService extends BlockService {
|
||||
focusBlock: this._focusBlock,
|
||||
});
|
||||
})
|
||||
.selectBlocksBetween({ tail: false });
|
||||
.pipe(selectBlocksBetween, { tail: false });
|
||||
};
|
||||
|
||||
private readonly _onEnter = (ctx: UIEventStateContext) => {
|
||||
const event = ctx.get('defaultState').event;
|
||||
const [result] = this._std.command
|
||||
.chain()
|
||||
.getBlockSelections()
|
||||
.inline((ctx, next) => {
|
||||
.pipe(getBlockSelectionsCommand)
|
||||
.pipe((ctx, next) => {
|
||||
const blockSelection = ctx.currentBlockSelections?.at(-1);
|
||||
if (!blockSelection) {
|
||||
return;
|
||||
@@ -466,8 +473,8 @@ export class NoteBlockService extends BlockService {
|
||||
private readonly _onEsc = () => {
|
||||
const [result] = this._std.command
|
||||
.chain()
|
||||
.getBlockSelections()
|
||||
.inline((ctx, next) => {
|
||||
.pipe(getBlockSelectionsCommand)
|
||||
.pipe((ctx, next) => {
|
||||
const blockSelection = ctx.currentBlockSelections?.at(-1);
|
||||
if (!blockSelection) {
|
||||
return;
|
||||
@@ -556,7 +563,7 @@ export class NoteBlockService extends BlockService {
|
||||
...this._bindQuickActionHotKey(),
|
||||
...this._bindTextConversionHotKey(),
|
||||
Tab: ctx => {
|
||||
const { success } = this.std.command.exec('indentBlocks');
|
||||
const [success] = this.std.command.exec(indentBlocks);
|
||||
|
||||
if (!success) return;
|
||||
|
||||
@@ -564,7 +571,7 @@ export class NoteBlockService extends BlockService {
|
||||
return true;
|
||||
},
|
||||
'Shift-Tab': ctx => {
|
||||
const { success } = this.std.command.exec('dedentBlocks');
|
||||
const [success] = this.std.command.exec(dedentBlocks);
|
||||
|
||||
if (!success) return;
|
||||
|
||||
@@ -572,7 +579,7 @@ export class NoteBlockService extends BlockService {
|
||||
return true;
|
||||
},
|
||||
'Mod-Backspace': ctx => {
|
||||
const { success } = this.std.command.exec('dedentBlocksToRoot');
|
||||
const [success] = this.std.command.exec(dedentBlocksToRoot);
|
||||
|
||||
if (!success) return;
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
BlockViewExtension,
|
||||
CommandExtension,
|
||||
FlavourExtension,
|
||||
} from '@blocksuite/block-std';
|
||||
import { BlockViewExtension, FlavourExtension } from '@blocksuite/block-std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
import { literal } from 'lit/static-html.js';
|
||||
|
||||
@@ -10,13 +6,11 @@ import {
|
||||
DocNoteBlockAdapterExtensions,
|
||||
EdgelessNoteBlockAdapterExtensions,
|
||||
} from './adapters/index.js';
|
||||
import { commands } from './commands/index.js';
|
||||
import { NoteBlockService } from './note-service.js';
|
||||
|
||||
export const NoteBlockSpec: ExtensionType[] = [
|
||||
FlavourExtension('affine:note'),
|
||||
NoteBlockService,
|
||||
CommandExtension(commands),
|
||||
BlockViewExtension('affine:note', literal`affine-note`),
|
||||
DocNoteBlockAdapterExtensions,
|
||||
].flat();
|
||||
@@ -24,7 +18,6 @@ export const NoteBlockSpec: ExtensionType[] = [
|
||||
export const EdgelessNoteBlockSpec: ExtensionType[] = [
|
||||
FlavourExtension('affine:note'),
|
||||
NoteBlockService,
|
||||
CommandExtension(commands),
|
||||
BlockViewExtension('affine:note', literal`affine-edgeless-note`),
|
||||
EdgelessNoteBlockAdapterExtensions,
|
||||
].flat();
|
||||
|
||||
@@ -4,6 +4,10 @@ import {
|
||||
notifyDocCreated,
|
||||
promptDocTitle,
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
draftSelectedModelsCommand,
|
||||
getSelectedModelsCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||
|
||||
export interface QuickActionConfig {
|
||||
@@ -18,23 +22,20 @@ export const quickActionConfig: QuickActionConfig[] = [
|
||||
id: 'convert-to-linked-doc',
|
||||
hotkey: `Mod-Shift-l`,
|
||||
showWhen: std => {
|
||||
const [_, ctx] = std.command
|
||||
.chain()
|
||||
.getSelectedModels({
|
||||
types: ['block'],
|
||||
})
|
||||
.run();
|
||||
const [_, ctx] = std.command.exec(getSelectedModelsCommand, {
|
||||
types: ['block'],
|
||||
});
|
||||
const { selectedModels } = ctx;
|
||||
return !!selectedModels && selectedModels.length > 0;
|
||||
},
|
||||
action: std => {
|
||||
const [_, ctx] = std.command
|
||||
.chain()
|
||||
.getSelectedModels({
|
||||
.pipe(getSelectedModelsCommand, {
|
||||
types: ['block'],
|
||||
mode: 'flat',
|
||||
})
|
||||
.draftSelectedModels()
|
||||
.pipe(draftSelectedModelsCommand)
|
||||
.run();
|
||||
const { selectedModels, draftedModels } = ctx;
|
||||
if (!selectedModels) return;
|
||||
|
||||
Reference in New Issue
Block a user