From 33890b0aa8c27acac05923593cbd18709b2d039b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Sat, 6 Apr 2024 15:37:13 +0200 Subject: [PATCH] feat: improve responsiveness --- src/i18n/de/index.ts | 1 + src/i18n/en/index.ts | 1 + .../components/layout/GenericLayout.svelte | 3 + src/lib/components/layout/Layout.svelte | 27 ++--- src/lib/serial/connection.ts | 2 +- src/routes/+layout.svelte | 2 + src/routes/Footer.svelte | 1 - src/routes/config/chords/+page.svelte | 110 +++++++++++------- 8 files changed, 93 insertions(+), 54 deletions(-) diff --git a/src/i18n/de/index.ts b/src/i18n/de/index.ts index f75cddda..507dae91 100644 --- a/src/i18n/de/index.ts +++ b/src/i18n/de/index.ts @@ -115,6 +115,7 @@ 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 422c4be9..ee846e02 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -114,6 +114,7 @@ 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/lib/components/layout/GenericLayout.svelte b/src/lib/components/layout/GenericLayout.svelte index 30f42da0..ac2adfb4 100644 --- a/src/lib/components/layout/GenericLayout.svelte +++ b/src/lib/components/layout/GenericLayout.svelte @@ -13,6 +13,8 @@ import { getContext } from "svelte"; import type { VisualLayoutConfig } from "./visual-layout.js"; import { changes, ChangeType, layout } from "$lib/undo-redo"; + import { fly } from "svelte/transition"; + import { expoOut } from "svelte/easing"; const { scale, margin, strokeWidth, fontSize, iconFontSize } = getContext("visual-layout-config"); @@ -194,6 +196,7 @@ class="print" viewBox="0 0 {layoutInfo.size[0] * scale} {layoutInfo.size[1] * scale}" bind:this={groupParent} + transition:fly={{ y: 48, easing: expoOut }} > {#each layoutInfo.keys as key, i} >("active-layer"); @@ -32,20 +33,20 @@
-
- {#each layers as [title, icon, value]} - - {/each} -
- {#await layouts[device]() then visualLayout} +
+ {#each layers as [title, icon, value]} + + {/each} +
+ {/await}
diff --git a/src/lib/serial/connection.ts b/src/lib/serial/connection.ts index 862e9b6d..2e6cd1a7 100644 --- a/src/lib/serial/connection.ts +++ b/src/lib/serial/connection.ts @@ -57,7 +57,7 @@ export async function initSerial(manual = false) { const device = get(serialPort) ?? new CharaDevice(); await device.init(manual); serialPort.set(device); - sync(); + await sync(); } export async function sync() { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index dd14e93f..dd0f9916 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -56,6 +56,7 @@ const dark = it.mode === "dark"; // window.matchMedia("(prefers-color-scheme: dark)").matches applyTheme(theme, { target: document.body, dark }); }); + if (import.meta.env.TAURI_FAMILY === undefined) { const { initPwa } = await import("./pwa-setup"); webManifestLink = await initPwa(); @@ -64,6 +65,7 @@ if (browser && $userPreferences.autoConnect && (await canAutoConnect())) { await initSerial(); } + if (data.importFile) { restoreFromFile(data.importFile); const url = new URL(location.href); diff --git a/src/routes/Footer.svelte b/src/routes/Footer.svelte index d27522f3..692c9db1 100644 --- a/src/routes/Footer.svelte +++ b/src/routes/Footer.svelte @@ -68,7 +68,6 @@ {/if} - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
  • import { KEYMAP_CODES } from "$lib/serial/keymap-codes"; - import flexsearch from "flexsearch"; + import FlexSearch from "flexsearch"; import LL from "../../../i18n/i18n-svelte"; import { action } from "$lib/title"; import { onDestroy, onMount, setContext } from "svelte"; @@ -8,8 +8,10 @@ import type { ChordInfo } from "$lib/undo-redo"; import { derived, writable } from "svelte/store"; import ChordEdit from "./ChordEdit.svelte"; - import { crossfade } from "svelte/transition"; + import { crossfade, fly } from "svelte/transition"; import ChordActionEdit from "./ChordActionEdit.svelte"; + import { browser } from "$app/environment"; + import { expoOut } from "svelte/easing"; const resultSize = 38; let results: HTMLElement; @@ -28,13 +30,15 @@ resizeObserver?.disconnect(); }); - $: searchIndex = $chords?.length > 0 ? buildIndex($chords) : undefined; + let searchIndex = derived(chords, (chords) => buildIndex(chords)); - function buildIndex(chords: ChordInfo[]): flexsearch.Index { - const index = new flexsearch.Index({ tokenize: "full" }); - chords.forEach((chord, i) => { + async function buildIndex(chords: ChordInfo[]): Promise { + const index = new FlexSearch.Index({ tokenize: "full" }); + if (chords.length === 0 || !browser) return index; + for (let i = 0; i < chords.length; i++) { + const chord = chords[i]!; if ("phrase" in chord) { - index.add( + await index.addAsync( i, chord.phrase .map((it) => KEYMAP_CODES.get(it)?.id) @@ -42,17 +46,17 @@ .join(""), ); } - }); + } return index; } const searchFilter = writable(undefined); - function search(event: Event) { + async function search(index: FlexSearch.Index, event: Event) { const query = (event.target as HTMLInputElement).value; searchFilter.set( query && searchIndex - ? (searchIndex.search(query) as number[]) + ? ((await index.searchAsync(query)) as number[]) : undefined, ); page = 0; @@ -97,11 +101,19 @@
    - + {#await $searchIndex} + + {:then index} + search(index, event)} + /> + {/await}
    {#if $lastPage !== -1} {page + 1} / {$lastPage + 1} @@ -122,28 +134,32 @@
    - - {#if page === 0} - - {/if} - {#if $lastPage !== -1} - {#each $items.slice(page * $pageSize - (page === 0 ? 0 : 1), (page + 1) * $pageSize - 1) as [chord] (JSON.stringify(chord?.id))} - {#if chord} - - - +
    + {#await $searchIndex then} +
    insertChord(detail)} - />
    + {#if $lastPage !== -1} + {#if page === 0} + + {/if} + {#each $items.slice(page * $pageSize - (page === 0 ? 0 : 1), (page + 1) * $pageSize - 1) as [chord] (JSON.stringify(chord?.id))} + {#if chord} + + + + {/if} + {/each} + {:else} + {/if} - {/each} - {:else} - - {/if} -
    insertChord(detail)} + />
    {$LL.configure.chords.search.NO_RESULTS()}{$LL.configure.chords.search.NO_RESULTS()}
    + + {/await} +
    @@ -187,8 +203,16 @@ } } - caption { - margin-top: 156px; + @keyframes pulse { + 0% { + opacity: 0.1; + } + 50% { + opacity: 0.8; + } + 100% { + opacity: 0.1; + } } input[type="search"] { @@ -225,6 +249,10 @@ border-style: solid; outline: none; } + + &:disabled { + animation: pulse 1s infinite; + } } section { @@ -239,10 +267,14 @@ border-radius: 16px; } + .results { + height: 100%; + min-width: min(90vw, 16.5cm); + } + table { height: fit-content; overflow: hidden; - min-width: min(90vw, 16.5cm); transition: all 1s ease; }