claude-desktop/src/lib/components/ToolCardEdit.svelte
Eddy ad9833fcb8
Some checks failed
Build AppImage / build (push) Has been cancelled
feat: Phase 8+9 — Inline Tool-Karten + komplettes UI-Redesign auf Cursor/Zed-Niveau [appimage]
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>
2026-04-27 14:27:09 +02:00

94 lines
2.8 KiB
Svelte

<script lang="ts">
// Spezialisierung Edit/Write/MultiEdit/NotebookEdit
// Zeigt Diff-Vorschau (rot/gruen). Wenn ein passender Eintrag in
// pendingChanges existiert, wird die existierende DiffView mit
// Accept/Reject-Buttons gerendert.
import ToolCallCard from './ToolCallCard.svelte';
import DiffView from './DiffView.svelte';
import { invoke } from '@tauri-apps/api/core';
import { pendingChanges, type InlineToolCall, type FileChange } from '$lib/stores';
interface Props {
call: InlineToolCall;
}
let { call }: Props = $props();
const filePath = $derived((call.input.file_path || call.input.path || '') as string);
// Versuche, einen passenden Eintrag aus dem pendingChanges-Store zu finden
const pending = $derived<FileChange | undefined>(
$pendingChanges.find(c => c.toolId === call.id || c.filePath === filePath)
);
// Fallback fuer Edit-Tool ohne pendingChanges-Eintrag (z.B. wenn der
// Snapshot bereits akzeptiert wurde): einfache Vorher/Nachher-Anzeige
// aus den Tool-Inputs.
const oldStr = $derived((call.input.old_string as string) || (pending?.contentBefore ?? ''));
const newStr = $derived((call.input.new_string as string) || (call.input.content as string) || (pending?.contentAfter ?? ''));
async function handleAccept() {
if (pending) {
try {
await invoke('accept_change', { toolId: pending.toolId });
pendingChanges.update(list => list.filter(c => c.toolId !== pending.toolId));
} catch (e) {
console.error('Accept failed:', e);
}
}
}
async function handleReject() {
if (pending) {
try {
await invoke('reject_change', { toolId: pending.toolId });
pendingChanges.update(list => list.filter(c => c.toolId !== pending.toolId));
} catch (e) {
console.error('Reject failed:', e);
}
}
}
</script>
<ToolCallCard {call} defaultOpen={true}>
{#snippet children()}
{#if call.status === 'running'}
<div class="placeholder">… Datei wird geschrieben …</div>
{:else if call.status === 'error'}
<div class="error-msg">{call.result || 'Fehler beim Schreiben'}</div>
{:else if pending}
<DiffView
oldText={pending.contentBefore}
newText={pending.contentAfter}
filename={pending.filePath}
interactive={true}
toolId={pending.toolId}
onAccept={handleAccept}
onReject={handleReject}
/>
{:else if oldStr || newStr}
<DiffView
oldText={oldStr}
newText={newStr}
filename={filePath}
interactive={false}
/>
{:else}
<div class="placeholder">{filePath || 'Edit'}</div>
{/if}
{/snippet}
</ToolCallCard>
<style>
.placeholder {
color: var(--vscode-descriptionForeground);
font-size: 11.5px;
font-family: var(--font-mono);
}
.error-msg {
color: var(--vscode-errorForeground);
font-family: var(--font-mono);
font-size: 11.5px;
white-space: pre-wrap;
}
</style>