87 lines
2.5 KiB
JavaScript
87 lines
2.5 KiB
JavaScript
export class SettingsWatch {
|
|
#settings;
|
|
#key_data = new Map();
|
|
|
|
constructor(settings, ...opts) {
|
|
this.#settings = settings;
|
|
|
|
for (const opt of opts) {
|
|
if (typeof opt == 'string') {
|
|
this.#addSetting(opt, {});
|
|
} else {
|
|
for (const [prop_name, opts] of Object.entries(opt)) {
|
|
this.#addSetting(prop_name, opts)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#addSetting(prop_name, opts) {
|
|
let key;
|
|
if (typeof opts == 'string') {
|
|
key = opts;
|
|
opts = {};
|
|
} else {
|
|
key = opts.key ?? prop_name.replace('_', '-');
|
|
}
|
|
|
|
const settings = this.#settings;
|
|
const raw_getter = opts.get_raw ?? this.#defaultRawGetter(settings, key);
|
|
const getter = opts.get ?? (x => x);
|
|
|
|
const update_cb = () => {
|
|
let value = getter(raw_getter(settings.get_value(key)));
|
|
this.#key_data.get(prop_name).value = value;
|
|
|
|
return value;
|
|
};
|
|
|
|
this.#key_data.set(prop_name, {});
|
|
Object.defineProperty(this, prop_name, {
|
|
enumerable: true,
|
|
configurable: true,
|
|
get() {
|
|
let data = this.#key_data.get(prop_name);
|
|
if (data.value === undefined) {
|
|
data.handler_id = settings.connect('changed::' + key, update_cb);
|
|
data.value = update_cb();
|
|
}
|
|
|
|
return data.value;
|
|
}
|
|
});
|
|
}
|
|
|
|
#defaultRawGetter(settings, key) {
|
|
const schema = settings.settings_schema.get_key(key);
|
|
const [range_ty, _range] = schema.get_range().recursiveUnpack();
|
|
|
|
if (range_ty == "enum") {
|
|
return value => {
|
|
return {
|
|
nick: value.unpack(),
|
|
|
|
// FIXME: remove unnecessary lookup if/when g_settings_schema_key_to_enum()
|
|
// becomes available. But for now, an extra lookup will have to do.
|
|
value: settings.get_enum(key),
|
|
};
|
|
};
|
|
}
|
|
|
|
return value => value.recursiveUnpack();
|
|
}
|
|
|
|
clear() {
|
|
for (const [key, data] of this.#key_data.entries()) {
|
|
if (data.handler_id !== undefined)
|
|
this.#settings.disconnect(data.handler_id);
|
|
|
|
delete this[key];
|
|
}
|
|
|
|
this.#key_data.clear();
|
|
}
|
|
}
|
|
|
|
// Allow calling clear as a static function.
|
|
SettingsWatch.clear = obj => SettingsWatch.prototype.clear.apply(obj);
|