修复:动画期间内容变高时把回到底部动画重新对准新底部
- 程序化平滑滚动期间布局补偿不再直接跳过:内容变高时以新的 scrollHeight 重发平滑滚动 - 避免动画停在旧目标后 programmaticScrollRef 等不到贴底事件、跟随与补偿整段挂起 - hook 用例断言动画目标从 [1200] 变为 [1200,1500] 且仍能交还控制权 - ADR 第 3 条补一条口径,决策记录补齐本条与错误行结构两条 Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
+21
@@ -439,6 +439,27 @@ describe('点「回到底部」后的程序化滚动', () => {
|
||||
expect(counter.writes).toBe(writesBefore);
|
||||
});
|
||||
|
||||
it('动画途中内容变高:把动画目标重新对准新的底部', () => {
|
||||
const { metrics, smooth, view } = renderLongList();
|
||||
fireEvent.click(view.getByTestId('to-bottom'));
|
||||
expect(smooth.targets).toEqual([1200]);
|
||||
|
||||
// 点下去之后内容又长高了(图片撑开 / 流式正文):点击瞬间记下的 1200 已经不是底部。
|
||||
metrics.scrollHeight = 1500;
|
||||
FakeResizeObserver.triggerLayoutChange();
|
||||
|
||||
// 修正前:程序化滚动期间补偿直接跳过,动画停在旧目标 1200 上;`programmaticScrollRef` 只在
|
||||
// 「贴底」那次滚动事件里交还,于是跟随与补偿永久挂起,胶囊又已按「已贴底」隐掉。
|
||||
expect(smooth.targets).toEqual([1200, 1500]);
|
||||
|
||||
// 动画落到新底部后照常交还控制权:再往上滚仍然能出现胶囊。
|
||||
metrics.scrollTop = 1500 - 400;
|
||||
fireEvent.scroll(view.getByTestId('list'));
|
||||
metrics.scrollTop = 400;
|
||||
fireEvent.scroll(view.getByTestId('list'));
|
||||
expect(view.getByTestId('capsule').textContent).toBe('回到底部');
|
||||
});
|
||||
|
||||
it('动画落到位后交还控制权:再往上滚照样显示胶囊', () => {
|
||||
const { metrics, view, list } = renderLongList();
|
||||
fireEvent.click(view.getByTestId('to-bottom'));
|
||||
|
||||
+8
-2
@@ -151,8 +151,14 @@ export function useConversationScroll({
|
||||
const list = listRef.current;
|
||||
if (!list) return;
|
||||
|
||||
// 程序化滚动在飞:滚动位置归它所有,这里写一次就会把动画取消在半路。
|
||||
if (programmaticScrollRef.current) return;
|
||||
// 程序化滚动在飞:滚动位置归这次动画所有,直接写 `scrollTop` 会把动画取消在半路。
|
||||
// 但内容在这期间变高(流式正文、图片撑开)时,点击瞬间记下的目标已经不是底部了——动画会
|
||||
// 停在旧目标上,而 `programmaticScrollRef` 只在「贴底」那次滚动事件里交还,于是跟随与补偿
|
||||
// 一直挂着、胶囊又已按「已贴底」隐掉。重新对准新的底部,让动画继续跑到真正的底。
|
||||
if (programmaticScrollRef.current) {
|
||||
if (followLatestRef.current) scrollListToBottom(list, 'smooth');
|
||||
return;
|
||||
}
|
||||
|
||||
if (followLatestRef.current) {
|
||||
scrollListToBottom(list, 'auto');
|
||||
|
||||
Reference in New Issue
Block a user