fix: duplicate chords crash

fix: duplicate confirm dialog does not show affected chord
fixes #137
fixes #163
This commit is contained in:
2025-02-14 15:17:22 +01:00
parent fb1f5b7ec7
commit f319714489
4 changed files with 56 additions and 31 deletions

View File

@@ -1,13 +1,14 @@
<script lang="ts"> <script lang="ts">
import Dialog from "$lib/dialogs/Dialog.svelte"; import Dialog from "$lib/dialogs/Dialog.svelte";
import ActionString from "$lib/components/ActionString.svelte"; import type { Chord } from "$lib/serial/chord";
import ChordActionEdit from "../../routes/(app)/config/chords/ChordActionEdit.svelte";
let { let {
title, title,
message, message,
abortTitle, abortTitle,
confirmTitle, confirmTitle,
actions = [], chord,
onabort, onabort,
onconfirm, onconfirm,
}: { }: {
@@ -15,7 +16,7 @@
message?: string; message?: string;
abortTitle: string; abortTitle: string;
confirmTitle: string; confirmTitle: string;
actions: number[]; chord: Chord & { deleted: boolean };
onabort: () => void; onabort: () => void;
onconfirm: () => void; onconfirm: () => void;
} = $props(); } = $props();
@@ -26,7 +27,20 @@
{#if message} {#if message}
<p>{@html message}</p> <p>{@html message}</p>
{/if} {/if}
<p><ActionString {actions} /></p> <p>
<ChordActionEdit
chord={{
...chord,
isApplied: false,
phraseChanged: false,
actionsChanged: false,
sortBy: "",
id: chord.actions,
}}
interactive={false}
onsubmit={() => {}}
/>
</p>
<div class="buttons"> <div class="buttons">
<button onclick={onabort}>{abortTitle}</button> <button onclick={onabort}>{abortTitle}</button>
<button class="primary" onclick={onconfirm}>{confirmTitle}</button> <button class="primary" onclick={onconfirm}>{confirmTitle}</button>

View File

@@ -1,33 +1,34 @@
import ConfirmDialog from "$lib/dialogs/ConfirmDialog.svelte"; import ConfirmDialog from "$lib/dialogs/ConfirmDialog.svelte";
import { mount, unmount } from "svelte";
import type { Chord } from "$lib/serial/chord";
export async function askForConfirmation( export async function askForConfirmation(
title: string, title: string,
message: string, message: string,
confirmTitle: string, confirmTitle: string,
abortTitle: string, abortTitle: string,
actions: number[], chord: Chord,
): Promise<boolean> { ): Promise<boolean> {
const dialog = new ConfirmDialog({ let resolvePromise: (value: boolean) => void;
const resultPromise = new Promise<boolean>((resolve) => {
resolvePromise = resolve;
});
const dialog = mount(ConfirmDialog, {
target: document.body, target: document.body,
props: { props: {
title, title,
message, message,
confirmTitle, confirmTitle,
abortTitle, abortTitle,
actions, chord,
onabort: () => resolvePromise(false),
onconfirm: () => resolvePromise(true),
}, },
}); });
let resolvePromise: (value: boolean) => void;
const resultPromise = new Promise<boolean>((resolve) => {
resolvePromise = resolve;
});
dialog.$on("abort", () => resolvePromise(false));
dialog.$on("confirm", () => resolvePromise(true));
const result = await resultPromise; const result = await resultPromise;
dialog.$destroy(); unmount(dialog);
return result; return result;
} }

View File

@@ -39,7 +39,7 @@
}); });
} }
} }
let redoQueue: Change[] = $state([]); let redoQueue: Change[][] = $state([]);
async function save() { async function save() {
try { try {
@@ -47,10 +47,10 @@
if (!port) return; if (!port) return;
$syncStatus = "uploading"; $syncStatus = "uploading";
for (const [id, { actions, phrase, deleted }] of $overlay.chords) { for (const [id, chord] of $overlay.chords) {
if (!deleted) { if (!chord.deleted) {
if (id !== JSON.stringify(actions)) { if (id !== JSON.stringify(chord.actions)) {
const existingChord = await port.getChordPhrase(actions); const existingChord = await port.getChordPhrase(chord.actions);
if ( if (
existingChord !== undefined && existingChord !== undefined &&
!(await askForConfirmation( !(await askForConfirmation(
@@ -58,26 +58,30 @@
$LL.configure.chords.conflict.DESCRIPTION(), $LL.configure.chords.conflict.DESCRIPTION(),
$LL.configure.chords.conflict.CONFIRM(), $LL.configure.chords.conflict.CONFIRM(),
$LL.configure.chords.conflict.ABORT(), $LL.configure.chords.conflict.ABORT(),
actions.slice(0, actions.lastIndexOf(0)), chord,
)) ))
) { ) {
changes.update((changes) => changes.update((changes) =>
changes.filter( changes
(it) => .map((it) =>
!( it.filter(
it.type === ChangeType.Chord && (it) =>
JSON.stringify(it.id) === id !(
it.type === ChangeType.Chord &&
JSON.stringify(it.id) === id
),
), ),
), )
.filter((it) => it.length > 0),
); );
continue; continue;
} }
await port.deleteChord({ actions: JSON.parse(id) }); await port.deleteChord({ actions: JSON.parse(id) });
} }
await port.setChord({ actions, phrase }); await port.setChord({ actions: chord.actions, phrase: chord.phrase });
} else { } else {
await port.deleteChord({ actions }); await port.deleteChord({ actions: chord.actions });
} }
} }

View File

@@ -13,7 +13,12 @@
let { let {
chord = undefined, chord = undefined,
onsubmit, onsubmit,
}: { chord?: ChordInfo; onsubmit: (actions: number[]) => void } = $props(); interactive = true,
}: {
chord?: ChordInfo;
interactive?: boolean;
onsubmit: (actions: number[]) => void;
} = $props();
let pressedKeys = new SvelteSet<number>(); let pressedKeys = new SvelteSet<number>();
let editing = $state(false); let editing = $state(false);
@@ -129,6 +134,7 @@
onkeydown={keydown} onkeydown={keydown}
onkeyup={keyup} onkeyup={keyup}
onblur={keyup} onblur={keyup}
disabled={!interactive}
> >
{#if editing && pressedKeys.size === 0} {#if editing && pressedKeys.size === 0}
<span>{$LL.configure.chords.HOLD_KEYS()}</span> <span>{$LL.configure.chords.HOLD_KEYS()}</span>