diff --git a/frontend/src/App.vue b/frontend/src/App.vue index be32d58..1c72876 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -25,6 +25,7 @@ import { isTauri, isMobileTauri, getTauriNotification } from './lib/tauri' import { initApprovalNotifications } from './services/approvalNotifications' import { useServerConfig } from './stores/server-config' import { useApprovalWindow } from './composables/useApprovalWindow' +import { usePipWindow } from './composables/usePipWindow' const route = useRoute() const router = useRouter() @@ -35,6 +36,7 @@ const showServerConfig = ref(false) const needsServerConfig = computed(() => isTauri && serverConfig && !serverConfig.isConfigured) const isPipWindow = computed(() => route.query.pip === '1' || route.query.window === '1') +let unlistenPipOpen: (() => void) | null = null const showVoice = ref(false) const showTranscriptDebug = ref(false) const showDebugConsole = ref(false) @@ -271,8 +273,15 @@ onMounted(async () => { fetchApprovalPending() // Initialize native approval notifications (Tauri only) + // Listen for PiP open requests from Rust global shortcuts (Ctrl+1-5) if (isTauri) { initApprovalNotifications() + + const { listen } = await import('@tauri-apps/api/event') + const { openPip } = usePipWindow() + unlistenPipOpen = await listen('pip:open', (event) => { + openPip(event.payload) + }) } // Connect centralized session state WS @@ -488,6 +497,7 @@ async function sendTestNotification() { onUnmounted(() => { document.removeEventListener('mousemove', trackMouse) document.removeEventListener('keydown', handleGlobalKeydown) + unlistenPipOpen?.() destroyTorch() disconnectApproval() destroySessionStateWS() diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 397014a..16438c4 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,7 +1,7 @@ use tauri::{ menu::{Menu, MenuItem}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, - Manager, WebviewWindowBuilder, WindowEvent, + Emitter, Manager, WindowEvent, }; use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState}; @@ -22,23 +22,8 @@ fn open_pip_terminal(app: &tauri::AppHandle, idx: u8) { return; } - // Create new PiP window — the page itself handles terminal connection or showing "new session" modal - let url = format!("/transcript-debug/{}?pip=1", idx); - let x = 1520.0_f64; // sensible default, will be near right edge on 1920px screens - let y = 60.0 + (idx as f64 - 1.0) * 40.0; - - let _ = WebviewWindowBuilder::new( - app, - &label, - tauri::WebviewUrl::App(url.into()), - ) - .title(&format!("T{} - Agent UI", idx)) - .inner_size(380.0, 620.0) - .position(x, y) - .decorations(false) - .resizable(true) - .focused(true) - .build(); + // Delegate creation to frontend (handles geometry restore, loading spinner, state tracking) + let _ = app.emit("pip:open", idx); } #[cfg_attr(mobile, tauri::mobile_entry_point)]