Files
sfxkeeb/frontend/src/lib/project.ts
T
end 45075b3328 feat(frontend): use Wails bindings for file I/O
Replace hidden file inputs and anchor downloads with native open/save
dialogs via a thin platform layer. WAV export sends base64 audio data to
the Go backend for writing to the user-chosen path.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 22:23:35 -07:00

66 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { renderKeyboardTrack } from './audio/export';
import type { SampleCache } from './audio/sampleCache';
import { saveAudio, saveProject } from './platform/files';
import type { LegacySwitchType, Marker, Project, SwitchType } from './types';
import { app, setActiveSwitch, setMarkers, setSelectedIds } from './store.svelte';
const LEGACY_SWITCH_MAP: Record<LegacySwitchType, SwitchType> = {
'cherry-mx-blue': 'mxblue',
'cherry-mx-red': 'mxblack',
'cherry-mx-brown': 'mxbrown',
};
function migrateSwitch(value: string): SwitchType {
if (value in LEGACY_SWITCH_MAP) {
return LEGACY_SWITCH_MAP[value as LegacySwitchType];
}
return value as SwitchType;
}
function migrateMarker(marker: Marker): Marker {
return {
...marker,
code: marker.code,
releaseTime: marker.releaseTime,
};
}
export function buildProject(): Project {
return {
version: 2,
switch: app.activeSwitch,
markers: app.markers.map((m) => ({ ...m })),
};
}
export async function downloadProject(filename = 'project.json') {
const project = buildProject();
const content = JSON.stringify(project, null, 2);
await saveProject(content, filename);
}
export function loadProject(data: Project & { version?: number; switch?: string }) {
if (data.version !== 1 && data.version !== 2) {
throw new Error(`Unsupported project version: ${data.version}`);
}
setMarkers((data.markers ?? []).map(migrateMarker));
setActiveSwitch(migrateSwitch(data.switch ?? 'mxbrown'));
setSelectedIds(new Set());
}
/**
* Export keyboard SFX only as a WAV file (no video audio).
* Rendered client-side at 1× via OfflineAudioContext.
*/
export async function exportAudio(duration: number, cache?: SampleCache) {
const project = buildProject();
const blob = await renderKeyboardTrack({
duration,
switchType: project.switch,
markers: project.markers,
cache,
});
await saveAudio(blob, 'keyboard_track.wav');
}