]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/commitdiff
ui: Refactor `isMobile` as reactive value in `viewport` store (#23330)
authorAleksander Grygier <redacted>
Wed, 20 May 2026 08:52:00 +0000 (10:52 +0200)
committerGitHub <redacted>
Wed, 20 May 2026 08:52:00 +0000 (10:52 +0200)
* refactor: `isMobile` as reactive value in `viewport` store

* refactor: Use Svelte media query for the viewport store

tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionAdd/ChatFormActionsAdd.svelte
tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionModels.svelte
tools/ui/src/lib/components/ui/sidebar/context.svelte.ts
tools/ui/src/lib/hooks/is-mobile.svelte.ts [deleted file]
tools/ui/src/lib/stores/settings.svelte.ts
tools/ui/src/lib/stores/viewport.svelte.ts [new file with mode: 0644]
tools/ui/src/routes/+layout.svelte

index 54ddcf9b0a766b824c2d30826a99542ef13ffca4..6a91bf90524286b2f30d61f1fa17609789fd1c4d 100644 (file)
@@ -1,5 +1,5 @@
 <script lang="ts">
-       import { IsMobile } from '$lib/hooks/is-mobile.svelte';
+       import { isMobile } from '$lib/stores/viewport.svelte';
        import ChatFormActionAddDropdown from './ChatFormActionAddDropdown.svelte';
        import ChatFormActionAddSheet from './ChatFormActionAddSheet.svelte';
        import ChatFormActionAddButton from './ChatFormActionAddButton.svelte';
@@ -31,8 +31,6 @@
                onMcpSettingsClick,
                onSystemPromptClick
        }: Props = $props();
-
-       const isMobile = new IsMobile();
 </script>
 
 {#if isMobile.current}
index 2970206056523c8242a641cb4da3dfc0a7a61e04..07f079f5b5195b7aa456b187922eaa8db48d826b 100644 (file)
@@ -3,7 +3,7 @@
        import { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte';
        import { isRouterMode, serverError } from '$lib/stores/server.svelte';
        import { ModelsSelectorDropdown, ModelsSelectorSheet } from '$lib/components/app';
-       import { IsMobile } from '$lib/hooks/is-mobile.svelte';
+       import { isMobile } from '$lib/stores/viewport.svelte';
        import { activeMessages } from '$lib/stores/conversations.svelte';
 
        interface Props {
        let selectorModelRef: ModelsSelectorDropdown | ModelsSelectorSheet | undefined =
                $state(undefined);
 
-       let isMobile = new IsMobile();
-
        export function open() {
                selectorModelRef?.open();
        }
index 9d49ee1f0b310ae76feaf5428e3b635b7eebb2fd..2fa5cc25dcb5705a14408190aeb0ade4bc8481a2 100644 (file)
@@ -1,4 +1,4 @@
-import { IsMobile } from '$lib/hooks/is-mobile.svelte.js';
+import { isMobile } from '$lib/stores/viewport.svelte.js';
 import { getContext, setContext } from 'svelte';
 import { SIDEBAR_KEYBOARD_SHORTCUT, SIDEBAR_MIN_WIDTH } from './constants.js';
 
@@ -27,19 +27,17 @@ class SidebarState {
        sidebarWidth = $state(SIDEBAR_MIN_WIDTH);
        isResizing = $state(false);
        setOpen: SidebarStateProps['setOpen'];
-       #isMobile: IsMobile;
        state = $derived.by(() => (this.open ? 'expanded' : 'collapsed'));
 
        constructor(props: SidebarStateProps) {
                this.setOpen = props.setOpen;
-               this.#isMobile = new IsMobile();
                this.props = props;
        }
 
        // Convenience getter for checking if the sidebar is mobile
        // without this, we would need to use `sidebar.isMobile.current` everywhere
        get isMobile() {
-               return this.#isMobile.current;
+               return isMobile.current;
        }
 
        // Event handler to apply to the `<svelte:window>`
diff --git a/tools/ui/src/lib/hooks/is-mobile.svelte.ts b/tools/ui/src/lib/hooks/is-mobile.svelte.ts
deleted file mode 100644 (file)
index 6454fc5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-import { DEFAULT_MOBILE_BREAKPOINT } from '$lib/constants';
-import { MediaQuery } from 'svelte/reactivity';
-
-export class IsMobile extends MediaQuery {
-       constructor(breakpoint: number = DEFAULT_MOBILE_BREAKPOINT) {
-               super(`max-width: ${breakpoint - 1}px`);
-       }
-}
index 58eea1ee6d3f2c183916ec425fada4a9735dd185..8d3c711b82e2805af473efcb22dccfe3da3216c7 100644 (file)
@@ -41,8 +41,7 @@ import {
        SETTINGS_KEYS,
        USER_OVERRIDES_LOCALSTORAGE_KEY
 } from '$lib/constants';
-
-import { IsMobile } from '$lib/hooks/is-mobile.svelte';
+import { isMobile } from '$lib/stores/viewport.svelte';
 import { ParameterSyncService } from '$lib/services/parameter-sync.service';
 import { serverStore } from '$lib/stores/server.svelte';
 import {
@@ -132,7 +131,7 @@ class SettingsStore {
 
                        // Default sendOnEnter to false on mobile when the user has no saved preference
                        if (!(SETTINGS_KEYS.SEND_ON_ENTER in savedVal)) {
-                               if (new IsMobile().current) {
+                               if (isMobile.current) {
                                        this.config[SETTINGS_KEYS.SEND_ON_ENTER] = false;
                                }
                        }
diff --git a/tools/ui/src/lib/stores/viewport.svelte.ts b/tools/ui/src/lib/stores/viewport.svelte.ts
new file mode 100644 (file)
index 0000000..dac241a
--- /dev/null
@@ -0,0 +1,9 @@
+import { browser } from '$app/environment';
+import { DEFAULT_MOBILE_BREAKPOINT } from '$lib/constants/viewport';
+import { MediaQuery } from 'svelte/reactivity';
+
+export const viewport = $state({
+       width: browser ? window.innerWidth : 0
+});
+
+export const isMobile = new MediaQuery(`max-width: ${DEFAULT_MOBILE_BREAKPOINT - 1}px`);
index 0610b07ae7761ca494a57c8d2d95701db492b228..2f1f5249722fdf1868eee88b35c16f2d8df1a1ed 100644 (file)
        import { modelsStore } from '$lib/stores/models.svelte';
        import { mcpStore } from '$lib/stores/mcp.svelte';
        import { TOOLTIP_DELAY_DURATION } from '$lib/constants';
-       import { IsMobile } from '$lib/hooks/is-mobile.svelte';
        import { useKeyboardShortcuts } from '$lib/hooks/use-keyboard-shortcuts.svelte';
        import { useSettingsNavigation } from '$lib/hooks/use-settings-navigation.svelte';
        import { conversations } from '$lib/stores/conversations.svelte';
+       import { isMobile } from '$lib/stores/viewport.svelte';
 
        let { children } = $props();
        let alwaysShowSidebarOnDesktop = $derived(config().alwaysShowSidebarOnDesktop);
-       let isMobile = new IsMobile();
        let isDesktop = $derived(!isMobile.current);
        let sidebarOpen = $state(false);
        let mounted = $state(false);
        let innerHeight = $state<number | undefined>();
+       let innerWidth = $state(browser ? window.innerWidth : 0);
 
        let chatSidebar:
                | {
        </Sidebar.Provider>
 </Tooltip.Provider>
 
-<svelte:window onkeydown={handleKeydown} bind:innerHeight />
+<svelte:window onkeydown={handleKeydown} bind:innerHeight bind:innerWidth />