1
0
mirror of https://github.com/koloml/philomena-tagging-assistant.git synced 2026-09-22 20:09:39 +00:00

1 Commits

Author SHA1 Message Date
34c0a11b4e Added separate class for syncing multiple preference fields with stores
This will make the sync code less boilerplate-y. Instead of manually
subscribing back and forth, this will be done inside the class in
correct order and in any amount.

Types are a bit wonky though.
2026-08-30 11:52:07 +02:00
5 changed files with 85 additions and 47 deletions

View File

@@ -70,6 +70,10 @@ export class PreferenceField<
set(value: Fields[Key]) {
return this.#preferences.writeRaw(this.#fieldKey, value);
}
get key(): Key {
return this.#fieldKey;
}
}
/**

65
src/lib/store-sync.ts Normal file
View File

@@ -0,0 +1,65 @@
import type { Writable } from "svelte/store";
import CacheablePreferences, { type PreferenceField } from "$lib/extension/base/CacheablePreferences";
interface PrerefenceConnectionOptions<ValueType> {
/**
* Optional callback to apply modifications to the value when sending them from the preference field to the single
* storage. If not provided, value itself will be sent instead.
*/
updateToStore?: (value: any) => ValueType;
}
export class PreferenceSync<PreferencesType extends Record<string, any> = Record<string, any>> {
readonly #preferences: CacheablePreferences<PreferencesType>;
readonly #syncedPairs: [PreferenceField<PreferencesType, string>, Writable<any>, PrerefenceConnectionOptions<any>][] = [];
protected constructor(preferences: CacheablePreferences<PreferencesType>) {
this.#preferences = preferences;
}
/**
* Connect the specific preference field to the provided storage.
* @param field Field object.
* @param store Storage object. Should contain the appropriate type for the value.
* @param [options] Additional settings.
*/
connect<FieldKey extends keyof PreferencesType>(
field: PreferenceField<PreferencesType, FieldKey>,
store: Writable<PreferencesType[FieldKey]>,
options: PrerefenceConnectionOptions<PreferencesType[FieldKey]> = {}
): this {
this.#syncedPairs.push([field as any, store, options]);
return this;
}
async startSync(): Promise<void> {
await Promise.allSettled(
this.#syncedPairs.map(
([field, store, options]) => field.get()
.then(initialValue => store.set(options.updateToStore?.(initialValue) ?? initialValue))
)
);
for (const [field, store] of this.#syncedPairs) {
store.subscribe(value => field.set(value));
}
this.#preferences.subscribe(updatedSettings => {
for (const [field, store, options] of this.#syncedPairs) {
if (!(field.key in updatedSettings)) {
continue;
}
const updatedValue = updatedSettings[field.key];
store.set(options.updateToStore?.(updatedValue) ?? updatedValue);
}
});
}
static for<
PreferencesType extends Record<string, any> = Record<string, any>
>(preferences: CacheablePreferences<PreferencesType>): PreferenceSync<PreferencesType> {
return new PreferenceSync<PreferencesType>(preferences);
}
}

View File

@@ -1,18 +1,11 @@
import { writable } from "svelte/store";
import MiscPreferences from "$lib/extension/preferences/MiscPreferences";
import { PreferenceSync } from "$lib/store-sync";
export const fullScreenViewerEnabled = writable(true);
const preferences = new MiscPreferences();
Promise.allSettled([
preferences.fullscreenViewer.get().then(v => fullScreenViewerEnabled.set(v))
]).then(() => {
fullScreenViewerEnabled.subscribe(value => {
void preferences.fullscreenViewer.set(value);
});
preferences.subscribe(settings => {
fullScreenViewerEnabled.set(Boolean(settings.fullscreenViewer));
});
});
void PreferenceSync.for(preferences)
.connect(preferences.fullscreenViewer, fullScreenViewerEnabled, {updateToStore: Boolean})
.startSync();

View File

@@ -1,18 +1,13 @@
import { writable } from "svelte/store";
import TaggingProfilesPreferences from "$lib/extension/preferences/TaggingProfilesPreferences";
import { PreferenceSync } from "$lib/store-sync";
export const stripBlacklistedTagsEnabled = writable(true);
const preferences = new TaggingProfilesPreferences();
Promise
.all([
preferences.stripBlacklistedTags.get().then(v => stripBlacklistedTagsEnabled.set(v ?? true))
])
.then(() => {
preferences.subscribe(settings => {
stripBlacklistedTagsEnabled.set(typeof settings.stripBlacklistedTags === 'boolean' ? settings.stripBlacklistedTags : true);
});
stripBlacklistedTagsEnabled.subscribe(v => preferences.stripBlacklistedTags.set(v));
});
void PreferenceSync.for(preferences)
.connect(preferences.stripBlacklistedTags, stripBlacklistedTagsEnabled, {
updateToStore: maybeBoolean => typeof maybeBoolean === 'boolean' ? maybeBoolean : true,
})
.startSync();

View File

@@ -1,5 +1,6 @@
import { writable } from "svelte/store";
import TagsPreferences from "$lib/extension/preferences/TagsPreferences";
import { PreferenceSync } from "$lib/store-sync";
const preferences = new TagsPreferences();
@@ -7,28 +8,8 @@ export const shouldSeparateTagGroups = writable(false);
export const shouldReplaceLinksOnForumPosts = writable(false);
export const shouldReplaceTextOfTagLinks = writable(true);
Promise
.allSettled([
preferences.groupSeparation.get().then(value => shouldSeparateTagGroups.set(value)),
preferences.replaceLinks.get().then(value => shouldReplaceLinksOnForumPosts.set(value)),
preferences.replaceLinkText.get().then(value => shouldReplaceTextOfTagLinks.set(value)),
])
.then(() => {
shouldSeparateTagGroups.subscribe(value => {
void preferences.groupSeparation.set(value);
});
shouldReplaceLinksOnForumPosts.subscribe(value => {
void preferences.replaceLinks.set(value);
});
shouldReplaceTextOfTagLinks.subscribe(value => {
void preferences.replaceLinkText.set(value);
});
preferences.subscribe(settings => {
shouldSeparateTagGroups.set(Boolean(settings.groupSeparation));
shouldReplaceLinksOnForumPosts.set(Boolean(settings.replaceLinks));
shouldReplaceTextOfTagLinks.set(Boolean(settings.replaceLinkText));
});
});
void PreferenceSync.for(preferences)
.connect(preferences.groupSeparation, shouldSeparateTagGroups, {updateToStore: Boolean})
.connect(preferences.replaceLinks, shouldReplaceLinksOnForumPosts, {updateToStore: Boolean})
.connect(preferences.replaceLinkText, shouldReplaceTextOfTagLinks, {updateToStore: Boolean})
.startSync();