mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 11:44:40 +00:00
implement vanilla js SettingsState class to optimise code and clean up source :DDD
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import browser from 'webextension-polyfill';
|
||||
import { SettingsState } from '../../../types/storage';
|
||||
|
||||
type ChangeListener = (newValue: any, oldValue: any) => void;
|
||||
|
||||
class StorageManager {
|
||||
private static instance: StorageManager;
|
||||
private data: SettingsState;
|
||||
private listeners: { [key: string]: ChangeListener[] };
|
||||
|
||||
private constructor() {
|
||||
this.data = {} as SettingsState;
|
||||
this.listeners = {};
|
||||
this.loadFromStorage();
|
||||
|
||||
const handler: ProxyHandler<StorageManager> = {
|
||||
get: (target, prop: keyof SettingsState | 'register') => {
|
||||
if (prop in target) {
|
||||
return (target as any)[prop];
|
||||
}
|
||||
return Reflect.get(target.data, prop);
|
||||
},
|
||||
set: (target, prop: keyof SettingsState, value) => {
|
||||
Reflect.set(target.data, prop, value);
|
||||
target.saveToStorage();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
this.initStorageListener();
|
||||
|
||||
return new Proxy(this, handler) as StorageManager & SettingsState;
|
||||
}
|
||||
|
||||
public static getInstance(): StorageManager & SettingsState {
|
||||
if (!StorageManager.instance) {
|
||||
StorageManager.instance = new StorageManager();
|
||||
}
|
||||
return StorageManager.instance as StorageManager & SettingsState;
|
||||
}
|
||||
|
||||
private async loadFromStorage(): Promise<void> {
|
||||
const result = await browser.storage.local.get();
|
||||
this.data = { ...this.data, ...result };
|
||||
}
|
||||
|
||||
private async saveToStorage(): Promise<void> {
|
||||
await browser.storage.local.set(this.data);
|
||||
}
|
||||
|
||||
private initStorageListener(): void {
|
||||
browser.storage.onChanged.addListener((changes, areaName) => {
|
||||
if (areaName === 'local') {
|
||||
for (const [key, { oldValue, newValue }] of Object.entries(changes)) {
|
||||
if (newValue !== undefined) {
|
||||
(this.data as any)[key] = newValue;
|
||||
} else {
|
||||
delete (this.data as any)[key];
|
||||
}
|
||||
if (this.listeners[key]) {
|
||||
for (const listener of this.listeners[key]) {
|
||||
listener(newValue, oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public register(prop: keyof SettingsState, listener: ChangeListener): void {
|
||||
if (!this.listeners[prop]) {
|
||||
this.listeners[prop] = [];
|
||||
}
|
||||
this.listeners[prop].push(listener);
|
||||
}
|
||||
}
|
||||
|
||||
export const settingsState = StorageManager.getInstance();
|
||||
@@ -0,0 +1,115 @@
|
||||
import { settingsState } from './SettingsState';
|
||||
import { updateAllColors } from '../../ui/colors/Manager';
|
||||
import {
|
||||
CreateBackground,
|
||||
CreateCustomShortcutDiv,
|
||||
RemoveBackground,
|
||||
RemoveShortcutDiv,
|
||||
addShortcuts,
|
||||
disableNotificationCollector,
|
||||
enableNotificationCollector,
|
||||
} from '../../../SEQTA';
|
||||
import { updateBgDurations } from '../../ui/Animation';
|
||||
import browser from 'webextension-polyfill';
|
||||
|
||||
export class StorageChangeHandler {
|
||||
constructor() {
|
||||
this.registerHandlers();
|
||||
}
|
||||
|
||||
private registerHandlers() {
|
||||
console.log(settingsState.onoff);
|
||||
settingsState.register('selectedColor', this.handleSelectedColorChange.bind(this));
|
||||
settingsState.register('onoff', this.handleOnOffChange.bind(this));
|
||||
settingsState.register('shortcuts', this.handleShortcutsChange.bind(this));
|
||||
settingsState.register('customshortcuts', this.handleCustomShortcutsChange.bind(this));
|
||||
settingsState.register('notificationcollector', this.handleNotificationCollectorChange.bind(this));
|
||||
settingsState.register('bksliderinput', this.handleBksliderInputChange.bind(this));
|
||||
settingsState.register('animatedbk', this.handleAnimatedBkChange.bind(this));
|
||||
settingsState.register('transparencyEffects', this.handleTransparencyEffectsChange.bind(this));
|
||||
}
|
||||
|
||||
private handleSelectedColorChange(newColor: any) {
|
||||
try {
|
||||
updateAllColors(newColor);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
private handleOnOffChange() {
|
||||
browser.runtime.sendMessage({ type: 'reloadTabs' });
|
||||
}
|
||||
|
||||
private handleNotificationCollectorChange(newValue: any) {
|
||||
if (newValue) {
|
||||
enableNotificationCollector();
|
||||
} else {
|
||||
disableNotificationCollector();
|
||||
}
|
||||
}
|
||||
|
||||
private handleCustomShortcutsChange(oldValue: any, newValue: any) {
|
||||
if (newValue) {
|
||||
if (newValue.length > oldValue.length) {
|
||||
CreateCustomShortcutDiv(newValue[oldValue.length]);
|
||||
} else if (newValue.length < oldValue.length) {
|
||||
const removedElement = oldValue.find(
|
||||
(oldItem: any) => !newValue.some((newItem: any) => JSON.stringify(oldItem) === JSON.stringify(newItem))
|
||||
);
|
||||
|
||||
if (removedElement) {
|
||||
RemoveShortcutDiv([removedElement]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleShortcutsChange(oldValue: any, newValue: any) {
|
||||
const addedShortcuts = newValue.filter((newItem: any) => {
|
||||
const isAdded = oldValue.some((oldItem: any) => {
|
||||
const match = oldItem.name === newItem.name;
|
||||
const wasDisabled = !oldItem.enabled;
|
||||
const isEnabled = newItem.enabled;
|
||||
return match && wasDisabled && isEnabled;
|
||||
});
|
||||
|
||||
return isAdded;
|
||||
});
|
||||
|
||||
const removedShortcuts = newValue.filter((newItem: any) => {
|
||||
const isRemoved = oldValue.some((oldItem: any) => {
|
||||
const match = oldItem.name === newItem.name;
|
||||
const wasEnabled = oldItem.enabled;
|
||||
const isDisabled = !newItem.enabled;
|
||||
return match && wasEnabled && isDisabled;
|
||||
});
|
||||
|
||||
return isRemoved;
|
||||
});
|
||||
|
||||
addShortcuts(addedShortcuts);
|
||||
RemoveShortcutDiv(removedShortcuts);
|
||||
}
|
||||
|
||||
private handleBksliderInputChange(newValue: any) {
|
||||
updateBgDurations(newValue);
|
||||
}
|
||||
|
||||
private handleAnimatedBkChange(newValue: boolean) {
|
||||
if (newValue) {
|
||||
CreateBackground();
|
||||
} else {
|
||||
RemoveBackground();
|
||||
document.getElementById('container')!.style.background = 'var(--background-secondary)';
|
||||
}
|
||||
}
|
||||
|
||||
private handleTransparencyEffectsChange(newValue: boolean) {
|
||||
if (newValue) {
|
||||
document.documentElement.classList.add('transparencyEffects');
|
||||
} else {
|
||||
document.documentElement.classList.remove('transparencyEffects');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
import browser from 'webextension-polyfill'
|
||||
|
||||
import {
|
||||
CreateBackground,
|
||||
CreateCustomShortcutDiv,
|
||||
RemoveBackground,
|
||||
RemoveShortcutDiv,
|
||||
addShortcuts,
|
||||
disableNotificationCollector,
|
||||
enableNotificationCollector,
|
||||
} from '../../../SEQTA';
|
||||
import { updateBgDurations } from '../../ui/Animation';
|
||||
import { getDarkMode, updateAllColors } from '../../ui/colors/Manager';
|
||||
|
||||
|
||||
export default class StorageListener {
|
||||
darkMode: any;
|
||||
constructor() {
|
||||
this.darkMode = getDarkMode();
|
||||
browser.storage.onChanged.addListener(this.handleStorageChanges.bind(this));
|
||||
}
|
||||
|
||||
handleStorageChanges(changes: any) {
|
||||
Object.keys(changes).forEach((changeKey) => {
|
||||
switch (changeKey) {
|
||||
|
||||
case 'selectedColor':
|
||||
this.handleSelectedColorChange(changes.selectedColor.newValue);
|
||||
break;
|
||||
|
||||
case 'onoff':
|
||||
this.handleOnOffChange();
|
||||
break;
|
||||
|
||||
case 'shortcuts':
|
||||
this.handleShortcutsChange(
|
||||
changes.shortcuts.oldValue,
|
||||
changes.shortcuts.newValue
|
||||
);
|
||||
break;
|
||||
|
||||
case 'DarkMode':
|
||||
this.darkMode = changes.DarkMode.newValue;
|
||||
break;
|
||||
|
||||
case 'customshortcuts':
|
||||
if (changes.customshortcuts.newValue) {
|
||||
this.handleCustomShortcutsChange(
|
||||
changes.customshortcuts.oldValue,
|
||||
changes.customshortcuts.newValue
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'notificationcollector':
|
||||
this.handleNotificationCollectorChange(changes.notificationcollector);
|
||||
break;
|
||||
|
||||
case 'bksliderinput':
|
||||
updateBgDurations(changes.bksliderinput.newValue);
|
||||
break;
|
||||
|
||||
case 'animatedbk':
|
||||
if (changes.animatedbk.newValue) {
|
||||
CreateBackground();
|
||||
} else {
|
||||
RemoveBackground();
|
||||
document.getElementById('container')!.style.background = 'var(--background-secondary)';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'transparencyEffects':
|
||||
if (changes.transparencyEffects.newValue) {
|
||||
document.documentElement.classList.add('transparencyEffects');
|
||||
} else {
|
||||
document.documentElement.classList.remove('transparencyEffects');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'theme':
|
||||
console.debug(changes.theme.newValue)
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleSelectedColorChange(newColor: any) {
|
||||
try {
|
||||
updateAllColors(this.darkMode, newColor);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
handleOnOffChange() {
|
||||
browser.runtime.sendMessage({ type: 'reloadTabs' })
|
||||
}
|
||||
|
||||
handleNotificationCollectorChange(details: any) {
|
||||
if (details.newValue) {
|
||||
enableNotificationCollector();
|
||||
} else {
|
||||
disableNotificationCollector();
|
||||
}
|
||||
}
|
||||
|
||||
handleCustomShortcutsChange(oldValue: any, newValue: any) {
|
||||
// Check for addition
|
||||
if (newValue.length > oldValue.length) {
|
||||
CreateCustomShortcutDiv(newValue[oldValue.length]);
|
||||
}
|
||||
// Check for removal
|
||||
else if (newValue.length < oldValue.length) {
|
||||
const removedElement = oldValue.find(
|
||||
(oldItem: any) =>
|
||||
!newValue.some(
|
||||
(newItem: any) => JSON.stringify(oldItem) === JSON.stringify(newItem)
|
||||
)
|
||||
);
|
||||
|
||||
if (removedElement) {
|
||||
RemoveShortcutDiv([ removedElement ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleShortcutsChange(oldValue: any, newValue: any) {
|
||||
// Find Added Shortcuts
|
||||
const addedShortcuts = newValue.filter((newItem: any) => {
|
||||
const isAdded = oldValue.some((oldItem: any) => {
|
||||
const match = oldItem.name === newItem.name;
|
||||
const wasDisabled = !oldItem.enabled;
|
||||
const isEnabled = newItem.enabled;
|
||||
return match && wasDisabled && isEnabled;
|
||||
});
|
||||
|
||||
return isAdded;
|
||||
});
|
||||
|
||||
// Find Removed Shortcuts
|
||||
const removedShortcuts = newValue.filter((newItem: any) => {
|
||||
const isRemoved = oldValue.some((oldItem: any) => {
|
||||
const match = oldItem.name === newItem.name;
|
||||
const wasEnabled = oldItem.enabled; // Was enabled in the old array
|
||||
const isDisabled = !newItem.enabled; // Is disabled in the new array
|
||||
|
||||
return match && wasEnabled && isDisabled;
|
||||
});
|
||||
|
||||
return isRemoved;
|
||||
});
|
||||
|
||||
// Add new shortcuts to the UI
|
||||
addShortcuts(addedShortcuts);
|
||||
|
||||
// Remove deleted shortcuts from the UI
|
||||
RemoveShortcutDiv(removedShortcuts);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user