feat(kon): scaffold hybrid modular workspace
- Cargo workspace with 6 domain crates: core, audio, transcription, ai-formatting, storage, cloud-providers - Minimal Tauri shell (lib.rs + main.rs) with plugin registration - Svelte 5 frontend copied from Ramble v0.2 - All crates compile as empty stubs - App identifier: uk.co.corbel.kon Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
73
src/lib/components/HotkeyRecorder.svelte
Normal file
73
src/lib/components/HotkeyRecorder.svelte
Normal file
@@ -0,0 +1,73 @@
|
||||
<script>
|
||||
import { settings, saveSettings } from "$lib/stores/page.svelte.js";
|
||||
|
||||
let recording = $state(false);
|
||||
let captured = $state(false);
|
||||
|
||||
const modifierKeys = new Set(["Control", "Shift", "Alt", "Meta"]);
|
||||
|
||||
function startRecording() {
|
||||
recording = true;
|
||||
captured = false;
|
||||
}
|
||||
|
||||
function handleKeyDown(e) {
|
||||
if (!recording) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Wait for a non-modifier key
|
||||
if (modifierKeys.has(e.key)) return;
|
||||
|
||||
const parts = [];
|
||||
if (e.ctrlKey) parts.push("Ctrl");
|
||||
if (e.shiftKey) parts.push("Shift");
|
||||
if (e.altKey) parts.push("Alt");
|
||||
if (e.metaKey) parts.push("Super");
|
||||
|
||||
// Must have at least one modifier
|
||||
if (parts.length === 0) {
|
||||
recording = false;
|
||||
return;
|
||||
}
|
||||
|
||||
parts.push(e.key.length === 1 ? e.key.toUpperCase() : e.key);
|
||||
settings.globalHotkey = parts.join("+");
|
||||
saveSettings();
|
||||
recording = false;
|
||||
captured = true;
|
||||
setTimeout(() => { captured = false; }, 1500);
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
recording = false;
|
||||
}
|
||||
|
||||
let chips = $derived(settings.globalHotkey.split("+"));
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="inline-flex items-center gap-1.5 rounded-xl px-4 py-2.5
|
||||
{recording
|
||||
? 'bg-bg-input border-accent shadow-[0_0_0_3px_rgba(232,168,124,0.1)]'
|
||||
: captured
|
||||
? 'bg-bg-input border-border animate-pulse-warm'
|
||||
: 'bg-bg-input border-border hover:border-border'}
|
||||
border transition-all"
|
||||
onclick={startRecording}
|
||||
onkeydown={handleKeyDown}
|
||||
onblur={handleBlur}
|
||||
aria-label="Record hotkey"
|
||||
>
|
||||
{#if recording}
|
||||
<span class="text-[11px] text-text-tertiary italic">Press new shortcut...</span>
|
||||
{:else}
|
||||
{#each chips as chip, i}
|
||||
{#if i > 0}
|
||||
<span class="text-[10px] text-text-tertiary">+</span>
|
||||
{/if}
|
||||
<span class="px-2 py-0.5 rounded-md bg-bg-elevated border border-border text-[11px] font-medium text-text
|
||||
shadow-[inset_0_1px_2px_rgba(0,0,0,0.3)]">{chip}</span>
|
||||
{/each}
|
||||
{/if}
|
||||
</button>
|
||||
Reference in New Issue
Block a user