fix(stage-tamagotchi-kirie): align Android developer menu

This commit is contained in:
LodyAI
2026-10-14 17:42:38 +08:00
parent 2b5756b031
commit ef72111463
4 changed files with 350 additions and 331 deletions
@@ -1,149 +1,9 @@
<script setup lang="ts">
import { CheckBar, IconItem } from '@proj-airi/stage-ui/components'
import { useSettings } from '@proj-airi/stage-ui/stores/settings'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const settings = useSettings()
const menu = computed(() => [
{
title: 'Audio Record',
description: 'Test Audio related composables',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/audio-record',
},
{
title: 'Background Theme color blending',
description: 'Test blending & theme',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/background-gradient-blending',
},
{
title: 'Background removal (WebGPU required)',
description: 'Utility for background removal',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/background-removal',
},
{
title: 'Chat',
description: 'Chat',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/chat',
},
{
title: 'Gesture Circle (Desktop only)',
description: 'Test gesture recognition',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/gesture-circle',
},
{
title: 'Image',
description: 'Image',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/image',
},
{
title: 'Polaroid',
description: 'Utility for taking shots of models',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/polaroid',
},
{
title: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.title'),
description: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.description'),
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-magic-keys',
},
{
title: 'Color extract',
description: 'Test color extraction',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/vibrant',
},
{
title: 'Aliyun Real-time Transcriber',
description: 'Stream microphone audio to Aliyun NLS and inspect live transcripts',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/providers-transcription-realtime-aliyun-nls',
},
{
title: 'Performance Playground',
description: 'VRM expressions + TTS lip sync playground',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/performance-playground',
},
{
title: 'Notification',
description: 'Test notification',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/notifications',
},
{
title: 'WebSocket Inspector',
description: 'Inspect raw WebSocket traffic',
icon: 'i-solar:transfer-horizontal-bold-duotone',
to: '/devtools/websocket-inspector',
},
])
import MobileDeveloperSettings from '@proj-airi/stage-pages/components/settings-developer-mobile.vue'
</script>
<template>
<CheckBar
v-model="settings.disableTransitions"
v-motion
:class="['mb-2', 'transition-all duration-250 ease-in-out']"
text="settings.animations.stage-transitions.title"
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250 + (19 * 10)"
:delay="1 * 50"
/>
<CheckBar
v-model="settings.usePageSpecificTransitions"
v-motion
:disabled="settings.disableTransitions"
text="settings.animations.use-page-specific-transitions.title"
description="settings.animations.use-page-specific-transitions.description"
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250 + (20 * 10)"
:delay="2 * 50"
:class="['transition-all duration-250 ease-in-out']"
/>
<div :class="['flex flex-col gap-4', 'pb-12']">
<IconItem
v-for="(item, index) in menu"
:key="item.to"
v-motion
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250"
:style="{
transitionDelay: `${index * 50}ms`, // Stagger items because UnoCSS cannot generate classes from runtime values.
}"
:title="item.title"
:description="item.description"
:icon="item.icon"
:to="item.to"
/>
</div>
<div
v-motion
:class="[
'text-neutral-200/50 dark:text-neutral-600/20',
'pointer-events-none fixed top-[65dvh] right--15 z--1',
'flex items-center justify-center',
]"
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
:duration="250"
>
<div :class="['text-60', 'i-solar:code-bold-duotone']" />
</div>
<MobileDeveloperSettings />
</template>
<route lang="yaml">
@@ -0,0 +1,196 @@
<script setup lang="ts">
import { useHostEventaInvoke } from '@proj-airi/stage-host-context'
import { ButtonBar, CheckBar, IconItem } from '@proj-airi/stage-ui/components'
import { useSettings } from '@proj-airi/stage-ui/stores/settings'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { electronOpenDevtoolsWindow, electronOpenMainDevtools } from '../../../../../shared/eventa'
const { t } = useI18n()
const settings = useSettings()
const router = useRouter()
const menu = computed(() => [
{
title: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.title'),
description: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.description'),
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-magic-keys',
},
{
title: t('tamagotchi.settings.pages.system.developer.sections.section.use-window-mouse.title'),
description: t('tamagotchi.settings.pages.system.developer.sections.section.use-window-mouse.description'),
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-window-mouse',
},
{
title: 'Displays',
description: 'Visualize connected displays and cursor position',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-electron-all-displays',
},
{
title: 'Widgets Calling',
description: 'Spawn overlay widgets and test component props',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/widgets-calling',
},
{
title: t('tamagotchi.settings.devtools.pages.context-flow.title'),
description: 'Inspect incoming context updates and outgoing chat stream events',
icon: 'i-solar:chat-square-call-bold-duotone',
to: '/devtools/context-flow',
},
{
title: 'Relative Mouse',
description: 'Get mouse position relative to the window',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-electron-relative-mouse',
},
{
title: 'Aliyun Real-time Transcriber',
description: 'Stream microphone audio to Aliyun NLS and inspect live transcripts',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/providers-transcription-realtime-aliyun-nls',
},
{
title: 'Beat Sync Visualizer',
description: 'Plot V-motion targets, trajectory, and scalar Y/Z over time',
icon: 'i-solar:chart-bold-duotone',
to: '/devtools/beat-sync',
},
{
title: t('tamagotchi.settings.devtools.pages.live2d-motion.title'),
description: t('tamagotchi.settings.devtools.pages.live2d-motion.description'),
icon: 'i-mingcute:game-2-fill',
to: '/devtools/live2d-motion',
},
{
title: 'WebSocket Inspector',
description: 'Inspect raw WebSocket traffic',
icon: 'i-solar:transfer-horizontal-bold-duotone',
to: '/devtools/websocket-inspector',
},
{
title: 'Plugin Host Debug',
description: 'Inspect discovered/enabled/loaded plugins and control load/unload lifecycle',
icon: 'i-solar:bug-bold-duotone',
to: '/devtools/plugin-host',
},
{
title: 'Updater',
description: 'Inspect updater state, explicit feed overrides, and install actions',
icon: 'i-solar:restart-bold-duotone',
to: '/devtools/updater',
},
{
title: 'Screen Capture',
description: 'Capture screen or window as video and/or audio streams',
icon: 'i-solar:screen-share-bold-duotone',
to: '/devtools/screen-capture',
},
{
title: 'Vision Capture',
description: 'Capture a screen frame and inspect the output payload',
icon: 'i-solar:eye-closed-bold-duotone',
to: '/devtools/vision',
},
{
title: 'Global Shortcut',
description: 'Register/unregister global shortcuts and watch trigger events fire',
icon: 'i-solar:keyboard-bold-duotone',
to: '/devtools/global-shortcut',
},
])
const openWebInspector = useHostEventaInvoke(electronOpenMainDevtools)
const openDevtoolsWindow = useHostEventaInvoke(electronOpenDevtoolsWindow)
</script>
<template>
<ButtonBar
v-model="settings.disableTransitions"
:class="['mb-2']"
icon="i-solar:settings-minimalistic-outline"
text="settings.pages.page.developers.open-devtools.title"
transition="all ease-in-out duration-250"
@click="openWebInspector({})"
>
{{ t('settings.pages.page.developers.open-devtools.button') }}
</ButtonBar>
<ButtonBar
:class="['mb-2']"
icon="i-solar:code-bold-duotone"
:text="t('tamagotchi.settings.devtools.pages.markdown-stress.title')"
transition="all ease-in-out duration-250"
@click="openDevtoolsWindow({ key: 'markdown-stress', route: '/devtools/markdown-stress' })"
>
{{ t('tamagotchi.settings.devtools.pages.markdown-stress.title') }}
</ButtonBar>
<ButtonBar
:class="['mb-2']"
icon="i-solar:chart-2-bold-duotone"
:text="t('tamagotchi.settings.devtools.pages.io-tracer.title')"
transition="all ease-in-out duration-250"
@click="openDevtoolsWindow({ key: 'io-tracer', route: '/devtools/io-tracer', width: 1600, height: 900 })"
>
{{ t('tamagotchi.settings.devtools.pages.io-tracer.title') }}
</ButtonBar>
<ButtonBar
:class="['mb-2']"
icon="i-solar:chart-square-bold-duotone"
:text="t('tamagotchi.settings.devtools.pages.lag-visualizer.title')"
transition="all ease-in-out duration-250"
@click="() => router.push('/devtools/performance-visualizer')"
>
{{ t('tamagotchi.settings.devtools.pages.lag-visualizer.title') }}
</ButtonBar>
<CheckBar
v-model="settings.disableTransitions"
mb-2
icon-on="i-solar:people-nearby-bold-duotone"
icon-off="i-solar:running-2-line-duotone"
text="settings.animations.stage-transitions.title"
transition="all ease-in-out duration-250"
/>
<CheckBar
v-model="settings.usePageSpecificTransitions"
:disabled="settings.disableTransitions"
icon-on="i-solar:running-2-line-duotone"
icon-off="i-solar:people-nearby-bold-duotone"
text="settings.animations.use-page-specific-transitions.title"
description="settings.animations.use-page-specific-transitions.description"
transition="all ease-in-out duration-250"
/>
<div flex="~ col gap-4" mt-2 pb-12>
<IconItem
v-for="(item, index) in menu"
:key="item.to"
v-motion
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250"
:style="{
transitionDelay: `${(index) * 50}ms`, // delay between each item, unocss doesn't support dynamic generation of classes now
}"
:title="item.title"
:description="item.description"
:icon="item.icon"
:to="item.to"
/>
</div>
<div
v-motion
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
fixed top="[65dvh]" right--15 z--1
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
:duration="250"
flex items-center justify-center
>
<div text="60" i-solar:code-bold-duotone />
</div>
</template>
@@ -1,198 +1,14 @@
<script setup lang="ts">
import { useHostEventaInvoke } from '@proj-airi/stage-host-context'
import { ButtonBar, CheckBar, IconItem } from '@proj-airi/stage-ui/components'
import { useSettings } from '@proj-airi/stage-ui/stores/settings'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import MobileDeveloperSettings from '@proj-airi/stage-pages/components/settings-developer-mobile.vue'
import { electronOpenDevtoolsWindow, electronOpenMainDevtools } from '../../../../shared/eventa'
import DesktopDeveloperSettings from './components/developer-desktop.vue'
const { t } = useI18n()
const settings = useSettings()
const router = useRouter()
const menu = computed(() => [
{
title: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.title'),
description: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.description'),
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-magic-keys',
},
{
title: t('tamagotchi.settings.pages.system.developer.sections.section.use-window-mouse.title'),
description: t('tamagotchi.settings.pages.system.developer.sections.section.use-window-mouse.description'),
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-window-mouse',
},
{
title: 'Displays',
description: 'Visualize connected displays and cursor position',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-electron-all-displays',
},
{
title: 'Widgets Calling',
description: 'Spawn overlay widgets and test component props',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/widgets-calling',
},
{
title: t('tamagotchi.settings.devtools.pages.context-flow.title'),
description: 'Inspect incoming context updates and outgoing chat stream events',
icon: 'i-solar:chat-square-call-bold-duotone',
to: '/devtools/context-flow',
},
{
title: 'Relative Mouse',
description: 'Get mouse position relative to the window',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-electron-relative-mouse',
},
{
title: 'Aliyun Real-time Transcriber',
description: 'Stream microphone audio to Aliyun NLS and inspect live transcripts',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/providers-transcription-realtime-aliyun-nls',
},
{
title: 'Beat Sync Visualizer',
description: 'Plot V-motion targets, trajectory, and scalar Y/Z over time',
icon: 'i-solar:chart-bold-duotone',
to: '/devtools/beat-sync',
},
{
title: t('tamagotchi.settings.devtools.pages.live2d-motion.title'),
description: t('tamagotchi.settings.devtools.pages.live2d-motion.description'),
icon: 'i-mingcute:game-2-fill',
to: '/devtools/live2d-motion',
},
{
title: 'WebSocket Inspector',
description: 'Inspect raw WebSocket traffic',
icon: 'i-solar:transfer-horizontal-bold-duotone',
to: '/devtools/websocket-inspector',
},
{
title: 'Plugin Host Debug',
description: 'Inspect discovered/enabled/loaded plugins and control load/unload lifecycle',
icon: 'i-solar:bug-bold-duotone',
to: '/devtools/plugin-host',
},
{
title: 'Updater',
description: 'Inspect updater state, explicit feed overrides, and install actions',
icon: 'i-solar:restart-bold-duotone',
to: '/devtools/updater',
},
{
title: 'Screen Capture',
description: 'Capture screen or window as video and/or audio streams',
icon: 'i-solar:screen-share-bold-duotone',
to: '/devtools/screen-capture',
},
{
title: 'Vision Capture',
description: 'Capture a screen frame and inspect the output payload',
icon: 'i-solar:eye-closed-bold-duotone',
to: '/devtools/vision',
},
{
title: 'Global Shortcut',
description: 'Register/unregister global shortcuts and watch trigger events fire',
icon: 'i-solar:keyboard-bold-duotone',
to: '/devtools/global-shortcut',
},
])
const openWebInspector = useHostEventaInvoke(electronOpenMainDevtools)
const openDevtoolsWindow = useHostEventaInvoke(electronOpenDevtoolsWindow)
import { isAndroidRenderer } from '../../../window-context'
</script>
<template>
<ButtonBar
v-model="settings.disableTransitions"
:class="['mb-2']"
icon="i-solar:settings-minimalistic-outline"
text="settings.pages.page.developers.open-devtools.title"
transition="all ease-in-out duration-250"
@click="openWebInspector({})"
>
{{ t('settings.pages.page.developers.open-devtools.button') }}
</ButtonBar>
<ButtonBar
:class="['mb-2']"
icon="i-solar:code-bold-duotone"
:text="t('tamagotchi.settings.devtools.pages.markdown-stress.title')"
transition="all ease-in-out duration-250"
@click="openDevtoolsWindow({ key: 'markdown-stress', route: '/devtools/markdown-stress' })"
>
{{ t('tamagotchi.settings.devtools.pages.markdown-stress.title') }}
</ButtonBar>
<ButtonBar
:class="['mb-2']"
icon="i-solar:chart-2-bold-duotone"
:text="t('tamagotchi.settings.devtools.pages.io-tracer.title')"
transition="all ease-in-out duration-250"
@click="openDevtoolsWindow({ key: 'io-tracer', route: '/devtools/io-tracer', width: 1600, height: 900 })"
>
{{ t('tamagotchi.settings.devtools.pages.io-tracer.title') }}
</ButtonBar>
<ButtonBar
:class="['mb-2']"
icon="i-solar:chart-square-bold-duotone"
:text="t('tamagotchi.settings.devtools.pages.lag-visualizer.title')"
transition="all ease-in-out duration-250"
@click="() => router.push('/devtools/performance-visualizer')"
>
{{ t('tamagotchi.settings.devtools.pages.lag-visualizer.title') }}
</ButtonBar>
<CheckBar
v-model="settings.disableTransitions"
mb-2
icon-on="i-solar:people-nearby-bold-duotone"
icon-off="i-solar:running-2-line-duotone"
text="settings.animations.stage-transitions.title"
transition="all ease-in-out duration-250"
/>
<CheckBar
v-model="settings.usePageSpecificTransitions"
:disabled="settings.disableTransitions"
icon-on="i-solar:running-2-line-duotone"
icon-off="i-solar:people-nearby-bold-duotone"
text="settings.animations.use-page-specific-transitions.title"
description="settings.animations.use-page-specific-transitions.description"
transition="all ease-in-out duration-250"
/>
<div flex="~ col gap-4" mt-2 pb-12>
<IconItem
v-for="(item, index) in menu"
:key="item.to"
v-motion
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250"
:style="{
transitionDelay: `${(index) * 50}ms`, // delay between each item, unocss doesn't support dynamic generation of classes now
}"
:title="item.title"
:description="item.description"
:icon="item.icon"
:to="item.to"
/>
</div>
<div
v-motion
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
fixed top="[65dvh]" right--15 z--1
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
:duration="250"
flex items-center justify-center
>
<div text="60" i-solar:code-bold-duotone />
</div>
<MobileDeveloperSettings v-if="isAndroidRenderer()" />
<DesktopDeveloperSettings v-else />
</template>
<route lang="yaml">
@@ -0,0 +1,147 @@
<script setup lang="ts">
import { CheckBar, IconItem } from '@proj-airi/stage-ui/components'
import { useSettings } from '@proj-airi/stage-ui/stores/settings'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const settings = useSettings()
const menu = computed(() => [
{
title: 'Audio Record',
description: 'Test Audio related composables',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/audio-record',
},
{
title: 'Background Theme color blending',
description: 'Test blending & theme',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/background-gradient-blending',
},
{
title: 'Background removal (WebGPU required)',
description: 'Utility for background removal',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/background-removal',
},
{
title: 'Chat',
description: 'Chat',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/chat',
},
{
title: 'Gesture Circle (Desktop only)',
description: 'Test gesture recognition',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/gesture-circle',
},
{
title: 'Image',
description: 'Image',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/image',
},
{
title: 'Polaroid',
description: 'Utility for taking shots of models',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/polaroid',
},
{
title: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.title'),
description: t('settings.pages.system.sections.section.developer.sections.section.use-magic-keys.description'),
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/use-magic-keys',
},
{
title: 'Color extract',
description: 'Test color extraction',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/vibrant',
},
{
title: 'Aliyun Real-time Transcriber',
description: 'Stream microphone audio to Aliyun NLS and inspect live transcripts',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/providers-transcription-realtime-aliyun-nls',
},
{
title: 'Performance Playground',
description: 'VRM expressions + TTS lip sync playground',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/performance-playground',
},
{
title: 'Notification',
description: 'Test notification',
icon: 'i-solar:sledgehammer-bold-duotone',
to: '/devtools/notifications',
},
{
title: 'WebSocket Inspector',
description: 'Inspect raw WebSocket traffic',
icon: 'i-solar:transfer-horizontal-bold-duotone',
to: '/devtools/websocket-inspector',
},
])
</script>
<template>
<CheckBar
v-model="settings.disableTransitions"
v-motion
:class="['mb-2', 'transition-all duration-250 ease-in-out']"
text="settings.animations.stage-transitions.title"
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250 + (19 * 10)"
:delay="1 * 50"
/>
<CheckBar
v-model="settings.usePageSpecificTransitions"
v-motion
:disabled="settings.disableTransitions"
text="settings.animations.use-page-specific-transitions.title"
description="settings.animations.use-page-specific-transitions.description"
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250 + (20 * 10)"
:delay="2 * 50"
:class="['transition-all duration-250 ease-in-out']"
/>
<div :class="['flex flex-col gap-4', 'pb-12']">
<IconItem
v-for="(item, index) in menu"
:key="item.to"
v-motion
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="250"
:style="{
transitionDelay: `${index * 50}ms`, // Stagger items because UnoCSS cannot generate classes from runtime values.
}"
:title="item.title"
:description="item.description"
:icon="item.icon"
:to="item.to"
/>
</div>
<div
v-motion
:class="[
'text-neutral-200/50 dark:text-neutral-600/20',
'pointer-events-none fixed top-[65dvh] right--15 z--1',
'flex items-center justify-center',
]"
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
:duration="250"
>
<div :class="['text-60', 'i-solar:code-bold-duotone']" />
</div>
</template>