diff --git a/src/i18n/de/index.ts b/src/i18n/de/index.ts index 507dae91..f75cddda 100644 --- a/src/i18n/de/index.ts +++ b/src/i18n/de/index.ts @@ -115,7 +115,6 @@ const de = { DUPLICATE: "Akkord existiert bereits", search: { PLACEHOLDER: "{0} Akkord{{|e}} durchsuchen", - INDEXING: "{0} Akkord{{|e}} werden indiziert...", NO_RESULTS: "Keine Ergebnisse", }, conflict: { diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index ee846e02..422c4be9 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -114,7 +114,6 @@ const en = { DUPLICATE: "Chord already exists", search: { PLACEHOLDER: "Search {0} chord{{|s}}", - INDEXING: "Indexing {0} chord{{|s}}...", NO_RESULTS: "No results", }, conflict: { diff --git a/src/routes/config/chords/+page.svelte b/src/routes/config/chords/+page.svelte index deb9d1c3..96b02605 100644 --- a/src/routes/config/chords/+page.svelte +++ b/src/routes/config/chords/+page.svelte @@ -3,7 +3,7 @@ import FlexSearch from "flexsearch"; import LL from "../../../i18n/i18n-svelte"; import { action } from "$lib/title"; - import { onDestroy, onMount, setContext } from "svelte"; + import { onDestroy, onMount, setContext, tick } from "svelte"; import { changes, ChangeType, chords } from "$lib/undo-redo"; import type { ChordInfo } from "$lib/undo-redo"; import { derived, writable } from "svelte/store"; @@ -12,12 +12,16 @@ import ChordActionEdit from "./ChordActionEdit.svelte"; import { browser } from "$app/environment"; import { expoOut } from "svelte/easing"; + import { osLayout } from "$lib/os-layout"; const resultSize = 38; let results: HTMLElement; const pageSize = writable(0); let resizeObserver: ResizeObserver; + let abortIndexing: (() => void) | undefined; + let progress = 0; + onMount(() => { resizeObserver = new ResizeObserver(() => { pageSize.set(Math.floor(results.clientHeight / resultSize)); @@ -30,18 +34,42 @@ resizeObserver?.disconnect(); }); - let searchIndex = derived(chords, (chords) => buildIndex(chords)); + let index = new FlexSearch.Index({ tokenize: "full" }); + let searchIndex = writable(undefined); + $: { + abortIndexing?.(); + progress = 0; + buildIndex($chords, $osLayout).then(searchIndex.set); + } - async function buildIndex(chords: ChordInfo[]): Promise { - const index = new FlexSearch.Index({ tokenize: "full" }); + async function buildIndex( + chords: ChordInfo[], + osLayout: Map, + ): Promise { if (chords.length === 0 || !browser) return index; + index = new FlexSearch.Index({ tokenize: "full" }); + let abort = false; + abortIndexing = () => { + abort = true; + }; for (let i = 0; i < chords.length; i++) { + if (abort) return index; + const chord = chords[i]!; + progress = i; + if ("phrase" in chord) { await index.addAsync( i, chord.phrase - .map((it) => KEYMAP_CODES.get(it)?.id) + .map((it) => { + const info = KEYMAP_CODES.get(it); + if (!info) return ""; + + return ( + (info.keyCode && osLayout.get(info.keyCode)) || info.id || "" + ); + }) .filter((it) => !!it) .join(""), ); @@ -101,19 +129,12 @@
- {#await $searchIndex} - - {:then index} - search(index, event)} - /> - {/await} + search($searchIndex, event)} + class:loading={progress !== $chords.length - 1} + />
{#if $lastPage !== -1} {page + 1} / {$lastPage + 1} @@ -135,7 +156,8 @@
- {#await $searchIndex then} + + {#await tick() then} {#if $lastPage !== -1} {#if page === 0} @@ -184,20 +206,13 @@ transition: outline-color 250ms ease; background: none; color: inherit; - outline: 1px dashed var(--md-sys-color-surface-variant); + border: 1px dashed var(--md-sys-color-outline); + outline: 2px solid transparent; + outline-offset: -1px; margin: 2px; - border: none; padding: 8px; border-radius: 4px; - @media (prefers-contrast: more) { - outline-color: var(--md-sys-color-outline); - - &:focus { - outline-width: 2px; - } - } - &:focus { outline-color: var(--md-sys-color-primary); } @@ -205,13 +220,13 @@ @keyframes pulse { 0% { - opacity: 0.1; + opacity: 0.4; } 50% { - opacity: 0.8; + opacity: 1; } 100% { - opacity: 0.1; + opacity: 0.4; } } @@ -237,11 +252,7 @@ &::placeholder { color: var(--md-sys-color-on-surface-variant); - opacity: 0.2; - - @media (prefers-contrast: more) { - opacity: 0.8; - } + opacity: 0.8; } &:focus { @@ -250,8 +261,8 @@ outline: none; } - &:disabled { - animation: pulse 1s infinite; + &.loading { + opacity: 0.4; } }