fix: smooth scroll when unlocking
This commit is contained in:
parent
b42cb3b032
commit
9ae43e89ff
@ -4,6 +4,7 @@ type ScrollContext = {
|
||||
getMessagesAreaElement?: () => HTMLElement | null;
|
||||
getThinkingContentElement?: (blockId: string) => HTMLElement | null;
|
||||
chatToggleScrollLockState?: () => boolean;
|
||||
chatSetScrollState?: (payload: { autoScrollEnabled?: boolean; userScrolling?: boolean }) => void;
|
||||
thinkingScrollLocks?: Map<string, boolean>;
|
||||
_setScrollingFlag?: (value: boolean) => void;
|
||||
autoScrollEnabled?: boolean;
|
||||
@ -11,7 +12,20 @@ type ScrollContext = {
|
||||
isOutputActive?: () => boolean;
|
||||
};
|
||||
|
||||
export function scrollToBottom(ctx: ScrollContext) {
|
||||
type ScrollOptions = {
|
||||
ignoreUserScrolling?: boolean;
|
||||
/**
|
||||
* When true, force userScrolling=false after the programmatic scroll so that
|
||||
* later自动滚动不会被“用户滚动中”状态卡住。
|
||||
*/
|
||||
resetUserScrolling?: boolean;
|
||||
/**
|
||||
* Control scroll behavior; 'smooth' 用于点击滚动锁按钮时的动画滚动。
|
||||
*/
|
||||
behavior?: ScrollBehavior;
|
||||
};
|
||||
|
||||
export function scrollToBottom(ctx: ScrollContext, options?: ScrollOptions) {
|
||||
const messagesArea = ctx.getMessagesAreaElement?.();
|
||||
if (!messagesArea) {
|
||||
return;
|
||||
@ -19,10 +33,13 @@ export function scrollToBottom(ctx: ScrollContext) {
|
||||
|
||||
const attempts = [0, 16, 60, 150, 320, 520]; // 多次尝试覆盖布局抖动/异步伸缩
|
||||
let cancelled = false;
|
||||
const useSmooth =
|
||||
options?.behavior === 'smooth' &&
|
||||
typeof (messagesArea as HTMLElement).scrollTo === 'function';
|
||||
|
||||
const perform = (idx: number) => {
|
||||
if (cancelled) return;
|
||||
if (ctx.userScrolling) {
|
||||
if (ctx.userScrolling && !options?.ignoreUserScrolling) {
|
||||
cancelled = true;
|
||||
if (typeof ctx._setScrollingFlag === 'function') {
|
||||
ctx._setScrollingFlag(false);
|
||||
@ -34,12 +51,32 @@ export function scrollToBottom(ctx: ScrollContext) {
|
||||
ctx._setScrollingFlag(true);
|
||||
}
|
||||
|
||||
messagesArea.scrollTop = messagesArea.scrollHeight;
|
||||
if (useSmooth) {
|
||||
(messagesArea as HTMLElement).scrollTo({
|
||||
top: messagesArea.scrollHeight,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
} else {
|
||||
messagesArea.scrollTop = messagesArea.scrollHeight;
|
||||
}
|
||||
|
||||
if (idx < attempts.length - 1) {
|
||||
setTimeout(() => perform(idx + 1), attempts[idx + 1] - attempts[idx]);
|
||||
} else if (typeof ctx._setScrollingFlag === 'function') {
|
||||
setTimeout(() => ctx._setScrollingFlag && ctx._setScrollingFlag(false), 40);
|
||||
if (options?.resetUserScrolling) {
|
||||
if (typeof ctx.chatSetScrollState === 'function') {
|
||||
ctx.chatSetScrollState({ userScrolling: false });
|
||||
} else if ('userScrolling' in ctx) {
|
||||
ctx.userScrolling = false;
|
||||
}
|
||||
}
|
||||
} else if (options?.resetUserScrolling) {
|
||||
if (typeof ctx.chatSetScrollState === 'function') {
|
||||
ctx.chatSetScrollState({ userScrolling: false });
|
||||
} else if ('userScrolling' in ctx) {
|
||||
ctx.userScrolling = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -58,7 +95,7 @@ export function toggleScrollLock(ctx: ScrollContext) {
|
||||
|
||||
// 没有模型输出时:允许点击,但不切换锁定,仅单次滚动到底部
|
||||
if (!active) {
|
||||
scrollToBottom(ctx);
|
||||
scrollToBottom(ctx, { ignoreUserScrolling: true, resetUserScrolling: true, behavior: 'smooth' });
|
||||
return ctx.autoScrollEnabled ?? false;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user