Files
Lumotia/src/routes/float/+layout@.svelte
Jake ea48d03cee
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
agent: dogfood polish 2026/04/19 — Linux native chrome + History redesign + mic picker cleanup
Second dogfood sprint. Headline fix: Linux now uses native KWin/Mutter
decorations instead of fragile frameless `startResizeDragging`, which
collapsed diagonal corner resize to a single axis and made drag feel
laggy. macOS / Windows keep custom chrome via `useCustomChrome` gate.

Other changes:

- Cross-window preferences sync via `kon:preferences-changed` Tauri
  event — theme and font changes propagate live to float/viewer.
- Hotkey recorder rewritten to use capture-phase document listener
  gated by $effect; button focus was unreliable in webkit2gtk.
- History page redesigned for cognitive-load hygiene: title-first
  compact row, inline title input, Edit popout opening /viewer in
  edit mode, clipboard export as .md with YAML frontmatter, manual
  tag chips + + Add tag input, header tag filter (cap 7), global
  Starred filter, `tag:xyz` search syntax.
- `deriveAutoTags` kept as empty hook for post-Task-7 LLM topic tags;
  research found all previous auto-tag chips redundant with row UI.
- Viewer window adds edit mode with debounced-save textarea; native
  title renamed to "Kon - Transcription Editor".
- Window minimums updated per GNOME HIG + WCAG reflow research:
  main 960x600, float 360x480, editor 560x520.
- Microphone picker filters raw ALSA strings (hw:, plughw:, front:,
  sysdefault:, null) and dedupes by CARD=X. New `description` field
  on DeviceInfo reads /proc/asound/cards so Blue Yeti shows as "Blue
  Microphones" instead of the short "Microphones" card name.
- GPU reporting fixed: get_runtime_capabilities now returns
  accelerators=[cpu,vulkan] and whisper.supports_gpu=true, matching
  the transcribe-rs whisper-vulkan feature linked unconditionally.
- ResizeHandles kept for macOS/Windows frameless: 12px edges, 20px
  corners via CSS vars, pointerdown + setPointerCapture, corners
  above edges in z-order, rendered as sibling (not child) of the
  animated layout root so `position: fixed` is viewport-relative.
- Dueling drag-region handlers removed — `data-tauri-drag-region` and
  manual `startDragging()` were stacked on the same elements; kept
  the manual handler which has the button/input early-return logic.

See HANDOVER.md for the full session log and deferred items.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:30:42 +01:00

92 lines
2.7 KiB
Svelte

<script>
import "../../app.css";
import { onMount, onDestroy } from "svelte";
import { listen } from "@tauri-apps/api/event";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { settings } from "$lib/stores/page.svelte.js";
import {
getPreferences,
updatePreferences,
applyExternalPreferences,
PREFERENCES_CHANGED_EVENT,
} from "$lib/stores/preferences.svelte.js";
import Titlebar from "$lib/components/Titlebar.svelte";
import { loadOsInfo, isLinux } from "$lib/utils/osInfo.js";
let { children } = $props();
let glowing = $state(false);
let unlistenFocus = null;
let unlistenPrefs = null;
let useCustomChrome = $state(false);
const prefs = getPreferences();
// Theme — sync legacy settings to preferences store (same as main layout)
$effect(() => {
const legacyTheme = settings.theme;
const mapped = legacyTheme === "Light" ? "light" : legacyTheme === "Dark" ? "dark" : "system";
if (prefs.theme !== mapped) {
updatePreferences({ theme: mapped });
}
});
// Listen for settings changes from main window
if (typeof window !== "undefined") {
window.addEventListener("storage", (e) => {
if (e.key === "kon_settings" && e.newValue) {
try {
Object.assign(settings, JSON.parse(e.newValue));
} catch {}
}
});
}
onMount(async () => {
loadOsInfo()
.then(() => { useCustomChrome = !isLinux(); })
.catch(() => {});
try {
unlistenFocus = await listen("task-window-focus", () => {
glowing = true;
setTimeout(() => { glowing = false; }, 700);
// Auto-focus quick-add input
const input = document.querySelector("[data-quick-add]");
if (input) input.focus();
});
} catch {}
try {
let ownLabel = null;
try { ownLabel = getCurrentWindow().label; } catch {}
unlistenPrefs = await listen(PREFERENCES_CHANGED_EVENT, (event) => {
const payload = event?.payload;
if (!payload || payload.source === ownLabel) return;
applyExternalPreferences(payload.prefs);
});
} catch {}
});
onDestroy(() => {
if (unlistenFocus) unlistenFocus();
if (unlistenPrefs) unlistenPrefs();
});
// Escape to close
function handleKeydown(e) {
if (e.key === "Escape") {
getCurrentWindow().close();
}
}
</script>
<svelte:window onkeydown={handleKeydown} />
<div class="h-screen w-screen overflow-hidden grain border border-border shadow-xl animate-float-enter flex flex-col {glowing ? 'animate-glow-pulse' : ''}">
{#if useCustomChrome}
<Titlebar compact />
{/if}
<div class="flex-1 min-h-0 overflow-hidden">
{@render children()}
</div>
</div>