add some jsdoc
This commit is contained in:
parent
c2eaa9d35a
commit
edfeca15ce
5 changed files with 61 additions and 5 deletions
|
@ -7,7 +7,7 @@
|
||||||
import { readFileSync, writeFileSync } from "fs";
|
import { readFileSync, writeFileSync } from "fs";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import type { Settings as TSettings } from "shared/settings";
|
import type { Settings as TSettings } from "shared/settings";
|
||||||
import { SettingsStore } from "shared/utils/makeChangeListenerProxy";
|
import { SettingsStore } from "shared/utils/SettingsStore";
|
||||||
|
|
||||||
import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants";
|
import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants";
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Settings as TSettings } from "shared/settings";
|
import type { Settings as TSettings } from "shared/settings";
|
||||||
import { SettingsStore } from "shared/utils/makeChangeListenerProxy";
|
import { SettingsStore } from "shared/utils/SettingsStore";
|
||||||
|
|
||||||
import { Common } from "./vencord";
|
import { Common } from "./vencord";
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,25 @@
|
||||||
* Copyright (c) 2023 Vendicated and Vencord contributors
|
* Copyright (c) 2023 Vendicated and Vencord contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SettingsStore allows you to easily create a mutable store that
|
||||||
|
* has support for global and path-based change listeners.
|
||||||
|
*/
|
||||||
export class SettingsStore<T extends object> {
|
export class SettingsStore<T extends object> {
|
||||||
public declare store: T;
|
|
||||||
private globalListeners = new Set<(newData: T) => void>();
|
|
||||||
private pathListeners = new Map<string, Set<(newData: unknown) => void>>();
|
private pathListeners = new Map<string, Set<(newData: unknown) => void>>();
|
||||||
|
private globalListeners = new Set<(newData: T) => void>();
|
||||||
|
|
||||||
public constructor(public plain: T) {
|
/**
|
||||||
|
* The store object. Making changes to this object will trigger the applicable change listeners
|
||||||
|
*/
|
||||||
|
public declare store: T;
|
||||||
|
/**
|
||||||
|
* The plain data. Changes to this object will not trigger any change listeners
|
||||||
|
*/
|
||||||
|
public declare plain: T;
|
||||||
|
|
||||||
|
public constructor(plain: T) {
|
||||||
|
this.plain = plain;
|
||||||
this.store = this.makeProxy(plain);
|
this.store = this.makeProxy(plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +52,13 @@ export class SettingsStore<T extends object> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the data of the store.
|
||||||
|
* This will update this.store and this.plain (and old references to them will be stale! Avoid storing them in variables)
|
||||||
|
*
|
||||||
|
* Additionally, all global listeners will be called with the new data
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
public setData(value: T) {
|
public setData(value: T) {
|
||||||
this.plain = value;
|
this.plain = value;
|
||||||
this.store = this.makeProxy(value);
|
this.store = this.makeProxy(value);
|
||||||
|
@ -46,20 +66,45 @@ export class SettingsStore<T extends object> {
|
||||||
this.globalListeners.forEach(cb => cb(value));
|
this.globalListeners.forEach(cb => cb(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a global change listener, that will fire whenever any setting is changed
|
||||||
|
*/
|
||||||
public addGlobalChangeListener(cb: (store: T) => void) {
|
public addGlobalChangeListener(cb: (store: T) => void) {
|
||||||
this.globalListeners.add(cb);
|
this.globalListeners.add(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a scoped change listener that will fire whenever a setting matching the specified path is changed.
|
||||||
|
*
|
||||||
|
* For example if path is `"foo.bar"`, the listener will fire on
|
||||||
|
* ```js
|
||||||
|
* Setting.store.foo.bar = "hi"
|
||||||
|
* ```
|
||||||
|
* but not on
|
||||||
|
* ```js
|
||||||
|
* Setting.store.foo.baz = "hi"
|
||||||
|
* ```
|
||||||
|
* @param path
|
||||||
|
* @param cb
|
||||||
|
*/
|
||||||
public addChangeListener(path: string, cb: (data: any) => void) {
|
public addChangeListener(path: string, cb: (data: any) => void) {
|
||||||
const listeners = this.pathListeners.get(path) ?? new Set();
|
const listeners = this.pathListeners.get(path) ?? new Set();
|
||||||
listeners.add(cb);
|
listeners.add(cb);
|
||||||
this.pathListeners.set(path, listeners);
|
this.pathListeners.set(path, listeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a global listener
|
||||||
|
* @see {@link addGlobalChangeListener}
|
||||||
|
*/
|
||||||
public removeGlobalChangeListener(cb: (store: T) => void) {
|
public removeGlobalChangeListener(cb: (store: T) => void) {
|
||||||
this.globalListeners.delete(cb);
|
this.globalListeners.delete(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a scoped listener
|
||||||
|
* @see {@link addChangeListener}
|
||||||
|
*/
|
||||||
public removeChangeListener(path: string, cb: (data: any) => void) {
|
public removeChangeListener(path: string, cb: (data: any) => void) {
|
||||||
const listeners = this.pathListeners.get(path);
|
const listeners = this.pathListeners.get(path);
|
||||||
if (!listeners) return;
|
if (!listeners) return;
|
|
@ -4,6 +4,12 @@
|
||||||
* Copyright (c) 2023 Vendicated and Vencord contributors
|
* Copyright (c) 2023 Vendicated and Vencord contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new function that will only be called after the given delay.
|
||||||
|
* Subsequent calls will cancel the previous timeout and start a new one from 0
|
||||||
|
*
|
||||||
|
* Useful for grouping multiple calls into one
|
||||||
|
*/
|
||||||
export function debounce<T extends Function>(func: T, delay = 300): T {
|
export function debounce<T extends Function>(func: T, delay = 300): T {
|
||||||
let timeout: NodeJS.Timeout;
|
let timeout: NodeJS.Timeout;
|
||||||
return function (...args: any[]) {
|
return function (...args: any[]) {
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
* Copyright (c) 2023 Vendicated and Vencord contributors
|
* Copyright (c) 2023 Vendicated and Vencord contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps the given function so that it can only be called once
|
||||||
|
* @param fn Function to wrap
|
||||||
|
* @returns New function that can only be called once
|
||||||
|
*/
|
||||||
export function once<T extends Function>(fn: T): T {
|
export function once<T extends Function>(fn: T): T {
|
||||||
let called = false;
|
let called = false;
|
||||||
return function (this: any, ...args: any[]) {
|
return function (this: any, ...args: any[]) {
|
||||||
|
|
Loading…
Reference in a new issue