feat(voice): кнопка X в overlay закрывает прослушивание
All checks were successful
Deploy / deploy (push) Successful in 2m13s

В overlay появляется крестик в правом верхнем углу. Тап = эмитит
voice-cancel → VoiceController прерывает активный VAD-захват и сам
overlay закрывается. Wake-word, если был активен, продолжает слушать
в фоне.
This commit is contained in:
Cosmo
2026-04-27 10:25:21 +00:00
parent 0ea9fad144
commit 9583c84e27
2 changed files with 42 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
'use client'
import { useEffect, useRef, useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { X } from 'lucide-react'
type VoiceState = 'idle' | 'wake' | 'listening' | 'command' | 'response' | 'error'
type Agent = 'cosmo' | 'lusya'
@@ -206,6 +207,31 @@ export default function VoiceOverlay() {
pointerEvents: 'none',
}}
>
{/* Закрыть прослушивание. Просим VoiceController прервать активный
VAD/recording через voice-cancel, и сами закрываем UI. */}
<button
onClick={() => {
window.dispatchEvent(new CustomEvent('voice-cancel'))
clearDismiss()
stopAudio()
setState('idle')
}}
aria-label="Закрыть"
style={{
position: 'absolute', top: 24, right: 24,
width: 56, height: 56, borderRadius: '50%',
border: 'none', cursor: 'pointer',
background: 'rgba(255,255,255,0.08)',
color: 'rgba(255,255,255,0.85)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
backdropFilter: 'blur(16px)',
WebkitBackdropFilter: 'blur(16px)' as any,
pointerEvents: 'auto',
}}
>
<X size={26} />
</button>
<SiriOrb core={colors.core} halo={colors.halo} state={state} />
{/* Subtle status (только "слушаю" — для остальных текст сам говорит за себя) */}