ui: Stores architecture improvements (#26910)
* refactor: Stores barrel imports + SSR gates * refactor: Drop agenticStore wrapper exports * refactor: Drop chatStore wrapper exports * refactor: Drop modelsStore wrapper exports * refactor: Drop serverStore wrapper exports * refactor: Drop unused mcpStore wrapper exports * refactor: Drop mcpResourceStore wrapper exports * refactor: Drop conversationsStore wrapper exports + move buildConversationTree to utils * refactor: Drop settingsStore wrapper exports * refactor: Drop unused toolsStore wrapper exports * refactor: Fix lint errors from store wrapper removal * fix: Missing change * refactor: Cleanup * refactor: Context Stats store
This commit is contained in:
@@ -3,10 +3,7 @@
|
||||
import { page } from '$app/state';
|
||||
import { DialogModelNotAvailable } from '$lib/components/app';
|
||||
import { APP_NAME, URL_PARAMS } from '$lib/constants';
|
||||
import { chatStore } from '$lib/stores/chat.svelte';
|
||||
import { conversationsStore, isConversationsInitialized } from '$lib/stores/conversations.svelte';
|
||||
import { modelOptions, modelsStore } from '$lib/stores/models.svelte';
|
||||
import { isRouterMode } from '$lib/stores/server.svelte';
|
||||
import { chatStore, conversationsStore, modelsStore, serverStore } from '$lib/stores';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let qParam = $derived(page.url.searchParams.get(URL_PARAMS.QUERY));
|
||||
@@ -17,7 +14,7 @@
|
||||
// Dialog state for model not available error
|
||||
let showModelNotAvailable = $state(false);
|
||||
let requestedModelName = $state('');
|
||||
let availableModelNames = $derived(modelOptions().map((m) => m.model));
|
||||
let availableModelNames = $derived(modelsStore.models.map((m) => m.model));
|
||||
|
||||
/**
|
||||
* Clear URL params after message is sent to prevent re-sending on refresh
|
||||
@@ -45,7 +42,11 @@
|
||||
|
||||
// with ?load=true, start loading right away so the model is ready sooner;
|
||||
// not awaited, so the UI stays usable during the load
|
||||
if (loadParam === 'true' && isRouterMode() && !modelsStore.isModelLoaded(model.id)) {
|
||||
if (
|
||||
loadParam === 'true' &&
|
||||
serverStore.isRouterMode &&
|
||||
!modelsStore.isModelLoaded(model.id)
|
||||
) {
|
||||
modelsStore
|
||||
.loadModel(model.id)
|
||||
.catch((error) => console.error('Failed to load model:', error));
|
||||
@@ -75,7 +76,7 @@
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (!isConversationsInitialized()) {
|
||||
if (!conversationsStore.isInitialized) {
|
||||
await conversationsStore.initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
import { page } from '$app/state';
|
||||
import { DialogModelNotAvailable } from '$lib/components/app';
|
||||
import { APP_NAME, ROUTES, URL_PARAMS } from '$lib/constants';
|
||||
import { chatStore } from '$lib/stores/chat.svelte';
|
||||
import { activeConversation, conversationsStore } from '$lib/stores/conversations.svelte';
|
||||
import { modelOptions, modelsStore } from '$lib/stores/models.svelte';
|
||||
import { chatStore, conversationsStore, modelsStore } from '$lib/stores';
|
||||
|
||||
let chatId = $derived(page.params.id);
|
||||
let currentChatId: string | undefined = undefined;
|
||||
@@ -18,7 +16,7 @@
|
||||
// Dialog state for model not available error
|
||||
let showModelNotAvailable = $state(false);
|
||||
let requestedModelName = $state('');
|
||||
let availableModelNames = $derived(modelOptions().map((m) => m.model));
|
||||
let availableModelNames = $derived(modelsStore.models.map((m) => m.model));
|
||||
|
||||
// Track if URL params have been processed for this chat
|
||||
let urlParamsProcessed = $state(false);
|
||||
@@ -86,7 +84,7 @@
|
||||
urlParamsProcessed = false; // Reset for new chat
|
||||
|
||||
// Skip loading if this conversation is already active (e.g., just created)
|
||||
if (activeConversation()?.id === chatId) {
|
||||
if (conversationsStore.activeConversation?.id === chatId) {
|
||||
void chatStore.discoverActiveStream(chatId);
|
||||
|
||||
if ((qParam !== null || modelParam !== null) && !urlParamsProcessed) {
|
||||
@@ -136,7 +134,7 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{activeConversation()?.name || 'Chat'} - {APP_NAME}</title>
|
||||
<title>{conversationsStore.activeConversation?.name || 'Chat'} - {APP_NAME}</title>
|
||||
</svelte:head>
|
||||
|
||||
<DialogModelNotAvailable
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
import { useKeyboardShortcuts } from '$lib/hooks/use-keyboard-shortcuts.svelte';
|
||||
import { usePwa } from '$lib/hooks/use-pwa.svelte';
|
||||
import { RouterService } from '$lib/services/router.service';
|
||||
import { buildInfoStore } from '$lib/stores/build-info.svelte';
|
||||
import { chatStore } from '$lib/stores/chat.svelte';
|
||||
import { conversations } from '$lib/stores/conversations.svelte';
|
||||
import { mcpStore } from '$lib/stores/mcp.svelte';
|
||||
import { modelsStore } from '$lib/stores/models.svelte';
|
||||
import { isRouterMode, serverStore } from '$lib/stores/server.svelte';
|
||||
import { config, settingsStore } from '$lib/stores/settings.svelte';
|
||||
import { theme } from '$lib/stores/theme.svelte';
|
||||
import { isMobile } from '$lib/stores/viewport.svelte';
|
||||
import {
|
||||
buildInfoStore,
|
||||
chatStore,
|
||||
conversationsStore,
|
||||
isMobile,
|
||||
mcpStore,
|
||||
modelsStore,
|
||||
serverStore,
|
||||
settingsStore,
|
||||
theme
|
||||
} from '$lib/stores';
|
||||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { untrack } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -44,7 +46,9 @@
|
||||
}
|
||||
| undefined = $state();
|
||||
|
||||
let showBuildVersion = $derived(config()[SETTINGS_KEYS.SHOW_BUILD_VERSION] as boolean);
|
||||
let showBuildVersion = $derived(
|
||||
settingsStore.config[SETTINGS_KEYS.SHOW_BUILD_VERSION] as boolean
|
||||
);
|
||||
|
||||
// Keep the hook object intact: destructuring needRefreshByStorage reads the getter once and freezes it
|
||||
const pwa = usePwa();
|
||||
@@ -67,7 +71,7 @@
|
||||
}
|
||||
|
||||
function navigateToConversation(direction: -1 | 1) {
|
||||
const allConvs = conversations();
|
||||
const allConvs = conversationsStore.conversations;
|
||||
|
||||
if (allConvs.length === 0) return;
|
||||
|
||||
@@ -100,7 +104,7 @@
|
||||
});
|
||||
|
||||
function checkApiKey() {
|
||||
const apiKey = config().apiKey;
|
||||
const apiKey = settingsStore.config.apiKey;
|
||||
|
||||
// Without a stored key there is nothing to re-validate here; the keyless
|
||||
// 401 case is handled by validateApiKey() at navigation time, and the
|
||||
@@ -179,7 +183,7 @@
|
||||
// textContent keeps the value as text, never parsed as HTML
|
||||
function customCss(node: HTMLStyleElement) {
|
||||
$effect(() => {
|
||||
node.textContent = (config().customCss as string | undefined) ?? '';
|
||||
node.textContent = (settingsStore.config.customCss as string | undefined) ?? '';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -188,7 +192,7 @@
|
||||
let routerModelsFetched = false;
|
||||
|
||||
$effect(() => {
|
||||
const isRouter = isRouterMode();
|
||||
const isRouter = serverStore.isRouterMode;
|
||||
const modelsCount = modelsStore.models.length;
|
||||
|
||||
// Only fetch router models once when we have models loaded and in router mode
|
||||
@@ -205,7 +209,7 @@
|
||||
$effect(() => {
|
||||
if (!browser) return;
|
||||
|
||||
if (!isRouterMode()) return;
|
||||
if (!serverStore.isRouterMode) return;
|
||||
|
||||
untrack(() => {
|
||||
modelsStore.subscribeStatus();
|
||||
@@ -252,7 +256,7 @@
|
||||
<meta name="theme-color" content={pwaAssetsHead.themeColor.content} />
|
||||
{/if}
|
||||
|
||||
{#if config().customCss}
|
||||
{#if settingsStore.config.customCss}
|
||||
<style use:customCss></style>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
import { SearchInput, SidebarNavigationSearchResults } from '$lib/components/app';
|
||||
import { ROUTES } from '$lib/constants';
|
||||
import { RouterService } from '$lib/services/router.service';
|
||||
import { chatStore } from '$lib/stores/chat.svelte';
|
||||
import { conversations, conversationsStore } from '$lib/stores/conversations.svelte';
|
||||
import { isMobile } from '$lib/stores/viewport.svelte';
|
||||
import { chatStore, conversationsStore, isMobile } from '$lib/stores';
|
||||
|
||||
let searchQuery = $state('');
|
||||
let searchInputRef = $state<HTMLInputElement | null>(null);
|
||||
@@ -19,7 +17,7 @@
|
||||
|
||||
if (query.length === 0) return [];
|
||||
|
||||
return conversations().filter((c) => c.name.toLowerCase().includes(query));
|
||||
return conversationsStore.conversations.filter((c) => c.name.toLowerCase().includes(query));
|
||||
});
|
||||
|
||||
// Search page is intended for mobile; on desktop the sidebar already exposes
|
||||
@@ -35,7 +33,7 @@
|
||||
}
|
||||
|
||||
async function handleEditConversation(id: string) {
|
||||
const conversation = conversations().find((c) => c.id === id);
|
||||
const conversation = conversationsStore.conversations.find((c) => c.id === id);
|
||||
|
||||
if (!conversation) return;
|
||||
|
||||
@@ -47,7 +45,7 @@
|
||||
}
|
||||
|
||||
async function handleDeleteConversation(id: string) {
|
||||
const conversation = conversations().find((c) => c.id === id);
|
||||
const conversation = conversationsStore.conversations.find((c) => c.id === id);
|
||||
|
||||
if (!conversation) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user