mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-02-07 09:42:41 +00:00
fix: crash when saving empty chords
This commit is contained in:
@@ -72,22 +72,26 @@ export function createSettingsBackup(): CharaSettingsFile {
|
||||
};
|
||||
}
|
||||
|
||||
export async function restoreBackup(event: Event) {
|
||||
export async function restoreBackup(
|
||||
event: Event,
|
||||
only?: "chords" | "layout" | "settings",
|
||||
) {
|
||||
const input = (event.target as HTMLInputElement).files![0];
|
||||
if (!input) return;
|
||||
const text = await input.text();
|
||||
if (input.name.endsWith(".json")) {
|
||||
restoreFromFile(JSON.parse(text));
|
||||
restoreFromFile(JSON.parse(text), only);
|
||||
} else if (isCsvLayout(text)) {
|
||||
restoreFromFile(csvLayoutToJson(text));
|
||||
restoreFromFile(csvLayoutToJson(text), only);
|
||||
} else if (isCsvChords(text)) {
|
||||
restoreFromFile(csvChordsToJson(text));
|
||||
restoreFromFile(csvChordsToJson(text), only);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
export function restoreFromFile(
|
||||
file: CharaBackupFile | CharaSettingsFile | CharaLayoutFile | CharaChordFile,
|
||||
only?: "chords" | "layout" | "settings",
|
||||
) {
|
||||
if (file.charaVersion !== 1) throw new Error("Incompatible backup");
|
||||
switch (file.type) {
|
||||
@@ -112,33 +116,45 @@ export function restoreFromFile(
|
||||
|
||||
changes.update((changes) => {
|
||||
changes.push([
|
||||
...getChangesFromChordFile(recent[0]),
|
||||
...getChangesFromLayoutFile(recent[1]),
|
||||
...getChangesFromSettingsFile(recent[2]),
|
||||
...(!only || only === "chords"
|
||||
? getChangesFromChordFile(recent[0])
|
||||
: []),
|
||||
...(!only || only === "layout"
|
||||
? getChangesFromLayoutFile(recent[1])
|
||||
: []),
|
||||
...(!only || only === "settings"
|
||||
? getChangesFromSettingsFile(recent[2])
|
||||
: []),
|
||||
]);
|
||||
return changes;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "chords": {
|
||||
changes.update((changes) => {
|
||||
changes.push(getChangesFromChordFile(file));
|
||||
return changes;
|
||||
});
|
||||
if (!only || only === "chords") {
|
||||
changes.update((changes) => {
|
||||
changes.push(getChangesFromChordFile(file));
|
||||
return changes;
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "layout": {
|
||||
changes.update((changes) => {
|
||||
changes.push(getChangesFromLayoutFile(file));
|
||||
return changes;
|
||||
});
|
||||
if (!only || only === "layout") {
|
||||
changes.update((changes) => {
|
||||
changes.push(getChangesFromLayoutFile(file));
|
||||
return changes;
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "settings": {
|
||||
changes.update((changes) => {
|
||||
changes.push(getChangesFromSettingsFile(file));
|
||||
return changes;
|
||||
});
|
||||
if (!only || only === "settings") {
|
||||
changes.update((changes) => {
|
||||
changes.push(getChangesFromSettingsFile(file));
|
||||
return changes;
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { serialLog, serialPort } from "$lib/serial/connection";
|
||||
import { onMount } from "svelte";
|
||||
import { slide } from "svelte/transition";
|
||||
|
||||
onMount(() => {
|
||||
io.scrollTo({ top: io.scrollHeight });
|
||||
});
|
||||
|
||||
function submit(event: Event) {
|
||||
event.preventDefault();
|
||||
$serialPort?.send(0, value.trim());
|
||||
|
||||
@@ -342,23 +342,24 @@ export class CharaDevice {
|
||||
.join(" ")
|
||||
.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
const readResult = await read(timeout);
|
||||
if (readResult === undefined) {
|
||||
return readResult
|
||||
?.replace(new RegExp(`^${commandString} `), "")
|
||||
.split(" ");
|
||||
}).then((it) => {
|
||||
if (it === undefined) {
|
||||
console.error("No response");
|
||||
return Array(expectedLength).fill("NO_RESPONSE") as LengthArray<
|
||||
string,
|
||||
T
|
||||
>;
|
||||
}
|
||||
const array = readResult
|
||||
.replace(new RegExp(`^${commandString} `), "")
|
||||
.split(" ");
|
||||
if (array.length < expectedLength) {
|
||||
if (it.length < expectedLength) {
|
||||
console.error("Response too short");
|
||||
return array.concat(
|
||||
Array(expectedLength - array.length).fill("TOO_SHORT"),
|
||||
return it.concat(
|
||||
Array(expectedLength - it.length).fill("TOO_SHORT"),
|
||||
) as LengthArray<string, T>;
|
||||
}
|
||||
return array as LengthArray<string, T>;
|
||||
return it as LengthArray<string, T>;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -401,7 +402,7 @@ export class CharaDevice {
|
||||
stringifyChordActions(chord.actions),
|
||||
stringifyPhrase(chord.phrase),
|
||||
]);
|
||||
if (status !== "0") console.error(`Failed with status ${status}`);
|
||||
if (status !== "0") throw new Error(`Failed with status ${status}`);
|
||||
}
|
||||
|
||||
async deleteChord(chord: Pick<Chord, "actions">) {
|
||||
|
||||
@@ -179,6 +179,22 @@ export const chords = derived(
|
||||
},
|
||||
);
|
||||
|
||||
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) =>
|
||||
|
||||
Reference in New Issue
Block a user