Skip to content

Commit 82a0896

Browse files
committed
feat(stage-tamagotchi): stage-web like ControlsIsland
1 parent 766e7da commit 82a0896

File tree

4 files changed

+62
-19
lines changed

4 files changed

+62
-19
lines changed

apps/stage-tamagotchi/src/renderer/components/InteractiveArea.vue

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useProvidersStore } from '@proj-airi/stage-ui/stores/providers'
88
import { useSettingsAudioDevice } from '@proj-airi/stage-ui/stores/settings'
99
import { BasicTextarea } from '@proj-airi/ui'
1010
import { storeToRefs } from 'pinia'
11-
import { onMounted, ref, watch } from 'vue'
11+
import { ref, watch } from 'vue'
1212
import { useI18n } from 'vue-i18n'
1313
1414
import TamagotchiChatHistory from './ChatHistory.vue'
@@ -17,7 +17,7 @@ const messageInput = ref('')
1717
const listening = ref(false)
1818
const attachments = ref<{ type: 'image', data: string, mimeType: string, url: string }[]>([])
1919
20-
// const { askPermission } = useSettingsAudioDevice()
20+
const { askPermission } = useSettingsAudioDevice()
2121
const { enabled, selectedAudioInput } = storeToRefs(useSettingsAudioDevice())
2222
const { send, onAfterMessageComposed, discoverToolsCompatibility } = useChatStore()
2323
const { messages } = storeToRefs(useChatStore())
@@ -116,21 +116,16 @@ function handleTranscription(_buffer: Float32Array) {
116116
alert('Transcription is not implemented yet')
117117
}
118118
119-
// async function handleAudioInputChange(event: Event) {
120-
// const target = event.target as HTMLSelectElement
121-
// const found = audioInputs.value.find(d => d.deviceId === target.value)
122-
// if (!found) {
123-
// selectedAudioDevice.value = undefined
124-
// return
125-
// }
126-
127-
// selectedAudioDevice.value = found
128-
// }
129-
130119
watch(enabled, async (value) => {
131120
if (value === false) {
132121
destroy()
133122
}
123+
else {
124+
await askPermission()
125+
start()
126+
}
127+
}, {
128+
immediate: true,
134129
})
135130
136131
watch([activeProvider, activeModel], async () => {
@@ -144,10 +139,6 @@ onAfterMessageComposed(async () => {
144139
attachments.value.forEach(att => URL.revokeObjectURL(att.url))
145140
attachments.value = []
146141
})
147-
148-
onMounted(() => {
149-
start()
150-
})
151142
</script>
152143

153144
<template>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<template>
2+
<button
3+
:class="[
4+
'border-2 border-solid border-neutral-200/60 dark:border-neutral-800/10',
5+
'bg-neutral-50/80 dark:bg-neutral-800/70',
6+
'w-fit flex items-center self-end justify-center p-2',
7+
'rounded-xl backdrop-blur-md',
8+
'transition-all hover:transition-none transition-duration-300 transition-ease-out',
9+
]"
10+
>
11+
<slot />
12+
</button>
13+
</template>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script setup lang="ts">
2+
import { HearingConfigDialog } from '@proj-airi/stage-ui/components'
3+
import { useSettingsAudioDevice } from '@proj-airi/stage-ui/stores/settings'
4+
import { useDark, useToggle } from '@vueuse/core'
5+
import { storeToRefs } from 'pinia'
6+
7+
import ControlButton from './ControlButton.vue'
8+
9+
const isDark = useDark({ disableTransition: false })
10+
const toggleDark = useToggle(isDark)
11+
12+
const settingsAudioDeviceStore = useSettingsAudioDevice()
13+
const { enabled } = storeToRefs(settingsAudioDeviceStore)
14+
</script>
15+
16+
<template>
17+
<div fixed bottom-2 right-2>
18+
<div flex flex-col gap-1>
19+
<HearingConfigDialog>
20+
<ControlButton>
21+
<Transition name="fade" mode="out-in">
22+
<div v-if="enabled" i-ph:microphone size-5 text="neutral-800 dark:neutral-300" />
23+
<div v-else i-ph:microphone-slash size-5 text="neutral-800 dark:neutral-300" />
24+
</Transition>
25+
</ControlButton>
26+
</HearingConfigDialog>
27+
<ControlButton :class="['cursor-move', 'drag-region']">
28+
<div i-ph:arrows-out-cardinal size-5 text="neutral-800 dark:neutral-300" />
29+
</ControlButton>
30+
<ControlButton @click="() => toggleDark()">
31+
<Transition name="fade" mode="out-in">
32+
<div v-if="isDark" i-solar:moon-outline size-5 text="neutral-800 dark:neutral-300" />
33+
<div v-else i-solar:sun-2-outline size-5 text="neutral-800 dark:neutral-300" />
34+
</Transition>
35+
</ControlButton>
36+
</div>
37+
</div>
38+
</template>

apps/stage-tamagotchi/src/renderer/pages/index.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useLive2d } from '@proj-airi/stage-ui/stores/live2d'
44
import { storeToRefs } from 'pinia'
55
import { computed, ref, watch } from 'vue'
66
7+
import ControlsIsland from '../components/Widgets/ControlsIsland/index.vue'
78
import ResourceStatusIsland from '../components/Widgets/ResourceStatusIsland/index.vue'
89
910
import { useWindowStore } from '../stores/window'
@@ -55,9 +56,9 @@ const modeIndicatorClass = computed(() => {
5556
flex="~ col"
5657
relative z-2 h-full overflow-hidden rounded-xl
5758
transition="opacity duration-500 ease-in-out"
58-
class="drag-region"
5959
>
6060
<div v-show="!isLoading" relative h-full w-full items-end gap-2 class="view">
61+
<ResourceStatusIsland ref="resourceStatusIslandRef" />
6162
<WidgetStage
6263
ref="widgetStageRef"
6364
v-model:state="componentStateStage"
@@ -69,7 +70,7 @@ const modeIndicatorClass = computed(() => {
6970
:y-offset="positionInPercentageString.y"
7071
mb="<md:18"
7172
/>
72-
<ResourceStatusIsland ref="resourceStatusIslandRef" />
73+
<ControlsIsland />
7374
</div>
7475
<div v-show="isLoading" h-full w-full>
7576
<div class="absolute left-0 top-0 z-99 h-full w-full flex cursor-grab items-center justify-center overflow-hidden">

0 commit comments

Comments
 (0)