feat: replace settings with a full page
This commit is contained in:
@@ -1,138 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import GeneralSettings from '~/components/Settings/GeneralSettings.vue';
|
||||
import ProviderSettings from '~/components/Settings/ProviderSettings.vue';
|
||||
import ProviderSidebar from '~/components/Settings/ProviderSidebar.vue';
|
||||
import SystemAssistants from '~/components/Settings/SystemAssistants.vue';
|
||||
import AppearanceSettings from '~/components/Settings/AppearanceSettings.vue';
|
||||
import AIServiceProvider from '~/components/Settings/AIServiceProvider.vue';
|
||||
|
||||
const { providers } = await useModels();
|
||||
|
||||
const PAGES_CONFIG = {
|
||||
general: {
|
||||
label: 'General',
|
||||
icon: 'i-mynaui-cog-four',
|
||||
component: GeneralSettings
|
||||
},
|
||||
appearance: {
|
||||
label: 'Appearance',
|
||||
icon: 'i-tabler-palette',
|
||||
component: AppearanceSettings
|
||||
},
|
||||
providers: {
|
||||
label: 'AI Providers',
|
||||
icon: 'i-mynaui-api',
|
||||
component: ProviderSettings,
|
||||
sidebar: ProviderSidebar
|
||||
},
|
||||
systemAssistants: {
|
||||
label: 'System Assistants',
|
||||
icon: 'i-mynaui-sparkles',
|
||||
component: SystemAssistants
|
||||
},
|
||||
} as const;
|
||||
|
||||
const props = defineProps<{
|
||||
page: keyof typeof PAGES_CONFIG;
|
||||
params?: string;
|
||||
}>();
|
||||
|
||||
const { close, setOptions } = useDialog();
|
||||
|
||||
const mobileNavOpen = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
if (window.innerWidth >= 768) {
|
||||
mobileNavOpen.value = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const handleNavigate = (page: string, params?: string) => {
|
||||
setOptions({ page: page as keyof typeof PAGES_CONFIG, params });
|
||||
mobileNavOpen.value = false;
|
||||
};
|
||||
|
||||
const runtimePage = computed(() => {
|
||||
// 1. Get the base config (e.g., 'providers' or 'general')
|
||||
const config = PAGES_CONFIG[props.page as keyof typeof PAGES_CONFIG] || PAGES_CONFIG.general;
|
||||
|
||||
// 2. Determine the actual component to show
|
||||
let component = config.component;
|
||||
let label = config.label as string;
|
||||
|
||||
if (props.page === 'providers' && props.params) {
|
||||
component = AIServiceProvider;
|
||||
const providerId = props.params;
|
||||
const provider = providers.value!.find(p => p.id === providerId);
|
||||
label = provider ? provider.name : 'Unknown Provider';
|
||||
}
|
||||
|
||||
return {
|
||||
...config,
|
||||
label,
|
||||
component,
|
||||
params: props.params,
|
||||
} as {
|
||||
label: string;
|
||||
icon: string;
|
||||
component: Component;
|
||||
sidebar?: Component;
|
||||
params: string;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-2 flex flex-col md:flex-row h-screen md:h-[70vh] md:h-[70dvh] w-screen md:w-[85vw]">
|
||||
<nav :class="[
|
||||
'w-full md:w-64 flex-col gap-1 mr-2 overflow-y-auto text-xl md:text-base',
|
||||
// Mobile: hidden by default, shown as fixed overlay
|
||||
'hidden md:flex',
|
||||
mobileNavOpen ? '!flex fixed inset-y-0 left-0 z-15 bg-[var(--bg-base)] p-2 shadow-xl' : ''
|
||||
]">
|
||||
<!-- Mobile close button -->
|
||||
<button
|
||||
class="md:hidden flex items-center justify-center h-9 w-full rounded-lg @hover:bg-[var(--color-hover)] text-[var(--text-secondary)]"
|
||||
@click="mobileNavOpen = false">
|
||||
<span class="i-mynaui-x-solid mr-2"></span>
|
||||
Close
|
||||
</button>
|
||||
|
||||
<!-- If the page has a custom sidebar (for nested lists), show it; otherwise show default nav -->
|
||||
<component v-if="runtimePage?.sidebar" :is="runtimePage.sidebar" @navigate="handleNavigate"
|
||||
:params="props.params" />
|
||||
|
||||
<button v-else v-for="(config, id) in PAGES_CONFIG" :key="id" @click="handleNavigate(id)"
|
||||
:class="[page === id ? 'bg-[var(--color-hover)]' : '@hover:bg-[var(--color-hover)]', 'flex justify-between items-center shrink-0 px-1 rounded-lg transition-colors cursor-pointer h-9']">
|
||||
<div class="flex items-center gap-2 max-w-full flex-1">
|
||||
<span :class="['w-5 h-5 text-5', config.icon]"></span>
|
||||
{{ config.label }}
|
||||
</div>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<!-- DYNAMIC CONTENT -->
|
||||
<main
|
||||
class="flex-1 flex flex-col overflow-y-hidden max-h-full h-full px-3 bg-[var(--bg-surface)] border rounded-none md:rounded-lg border-[var(--color-border)]">
|
||||
<header class="flex items-center justify-between pl-2 pb-2 pt-2 ">
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Mobile menu button -->
|
||||
<button
|
||||
class="md:hidden flex items-center justify-center h-8 w-8 rounded-lg @hover:bg-[var(--color-hover)]"
|
||||
@click="mobileNavOpen = true">
|
||||
<span class="i-mynaui-menu text-5"></span>
|
||||
</button>
|
||||
<h2 class="text-lg font-semibold m-0 case-capital">{{ runtimePage.label }}</h2>
|
||||
</div>
|
||||
<button
|
||||
class="@hover:bg-[var(--color-hover)] p-1.5 rounded-md transition-colors duration-200 ease-[cubic-bezier(0,0.55,0.45,1)]"
|
||||
@click="close">
|
||||
<span class="i-mynaui-x-solid"></span>
|
||||
</button>
|
||||
</header>
|
||||
<component @navigate="handleNavigate" :is="runtimePage.component" :params="props.params" />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import Textbox from './Textbox.vue';
|
||||
import Settings from './Settings.vue';
|
||||
import QuickSwitcher from './QuickSwitcher.vue';
|
||||
|
||||
import { DialogType } from '~/composables/useDialog';
|
||||
@@ -11,7 +10,7 @@ const { addShortcut } = useKeyboardShortcuts();
|
||||
const unbindSettingsShortcut = addShortcut(['ctrl', ','], (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
openDialog(DialogType.Settings);
|
||||
navigateTo('/settings');
|
||||
});
|
||||
|
||||
const unbindQuickSwitcherShortcut = addShortcut(['ctrl', 'k'], (event) => {
|
||||
@@ -57,9 +56,7 @@ onUnmounted(() => {
|
||||
<div
|
||||
class="absolute w-full h-full md:w-auto md:h-auto max-w-6xl bg-[var(--bg-base)] rounded-none md:rounded-2xl shadow-2xl border border-[var(--color-border)] flex">
|
||||
<KeepAlive>
|
||||
<Settings v-if="page === DialogType.Settings" :page="data.page" :params="data.params" />
|
||||
|
||||
<Textbox v-else-if="page === DialogType.Textbox" v-bind="data" @confirm="confirm" @cancel="close" />
|
||||
<Textbox v-if="page === DialogType.Textbox" v-bind="data" @confirm="confirm" @cancel="close" />
|
||||
|
||||
<QuickSwitcher v-else-if="page === DialogType.QuickSwitcher" @close="close" />
|
||||
</KeepAlive>
|
||||
|
||||
Reference in New Issue
Block a user