Refactor AccountStorage to use private fields for state management

5085f6cdc9f68dc702ab3a78e5dc7f0efe30c770

Cohee <18619528+Cohee1207@users.noreply.github.com>

2 files changed, +30 -17Ignore whitespace
public/script.js+1 -1
@@ -7098,7 +7098,7 @@ export async function saveSettings(loopCounter = 0) {
7098 url: '/api/settings/save',7098 url: '/api/settings/save',
7099 data: JSON.stringify({7099 data: JSON.stringify({
7100 firstRun: firstRun,7100 firstRun: firstRun,
7101 accountStorage: accountStorage.state,7101 accountStorage: accountStorage.getState(),
7102 currentVersion: currentVersion,7102 currentVersion: currentVersion,
7103 username: name1,7103 username: name1,
7104 active_character: active_character,7104 active_character: active_character,
public/scripts/util/AccountStorage.js+29 -16
@@ -34,10 +34,15 @@ const MIGRATABLE_KEYS = [
34 * Provides access to account storage of arbitrary key-value pairs.34 * Provides access to account storage of arbitrary key-value pairs.
35 */35 */
36class AccountStorage {36class AccountStorage {
37 constructor() {37 /**
38 this.state = {};38 * @type {Record<string, string>} Storage state
39 this.ready = false;39 */
40 }40 #state = {};
41
42 /**
43 * @type {boolean} If the storage was initialized
44 */
45 #ready = false;
4146
42 #migrateLocalStorage() {47 #migrateLocalStorage() {
43 for (let i = 0; i < globalThis.localStorage.length; i++) {48 for (let i = 0; i < globalThis.localStorage.length; i++) {
@@ -45,7 +50,7 @@ class AccountStorage {
45 const value = globalThis.localStorage.getItem(key);50 const value = globalThis.localStorage.getItem(key);
4651
47 if (MIGRATABLE_KEYS.some(k => k.test(key))) {52 if (MIGRATABLE_KEYS.some(k => k.test(key))) {
48 this.state[key] = value;53 this.#state[key] = value;
49 globalThis.localStorage.removeItem(key);54 globalThis.localStorage.removeItem(key);
50 }55 }
51 }56 }
@@ -57,16 +62,16 @@ class AccountStorage {
57 */62 */
58 init(state) {63 init(state) {
59 if (state && typeof state === 'object') {64 if (state && typeof state === 'object') {
60 this.state = Object.assign(this.state, state);65 this.#state = Object.assign(this.#state, state);
61 }66 }
6267
63 if (!Object.hasOwn(this.state, MIGRATED_MARKER)) {68 if (!Object.hasOwn(this.#state, MIGRATED_MARKER)) {
64 this.#migrateLocalStorage();69 this.#migrateLocalStorage();
65 this.state[MIGRATED_MARKER] = 1;70 this.#state[MIGRATED_MARKER] = '1';
66 saveSettingsDebounced();71 saveSettingsDebounced();
67 }72 }
6873
69 this.ready = true;74 this.#ready = true;
70 }75 }
7176
72 /**77 /**
@@ -75,11 +80,11 @@ class AccountStorage {
75 * @returns {string|null} Value of the key80 * @returns {string|null} Value of the key
76 */81 */
77 getItem(key) {82 getItem(key) {
78 if (!this.ready) {83 if (!this.#ready) {
79 console.warn(`AccountStorage not ready (trying to read from ${key})`);84 console.warn(`AccountStorage not ready (trying to read from ${key})`);
80 }85 }
8186
82 return Object.hasOwn(this.state, key) ? String(this.state[key]) : null;87 return Object.hasOwn(this.#state, key) ? String(this.#state[key]) : null;
83 }88 }
8489
85 /**90 /**
@@ -88,11 +93,11 @@ class AccountStorage {
88 * @param {string} value Value to set93 * @param {string} value Value to set
89 */94 */
90 setItem(key, value) {95 setItem(key, value) {
91 if (!this.ready) {96 if (!this.#ready) {
92 console.warn(`AccountStorage not ready (trying to write to ${key})`);97 console.warn(`AccountStorage not ready (trying to write to ${key})`);
93 }98 }
9499
95 this.state[key] = String(value);100 this.#state[key] = String(value);
96 saveSettingsDebounced();101 saveSettingsDebounced();
97 }102 }
98103
@@ -101,17 +106,25 @@ class AccountStorage {
101 * @param {string} key Key to remove106 * @param {string} key Key to remove
102 */107 */
103 removeItem(key) {108 removeItem(key) {
104 if (!this.ready) {109 if (!this.#ready) {
105 console.warn(`AccountStorage not ready (trying to remove ${key})`);110 console.warn(`AccountStorage not ready (trying to remove ${key})`);
106 }111 }
107112
108 if (!Object.hasOwn(this.state, key)) {113 if (!Object.hasOwn(this.#state, key)) {
109 return;114 return;
110 }115 }
111116
112 delete this.state[key];117 delete this.#state[key];
113 saveSettingsDebounced();118 saveSettingsDebounced();
114 }119 }
120
121 /**
122 * Gets a snapshot of the storage state.
123 * @returns {Record<string, string>} A deep clone of the storage state
124 */
125 getState() {
126 return structuredClone(this.#state);
127 }
115}128}
116129
117/**130/**