feat: compact boundary divider, overlay fix, approval window, PiP, Tauri enhancements

- Add CompactBoundaryDivider component for compact_boundary system messages
- Fix readability overlay: v-if removes element entirely at 0% opacity
- Add approval page and window composable
- Add PiP window support and loading screen
- Tauri: add window management commands and capabilities
- Disable Ctrl+1..5 shortcuts in Tauri (handled by global shortcuts)
This commit is contained in:
2026-02-24 12:13:15 -06:00
parent a92e4ffbda
commit 78978813cd
23 changed files with 1616 additions and 34 deletions

View File

@@ -0,0 +1,123 @@
import { ref } from 'vue'
import { isTauri, getTauriStore } from '@/lib/tauri'
import { trackLoading } from '@/lib/loadingWindow'
const STORE_KEY_PREFIX = 'pipWindow.geometry.'
interface WindowGeometry {
x: number
y: number
width: number
height: number
}
const pipWindows = ref<Map<number, boolean>>(new Map())
async function loadGeometry(idx: number): Promise<WindowGeometry | null> {
try {
const store = await getTauriStore()
return await store.get<WindowGeometry>(`${STORE_KEY_PREFIX}${idx}`) ?? null
} catch {
return null
}
}
async function saveGeometry(idx: number, geo: WindowGeometry): Promise<void> {
try {
const store = await getTauriStore()
await store.set(`${STORE_KEY_PREFIX}${idx}`, geo)
} catch {}
}
export function usePipWindow() {
async function openPip(terminalIndex: number): Promise<boolean> {
if (!isTauri) return false
const pipLabel = `pip-terminal-${terminalIndex}`
try {
const { WebviewWindow } = await import('@tauri-apps/api/webviewWindow')
const existing = await WebviewWindow.getByLabel(pipLabel)
if (existing) {
await existing.setFocus()
return true
}
const pipUrl = `/transcript-debug/${terminalIndex}?pip=1`
// Restore last position/size or use defaults
const saved = await loadGeometry(terminalIndex)
const x = saved?.x ?? (window.screen.width - 400)
const y = saved?.y ?? (60 + (terminalIndex - 1) * 40)
const width = saved?.width ?? 380
const height = saved?.height ?? 620
// Track in the shared loading indicator (bottom-right spinner)
const dismissLoading = await trackLoading(pipLabel)
// Create real window hidden
const pip = new WebviewWindow(pipLabel, {
url: pipUrl,
title: `T${terminalIndex} - Agent UI`,
width,
height,
x,
y,
visible: false,
alwaysOnTop: false,
decorations: false,
resizable: true,
focus: true,
})
pipWindows.value.set(terminalIndex, true)
// When real window is ready: show it, remove from loading tracker
pip.once('tauri://webview-created', () => {
setTimeout(async () => {
try { await pip.show() } catch {}
try { await pip.setFocus() } catch {}
await dismissLoading()
}, 200)
})
// Persist geometry on close
pip.onCloseRequested(async () => {
try {
const pos = await pip.outerPosition()
const size = await pip.outerSize()
await saveGeometry(terminalIndex, {
x: pos.x,
y: pos.y,
width: size.width,
height: size.height,
})
} catch {}
pipWindows.value.delete(terminalIndex)
})
return true
} catch (e) {
console.warn(`Failed to open PiP window for T${terminalIndex}:`, e)
pipWindows.value.delete(terminalIndex)
return false
}
}
async function closePip(terminalIndex: number): Promise<void> {
const pipLabel = `pip-terminal-${terminalIndex}`
try {
const { WebviewWindow } = await import('@tauri-apps/api/webviewWindow')
const existing = await WebviewWindow.getByLabel(pipLabel)
if (existing) await existing.close()
} catch {}
pipWindows.value.delete(terminalIndex)
}
function isPipOpen(terminalIndex: number): boolean {
return pipWindows.value.get(terminalIndex) ?? false
}
return { openPip, closePip, isPipOpen, pipWindows }
}