+12
-28
@@ -1,19 +1,19 @@
|
||||
<script lang="ts" setup>
|
||||
import { supportedControl as threeSupportedControl, useThreeViewControl } from '@proj-airi/stage-ui-three'
|
||||
import { supportedControl as l2dSupportedCtrl, useL2dViewControl } from '@proj-airi/stage-ui/stores/live2d'
|
||||
import { defaultControlConfig as threeCtrlConf, supportedControl as threeSupportedControl, useThreeViewControl } from '@proj-airi/stage-ui-three'
|
||||
import { defaultControlConfig as l2dCtrlConf, supportedControl as l2dSupportedCtrl, useL2dViewControl } from '@proj-airi/stage-ui/stores/live2d'
|
||||
import { useSettingsStageModel } from '@proj-airi/stage-ui/stores/settings/stage-model'
|
||||
import { Button } from '@proj-airi/ui'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { stageModelRenderer } = storeToRefs(useSettingsStageModel())
|
||||
const { viewControlsEnabled: l2dViewCtrlEnabled, viewControlMode: l2dCtrlMode, reset: l2dReset } = useL2dViewControl()
|
||||
const { viewControlsEnabled: threePlainCtrlEnabled, viewControlMode: threeCtrlMode, reset: threeReset } = useThreeViewControl()
|
||||
const { viewControlsEnabled: l2dViewCtrlEnabled, viewControlMode: l2dCtrlMode, set: l2dSet } = useL2dViewControl()
|
||||
const { viewControlsEnabled: threeSliderCtrlEnabled, viewControlMode: threeCtrlMode, set: threeSet } = useThreeViewControl()
|
||||
const controlEnabled = computed(() => {
|
||||
if (stageModelRenderer.value === 'live2d')
|
||||
return { enabled: l2dViewCtrlEnabled, mode: l2dCtrlMode, supported: l2dSupportedCtrl, reset: l2dReset }
|
||||
return { enabled: l2dViewCtrlEnabled, mode: l2dCtrlMode, supported: l2dSupportedCtrl, conf: l2dCtrlConf, reset: l2dSet }
|
||||
if (stageModelRenderer.value === 'vrm')
|
||||
return { enabled: threePlainCtrlEnabled, mode: threeCtrlMode, supported: threeSupportedControl, reset: threeReset }
|
||||
return { enabled: threeSliderCtrlEnabled, mode: threeCtrlMode, supported: threeSupportedControl, conf: threeCtrlConf, reset: threeSet }
|
||||
return null
|
||||
})
|
||||
|
||||
@@ -26,39 +26,23 @@ function handleViewControlsToggle(targetMode: string) {
|
||||
}
|
||||
controlEnabled.value.mode.value = targetMode as any
|
||||
}
|
||||
|
||||
// watch()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div w-full flex flex-1 items-center self-end justify-end gap-2>
|
||||
<Transition name="fade">
|
||||
<div v-if="controlEnabled?.enabled.value" w-full flex justify-between gap-2>
|
||||
<Button variant="secondary-muted" :toggled="controlEnabled.mode.value === 'x'" w-full @click="handleViewControlsToggle('x')">
|
||||
X
|
||||
</Button>
|
||||
<Button variant="secondary-muted" :toggled="controlEnabled.mode.value === 'y'" w-full @click="handleViewControlsToggle('y')">
|
||||
Y
|
||||
</Button>
|
||||
<Button v-if="controlEnabled.supported.includes('z' as any)" variant="secondary-muted" :toggled="controlEnabled.mode.value === 'z'" w-full @click="handleViewControlsToggle('z')">
|
||||
Z
|
||||
</Button>
|
||||
<Button v-if="controlEnabled.supported.includes('cameraFOV' as any)" variant="secondary-muted" :toggled="controlEnabled.mode.value === 'cameraFOV'" w-full @click="handleViewControlsToggle('cameraFOV')">
|
||||
FOV
|
||||
</Button>
|
||||
<Button v-if="controlEnabled.supported.includes('scale' as any)" variant="secondary-muted" :toggled="controlEnabled.mode.value === 'scale'" w-full @click="handleViewControlsToggle('scale')">
|
||||
Scale
|
||||
</Button>
|
||||
<Button v-if="controlEnabled.supported.includes('cameraDistance' as any)" variant="secondary-muted" :toggled="controlEnabled.mode.value === 'cameraDistance'" w-full @click="handleViewControlsToggle('cameraDistance')">
|
||||
Dis
|
||||
<Button
|
||||
v-for="control in controlEnabled.supported" :key="control" variant="secondary-muted"
|
||||
:toggled="controlEnabled.mode.value === control" w-full @click="handleViewControlsToggle(control)"
|
||||
>
|
||||
{{ (controlEnabled.conf as any)[control].buttonText }}
|
||||
</Button>
|
||||
</div>
|
||||
</Transition>
|
||||
<button
|
||||
w-fit flex items-center self-end justify-center justify-self-end rounded-xl p-2 backdrop-blur-md
|
||||
border="2 solid neutral-100/60 dark:neutral-800/30"
|
||||
bg="neutral-50/70 dark:neutral-800/70"
|
||||
title="View"
|
||||
border="2 solid neutral-100/60 dark:neutral-800/30" bg="neutral-50/70 dark:neutral-800/70" title="View"
|
||||
text="neutral-500 dark:neutral-400"
|
||||
@click="controlEnabled && (controlEnabled.enabled.value = !controlEnabled.enabled.value)"
|
||||
>
|
||||
|
||||
@@ -31,7 +31,6 @@ import { useTranscriptions } from '../../composables/use-transcriptions'
|
||||
import { BackgroundDialogPicker } from '../Backgrounds'
|
||||
|
||||
const { isDark, toggleDark } = useTheme()
|
||||
const hearingDialogOpen = ref(false)
|
||||
const chatOrchestrator = useChatOrchestratorStore()
|
||||
const chatSession = useChatSessionStore()
|
||||
const chatStream = useChatStreamStore()
|
||||
@@ -59,24 +58,25 @@ const { themeColorsHueDynamic } = storeToRefs(useSettings())
|
||||
const { viewControlsEnabled: l2dViewCtrlEnabled } = useL2dViewControl()
|
||||
const { viewControlsEnabled: threeViewCtrlEnabled } = useThreeViewControl()
|
||||
const settingsAudioDevice = useSettingsAudioDevice()
|
||||
const { enabled, selectedAudioInput, stream, audioInputs } = storeToRefs(settingsAudioDevice)
|
||||
const { enabled, stream } = storeToRefs(settingsAudioDevice)
|
||||
const { ingest, onAfterMessageComposed } = chatOrchestrator
|
||||
const { t } = useI18n()
|
||||
const { audioContext } = useAudioContext()
|
||||
const { startAnalyzer, stopAnalyzer, volumeLevel } = useAudioAnalyzer()
|
||||
const { startAnalyzer, stopAnalyzer } = useAudioAnalyzer()
|
||||
let analyzerSource: MediaStreamAudioSourceNode | undefined
|
||||
|
||||
function isMobileDevice() {
|
||||
return /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
const { isListening } = useTranscriptions(
|
||||
const { isListening, startStreamingTranscription, stopStreamingTranscription } = useTranscriptions(
|
||||
{
|
||||
messageInputRef: messageInput,
|
||||
sendMessage: handleSend,
|
||||
isStageTamagotchi,
|
||||
},
|
||||
)
|
||||
const toggleTranscription = () => isListening.value ? stopStreamingTranscription() : startStreamingTranscription()
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!isMobileDevice()) {
|
||||
@@ -115,14 +115,14 @@ function teardownAnalyzer() {
|
||||
try {
|
||||
analyzerSource?.disconnect()
|
||||
}
|
||||
catch {}
|
||||
catch { }
|
||||
analyzerSource = undefined
|
||||
stopAnalyzer()
|
||||
}
|
||||
|
||||
async function setupAnalyzer() {
|
||||
teardownAnalyzer()
|
||||
if (!hearingDialogOpen.value || !enabled.value || !stream.value)
|
||||
if (!enabled.value || !stream.value)
|
||||
return
|
||||
if (audioContext.state === 'suspended')
|
||||
await audioContext.resume()
|
||||
@@ -137,12 +137,6 @@ watch([enabled, stream], () => {
|
||||
setupAnalyzer()
|
||||
}, { immediate: true })
|
||||
|
||||
watch(hearingDialogOpen, (value) => {
|
||||
if (value) {
|
||||
settingsAudioDevice.askPermission()
|
||||
}
|
||||
})
|
||||
|
||||
onAfterMessageComposed(async () => {
|
||||
})
|
||||
|
||||
@@ -196,11 +190,9 @@ onMounted(() => {
|
||||
</button>
|
||||
<ChatSessionsDrawer v-model="sessionsDrawerOpen" />
|
||||
<HearingConfigDialog
|
||||
v-model:show="hearingDialogOpen"
|
||||
v-model:enabled="enabled"
|
||||
v-model:selected-audio-input="selectedAudioInput"
|
||||
:audio-inputs="audioInputs"
|
||||
:volume-level="volumeLevel"
|
||||
:transcription="isListening"
|
||||
:toggle-transcription="toggleTranscription"
|
||||
:granted="true"
|
||||
>
|
||||
<button
|
||||
|
||||
@@ -139,8 +139,7 @@ watch(hearingPopoverOpen, async (value) => {
|
||||
onAfterMessageComposed(async () => {
|
||||
})
|
||||
|
||||
const { startAnalyzer, stopAnalyzer, volumeLevel } = useAudioAnalyzer()
|
||||
const normalizedVolume = computed(() => Math.min(1, Math.max(0, (volumeLevel.value ?? 0) / 100)))
|
||||
const { startAnalyzer, stopAnalyzer } = useAudioAnalyzer()
|
||||
let analyzerSource: MediaStreamAudioSourceNode | undefined
|
||||
|
||||
function teardownAnalyzer() {
|
||||
@@ -294,7 +293,6 @@ watch(sendMode, () => {
|
||||
v-model:auto-send="autoSendEnabled"
|
||||
:transcription="isListening"
|
||||
:granted="true"
|
||||
:volume-level="normalizedVolume"
|
||||
@toggle-transcription="() => isListening ? stopStreamingTranscription() : startStreamingTranscription()"
|
||||
/>
|
||||
</PopoverContent>
|
||||
|
||||
@@ -17,13 +17,14 @@ export function useTranscriptions(options: TranscriptionOptions) {
|
||||
const { messageInputRef: messageInput, sendMessage, isStageTamagotchi } = options
|
||||
|
||||
const hearingStore = useHearingStore()
|
||||
const audioDeviceSettingsStore = useSettingsAudioDevice()
|
||||
const hearingPipeline = useHearingSpeechInputPipeline()
|
||||
const { transcribeForMediaStream, stopStreamingTranscription } = hearingPipeline
|
||||
const { supportsStreamInput } = storeToRefs(hearingPipeline)
|
||||
const { configured: hearingConfigured, autoSendEnabled, autoSendDelay } = storeToRefs(hearingStore)
|
||||
const { enabled: hearingEnabled, stream } = storeToRefs(useSettingsAudioDevice())
|
||||
const { enabled: hearingEnabled, stream } = storeToRefs(audioDeviceSettingsStore)
|
||||
const providersStore = useProvidersStore()
|
||||
const { askPermission, startStream } = useSettingsAudioDevice()
|
||||
const { askPermission, startStream } = audioDeviceSettingsStore
|
||||
|
||||
const isListening = ref(false)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user