mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
feat(editor): add isLocal flag in blockUpdated subject (#10799)
This commit is contained in:
@@ -43,11 +43,11 @@ export class Block {
|
||||
) {
|
||||
const onChange = !options.onChange
|
||||
? undefined
|
||||
: (key: string) => {
|
||||
: (key: string, isLocal: boolean) => {
|
||||
if (!this._syncController || !this.model) {
|
||||
return;
|
||||
}
|
||||
options.onChange?.(this, key);
|
||||
options.onChange?.(this, key, isLocal);
|
||||
};
|
||||
const flavour = yBlock.get('sys:flavour') as string;
|
||||
const blockSchema = this.schema.get(flavour);
|
||||
|
||||
@@ -25,7 +25,7 @@ export class FlatSyncController {
|
||||
readonly schema: Schema,
|
||||
readonly yBlock: YBlock,
|
||||
readonly doc?: Store,
|
||||
readonly onChange?: (key: string) => void
|
||||
readonly onChange?: (key: string, isLocal: boolean) => void
|
||||
) {
|
||||
const { id, flavour, version, yChildren, props } = this._parseYBlock();
|
||||
|
||||
|
||||
@@ -42,6 +42,13 @@ export class SyncController {
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
const isLocal =
|
||||
!this.yBlock.doc ||
|
||||
!event.transaction.origin ||
|
||||
event.transaction.origin instanceof Y.UndoManager ||
|
||||
event.transaction.origin.proxy
|
||||
? true
|
||||
: event.transaction.origin === this.yBlock.doc.clientID;
|
||||
if (type.action === 'update' || type.action === 'add') {
|
||||
const value = this.yBlock.get(key);
|
||||
const keyName = key.replace('prop:', '');
|
||||
@@ -57,7 +64,7 @@ export class SyncController {
|
||||
}
|
||||
});
|
||||
});
|
||||
this.onChange?.(keyName);
|
||||
this.onChange?.(keyName, isLocal);
|
||||
return;
|
||||
}
|
||||
if (type.action === 'delete') {
|
||||
@@ -70,7 +77,7 @@ export class SyncController {
|
||||
this.model[`${keyName}$`].value = undefined;
|
||||
}
|
||||
});
|
||||
this.onChange?.(keyName);
|
||||
this.onChange?.(keyName, isLocal);
|
||||
return;
|
||||
}
|
||||
});
|
||||
@@ -105,7 +112,7 @@ export class SyncController {
|
||||
readonly schema: Schema,
|
||||
readonly yBlock: YBlock,
|
||||
readonly doc?: Store,
|
||||
readonly onChange?: (key: string) => void
|
||||
readonly onChange?: (key: string, isLocal: boolean) => void
|
||||
) {
|
||||
const { id, flavour, version, yChildren, props } = this._parseYBlock();
|
||||
|
||||
@@ -178,7 +185,7 @@ export class SyncController {
|
||||
if (this._stashed.has(p)) {
|
||||
setValue(target, p, value);
|
||||
const result = Reflect.set(target, p, value, receiver);
|
||||
this.onChange?.(p);
|
||||
this.onChange?.(p, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -222,8 +229,8 @@ export class SyncController {
|
||||
|
||||
private _getPropsProxy(name: string, value: unknown) {
|
||||
return createYProxy(value, {
|
||||
onChange: () => {
|
||||
this.onChange?.(name);
|
||||
onChange: (_, isLocal) => {
|
||||
this.onChange?.(name, isLocal);
|
||||
const signalKey = `${name}$`;
|
||||
if (signalKey in this.model) {
|
||||
this._mutex(() => {
|
||||
@@ -344,12 +351,12 @@ export class SyncController {
|
||||
},
|
||||
set: (target, p, value, receiver) => {
|
||||
const result = Reflect.set(target, p, value, receiver);
|
||||
this.onChange?.(prop);
|
||||
this.onChange?.(prop, true);
|
||||
return result;
|
||||
},
|
||||
deleteProperty: (target, p) => {
|
||||
const result = Reflect.deleteProperty(target, p);
|
||||
this.onChange?.(prop);
|
||||
this.onChange?.(prop, true);
|
||||
return result;
|
||||
},
|
||||
});
|
||||
@@ -365,12 +372,12 @@ export class SyncController {
|
||||
return Reflect.set(target, p, value, receiver);
|
||||
}
|
||||
const result = Reflect.set(target, p, value, receiver);
|
||||
this.onChange?.(prop);
|
||||
this.onChange?.(prop, true);
|
||||
return result;
|
||||
},
|
||||
deleteProperty: (target, p) => {
|
||||
const result = Reflect.deleteProperty(target, p);
|
||||
this.onChange?.(p as string);
|
||||
this.onChange?.(p as string, true);
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ export type YBlock = Y.Map<unknown> & {
|
||||
};
|
||||
|
||||
export type BlockOptions = {
|
||||
onChange?: (block: Block, key: string) => void;
|
||||
onChange?: (block: Block, key: string, isLocal: boolean) => void;
|
||||
};
|
||||
|
||||
export type BlockSysProps = {
|
||||
|
||||
@@ -29,10 +29,12 @@ export interface Doc {
|
||||
| {
|
||||
type: 'add';
|
||||
id: string;
|
||||
isLocal: boolean;
|
||||
}
|
||||
| {
|
||||
type: 'delete';
|
||||
id: string;
|
||||
isLocal: boolean;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -34,6 +34,31 @@ export type StoreOptions = {
|
||||
extensions?: ExtensionType[];
|
||||
};
|
||||
|
||||
export type BlockUpdatedPayload =
|
||||
| {
|
||||
type: 'add';
|
||||
id: string;
|
||||
isLocal: boolean;
|
||||
init: boolean;
|
||||
flavour: string;
|
||||
model: BlockModel;
|
||||
}
|
||||
| {
|
||||
type: 'delete';
|
||||
id: string;
|
||||
isLocal: boolean;
|
||||
flavour: string;
|
||||
parent: string;
|
||||
model: BlockModel;
|
||||
}
|
||||
| {
|
||||
type: 'update';
|
||||
id: string;
|
||||
isLocal: boolean;
|
||||
flavour: string;
|
||||
props: { key: string };
|
||||
};
|
||||
|
||||
const internalExtensions = [StoreSelectionExtension];
|
||||
|
||||
export class Store {
|
||||
@@ -76,28 +101,7 @@ export class Store {
|
||||
*/
|
||||
rootAdded: Subject<string>;
|
||||
rootDeleted: Subject<string>;
|
||||
blockUpdated: Subject<
|
||||
| {
|
||||
type: 'add';
|
||||
id: string;
|
||||
init: boolean;
|
||||
flavour: string;
|
||||
model: BlockModel;
|
||||
}
|
||||
| {
|
||||
type: 'delete';
|
||||
id: string;
|
||||
flavour: string;
|
||||
parent: string;
|
||||
model: BlockModel;
|
||||
}
|
||||
| {
|
||||
type: 'update';
|
||||
id: string;
|
||||
flavour: string;
|
||||
props: { key: string };
|
||||
}
|
||||
>;
|
||||
blockUpdated: Subject<BlockUpdatedPayload>;
|
||||
};
|
||||
|
||||
updateBlock: {
|
||||
@@ -357,7 +361,7 @@ export class Store {
|
||||
if (id in this._blocks.peek()) {
|
||||
return;
|
||||
}
|
||||
this._onBlockAdded(id, true);
|
||||
this._onBlockAdded(id, false, true);
|
||||
});
|
||||
|
||||
this._subscribeToSlots();
|
||||
@@ -365,31 +369,18 @@ export class Store {
|
||||
|
||||
private readonly _subscribeToSlots = () => {
|
||||
this.disposableGroup.add(
|
||||
this._doc.slots.yBlockUpdated.subscribe(
|
||||
({ type, id }: { type: string; id: string }) => {
|
||||
switch (type) {
|
||||
case 'add': {
|
||||
this._onBlockAdded(id);
|
||||
return;
|
||||
}
|
||||
case 'delete': {
|
||||
this._onBlockRemoved(id);
|
||||
return;
|
||||
}
|
||||
case 'update': {
|
||||
const block = this.getBlock(id);
|
||||
if (!block) return;
|
||||
this.slots.blockUpdated.next({
|
||||
type: 'update',
|
||||
id,
|
||||
flavour: block.flavour,
|
||||
props: { key: 'content' },
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._doc.slots.yBlockUpdated.subscribe(({ type, id, isLocal }) => {
|
||||
switch (type) {
|
||||
case 'add': {
|
||||
this._onBlockAdded(id, isLocal, false);
|
||||
return;
|
||||
}
|
||||
case 'delete': {
|
||||
this._onBlockRemoved(id, isLocal);
|
||||
return;
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
this.disposableGroup.add(this.slots.ready);
|
||||
this.disposableGroup.add(this.slots.blockUpdated);
|
||||
@@ -414,7 +405,7 @@ export class Store {
|
||||
return fn(parent, index);
|
||||
}
|
||||
|
||||
private _onBlockAdded(id: string, init = false) {
|
||||
private _onBlockAdded(id: string, isLocal: boolean, init: boolean) {
|
||||
try {
|
||||
if (id in this._blocks.peek()) {
|
||||
return;
|
||||
@@ -426,7 +417,7 @@ export class Store {
|
||||
}
|
||||
|
||||
const options: BlockOptions = {
|
||||
onChange: (block, key) => {
|
||||
onChange: (block, key, isLocal) => {
|
||||
if (key) {
|
||||
block.model.propsUpdated.next({ key });
|
||||
}
|
||||
@@ -436,6 +427,7 @@ export class Store {
|
||||
id,
|
||||
flavour: block.flavour,
|
||||
props: { key },
|
||||
isLocal,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -459,6 +451,7 @@ export class Store {
|
||||
init,
|
||||
flavour: block.model.flavour,
|
||||
model: block.model,
|
||||
isLocal,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('An error occurred while adding block:');
|
||||
@@ -466,7 +459,7 @@ export class Store {
|
||||
}
|
||||
}
|
||||
|
||||
private _onBlockRemoved(id: string) {
|
||||
private _onBlockRemoved(id: string, isLocal: boolean) {
|
||||
try {
|
||||
const block = this.getBlock(id);
|
||||
if (!block) return;
|
||||
@@ -481,6 +474,7 @@ export class Store {
|
||||
flavour: block.flavour,
|
||||
parent: this.getParent(block.model)?.id ?? '',
|
||||
model: block.model,
|
||||
isLocal,
|
||||
});
|
||||
|
||||
const { [id]: _, ...blocks } = this._blocks.peek();
|
||||
|
||||
Reference in New Issue
Block a user