Some checks failed
Build AppImage / build (push) Has been cancelled
Phase 8 (VS-Code-Look Chatbereich): - Linksbuendige Messages mit Avatar-Spalte, Hover-Actions - Inline Tool-Karten (Read/Edit/Bash/Generic) in Assistant-Messages - Edit-Karten zeigen Diff direkt mit Accept/Reject - Tool-Calls werden via events.ts an letzte Assistant-Message gebunden - Smart-Sticky-Scroll (Auto-Scroll stoppt wenn User selbst scrollt) - OOM-Bug durch MutationObserver mit subtree:true behoben Phase 9 (Komplettes UI-Redesign): - Design-System in app.css: 4 Graustufen, 1 Akzent (#007acc), 4 Status-Farben, 5 Schriftgroessen (11/12/13/14/16), 4-Punkt-Spacing, 2 Radius-Werte - vscode.css als Aliase auf das neue System - UI-Library src/lib/ui/: Button, Card, Icon, Badge, StatusDot, Tooltip, Drawer, Tabs - Lucide-svelte fuer SVG-Icons (ersetzt Emojis im Chrome) - StatusBar (22px) ersetzt ueberfuellten Footer mit 6+ Stats - Titlebar entruempelt: ✱-Logo + Stop + Schulungsmodus + Version - 2-spaltiges Layout (Sidebar 240px + Hauptbereich) statt 4-Pane-Zerstueckelung - ToolDrawer: 13 Panels in 4 Gruppen (Aktivitaet/Speicher/Werkzeuge/Einstellungen), jede Gruppe mit internen Tabs, Esc schliesst - Cmd+K global oeffnet QuickActions als zentrale Navigation - StatusDot-Komponente ersetzt Emoji-Status (🟢🟡⚪🔴) in AgentView - Hardgecodete Farben (#ef4444, #22c55e, #eab308 ...) in 9 Komponenten durch CSS-Variablen ersetzt Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
142 lines
4.2 KiB
Svelte
142 lines
4.2 KiB
Svelte
<script lang="ts">
|
|
// Hauptfenster-Layout (Phase 9, Cursor-Stil 2-spaltig)
|
|
//
|
|
// ┌──────────────────────────────────────────┐
|
|
// │ Sidebar (240px) │ Hauptbereich (flex) │
|
|
// │ - Suche │ ChatPanel │
|
|
// │ - Sessions │ (oder Detached │
|
|
// │ - Nav-Rail │ Placeholder) │
|
|
// └──────────────────────────────────────────┘
|
|
// ToolDrawer wird ueber Sidebar-Nav getriggert und ueberlagert von rechts.
|
|
|
|
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 Drawer
|
|
if (e.key === 'Escape' && activeDrawer) {
|
|
activeDrawer = null;
|
|
}
|
|
};
|
|
window.addEventListener('keydown', handler);
|
|
|
|
// Quick-Actions Navigation: Drawer-Sektion bei Sub-Tab-Wahl oeffnen
|
|
await listen<{ panel: string; tab: string }>('navigate-tab', (event) => {
|
|
const t = event.payload.tab;
|
|
// Mappe Sub-Tab → Section
|
|
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;
|
|
// Wenn die Action eine navigate-tab Anweisung war, oeffnet der Listener den Drawer
|
|
// Andere Actions werden vom ChatPanel verarbeitet (Slash-Commands etc.)
|
|
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>
|
|
</div>
|
|
|
|
<ToolDrawer
|
|
section={activeDrawer}
|
|
onClose={() => (activeDrawer = null)}
|
|
/>
|
|
|
|
<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);
|
|
}
|
|
|
|
.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>
|