Przeglądaj źródła

enh: dynamic commands height

Timothy Jaeryang Baek 9 miesięcy temu
rodzic
commit
355a3eaedb

+ 34 - 8
src/lib/components/chat/MessageInput/Commands/Knowledge.svelte

@@ -6,7 +6,7 @@
 	import relativeTime from 'dayjs/plugin/relativeTime';
 	dayjs.extend(relativeTime);
 
-	import { createEventDispatcher, tick, getContext, onMount } from 'svelte';
+	import { createEventDispatcher, tick, getContext, onMount, onDestroy } from 'svelte';
 	import { removeLastWordFromString, isValidHttpUrl } from '$lib/utils';
 	import { knowledge } from '$lib/stores';
 
@@ -42,6 +42,24 @@
 		selectedIdx = Math.min(selectedIdx + 1, filteredItems.length - 1);
 	};
 
+	let container;
+	let adjustHeightDebounce;
+
+	const adjustHeight = () => {
+		if (container) {
+			if (adjustHeightDebounce) {
+				clearTimeout(adjustHeightDebounce);
+			}
+
+			adjustHeightDebounce = setTimeout(() => {
+				if (!container) return;
+
+				// Ensure the container is visible before adjusting height
+				const rect = container.getBoundingClientRect();
+				container.style.maxHeight = Math.max(Math.min(240, rect.bottom - 100), 100) + 'px';
+			}, 100);
+		}
+	};
 	const confirmSelect = async (item) => {
 		dispatch('select', item);
 
@@ -75,7 +93,18 @@
 		await tick();
 	};
 
+	const decodeString = (str: string) => {
+		try {
+			return decodeURIComponent(str);
+		} catch (e) {
+			return str;
+		}
+	};
+
 	onMount(() => {
+		window.addEventListener('resize', adjustHeight);
+		adjustHeight();
+
 		let legacy_documents = $knowledge
 			.filter((item) => item?.meta?.document)
 			.map((item) => ({
@@ -155,13 +184,9 @@
 		});
 	});
 
-	const decodeString = (str: string) => {
-		try {
-			return decodeURIComponent(str);
-		} catch (e) {
-			return str;
-		}
-	};
+	onDestroy(() => {
+		window.removeEventListener('resize', adjustHeight);
+	});
 </script>
 
 {#if filteredItems.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}
@@ -174,6 +199,7 @@
 				<div
 					class="m-1 overflow-y-auto p-1 rounded-r-xl space-y-0.5 scrollbar-hidden max-h-60"
 					id="command-options-container"
+					bind:this={container}
 				>
 					{#each filteredItems as item, idx}
 						<button

+ 28 - 1
src/lib/components/chat/MessageInput/Commands/Models.svelte

@@ -1,7 +1,7 @@
 <script lang="ts">
 	import Fuse from 'fuse.js';
 
-	import { createEventDispatcher, onMount } from 'svelte';
+	import { createEventDispatcher, onDestroy, onMount } from 'svelte';
 	import { tick, getContext } from 'svelte';
 
 	import { models } from '$lib/stores';
@@ -51,18 +51,44 @@
 		selectedIdx = Math.min(selectedIdx + 1, filteredItems.length - 1);
 	};
 
+	let container;
+	let adjustHeightDebounce;
+
+	const adjustHeight = () => {
+		if (container) {
+			if (adjustHeightDebounce) {
+				clearTimeout(adjustHeightDebounce);
+			}
+
+			adjustHeightDebounce = setTimeout(() => {
+				if (!container) return;
+
+				// Ensure the container is visible before adjusting height
+				const rect = container.getBoundingClientRect();
+				container.style.maxHeight = Math.max(Math.min(240, rect.bottom - 100), 100) + 'px';
+			}, 100);
+		}
+	};
+
 	const confirmSelect = async (model) => {
 		command = '';
 		dispatch('select', model);
 	};
 
 	onMount(async () => {
+		window.addEventListener('resize', adjustHeight);
+		adjustHeight();
+
 		await tick();
 		const chatInputElement = document.getElementById('chat-input');
 		await tick();
 		chatInputElement?.focus();
 		await tick();
 	});
+
+	onDestroy(() => {
+		window.removeEventListener('resize', adjustHeight);
+	});
 </script>
 
 {#if filteredItems.length > 0}
@@ -75,6 +101,7 @@
 				<div
 					class="m-1 overflow-y-auto p-1 rounded-r-lg space-y-0.5 scrollbar-hidden max-h-60"
 					id="command-options-container"
+					bind:this={container}
 				>
 					{#each filteredItems as model, modelIdx}
 						<button

+ 30 - 1
src/lib/components/chat/MessageInput/Commands/Prompts.svelte

@@ -9,7 +9,7 @@
 		getUserTimezone,
 		getWeekday
 	} from '$lib/utils';
-	import { tick, getContext } from 'svelte';
+	import { tick, getContext, onMount, onDestroy } from 'svelte';
 	import { toast } from 'svelte-sonner';
 
 	const i18n = getContext('i18n');
@@ -38,6 +38,25 @@
 		selectedPromptIdx = Math.min(selectedPromptIdx + 1, filteredPrompts.length - 1);
 	};
 
+	let container;
+	let adjustHeightDebounce;
+
+	const adjustHeight = () => {
+		if (container) {
+			if (adjustHeightDebounce) {
+				clearTimeout(adjustHeightDebounce);
+			}
+
+			adjustHeightDebounce = setTimeout(() => {
+				if (!container) return;
+
+				// Ensure the container is visible before adjusting height
+				const rect = container.getBoundingClientRect();
+				container.style.maxHeight = Math.max(Math.min(240, rect.bottom - 100), 100) + 'px';
+			}, 100);
+		}
+	};
+
 	const confirmPrompt = async (command) => {
 		let text = command.content;
 
@@ -172,6 +191,15 @@
 			}
 		}
 	};
+
+	onMount(() => {
+		window.addEventListener('resize', adjustHeight);
+		adjustHeight();
+	});
+
+	onDestroy(() => {
+		window.removeEventListener('resize', adjustHeight);
+	});
 </script>
 
 {#if filteredPrompts.length > 0}
@@ -184,6 +212,7 @@
 				<div
 					class="m-1 overflow-y-auto p-1 space-y-0.5 scrollbar-hidden max-h-60"
 					id="command-options-container"
+					bind:this={container}
 				>
 					{#each filteredPrompts as prompt, promptIdx}
 						<button