diff options
Diffstat (limited to 'extensions/46/middleclickclose/src/settingsWatch.js')
-rw-r--r-- | extensions/46/middleclickclose/src/settingsWatch.js | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/extensions/46/middleclickclose/src/settingsWatch.js b/extensions/46/middleclickclose/src/settingsWatch.js new file mode 100644 index 0000000..fd8b8bd --- /dev/null +++ b/extensions/46/middleclickclose/src/settingsWatch.js @@ -0,0 +1,87 @@ +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); |