Skip to content

Commit 624b8c5

Browse files
committed
chore: extract setting logic to standalone class
1 parent d6d67cd commit 624b8c5

4 files changed

Lines changed: 239 additions & 83 deletions

File tree

.eslintrc.cjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@ module.exports = {
33
extends: 'airbnb-base',
44
env: {
55
node: true,
6+
es6: true,
7+
},
8+
parserOptions: {
9+
ecmaVersion: 'latest',
610
},
711
rules: {
812
camelcase: ['warn', { ignoreGlobals: true }],
913
// Allow this behavior, but want to be aware of any possible issues
1014
'consistent-return': 'warn',
15+
'lines-between-class-members': ['error', 'always', {
16+
exceptAfterSingleLine: true,
17+
}],
1118
// Allow modification of properties
1219
'no-param-reassign': ['warn', { props: false }],
1320
// Allow short circuits: test && action

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
"contributors": [
1313
"Austin Peterson <austin@akpwebdesign.com> (https://blog.akpwebdesign.com)"
1414
],
15+
"engines": {
16+
"node": ">= 18"
17+
},
1518
"type": "module",
1619
"scripts": {
1720
"build": "rollup -c",
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import EventEmitter from '../eventEmitter.js';
2+
import SettingType from './types/setting.js';
3+
4+
export default class RegisteredSetting {
5+
/** @type {string} */
6+
#key;
7+
/** @type {string} */
8+
#name;
9+
/** @type {SettingType} */
10+
#type;
11+
/** @type {string} (or plugin) */
12+
#page;
13+
/** @type {string} */
14+
#category;
15+
/** @type {any} */
16+
#default;
17+
/** @type {boolean | Function} */
18+
#disabled;
19+
/** @type {boolean | Function} */
20+
#hidden;
21+
/** @type {boolean | Function} */
22+
#remove;
23+
/** @type {boolean | Function} */
24+
#export;
25+
/** @type {string} */
26+
#prefix;
27+
/** @type {boolean | Function} */
28+
#reset;
29+
#data;
30+
/** @type {string | Function} */
31+
#note;
32+
/** @type {boolean | Function} */
33+
#refresh;
34+
/** @type {Function} */
35+
#onChange;
36+
/** @type {EventEmitter} */
37+
#events;
38+
39+
constructor({
40+
category,
41+
converter,
42+
data,
43+
default: def,
44+
disabled,
45+
export: exporting,
46+
extraPrefix,
47+
events,
48+
hidden,
49+
key,
50+
name,
51+
note,
52+
onChange,
53+
page,
54+
refresh,
55+
remove,
56+
reset,
57+
type,
58+
} = {}) {
59+
this.#key = key;
60+
this.#name = name || key;
61+
this.#type = type;
62+
this.#page = page;
63+
this.#category = category;
64+
this.#default = def;
65+
this.#disabled = disabled;
66+
this.#hidden = hidden;
67+
this.#remove = remove;
68+
this.#export = exporting;
69+
this.#prefix = extraPrefix;
70+
this.#reset = reset;
71+
this.#data = data;
72+
this.#note = note;
73+
this.#refresh = refresh;
74+
this.#onChange = onChange;
75+
this.#events = events;
76+
77+
if (typeof converter === 'function') {
78+
this.#convert(converter);
79+
}
80+
}
81+
82+
get key() {
83+
return this.#key;
84+
}
85+
86+
get name() {
87+
return this.#name;
88+
}
89+
90+
get type() {
91+
return this.#type;
92+
}
93+
94+
get page() {
95+
return this.#page;
96+
}
97+
98+
get category() {
99+
return this.#category;
100+
}
101+
102+
get disabled() {
103+
return this.#value(this.#disabled) === true;
104+
}
105+
106+
get hidden() {
107+
return this.#value(this.#hidden) === true;
108+
}
109+
110+
get remove() {
111+
return this.#value(this.#remove) === true;
112+
}
113+
114+
get exportable() {
115+
return this.#value(this.#export) !== false;
116+
}
117+
118+
get extraPrefix() {
119+
return this.#prefix;
120+
}
121+
122+
get reset() {
123+
return this.#value(this.#reset) === true;
124+
}
125+
126+
get data() {
127+
return this.#data;
128+
}
129+
130+
get note() {
131+
const notes = [];
132+
133+
const note = this.#value(this.#note);
134+
if (note) {
135+
notes.push(note);
136+
}
137+
138+
if (this.#value(this.#refresh)) {
139+
// TODO: Translation file
140+
notes.push('Will require you to refresh the page.');
141+
}
142+
143+
return notes.join('<br>');
144+
}
145+
146+
update(val) {
147+
const {
148+
key,
149+
type,
150+
value: prev,
151+
} = this;
152+
if (val === undefined) {
153+
localStorage.removeItem(key);
154+
} else {
155+
localStorage.setItem(key, type.encode(val));
156+
}
157+
if (typeof this.#onChange === 'function') {
158+
this.#onChange(this.value, prev);
159+
}
160+
this.#events.emit(key, val, prev);
161+
this.#events.emit('setting:change', key, val, prev);
162+
}
163+
164+
get value() {
165+
const val = localStorage.getItem(this.key);
166+
if (!val) {
167+
return this.default;
168+
}
169+
return this.type.value(val);
170+
}
171+
172+
get default() {
173+
const val = this.#default;
174+
if (val !== undefined) {
175+
return this.type.value(this.#value(val));
176+
}
177+
return this.type.default(this.data);
178+
}
179+
180+
#convert(converter) {
181+
const { key } = this;
182+
const current = localStorage.getItem(key);
183+
if (typeof current === 'string') {
184+
const converted = converter(current);
185+
if (converted === null) {
186+
localStorage.removeItem(key);
187+
} else if (converted !== undefined) {
188+
localStorage.setItem(key, converted);
189+
}
190+
}
191+
}
192+
193+
#value(input) {
194+
if (typeof input === 'function') {
195+
return input();
196+
}
197+
198+
return input;
199+
}
200+
}

0 commit comments

Comments
 (0)