feat: voice mic, pixel life layer, enhanced transcript-debug UX
VoiceMicButton component, PixelLife aquatic layer, improved UserMessageBubble with voice display, AgentBadge terminal switcher, ChatContainer voice integration, FloatingTranscriptDebug ocean life enhancements, and terminal registry support. Remove traefik config.
This commit is contained in:
@@ -5,6 +5,7 @@ import Toolbar from './components/Toolbar.vue'
|
||||
import TorchButton from './components/TorchButton.vue'
|
||||
import FloatingTerminal from './components/FloatingTerminal.vue'
|
||||
import FloatingResponse from './components/FloatingResponse.vue'
|
||||
import { initWhisperSocket } from './services/whisperSocket'
|
||||
import FloatingVoice from './components/FloatingVoice.vue'
|
||||
import FloatingTranscriptDebug from './components/FloatingTranscriptDebug.vue'
|
||||
import AgentBar from './components/AgentBar.vue'
|
||||
@@ -70,6 +71,8 @@ function clearDebugLogs() {
|
||||
const terminalRef = ref<InstanceType<typeof FloatingTerminal> | null>(null)
|
||||
const responseRef = ref<InstanceType<typeof FloatingResponse> | null>(null)
|
||||
const voiceRef = ref<InstanceType<typeof FloatingVoice> | null>(null)
|
||||
const transcriptDebugRef = ref<InstanceType<typeof FloatingTranscriptDebug> | null>(null)
|
||||
const mousePos = ref({ x: 0, y: 0 })
|
||||
const canvasStore = useCanvasStore()
|
||||
const projectCanvasStore = useProjectCanvasStore()
|
||||
const { totalPending, modalVisible, connect: connectApproval, disconnect: disconnectApproval, fetchPending: fetchApprovalPending } = useGlobalApproval()
|
||||
@@ -104,6 +107,21 @@ function hardRefresh() {
|
||||
location.reload()
|
||||
}
|
||||
|
||||
function trackMouse(e: MouseEvent) {
|
||||
mousePos.value = { x: e.clientX, y: e.clientY }
|
||||
}
|
||||
|
||||
function handleGlobalKeydown(e: KeyboardEvent) {
|
||||
if (e.ctrlKey && e.key === 'e') {
|
||||
e.preventDefault()
|
||||
if (transcriptDebugRef.value) {
|
||||
transcriptDebugRef.value.openAtCursor(mousePos.value.x, mousePos.value.y)
|
||||
} else {
|
||||
showTranscriptDebug.value = !showTranscriptDebug.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Voice FAB push-to-talk handlers
|
||||
function handleVoiceFabClick() {
|
||||
// If touch just ended, ignore click
|
||||
@@ -273,6 +291,9 @@ onMounted(async () => {
|
||||
connectApproval()
|
||||
fetchApprovalPending()
|
||||
|
||||
// Initialize Whisper WebSocket connection early
|
||||
initWhisperSocket()
|
||||
|
||||
// Fire torch connection early (don't await yet)
|
||||
const torchReady = initTorch()
|
||||
|
||||
@@ -342,6 +363,12 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Track mouse for Ctrl+E cursor-based opening
|
||||
document.addEventListener('mousemove', trackMouse)
|
||||
|
||||
// Global keyboard shortcut: Ctrl+E toggles Transcript Debug
|
||||
document.addEventListener('keydown', handleGlobalKeydown)
|
||||
|
||||
// Detect virtual keyboard on mobile
|
||||
if (window.visualViewport) {
|
||||
const initialHeight = window.visualViewport.height
|
||||
@@ -357,6 +384,8 @@ onMounted(async () => {
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('mousemove', trackMouse)
|
||||
document.removeEventListener('keydown', handleGlobalKeydown)
|
||||
destroyTorch()
|
||||
disconnectApproval()
|
||||
if (statusReconnectTimeout) clearTimeout(statusReconnectTimeout)
|
||||
@@ -577,7 +606,7 @@ watch(() => route.name, (newPage) => {
|
||||
<FloatingVoice ref="voiceRef" v-model="showVoice" />
|
||||
|
||||
<!-- Floating Transcript Debug -->
|
||||
<FloatingTranscriptDebug v-model="showTranscriptDebug" />
|
||||
<FloatingTranscriptDebug ref="transcriptDebugRef" v-model="showTranscriptDebug" />
|
||||
|
||||
<!-- Global Hooks Approval Modal -->
|
||||
<HooksApprovalModal />
|
||||
|
||||
Reference in New Issue
Block a user