refactor(stage-*): de-centralize for route header
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterView } from 'vue-router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { PageHeader } from '@proj-airi/stage-ui/components'
|
||||
import { useProvidersStore } from '@proj-airi/stage-ui/stores/providers'
|
||||
import { useTheme } from '@proj-airi/ui'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, onMounted, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterView, useRoute } from 'vue-router'
|
||||
@@ -15,139 +14,54 @@ const route = useRoute()
|
||||
const { isDark: dark } = useTheme()
|
||||
const { t } = useI18n()
|
||||
const providersStore = useProvidersStore()
|
||||
const { allProvidersMetadata } = storeToRefs(providersStore)
|
||||
const routeMeta = computed(() => route.meta as {
|
||||
titleKey?: string
|
||||
subtitleKey?: string
|
||||
title?: string
|
||||
subtitle?: string
|
||||
})
|
||||
|
||||
const routeHeaderMetadataMap = computed(() => {
|
||||
const map: Record<string, { subtitle?: string, title: string }> = {
|
||||
'/settings/airi-card': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.card.title'),
|
||||
},
|
||||
'/settings/characters': {
|
||||
subtitle: t('settings.title'),
|
||||
title: 'Characters',
|
||||
},
|
||||
'/settings/system': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.system.title'),
|
||||
},
|
||||
'/settings/system/general': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.system.general.title'),
|
||||
},
|
||||
'/settings/system/color-scheme': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.system.color-scheme.title'),
|
||||
},
|
||||
'/settings/system/developer': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.system.developer.title'),
|
||||
},
|
||||
'/settings/memory': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.memory.title'),
|
||||
},
|
||||
'/settings/models': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.models.title'),
|
||||
},
|
||||
'/settings/modules': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.title'),
|
||||
},
|
||||
'/settings/modules/consciousness': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.consciousness.title'),
|
||||
},
|
||||
'/settings/modules/speech': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.speech.title'),
|
||||
},
|
||||
'/settings/modules/hearing': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.hearing.title'),
|
||||
},
|
||||
'/settings/modules/vision': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.vision.title'),
|
||||
},
|
||||
'/settings/modules/memory-short-term': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.memory-short-term.title'),
|
||||
},
|
||||
'/settings/modules/memory-long-term': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.memory-long-term.title'),
|
||||
},
|
||||
'/settings/modules/messaging-discord': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.messaging-discord.title'),
|
||||
},
|
||||
'/settings/modules/x': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.x.title'),
|
||||
},
|
||||
'/settings/modules/gaming-minecraft': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.gaming-minecraft.title'),
|
||||
},
|
||||
'/settings/modules/gaming-factorio': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.modules.gaming-factorio.title'),
|
||||
},
|
||||
'/settings/providers': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.providers.title'),
|
||||
},
|
||||
'/settings/data': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.data.title'),
|
||||
},
|
||||
'/settings/connection': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.connection.title'),
|
||||
},
|
||||
'/settings/scene': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.scene.title'),
|
||||
},
|
||||
'/settings': {
|
||||
title: t('settings.title'),
|
||||
},
|
||||
'/devtools/context-flow': {
|
||||
subtitle: t('tamagotchi.settings.devtools.title'),
|
||||
title: t('tamagotchi.settings.devtools.pages.context-flow.title'),
|
||||
},
|
||||
'/devtools/websocket-inspector': {
|
||||
subtitle: t('tamagotchi.settings.devtools.title'),
|
||||
title: 'WebSocket Inspector',
|
||||
},
|
||||
'/devtools/performance-visualizer': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.system.sections.section.developer.sections.section.performance-visualizer.title'),
|
||||
},
|
||||
'/devtools/markdown-stress': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.system.sections.section.developer.sections.section.markdown-stress.title'),
|
||||
},
|
||||
'/devtools/screen-capture': {
|
||||
subtitle: t('settings.title'),
|
||||
title: 'Screen Capture',
|
||||
},
|
||||
const providerTitle = computed(() => {
|
||||
if (!route.path.startsWith('/settings/providers/'))
|
||||
return undefined
|
||||
|
||||
const segments = route.path.split('/').filter(Boolean)
|
||||
const providerId = segments[3]
|
||||
|
||||
if (!providerId)
|
||||
return undefined
|
||||
|
||||
try {
|
||||
const metadata = providersStore.getProviderMetadata(providerId)
|
||||
return t(metadata.nameKey)
|
||||
}
|
||||
|
||||
for (const metadata of allProvidersMetadata.value) {
|
||||
map[`/settings/providers/${metadata.category}/${metadata.id}`] = {
|
||||
subtitle: t('settings.title'),
|
||||
title: t(metadata.nameKey),
|
||||
}
|
||||
catch {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return map
|
||||
})
|
||||
|
||||
// const activeSettingsTutorial = ref('default')
|
||||
const routeHeaderMetadata = computed(() => routeHeaderMetadataMap.value[route.path])
|
||||
const routeHeaderMetadata = computed(() => {
|
||||
const { titleKey, subtitleKey, title, subtitle } = routeMeta.value
|
||||
const resolvedTitle = titleKey ? t(titleKey) : title
|
||||
const resolvedSubtitle = subtitleKey ? t(subtitleKey) : subtitle
|
||||
|
||||
if (resolvedTitle || resolvedSubtitle) {
|
||||
return {
|
||||
title: resolvedTitle,
|
||||
subtitle: resolvedSubtitle,
|
||||
}
|
||||
}
|
||||
|
||||
if (providerTitle.value) {
|
||||
return {
|
||||
title: providerTitle.value,
|
||||
subtitle: t('settings.title'),
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
||||
const { updateThemeColor } = useThemeColor(themeColorFromValue({ light: 'rgb(255 255 255)', dark: 'rgb(18 18 18)' }))
|
||||
watch(dark, () => updateThemeColor(), { immediate: true })
|
||||
|
||||
@@ -347,4 +347,6 @@ function hitVSequence() {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.beat_sync.title
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
@@ -586,4 +586,6 @@ onUnmounted(() => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: tamagotchi.settings.devtools.pages.context-flow.title
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
@@ -62,4 +62,6 @@ async function handleFileChange(event: Event) {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
title: Image
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
@@ -157,4 +157,6 @@ function toggleMode() {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: tamagotchi.settings.devtools.pages.markdown-stress.title
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
+2
@@ -503,4 +503,6 @@ onBeforeUnmount(async () => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
title: Aliyun NLS Realtime Transcription
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
@@ -65,4 +65,6 @@ watch(files, (files) => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
title: Vibrant
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
@@ -188,4 +188,6 @@ function payloadClasses(direction: 'incoming' | 'outgoing') {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
title: WebSocket Inspector
|
||||
subtitleKey: tamagotchi.settings.devtools.title
|
||||
</route>
|
||||
|
||||
@@ -331,6 +331,12 @@ function getModuleShortName(id: string, module: 'consciousness' | 'voice') {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.card.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.card.description
|
||||
icon: i-solar:emoji-funny-square-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 1
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -9,6 +9,12 @@ import ConnectionSettings from './ConnectionSettings.vue'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.connection.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.connection.description
|
||||
icon: i-solar:wi-fi-router-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 8
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -286,6 +286,12 @@ async function handleImport(event: Event) {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.data.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.data.description
|
||||
icon: i-solar:database-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 7
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -26,62 +26,18 @@ const removeBeforeEach = router.beforeEach(async (_, __, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
const settings = computed(() => [
|
||||
{
|
||||
title: t('settings.pages.card.title'),
|
||||
description: t('settings.pages.card.description'),
|
||||
icon: 'i-solar:emoji-funny-square-bold-duotone',
|
||||
to: '/settings/airi-card',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.modules.title'),
|
||||
description: t('settings.pages.modules.description'),
|
||||
icon: 'i-solar:layers-bold-duotone',
|
||||
to: '/settings/modules',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.scene.title'),
|
||||
description: t('settings.pages.scene.description'),
|
||||
icon: 'i-solar:armchair-2-bold-duotone',
|
||||
to: '/settings/scene',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.models.title'),
|
||||
description: t('settings.pages.models.description'),
|
||||
icon: 'i-solar:people-nearby-bold-duotone',
|
||||
to: '/settings/models',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.memory.title'),
|
||||
description: t('settings.pages.memory.description'),
|
||||
icon: 'i-solar:leaf-bold-duotone',
|
||||
to: '/settings/memory',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.providers.title'),
|
||||
description: t('settings.pages.providers.description'),
|
||||
icon: 'i-solar:box-minimalistic-bold-duotone',
|
||||
to: '/settings/providers',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.data.title'),
|
||||
description: t('settings.pages.data.description'),
|
||||
icon: 'i-solar:database-bold-duotone',
|
||||
to: '/settings/data',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.connection.title'),
|
||||
description: t('settings.pages.connection.description'),
|
||||
icon: 'i-solar:wi-fi-router-bold-duotone',
|
||||
to: '/settings/connection',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.system.title'),
|
||||
description: t('settings.pages.system.description'),
|
||||
icon: 'i-solar:filters-bold-duotone',
|
||||
to: '/settings/system',
|
||||
},
|
||||
])
|
||||
const settings = computed(() => {
|
||||
return router
|
||||
.getRoutes()
|
||||
.filter(route => route.meta?.settingsEntry)
|
||||
.sort((a, b) => (Number(a.meta?.order ?? 0) - Number(b.meta?.order ?? 0)))
|
||||
.map(route => ({
|
||||
title: route.meta?.titleKey ? t(route.meta.titleKey as string) : (route.meta?.title as string | undefined),
|
||||
description: route.meta?.descriptionKey ? t(route.meta.descriptionKey as string) : (route.meta?.description as string | undefined) || '',
|
||||
icon: route.meta?.icon as string | undefined,
|
||||
to: route.path,
|
||||
}))
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -122,6 +78,7 @@ const settings = computed(() => [
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -9,6 +9,12 @@ import { WIP } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.memory.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.memory.description
|
||||
icon: i-solar:leaf-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 5
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -59,6 +59,12 @@ async function extractColorsFromModel() {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.models.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.models.description
|
||||
icon: i-solar:people-nearby-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 4
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -350,6 +350,8 @@ onUnmounted(() => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.beat_sync.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -249,6 +249,8 @@ function handleDeleteProvider(providerId: string) {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.consciousness.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -9,6 +9,8 @@ import { GamingFactorio } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.gaming-factorio.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -9,6 +9,8 @@ import { GamingMinecraft } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.gaming-minecraft.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -919,6 +919,8 @@ onUnmounted(() => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.hearing.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -45,6 +45,12 @@ const { lastClickedIndex, setLastClickedIndex } = useRippleGridState()
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.modules.description
|
||||
icon: i-solar:layers-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 2
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -9,6 +9,8 @@ import { WIP } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.memory-long-term.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -9,6 +9,8 @@ import { WIP } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.memory-short-term.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -9,6 +9,8 @@ import { MessagingDiscord } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.messaging-discord.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -593,6 +593,8 @@ function updateCustomModelName(value: string | undefined) {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.speech.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -9,6 +9,8 @@ import { WIP } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.vision.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -9,6 +9,8 @@ import { X } from '@proj-airi/stage-ui/components'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.modules.x.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -137,6 +137,12 @@ useScrollToHash(() => route.hash, {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.providers.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.providers.description
|
||||
icon: i-solar:box-minimalistic-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 6
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -31,6 +31,12 @@ import { Callout } from '@proj-airi/ui'
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.scene.title
|
||||
subtitleKey: settings.title
|
||||
descriptionKey: settings.pages.scene.description
|
||||
icon: i-solar:armchair-2-bold-duotone
|
||||
settingsEntry: true
|
||||
order: 3
|
||||
stageTransition:
|
||||
name: slide
|
||||
pageSpecificAvailable: true
|
||||
|
||||
@@ -227,6 +227,8 @@ const themePresets = computed(() => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.system.color-scheme.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
@@ -87,6 +87,8 @@ const languages = computed(() => {
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
titleKey: settings.pages.system.general.title
|
||||
subtitleKey: settings.title
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
|
||||
Reference in New Issue
Block a user