Refactor AccountStorage to use private fields for state management

This commit is contained in:
Cohee
2025-02-12 10:58:36 +02:00
parent 798f8d92a3
commit 5085f6cdc9
2 changed files with 30 additions and 17 deletions

View File

@ -7098,7 +7098,7 @@ export async function saveSettings(loopCounter = 0) {
url: '/api/settings/save', url: '/api/settings/save',
data: JSON.stringify({ data: JSON.stringify({
firstRun: firstRun, firstRun: firstRun,
accountStorage: accountStorage.state, accountStorage: accountStorage.getState(),
currentVersion: currentVersion, currentVersion: currentVersion,
username: name1, username: name1,
active_character: active_character, active_character: active_character,

View File

@ -34,10 +34,15 @@ const MIGRATABLE_KEYS = [
* Provides access to account storage of arbitrary key-value pairs. * Provides access to account storage of arbitrary key-value pairs.
*/ */
class AccountStorage { class AccountStorage {
constructor() { /**
this.state = {}; * @type {Record<string, string>} Storage state
this.ready = false; */
} #state = {};
/**
* @type {boolean} If the storage was initialized
*/
#ready = false;
#migrateLocalStorage() { #migrateLocalStorage() {
for (let i = 0; i < globalThis.localStorage.length; i++) { for (let i = 0; i < globalThis.localStorage.length; i++) {
@ -45,7 +50,7 @@ class AccountStorage {
const value = globalThis.localStorage.getItem(key); const value = globalThis.localStorage.getItem(key);
if (MIGRATABLE_KEYS.some(k => k.test(key))) { if (MIGRATABLE_KEYS.some(k => k.test(key))) {
this.state[key] = value; this.#state[key] = value;
globalThis.localStorage.removeItem(key); globalThis.localStorage.removeItem(key);
} }
} }
@ -57,16 +62,16 @@ class AccountStorage {
*/ */
init(state) { init(state) {
if (state && typeof state === 'object') { if (state && typeof state === 'object') {
this.state = Object.assign(this.state, state); this.#state = Object.assign(this.#state, state);
} }
if (!Object.hasOwn(this.state, MIGRATED_MARKER)) { if (!Object.hasOwn(this.#state, MIGRATED_MARKER)) {
this.#migrateLocalStorage(); this.#migrateLocalStorage();
this.state[MIGRATED_MARKER] = 1; this.#state[MIGRATED_MARKER] = '1';
saveSettingsDebounced(); saveSettingsDebounced();
} }
this.ready = true; this.#ready = true;
} }
/** /**
@ -75,11 +80,11 @@ class AccountStorage {
* @returns {string|null} Value of the key * @returns {string|null} Value of the key
*/ */
getItem(key) { getItem(key) {
if (!this.ready) { if (!this.#ready) {
console.warn(`AccountStorage not ready (trying to read from ${key})`); console.warn(`AccountStorage not ready (trying to read from ${key})`);
} }
return Object.hasOwn(this.state, key) ? String(this.state[key]) : null; return Object.hasOwn(this.#state, key) ? String(this.#state[key]) : null;
} }
/** /**
@ -88,11 +93,11 @@ class AccountStorage {
* @param {string} value Value to set * @param {string} value Value to set
*/ */
setItem(key, value) { setItem(key, value) {
if (!this.ready) { if (!this.#ready) {
console.warn(`AccountStorage not ready (trying to write to ${key})`); console.warn(`AccountStorage not ready (trying to write to ${key})`);
} }
this.state[key] = String(value); this.#state[key] = String(value);
saveSettingsDebounced(); saveSettingsDebounced();
} }
@ -101,17 +106,25 @@ class AccountStorage {
* @param {string} key Key to remove * @param {string} key Key to remove
*/ */
removeItem(key) { removeItem(key) {
if (!this.ready) { if (!this.#ready) {
console.warn(`AccountStorage not ready (trying to remove ${key})`); console.warn(`AccountStorage not ready (trying to remove ${key})`);
} }
if (!Object.hasOwn(this.state, key)) { if (!Object.hasOwn(this.#state, key)) {
return; return;
} }
delete this.state[key]; delete this.#state[key];
saveSettingsDebounced(); saveSettingsDebounced();
} }
/**
* Gets a snapshot of the storage state.
* @returns {Record<string, string>} A deep clone of the storage state
*/
getState() {
return structuredClone(this.#state);
}
} }
/** /**