feat: improve responsiveness

This commit is contained in:
2024-04-06 15:37:13 +02:00
parent 6f925de1af
commit 33890b0aa8
8 changed files with 93 additions and 54 deletions

View File

@@ -115,6 +115,7 @@ const de = {
DUPLICATE: "Akkord existiert bereits", DUPLICATE: "Akkord existiert bereits",
search: { search: {
PLACEHOLDER: "{0} Akkord{{|e}} durchsuchen", PLACEHOLDER: "{0} Akkord{{|e}} durchsuchen",
INDEXING: "{0} Akkord{{|e}} werden indiziert...",
NO_RESULTS: "Keine Ergebnisse", NO_RESULTS: "Keine Ergebnisse",
}, },
conflict: { conflict: {

View File

@@ -114,6 +114,7 @@ const en = {
DUPLICATE: "Chord already exists", DUPLICATE: "Chord already exists",
search: { search: {
PLACEHOLDER: "Search {0} chord{{|s}}", PLACEHOLDER: "Search {0} chord{{|s}}",
INDEXING: "Indexing {0} chord{{|s}}...",
NO_RESULTS: "No results", NO_RESULTS: "No results",
}, },
conflict: { conflict: {

View File

@@ -13,6 +13,8 @@
import { getContext } from "svelte"; import { getContext } from "svelte";
import type { VisualLayoutConfig } from "./visual-layout.js"; import type { VisualLayoutConfig } from "./visual-layout.js";
import { changes, ChangeType, layout } from "$lib/undo-redo"; import { changes, ChangeType, layout } from "$lib/undo-redo";
import { fly } from "svelte/transition";
import { expoOut } from "svelte/easing";
const { scale, margin, strokeWidth, fontSize, iconFontSize } = const { scale, margin, strokeWidth, fontSize, iconFontSize } =
getContext<VisualLayoutConfig>("visual-layout-config"); getContext<VisualLayoutConfig>("visual-layout-config");
@@ -194,6 +196,7 @@
class="print" class="print"
viewBox="0 0 {layoutInfo.size[0] * scale} {layoutInfo.size[1] * scale}" viewBox="0 0 {layoutInfo.size[0] * scale} {layoutInfo.size[1] * scale}"
bind:this={groupParent} bind:this={groupParent}
transition:fly={{ y: 48, easing: expoOut }}
> >
{#each layoutInfo.keys as key, i} {#each layoutInfo.keys as key, i}
<KeyboardKey <KeyboardKey

View File

@@ -5,6 +5,7 @@
import { getContext } from "svelte"; import { getContext } from "svelte";
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import type { VisualLayout } from "$lib/serialization/visual-layout"; import type { VisualLayout } from "$lib/serialization/visual-layout";
import { fade } from "svelte/transition";
$: device = $serialPort?.device ?? "ONE"; $: device = $serialPort?.device ?? "ONE";
const activeLayer = getContext<Writable<number>>("active-layer"); const activeLayer = getContext<Writable<number>>("active-layer");
@@ -32,7 +33,8 @@
</script> </script>
<div class="container"> <div class="container">
<fieldset> {#await layouts[device]() then visualLayout}
<fieldset transition:fade>
{#each layers as [title, icon, value]} {#each layers as [title, icon, value]}
<button <button
class="icon" class="icon"
@@ -45,7 +47,6 @@
{/each} {/each}
</fieldset> </fieldset>
{#await layouts[device]() then visualLayout}
<GenericLayout {visualLayout} /> <GenericLayout {visualLayout} />
{/await} {/await}
</div> </div>

View File

@@ -57,7 +57,7 @@ export async function initSerial(manual = false) {
const device = get(serialPort) ?? new CharaDevice(); const device = get(serialPort) ?? new CharaDevice();
await device.init(manual); await device.init(manual);
serialPort.set(device); serialPort.set(device);
sync(); await sync();
} }
export async function sync() { export async function sync() {

View File

@@ -56,6 +56,7 @@
const dark = it.mode === "dark"; // window.matchMedia("(prefers-color-scheme: dark)").matches const dark = it.mode === "dark"; // window.matchMedia("(prefers-color-scheme: dark)").matches
applyTheme(theme, { target: document.body, dark }); applyTheme(theme, { target: document.body, dark });
}); });
if (import.meta.env.TAURI_FAMILY === undefined) { if (import.meta.env.TAURI_FAMILY === undefined) {
const { initPwa } = await import("./pwa-setup"); const { initPwa } = await import("./pwa-setup");
webManifestLink = await initPwa(); webManifestLink = await initPwa();
@@ -64,6 +65,7 @@
if (browser && $userPreferences.autoConnect && (await canAutoConnect())) { if (browser && $userPreferences.autoConnect && (await canAutoConnect())) {
await initSerial(); await initSerial();
} }
if (data.importFile) { if (data.importFile) {
restoreFromFile(data.importFile); restoreFromFile(data.importFile);
const url = new URL(location.href); const url = new URL(location.href);

View File

@@ -68,7 +68,6 @@
{/if} {/if}
<SyncOverlay /> <SyncOverlay />
</div> </div>
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
<ul> <ul>
<li class="hide-forced-colors"> <li class="hide-forced-colors">
<input <input

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { KEYMAP_CODES } from "$lib/serial/keymap-codes"; import { KEYMAP_CODES } from "$lib/serial/keymap-codes";
import flexsearch from "flexsearch"; import FlexSearch from "flexsearch";
import LL from "../../../i18n/i18n-svelte"; import LL from "../../../i18n/i18n-svelte";
import { action } from "$lib/title"; import { action } from "$lib/title";
import { onDestroy, onMount, setContext } from "svelte"; import { onDestroy, onMount, setContext } from "svelte";
@@ -8,8 +8,10 @@
import type { ChordInfo } from "$lib/undo-redo"; import type { ChordInfo } from "$lib/undo-redo";
import { derived, writable } from "svelte/store"; import { derived, writable } from "svelte/store";
import ChordEdit from "./ChordEdit.svelte"; import ChordEdit from "./ChordEdit.svelte";
import { crossfade } from "svelte/transition"; import { crossfade, fly } from "svelte/transition";
import ChordActionEdit from "./ChordActionEdit.svelte"; import ChordActionEdit from "./ChordActionEdit.svelte";
import { browser } from "$app/environment";
import { expoOut } from "svelte/easing";
const resultSize = 38; const resultSize = 38;
let results: HTMLElement; let results: HTMLElement;
@@ -28,13 +30,15 @@
resizeObserver?.disconnect(); resizeObserver?.disconnect();
}); });
$: searchIndex = $chords?.length > 0 ? buildIndex($chords) : undefined; let searchIndex = derived(chords, (chords) => buildIndex(chords));
function buildIndex(chords: ChordInfo[]): flexsearch.Index { async function buildIndex(chords: ChordInfo[]): Promise<FlexSearch.Index> {
const index = new flexsearch.Index({ tokenize: "full" }); const index = new FlexSearch.Index({ tokenize: "full" });
chords.forEach((chord, i) => { if (chords.length === 0 || !browser) return index;
for (let i = 0; i < chords.length; i++) {
const chord = chords[i]!;
if ("phrase" in chord) { if ("phrase" in chord) {
index.add( await index.addAsync(
i, i,
chord.phrase chord.phrase
.map((it) => KEYMAP_CODES.get(it)?.id) .map((it) => KEYMAP_CODES.get(it)?.id)
@@ -42,17 +46,17 @@
.join(""), .join(""),
); );
} }
}); }
return index; return index;
} }
const searchFilter = writable<number[] | undefined>(undefined); const searchFilter = writable<number[] | undefined>(undefined);
function search(event: Event) { async function search(index: FlexSearch.Index, event: Event) {
const query = (event.target as HTMLInputElement).value; const query = (event.target as HTMLInputElement).value;
searchFilter.set( searchFilter.set(
query && searchIndex query && searchIndex
? (searchIndex.search(query) as number[]) ? ((await index.searchAsync(query)) as number[])
: undefined, : undefined,
); );
page = 0; page = 0;
@@ -97,11 +101,19 @@
</svelte:head> </svelte:head>
<div class="search-container"> <div class="search-container">
{#await $searchIndex}
<input
type="search"
placeholder={$LL.configure.chords.search.INDEXING($chords.length)}
disabled={true}
/>
{:then index}
<input <input
type="search" type="search"
placeholder={$LL.configure.chords.search.PLACEHOLDER($chords.length)} placeholder={$LL.configure.chords.search.PLACEHOLDER($chords.length)}
on:input={search} on:input={(event) => search(index, event)}
/> />
{/await}
<div class="paginator"> <div class="paginator">
{#if $lastPage !== -1} {#if $lastPage !== -1}
{page + 1} / {$lastPage + 1} {page + 1} / {$lastPage + 1}
@@ -122,7 +134,10 @@
</div> </div>
<section bind:this={results}> <section bind:this={results}>
<table> <div class="results">
{#await $searchIndex then}
<table transition:fly={{ y: 48, easing: expoOut }}>
{#if $lastPage !== -1}
{#if page === 0} {#if page === 0}
<tr <tr
><th class="new-chord" ><th class="new-chord"
@@ -132,7 +147,6 @@
><td /><td /></tr ><td /><td /></tr
> >
{/if} {/if}
{#if $lastPage !== -1}
{#each $items.slice(page * $pageSize - (page === 0 ? 0 : 1), (page + 1) * $pageSize - 1) as [chord] (JSON.stringify(chord?.id))} {#each $items.slice(page * $pageSize - (page === 0 ? 0 : 1), (page + 1) * $pageSize - 1) as [chord] (JSON.stringify(chord?.id))}
{#if chord} {#if chord}
<tr> <tr>
@@ -144,6 +158,8 @@
<caption>{$LL.configure.chords.search.NO_RESULTS()}</caption> <caption>{$LL.configure.chords.search.NO_RESULTS()}</caption>
{/if} {/if}
</table> </table>
{/await}
</div>
<textarea placeholder={$LL.configure.chords.TRY_TYPING()}></textarea> <textarea placeholder={$LL.configure.chords.TRY_TYPING()}></textarea>
</section> </section>
@@ -187,8 +203,16 @@
} }
} }
caption { @keyframes pulse {
margin-top: 156px; 0% {
opacity: 0.1;
}
50% {
opacity: 0.8;
}
100% {
opacity: 0.1;
}
} }
input[type="search"] { input[type="search"] {
@@ -225,6 +249,10 @@
border-style: solid; border-style: solid;
outline: none; outline: none;
} }
&:disabled {
animation: pulse 1s infinite;
}
} }
section { section {
@@ -239,10 +267,14 @@
border-radius: 16px; border-radius: 16px;
} }
.results {
height: 100%;
min-width: min(90vw, 16.5cm);
}
table { table {
height: fit-content; height: fit-content;
overflow: hidden; overflow: hidden;
min-width: min(90vw, 16.5cm);
transition: all 1s ease; transition: all 1s ease;
} }
</style> </style>