diff --git a/src/i18n/de/index.ts b/src/i18n/de/index.ts index f75cddda..3b951b90 100644 --- a/src/i18n/de/index.ts +++ b/src/i18n/de/index.ts @@ -124,6 +124,7 @@ const de = { CONFIRM: "Überschreiben", ABORT: "Überspringen", }, + VOCABULARY: "Vokabelliste", TRY_TYPING: "Versuche hier zu tippen", }, layout: { diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index 422c4be9..5af8b2ed 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -123,6 +123,7 @@ const en = { CONFIRM: "Overwrite", ABORT: "Skip", }, + VOCABULARY: "Vocabulary", TRY_TYPING: "Try typing here", }, layout: { diff --git a/src/routes/config/chords/+page.svelte b/src/routes/config/chords/+page.svelte index a50ffc6d..1a45b514 100644 --- a/src/routes/config/chords/+page.svelte +++ b/src/routes/config/chords/+page.svelte @@ -43,6 +43,24 @@ buildIndex($chords, $osLayout).then(searchIndex.set); } + function plainPhrase(phrase: number[], osLayout: Map) { + return phrase + .map((it) => { + const info = KEYMAP_CODES.get(it); + if (!info) return ""; + + const bestGuess = + (info.keyCode && osLayout.get(info.keyCode)) || + info.display || + info.id || + ""; + + return bestGuess.length === 1 ? bestGuess : ""; + }) + .filter((it) => !!it) + .join(""); + } + async function buildIndex( chords: ChordInfo[], osLayout: Map, @@ -60,20 +78,7 @@ progress = i; if ("phrase" in chord) { - await index.addAsync( - i, - chord.phrase - .map((it) => { - const info = KEYMAP_CODES.get(it); - if (!info) return ""; - - return ( - (info.keyCode && osLayout.get(info.keyCode)) || info.id || "" - ); - }) - .filter((it) => !!it) - .join(""), - ); + await index.addAsync(i, plainPhrase(chord.phrase, osLayout)); } } return index; @@ -108,6 +113,24 @@ }); } + function downloadVocabulary() { + const vocabulary = new Set( + $chords.map((it) => + "phrase" in it ? plainPhrase(it.phrase, $osLayout).trim() : "", + ), + ); + vocabulary.delete(""); + const blob = new Blob([Array.from(vocabulary).join("|")], { + type: "text/plain", + }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = "vocabulary.txt"; + a.click(); + URL.revokeObjectURL(url); + } + const items = derived( [searchFilter, chords], ([filter, chords]) => @@ -182,11 +205,17 @@ {/if} - + {/await} @@ -207,7 +236,17 @@ visibility: hidden; } + .sidebar { + display: flex; + flex-direction: column; + + > button { + padding-inline-start: 0; + } + } + textarea { + flex: 1; transition: outline-color 250ms ease; background: none; color: inherit;