Autoscroll the notebook textarea depending on config parameter
This commit is contained in:
parent
e80ba11778
commit
8a71126e5b
Binary file not shown.
|
|
@ -16,6 +16,21 @@
|
||||||
|
|
||||||
let inputContent = $state(content);
|
let inputContent = $state(content);
|
||||||
|
|
||||||
|
import {
|
||||||
|
AUTO_SCROLL_AT_BOTTOM_THRESHOLD,
|
||||||
|
AUTO_SCROLL_INTERVAL,
|
||||||
|
INITIAL_SCROLL_DELAY
|
||||||
|
} from '$lib/constants/auto-scroll';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let disableAutoScroll = $derived(Boolean(config().disableAutoScroll));
|
||||||
|
let autoScrollEnabled = $state(true);
|
||||||
|
let scrollContainer: HTMLTextAreaElement | null = $state(null);
|
||||||
|
let lastScrollTop = $state(0);
|
||||||
|
let scrollInterval: ReturnType<typeof setInterval> | undefined;
|
||||||
|
let scrollTimeout: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
let userScrolledUp = $state(false);
|
||||||
|
|
||||||
let isRouter = $derived(isRouterMode());
|
let isRouter = $derived(isRouterMode());
|
||||||
|
|
||||||
// Sync local input with store content
|
// Sync local input with store content
|
||||||
|
|
@ -29,6 +44,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleGenerate() {
|
async function handleGenerate() {
|
||||||
|
if (!disableAutoScroll) {
|
||||||
|
userScrolledUp = false;
|
||||||
|
autoScrollEnabled = true;
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
if (notebookModel == null) {
|
if (notebookModel == null) {
|
||||||
notebookModel = activeModelId;
|
notebookModel = activeModelId;
|
||||||
}
|
}
|
||||||
|
|
@ -93,6 +114,68 @@
|
||||||
notebookModel = modelName;
|
notebookModel = modelName;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleScroll() {
|
||||||
|
if (disableAutoScroll || !scrollContainer) return;
|
||||||
|
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
||||||
|
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
|
||||||
|
const isAtBottom = distanceFromBottom < AUTO_SCROLL_AT_BOTTOM_THRESHOLD;
|
||||||
|
|
||||||
|
if (scrollTop < lastScrollTop && !isAtBottom) {
|
||||||
|
userScrolledUp = true;
|
||||||
|
autoScrollEnabled = false;
|
||||||
|
} else if (isAtBottom && userScrolledUp) {
|
||||||
|
userScrolledUp = false;
|
||||||
|
autoScrollEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollTimeout) {
|
||||||
|
clearTimeout(scrollTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTimeout = setTimeout(() => {
|
||||||
|
if (isAtBottom) {
|
||||||
|
userScrolledUp = false;
|
||||||
|
autoScrollEnabled = true;
|
||||||
|
}
|
||||||
|
}, AUTO_SCROLL_INTERVAL);
|
||||||
|
|
||||||
|
lastScrollTop = scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToBottom(behavior: ScrollBehavior = 'smooth') {
|
||||||
|
if (disableAutoScroll) return;
|
||||||
|
|
||||||
|
scrollContainer?.scrollTo({
|
||||||
|
top: scrollContainer?.scrollHeight,
|
||||||
|
behavior
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (!disableAutoScroll) {
|
||||||
|
setTimeout(() => scrollToBottom('instant'), INITIAL_SCROLL_DELAY);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (disableAutoScroll) {
|
||||||
|
autoScrollEnabled = false;
|
||||||
|
if (scrollInterval) {
|
||||||
|
clearInterval(scrollInterval);
|
||||||
|
scrollInterval = undefined;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notebookStore.isGenerating && autoScrollEnabled) {
|
||||||
|
scrollInterval = setInterval(() => scrollToBottom(), AUTO_SCROLL_INTERVAL);
|
||||||
|
} else if (scrollInterval) {
|
||||||
|
clearInterval(scrollInterval);
|
||||||
|
scrollInterval = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex h-full flex-col">
|
<div class="flex h-full flex-col">
|
||||||
|
|
@ -109,6 +192,8 @@
|
||||||
|
|
||||||
<div class="flex-1 overflow-y-auto p-4 md:p-6">
|
<div class="flex-1 overflow-y-auto p-4 md:p-6">
|
||||||
<Textarea
|
<Textarea
|
||||||
|
bind:ref={scrollContainer}
|
||||||
|
onscroll={handleScroll}
|
||||||
value={inputContent}
|
value={inputContent}
|
||||||
oninput={handleInput}
|
oninput={handleInput}
|
||||||
class="h-full min-h-[500px] w-full resize-none rounded-xl border-none bg-muted p-4 text-base focus-visible:ring-0 md:p-6"
|
class="h-full min-h-[500px] w-full resize-none rounded-xl border-none bg-muted p-4 text-base focus-visible:ring-0 md:p-6"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue