mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
fix(editor): missing signal of optional flat props (#13762)
Close https://github.com/toeverything/AFFiNE/issues/13750 #### PR Dependency Tree * **PR #13762** 👈 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** * Optional block properties are now supported (e.g., flat-table), with default values applied automatically when not set. * **Bug Fixes** * More reliable initialization and syncing of block properties, ensuring defaults appear consistently. * Change notifications now correctly reflect updates to optional/defaulted properties. * **Tests** * Added tests verifying optional property behavior, default application, syncing, and change events. <!-- end of auto-generated comment: release notes by coderabbit.ai --> #### PR Dependency Tree * **PR #13762** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal)
This commit is contained in:
@@ -51,6 +51,7 @@ const flatTableSchema = defineBlockSchema({
|
||||
textCols: {} as Record<string, Text>,
|
||||
rows: {} as Record<string, { color: string }>,
|
||||
labels: [] as Array<string>,
|
||||
optional: undefined as string | undefined,
|
||||
}),
|
||||
metadata: {
|
||||
role: 'content',
|
||||
@@ -494,6 +495,16 @@ describe('flat', () => {
|
||||
expect(model.props.textCols$.value.a.toDelta()).toEqual([
|
||||
{ insert: 'test' },
|
||||
]);
|
||||
|
||||
onChange.mockClear();
|
||||
expect(model.props).not.toHaveProperty('optional');
|
||||
expect(model.props).toHaveProperty('optional$');
|
||||
model.props.optional$.value = 'test';
|
||||
expect(model.props.optional).toBe('test');
|
||||
expect(model.props.optional$.value).toBe('test');
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledWith(expect.anything(), 'optional', true);
|
||||
expect(yBlock.get('prop:optional')).toBe('test');
|
||||
});
|
||||
|
||||
test('stash and pop', () => {
|
||||
|
||||
@@ -47,6 +47,7 @@ export class FlatSyncController {
|
||||
}
|
||||
|
||||
const model = schema.model.toModel?.() ?? new BlockModel<object>();
|
||||
const defaultProps = schema.model.props?.(internalPrimitives);
|
||||
model.schema = schema;
|
||||
|
||||
model.id = this.id;
|
||||
@@ -55,7 +56,8 @@ export class FlatSyncController {
|
||||
const reactive = new ReactiveFlatYMap(
|
||||
this.yBlock,
|
||||
model.deleted,
|
||||
this.onChange
|
||||
this.onChange,
|
||||
defaultProps
|
||||
);
|
||||
this._reactive = reactive;
|
||||
const proxy = reactive.proxy;
|
||||
@@ -66,17 +68,6 @@ export class FlatSyncController {
|
||||
model.store = this.doc;
|
||||
}
|
||||
|
||||
const defaultProps = schema.model.props?.(internalPrimitives);
|
||||
if (defaultProps) {
|
||||
Object.entries(defaultProps).forEach(([key, value]) => {
|
||||
if (key in proxy) {
|
||||
return;
|
||||
}
|
||||
if (value === undefined) return;
|
||||
proxy[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,8 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
|
||||
constructor(
|
||||
protected readonly _ySource: YMap<unknown>,
|
||||
private readonly _onDispose: Subject<void>,
|
||||
private readonly _onChange?: OnChange
|
||||
private readonly _onChange?: OnChange,
|
||||
defaultProps?: Record<string, unknown>
|
||||
) {
|
||||
super();
|
||||
this._initialized = false;
|
||||
@@ -112,7 +113,7 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
|
||||
|
||||
const proxy = this._getProxy(source, source);
|
||||
|
||||
Object.entries(source).forEach(([key, value]) => {
|
||||
const initSignals = (key: string, value: unknown) => {
|
||||
const signalData = signal(value);
|
||||
source[`${key}$`] = signalData;
|
||||
const unsubscribe = signalData.subscribe(next => {
|
||||
@@ -128,11 +129,30 @@ export class ReactiveFlatYMap extends BaseReactiveYData<
|
||||
subscription.unsubscribe();
|
||||
unsubscribe();
|
||||
});
|
||||
};
|
||||
|
||||
Object.entries(source).forEach(([key, value]) => {
|
||||
initSignals(key, value);
|
||||
});
|
||||
|
||||
if (defaultProps) {
|
||||
Object.entries(defaultProps).forEach(([key, value]) => {
|
||||
if (!(key in proxy) && value === undefined) {
|
||||
initSignals(key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._proxy = proxy;
|
||||
this._ySource.observe(this._observer);
|
||||
this._initialized = true;
|
||||
|
||||
if (defaultProps) {
|
||||
Object.entries(defaultProps).forEach(([key, value]) => {
|
||||
if (key in proxy || value === undefined) return;
|
||||
proxy[key] = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pop = (prop: string): void => {
|
||||
|
||||
Reference in New Issue
Block a user