feat: cv2

This commit is contained in:
2026-01-09 14:42:33 +01:00
parent dee754c015
commit 108884151e
40 changed files with 2356 additions and 2217 deletions

View File

@@ -1,16 +1,9 @@
import { persistentWritable } from "$lib/storage";
import { derived } from "svelte/store";
import { hashChord, type Chord } from "$lib/serial/chord";
import {
deviceChords,
deviceLayout,
deviceSettings,
} from "$lib/serial/connection";
import { KEYMAP_CODES } from "$lib/serial/keymap-codes";
import { deviceLayout, deviceSettings } from "$lib/serial/connection";
export enum ChangeType {
Layout,
Chord,
Setting,
}
@@ -22,14 +15,6 @@ export interface LayoutChange {
profile?: number;
}
export interface ChordChange {
type: ChangeType.Chord;
deleted?: true;
id: number[];
actions: number[];
phrase: number[];
}
export interface SettingChange {
type: ChangeType.Setting;
id: number;
@@ -42,20 +27,18 @@ export interface ChangeInfo {
isCommitted?: boolean;
}
export type Change = LayoutChange | ChordChange | SettingChange;
export type Change = LayoutChange | SettingChange;
export const changes = persistentWritable<Change[][]>("changes", []);
export interface Overlay {
layout: Array<Array<Map<number, number> | undefined> | undefined>;
chords: Map<string, Chord & { deleted: boolean }>;
settings: Array<Map<number, number> | undefined>;
}
export const overlay = derived(changes, (changes) => {
const overlay: Overlay = {
layout: [],
chords: new Map(),
settings: [],
};
@@ -71,13 +54,6 @@ export const overlay = derived(changes, (changes) => {
change.action,
);
break;
case ChangeType.Chord:
overlay.chords.set(JSON.stringify(change.id), {
actions: change.actions,
phrase: change.phrase,
deleted: change.deleted ?? false,
});
break;
case ChangeType.Setting:
change.profile ??= 0;
overlay.settings[change.profile] ??= new Map();
@@ -113,90 +89,3 @@ export const layout = derived([overlay, deviceLayout], ([overlay, profiles]) =>
),
),
);
export type ChordInfo = Chord &
ChangeInfo & {
phraseChanged: boolean;
actionsChanged: boolean;
sortBy: string;
} & {
id: number[];
deleted: boolean;
};
export const chords = derived(
[overlay, deviceChords, KEYMAP_CODES],
([overlay, chords, codes]) => {
const newChords = new Set(overlay.chords.keys());
const changedChords = chords.map<ChordInfo>((chord) => {
const id = JSON.stringify(chord.actions);
if (overlay.chords.has(id)) {
newChords.delete(id);
const changedChord = overlay.chords.get(id)!;
return {
id: chord.actions,
// use the old phrase for stable editing
sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
actions: changedChord.actions,
phrase: changedChord.phrase,
actionsChanged: id !== JSON.stringify(changedChord.actions),
phraseChanged:
JSON.stringify(chord.phrase) !==
JSON.stringify(changedChord.phrase),
isApplied: false,
deleted: changedChord.deleted,
};
} else {
return {
id: chord.actions,
sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
actions: chord.actions,
phrase: chord.phrase,
phraseChanged: false,
actionsChanged: false,
isApplied: true,
deleted: false,
};
}
});
for (const id of newChords) {
const chord = overlay.chords.get(id)!;
changedChords.push({
sortBy: "",
isApplied: false,
actionsChanged: true,
phraseChanged: false,
deleted: chord.deleted,
id: JSON.parse(id),
phrase: chord.phrase,
actions: chord.actions,
});
}
return changedChords.sort(({ sortBy: a }, { sortBy: b }) =>
a.localeCompare(b),
);
},
);
export const duplicateChords = derived(chords, (chords) => {
const duplicates = new Set<string>();
const seen = new Set<string>();
for (const chord of chords) {
const key = JSON.stringify(chord.actions);
if (seen.has(key)) {
duplicates.add(key);
} else {
seen.add(key);
}
}
return duplicates;
});
export const chordHashes = derived(
chords,
(chords) =>
new Map(chords.map((chord) => [hashChord(chord.actions), chord] as const)),
);