enh: dynamic commands height

This commit is contained in:
Timothy Jaeryang Baek 2025-07-01 15:57:01 +04:00
parent 8d49288499
commit 355a3eaedb
3 changed files with 92 additions and 10 deletions

View file

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

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import Fuse from 'fuse.js'; import Fuse from 'fuse.js';
import { createEventDispatcher, onMount } from 'svelte'; import { createEventDispatcher, onDestroy, onMount } from 'svelte';
import { tick, getContext } from 'svelte'; import { tick, getContext } from 'svelte';
import { models } from '$lib/stores'; import { models } from '$lib/stores';
@ -51,18 +51,44 @@
selectedIdx = Math.min(selectedIdx + 1, filteredItems.length - 1); 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) => { const confirmSelect = async (model) => {
command = ''; command = '';
dispatch('select', model); dispatch('select', model);
}; };
onMount(async () => { onMount(async () => {
window.addEventListener('resize', adjustHeight);
adjustHeight();
await tick(); await tick();
const chatInputElement = document.getElementById('chat-input'); const chatInputElement = document.getElementById('chat-input');
await tick(); await tick();
chatInputElement?.focus(); chatInputElement?.focus();
await tick(); await tick();
}); });
onDestroy(() => {
window.removeEventListener('resize', adjustHeight);
});
</script> </script>
{#if filteredItems.length > 0} {#if filteredItems.length > 0}
@ -75,6 +101,7 @@
<div <div
class="m-1 overflow-y-auto p-1 rounded-r-lg space-y-0.5 scrollbar-hidden max-h-60" class="m-1 overflow-y-auto p-1 rounded-r-lg space-y-0.5 scrollbar-hidden max-h-60"
id="command-options-container" id="command-options-container"
bind:this={container}
> >
{#each filteredItems as model, modelIdx} {#each filteredItems as model, modelIdx}
<button <button

View file

@ -9,7 +9,7 @@
getUserTimezone, getUserTimezone,
getWeekday getWeekday
} from '$lib/utils'; } from '$lib/utils';
import { tick, getContext } from 'svelte'; import { tick, getContext, onMount, onDestroy } from 'svelte';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
@ -38,6 +38,25 @@
selectedPromptIdx = Math.min(selectedPromptIdx + 1, filteredPrompts.length - 1); 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) => { const confirmPrompt = async (command) => {
let text = command.content; let text = command.content;
@ -172,6 +191,15 @@
} }
} }
}; };
onMount(() => {
window.addEventListener('resize', adjustHeight);
adjustHeight();
});
onDestroy(() => {
window.removeEventListener('resize', adjustHeight);
});
</script> </script>
{#if filteredPrompts.length > 0} {#if filteredPrompts.length > 0}
@ -184,6 +212,7 @@
<div <div
class="m-1 overflow-y-auto p-1 space-y-0.5 scrollbar-hidden max-h-60" class="m-1 overflow-y-auto p-1 space-y-0.5 scrollbar-hidden max-h-60"
id="command-options-container" id="command-options-container"
bind:this={container}
> >
{#each filteredPrompts as prompt, promptIdx} {#each filteredPrompts as prompt, promptIdx}
<button <button