refactor(editor): flat data for table block (#10010)

close: BS-2548
This commit is contained in:
Saul-Mirone
2025-02-10 19:09:33 +00:00
parent a5f36eb1d8
commit c6b8f2b584
9 changed files with 125 additions and 98 deletions

View File

@@ -33,6 +33,7 @@ type CreateProxyOptions = {
shouldByPassSignal: () => boolean;
byPassSignalUpdate: (fn: () => void) => void;
stashed: Set<string | number>;
initialized: () => boolean;
};
const proxySymbol = Symbol('proxy');
@@ -60,6 +61,7 @@ function createProxy(
byPassSignalUpdate,
basePath,
onChange,
initialized,
transform = (_key, value) => value,
stashed,
} = options;
@@ -73,7 +75,7 @@ function createProxy(
if (isPureObject(value) && !isProxy(value)) {
const proxy = createProxy(yMap, value as UnRecord, root, {
...options,
basePath: `${basePath}.${key}`,
basePath: basePath ? `${basePath}.${key}` : key,
});
base[key] = proxy;
}
@@ -111,6 +113,9 @@ function createProxy(
root[signalKey] = signalData;
onDispose.once(
signalData.subscribe(next => {
if (!initialized()) {
return;
}
byPassSignalUpdate(() => {
proxy[p] = next;
onChange?.(firstKey, next);
@@ -137,7 +142,7 @@ function createProxy(
if (isPureObject(value)) {
const syncYMap = () => {
yMap.forEach((_, key) => {
if (keyWithoutPrefix(key).startsWith(fullPath)) {
if (initialized() && keyWithoutPrefix(key).startsWith(fullPath)) {
yMap.delete(key);
}
});
@@ -148,13 +153,13 @@ function createProxy(
run(value, fullPath);
} else {
list.push(() => {
yMap.set(keyWithPrefix(fullPath), value);
yMap.set(keyWithPrefix(fullPath), native2Y(value));
});
}
});
};
run(value, fullPath);
if (list.length) {
if (list.length && initialized()) {
yMap.doc?.transact(
() => {
list.forEach(fn => fn());
@@ -180,7 +185,7 @@ function createProxy(
const yValue = native2Y(value);
const next = transform(firstKey, value, yValue);
if (!isStashed) {
if (!isStashed && initialized()) {
yMap.doc?.transact(
() => {
yMap.set(keyWithPrefix(fullPath), yValue);
@@ -233,7 +238,7 @@ function createProxy(
});
};
if (!isStashed) {
if (!isStashed && initialized()) {
yMap.doc?.transact(
() => {
const fullKey = keyWithPrefix(fullPath);
@@ -268,6 +273,8 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
protected readonly _source: UnRecord;
protected readonly _options?: ProxyOptions<UnRecord>;
private readonly _initialized;
private readonly _observer = (event: YMapEvent<unknown>) => {
const yMap = this._ySource;
const proxy = this._proxy;
@@ -344,9 +351,12 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
};
private readonly _createDefaultData = (): UnRecord => {
const data: UnRecord = {};
const root: UnRecord = {};
const transform = this._transform;
Array.from(this._ySource.entries()).forEach(([key, value]) => {
if (key.startsWith('sys')) {
return;
}
const keys = keyWithoutPrefix(key).split('.');
const firstKey = keys[0];
@@ -356,7 +366,8 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
} else if (value instanceof YArray) {
finalData = transform(firstKey, value.toArray(), value);
} else if (value instanceof YText) {
finalData = transform(firstKey, new Text(value), value);
const next = new Text(value);
finalData = transform(firstKey, next, value);
} else if (value instanceof YMap) {
throw new BlockSuiteError(
ErrorCode.ReactiveProxyError,
@@ -369,21 +380,25 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
void keys.reduce((acc: UnRecord, key, index) => {
if (!acc[key] && index !== allLength - 1) {
const path = keys.slice(0, index + 1).join('.');
const data = this._getProxy({} as UnRecord, path);
const data = this._getProxy({} as UnRecord, root, path);
acc[key] = data;
}
if (index === allLength - 1) {
acc[key] = finalData;
}
return acc[key] as UnRecord;
}, data);
}, root);
});
return data;
return root;
};
private readonly _getProxy = (source: UnRecord, path?: string): UnRecord => {
return createProxy(this._ySource, source, source, {
private readonly _getProxy = (
source: UnRecord,
root: UnRecord,
path?: string
): UnRecord => {
return createProxy(this._ySource, source, root, {
onDispose: this._onDispose,
shouldByPassSignal: () => this._skipNext,
byPassSignalUpdate: this._updateWithSkip,
@@ -391,6 +406,7 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
onChange: this._onChange,
transform: this._transform,
stashed: this._stashed,
initialized: () => this._initialized,
});
};
@@ -400,16 +416,20 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
private readonly _onChange?: OnChange
) {
super();
this._initialized = false;
const source = this._createDefaultData();
this._source = source;
const proxy = this._getProxy(source);
const proxy = this._getProxy(source, source);
Object.entries(source).forEach(([key, value]) => {
const signalData = signal(value);
source[`${key}$`] = signalData;
_onDispose.once(
signalData.subscribe(next => {
if (!this._initialized) {
return;
}
this._updateWithSkip(() => {
proxy[key] = next;
this._onChange?.(key, next);
@@ -420,6 +440,7 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
this._proxy = proxy;
this._ySource.observe(this._observer);
this._initialized = true;
}
pop = (prop: string): void => {