Merge remote-tracking branch 'origin/release/0.8.0' into feature/fullscreen-tagging-profile

# Conflicts:
#	src/content/components/philomena/MediaBox.ts
This commit is contained in:
koloml committed 2026-10-14 01:31:14 +02:00
commit ecd95d3b4f
16 files changed
+556 -60

No files matched your search

+3 -2
View File
@@ -2,10 +2,11 @@
* Reusable function to create icons from FontAwesome. Usable only for website, since extension doesn't host its own
* copy of FA styles. Extension should use imports of SVGs inside CSS instead.
* @param iconSlug Slug of the icon to be added.
* @param [subtype="solid"] Subtype of the icon. Some icons only exist in specific subtypes.
* @return Element with classes for FontAwesome icon added.
*/
export function createFontAwesomeIcon(iconSlug: string): HTMLElement {
export function createFontAwesomeIcon(iconSlug: string, subtype: string = 'solid'): HTMLElement {
const iconElement = document.createElement('i');
iconElement.classList.add('fa-solid', `fa-${iconSlug}`);
iconElement.classList.add(`fa-${subtype}`, `fa-${iconSlug}`);
return iconElement;
}
@@ -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
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);
}
}