feat: Separate dialogs for MCP Servers Settings and Import/Export
This commit is contained in:
parent
9c922bae32
commit
8c55e86cba
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -18,7 +18,7 @@
|
|||
<div style="display: contents">
|
||||
<script>
|
||||
{
|
||||
__sveltekit_pcz11y = {
|
||||
__sveltekit_uoz4e7 = {
|
||||
base: new URL('.', location).pathname.slice(0, -1)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.987 0 0);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.19 0 0);
|
||||
--sidebar: oklch(0.2 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@
|
|||
ModelsSelector,
|
||||
ModelsSelectorSheet
|
||||
} from '$lib/components/app';
|
||||
import { SETTINGS_SECTION_TITLES } from '$lib/constants';
|
||||
import { getChatSettingsDialogContext } from '$lib/contexts';
|
||||
import { getMcpServersDialogContext } from '$lib/contexts';
|
||||
import { FileTypeCategory } from '$lib/enums';
|
||||
import { IsMobile } from '$lib/hooks/is-mobile.svelte';
|
||||
import { chatStore } from '$lib/stores/chat.svelte';
|
||||
|
|
@ -54,7 +53,7 @@
|
|||
onMcpResourcesClick
|
||||
}: Props = $props();
|
||||
|
||||
const chatSettingsDialog = getChatSettingsDialogContext();
|
||||
const mcpServersDialog = getMcpServersDialogContext();
|
||||
|
||||
let currentConfig = $derived(config());
|
||||
let isRouter = $derived(isRouterMode());
|
||||
|
|
@ -214,7 +213,7 @@
|
|||
</div>
|
||||
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
<McpActiveServersAvatars onClick={() => chatSettingsDialog.open(SETTINGS_SECTION_TITLES.MCP)} />
|
||||
<McpActiveServersAvatars onClick={() => mcpServersDialog.open()} />
|
||||
|
||||
{#if isMobile.current}
|
||||
<ModelsSelectorSheet
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import { afterNavigate } from '$app/navigation';
|
||||
import {
|
||||
ChatScreenForm,
|
||||
ChatScreenHeader,
|
||||
ChatMessages,
|
||||
ChatScreenProcessingInfo,
|
||||
DialogEmptyFileAlert,
|
||||
|
|
@ -342,8 +341,6 @@
|
|||
|
||||
<svelte:window onkeydown={handleKeydown} />
|
||||
|
||||
<ChatScreenHeader />
|
||||
|
||||
{#if !isEmpty}
|
||||
<div
|
||||
bind:this={chatScrollContainer}
|
||||
|
|
@ -427,7 +424,7 @@
|
|||
>
|
||||
<div class="w-full max-w-[48rem] px-4">
|
||||
<div class="mb-10 text-center" in:fade={{ duration: 300 }}>
|
||||
<h1 class="mb-2 text-2xl font-semibold tracking-tight md:text-3xl">llama.cpp</h1>
|
||||
<h1 class="mb-2 text-2xl font-semibold tracking-tight md:text-3xl">Hello there</h1>
|
||||
|
||||
<p class="text-muted-foreground md:text-lg">
|
||||
{serverStore.props?.modalities?.audio
|
||||
|
|
|
|||
|
|
@ -7,16 +7,9 @@
|
|||
Monitor,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Database,
|
||||
ListRestart
|
||||
} from '@lucide/svelte';
|
||||
import {
|
||||
ChatSettingsFooter,
|
||||
ChatSettingsImportExportTab,
|
||||
ChatSettingsFields,
|
||||
McpLogo,
|
||||
McpServersSettings
|
||||
} from '$lib/components/app';
|
||||
import { ChatSettingsFooter, ChatSettingsFields } from '$lib/components/app';
|
||||
import { ScrollArea } from '$lib/components/ui/scroll-area';
|
||||
import { config, settingsStore } from '$lib/stores/settings.svelte';
|
||||
import {
|
||||
|
|
@ -283,16 +276,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: SETTINGS_SECTION_TITLES.IMPORT_EXPORT,
|
||||
icon: Database,
|
||||
fields: []
|
||||
},
|
||||
{
|
||||
title: SETTINGS_SECTION_TITLES.MCP,
|
||||
icon: McpLogo,
|
||||
fields: []
|
||||
},
|
||||
{
|
||||
title: SETTINGS_SECTION_TITLES.DEVELOPER,
|
||||
icon: Code,
|
||||
|
|
@ -529,12 +512,6 @@
|
|||
<h3 class="text-lg font-semibold">{currentSection.title}</h3>
|
||||
</div>
|
||||
|
||||
{#if currentSection.title === SETTINGS_SECTION_TITLES.IMPORT_EXPORT}
|
||||
<ChatSettingsImportExportTab />
|
||||
{:else if currentSection.title === SETTINGS_SECTION_TITLES.MCP}
|
||||
<McpServersSettings />
|
||||
{/if}
|
||||
|
||||
{#if currentSection.fields}
|
||||
<div class="space-y-6">
|
||||
<ChatSettingsFields
|
||||
|
|
|
|||
|
|
@ -138,8 +138,8 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<ScrollArea class="h-[100vh]">
|
||||
<Sidebar.Header class=" top-0 z-10 gap-4 bg-sidebar/50 p-4 pb-2 backdrop-blur-lg md:sticky">
|
||||
<ScrollArea>
|
||||
<Sidebar.Header class=" top-0 z-10 gap-4 bg-sidebar/50 p-3 pt-4 pb-2 backdrop-blur-lg md:sticky">
|
||||
<a href="#/" onclick={handleMobileSidebarItemClick}>
|
||||
<h1 class="inline-flex items-center gap-1 px-2 text-xl font-semibold">llama.cpp</h1>
|
||||
</a>
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
<ChatSidebarActions {handleMobileSidebarItemClick} bind:isSearchModeActive bind:searchQuery />
|
||||
</Sidebar.Header>
|
||||
|
||||
<Sidebar.Group class="mt-2 space-y-2 p-0 px-4">
|
||||
<Sidebar.Group class="mt-2 space-y-2 p-0 px-3">
|
||||
{#if (filteredConversations.length > 0 && isSearchModeActive) || !isSearchModeActive}
|
||||
<Sidebar.GroupLabel>
|
||||
{isSearchModeActive ? 'Search results' : 'Conversations'}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { Search, SquarePen, X } from '@lucide/svelte';
|
||||
import { Database, Search, Settings, SquarePen, X } from '@lucide/svelte';
|
||||
import { KeyboardShortcutInfo } from '$lib/components/app';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
import { McpLogo } from '$lib/components/app';
|
||||
import { SETTINGS_SECTION_TITLES } from '$lib/constants';
|
||||
import { getChatSettingsDialogContext } from '$lib/contexts';
|
||||
import {
|
||||
getChatSettingsDialogContext,
|
||||
getMcpServersDialogContext,
|
||||
getImportExportDialogContext
|
||||
} from '$lib/contexts';
|
||||
|
||||
interface Props {
|
||||
handleMobileSidebarItemClick: () => void;
|
||||
|
|
@ -22,6 +25,8 @@
|
|||
let searchInput: HTMLInputElement | null = $state(null);
|
||||
|
||||
const chatSettingsDialog = getChatSettingsDialogContext();
|
||||
const mcpServersDialog = getMcpServersDialogContext();
|
||||
const importExportDialog = getImportExportDialogContext();
|
||||
|
||||
function handleSearchModeDeactivate() {
|
||||
isSearchModeActive = false;
|
||||
|
|
@ -55,7 +60,7 @@
|
|||
</div>
|
||||
{:else}
|
||||
<Button
|
||||
class="w-full justify-between backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
href="?new_chat=true#/"
|
||||
onclick={handleMobileSidebarItemClick}
|
||||
variant="ghost"
|
||||
|
|
@ -70,7 +75,7 @@
|
|||
</Button>
|
||||
|
||||
<Button
|
||||
class="w-full justify-between backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
onclick={() => {
|
||||
isSearchModeActive = true;
|
||||
}}
|
||||
|
|
@ -86,9 +91,9 @@
|
|||
</Button>
|
||||
|
||||
<Button
|
||||
class="w-full justify-between backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
onclick={() => {
|
||||
chatSettingsDialog.open(SETTINGS_SECTION_TITLES.MCP);
|
||||
mcpServersDialog.open();
|
||||
}}
|
||||
variant="ghost"
|
||||
>
|
||||
|
|
@ -98,5 +103,33 @@
|
|||
MCP Servers
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
onclick={() => {
|
||||
importExportDialog.open();
|
||||
}}
|
||||
variant="ghost"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<Database class="h-4 w-4" />
|
||||
|
||||
Import / Export
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100"
|
||||
onclick={() => {
|
||||
chatSettingsDialog.open();
|
||||
}}
|
||||
variant="ghost"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<Settings class="h-4 w-4" />
|
||||
|
||||
Settings
|
||||
</div>
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
<script lang="ts">
|
||||
import * as Dialog from '$lib/components/ui/dialog';
|
||||
import { ChatSettingsImportExportTab } from '$lib/components/app/chat';
|
||||
|
||||
interface Props {
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
let { onOpenChange, open = false }: Props = $props();
|
||||
|
||||
function handleClose() {
|
||||
onOpenChange?.(false);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Dialog.Root {open} onOpenChange={handleClose}>
|
||||
<Dialog.Content
|
||||
class="z-999999 flex h-[100dvh] max-h-[100dvh] min-h-[100dvh] max-w-4xl! flex-col gap-0 rounded-none
|
||||
p-0 md:h-[80vh] md:max-h-[80vh] md:min-h-0 md:rounded-lg"
|
||||
>
|
||||
<div class="grid gap-2 border-b border-border/30 p-4 md:p-6">
|
||||
<Dialog.Title class="text-lg font-semibold">Import/Export Conversations</Dialog.Title>
|
||||
<Dialog.Description class="text-sm text-muted-foreground">
|
||||
Export your conversations to a JSON file or import previously exported conversations.
|
||||
</Dialog.Description>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-y-auto px-4 py-6">
|
||||
<ChatSettingsImportExportTab />
|
||||
</div>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
open?: boolean;
|
||||
}
|
||||
|
||||
let { onOpenChange, open = $bindable(false) }: Props = $props();
|
||||
let { onOpenChange, open = false }: Props = $props();
|
||||
|
||||
function handleClose() {
|
||||
onOpenChange?.(false);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,50 @@
|
|||
*/
|
||||
export { default as DialogChatSettings } from './DialogChatSettings.svelte';
|
||||
|
||||
/**
|
||||
* **DialogMcpServersSettings** - MCP servers management dialog
|
||||
*
|
||||
* Modal dialog for managing MCP servers with dedicated context.
|
||||
*
|
||||
* **Architecture:**
|
||||
* - Uses context-based state management
|
||||
* - Provides `open()` method via context
|
||||
* - Contains McpServersSettings component
|
||||
*
|
||||
* @example
|
||||
* ```svelte
|
||||
* <!-- In parent component -->
|
||||
* <DialogMcpServersSettings />
|
||||
*
|
||||
* <!-- Trigger via context -->
|
||||
* {#const mcpDialog = getMcpServersDialogContext()}
|
||||
* <Button onclick={() => mcpDialog.open()}>Manage MCP Servers</Button>
|
||||
* ```
|
||||
*/
|
||||
export { default as DialogMcpServersSettings } from './DialogMcpServersSettings.svelte';
|
||||
|
||||
/**
|
||||
* **DialogChatSettingsImportExport** - Import/Export conversations dialog
|
||||
*
|
||||
* Modal dialog for importing and exporting conversations with dedicated context.
|
||||
*
|
||||
* **Architecture:**
|
||||
* - Uses context-based state management
|
||||
* - Provides `open()` method via context
|
||||
* - Contains ChatSettingsImportExportTab component
|
||||
*
|
||||
* @example
|
||||
* ```svelte
|
||||
* <!-- In parent component -->
|
||||
* <DialogChatSettingsImportExport />
|
||||
*
|
||||
* <!-- Trigger via context -->
|
||||
* {#const importExportDialog = getImportExportDialogContext()}
|
||||
* <Button onclick={() => importExportDialog.open()}>Import/Export</Button>
|
||||
* ```
|
||||
*/
|
||||
export { default as DialogChatSettingsImportExport } from './DialogChatSettingsImportExport.svelte';
|
||||
|
||||
/**
|
||||
*
|
||||
* CONFIRMATION DIALOGS
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { tv, type VariantProps } from 'tailwind-variants';
|
||||
|
||||
export const sidebarMenuButtonVariants = tv({
|
||||
base: 'peer/menu-button outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground group-has-data-[sidebar=menu-action]/menu-item:pr-8 data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
base: 'peer/menu-button outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground group-has-data-[sidebar=menu-action]/menu-item:pr-8 data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! flex w-full items-center gap-2 overflow-hidden rounded-md py-2 px-1 text-left text-sm transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
|
||||
|
|
|
|||
|
|
@ -21,9 +21,7 @@
|
|||
data-slot="sidebar-trigger"
|
||||
variant="ghost"
|
||||
size="icon-lg"
|
||||
class="rounded-full backdrop-blur-lg {className} md:left-{sidebar.open
|
||||
? 'unset'
|
||||
: '2'} -top-2 -left-2 md:top-0"
|
||||
class="rounded-full backdrop-blur-lg {className} top-1.5 md:left-[14.5rem]"
|
||||
type="button"
|
||||
onclick={(e) => {
|
||||
onclick?.(e);
|
||||
|
|
|
|||
|
|
@ -74,19 +74,23 @@
|
|||
: 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)'
|
||||
)}
|
||||
></div>
|
||||
|
||||
<div
|
||||
data-slot="sidebar-container"
|
||||
class={cn(
|
||||
'fixed inset-y-0 z-999 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:z-0 md:flex',
|
||||
'fixed inset-y-0 z-999 hidden w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:z-0 md:flex',
|
||||
side === 'left'
|
||||
? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
|
||||
: 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
|
||||
? 'left-3 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
|
||||
: 'right-1 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
|
||||
// Adjust the padding for floating and inset variants.
|
||||
variant === 'floating' || variant === 'inset'
|
||||
? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
|
||||
: 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
|
||||
// Add margin and rounded corners
|
||||
'my-3 overflow-hidden rounded-2xl border border-sidebar-border shadow-md',
|
||||
className
|
||||
)}
|
||||
style="height: calc(100dvh - 1.5rem);"
|
||||
{...restProps}
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
export const CONTEXT_KEY_MESSAGE_EDIT = 'chat-message-edit';
|
||||
export const CONTEXT_KEY_CHAT_ACTIONS = 'chat-actions';
|
||||
export const CONTEXT_KEY_CHAT_SETTINGS_DIALOG = 'chat-settings-dialog';
|
||||
export const CONTEXT_KEY_MCP_SERVERS_DIALOG = 'mcp-servers-dialog';
|
||||
export const CONTEXT_KEY_IMPORT_EXPORT_DIALOG = 'import-export-dialog';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
import { getContext, setContext } from 'svelte';
|
||||
import { CONTEXT_KEY_IMPORT_EXPORT_DIALOG } from '$lib/constants';
|
||||
|
||||
export interface ImportExportDialogContext {
|
||||
open: () => void;
|
||||
}
|
||||
|
||||
const IMPORT_EXPORT_DIALOG_KEY = Symbol.for(CONTEXT_KEY_IMPORT_EXPORT_DIALOG);
|
||||
|
||||
export function setImportExportDialogContext(
|
||||
ctx: ImportExportDialogContext
|
||||
): ImportExportDialogContext {
|
||||
return setContext(IMPORT_EXPORT_DIALOG_KEY, ctx);
|
||||
}
|
||||
|
||||
export function getImportExportDialogContext(): ImportExportDialogContext {
|
||||
return getContext(IMPORT_EXPORT_DIALOG_KEY);
|
||||
}
|
||||
|
|
@ -17,3 +17,15 @@ export {
|
|||
setChatSettingsDialogContext,
|
||||
type ChatSettingsDialogContext
|
||||
} from './chat-settings-dialog.context';
|
||||
|
||||
export {
|
||||
getMcpServersDialogContext,
|
||||
setMcpServersDialogContext,
|
||||
type McpServersDialogContext
|
||||
} from './mcp-servers-dialog.context';
|
||||
|
||||
export {
|
||||
getImportExportDialogContext,
|
||||
setImportExportDialogContext,
|
||||
type ImportExportDialogContext
|
||||
} from './import-export-dialog.context';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
import { getContext, setContext } from 'svelte';
|
||||
import { CONTEXT_KEY_MCP_SERVERS_DIALOG } from '$lib/constants';
|
||||
|
||||
export interface McpServersDialogContext {
|
||||
open: () => void;
|
||||
}
|
||||
|
||||
const MCP_SERVERS_DIALOG_KEY = Symbol.for(CONTEXT_KEY_MCP_SERVERS_DIALOG);
|
||||
|
||||
export function setMcpServersDialogContext(ctx: McpServersDialogContext): McpServersDialogContext {
|
||||
return setContext(MCP_SERVERS_DIALOG_KEY, ctx);
|
||||
}
|
||||
|
||||
export function getMcpServersDialogContext(): McpServersDialogContext {
|
||||
return getContext(MCP_SERVERS_DIALOG_KEY);
|
||||
}
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
import {
|
||||
ChatSidebar,
|
||||
DialogConversationTitleUpdate,
|
||||
DialogChatSettings
|
||||
DialogChatSettings,
|
||||
DialogMcpServersSettings,
|
||||
DialogChatSettingsImportExport
|
||||
} from '$lib/components/app';
|
||||
import { isLoading } from '$lib/stores/chat.svelte';
|
||||
import { conversationsStore, activeMessages } from '$lib/stores/conversations.svelte';
|
||||
|
|
@ -24,7 +26,11 @@
|
|||
import type { SettingsSectionTitle } from '$lib/constants';
|
||||
import { KeyboardKey } from '$lib/enums';
|
||||
import { IsMobile } from '$lib/hooks/is-mobile.svelte';
|
||||
import { setChatSettingsDialogContext } from '$lib/contexts';
|
||||
import {
|
||||
setChatSettingsDialogContext,
|
||||
setMcpServersDialogContext,
|
||||
setImportExportDialogContext
|
||||
} from '$lib/contexts';
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
|
|
@ -50,6 +56,8 @@
|
|||
|
||||
let chatSettingsDialogOpen = $state(false);
|
||||
let chatSettingsDialogInitialSection = $state<SettingsSectionTitle | undefined>(undefined);
|
||||
let mcpServersDialogOpen = $state(false);
|
||||
let importExportDialogOpen = $state(false);
|
||||
|
||||
setChatSettingsDialogContext({
|
||||
open: (initialSection?: SettingsSectionTitle) => {
|
||||
|
|
@ -58,6 +66,18 @@
|
|||
}
|
||||
});
|
||||
|
||||
setMcpServersDialogContext({
|
||||
open: () => {
|
||||
mcpServersDialogOpen = true;
|
||||
}
|
||||
});
|
||||
|
||||
setImportExportDialogContext({
|
||||
open: () => {
|
||||
importExportDialogOpen = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Global keyboard shortcuts
|
||||
function handleKeydown(event: KeyboardEvent) {
|
||||
const isCtrlOrCmd = event.ctrlKey || event.metaKey;
|
||||
|
|
@ -235,6 +255,15 @@
|
|||
initialSection={chatSettingsDialogInitialSection}
|
||||
/>
|
||||
|
||||
<DialogMcpServersSettings
|
||||
open={mcpServersDialogOpen}
|
||||
onOpenChange={(open) => (mcpServersDialogOpen = open)}
|
||||
/>
|
||||
<DialogChatSettingsImportExport
|
||||
open={importExportDialogOpen}
|
||||
onOpenChange={(open) => (importExportDialogOpen = open)}
|
||||
/>
|
||||
|
||||
<DialogConversationTitleUpdate
|
||||
bind:open={titleUpdateDialogOpen}
|
||||
currentTitle={titleUpdateCurrentTitle}
|
||||
|
|
|
|||
Loading…
Reference in New Issue