fix(stage-*): combobox not displaying default value

This commit is contained in:
Neko Ayaka
2025-07-30 00:25:06 +08:00
parent 550c4115c2
commit 808a47662b
5 changed files with 24 additions and 18 deletions
@@ -2,8 +2,8 @@
import type { TranscriptionProvider } from '@xsai-ext/shared-providers'
import { Alert, Button, ErrorContainer, LevelMeter, RadioCardManySelect, RadioCardSimple, TestDummyMarker, ThresholdMeter, TimeSeriesChart } from '@proj-airi/stage-ui/components'
import { useAudioAnalyzer, useAudioDevice, useAudioRecorder } from '@proj-airi/stage-ui/composables'
import { useAudioContext, useHearingStore, useProvidersStore } from '@proj-airi/stage-ui/stores'
import { useAudioAnalyzer, useAudioRecorder } from '@proj-airi/stage-ui/composables'
import { useAudioContext, useHearingStore, useProvidersStore, useSettingsAudioDevice } from '@proj-airi/stage-ui/stores'
import { FieldCheckbox, FieldRange, FieldSelect } from '@proj-airi/ui'
import { storeToRefs } from 'pinia'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
@@ -29,7 +29,8 @@ const {
const providersStore = useProvidersStore()
const { configuredTranscriptionProvidersMetadata } = storeToRefs(providersStore)
const { audioInputs, selectedAudioInput, stream, stopStream, startStream } = useAudioDevice()
const { stopStream, startStream } = useSettingsAudioDevice()
const { audioInputs, selectedAudioInput, stream } = storeToRefs(useSettingsAudioDevice())
const { startRecord, stopRecord, onStopRecord } = useAudioRecorder(stream)
const { startAnalyzer, stopAnalyzer, onAnalyzerUpdate, volumeLevel } = useAudioAnalyzer()
const { audioContext } = storeToRefs(useAudioContext())
+2 -2
View File
@@ -84,13 +84,13 @@ export const useAudioContext = defineStore('audio-context', () => {
export function useAudioDevice(requestPermission: boolean = false) {
const devices = useDevicesList({ constraints: { audio: true }, requestPermissions: requestPermission })
const audioInputs = computed(() => devices.audioInputs.value)
const selectedAudioInput = ref<string>(devices.audioInputs.value[0]?.deviceId || '')
const selectedAudioInput = ref<string>(devices.audioInputs.value.find(device => device.deviceId === 'default')?.deviceId || '')
const deviceConstraints = computed<MediaStreamConstraints>(() => ({ audio: { deviceId: { exact: selectedAudioInput.value }, autoGainControl: true, echoCancellation: true, noiseSuppression: true } }))
const { stream, stop: stopStream, start: startStream } = useUserMedia({ constraints: deviceConstraints, enabled: false, autoSwitch: true })
watch(audioInputs, () => {
if (!selectedAudioInput.value && audioInputs.value.length > 0) {
selectedAudioInput.value = audioInputs.value[0]?.deviceId
selectedAudioInput.value = audioInputs.value.find(input => input.deviceId === 'default')?.deviceId || audioInputs.value[0].deviceId
}
})
+7 -4
View File
@@ -116,8 +116,8 @@ export const useSettingsAudioDevice = defineStore('settings-audio-devices', () =
const selectedAudioInputPersist = useLocalStorage('settings/audio/input', selectedAudioInputNonPersist.value)
const selectedAudioInputEnabledPersist = useLocalStorage('settings/audio/input-enabled', false)
watch(selectedAudioInputNonPersist, (newValue) => {
selectedAudioInputPersist.value = newValue
watch(selectedAudioInputPersist, (newValue) => {
selectedAudioInputNonPersist.value = newValue
})
watch(selectedAudioInputEnabledPersist, (val) => {
@@ -130,15 +130,18 @@ export const useSettingsAudioDevice = defineStore('settings-audio-devices', () =
})
onMounted(() => {
if (selectedAudioInputEnabledPersist.value && selectedAudioInputNonPersist.value) {
if (selectedAudioInputEnabledPersist.value && selectedAudioInputPersist.value) {
startStream()
}
if (selectedAudioInputNonPersist.value && !selectedAudioInputEnabledPersist.value) {
selectedAudioInputPersist.value = selectedAudioInputNonPersist.value
}
})
return {
audioInputs,
deviceConstraints,
selectedAudioInput: selectedAudioInputNonPersist,
selectedAudioInput: selectedAudioInputPersist,
enabled: selectedAudioInputEnabledPersist,
stream,
@@ -1,4 +1,6 @@
<script setup lang="ts">
<script setup lang="ts" generic="T extends AcceptableValue">
import type { AcceptableValue } from 'reka-ui'
import {
ComboboxAnchor,
ComboboxContent,
@@ -15,26 +17,26 @@ import {
} from 'reka-ui'
const props = defineProps<{
options: { groupLabel: string, children?: { label: string, value: any }[] }[]
options: { groupLabel: string, children?: { label: string, value: T }[] }[]
placeholder?: string
}>()
function toDisplayValue(value: any): string {
const modelValue = defineModel<T>({ required: false })
function toDisplayValue(value: T): string {
const option = props.options.flatMap(group => group.children).find(option => option?.value === value)
return option ? option.label : props.placeholder || ''
}
</script>
<template>
<ComboboxRoot
class="relative w-full"
>
<ComboboxRoot v-model="modelValue" class="relative w-full">
<ComboboxAnchor
:class="[
'w-full inline-flex items-center justify-between rounded-xl border px-3 leading-none h-10 gap-[5px] outline-none',
'text-sm text-neutral-700 dark:text-neutral-200 data-[placeholder]:text-neutral-200',
'bg-white dark:bg-neutral-900 disabled:bg-neutral-100 hover:bg-neutral-50 dark:disabled:bg-neutral-900 dark:hover:bg-neutral-700',
'border-neutral-200 dark:border-neutral-800 border-solid border-2 focus:border-neutral-300 dark:focus:border-neutral-600',
'border-neutral-200 dark:border-neutral-800 border-solid border-2 focus:border-primary-300 dark:focus:border-primary-400/50',
'shadow-sm focus:shadow-[0_0_0_2px] focus:shadow-black',
'transition-colors duration-200 ease-in-out',
]"
@@ -104,7 +106,7 @@ function toDisplayValue(value: any): string {
:text-value="option.label"
:value="option.value"
:class="[
'leading-none rounded-md flex items-center h-8 pr-[0.5rem] pl-[1.5rem] relative select-none data-[disabled]:pointer-events-none data-[highlighted]:outline-none',
'leading-none rounded-lg flex items-center h-8 pr-[0.5rem] pl-[1.5rem] relative select-none data-[disabled]:pointer-events-none data-[highlighted]:outline-none',
'data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-800',
'text-sm text-neutral-700 dark:text-neutral-200 data-[disabled]:text-neutral-400 dark:data-[disabled]:text-neutral-600 data-[highlighted]:text-grass1',
'transition-colors duration-200 ease-in-out',
@@ -27,5 +27,5 @@ provide('hide', handleHide)
</script>
<template>
<Combobox v-model="modelValue" :options="[{ groupLabel: '', children: props.options }]" />
<Combobox v-model="modelValue" :default-value="modelValue" :options="[{ groupLabel: '', children: props.options }]" />
</template>