Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

162 lines
5.1 KiB

/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
//import { MOUNT_CLASS_TO } from "../config/debug";
import type { ArgumentTypes, SuperReturnType } from "../types";
// class EventSystem {
// wm: WeakMap<any, Record<any, Set<any>>> = new WeakMap();
// add(target: any, event: any, listener: any) {
// let listeners = this.wm.get(target);
// if (listeners === undefined) {
// listeners = {};
// }
// let listenersForEvent = listeners[event];
// if (listenersForEvent === undefined) {
// listenersForEvent = new Set();
// }
// listenersForEvent.add(listener);
// listeners[event] = listenersForEvent;
// //target.addEventListener(event, listener);
// this.wm.set(target, listeners);
// };
// remove(target: any, event: any, listener: any) {
// let listeners = this.wm.get(target);
// if (!listeners) return;
// let listenersForEvent = listeners[event];
// if (!listenersForEvent) return;
// listenersForEvent.delete(listener);
// };
// /* fire(target, event) {
// let listeners = this.wm.get(target);
// if (!listeners) return;
// let listenersForEvent = listeners[event];
// if (!listenersForEvent) return;
// for (let handler of handlers) {
// setTimeout(handler, 0, event, target); // we use a setTimeout here because we want event triggering to be asynchronous.
// }
// }; */
// }
// console.log = () => {};
// const e = new EventSystem();
// MOUNT_CLASS_TO.e = e;
export type EventListenerListeners = Record<string, Function>;
/**
* Better not to remove listeners during setting
* Should add listener callback only once
*/
// type EventLitenerCallback<T> = (data: T) =>
// export default class EventListenerBase<Listeners extends {[name: string]: Function}> {
export default class EventListenerBase<Listeners extends EventListenerListeners> {
protected listeners: Partial<{
[k in keyof Listeners]: Array<{callback: Listeners[k], options: boolean | AddEventListenerOptions}>
}>;
protected listenerResults: Partial<{
[k in keyof Listeners]: ArgumentTypes<Listeners[k]>
}>;
private reuseResults: boolean;
constructor(reuseResults?: boolean) {
this._constructor(reuseResults);
}
public _constructor(reuseResults = false): any {
this.reuseResults = reuseResults;
this.listeners = {};
this.listenerResults = {};
}
public addEventListener<T extends keyof Listeners>(name: T, callback: Listeners[T], options?: boolean | AddEventListenerOptions) {
(this.listeners[name] ?? (this.listeners[name] = [])).push({callback, options}); // ! add before because if you don't, you won't be able to delete it from callback
if(this.listenerResults.hasOwnProperty(name)) {
callback(...this.listenerResults[name]);
if((options as AddEventListenerOptions)?.once) {
this.listeners[name].pop();
return;
}
}
//e.add(this, name, {callback, once});
}
public addMultipleEventsListeners(obj: {
[name in keyof Listeners]?: Listeners[name]
}) {
for(const i in obj) {
this.addEventListener(i, obj[i]);
}
}
public removeEventListener<T extends keyof Listeners>(name: T, callback: Listeners[T], options?: boolean | AddEventListenerOptions) {
if(this.listeners[name]) {
this.listeners[name].findAndSplice(l => l.callback === callback);
}
//e.remove(this, name, callback);
}
// * must be protected, but who cares
private _dispatchEvent<T extends keyof Listeners>(name: T, collectResults: boolean, ...args: ArgumentTypes<Listeners[T]>) {
if(this.reuseResults) {
this.listenerResults[name] = args;
}
const arr: Array<SuperReturnType<Listeners[typeof name]>> = collectResults && [];
const listeners = this.listeners[name];
if(listeners) {
// ! this one will guarantee execution even if delete another listener during setting
const left = listeners.slice();
left.forEach((listener) => {
const index = listeners.findIndex((l) => l.callback === listener.callback);
if(index === -1) {
return;
}
let result: any;
try {
result = listener.callback(...args);
} catch(err) {
console.error(err);
}
if(arr) {
arr.push(result);
}
if((listener.options as AddEventListenerOptions)?.once) {
this.removeEventListener(name, listener.callback);
}
});
}
return arr;
}
public dispatchResultableEvent<T extends keyof Listeners>(name: T, ...args: ArgumentTypes<Listeners[T]>) {
return this._dispatchEvent(name, true, ...args);
}
// * must be protected, but who cares
public dispatchEvent<T extends keyof Listeners>(name: T, ...args: ArgumentTypes<Listeners[T]>) {
this._dispatchEvent(name, false, ...args);
}
public cleanup() {
this.listeners = {};
this.listenerResults = {};
}
}