fix: voice status global store, per-view mic reactivity, single-voice preview

- Move voice status into settings store (voiceSttReady, voiceTtsReady),
  checked once at login and refreshed after admin model reload
- ChatView, BriefingView, DashboardChatInput now use computed refs from
  the store — mic buttons appear reactively without needing a page reload
- BriefingView: separate STT-only guard for mic PTT vs TTS-only guard for
  listen mode / speak buttons
- Add ▶ Preview button to Voice & Speed section in Settings for single-
  voice testing without enabling blend mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-30 20:53:06 -04:00
parent b4b4b0d9d6
commit 71ca0ecb5c
7 changed files with 70 additions and 37 deletions
+5 -10
View File
@@ -1,8 +1,9 @@
<script setup lang="ts">
import { ref, nextTick, onMounted } from "vue";
import { apiGet, getVoiceStatus, transcribeAudio } from "@/api/client";
import { ref, computed, nextTick } from "vue";
import { apiGet, transcribeAudio } from "@/api/client";
import { useVoiceRecorder } from "@/composables/useVoiceRecorder";
import { useChatStore } from "@/stores/chat";
import { useSettingsStore } from "@/stores/settings";
import type { Note } from "@/types/note";
const emit = defineEmits<{
@@ -108,17 +109,11 @@ function focus() {
}
// Voice PTT
const voiceEnabled = ref(false);
const settingsStore = useSettingsStore();
const voiceEnabled = computed(() => settingsStore.voiceSttReady);
const transcribingVoice = ref(false);
const recorder = useVoiceRecorder();
onMounted(async () => {
try {
const status = await getVoiceStatus();
voiceEnabled.value = status.enabled && status.stt;
} catch { /* voice absent */ }
});
async function startPtt() {
if (!voiceEnabled.value || recorder.recording.value) return;
await recorder.startRecording();