You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-06-24 23:26:50 +02:00
All: Use Lerna to manage monorepo
This commit is contained in:
129
packages/lib/eventManager.ts
Normal file
129
packages/lib/eventManager.ts
Normal file
@ -0,0 +1,129 @@
|
||||
const events = require('events');
|
||||
|
||||
class EventManager {
|
||||
|
||||
private emitter_:any;
|
||||
private appStatePrevious_:any;
|
||||
private appStateWatchedProps_:string[];
|
||||
private appStateListeners_:any;
|
||||
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.emitter_ = new events.EventEmitter();
|
||||
|
||||
this.appStatePrevious_ = {};
|
||||
this.appStateWatchedProps_ = [];
|
||||
this.appStateListeners_ = {};
|
||||
}
|
||||
|
||||
on(eventName:string, callback:Function) {
|
||||
return this.emitter_.on(eventName, callback);
|
||||
}
|
||||
|
||||
emit(eventName:string, object:any = null) {
|
||||
return this.emitter_.emit(eventName, object);
|
||||
}
|
||||
|
||||
removeListener(eventName:string, callback:Function) {
|
||||
return this.emitter_.removeListener(eventName, callback);
|
||||
}
|
||||
|
||||
off(eventName:string, callback:Function) {
|
||||
return this.removeListener(eventName, callback);
|
||||
}
|
||||
|
||||
filterOn(filterName:string, callback:Function) {
|
||||
return this.emitter_.on(`filter:${filterName}`, callback);
|
||||
}
|
||||
|
||||
filterOff(filterName:string, callback:Function) {
|
||||
return this.removeListener(`filter:${filterName}`, callback);
|
||||
}
|
||||
|
||||
filterEmit(filterName:string, object:any) {
|
||||
// We freeze the object we pass to the listeners so that they
|
||||
// don't modify it directly. Instead they must return a
|
||||
// modified copy (or the input itself).
|
||||
let output = Object.freeze(object);
|
||||
const listeners = this.emitter_.listeners(`filter:${filterName}`);
|
||||
for (const listener of listeners) {
|
||||
const newOutput = listener(output);
|
||||
|
||||
if (newOutput === undefined) {
|
||||
throw new Error(`Filter "${filterName}": Filter must return a value or the unmodified input. Returning nothing or "undefined" is not supported.`);
|
||||
}
|
||||
|
||||
if (newOutput !== output) {
|
||||
output = Object.freeze(newOutput);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
appStateOn(propName:string, callback:Function) {
|
||||
if (!this.appStateListeners_[propName]) {
|
||||
this.appStateListeners_[propName] = [];
|
||||
this.appStateWatchedProps_.push(propName);
|
||||
}
|
||||
|
||||
this.appStateListeners_[propName].push(callback);
|
||||
}
|
||||
|
||||
appStateOff(propName:string, callback:Function) {
|
||||
if (!this.appStateListeners_[propName]) {
|
||||
throw new Error('EventManager: Trying to unregister a state prop watch for a non-watched prop (1)');
|
||||
}
|
||||
|
||||
const idx = this.appStateListeners_[propName].indexOf(callback);
|
||||
if (idx < 0) throw new Error('EventManager: Trying to unregister a state prop watch for a non-watched prop (2)');
|
||||
|
||||
this.appStateListeners_[propName].splice(idx, 1);
|
||||
}
|
||||
|
||||
stateValue_(state:any, propName:string) {
|
||||
const parts = propName.split('.');
|
||||
let s = state;
|
||||
for (const p of parts) {
|
||||
if (!(p in s)) throw new Error(`Invalid state property path: ${propName}`);
|
||||
s = s[p];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// This function works by keeping a copy of the watched props and, whenever this function
|
||||
// is called, comparing the previous and new values and emitting events if they have changed.
|
||||
// The appStateEmit function should be called from a middleware.
|
||||
appStateEmit(state:any) {
|
||||
if (!this.appStateWatchedProps_.length) return;
|
||||
|
||||
for (const propName of this.appStateWatchedProps_) {
|
||||
let emit = false;
|
||||
|
||||
const stateValue = this.stateValue_(state, propName);
|
||||
|
||||
if (!(propName in this.appStatePrevious_) || this.appStatePrevious_[propName] !== stateValue) {
|
||||
this.appStatePrevious_[propName] = stateValue;
|
||||
emit = true;
|
||||
}
|
||||
|
||||
if (emit) {
|
||||
const listeners = this.appStateListeners_[propName];
|
||||
if (!listeners || !listeners.length) continue;
|
||||
|
||||
const eventValue = Object.freeze(stateValue);
|
||||
for (const listener of listeners) {
|
||||
listener({ value: eventValue });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const eventManager = new EventManager();
|
||||
|
||||
export default eventManager;
|
Reference in New Issue
Block a user