Phase 12 Hook-System (hooks.rs + HooksPanel):
- HookManager mit Event-Registry + Ausfuehrungs-Log
- 5 Built-in Hooks (SessionStart, PreToolUse, PostToolUse,
BeforeCompacting, AfterCompacting)
- Tauri-Commands: list_hooks, set_hook_enabled, get_hook_executions, fire_hook
- HooksPanel.svelte mit Live-Ausfuehrungs-Log
Phase 13 VSCodium-Integration:
- vscode-extension/: WebSocket-Server auf Port 7890
(Commands: openFile, goToLine, formatDocument, findInFiles,
openTerminal, getStatus, executeCommand, ping)
- src-tauri/src/ide.rs: WebSocket-Client via tokio-tungstenite
- IdePanel.svelte: Status, Port-Konfig, Ping-Test, Live-Anzeige aktive Datei
Phase 14 Programm-Steuerung (programs.rs + ProgramsPanel):
- D-Bus: dbus_call + dbus_list_services
- Xvfb: start/stop/status + screenshot (scrot)
- Playwright-Info (MCP-Verweis)
- ProgramsPanel mit 4 Sektionen (VSCodium, Playwright, D-Bus, Xvfb)
Phase 15 Schulungsmodus (teaching.rs + presentation/+page.svelte):
- Separates Tauri-Webview-Fenster
- MermaidDiagram.svelte (dynamic import mermaid)
- AnimatedCode.svelte mit WPM-Steuerung
- Tauri-Commands: presentation_open/close/send_slide/clear
- 🎓-Button in der Titelbar
- Capabilities um core:webview:allow-create-webview-window erweitert
Deps:
- Cargo: +tokio-tungstenite 0.23, +futures-util 0.3
- npm: +mermaid ^11.4.0 (npm install erforderlich)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
64 lines
2 KiB
Rust
64 lines
2 KiB
Rust
// Claude Desktop — Schulungsmodus (Phase 15)
|
|
// Oeffnet separates Praesentations-Fenster + sendet Slides
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use tauri::{AppHandle, Emitter, Manager, WebviewUrl, WebviewWindowBuilder};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Slide {
|
|
pub r#type: String, // "mermaid" | "code" | "text"
|
|
pub content: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub language: Option<String>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub title: Option<String>,
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn presentation_open(app: AppHandle) -> Result<(), String> {
|
|
// Falls Fenster bereits existiert, nach vorne holen
|
|
if let Some(win) = app.get_webview_window("presentation") {
|
|
let _ = win.show();
|
|
let _ = win.set_focus();
|
|
return Ok(());
|
|
}
|
|
|
|
WebviewWindowBuilder::new(&app, "presentation", WebviewUrl::App("/presentation".into()))
|
|
.title("Claude — Schulungsmodus")
|
|
.inner_size(1200.0, 800.0)
|
|
.center()
|
|
.build()
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn presentation_close(app: AppHandle) -> Result<(), String> {
|
|
if let Some(win) = app.get_webview_window("presentation") {
|
|
let _ = win.close();
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn presentation_send_slide(app: AppHandle, slide: Slide) -> Result<(), String> {
|
|
// Fenster oeffnen falls noch nicht offen
|
|
if app.get_webview_window("presentation").is_none() {
|
|
let _ = presentation_open(app.clone()).await;
|
|
tokio::time::sleep(std::time::Duration::from_millis(400)).await;
|
|
}
|
|
|
|
if let Some(win) = app.get_webview_window("presentation") {
|
|
win.emit("presentation-slide", &slide).map_err(|e| e.to_string())?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn presentation_clear(app: AppHandle) -> Result<(), String> {
|
|
if let Some(win) = app.get_webview_window("presentation") {
|
|
win.emit("presentation-clear", ()).map_err(|e| e.to_string())?;
|
|
}
|
|
Ok(())
|
|
}
|