From 2893afa2badd1237e1805937a2af78bfab64d36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Thu, 11 Dec 2025 20:51:32 +0100 Subject: [PATCH] feat: qol improvements --- icons.config.js | 2 + src/lib/ProgressButton.svelte | 121 +++++++++++ src/lib/components/Action.svelte | 132 ++++++++---- src/lib/components/Tooltip.svelte | 9 +- .../components/layout/ActionSelector.svelte | 101 ++++++--- src/lib/components/verbose-action.ts | 9 + src/lib/hover-popover.ts | 4 +- src/lib/title.ts | 40 +++- src/routes/(app)/ConnectPopup.svelte | 199 +++++++++++++----- src/routes/(app)/Footer.svelte | 52 ++++- src/routes/(app)/Sidebar.svelte | 4 +- .../ccos/[device]/[version]/+page.svelte | 102 +-------- src/routes/(app)/config/EditActions.svelte | 71 ++++--- src/routes/(app)/config/Navigation.svelte | 15 +- src/routes/(app)/config/chords/+page.svelte | 2 +- .../config/chords/ChordPhraseEdit.svelte | 46 ++-- src/routes/(app)/config/settings/+page.svelte | 27 +-- 17 files changed, 632 insertions(+), 304 deletions(-) create mode 100644 src/lib/ProgressButton.svelte create mode 100644 src/lib/components/verbose-action.ts diff --git a/icons.config.js b/icons.config.js index ded6d2a4..8456c7ec 100644 --- a/icons.config.js +++ b/icons.config.js @@ -79,6 +79,7 @@ const config = { "palette", "translate", "smart_toy", + "visibility_off", "play_arrow", "extension", "upload_file", @@ -165,6 +166,7 @@ const config = { routine: "e20c", experiment: "e686", dictionary: "f539", + visibility_off: "e8f5", }, }; diff --git a/src/lib/ProgressButton.svelte b/src/lib/ProgressButton.svelte new file mode 100644 index 00000000..7d09e275 --- /dev/null +++ b/src/lib/ProgressButton.svelte @@ -0,0 +1,121 @@ + + + + + diff --git a/src/lib/components/Action.svelte b/src/lib/components/Action.svelte index b4f6b1d6..281d4564 100644 --- a/src/lib/components/Action.svelte +++ b/src/lib/components/Action.svelte @@ -3,11 +3,14 @@ import type { KeyInfo } from "$lib/serial/keymap-codes"; import { osLayout } from "$lib/os-layout"; import { tooltip } from "$lib/hover-popover"; + import { isVerbose } from "./verbose-action"; + import { actionTooltip } from "$lib/title"; let { action, display, - }: { action: number | KeyInfo; display: "inline-keys" | "keys" } = $props(); + }: { action: number | KeyInfo; display: "inline-keys" | "keys" | "verbose" } = + $props(); let info = $derived( typeof action === "number" @@ -15,52 +18,56 @@ : action, ); let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode)); - - let popover: HTMLElement | undefined = $state(undefined); + let hasPopover = $derived(!info.id || info.title || info.description); -{#snippet popoverSnippet()} -
- <{info.id ?? `0x${info.code.toString(16)}`}> - {#if info.title} - {info.title} - {/if} - {#if info.variant === "left"} - (Left) - {:else if info.variant === "right"} - (Right) - {/if} -
+{#snippet popover()} + {#if info.icon || info.display || !info.id} + <{info.id ?? `0x${info.code.toString(16)}`}> + {/if} + {#if info.title} + {info.title} + {/if} + {#if info.variant === "left"} + (Left) + {:else if info.variant === "right"} + (Right) + {/if} + {#if info.description} +
+ {info.description} + {/if} {/snippet} -{#if display === "keys"} +{#snippet kbdText()} + {dynamicMapping ?? + info.icon ?? + info.display ?? + info.id ?? + `0x${info.code.toString(16)}`} +{/snippet} +{#snippet kbdSnippet(withPopover = true)} - {dynamicMapping ?? - info.icon ?? - info.display ?? - info.id ?? - `0x${info.code.toString(16)}`} - {@render popoverSnippet()} + {@render kbdText()} -{:else if display === "inline-keys"} +{/snippet} +{#snippet inlineKbdSnippet()} {#if !info.icon && dynamicMapping?.length === 1} {dynamicMapping}{@render popoverSnippet()}{dynamicMapping} {:else if !info.icon && info.id?.length === 1} {info.id}{@render popoverSnippet()}{info.id} {:else} - {dynamicMapping ?? - info.icon ?? - info.display ?? - info.id ?? - `0x${info.code.toString(16)}`}{@render popoverSnippet()} + {@render kbdText()} + {/if} +{/snippet} + +{#if display === "keys"} + {@render kbdSnippet()} +{:else if display === "verbose"} + {#if isVerbose(info)} +
+ {@render kbdSnippet(false)} +
{info.title}
+
+ {:else} + {@render inlineKbdSnippet()} + {/if} +{:else if display === "inline-keys"} + {@render inlineKbdSnippet()} {/if} diff --git a/src/lib/components/Tooltip.svelte b/src/lib/components/Tooltip.svelte index e1c57659..80bebc7c 100644 --- a/src/lib/components/Tooltip.svelte +++ b/src/lib/components/Tooltip.svelte @@ -1,9 +1,14 @@ -{#if title} +{#if typeof title === "string"}

{@html title}

+{:else} + {@render title?.()} {/if} {#if shortcut} diff --git a/src/lib/components/layout/ActionSelector.svelte b/src/lib/components/layout/ActionSelector.svelte index 9a950a5e..6c134299 100644 --- a/src/lib/components/layout/ActionSelector.svelte +++ b/src/lib/components/layout/ActionSelector.svelte @@ -11,6 +11,9 @@ import LL from "$i18n/i18n-svelte"; import { action } from "$lib/title"; import { get } from "svelte/store"; + import type { KeymapCategory } from "$lib/meta/types/actions"; + import Action from "../Action.svelte"; + import { isVerbose } from "../verbose-action"; let { currentAction = undefined, @@ -26,6 +29,7 @@ onMount(() => { searchBox.focus(); + search(); }); const index = new FlexSearch.Index({ tokenize: "full" }); @@ -46,7 +50,29 @@ } async function search() { - results = (await index!.searchAsync(searchBox.value)) as number[]; + const groups = new Map( + $KEYMAP_CATEGORIES.map( + (category) => [category, []] as [KeymapCategory, KeyInfo[]], + ), + ); + const result = + searchBox.value === "" + ? Array.from($KEYMAP_CODES.keys()) + : await index!.searchAsync(searchBox.value); + for (const id of result) { + const action = $KEYMAP_CODES.get(id as number); + if (action?.category) { + groups.get(action.category)?.push(action); + } + } + + function sortValue(action: KeyInfo): number { + return isVerbose(action) ? 0 : action.id?.length === 1 ? 2 : 1; + } + for (const actions of groups.values()) { + actions.sort((a, b) => sortValue(b) - sortValue(a)); + } + results = groups; exact = get(KEYMAP_IDS).get(searchBox.value)?.code; code = Number(searchBox.value); } @@ -81,13 +107,12 @@ event.preventDefault(); } - let results: number[] = $state([]); + let results: Map = $state(new Map()); let exact: number | undefined = $state(undefined); let code: number = $state(Number.NaN); let searchBox: HTMLInputElement; let resultList: HTMLUListElement; - let filter: Set | undefined = $state(undefined); @@ -122,29 +147,6 @@ onclick={onclose}>close -
- - {#each $KEYMAP_CATEGORIES as category} - {#if category.name !== "Internal"} - - {/if} - {/each} -
{#if currentAction !== undefined}