Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 027fbec606 | |||
| 730dbfaf7b |
@@ -114,6 +114,18 @@ const transcribingVoice = ref(false)
|
|||||||
const recorder = useVoiceRecorder()
|
const recorder = useVoiceRecorder()
|
||||||
const silenceDetector = useSilenceDetector()
|
const silenceDetector = useSilenceDetector()
|
||||||
|
|
||||||
|
// Live mic pulse. `silenceDetector.amplitude` is 0..1 RMS; we floor at 0.1
|
||||||
|
// so the button still breathes on silence and cap the scale growth so loud
|
||||||
|
// input doesn't punch through the input bar.
|
||||||
|
const micStyle = computed(() => {
|
||||||
|
if (!recorder.recording.value) return {}
|
||||||
|
const pulse = 0.1 + Math.min(silenceDetector.amplitude.value, 1) * 0.9
|
||||||
|
return {
|
||||||
|
transform: `scale(${1 + pulse * 0.18})`,
|
||||||
|
boxShadow: `0 0 ${6 + pulse * 14}px ${2 + pulse * 4}px rgba(239, 68, 68, ${0.2 + pulse * 0.3})`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
async function toggleVoice() {
|
async function toggleVoice() {
|
||||||
if (transcribingVoice.value) return
|
if (transcribingVoice.value) return
|
||||||
if (recorder.recording.value) {
|
if (recorder.recording.value) {
|
||||||
@@ -235,6 +247,7 @@ defineExpose({ focus, prefill })
|
|||||||
v-if="voiceEnabled"
|
v-if="voiceEnabled"
|
||||||
class="btn-icon btn-mic"
|
class="btn-icon btn-mic"
|
||||||
:class="{ 'mic-recording': recorder.recording.value, 'mic-transcribing': transcribingVoice }"
|
:class="{ 'mic-recording': recorder.recording.value, 'mic-transcribing': transcribingVoice }"
|
||||||
|
:style="micStyle"
|
||||||
@click.prevent="toggleVoice"
|
@click.prevent="toggleVoice"
|
||||||
:disabled="transcribingVoice || !store.chatReady"
|
:disabled="transcribingVoice || !store.chatReady"
|
||||||
:title="recorder.recording.value ? 'Click to stop (or wait for silence)' : 'Click to speak'"
|
:title="recorder.recording.value ? 'Click to stop (or wait for silence)' : 'Click to speak'"
|
||||||
@@ -343,7 +356,14 @@ defineExpose({ focus, prefill })
|
|||||||
.btn-icon:hover { opacity: 1; }
|
.btn-icon:hover { opacity: 1; }
|
||||||
.btn-icon:disabled { opacity: 0.3; cursor: default; }
|
.btn-icon:disabled { opacity: 0.3; cursor: default; }
|
||||||
|
|
||||||
.btn-mic.mic-recording { opacity: 1; color: #ef4444; }
|
.btn-mic.mic-recording {
|
||||||
|
opacity: 1;
|
||||||
|
color: #ef4444;
|
||||||
|
border-radius: 50%;
|
||||||
|
/* Smooth between amplitude samples (~100ms) so the pulse feels continuous
|
||||||
|
rather than stepping. */
|
||||||
|
transition: transform 0.12s ease-out, box-shadow 0.12s ease-out;
|
||||||
|
}
|
||||||
.btn-mic.mic-transcribing { opacity: 0.5; }
|
.btn-mic.mic-transcribing { opacity: 0.5; }
|
||||||
|
|
||||||
.note-picker-wrapper { position: relative; }
|
.note-picker-wrapper { position: relative; }
|
||||||
|
|||||||
Reference in New Issue
Block a user