From f581f840653be4893abcae80f6afe8c0716ba16a Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 17:52:15 +0400 Subject: [PATCH 1/9] Presets: Added conditional presets option Now presets can be configured to show up only when specific tag is provided. --- src/lib/extension/entities/TagEditorPreset.ts | 4 ++++ src/lib/extension/transporting/exporters.ts | 2 ++ src/lib/extension/transporting/validators.ts | 2 ++ .../features/presets/[id]/edit/+page.svelte | 17 +++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/src/lib/extension/entities/TagEditorPreset.ts b/src/lib/extension/entities/TagEditorPreset.ts index d904d5f..681fc61 100644 --- a/src/lib/extension/entities/TagEditorPreset.ts +++ b/src/lib/extension/entities/TagEditorPreset.ts @@ -3,6 +3,8 @@ import StorageEntity from "$lib/extension/base/StorageEntity"; interface TagEditorPresetSettings { name: string; tags: string[]; + conditional: boolean; + requiredTags: string[]; } export default class TagEditorPreset extends StorageEntity { @@ -10,6 +12,8 @@ export default class TagEditorPreset extends StorageEntity([]); + let isConditional = $state(false); + let requiredTags = $state([]); $effect(() => { if (presetId === 'new') { @@ -39,6 +42,8 @@ presetName = targetPreset.settings.name; tagsList = [...targetPreset.settings.tags].sort((a, b) => a.localeCompare(b)); + isConditional = targetPreset.settings.conditional; + requiredTags = [...targetPreset.settings.requiredTags].sort((a, b) => a.localeCompare(b)); }); async function savePreset() { @@ -49,6 +54,8 @@ targetPreset.settings.name = presetName; targetPreset.settings.tags = [...tagsList]; + targetPreset.settings.conditional = isConditional; + targetPreset.settings.requiredTags = [...requiredTags]; await targetPreset.save(); await goto(`/features/presets/${targetPreset.id}`); @@ -67,6 +74,16 @@ + + + Show this preset only when specified tags are provided. + + + {#if isConditional} + + + + {/if}
From 399e75809b4b3c29cf9f697be5ededa6daabcb5f Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 17:52:35 +0400 Subject: [PATCH 2/9] Display presets when tag is found or hide it otherwise --- .../extension/presets/PresetTableRow.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/content/components/extension/presets/PresetTableRow.ts b/src/content/components/extension/presets/PresetTableRow.ts index 61bcafd..4e6a453 100644 --- a/src/content/components/extension/presets/PresetTableRow.ts +++ b/src/content/components/extension/presets/PresetTableRow.ts @@ -9,6 +9,7 @@ export default class PresetTableRow extends BaseComponent { #tagsList: HTMLElement[] = []; #applyAllButton = document.createElement('button'); #removeAllButton = document.createElement('button'); + #alternateColorDummy = document.createElement('span'); constructor(container: HTMLElement, preset: TagEditorPreset) { super(container); @@ -64,6 +65,8 @@ export default class PresetTableRow extends BaseComponent { tagsCell, actionsCell, ); + + this.#alternateColorDummy.style.display = 'none'; } protected init() { @@ -108,6 +111,26 @@ export default class PresetTableRow extends BaseComponent { }); } + #maybeRefreshVisibilityFromTags(sourceTags: Set) { + if (!this.#preset.settings.conditional || this.#isMatchesConditional(sourceTags)) { + this.container.style.display = ''; + this.#alternateColorDummy.remove(); + return; + } + + this.container.style.display = 'none'; + this.container.after(this.#alternateColorDummy); + } + + #isMatchesConditional(sourceTags: Set): boolean { + const listOfRequiredTags = this.#preset.settings.requiredTags; + + return Boolean( + listOfRequiredTags.length + && listOfRequiredTags.some(tagName => sourceTags.has(tagName)) + ); + } + updateTags(tags: Set) { for (const tagElement of this.#tagsList) { tagElement.classList.toggle( @@ -115,6 +138,8 @@ export default class PresetTableRow extends BaseComponent { !tags.has(tagElement.dataset.tagName || ''), ); } + + this.#maybeRefreshVisibilityFromTags(tags); } remove() { From b031b88512e2358dd22603d942048a105954cf61 Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 17:52:46 +0400 Subject: [PATCH 3/9] Fixed tags being user-selectable --- src/styles/content/tag-presets.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/styles/content/tag-presets.scss b/src/styles/content/tag-presets.scss index cf24ef6..9b7bdcc 100644 --- a/src/styles/content/tag-presets.scss +++ b/src/styles/content/tag-presets.scss @@ -3,6 +3,7 @@ .block.tag-presets { .tag { cursor: pointer; + user-select: none; &.is-missing { opacity: 0.5; From a45248cebffc4bb47bfdd115b5ec338323d9749c Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 18:02:54 +0400 Subject: [PATCH 4/9] Fixed crashing build due to missing trailing comma --- src/lib/extension/entities/TagEditorPreset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/extension/entities/TagEditorPreset.ts b/src/lib/extension/entities/TagEditorPreset.ts index 360bf9a..ba708a6 100644 --- a/src/lib/extension/entities/TagEditorPreset.ts +++ b/src/lib/extension/entities/TagEditorPreset.ts @@ -13,7 +13,7 @@ export default class TagEditorPreset extends StorageEntity Date: Sun, 5 Apr 2026 18:18:52 +0400 Subject: [PATCH 5/9] Show when preset is conditional in the viewer block --- src/components/features/PresetView.svelte | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/features/PresetView.svelte b/src/components/features/PresetView.svelte index 4dcc1b4..bdd1a32 100644 --- a/src/components/features/PresetView.svelte +++ b/src/components/features/PresetView.svelte @@ -10,6 +10,7 @@ let { preset }: PresetViewProps = $props(); const sortedTagsList = $derived(preset.settings.tags.toSorted((a, b) => a.localeCompare(b))); + const requiredTagsList = $derived(preset.settings.requiredTags.toSorted((a, b) => a.localeCompare(b))); @@ -24,3 +25,11 @@ be automatically removed from the editor. {/if} +{#if preset.settings.conditional} + + This preset will only appear when one of the tags below are present on image. + + + + +{/if} From 3f9412b02de545fe13be4090fc4467e11c8bb3b7 Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 18:27:02 +0400 Subject: [PATCH 6/9] A bit more concrete wording for checkbox --- src/routes/features/presets/[id]/edit/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/features/presets/[id]/edit/+page.svelte b/src/routes/features/presets/[id]/edit/+page.svelte index 1af79a5..41dfd77 100644 --- a/src/routes/features/presets/[id]/edit/+page.svelte +++ b/src/routes/features/presets/[id]/edit/+page.svelte @@ -84,7 +84,7 @@ - Show this preset only when specified tags are provided. + Show this preset only when any of specified tags are provided. {#if isConditional} From 66fd093e5ae32dbc09702c1c2993596ab49d3166 Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 18:29:47 +0400 Subject: [PATCH 7/9] Marking unchanged properties as readonly --- .../components/extension/presets/PresetTableRow.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/content/components/extension/presets/PresetTableRow.ts b/src/content/components/extension/presets/PresetTableRow.ts index 0de7860..a38fa9e 100644 --- a/src/content/components/extension/presets/PresetTableRow.ts +++ b/src/content/components/extension/presets/PresetTableRow.ts @@ -5,12 +5,13 @@ import { EVENT_PRESET_TAG_CHANGE_APPLIED } from "$content/components/events/pres import { createFontAwesomeIcon } from "$lib/dom-utils"; export default class PresetTableRow extends BaseComponent { - #preset: TagEditorPreset; + readonly #preset: TagEditorPreset; + readonly #applyAllButton = document.createElement('button'); + readonly #removeAllButton = document.createElement('button'); + readonly #exclusiveWarning = document.createElement('div'); + readonly #alternateColorDummy = document.createElement('span'); + #tagsList: HTMLElement[] = []; - #applyAllButton = document.createElement('button'); - #removeAllButton = document.createElement('button'); - #exclusiveWarning = document.createElement('div'); - #alternateColorDummy = document.createElement('span'); constructor(container: HTMLElement, preset: TagEditorPreset) { super(container); From b4419b5de320a55f5505d4ad3cf0316daa152df6 Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 18:33:34 +0400 Subject: [PATCH 8/9] Validate `exclusive` and `conditional` as optional booleans --- src/lib/extension/transporting/validators.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/lib/extension/transporting/validators.ts b/src/lib/extension/transporting/validators.ts index 510a591..53ceceb 100644 --- a/src/lib/extension/transporting/validators.ts +++ b/src/lib/extension/transporting/validators.ts @@ -32,6 +32,14 @@ function validateOptionalArray(value: unknown): boolean { return typeof value === 'undefined' || value === null || Array.isArray(value); } +/** + * Check if the following value is not set or is a valid boolean. + * @param value Value to be checked. + */ +function validateOptionalBoolean(value: unknown): boolean { + return typeof value === 'undefined' || typeof value === 'boolean'; +} + /** * Map of validators for each entity. Function should throw the error if validation failed. */ @@ -73,7 +81,8 @@ const entitiesValidators: EntitiesValidationMap = { !validateRequiredString(importedObject?.id) || !validateRequiredString(importedObject?.name) || !validateOptionalArray(importedObject?.tags) - || typeof importedObject.conditional !== 'boolean' + || !validateOptionalBoolean(importedObject?.exclusive) + || !validateOptionalBoolean(importedObject?.conditional) || !validateOptionalArray(importedObject?.requiredTags) ) { throw new Error('Invalid preset format detected!'); From c12b00817b0fa771eb57cde86c315b46f819ca65 Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sun, 5 Apr 2026 18:35:26 +0400 Subject: [PATCH 9/9] Compare value to undefined instead of calling `typeof` --- src/lib/extension/transporting/validators.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/extension/transporting/validators.ts b/src/lib/extension/transporting/validators.ts index 53ceceb..1ff6150 100644 --- a/src/lib/extension/transporting/validators.ts +++ b/src/lib/extension/transporting/validators.ts @@ -29,7 +29,7 @@ function validateRequiredString(value: unknown): boolean { * @param value Value to be checked. */ function validateOptionalArray(value: unknown): boolean { - return typeof value === 'undefined' || value === null || Array.isArray(value); + return value === undefined || value === null || Array.isArray(value); } /** @@ -37,7 +37,7 @@ function validateOptionalArray(value: unknown): boolean { * @param value Value to be checked. */ function validateOptionalBoolean(value: unknown): boolean { - return typeof value === 'undefined' || typeof value === 'boolean'; + return value === undefined || typeof value === 'boolean'; } /**