refactor: use standard prettier formatting

This commit is contained in:
2024-04-06 13:15:35 +02:00
parent 86ec8651b6
commit 854ab6d3be
106 changed files with 2703 additions and 2046 deletions

View File

@@ -1,73 +1,74 @@
<script lang="ts">
import {KEYMAP_CATEGORIES, KEYMAP_CODES} from "$lib/serial/keymap-codes"
import type {KeyInfo} from "$lib/serial/keymap-codes"
import Index from "flexsearch"
import {createEventDispatcher} from "svelte"
import ActionListItem from "$lib/components/ActionListItem.svelte"
import LL from "../../../i18n/i18n-svelte"
import {action} from "$lib/title"
import { KEYMAP_CATEGORIES, KEYMAP_CODES } from "$lib/serial/keymap-codes";
import type { KeyInfo } from "$lib/serial/keymap-codes";
import Index from "flexsearch";
import { createEventDispatcher } from "svelte";
import ActionListItem from "$lib/components/ActionListItem.svelte";
import LL from "../../../i18n/i18n-svelte";
import { action } from "$lib/title";
export let currentAction: number | undefined = undefined
export let nextAction: number | undefined = undefined
export let currentAction: number | undefined = undefined;
export let nextAction: number | undefined = undefined;
const index = new Index({tokenize: "full"})
const index = new Index({ tokenize: "full" });
for (const action of Object.values(KEYMAP_CODES)) {
index?.add(
action.code,
`${action.title || ""} ${action.variant || ""} ${action.category} ${action.id || ""} ${
action.description || ""
}`,
)
);
}
const exactIndex: Record<string, KeyInfo> = Object.fromEntries(
Object.values(KEYMAP_CODES)
.filter(it => !!it.id)
.map(it => [it.id, it] as const),
)
.filter((it) => !!it.id)
.map((it) => [it.id, it] as const),
);
function search() {
results = index!.search(searchBox.value)
exact = exactIndex[searchBox.value]?.code
code = Number(searchBox.value)
results = index!.search(searchBox.value);
exact = exactIndex[searchBox.value]?.code;
code = Number(searchBox.value);
}
function select(id?: number) {
if (id !== undefined) {
dispatch("select", id)
dispatch("select", id);
}
}
function keyboardNavigation(event: KeyboardEvent) {
if (event.shiftKey && event.key === "Enter") {
dispatch("select", exact)
dispatch("select", exact);
} else if (event.key === "ArrowDown") {
const element =
resultList.querySelector("li:focus-within")?.nextSibling ?? resultList.querySelector("li:not(.exact)")
resultList.querySelector("li:focus-within")?.nextSibling ??
resultList.querySelector("li:not(.exact)");
if (element instanceof HTMLLIElement) {
element.querySelector("button")?.focus()
element.querySelector("button")?.focus();
}
} else if (event.key === "ArrowUp") {
const element =
resultList.querySelector("li:focus-within")?.previousSibling ??
resultList.querySelector("li:not(.exact)")
resultList.querySelector("li:not(.exact)");
if (element instanceof HTMLLIElement) {
element.querySelector("button")?.focus()
element.querySelector("button")?.focus();
}
} else {
searchBox.focus()
return
searchBox.focus();
return;
}
event.preventDefault()
event.preventDefault();
}
let results: number[] = Object.keys(KEYMAP_CODES).map(Number)
let exact: number | undefined = undefined
let code: number = Number.NaN
let results: number[] = Object.keys(KEYMAP_CODES).map(Number);
let exact: number | undefined = undefined;
let code: number = Number.NaN;
const dispatch = createEventDispatcher()
let searchBox: HTMLInputElement
let resultList: HTMLUListElement
let filter: Set<number>
const dispatch = createEventDispatcher();
let searchBox: HTMLInputElement;
let resultList: HTMLUListElement;
let filter: Set<number>;
</script>
<svelte:window on:keydown={keyboardNavigation} />
@@ -80,18 +81,18 @@
type="search"
bind:this={searchBox}
on:input={search}
on:keypress={event => {
on:keypress={(event) => {
if (event.key === "Enter") {
select(exact)
select(exact);
}
}}
placeholder={$LL.actionSearch.PLACEHOLDER()}
/>
<button on:click={() => select(0)} use:action={{shortcut: "shift+esc"}}
<button on:click={() => select(0)} use:action={{ shortcut: "shift+esc" }}
>{$LL.actionSearch.DELETE()}</button
>
<button
use:action={{title: $LL.modal.CLOSE(), shortcut: "esc"}}
use:action={{ title: $LL.modal.CLOSE(), shortcut: "esc" }}
class="icon"
on:click={() => dispatch("close")}>close</button
>
@@ -143,7 +144,7 @@
<li>Action code is out of range</li>
{/if}
{/if}
{#each filter ? results.filter(it => filter.has(it)) : results as id (id)}
{#each filter ? results.filter( (it) => filter.has(it), ) : results as id (id)}
<li><ActionListItem {id} on:click={() => select(id)} /></li>
{/each}
</ul>

View File

@@ -1,177 +1,189 @@
<script lang="ts">
import {compileLayout} from "$lib/serialization/visual-layout"
import type {VisualLayout, CompiledLayoutKey} from "$lib/serialization/visual-layout"
import {deviceLayout} from "$lib/serial/connection"
import {dev} from "$app/environment"
import ActionSelector from "$lib/components/layout/ActionSelector.svelte"
import {get} from "svelte/store"
import type {Writable} from "svelte/store"
import KeyboardKey from "$lib/components/layout/KeyboardKey.svelte"
import {getContext} from "svelte"
import type {VisualLayoutConfig} from "./visual-layout.js"
import {changes, ChangeType, layout} from "$lib/undo-redo"
import { compileLayout } from "$lib/serialization/visual-layout";
import type {
VisualLayout,
CompiledLayoutKey,
} from "$lib/serialization/visual-layout";
import { deviceLayout } from "$lib/serial/connection";
import { dev } from "$app/environment";
import ActionSelector from "$lib/components/layout/ActionSelector.svelte";
import { get } from "svelte/store";
import type { Writable } from "svelte/store";
import KeyboardKey from "$lib/components/layout/KeyboardKey.svelte";
import { getContext } from "svelte";
import type { VisualLayoutConfig } from "./visual-layout.js";
import { changes, ChangeType, layout } from "$lib/undo-redo";
const {scale, margin, strokeWidth, fontSize, iconFontSize} =
getContext<VisualLayoutConfig>("visual-layout-config")
const activeLayer = getContext<Writable<number>>("active-layer")
const { scale, margin, strokeWidth, fontSize, iconFontSize } =
getContext<VisualLayoutConfig>("visual-layout-config");
const activeLayer = getContext<Writable<number>>("active-layer");
if (dev) {
// you have absolutely no idea what a difference this makes for performance
console.assert(scale % 1 === 0, "Scale must be an integer")
console.assert((scale / 2) % 1 === 0, "Scale must be divisible by 2")
console.assert(strokeWidth % 1 === 0, "Stroke must be an integer")
console.assert(margin % 1 === 0, "Margin must be an integer")
console.assert(fontSize % 1 === 0, "Font size must be an integer")
console.assert(iconFontSize % 1 === 0, "Icon font size must be an integer")
console.assert(scale % 1 === 0, "Scale must be an integer");
console.assert((scale / 2) % 1 === 0, "Scale must be divisible by 2");
console.assert(strokeWidth % 1 === 0, "Stroke must be an integer");
console.assert(margin % 1 === 0, "Margin must be an integer");
console.assert(fontSize % 1 === 0, "Font size must be an integer");
console.assert(iconFontSize % 1 === 0, "Icon font size must be an integer");
}
export let visualLayout: VisualLayout
$: layoutInfo = compileLayout(visualLayout)
export let visualLayout: VisualLayout;
$: layoutInfo = compileLayout(visualLayout);
function getCenter(key: CompiledLayoutKey): [x: number, y: number] {
return [key.pos[0] + key.size[0] / 2, key.pos[1] + key.size[1] / 2]
return [key.pos[0] + key.size[0] / 2, key.pos[1] + key.size[1] / 2];
}
function getDistance(a: CompiledLayoutKey, b: CompiledLayoutKey) {
const x1 = a.pos[0] + margin
const y1 = a.pos[1] + margin
const x1b = x1 + a.size[0] - margin
const y1b = y1 + a.size[1] - margin
const x2 = b.pos[0] + margin
const y2 = b.pos[1] + margin
const x2b = x2 + b.size[0] - margin
const y2b = y2 + b.size[1] - margin
const x1 = a.pos[0] + margin;
const y1 = a.pos[1] + margin;
const x1b = x1 + a.size[0] - margin;
const y1b = y1 + a.size[1] - margin;
const x2 = b.pos[0] + margin;
const y2 = b.pos[1] + margin;
const x2b = x2 + b.size[0] - margin;
const y2b = y2 + b.size[1] - margin;
const left = x2b < x1
const right = x1b < x2
const bottom = y2b < y1
const top = y1b < y2
const left = x2b < x1;
const right = x1b < x2;
const bottom = y2b < y1;
const top = y1b < y2;
return top && left
? Math.sqrt((x1 - x2b) ** 2 + (y1b - y2) ** 2)
: left && bottom
? Math.sqrt((x1 - x2b) ** 2 + (y1 - y2b) ** 2)
: bottom && right
? Math.sqrt((x1b - x2) ** 2 + (y1 - y2b) ** 2)
: right && top
? Math.sqrt((x1b - x2) ** 2 + (y1b - y2) ** 2)
: left
? x1 - x2b
: right
? x2 - x1b
: bottom
? y1 - y2b
: top
? y2 - y1b
: 0
? Math.sqrt((x1 - x2b) ** 2 + (y1 - y2b) ** 2)
: bottom && right
? Math.sqrt((x1b - x2) ** 2 + (y1 - y2b) ** 2)
: right && top
? Math.sqrt((x1b - x2) ** 2 + (y1b - y2) ** 2)
: left
? x1 - x2b
: right
? x2 - x1b
: bottom
? y1 - y2b
: top
? y2 - y1b
: 0;
}
function navigate(event: KeyboardEvent) {
if (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) return
if (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey)
return;
let wantedAngle: number
const angleThreshold = Math.PI
let wantedAngle: number;
const angleThreshold = Math.PI;
if (event.key === "ArrowUp") wantedAngle = Math.PI
else if (event.key === "ArrowDown") wantedAngle = 0
else if (event.key === "ArrowRight") wantedAngle = Math.PI / 2
else if (event.key === "ArrowLeft") wantedAngle = -Math.PI / 2
else return
if (event.key === "ArrowUp") wantedAngle = Math.PI;
else if (event.key === "ArrowDown") wantedAngle = 0;
else if (event.key === "ArrowRight") wantedAngle = Math.PI / 2;
else if (event.key === "ArrowLeft") wantedAngle = -Math.PI / 2;
else return;
event.preventDefault()
if (!focusKey) (groupParent.firstChild as SVGGElement).focus()
const [focusX, focusY] = getCenter(focusKey)
event.preventDefault();
if (!focusKey) (groupParent.firstChild as SVGGElement).focus();
const [focusX, focusY] = getCenter(focusKey);
let bestDistance = Infinity
let bestCandidate = 0
let isOptimalAngle = false
let bestDistance = Infinity;
let bestCandidate = 0;
let isOptimalAngle = false;
for (const [i, key] of layoutInfo.keys.entries()) {
if (key === focusKey) continue
const [keyX, keyY] = getCenter(key)
const deltaX = keyX - focusX
const deltaY = keyY - focusY
const angle = Math.atan2(deltaX, deltaY)
const distance = getDistance(key, focusKey)
if (key === focusKey) continue;
const [keyX, keyY] = getCenter(key);
const deltaX = keyX - focusX;
const deltaY = keyY - focusY;
const angle = Math.atan2(deltaX, deltaY);
const distance = getDistance(key, focusKey);
const angleDelta = Math.abs(wantedAngle - angle)
const angleDelta = Math.abs(wantedAngle - angle);
if (isOptimalAngle ? angleDelta > Number.EPSILON : angleDelta >= angleThreshold) continue
if (distance > bestDistance) continue
if (
isOptimalAngle
? angleDelta > Number.EPSILON
: angleDelta >= angleThreshold
)
continue;
if (distance > bestDistance) continue;
bestDistance = distance
bestCandidate = i
isOptimalAngle = angleDelta <= Number.EPSILON
bestDistance = distance;
bestCandidate = i;
isOptimalAngle = angleDelta <= Number.EPSILON;
}
const node = groupParent.children.item(bestCandidate)
const node = groupParent.children.item(bestCandidate);
if (node instanceof SVGGElement) {
node.focus()
node.focus();
}
}
function edit(index: number) {
const keyInfo = layoutInfo.keys[index]
const clickedGroup = groupParent.children.item(index) as SVGGElement
const nextAction = get(layout)[get(activeLayer)][keyInfo.id]
const currentAction = get(deviceLayout)[get(activeLayer)][keyInfo.id]
const keyInfo = layoutInfo.keys[index];
const clickedGroup = groupParent.children.item(index) as SVGGElement;
const nextAction = get(layout)[get(activeLayer)][keyInfo.id];
const currentAction = get(deviceLayout)[get(activeLayer)][keyInfo.id];
const component = new ActionSelector({
target: document.body,
props: {
currentAction,
nextAction: nextAction.isApplied ? undefined : nextAction.action,
},
})
const dialog = document.querySelector("dialog > div") as HTMLDivElement
const backdrop = document.querySelector("dialog") as HTMLDialogElement
const dialogRect = dialog.getBoundingClientRect()
const groupRect = clickedGroup.getBoundingClientRect()
});
const dialog = document.querySelector("dialog > div") as HTMLDivElement;
const backdrop = document.querySelector("dialog") as HTMLDialogElement;
const dialogRect = dialog.getBoundingClientRect();
const groupRect = clickedGroup.getBoundingClientRect();
const scale = 0.5
const scale = 0.5;
const dialogScale = `${1 - scale * (1 - groupRect.width / dialogRect.width)} ${
1 - scale * (1 - groupRect.height / dialogRect.height)
}`
}`;
const dialogTranslate = `${scale * (groupRect.x - dialogRect.x)}px ${
scale * (groupRect.y - dialogRect.y)
}px`
}px`;
const duration = 150
const options = {duration, easing: "ease"}
const duration = 150;
const options = { duration, easing: "ease" };
const dialogAnimation = dialog.animate(
[
{scale: dialogScale, translate: dialogTranslate},
{translate: "0 0", scale: "1"},
{ scale: dialogScale, translate: dialogTranslate },
{ translate: "0 0", scale: "1" },
],
options,
)
const backdropAnimation = backdrop.animate([{opacity: 0}, {opacity: 1}], options)
);
const backdropAnimation = backdrop.animate(
[{ opacity: 0 }, { opacity: 1 }],
options,
);
async function closed() {
dialogAnimation.reverse()
backdropAnimation.reverse()
dialogAnimation.reverse();
backdropAnimation.reverse();
await dialogAnimation.finished
await dialogAnimation.finished;
component.$destroy()
component.$destroy();
}
component.$on("close", closed)
component.$on("select", ({detail}) => {
changes.update(changes => {
component.$on("close", closed);
component.$on("select", ({ detail }) => {
changes.update((changes) => {
changes.push({
type: ChangeType.Layout,
id: keyInfo.id,
layer: get(activeLayer),
action: detail,
})
return changes
})
closed()
})
});
return changes;
});
closed();
});
}
let focusKey: CompiledLayoutKey
let groupParent: SVGElement
let focusKey: CompiledLayoutKey;
let groupParent: SVGElement;
</script>
<svelte:window on:keydown={navigate} />
@@ -187,9 +199,9 @@
{key}
on:focusin={() => (focusKey = key)}
on:click={() => edit(i)}
on:keypress={({key}) => {
on:keypress={({ key }) => {
if (key === "Enter") {
edit(i)
edit(i);
}
}}
/>

View File

@@ -1,30 +1,35 @@
<script lang="ts">
import {getContext} from "svelte"
import type {Writable} from "svelte/store"
import type {VisualLayoutConfig} from "$lib/components/layout/visual-layout"
import type {CompiledLayoutKey} from "$lib/serialization/visual-layout"
import {layout} from "$lib/undo-redo.js"
import {osLayout} from "$lib/os-layout.js"
import {KEYMAP_CODES} from "$lib/serial/keymap-codes"
import {action} from "$lib/title"
import { getContext } from "svelte";
import type { Writable } from "svelte/store";
import type { VisualLayoutConfig } from "$lib/components/layout/visual-layout";
import type { CompiledLayoutKey } from "$lib/serialization/visual-layout";
import { layout } from "$lib/undo-redo.js";
import { osLayout } from "$lib/os-layout.js";
import { KEYMAP_CODES } from "$lib/serial/keymap-codes";
import { action } from "$lib/title";
const {fontSize, margin, inactiveOpacity, inactiveScale, iconFontSize} =
getContext<VisualLayoutConfig>("visual-layout-config")
const activeLayer = getContext<Writable<number>>("active-layer")
const { fontSize, margin, inactiveOpacity, inactiveScale, iconFontSize } =
getContext<VisualLayoutConfig>("visual-layout-config");
const activeLayer = getContext<Writable<number>>("active-layer");
export let key: CompiledLayoutKey
export let fontSizeMultiplier = 1
export let key: CompiledLayoutKey;
export let fontSizeMultiplier = 1;
export let middle: [number, number]
export let pos: [number, number]
export let rotate: number
export let middle: [number, number];
export let pos: [number, number];
export let rotate: number;
export let positions: [[number, number], [number, number], [number, number]]
export let positions: [[number, number], [number, number], [number, number]];
</script>
{#each positions as position, layer}
{@const {action: actionId, isApplied} = $layout[layer][key.id] ?? {action: 0, isApplied: true}}
{@const {code, icon, id, display, title, keyCode, variant} = KEYMAP_CODES[actionId] ?? {code: actionId}}
{@const { action: actionId, isApplied } = $layout[layer][key.id] ?? {
action: 0,
isApplied: true,
}}
{@const { code, icon, id, display, title, keyCode, variant } = KEYMAP_CODES[
actionId
] ?? { code: actionId }}
{@const dynamicMapping = keyCode && $osLayout.get(keyCode)}
{@const tooltip =
(title ?? id ?? `0x${code.toString(16)}`) +
@@ -50,7 +55,7 @@
? "0 0 0"
: `${direction[0].toPrecision(2)}px ${direction[1].toPrecision(2)}px 0`}
style:rotate="{rotate}deg"
use:action={{title: tooltip}}
use:action={{ title: tooltip }}
>
{#if code !== 0}
{dynamicMapping || icon || display || id || `0x${code.toString(16)}`}

View File

@@ -1,20 +1,29 @@
<script lang="ts">
import type {CompiledLayoutKey} from "$lib/serialization/visual-layout"
import {getContext} from "svelte"
import type {VisualLayoutConfig} from "./visual-layout.js"
import KeyText from "$lib/components/layout/KeyText.svelte"
import type { CompiledLayoutKey } from "$lib/serialization/visual-layout";
import { getContext } from "svelte";
import type { VisualLayoutConfig } from "./visual-layout.js";
import KeyText from "$lib/components/layout/KeyText.svelte";
const {scale, margin, strokeWidth} = getContext<VisualLayoutConfig>("visual-layout-config")
export let i: number
export let key: CompiledLayoutKey
const { scale, margin, strokeWidth } = getContext<VisualLayoutConfig>(
"visual-layout-config",
);
export let i: number;
export let key: CompiledLayoutKey;
$: posX = key.pos[0] * scale
$: posY = key.pos[1] * scale
$: sizeX = key.size[0] * scale
$: sizeY = key.size[1] * scale
$: posX = key.pos[0] * scale;
$: posY = key.pos[1] * scale;
$: sizeX = key.size[0] * scale;
$: sizeY = key.size[1] * scale;
</script>
<g class="key-group" on:click on:keypress on:focusin role="button" tabindex={i + 1}>
<g
class="key-group"
on:click
on:keypress
on:focusin
role="button"
tabindex={i + 1}
>
{#if key.shape === "square"}
<rect
x={posX + margin}
@@ -44,15 +53,23 @@
{@const multiplier = 1.25}
{@const rotateRad = (key.rotate + 45) * (Math.PI / 180)}
{@const rotX = Math.round((Math.abs(Math.cos(rotateRad - Math.PI / 2)) + Number.EPSILON) * 100) / 100}
{@const rotY = Math.round((Math.abs(Math.sin(rotateRad - Math.PI / 2)) + Number.EPSILON) * 100) / 100}
{@const rotX =
Math.round(
(Math.abs(Math.cos(rotateRad - Math.PI / 2)) + Number.EPSILON) * 100,
) / 100}
{@const rotY =
Math.round(
(Math.abs(Math.sin(rotateRad - Math.PI / 2)) + Number.EPSILON) * 100,
) / 100}
{@const rc = r1 - (r1 - r2) / 2}
{@const middleX = Math.cos(rotateRad) * rc}
{@const middleY = Math.sin(rotateRad) * rc}
<path
style:transform="rotateZ({key.rotate}deg) translate({innerMargin}px, {innerMargin}px)"
d="M{posX + p1},{posY} a{r1},{r1} 0 0,1 {-p1},{p1} l0,{-(p1 - p2)} a{r2},{r2} 0 0,0 {p2},{-p2}z"
d="M{posX + p1},{posY} a{r1},{r1} 0 0,1 {-p1},{p1} l0,{-(
p1 - p2
)} a{r2},{r2} 0 0,0 {p2},{-p2}z"
/>
<KeyText
{key}

View File

@@ -1,25 +1,34 @@
<script lang="ts">
import {serialPort} from "$lib/serial/connection"
import {action} from "$lib/title"
import GenericLayout from "$lib/components/layout/GenericLayout.svelte"
import {getContext} from "svelte"
import type {Writable} from "svelte/store"
import type {VisualLayout} from "$lib/serialization/visual-layout"
import { serialPort } from "$lib/serial/connection";
import { action } from "$lib/title";
import GenericLayout from "$lib/components/layout/GenericLayout.svelte";
import { getContext } from "svelte";
import type { Writable } from "svelte/store";
import type { VisualLayout } from "$lib/serialization/visual-layout";
$: device = $serialPort?.device ?? "ONE"
const activeLayer = getContext<Writable<number>>("active-layer")
$: device = $serialPort?.device ?? "ONE";
const activeLayer = getContext<Writable<number>>("active-layer");
const layers = [
["Numeric Layer", "123", 1],
["Primary Layer", "abc", 0],
["Function Layer", "function", 2],
] as const
] as const;
const layouts = {
ONE: () => import("$lib/assets/layouts/one.yml").then(it => it.default as VisualLayout),
LITE: () => import("$lib/assets/layouts/lite.yml").then(it => it.default as VisualLayout),
X: () => import("$lib/assets/layouts/generic/103-key.yml").then(it => it.default as VisualLayout),
}
ONE: () =>
import("$lib/assets/layouts/one.yml").then(
(it) => it.default as VisualLayout,
),
LITE: () =>
import("$lib/assets/layouts/lite.yml").then(
(it) => it.default as VisualLayout,
),
X: () =>
import("$lib/assets/layouts/generic/103-key.yml").then(
(it) => it.default as VisualLayout,
),
};
</script>
<div class="container">
@@ -27,7 +36,7 @@
{#each layers as [title, icon, value]}
<button
class="icon"
use:action={{title, shortcut: `alt+${value + 1}`}}
use:action={{ title, shortcut: `alt+${value + 1}` }}
on:click={() => ($activeLayer = value)}
class:active={$activeLayer === value}
>

View File

@@ -1,9 +1,9 @@
export interface VisualLayoutConfig {
scale: number
inactiveScale: number
inactiveOpacity: number
strokeWidth: number
margin: number
fontSize: number
iconFontSize: number
scale: number;
inactiveScale: number;
inactiveOpacity: number;
strokeWidth: number;
margin: number;
fontSize: number;
iconFontSize: number;
}