diff options
author | Wolfgang Müller | 2025-02-13 19:04:12 +0100 |
---|---|---|
committer | Wolfgang Müller | 2025-02-13 19:04:12 +0100 |
commit | 618f72b31d57ac17f475dbe983a31627cff3b96e (patch) | |
tree | 21cc384917ad64fe726d6356d3616df4b7507927 | |
parent | 341fc19d4b7e9d8fb8b9a9d72377cf36565f2f2e (diff) | |
download | hircine-618f72b31d57ac17f475dbe983a31627cff3b96e.tar.gz |
frontend: Allow control-clicking to open the quick filter
This makes hircine's behaviour more consistent with standard browser
behaviour (that would also open a new tab when control-clicking).
-rw-r--r-- | frontend/src/lib/Navigation.ts | 6 | ||||
-rw-r--r-- | frontend/src/lib/components/Cardlet.svelte | 19 | ||||
-rw-r--r-- | frontend/src/lib/selection/Selectable.svelte | 36 | ||||
-rw-r--r-- | frontend/src/routes/artists/+page.svelte | 9 | ||||
-rw-r--r-- | frontend/src/routes/characters/+page.svelte | 9 | ||||
-rw-r--r-- | frontend/src/routes/circles/+page.svelte | 9 | ||||
-rw-r--r-- | frontend/src/routes/namespaces/+page.svelte | 9 | ||||
-rw-r--r-- | frontend/src/routes/tags/+page.svelte | 9 | ||||
-rw-r--r-- | frontend/src/routes/worlds/+page.svelte | 9 |
9 files changed, 72 insertions, 43 deletions
diff --git a/frontend/src/lib/Navigation.ts b/frontend/src/lib/Navigation.ts index f3bc413..4dcb998 100644 --- a/frontend/src/lib/Navigation.ts +++ b/frontend/src/lib/Navigation.ts @@ -1,5 +1,5 @@ import { goto as svelteGoto } from '$app/navigation'; -import { SortDirection } from '$gql/graphql'; +import { SortDirection, type ComicFilter } from '$gql/graphql'; import JsonURL from '@jsonurl/jsonurl'; import { toastError } from './Toasts'; import type { Key } from './Utils'; @@ -120,3 +120,7 @@ export function navigate(params: NavigationParameters<object>, current?: URLSear export function href<T>(base: string, params: NavigationParameters<T>) { return `/${base}/?${parametersFrom(params).toString()}`; } + +export function quickComicFilter(id: number | string, filter: keyof ComicFilter) { + window.open(href('comics', { filter: { include: { [filter]: { all: [id] } } } })); +} diff --git a/frontend/src/lib/components/Cardlet.svelte b/frontend/src/lib/components/Cardlet.svelte index d249cc8..d0c0509 100644 --- a/frontend/src/lib/components/Cardlet.svelte +++ b/frontend/src/lib/components/Cardlet.svelte @@ -1,30 +1,15 @@ <script lang="ts"> - import type { ComicFilter } from '$gql/graphql'; - import { href } from '$lib/Navigation'; import type { Snippet } from 'svelte'; interface Props { name: string; title?: string | null; - filter?: keyof ComicFilter; - id?: number | string; overlay?: Snippet; onclick: (event: MouseEvent) => void; + onauxclick?: (event: MouseEvent) => void; } - let { - name, - title = undefined, - filter = undefined, - id = undefined, - overlay, - onclick - }: Props = $props(); - - const onauxclick = (e: MouseEvent) => { - if (filter === undefined || id === undefined || e.button !== 1) return; - window.open(href('comics', { filter: { include: { [filter]: { all: [id] } } } })); - }; + let { name, title = undefined, overlay, onclick, onauxclick = undefined }: Props = $props(); </script> <button diff --git a/frontend/src/lib/selection/Selectable.svelte b/frontend/src/lib/selection/Selectable.svelte index 4705f44..439d6b7 100644 --- a/frontend/src/lib/selection/Selectable.svelte +++ b/frontend/src/lib/selection/Selectable.svelte @@ -2,25 +2,47 @@ import type { Snippet } from 'svelte'; import { getSelectionContext } from './Selection.svelte'; + interface SnippetProps { + onclick: (event: MouseEvent) => void; + onauxclick: (event: MouseEvent) => void; + selected: boolean; + } + interface Props { id: number; index: number; - edit?: ((id: number) => void) | undefined; - children?: Snippet<[{ onclick: (event: MouseEvent) => void; selected: boolean }]>; + onclick?: (id: number) => void; + onauxclick?: (id: number) => void; + children?: Snippet<[SnippetProps]>; } - let { id, index, edit = undefined, children }: Props = $props(); + let { + id, + index, + onclick: onclick = undefined, + onauxclick = undefined, + children + }: Props = $props(); + let selection = getSelectionContext(); - const onclick = (event: MouseEvent) => { + const click = (event: MouseEvent) => { if (selection.active) { selection.update(index, event.shiftKey); event.preventDefault(); - } else if (edit) { - edit(id); + } else if (event.ctrlKey && onauxclick) { + onauxclick(id); + } else if (onclick) { + onclick(id); event.preventDefault(); } }; + + const auxclick = (event: MouseEvent) => { + if (event.button === 1 && onauxclick) { + onauxclick(id); + } + }; </script> -{@render children?.({ onclick, selected: selection.contains(id) })} +{@render children?.({ onclick: click, onauxclick: auxclick, selected: selection.contains(id) })} diff --git a/frontend/src/routes/artists/+page.svelte b/frontend/src/routes/artists/+page.svelte index c907470..9f0d893 100644 --- a/frontend/src/routes/artists/+page.svelte +++ b/frontend/src/routes/artists/+page.svelte @@ -4,6 +4,7 @@ import type { Artist } from '$gql/graphql'; import { ArtistSortLabel } from '$lib/Enums'; import { BasicFilterContext } from '$lib/Filter.svelte'; + import { quickComicFilter } from '$lib/Navigation'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; import Cardlet from '$lib/components/Cardlet.svelte'; @@ -53,6 +54,8 @@ .then((artist) => modals.open(EditArtist, { artist })) .catch(toastFinally); }; + + const quickFilter = (id: number) => quickComicFilter(id, 'artists'); </script> <Head section="artists" /> @@ -78,9 +81,9 @@ <main> <Cardlets> {#each artists.edges as { id, name }, index (id)} - <Selectable {index} {id} {edit}> - {#snippet children({ onclick, selected })} - <Cardlet {name} {onclick} filter="artists" {id}> + <Selectable {index} {id} onclick={edit} onauxclick={quickFilter}> + {#snippet children({ onclick, onauxclick, selected })} + <Cardlet {name} {onclick} {onauxclick}> {#snippet overlay()} <SelectionOverlay position="right" centered {selected} /> {/snippet} diff --git a/frontend/src/routes/characters/+page.svelte b/frontend/src/routes/characters/+page.svelte index 04c72cb..3a4b737 100644 --- a/frontend/src/routes/characters/+page.svelte +++ b/frontend/src/routes/characters/+page.svelte @@ -4,6 +4,7 @@ import type { Character } from '$gql/graphql'; import { CharacterSortLabel } from '$lib/Enums'; import { BasicFilterContext } from '$lib/Filter.svelte'; + import { quickComicFilter } from '$lib/Navigation'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; import Cardlet from '$lib/components/Cardlet.svelte'; @@ -53,6 +54,8 @@ .then((character) => modals.open(EditCharacter, { character })) .catch(toastFinally); }; + + const quickFilter = (id: number) => quickComicFilter(id, 'characters'); </script> <Head section="characters" /> @@ -78,9 +81,9 @@ <main> <Cardlets> {#each characters.edges as { id, name }, index (id)} - <Selectable {index} {id} {edit}> - {#snippet children({ onclick, selected })} - <Cardlet {name} {onclick} filter="characters" {id}> + <Selectable {index} {id} onclick={edit} onauxclick={quickFilter}> + {#snippet children({ onclick, onauxclick, selected })} + <Cardlet {name} {onclick} {onauxclick}> {#snippet overlay()} <SelectionOverlay position="right" centered {selected} /> {/snippet} diff --git a/frontend/src/routes/circles/+page.svelte b/frontend/src/routes/circles/+page.svelte index 57520f8..8bac7ed 100644 --- a/frontend/src/routes/circles/+page.svelte +++ b/frontend/src/routes/circles/+page.svelte @@ -4,6 +4,7 @@ import type { Circle } from '$gql/graphql'; import { CircleSortLabel } from '$lib/Enums'; import { BasicFilterContext } from '$lib/Filter.svelte'; + import { quickComicFilter } from '$lib/Navigation'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; import Cardlet from '$lib/components/Cardlet.svelte'; @@ -53,6 +54,8 @@ .then((circle) => modals.open(EditCircle, { circle })) .catch(toastFinally); }; + + const quickFilter = (id: number) => quickComicFilter(id, 'circles'); </script> <Head section="circles" /> @@ -78,9 +81,9 @@ <main> <Cardlets> {#each circles.edges as { id, name }, index (id)} - <Selectable {index} {id} {edit}> - {#snippet children({ onclick, selected })} - <Cardlet {name} {onclick} filter="circles" {id}> + <Selectable {index} {id} onclick={edit} onauxclick={quickFilter}> + {#snippet children({ onclick, onauxclick, selected })} + <Cardlet {name} {onclick} {onauxclick}> {#snippet overlay()} <SelectionOverlay position="right" centered {selected} /> {/snippet} diff --git a/frontend/src/routes/namespaces/+page.svelte b/frontend/src/routes/namespaces/+page.svelte index 04f7737..d8e728d 100644 --- a/frontend/src/routes/namespaces/+page.svelte +++ b/frontend/src/routes/namespaces/+page.svelte @@ -4,6 +4,7 @@ import type { Namespace } from '$gql/graphql'; import { NamespaceSortLabel } from '$lib/Enums'; import { BasicFilterContext } from '$lib/Filter.svelte'; + import { quickComicFilter } from '$lib/Navigation'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; import Cardlet from '$lib/components/Cardlet.svelte'; @@ -53,6 +54,8 @@ .then((namespace) => modals.open(EditNamespace, { namespace })) .catch(toastFinally); }; + + const quickFilter = (id: number) => quickComicFilter(`${id}:`, 'tags'); </script> <Head section="Namespaces" /> @@ -78,9 +81,9 @@ <main> <Cardlets> {#each namespaces.edges as { id, name }, index (id)} - <Selectable {index} {id} {edit}> - {#snippet children({ onclick, selected })} - <Cardlet {name} {onclick} filter="tags" id={`${id}:`}> + <Selectable {index} {id} onclick={edit} onauxclick={quickFilter}> + {#snippet children({ onclick, onauxclick, selected })} + <Cardlet {name} {onclick} {onauxclick}> {#snippet overlay()} <SelectionOverlay position="right" centered {selected} /> {/snippet} diff --git a/frontend/src/routes/tags/+page.svelte b/frontend/src/routes/tags/+page.svelte index 30554c7..f71267f 100644 --- a/frontend/src/routes/tags/+page.svelte +++ b/frontend/src/routes/tags/+page.svelte @@ -4,6 +4,7 @@ import { type Tag } from '$gql/graphql'; import { TagSortLabel } from '$lib/Enums'; import { TagFilterContext } from '$lib/Filter.svelte'; + import { quickComicFilter } from '$lib/Navigation'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; import Cardlet from '$lib/components/Cardlet.svelte'; @@ -58,6 +59,8 @@ .then((tag) => modals.open(EditTag, { tag })) .catch(toastFinally); }; + + const quickFilter = (id: number) => quickComicFilter(`:${id}`, 'tags'); </script> <Head section="Tags" /> @@ -88,9 +91,9 @@ <main> <Cardlets> {#each tags.edges as { id, name, description }, index (id)} - <Selectable {index} {id} {edit}> - {#snippet children({ onclick, selected })} - <Cardlet {name} title={description} {onclick} filter="tags" id={`:${id}`}> + <Selectable {index} {id} onclick={edit} onauxclick={quickFilter}> + {#snippet children({ onclick, onauxclick, selected })} + <Cardlet {name} title={description} {onclick} {onauxclick}> {#snippet overlay()} <SelectionOverlay position="right" centered {selected} /> {/snippet} diff --git a/frontend/src/routes/worlds/+page.svelte b/frontend/src/routes/worlds/+page.svelte index f223a61..6b95142 100644 --- a/frontend/src/routes/worlds/+page.svelte +++ b/frontend/src/routes/worlds/+page.svelte @@ -4,6 +4,7 @@ import type { World } from '$gql/graphql'; import { WorldSortLabel } from '$lib/Enums'; import { BasicFilterContext } from '$lib/Filter.svelte'; + import { quickComicFilter } from '$lib/Navigation'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; import Cardlet from '$lib/components/Cardlet.svelte'; @@ -53,6 +54,8 @@ .then((world) => modals.open(EditWorld, { world })) .catch(toastFinally); }; + + const quickFilter = (id: number) => quickComicFilter(id, 'worlds'); </script> <Head section="worlds" /> @@ -78,9 +81,9 @@ <main> <Cardlets> {#each worlds.edges as { id, name }, index (id)} - <Selectable {index} {id} {edit}> - {#snippet children({ onclick, selected })} - <Cardlet {name} {onclick} filter="worlds" {id}> + <Selectable {index} {id} onclick={edit} onauxclick={quickFilter}> + {#snippet children({ onclick, onauxclick, selected })} + <Cardlet {name} {onclick} {onauxclick}> {#snippet overlay()} <SelectionOverlay position="right" centered {selected} /> {/snippet} |