feat(editor): type safe draft model and transformer (#10486)
This commit is contained in:
@@ -304,11 +304,12 @@ export function getDocContentWithMaxLength(doc: Store, maxlength = 500) {
|
||||
|
||||
export function getTitleFromSelectedModels(selectedModels: DraftModel[]) {
|
||||
const firstBlock = selectedModels[0];
|
||||
if (
|
||||
matchModels(firstBlock, [ParagraphBlockModel]) &&
|
||||
firstBlock.type.startsWith('h')
|
||||
) {
|
||||
return firstBlock.text.toString();
|
||||
const isParagraph = (
|
||||
model: DraftModel
|
||||
): model is DraftModel<ParagraphBlockModel> =>
|
||||
model.flavour === 'affine:paragraph';
|
||||
if (isParagraph(firstBlock) && firstBlock.type.startsWith('h')) {
|
||||
return firstBlock.text?.toString();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -394,7 +395,7 @@ export async function convertSelectedBlocksToLinkedDoc(
|
||||
'before'
|
||||
);
|
||||
// delete selected elements
|
||||
models.forEach(model => doc.deleteBlock(model));
|
||||
models.forEach(model => doc.deleteBlock(model.id));
|
||||
return linkedDoc;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
getSelectedModelsCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||
import { toDraftModel } from '@blocksuite/store';
|
||||
|
||||
export interface QuickActionConfig {
|
||||
id: string;
|
||||
@@ -45,7 +46,9 @@ export const quickActionConfig: QuickActionConfig[] = [
|
||||
std.selection.clear();
|
||||
|
||||
const doc = std.store;
|
||||
const autofill = getTitleFromSelectedModels(selectedModels);
|
||||
const autofill = getTitleFromSelectedModels(
|
||||
selectedModels.map(toDraftModel)
|
||||
);
|
||||
promptDocTitle(std, autofill)
|
||||
.then(title => {
|
||||
if (title === null) return;
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
type UIEventHandler,
|
||||
} from '@blocksuite/block-std';
|
||||
import { IS_MAC, IS_WINDOWS } from '@blocksuite/global/env';
|
||||
import { toDraftModel } from '@blocksuite/store';
|
||||
|
||||
export class PageKeyboardManager {
|
||||
private readonly _handleDelete: UIEventHandler = ctx => {
|
||||
@@ -143,7 +144,9 @@ export class PageKeyboardManager {
|
||||
}
|
||||
|
||||
const doc = rootComponent.host.doc;
|
||||
const autofill = getTitleFromSelectedModels(selectedModels);
|
||||
const autofill = getTitleFromSelectedModels(
|
||||
selectedModels.map(toDraftModel)
|
||||
);
|
||||
promptDocTitle(rootComponent.std, autofill)
|
||||
.then(title => {
|
||||
if (title === null) return;
|
||||
|
||||
@@ -64,7 +64,7 @@ import type {
|
||||
import { tableViewMeta } from '@blocksuite/data-view/view-presets';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { MoreVerticalIcon } from '@blocksuite/icons/lit';
|
||||
import { Slice } from '@blocksuite/store';
|
||||
import { Slice, toDraftModel } from '@blocksuite/store';
|
||||
import { html, type TemplateResult } from 'lit';
|
||||
|
||||
import { FormatBarContext } from './context.js';
|
||||
@@ -230,7 +230,9 @@ export function toolbarDefaultConfig(toolbar: AffineFormatBarWidget) {
|
||||
host.selection.clear();
|
||||
|
||||
const doc = host.doc;
|
||||
const autofill = getTitleFromSelectedModels(selectedModels);
|
||||
const autofill = getTitleFromSelectedModels(
|
||||
selectedModels.map(toDraftModel)
|
||||
);
|
||||
promptDocTitle(std, autofill)
|
||||
.then(async title => {
|
||||
if (title === null) return;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RootBlockModel } from '@blocksuite/affine-model';
|
||||
import type { RootBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
type BlockStdScope,
|
||||
type EditorHost,
|
||||
@@ -12,7 +12,9 @@ import type {
|
||||
TransformerSlots,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import { matchModels } from '../../utils';
|
||||
const isRootDraftModel = (
|
||||
model: DraftModel
|
||||
): model is DraftModel<RootBlockModel> => model.flavour === 'affine:root';
|
||||
|
||||
const handlePoint = (
|
||||
point: TextRangePoint,
|
||||
@@ -20,7 +22,7 @@ const handlePoint = (
|
||||
model: DraftModel
|
||||
) => {
|
||||
const { index, length } = point;
|
||||
if (matchModels(model, [RootBlockModel])) {
|
||||
if (isRootDraftModel(model)) {
|
||||
if (length === 0) return;
|
||||
(snapshot.props.title as Record<string, unknown>).delta =
|
||||
model.title.sliceToDelta(index, length + index);
|
||||
|
||||
@@ -11,7 +11,7 @@ type ModelList<T> =
|
||||
export function matchModels<
|
||||
const Model extends ConstructorType<BlockModel>[],
|
||||
U extends ModelList<Model>[number] = ModelList<Model>[number],
|
||||
>(model: unknown, expected: Model): model is U {
|
||||
>(model: BlockModel | null, expected: Model): model is U {
|
||||
return (
|
||||
!!model && expected.some(expectedModel => model instanceof expectedModel)
|
||||
);
|
||||
|
||||
@@ -1139,7 +1139,7 @@ export class DragEventWatcher {
|
||||
block.flavour === 'affine:bookmark' ||
|
||||
block.flavour.startsWith('affine:embed-'))
|
||||
) {
|
||||
store.updateBlock(block as BlockModel, {
|
||||
store.updateBlock(block.id, {
|
||||
xywh: content[idx].props.xywh,
|
||||
style: content[idx].props.style,
|
||||
});
|
||||
@@ -1164,7 +1164,7 @@ export class DragEventWatcher {
|
||||
block.flavour === 'affine:attachment' ||
|
||||
block.flavour.startsWith('affine:embed-')
|
||||
) {
|
||||
store.updateBlock(block as BlockModel, {
|
||||
store.updateBlock(block.id, {
|
||||
xywh: content[idx].props.xywh,
|
||||
style: content[idx].props.style,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user