1
0
mirror of https://github.com/koloml/furbooru-tagging-assistant.git synced 2026-03-24 23:02:58 +00:00

Renaming for tagging profiles and preferences classes

This commit is contained in:
2026-02-28 22:44:47 +04:00
parent 441091142c
commit dc29c6ca69
34 changed files with 236 additions and 238 deletions

4
src/app.d.ts vendored
View File

@@ -1,6 +1,6 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import type TagGroup from "$entities/TagGroup";
declare global {
@@ -37,7 +37,7 @@ declare global {
);
interface EntityNamesMap {
profiles: MaintenanceProfile;
profiles: TaggingProfile;
groups: TagGroup;
}

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import type MaintenanceProfile from "$entities/MaintenanceProfile";
import type TaggingProfile from "$entities/TaggingProfile";
interface ProfileViewProps {
profile: MaintenanceProfile;
profile: TaggingProfile;
}
let { profile }: ProfileViewProps = $props();

View File

@@ -1,5 +1,5 @@
import { BaseComponent } from "$content/components/base/BaseComponent";
import TagSettings from "$lib/extension/settings/TagSettings";
import TagsPreferences from "$lib/extension/preferences/TagsPreferences";
import { getComponent } from "$content/components/base/component-utils";
import { resolveTagNameFromLink, resolveTagCategoryFromTagName } from "$lib/booru/tag-utils";
@@ -17,8 +17,8 @@ export class BlockCommunication extends BaseComponent {
protected init() {
Promise.all([
BlockCommunication.#tagSettings.resolveReplaceLinks(),
BlockCommunication.#tagSettings.resolveReplaceLinkText(),
BlockCommunication.#preferences.resolveReplaceLinks(),
BlockCommunication.#preferences.resolveReplaceLinkText(),
]).then(([replaceLinks, replaceLinkText]) => {
this.#onReplaceLinkSettingResolved(
replaceLinks,
@@ -26,7 +26,7 @@ export class BlockCommunication extends BaseComponent {
);
});
BlockCommunication.#tagSettings.subscribe(settings => {
BlockCommunication.#preferences.subscribe(settings => {
this.#onReplaceLinkSettingResolved(
settings.replaceLinks ?? false,
settings.replaceLinkText ?? true
@@ -112,7 +112,7 @@ export class BlockCommunication extends BaseComponent {
);
}
static #tagSettings = new TagSettings();
static #preferences = new TagsPreferences();
/**
* Map of links to their original texts. These texts need to be stored here to make them restorable. Keys is a link

View File

@@ -1,5 +1,5 @@
import { BaseComponent } from "$content/components/base/BaseComponent";
import MiscSettings, { type FullscreenViewerSize } from "$lib/extension/settings/MiscSettings";
import MiscPreferences, { type FullscreenViewerSize } from "$lib/extension/preferences/MiscPreferences";
import { emit, on } from "$content/components/events/comms";
import { EVENT_SIZE_LOADED } from "$content/components/events/fullscreen-viewer-events";
@@ -53,7 +53,7 @@ export class FullscreenViewer extends BaseComponent {
this.#imageElement.addEventListener('load', this.#onLoaded.bind(this));
this.#sizeSelectorElement.addEventListener('click', event => event.stopPropagation());
FullscreenViewer.#miscSettings
FullscreenViewer.#preferences
.resolveFullscreenViewerPreviewSize()
.then(this.#onSizeResolved.bind(this))
.then(this.#watchForSizeSelectionChanges.bind(this));
@@ -179,7 +179,7 @@ export class FullscreenViewer extends BaseComponent {
#watchForSizeSelectionChanges() {
let lastActiveSize = this.#sizeSelectorElement.value;
FullscreenViewer.#miscSettings.subscribe(settings => {
FullscreenViewer.#preferences.subscribe(settings => {
const targetSize = settings.fullscreenViewerSize;
if (!targetSize || lastActiveSize === targetSize) {
@@ -202,7 +202,7 @@ export class FullscreenViewer extends BaseComponent {
}
lastActiveSize = targetSize;
void FullscreenViewer.#miscSettings.setFullscreenViewerPreviewSize(targetSize);
void FullscreenViewer.#preferences.setFullscreenViewerPreviewSize(targetSize);
});
}
@@ -289,7 +289,7 @@ export class FullscreenViewer extends BaseComponent {
return url.endsWith('.mp4') || url.endsWith('.webm');
}
static #miscSettings = new MiscSettings();
static #preferences = new MiscPreferences();
static #offsetProperty = '--offset';
static #opacityProperty = '--opacity';

View File

@@ -1,6 +1,6 @@
import { BaseComponent } from "$content/components/base/BaseComponent";
import { getComponent } from "$content/components/base/component-utils";
import MiscSettings from "$lib/extension/settings/MiscSettings";
import MiscPreferences from "$lib/extension/preferences/MiscPreferences";
import { FullscreenViewer } from "$content/components/FullscreenViewer";
import type { MediaBoxTools } from "$content/components/MediaBoxTools";
@@ -10,8 +10,6 @@ export class ImageShowFullscreenButton extends BaseComponent {
protected build() {
this.container.innerText = '🔍';
ImageShowFullscreenButton.#miscSettings ??= new MiscSettings();
}
protected init() {
@@ -27,14 +25,14 @@ export class ImageShowFullscreenButton extends BaseComponent {
this.on('click', this.#onButtonClicked.bind(this));
if (ImageShowFullscreenButton.#miscSettings) {
ImageShowFullscreenButton.#miscSettings.resolveFullscreenViewerEnabled()
if (ImageShowFullscreenButton.#preferences) {
ImageShowFullscreenButton.#preferences.resolveFullscreenViewerEnabled()
.then(isEnabled => {
this.#isFullscreenButtonEnabled = isEnabled;
this.#updateFullscreenButtonVisibility();
})
.then(() => {
ImageShowFullscreenButton.#miscSettings?.subscribe(settings => {
ImageShowFullscreenButton.#preferences?.subscribe(settings => {
this.#isFullscreenButtonEnabled = settings.fullscreenViewer ?? true;
this.#updateFullscreenButtonVisibility();
})
@@ -76,7 +74,7 @@ export class ImageShowFullscreenButton extends BaseComponent {
return viewer;
}
static #miscSettings: MiscSettings | null = null;
static #preferences = new MiscPreferences();
}
export function createImageShowFullscreenButton() {

View File

@@ -1,5 +1,5 @@
import MaintenanceSettings from "$lib/extension/settings/MaintenanceSettings";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfilesPreferences from "$lib/extension/preferences/TaggingProfilesPreferences";
import TaggingProfile from "$entities/TaggingProfile";
import { BaseComponent } from "$content/components/base/BaseComponent";
import { getComponent } from "$content/components/base/component-utils";
import ScrapedAPI from "$lib/booru/scraped/ScrapedAPI";
@@ -25,7 +25,7 @@ export class MaintenancePopup extends BaseComponent {
#tagsListElement: HTMLElement = document.createElement('div');
#tagsList: HTMLElement[] = [];
#suggestedInvalidTags: Map<string, HTMLElement> = new Map();
#activeProfile: MaintenanceProfile | null = null;
#activeProfile: TaggingProfile | null = null;
#mediaBoxTools: MediaBoxTools | null = null;
#tagsToRemove: Set<string> = new Set();
#tagsToAdd: Set<string> = new Set();
@@ -79,7 +79,7 @@ export class MaintenancePopup extends BaseComponent {
mediaBox.on('mouseover', this.#onMouseEnteredArea.bind(this));
}
#onActiveProfileChanged(activeProfile: MaintenanceProfile | null) {
#onActiveProfileChanged(activeProfile: TaggingProfile | null) {
this.#activeProfile = activeProfile;
this.container.classList.toggle('is-active', activeProfile !== null);
this.#refreshTagsList();
@@ -214,7 +214,7 @@ export class MaintenancePopup extends BaseComponent {
let maybeTagsAndAliasesAfterUpdate;
const shouldAutoRemove = await MaintenancePopup.#maintenanceSettings.resolveStripBlacklistedTags();
const shouldAutoRemove = await MaintenancePopup.#preferences.resolveStripBlacklistedTags();
try {
maybeTagsAndAliasesAfterUpdate = await MaintenancePopup.#scrapedAPI.updateImageTags(
@@ -333,7 +333,7 @@ export class MaintenancePopup extends BaseComponent {
/**
* Controller with maintenance settings.
*/
static #maintenanceSettings = new MaintenanceSettings();
static #preferences = new TaggingProfilesPreferences();
/**
* Subscribe to all necessary feeds to watch for every active profile change. Additionally, will execute the callback
@@ -341,10 +341,10 @@ export class MaintenancePopup extends BaseComponent {
* @param callback Callback to execute whenever selection of active profile or profile itself has been changed.
* @return Unsubscribe function. Call it to stop watching for changes.
*/
static #watchActiveProfile(callback: (profile: MaintenanceProfile | null) => void): () => void {
static #watchActiveProfile(callback: (profile: TaggingProfile | null) => void): () => void {
let lastActiveProfileId: string | null | undefined = null;
const unsubscribeFromProfilesChanges = MaintenanceProfile.subscribe(profiles => {
const unsubscribeFromProfilesChanges = TaggingProfile.subscribe(profiles => {
if (lastActiveProfileId) {
callback(
profiles.find(profile => profile.id === lastActiveProfileId) || null
@@ -352,19 +352,19 @@ export class MaintenancePopup extends BaseComponent {
}
});
const unsubscribeFromMaintenanceSettings = this.#maintenanceSettings.subscribe(settings => {
const unsubscribeFromMaintenanceSettings = this.#preferences.subscribe(settings => {
if (settings.activeProfile === lastActiveProfileId) {
return;
}
lastActiveProfileId = settings.activeProfile;
this.#maintenanceSettings
this.#preferences
.resolveActiveProfileAsObject()
.then(callback);
});
this.#maintenanceSettings
this.#preferences
.resolveActiveProfileAsObject()
.then(profileOrNull => {
if (profileOrNull) {

View File

@@ -4,7 +4,7 @@ import { MaintenancePopup } from "$content/components/MaintenancePopup";
import { on } from "$content/components/events/comms";
import { EVENT_ACTIVE_PROFILE_CHANGED } from "$content/components/events/maintenance-popup-events";
import type { MediaBoxWrapper } from "$content/components/MediaBoxWrapper";
import type MaintenanceProfile from "$entities/MaintenanceProfile";
import type TaggingProfile from "$entities/TaggingProfile";
export class MediaBoxTools extends BaseComponent {
#mediaBox: MediaBoxWrapper | null = null;
@@ -42,7 +42,7 @@ export class MediaBoxTools extends BaseComponent {
on(this, EVENT_ACTIVE_PROFILE_CHANGED, this.#onActiveProfileChanged.bind(this));
}
#onActiveProfileChanged(profileChangedEvent: CustomEvent<MaintenanceProfile | null>) {
#onActiveProfileChanged(profileChangedEvent: CustomEvent<TaggingProfile | null>) {
this.container.classList.toggle('has-active-profile', profileChangedEvent.detail !== null);
}

View File

@@ -1,6 +1,6 @@
import { BaseComponent } from "$content/components/base/BaseComponent";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import MaintenanceSettings from "$lib/extension/settings/MaintenanceSettings";
import TaggingProfile from "$entities/TaggingProfile";
import TaggingProfilesPreferences from "$lib/extension/preferences/TaggingProfilesPreferences";
import { getComponent } from "$content/components/base/component-utils";
import CustomCategoriesResolver from "$lib/extension/CustomCategoriesResolver";
import { on } from "$content/components/events/comms";
@@ -29,7 +29,7 @@ export class TagDropdownWrapper extends BaseComponent {
/**
* Local clone of the currently active profile used for updating the list of tags.
*/
#activeProfile: MaintenanceProfile | null = null;
#activeProfile: TaggingProfile | null = null;
/**
* Is cursor currently entered the dropdown.
@@ -172,14 +172,14 @@ export class TagDropdownWrapper extends BaseComponent {
throw new Error('Missing tag name to create the profile!');
}
const profile = new MaintenanceProfile(crypto.randomUUID(), {
const profile = new TaggingProfile(crypto.randomUUID(), {
name: 'Temporary Profile (' + (new Date().toISOString()) + ')',
tags: [this.tagName],
temporary: true,
});
await profile.save();
await TagDropdownWrapper.#maintenanceSettings.setActiveProfileId(profile.id);
await TagDropdownWrapper.#preferences.setActiveProfileId(profile.id);
}
async #onToggleInExistingClicked() {
@@ -205,25 +205,25 @@ export class TagDropdownWrapper extends BaseComponent {
await this.#activeProfile.save();
}
static #maintenanceSettings = new MaintenanceSettings();
static #preferences = new TaggingProfilesPreferences();
/**
* Watch for changes to active profile.
* @param onActiveProfileChange Callback to call when profile was
* changed.
*/
static #watchActiveProfile(onActiveProfileChange: (profile: MaintenanceProfile | null) => void) {
static #watchActiveProfile(onActiveProfileChange: (profile: TaggingProfile | null) => void) {
let lastActiveProfile: string | null = null;
this.#maintenanceSettings.subscribe((settings) => {
this.#preferences.subscribe((settings) => {
lastActiveProfile = settings.activeProfile ?? null;
this.#maintenanceSettings
this.#preferences
.resolveActiveProfileAsObject()
.then(onActiveProfileChange);
});
MaintenanceProfile.subscribe(profiles => {
TaggingProfile.subscribe(profiles => {
const activeProfile = profiles
.find(profile => profile.id === lastActiveProfile);
@@ -231,7 +231,7 @@ export class TagDropdownWrapper extends BaseComponent {
);
});
this.#maintenanceSettings
this.#preferences
.resolveActiveProfileAsObject()
.then(activeProfile => {
lastActiveProfile = activeProfile?.id ?? null;

View File

@@ -5,7 +5,7 @@ import { on } from "$content/components/events/comms";
import { EVENT_FORM_EDITOR_UPDATED } from "$content/components/events/tags-form-events";
import { getComponent } from "$content/components/base/component-utils";
import { EVENT_TAG_GROUP_RESOLVED } from "$content/components/events/tag-dropdown-events";
import TagSettings from "$lib/extension/settings/TagSettings";
import TagsPreferences from "$lib/extension/preferences/TagsPreferences";
export class TagsListBlock extends BaseComponent {
#tagsListButtonsContainer: HTMLElement | null = null;
@@ -14,7 +14,7 @@ export class TagsListBlock extends BaseComponent {
#toggleGroupingButton = document.createElement('a');
#toggleGroupingButtonIcon = document.createElement('i');
#tagSettings = new TagSettings();
#preferences = new TagsPreferences();
#shouldDisplaySeparation = false;
@@ -44,8 +44,8 @@ export class TagsListBlock extends BaseComponent {
}
init() {
this.#tagSettings.resolveGroupSeparation().then(this.#onTagSeparationChange.bind(this));
this.#tagSettings.subscribe(settings => {
this.#preferences.resolveGroupSeparation().then(this.#onTagSeparationChange.bind(this));
this.#preferences.subscribe(settings => {
this.#onTagSeparationChange(Boolean(settings.groupSeparation))
});
@@ -103,7 +103,7 @@ export class TagsListBlock extends BaseComponent {
#onToggleGroupingClicked(event: Event) {
event.preventDefault();
void this.#tagSettings.setGroupSeparation(!this.#shouldDisplaySeparation);
void this.#preferences.setGroupSeparation(!this.#shouldDisplaySeparation);
}
#handleTagGroupChanges(tagGroup: TagGroup) {

View File

@@ -1,4 +1,4 @@
import type { FullscreenViewerSize } from "$lib/extension/settings/MiscSettings";
import type { FullscreenViewerSize } from "$lib/extension/preferences/MiscPreferences";
export const EVENT_SIZE_LOADED = 'size-loaded';

View File

@@ -1,4 +1,4 @@
import type MaintenanceProfile from "$entities/MaintenanceProfile";
import type TaggingProfile from "$entities/TaggingProfile";
export const EVENT_ACTIVE_PROFILE_CHANGED = 'active-profile-changed';
export const EVENT_MAINTENANCE_STATE_CHANGED = 'maintenance-state-change';
@@ -7,7 +7,7 @@ export const EVENT_TAGS_UPDATED = 'tags-updated';
type MaintenanceState = 'processing' | 'failed' | 'complete' | 'waiting';
export interface MaintenancePopupEventsMap {
[EVENT_ACTIVE_PROFILE_CHANGED]: MaintenanceProfile | null;
[EVENT_ACTIVE_PROFILE_CHANGED]: TaggingProfile | null;
[EVENT_MAINTENANCE_STATE_CHANGED]: MaintenanceState;
[EVENT_TAGS_UPDATED]: Map<string, string> | null;
}

View File

@@ -2,7 +2,7 @@ import type StorageEntity from "$lib/extension/base/StorageEntity";
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from "lz-string";
import type { ImportableElementsList, ImportableEntityObject } from "$lib/extension/transporting/importables";
import EntitiesTransporter, { type SameSiteStatus } from "$lib/extension/EntitiesTransporter";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import TagGroup from "$entities/TagGroup";
type TransportersMapping = {
@@ -73,7 +73,7 @@ export default class BulkEntitiesTransporter {
elements: entities
.map(entity => {
switch (true) {
case entity instanceof MaintenanceProfile:
case entity instanceof TaggingProfile:
return BulkEntitiesTransporter.#transporters.profiles.exportToObject(entity);
case entity instanceof TagGroup:
return BulkEntitiesTransporter.#transporters.groups.exportToObject(entity);
@@ -99,7 +99,7 @@ export default class BulkEntitiesTransporter {
}
static #transporters: TransportersMapping = {
profiles: new EntitiesTransporter(MaintenanceProfile),
profiles: new EntitiesTransporter(TaggingProfile),
groups: new EntitiesTransporter(TagGroup),
}

View File

@@ -1,6 +1,6 @@
import ConfigurationController from "$lib/extension/ConfigurationController";
export default class CacheableSettings<Fields> {
export default class CacheablePreferences<Fields> {
#controller: ConfigurationController;
#cachedValues: Map<keyof Fields, any> = new Map();
#disposables: Function[] = [];

View File

@@ -1,20 +1,20 @@
import StorageEntity from "$lib/extension/base/StorageEntity";
export interface MaintenanceProfileSettings {
export interface TaggingProfileSettings {
name: string;
tags: string[];
temporary: boolean;
}
/**
* Class representing the maintenance profile entity.
* Class representing the tagging profile entity.
*/
export default class MaintenanceProfile extends StorageEntity<MaintenanceProfileSettings> {
export default class TaggingProfile extends StorageEntity<TaggingProfileSettings> {
/**
* @param id ID of the entity.
* @param settings Maintenance profile settings object.
*/
constructor(id: string, settings: Partial<MaintenanceProfileSettings>) {
constructor(id: string, settings: Partial<TaggingProfileSettings>) {
super(id, {
name: settings.name || '',
tags: settings.tags || [],

View File

@@ -1,13 +1,13 @@
import CacheableSettings from "$lib/extension/base/CacheableSettings";
import CacheablePreferences from "$lib/extension/base/CacheablePreferences";
export type FullscreenViewerSize = keyof App.ImageURIs;
interface MiscSettingsFields {
interface MiscPreferencesFields {
fullscreenViewer: boolean;
fullscreenViewerSize: FullscreenViewerSize;
}
export default class MiscSettings extends CacheableSettings<MiscSettingsFields> {
export default class MiscPreferences extends CacheablePreferences<MiscPreferencesFields> {
constructor() {
super("misc");
}

View File

@@ -1,12 +1,12 @@
import MaintenanceProfile from "$entities/MaintenanceProfile";
import CacheableSettings from "$lib/extension/base/CacheableSettings";
import TaggingProfile from "$entities/TaggingProfile";
import CacheablePreferences from "$lib/extension/base/CacheablePreferences";
interface MaintenanceSettingsFields {
interface TaggingProfilePreferencesFields {
activeProfile: string | null;
stripBlacklistedTags: boolean;
}
export default class MaintenanceSettings extends CacheableSettings<MaintenanceSettingsFields> {
export default class TaggingProfilesPreferences extends CacheablePreferences<TaggingProfilePreferencesFields> {
constructor() {
super("maintenance");
}
@@ -21,10 +21,10 @@ export default class MaintenanceSettings extends CacheableSettings<MaintenanceSe
/**
* Get the active maintenance profile if it is set.
*/
async resolveActiveProfileAsObject(): Promise<MaintenanceProfile | null> {
async resolveActiveProfileAsObject(): Promise<TaggingProfile | null> {
const resolvedProfileId = await this.resolveActiveProfileId();
return (await MaintenanceProfile.readAll())
return (await TaggingProfile.readAll())
.find(profile => profile.id === resolvedProfileId) || null;
}

View File

@@ -1,12 +1,12 @@
import CacheableSettings from "$lib/extension/base/CacheableSettings";
import CacheablePreferences from "$lib/extension/base/CacheablePreferences";
interface TagSettingsFields {
interface TagsPreferencesFields {
groupSeparation: boolean;
replaceLinks: boolean;
replaceLinkText: boolean;
}
export default class TagSettings extends CacheableSettings<TagSettingsFields> {
export default class TagsPreferences extends CacheablePreferences<TagsPreferencesFields> {
constructor() {
super("tag");
}

View File

@@ -1,30 +1,30 @@
<script lang="ts">
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { activeTaggingProfile, taggingProfiles } from "$stores/entities/tagging-profiles";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import { popupTitle } from "$stores/popup";
$popupTitle = null;
let activeProfile = $derived<MaintenanceProfile | null>(
$maintenanceProfiles.find(profile => profile.id === $activeProfileStore) || null
let activeProfile = $derived<TaggingProfile | null>(
$taggingProfiles.find(profile => profile.id === $activeTaggingProfile) || null
);
function turnOffActiveProfile() {
$activeProfileStore = null;
$activeTaggingProfile = null;
}
</script>
<Menu>
{#if activeProfile}
<MenuCheckboxItem checked oninput={turnOffActiveProfile} href="/features/maintenance/{activeProfile.id}">
<MenuCheckboxItem checked oninput={turnOffActiveProfile} href="/features/profiles/{activeProfile.id}">
Active Profile: {activeProfile.settings.name}
</MenuCheckboxItem>
<hr>
{/if}
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
<MenuItem href="/features/profiles">Tagging Profiles</MenuItem>
<MenuItem href="/features/groups">Tag Groups</MenuItem>
<hr>
<MenuItem href="/transporting">Import/Export</MenuItem>

View File

@@ -6,5 +6,5 @@
<Menu>
<MenuItem href="/">Back</MenuItem>
<hr>
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
<MenuItem href="/features/profiles">Tagging Profiles</MenuItem>
</Menu>

View File

@@ -2,45 +2,45 @@
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import MenuRadioItem from "$components/ui/menu/MenuRadioItem.svelte";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import { activeTaggingProfile, taggingProfiles } from "$stores/entities/tagging-profiles";
import TaggingProfile from "$entities/TaggingProfile";
import { popupTitle } from "$stores/popup";
$popupTitle = 'Tagging Profiles';
let profiles = $derived<MaintenanceProfile[]>(
$maintenanceProfiles.sort((a, b) => a.settings.name.localeCompare(b.settings.name))
let profiles = $derived<TaggingProfile[]>(
$taggingProfiles.sort((a, b) => a.settings.name.localeCompare(b.settings.name))
);
function resetActiveProfile() {
$activeProfileStore = null;
$activeTaggingProfile = null;
}
function enableSelectedProfile(event: Event) {
const target = event.target;
if (target instanceof HTMLInputElement && target.checked) {
activeProfileStore.set(target.value);
activeTaggingProfile.set(target.value);
}
}
</script>
<Menu>
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/maintenance/new/edit" icon="plus">Create New</MenuItem>
<MenuItem href="/features/profiles/new/edit" icon="plus">Create New</MenuItem>
{#if profiles.length}
<hr>
{/if}
{#each profiles as profile}
<MenuRadioItem href="/features/maintenance/{profile.id}"
<MenuRadioItem href="/features/profiles/{profile.id}"
name="active-profile"
value={profile.id}
checked={$activeProfileStore === profile.id}
checked={$activeTaggingProfile === profile.id}
oninput={enableSelectedProfile}>
{profile.settings.name}
</MenuRadioItem>
{/each}
<hr>
<MenuItem href="#" onclick={resetActiveProfile}>Reset Active Profile</MenuItem>
<MenuItem href="/features/maintenance/import">Import Profile</MenuItem>
<MenuItem href="/features/profiles/import">Import Profile</MenuItem>
</Menu>

View File

@@ -3,26 +3,26 @@
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { page } from "$app/state";
import { goto } from "$app/navigation";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { activeTaggingProfile, taggingProfiles } from "$stores/entities/tagging-profiles";
import ProfileView from "$components/features/ProfileView.svelte";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import { popupTitle } from "$stores/popup";
let profileId = $derived(page.params.id);
let profile = $derived<MaintenanceProfile|null>(
$maintenanceProfiles.find(profile => profile.id === profileId) || null
let profile = $derived<TaggingProfile|null>(
$taggingProfiles.find(profile => profile.id === profileId) || null
);
$effect(() => {
if (profileId === 'new') {
goto('/features/maintenance/new/edit');
goto('/features/profiles/new/edit');
return;
}
if (!profile) {
console.warn(`Profile ${profileId} not found.`);
goto('/features/maintenance');
goto('/features/profiles');
} else {
$popupTitle = `Tagging Profile: ${profile.settings.name}`;
}
@@ -31,22 +31,22 @@
let isActiveProfile = $state(false);
$effect.pre(() => {
isActiveProfile = $activeProfileStore === profileId;
isActiveProfile = $activeTaggingProfile === profileId;
});
$effect(() => {
if (isActiveProfile && $activeProfileStore !== profileId) {
$activeProfileStore = profileId;
if (isActiveProfile && $activeTaggingProfile !== profileId) {
$activeTaggingProfile = profileId;
}
if (!isActiveProfile && $activeProfileStore === profileId) {
$activeProfileStore = null;
if (!isActiveProfile && $activeTaggingProfile === profileId) {
$activeTaggingProfile = null;
}
});
</script>
<Menu>
<MenuItem href="/features/maintenance" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/profiles" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if profile}
@@ -54,14 +54,14 @@
{/if}
<Menu>
<hr>
<MenuItem href="/features/maintenance/{profileId}/edit" icon="wrench">Edit Profile</MenuItem>
<MenuItem href="/features/profiles/{profileId}/edit" icon="wrench">Edit Profile</MenuItem>
<MenuCheckboxItem bind:checked={isActiveProfile}>
Activate Profile
</MenuCheckboxItem>
<MenuItem href="/features/maintenance/{profileId}/export" icon="file-export">
<MenuItem href="/features/profiles/{profileId}/export" icon="file-export">
Export Profile
</MenuItem>
<MenuItem href="/features/maintenance/{profileId}/delete" icon="trash">
<MenuItem href="/features/profiles/{profileId}/delete" icon="trash">
Delete Profile
</MenuItem>
</Menu>

View File

@@ -3,18 +3,18 @@
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { page } from "$app/state";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import { taggingProfiles } from "$stores/entities/tagging-profiles";
import TaggingProfile from "$entities/TaggingProfile";
import { popupTitle } from "$stores/popup";
const profileId = $derived(page.params.id);
const targetProfile = $derived<MaintenanceProfile | null>(
$maintenanceProfiles.find(profile => profile.id === profileId) || null
const targetProfile = $derived<TaggingProfile | null>(
$taggingProfiles.find(profile => profile.id === profileId) || null
);
$effect(() => {
if (!targetProfile) {
goto('/features/maintenance');
goto('/features/profiles');
} else {
$popupTitle = `Deleting Tagging Profile: ${targetProfile.settings.name}`
}
@@ -27,12 +27,12 @@
}
await targetProfile.delete();
await goto('/features/maintenance');
await goto('/features/profiles');
}
</script>
<Menu>
<MenuItem href="/features/maintenance/{profileId}" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/profiles/{profileId}" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if targetProfile}
@@ -42,7 +42,7 @@
<Menu>
<hr>
<MenuItem onclick={deleteProfile}>Yes</MenuItem>
<MenuItem href="/features/maintenance/{profileId}">No</MenuItem>
<MenuItem href="/features/profiles/{profileId}">No</MenuItem>
</Menu>
{:else}
<p>Loading...</p>

View File

@@ -7,19 +7,19 @@
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import { page } from "$app/state";
import { goto } from "$app/navigation";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import { taggingProfiles } from "$stores/entities/tagging-profiles";
import TaggingProfile from "$entities/TaggingProfile";
import { popupTitle } from "$stores/popup";
let profileId = $derived(page.params.id);
let targetProfile = $derived.by<MaintenanceProfile | null>(() => {
let targetProfile = $derived.by<TaggingProfile | null>(() => {
if (profileId === 'new') {
return new MaintenanceProfile(crypto.randomUUID(), {});
return new TaggingProfile(crypto.randomUUID(), {});
}
return $maintenanceProfiles.find(profile => profile.id === profileId) || null;
return $taggingProfiles.find(profile => profile.id === profileId) || null;
});
let profileName = $state('');
@@ -32,7 +32,7 @@
}
if (!targetProfile) {
goto('/features/maintenance');
goto('/features/profiles');
return;
}
@@ -53,12 +53,12 @@
targetProfile.settings.temporary = false;
await targetProfile.save();
await goto('/features/maintenance/' + targetProfile.id);
await goto('/features/profiles/' + targetProfile.id);
}
</script>
<Menu>
<MenuItem href="/features/maintenance{profileId === 'new' ? '' : '/' + profileId}" icon="arrow-left">
<MenuItem href="/features/profiles{profileId === 'new' ? '' : '/' + profileId}" icon="arrow-left">
Back
</MenuItem>
<hr>

View File

@@ -1,31 +1,31 @@
<script lang="ts">
import { page } from "$app/state";
import { goto } from "$app/navigation";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { taggingProfiles } from "$stores/entities/tagging-profiles";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import { popupTitle } from "$stores/popup";
let isCompressedProfileShown = $state(true);
const profileId = $derived(page.params.id);
const profile = $derived<MaintenanceProfile | null>(
$maintenanceProfiles.find(profile => profile.id === profileId) || null
const profile = $derived<TaggingProfile | null>(
$taggingProfiles.find(profile => profile.id === profileId) || null
);
$effect(() => {
if (!profile) {
goto('/features/maintenance/');
goto('/features/profiles/');
} else {
$popupTitle = `Export Tagging Profile: ${profile.settings.name}`;
}
});
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
const profilesTransporter = new EntitiesTransporter(TaggingProfile);
let rawExportedProfile = $derived(profile ? profilesTransporter.exportToJSON(profile) : '');
let compressedExportedProfile = $derived(profile ? profilesTransporter.exportToCompressedJSON(profile) : '');
@@ -33,7 +33,7 @@
</script>
<Menu>
<MenuItem href="/features/maintenance/{profileId}" icon="arrow-left">
<MenuItem href="/features/profiles/{profileId}" icon="arrow-left">
Back
</MenuItem>
<hr>

View File

@@ -2,22 +2,22 @@
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import FormControl from "$components/ui/forms/FormControl.svelte";
import ProfileView from "$components/features/ProfileView.svelte";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { taggingProfiles } from "$stores/entities/tagging-profiles";
import { goto } from "$app/navigation";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import { popupTitle } from "$stores/popup";
import Notice from "$components/ui/Notice.svelte";
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
const profilesTransporter = new EntitiesTransporter(TaggingProfile);
let importedString = $state('');
let errorMessage = $state('');
let candidateProfile = $state<MaintenanceProfile | null>(null);
let existingProfile = $state<MaintenanceProfile | null>(null);
let candidateProfile = $state<TaggingProfile | null>(null);
let existingProfile = $state<TaggingProfile | null>(null);
$effect(() => {
$popupTitle = candidateProfile
@@ -49,7 +49,7 @@
}
if (candidateProfile) {
existingProfile = $maintenanceProfiles.find(profile => profile.id === candidateProfile?.id) ?? null;
existingProfile = $taggingProfiles.find(profile => profile.id === candidateProfile?.id) ?? null;
}
}
@@ -59,7 +59,7 @@
}
candidateProfile.save().then(() => {
goto(`/features/maintenance`);
goto(`/features/profiles`);
});
}
@@ -68,16 +68,16 @@
return;
}
const clonedProfile = new MaintenanceProfile(crypto.randomUUID(), candidateProfile.settings);
const clonedProfile = new TaggingProfile(crypto.randomUUID(), candidateProfile.settings);
clonedProfile.settings.name += ` (Clone ${new Date().toISOString()})`;
clonedProfile.save().then(() => {
goto(`/features/maintenance`);
goto(`/features/profiles`);
});
}
</script>
<Menu>
<MenuItem href="/features/maintenance" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/profiles" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if errorMessage}

View File

@@ -4,12 +4,12 @@
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { stripBlacklistedTagsEnabled } from "$stores/preferences/maintenance";
import { stripBlacklistedTagsEnabled } from "$stores/preferences/profiles";
import {
shouldReplaceLinksOnForumPosts,
shouldReplaceTextOfTagLinks,
shouldSeparateTagGroups
} from "$stores/preferences/tag";
} from "$stores/preferences/tags";
import { popupTitle } from "$stores/popup";
$popupTitle = 'Tagging Preferences';

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { taggingProfiles } from "$stores/entities/tagging-profiles";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
import BulkEntitiesTransporter from "$lib/extension/BulkEntitiesTransporter";
@@ -30,7 +30,7 @@
if (displayExportedString) {
const elementsToExport: StorageEntity[] = [];
$maintenanceProfiles.forEach(profile => {
$taggingProfiles.forEach(profile => {
if (exportedEntities.profiles[profile.id]) {
elementsToExport.push(profile);
}
@@ -55,7 +55,7 @@
function refreshAreAllEntitiesChecked() {
requestAnimationFrame(() => {
exportAllProfiles = $maintenanceProfiles.every(profile => exportedEntities.profiles[profile.id]);
exportAllProfiles = $taggingProfiles.every(profile => exportedEntities.profiles[profile.id]);
exportAllGroups = $tagGroups.every(group => exportedEntities.groups[group.id]);
});
}
@@ -69,7 +69,7 @@
requestAnimationFrame(() => {
switch (targetEntity) {
case "profiles":
$maintenanceProfiles.forEach(profile => exportedEntities.profiles[profile.id] = exportAllProfiles);
$taggingProfiles.forEach(profile => exportedEntities.profiles[profile.id] = exportAllProfiles);
break;
case "groups":
$tagGroups.forEach(group => exportedEntities.groups[group.id] = exportAllGroups);
@@ -94,11 +94,11 @@
<Menu>
<MenuItem href="/transporting" icon="arrow-left">Back</MenuItem>
<hr>
{#if $maintenanceProfiles.length}
{#if $taggingProfiles.length}
<MenuCheckboxItem bind:checked={exportAllProfiles} oninput={createToggleAllOnUserInput('profiles')}>
Export All Profiles
</MenuCheckboxItem>
{#each $maintenanceProfiles as profile}
{#each $taggingProfiles as profile}
<MenuCheckboxItem bind:checked={exportedEntities.profiles[profile.id]} oninput={refreshAreAllEntitiesChecked}>
Profile: {profile.settings.name}
</MenuCheckboxItem>

View File

@@ -3,11 +3,11 @@
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import TaggingProfile from "$entities/TaggingProfile";
import TagGroup from "$entities/TagGroup";
import BulkEntitiesTransporter from "$lib/extension/BulkEntitiesTransporter";
import type StorageEntity from "$lib/extension/base/StorageEntity";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { taggingProfiles } from "$stores/entities/tagging-profiles";
import { tagGroups } from "$stores/entities/tag-groups";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
import ProfileView from "$components/features/ProfileView.svelte";
@@ -20,7 +20,7 @@
let importedString = $state('');
let errorMessage = $state('');
let importedProfiles = $state<MaintenanceProfile[]>([]);
let importedProfiles = $state<TaggingProfile[]>([]);
let importedGroups = $state<TagGroup[]>([]);
let saveAllProfiles = $state(false);
@@ -36,10 +36,10 @@
let previewedEntity = $state<StorageEntity | null>(null);
const existingProfilesMap = $derived(
$maintenanceProfiles.reduce((map, profile) => {
$taggingProfiles.reduce((map, profile) => {
map.set(profile.id, profile);
return map;
}, new Map<string, MaintenanceProfile>())
}, new Map<string, TaggingProfile>())
);
const existingGroupsMap = $derived(
@@ -98,7 +98,7 @@
for (const targetImportedEntity of importedEntities) {
switch (targetImportedEntity.type) {
case "profiles":
importedProfiles.push(targetImportedEntity as MaintenanceProfile);
importedProfiles.push(targetImportedEntity as TaggingProfile);
break;
case "groups":
importedGroups.push(targetImportedEntity as TagGroup);
@@ -202,7 +202,7 @@
<MenuItem onclick={() => previewedEntity = null} icon="arrow-left">Back to Selection</MenuItem>
<hr>
</Menu>
{#if previewedEntity instanceof MaintenanceProfile}
{#if previewedEntity instanceof TaggingProfile}
<ProfileView profile={previewedEntity}></ProfileView>
{:else if previewedEntity instanceof TagGroup}
<GroupView group={previewedEntity}></GroupView>

View File

@@ -1,52 +0,0 @@
import { type Writable, writable } from "svelte/store";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import MaintenanceSettings from "$lib/extension/settings/MaintenanceSettings";
/**
* Store for working with maintenance profiles in the Svelte popup.
*/
export const maintenanceProfiles: Writable<MaintenanceProfile[]> = writable([]);
/**
* Store for the active maintenance profile ID.
*/
export const activeProfileStore: Writable<string|null> = writable(null);
const maintenanceSettings = new MaintenanceSettings();
/**
* Active profile ID stored locally. Used to reset active profile once the existing profile was removed.
*/
let lastActiveProfileId: string|null = null;
Promise.allSettled([
// Read the initial values from the storages first
MaintenanceProfile.readAll().then(profiles => {
maintenanceProfiles.set(profiles);
}),
maintenanceSettings.resolveActiveProfileId().then(activeProfileId => {
activeProfileStore.set(activeProfileId);
})
]).then(() => {
// And only after initial values are loaded, start watching for changes from storage and from user's interaction
MaintenanceProfile.subscribe(profiles => {
maintenanceProfiles.set(profiles);
});
maintenanceSettings.subscribe(settings => {
activeProfileStore.set(settings.activeProfile || null);
});
activeProfileStore.subscribe(profileId => {
lastActiveProfileId = profileId;
void maintenanceSettings.setActiveProfileId(profileId);
});
// Watch the existence of the active profile on every change.
MaintenanceProfile.subscribe(profiles => {
if (!profiles.find(profile => profile.id === lastActiveProfileId)) {
activeProfileStore.set(null);
}
});
});

View File

@@ -0,0 +1,52 @@
import { type Writable, writable } from "svelte/store";
import TaggingProfile from "$entities/TaggingProfile";
import TaggingProfilesPreferences from "$lib/extension/preferences/TaggingProfilesPreferences";
/**
* Store for working with maintenance profiles in the Svelte popup.
*/
export const taggingProfiles: Writable<TaggingProfile[]> = writable([]);
/**
* Store for the active maintenance profile ID.
*/
export const activeTaggingProfile: Writable<string|null> = writable(null);
const preferences = new TaggingProfilesPreferences();
/**
* Active profile ID stored locally. Used to reset active profile once the existing profile was removed.
*/
let lastActiveProfileId: string|null = null;
Promise.allSettled([
// Read the initial values from the storages first
TaggingProfile.readAll().then(profiles => {
taggingProfiles.set(profiles);
}),
preferences.resolveActiveProfileId().then(activeProfileId => {
activeTaggingProfile.set(activeProfileId);
})
]).then(() => {
// And only after initial values are loaded, start watching for changes from storage and from user's interaction
TaggingProfile.subscribe(profiles => {
taggingProfiles.set(profiles);
});
preferences.subscribe(settings => {
activeTaggingProfile.set(settings.activeProfile || null);
});
activeTaggingProfile.subscribe(profileId => {
lastActiveProfileId = profileId;
void preferences.setActiveProfileId(profileId);
});
// Watch the existence of the active profile on every change.
TaggingProfile.subscribe(profiles => {
if (!profiles.find(profile => profile.id === lastActiveProfileId)) {
activeTaggingProfile.set(null);
}
});
});

View File

@@ -1,18 +0,0 @@
import { writable } from "svelte/store";
import MaintenanceSettings from "$lib/extension/settings/MaintenanceSettings";
export const stripBlacklistedTagsEnabled = writable(true);
const maintenanceSettings = new MaintenanceSettings();
Promise
.all([
maintenanceSettings.resolveStripBlacklistedTags().then(v => stripBlacklistedTagsEnabled.set(v ?? true))
])
.then(() => {
maintenanceSettings.subscribe(settings => {
stripBlacklistedTagsEnabled.set(typeof settings.stripBlacklistedTags === 'boolean' ? settings.stripBlacklistedTags : true);
});
stripBlacklistedTagsEnabled.subscribe(v => maintenanceSettings.setStripBlacklistedTags(v));
});

View File

@@ -1,18 +1,18 @@
import { writable } from "svelte/store";
import MiscSettings from "$lib/extension/settings/MiscSettings";
import MiscPreferences from "$lib/extension/preferences/MiscPreferences";
export const fullScreenViewerEnabled = writable(true);
const miscSettings = new MiscSettings();
const preferences = new MiscPreferences();
Promise.allSettled([
miscSettings.resolveFullscreenViewerEnabled().then(v => fullScreenViewerEnabled.set(v))
preferences.resolveFullscreenViewerEnabled().then(v => fullScreenViewerEnabled.set(v))
]).then(() => {
fullScreenViewerEnabled.subscribe(value => {
void miscSettings.setFullscreenViewerEnabled(value);
void preferences.setFullscreenViewerEnabled(value);
});
miscSettings.subscribe(settings => {
preferences.subscribe(settings => {
fullScreenViewerEnabled.set(Boolean(settings.fullscreenViewer));
});
});

View File

@@ -0,0 +1,18 @@
import { writable } from "svelte/store";
import TaggingProfilesPreferences from "$lib/extension/preferences/TaggingProfilesPreferences";
export const stripBlacklistedTagsEnabled = writable(true);
const preferences = new TaggingProfilesPreferences();
Promise
.all([
preferences.resolveStripBlacklistedTags().then(v => stripBlacklistedTagsEnabled.set(v ?? true))
])
.then(() => {
preferences.subscribe(settings => {
stripBlacklistedTagsEnabled.set(typeof settings.stripBlacklistedTags === 'boolean' ? settings.stripBlacklistedTags : true);
});
stripBlacklistedTagsEnabled.subscribe(v => preferences.setStripBlacklistedTags(v));
});

View File

@@ -1,7 +1,7 @@
import { writable } from "svelte/store";
import TagSettings from "$lib/extension/settings/TagSettings";
import TagsPreferences from "$lib/extension/preferences/TagsPreferences";
const tagSettings = new TagSettings();
const preferences = new TagsPreferences();
export const shouldSeparateTagGroups = writable(false);
export const shouldReplaceLinksOnForumPosts = writable(false);
@@ -9,24 +9,24 @@ export const shouldReplaceTextOfTagLinks = writable(true);
Promise
.allSettled([
tagSettings.resolveGroupSeparation().then(value => shouldSeparateTagGroups.set(value)),
tagSettings.resolveReplaceLinks().then(value => shouldReplaceLinksOnForumPosts.set(value)),
tagSettings.resolveReplaceLinkText().then(value => shouldReplaceTextOfTagLinks.set(value)),
preferences.resolveGroupSeparation().then(value => shouldSeparateTagGroups.set(value)),
preferences.resolveReplaceLinks().then(value => shouldReplaceLinksOnForumPosts.set(value)),
preferences.resolveReplaceLinkText().then(value => shouldReplaceTextOfTagLinks.set(value)),
])
.then(() => {
shouldSeparateTagGroups.subscribe(value => {
void tagSettings.setGroupSeparation(value);
void preferences.setGroupSeparation(value);
});
shouldReplaceLinksOnForumPosts.subscribe(value => {
void tagSettings.setReplaceLinks(value);
void preferences.setReplaceLinks(value);
});
shouldReplaceTextOfTagLinks.subscribe(value => {
void tagSettings.setReplaceLinkText(value);
void preferences.setReplaceLinkText(value);
});
tagSettings.subscribe(settings => {
preferences.subscribe(settings => {
shouldSeparateTagGroups.set(Boolean(settings.groupSeparation));
shouldReplaceLinksOnForumPosts.set(Boolean(settings.replaceLinks));
shouldReplaceTextOfTagLinks.set(Boolean(settings.replaceLinkText));