import { Entity } from './entity'; import { DisposableImpl, Emitter } from '@gedit/utils'; /** * 实体的数据块 */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export abstract class EntityData extends DisposableImpl { static type = 'EntityData'; protected onDataChangedEmitter = new Emitter>(); protected _data: DATA = this.getDefaultData(); private _pauseChanged = false; /** * 修改后触发 */ readonly onDataChanged = this.onDataChangedEmitter.event; /** * 初始化数据 */ abstract getDefaultData(): DATA; constructor(protected readonly entity: Entity) { super(); this.toDispose.push(this.onDataChangedEmitter); } /** * data 类型 */ get type(): string { // eslint-disable-next-line @typescript-eslint/no-explicit-any if (!(this.constructor as any).type) { throw new Error('Entity Data Registry need a type: ' + this.constructor.name); } // eslint-disable-next-line @typescript-eslint/no-explicit-any return (this.constructor as any).type; } /** * 当前数据 */ get data(): DATA { return this._data; } /** * 更新单个数据 * @param key * @param value */ update(props: Partial | keyof DATA | DATA, value?: any): void { if (arguments.length === 2) { if (this._data[props as keyof DATA] !== value) { this._data[props as keyof DATA] = value; this.fireChanged(); } return; } if (this.checkChanged(props as Partial)) { if (typeof props !== 'object') { this._data = props as any; } else { this._data = { ...this._data, ...props as Partial}; } this.fireChanged(); } } /** * 检测属性是否更改, 默认采用浅比较 * @param newProps */ checkChanged(newProps: Partial | DATA): boolean { return Entity.checkDataChanged(this._data, newProps); } /** * 存储数据, 一般在关闭浏览器后需要暂时存到localStorage */ toJSON(): object { return { type: this.type, data: this.data }; } /** * 还原数据 */ fromJSON(data: object): void { this.update(data); } get pauseChanged(): boolean { return this._pauseChanged; } set pauseChanged(p) { this._pauseChanged = p; } fireChanged(): void { if (this._pauseChanged) return; this.onDataChangedEmitter.fire(this as EntityData); } } export type EntityDataProps = E['data']; export interface EntityDataRegistry { new ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] ): E readonly type: E['type'], }