feat(editor): unify block props api (#10888)
Closes: [BS-2707](https://linear.app/affine-design/issue/BS-2707/统一使用props获取和更新block-prop)
This commit is contained in:
@@ -72,7 +72,7 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
|
||||
const note = this._rootModel.children.find(
|
||||
(child): child is NoteBlockModel =>
|
||||
matchModels(child, [NoteBlockModel]) &&
|
||||
child.displayMode !== NoteDisplayMode.EdgelessOnly
|
||||
child.props.displayMode !== NoteDisplayMode.EdgelessOnly
|
||||
);
|
||||
if (note) return note;
|
||||
|
||||
@@ -89,7 +89,7 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
|
||||
|
||||
const inlineRange = this.inlineEditor?.getInlineRange();
|
||||
if (inlineRange) {
|
||||
const rightText = this._rootModel.title.split(inlineRange.index);
|
||||
const rightText = this._rootModel.props.title.split(inlineRange.index);
|
||||
const newFirstParagraphId = this.doc.addBlock(
|
||||
'affine:paragraph',
|
||||
{ text: rightText },
|
||||
@@ -129,7 +129,7 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
|
||||
|
||||
private readonly _updateTitleInMeta = () => {
|
||||
this.doc.workspace.meta.setDocMeta(this.doc.id, {
|
||||
title: this._rootModel.title.toString(),
|
||||
title: this._rootModel.props.title.toString(),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -188,14 +188,14 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
|
||||
this._updateTitleInMeta();
|
||||
this.requestUpdate();
|
||||
};
|
||||
this._rootModel.title.yText.observe(updateMetaTitle);
|
||||
this._rootModel.props.title.yText.observe(updateMetaTitle);
|
||||
this._disposables.add(() => {
|
||||
this._rootModel.title.yText.unobserve(updateMetaTitle);
|
||||
this._rootModel.props.title.yText.unobserve(updateMetaTitle);
|
||||
});
|
||||
}
|
||||
|
||||
override render() {
|
||||
const isEmpty = !this._rootModel.title.length && !this._isComposing;
|
||||
const isEmpty = !this._rootModel.props.title.length && !this._isComposing;
|
||||
|
||||
return html`
|
||||
<div
|
||||
@@ -205,7 +205,7 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
|
||||
data-block-is-title="true"
|
||||
>
|
||||
<rich-text
|
||||
.yText=${this._rootModel.title.yText}
|
||||
.yText=${this._rootModel.props.title.yText}
|
||||
.undoManager=${this.doc.history}
|
||||
.verticalScrollContainerGetter=${() => this._viewport}
|
||||
.readonly=${this.doc.readonly}
|
||||
|
||||
@@ -150,7 +150,7 @@ export class FramePanelBody extends SignalWatcher(
|
||||
private readonly _updateFrameItems = () => {
|
||||
this._frameItems = this.frames.map((frame, idx) => ({
|
||||
frame,
|
||||
frameIndex: frame.presentationIndex ?? frame.index,
|
||||
frameIndex: frame.props.presentationIndex ?? frame.props.index,
|
||||
cardIndex: idx,
|
||||
}));
|
||||
};
|
||||
@@ -307,8 +307,8 @@ export class FramePanelBody extends SignalWatcher(
|
||||
|
||||
// update selected frames index
|
||||
// make the indexes larger than the frame before and smaller than the frame after
|
||||
let before = frames[insertIndex - 1]?.presentationIndex || null;
|
||||
const after = frames[insertIndex]?.presentationIndex || null;
|
||||
let before = frames[insertIndex - 1]?.props.presentationIndex || null;
|
||||
const after = frames[insertIndex]?.props.presentationIndex || null;
|
||||
selectedFrames.forEach(frame => {
|
||||
const newIndex = generateKeyBetweenV2(before, after);
|
||||
frame.doc.updateBlock(frame, {
|
||||
@@ -352,7 +352,7 @@ export class FramePanelBody extends SignalWatcher(
|
||||
frames.forEach((frame, idx) => {
|
||||
const frameItem = {
|
||||
frame,
|
||||
frameIndex: frame.presentationIndex ?? frame.index,
|
||||
frameIndex: frame.props.presentationIndex ?? frame.props.index,
|
||||
cardIndex: idx,
|
||||
};
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ export class FrameCardTitleEditor extends WithDisposable(ShadowlessElement) {
|
||||
display: 'block',
|
||||
});
|
||||
return html`<rich-text
|
||||
.yText=${this.frameModel.title.yText}
|
||||
.yText=${this.frameModel.props.title.yText}
|
||||
.enableFormat=${false}
|
||||
.enableAutoScrollHorizontally=${true}
|
||||
.enableUndoRedo=${false}
|
||||
|
||||
@@ -116,7 +116,7 @@ export class FrameCardTitle extends WithDisposable(ShadowlessElement) {
|
||||
<span
|
||||
@click=${(e: MouseEvent) => e.stopPropagation()}
|
||||
@dblclick=${this._mountTitleEditor}
|
||||
>${this.frame.title}</span
|
||||
>${this.frame.props.title}</span
|
||||
>
|
||||
</div>
|
||||
</div>`;
|
||||
@@ -124,7 +124,7 @@ export class FrameCardTitle extends WithDisposable(ShadowlessElement) {
|
||||
|
||||
override updated(_changedProperties: PropertyValues) {
|
||||
if (_changedProperties.has('frame')) {
|
||||
this._setFrameDisposables(this.frame.title.yText);
|
||||
this._setFrameDisposables(this.frame.props.title.yText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,8 @@ export class OutlineNoteCard extends SignalWatcher(
|
||||
this.disposables.add(
|
||||
std.dnd.draggable<NoteCardEntity>({
|
||||
element: this,
|
||||
canDrag: () => this.note.displayMode !== NoteDisplayMode.EdgelessOnly,
|
||||
canDrag: () =>
|
||||
this.note.props.displayMode !== NoteDisplayMode.EdgelessOnly,
|
||||
onDragStart: () => {
|
||||
if (this.status !== 'selected') {
|
||||
this.dispatchEvent(
|
||||
@@ -139,7 +140,7 @@ export class OutlineNoteCard extends SignalWatcher(
|
||||
noteId: this.note.id,
|
||||
}),
|
||||
canDrop: () => {
|
||||
return this.note.displayMode !== NoteDisplayMode.EdgelessOnly;
|
||||
return this.note.props.displayMode !== NoteDisplayMode.EdgelessOnly;
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -167,16 +168,17 @@ export class OutlineNoteCard extends SignalWatcher(
|
||||
}
|
||||
|
||||
override render() {
|
||||
const { children, displayMode } = this.note;
|
||||
const { displayMode } = this.note.props;
|
||||
const { children } = this.note;
|
||||
const currentMode = this._getCurrentModeLabel(displayMode);
|
||||
const invisible =
|
||||
this.note.displayMode$.value === NoteDisplayMode.EdgelessOnly;
|
||||
this.note.props.displayMode$.value === NoteDisplayMode.EdgelessOnly;
|
||||
|
||||
const enableSorting = this._context.enableSorting$.value;
|
||||
|
||||
return html`
|
||||
<div
|
||||
data-visibility=${this.note.displayMode}
|
||||
data-visibility=${this.note.props.displayMode}
|
||||
data-sortable=${enableSorting}
|
||||
data-status=${this.status}
|
||||
class=${styles.outlineCard}
|
||||
|
||||
@@ -45,8 +45,8 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
|
||||
private _TextBlockPreview(block: ParagraphBlockModel | ListBlockModel) {
|
||||
const deltas: DeltaInsert<AffineTextAttributes>[] =
|
||||
block.text.yText.toDelta();
|
||||
if (!block.text.length) return nothing;
|
||||
block.props.text.yText.toDelta();
|
||||
if (!block.props.text.length) return nothing;
|
||||
const iconClass = this.disabledIcon ? styles.iconDisabled : styles.icon;
|
||||
|
||||
const previewText = deltas.map(delta => {
|
||||
@@ -90,17 +90,21 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
});
|
||||
|
||||
const headingClass =
|
||||
block.type in styles.subtypeStyles
|
||||
? styles.subtypeStyles[block.type as keyof typeof styles.subtypeStyles]
|
||||
block.props.type in styles.subtypeStyles
|
||||
? styles.subtypeStyles[
|
||||
block.props.type as keyof typeof styles.subtypeStyles
|
||||
]
|
||||
: '';
|
||||
|
||||
return html`<span
|
||||
data-testid="outline-block-preview-${block.type}"
|
||||
data-testid="outline-block-preview-${block.props.type}"
|
||||
class="${styles.text} ${styles.textGeneral} ${headingClass}"
|
||||
>${previewText}</span
|
||||
>
|
||||
${this._context.showIcons$.value
|
||||
? html`<span class=${iconClass}>${previewIconMap[block.type]}</span>`
|
||||
? html`<span class=${iconClass}
|
||||
>${previewIconMap[block.props.type]}</span
|
||||
>`
|
||||
: nothing}`;
|
||||
}
|
||||
|
||||
@@ -126,12 +130,12 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
switch (block.flavour) {
|
||||
case 'affine:page':
|
||||
assertType<RootBlockModel>(block);
|
||||
return block.title.length > 0
|
||||
return block.props.title.length > 0
|
||||
? html`<span
|
||||
data-testid="outline-block-preview-title"
|
||||
class="${styles.text} ${styles.subtypeStyles.title}"
|
||||
>
|
||||
${block.title$.value}
|
||||
${block.props.title$.value}
|
||||
</span>`
|
||||
: nothing;
|
||||
case 'affine:paragraph':
|
||||
@@ -144,7 +148,9 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
assertType<BookmarkBlockModel>(block);
|
||||
return html`
|
||||
<span class="${styles.text} ${styles.textGeneral}"
|
||||
>${block.title || block.url || placeholderMap['bookmark']}</span
|
||||
>${block.props.title ||
|
||||
block.props.url ||
|
||||
placeholderMap['bookmark']}</span
|
||||
>
|
||||
${showPreviewIcon
|
||||
? html`<span class=${iconClass}
|
||||
@@ -156,7 +162,7 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
assertType<CodeBlockModel>(block);
|
||||
return html`
|
||||
<span class="${styles.text} ${styles.textGeneral}"
|
||||
>${block.language ?? placeholderMap['code']}</span
|
||||
>${block.props.language ?? placeholderMap['code']}</span
|
||||
>
|
||||
${showPreviewIcon
|
||||
? html`<span class=${iconClass}>${previewIconMap['code']}</span>`
|
||||
@@ -166,8 +172,8 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
assertType<DatabaseBlockModel>(block);
|
||||
return html`
|
||||
<span class="${styles.text} ${styles.textGeneral}"
|
||||
>${block.title.toString().length
|
||||
? block.title.toString()
|
||||
>${block.props.title.toString().length
|
||||
? block.props.title.toString()
|
||||
: placeholderMap['database']}</span
|
||||
>
|
||||
${showPreviewIcon
|
||||
@@ -178,8 +184,8 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
assertType<ImageBlockModel>(block);
|
||||
return html`
|
||||
<span class="${styles.text} ${styles.textGeneral}"
|
||||
>${block.caption?.length
|
||||
? block.caption
|
||||
>${block.props.caption?.length
|
||||
? block.props.caption
|
||||
: placeholderMap['image']}</span
|
||||
>
|
||||
${showPreviewIcon
|
||||
@@ -190,8 +196,8 @@ export class OutlineBlockPreview extends SignalWatcher(
|
||||
assertType<AttachmentBlockModel>(block);
|
||||
return html`
|
||||
<span class="${styles.text} ${styles.textGeneral}"
|
||||
>${block.name?.length
|
||||
? block.name
|
||||
>${block.props.name?.length
|
||||
? block.props.name
|
||||
: placeholderMap['attachment']}</span
|
||||
>
|
||||
${showPreviewIcon
|
||||
|
||||
@@ -27,7 +27,7 @@ import type { TemplateResult } from 'lit';
|
||||
const _16px = { width: '16px', height: '16px' };
|
||||
|
||||
const paragraphIconMap: Record<
|
||||
ParagraphBlockModel['type'],
|
||||
ParagraphBlockModel['props']['type'],
|
||||
TemplateResult<1>
|
||||
> = {
|
||||
quote: QuoteIcon(_16px),
|
||||
@@ -54,7 +54,10 @@ export const previewIconMap = {
|
||||
attachment: AttachmentIcon(_16px),
|
||||
};
|
||||
|
||||
const paragraphPlaceholderMap: Record<ParagraphBlockModel['type'], string> = {
|
||||
const paragraphPlaceholderMap: Record<
|
||||
ParagraphBlockModel['props']['type'],
|
||||
string
|
||||
> = {
|
||||
quote: 'Quote',
|
||||
text: 'Text Block',
|
||||
h1: 'Heading 1',
|
||||
|
||||
@@ -140,13 +140,13 @@ export class MobileOutlineMenu extends SignalWatcher(
|
||||
let text = '';
|
||||
if (matchModels(item, [RootBlockModel])) {
|
||||
className = 'title';
|
||||
text = item.title$.value.toString();
|
||||
text = item.props.title$.value.toString();
|
||||
} else if (
|
||||
matchModels(item, [ParagraphBlockModel]) &&
|
||||
['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(item.type$.value)
|
||||
['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(item.props.type$.value)
|
||||
) {
|
||||
className = item.type$.value;
|
||||
text = item.text$.value.toString();
|
||||
className = item.props.type$.value;
|
||||
text = item.props.text$.value.toString();
|
||||
} else {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ export function getNotesFromDoc(
|
||||
rootModel.children.forEach(block => {
|
||||
if (!matchModels(block, [NoteBlockModel])) return;
|
||||
|
||||
if (modes.includes(block.displayMode$.value)) {
|
||||
if (modes.includes(block.props.displayMode$.value)) {
|
||||
notes.push(block);
|
||||
}
|
||||
});
|
||||
@@ -42,7 +42,7 @@ export function isHeadingBlock(
|
||||
): block is ParagraphBlockModel {
|
||||
return (
|
||||
matchModels(block, [ParagraphBlockModel]) &&
|
||||
headingKeys.has(block.type$.value)
|
||||
headingKeys.has(block.props.type$.value)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user