claude-desktop/src/routes/+page.svelte
Eddy f6a12de6ef
All checks were successful
Build AppImage / build (push) Successful in 6m56s
fix: Panel als fester Teil des Layouts statt Overlay [appimage]
ToolDrawer ist jetzt 3. Spalte im Flex-Layout (Sidebar | Chat | Panel).
Kein position:fixed, kein Backdrop, kein Overlay. Panel bleibt fest offen
bis X-Button, Esc oder erneuter Sidebar-Klick. Chat wird schmaler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-02 22:42:31 +02:00

154 lines
4.4 KiB
Svelte

<script lang="ts">
// Hauptfenster-Layout (Phase 9.2 — 3-spaltig mit festem Panel)
//
// ┌─────────────────────────────────────────────────────┐
// │ Sidebar (240px) │ Chat (flex) │ Panel (420px) │
// │ - Suche │ ChatPanel │ ToolDrawer │
// │ - Sessions │ │ (optional) │
// │ - Nav-Rail │ │ │
// └─────────────────────────────────────────────────────┘
// Panel ist fester Teil des Flex-Layouts, kein Overlay.
// Schließt nur per X-Button, Esc oder erneuten Sidebar-Klick.
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
import { onMount } from 'svelte';
import { chatDetached } from '$lib/stores/app';
import ChatPanel from '$lib/components/ChatPanel.svelte';
import Sidebar, { type DrawerSection } from '$lib/components/Sidebar.svelte';
import ToolDrawer from '$lib/components/ToolDrawer.svelte';
import QuickActions from '$lib/components/QuickActions.svelte';
let activeDrawer = $state<DrawerSection | null>(null);
let showQuickActions = $state(false);
function toggleDrawer(section: DrawerSection) {
activeDrawer = activeDrawer === section ? null : section;
}
function openSearch() {
showQuickActions = true;
}
onMount(async () => {
// Detach/Reattach
await listen('chat-reattached', () => { $chatDetached = false; });
await listen('chat-detached', () => { $chatDetached = true; });
// Globaler Cmd/Ctrl+K Listener fuer Quick-Actions
const handler = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') {
e.preventDefault();
showQuickActions = !showQuickActions;
}
// Esc schliesst Panel
if (e.key === 'Escape' && activeDrawer) {
activeDrawer = null;
}
};
window.addEventListener('keydown', handler);
// Quick-Actions Navigation: Panel-Sektion bei Sub-Tab-Wahl oeffnen
await listen<{ panel: string; tab: string }>('navigate-tab', (event) => {
const t = event.payload.tab;
if (['activity', 'monitor', 'perf'].includes(t)) activeDrawer = 'activity';
else if (['memory', 'knowledge', 'context'].includes(t)) activeDrawer = 'memory';
else if (['programs', 'voice', 'agents', 'guards', 'hooks'].includes(t)) activeDrawer = 'tools';
else if (['settings', 'audit'].includes(t)) activeDrawer = 'settings';
});
return () => window.removeEventListener('keydown', handler);
});
function handleQuickAction(action: any) {
showQuickActions = false;
if (action?.invoke) {
invoke(action.invoke, action.invokeArgs ?? {}).catch((e) =>
console.error('Quick-Action invoke failed:', e)
);
}
}
</script>
<div class="layout">
<Sidebar
{activeDrawer}
onSearchOpen={openSearch}
onDrawerToggle={toggleDrawer}
/>
<div class="main">
{#if !$chatDetached}
<ChatPanel />
{:else}
<div class="detached">
<p>Chat ist in einem eigenen Fenster.</p>
<button class="reattach" onclick={() => invoke('chat_window_close')}>
Zurückholen
</button>
</div>
{/if}
</div>
{#if activeDrawer}
<div class="panel">
<ToolDrawer
section={activeDrawer}
onClose={() => (activeDrawer = null)}
/>
</div>
{/if}
</div>
<QuickActions bind:visible={showQuickActions} onExecute={handleQuickAction} />
<style>
.layout {
display: flex;
height: 100%;
min-height: 0;
background: var(--bg-primary);
}
.main {
flex: 1;
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
background: var(--bg-primary);
}
.panel {
width: 420px;
flex-shrink: 0;
min-height: 0;
display: flex;
flex-direction: column;
border-left: 1px solid var(--border);
background: var(--bg-secondary);
}
.detached {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--sp-3);
color: var(--text-secondary);
}
.reattach {
padding: var(--sp-2) var(--sp-4);
background: var(--accent);
color: var(--accent-fg);
border: 0;
border-radius: var(--r-sm);
font-size: var(--fs-md);
cursor: pointer;
}
.reattach:hover {
background: var(--accent-hover);
}
</style>