mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-18 18:46:19 +08:00
feat: improve editor performance (#14429)
#### PR Dependency Tree * **PR #14429** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * HTML import now splits lines on <br> into separate paragraphs while preserving inline formatting. * **Bug Fixes** * Paste falls back to inserting after the first paragraph when no explicit target is found. * **Style** * Improved page-mode viewport styling for consistent content layout. * **Tests** * Added snapshot tests for <br>-based paragraph splitting; re-enabled an e2e drag-page test. * **Chores** * Deferred/deduplicated font loading, inline text caching, drag-handle/pointer optimizations, and safer inline render synchronization. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -10,25 +10,15 @@ import type { InlineRange } from '../types.js';
|
||||
import { deltaInsertsToChunks } from '../utils/delta-convert.js';
|
||||
|
||||
export class RenderService<TextAttributes extends BaseTextAttributes> {
|
||||
private readonly _onYTextChange = (
|
||||
_: Y.YTextEvent,
|
||||
transaction: Y.Transaction
|
||||
) => {
|
||||
this.editor.slots.textChange.next();
|
||||
private _pendingRemoteInlineRangeSync = false;
|
||||
|
||||
const yText = this.editor.yText;
|
||||
private _carriageReturnValidationCounter = 0;
|
||||
|
||||
if (yText.toString().includes('\r')) {
|
||||
throw new BlockSuiteError(
|
||||
ErrorCode.InlineEditorError,
|
||||
'yText must not contain "\\r" because it will break the range synchronization'
|
||||
);
|
||||
}
|
||||
|
||||
this.render();
|
||||
private _renderVersion = 0;
|
||||
|
||||
private readonly _syncRemoteInlineRange = () => {
|
||||
const inlineRange = this.editor.inlineRange$.peek();
|
||||
if (!inlineRange || transaction.local) return;
|
||||
if (!inlineRange) return;
|
||||
|
||||
const lastStartRelativePosition = this.editor.lastStartRelativePosition;
|
||||
const lastEndRelativePosition = this.editor.lastEndRelativePosition;
|
||||
@@ -50,7 +40,7 @@ export class RenderService<TextAttributes extends BaseTextAttributes> {
|
||||
|
||||
const startIndex = absoluteStart?.index;
|
||||
const endIndex = absoluteEnd?.index;
|
||||
if (!startIndex || !endIndex) return;
|
||||
if (startIndex == null || endIndex == null) return;
|
||||
|
||||
const newInlineRange: InlineRange = {
|
||||
index: startIndex,
|
||||
@@ -59,7 +49,31 @@ export class RenderService<TextAttributes extends BaseTextAttributes> {
|
||||
if (!this.editor.isValidInlineRange(newInlineRange)) return;
|
||||
|
||||
this.editor.setInlineRange(newInlineRange);
|
||||
this.editor.syncInlineRange();
|
||||
};
|
||||
|
||||
private readonly _onYTextChange = (
|
||||
_: Y.YTextEvent,
|
||||
transaction: Y.Transaction
|
||||
) => {
|
||||
this.editor.slots.textChange.next();
|
||||
|
||||
const yText = this.editor.yText;
|
||||
|
||||
if (
|
||||
(this._carriageReturnValidationCounter++ & 0x3f) === 0 &&
|
||||
yText.toString().includes('\r')
|
||||
) {
|
||||
throw new BlockSuiteError(
|
||||
ErrorCode.InlineEditorError,
|
||||
'yText must not contain "\\r" because it will break the range synchronization'
|
||||
);
|
||||
}
|
||||
|
||||
if (!transaction.local) {
|
||||
this._pendingRemoteInlineRangeSync = true;
|
||||
}
|
||||
|
||||
this.render();
|
||||
};
|
||||
|
||||
mount = () => {
|
||||
@@ -70,6 +84,7 @@ export class RenderService<TextAttributes extends BaseTextAttributes> {
|
||||
editor.disposables.add({
|
||||
dispose: () => {
|
||||
yText.unobserve(this._onYTextChange);
|
||||
this._pendingRemoteInlineRangeSync = false;
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -82,6 +97,7 @@ export class RenderService<TextAttributes extends BaseTextAttributes> {
|
||||
render = () => {
|
||||
if (!this.editor.rootElement) return;
|
||||
|
||||
const renderVersion = ++this._renderVersion;
|
||||
this._rendering = true;
|
||||
|
||||
const rootElement = this.editor.rootElement;
|
||||
@@ -152,11 +168,21 @@ export class RenderService<TextAttributes extends BaseTextAttributes> {
|
||||
this.editor
|
||||
.waitForUpdate()
|
||||
.then(() => {
|
||||
if (renderVersion !== this._renderVersion) return;
|
||||
if (this._pendingRemoteInlineRangeSync) {
|
||||
this._pendingRemoteInlineRangeSync = false;
|
||||
this._syncRemoteInlineRange();
|
||||
}
|
||||
this._rendering = false;
|
||||
this.editor.slots.renderComplete.next();
|
||||
this.editor.syncInlineRange();
|
||||
})
|
||||
.catch(console.error);
|
||||
.catch(error => {
|
||||
if (renderVersion === this._renderVersion) {
|
||||
this._rendering = false;
|
||||
}
|
||||
console.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
rerenderWholeEditor = () => {
|
||||
|
||||
Reference in New Issue
Block a user