Fix sticky bottom anchoring on initial content growth
This commit is contained in:
@@ -560,6 +560,54 @@ describe("bottom anchor controller driver", () => {
|
|||||||
|
|
||||||
expect(harness.driver.getSnapshot().mode).toBe("detached");
|
expect(harness.driver.getSnapshot().mode).toBe("detached");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("keeps initial native content growth anchored before layout scroll events arrive", () => {
|
||||||
|
const harness = createDriverHarness({
|
||||||
|
transportBehavior: {
|
||||||
|
verificationDelayFrames: 2,
|
||||||
|
verificationRetryMode: "recheck",
|
||||||
|
},
|
||||||
|
measurementState: createMeasurementState({
|
||||||
|
containerKey: "native-virtualized",
|
||||||
|
viewportWidth: 0,
|
||||||
|
viewportHeight: 0,
|
||||||
|
contentHeight: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
viewportMeasuredForKey: null,
|
||||||
|
contentMeasuredForKey: null,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
harness.scrollToBottom.mockImplementation(() => {
|
||||||
|
harness.context.measurementState.offsetY = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
harness.context.measurementState.contentHeight = 1348;
|
||||||
|
harness.context.measurementState.contentMeasuredForKey = "native-virtualized";
|
||||||
|
harness.driver.handleContentSizeChange({
|
||||||
|
previousContentHeight: 0,
|
||||||
|
contentHeight: 1348,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(harness.scrollToBottom).toHaveBeenCalledTimes(1);
|
||||||
|
expect(harness.driver.getSnapshot()).toMatchObject({
|
||||||
|
mode: "sticky-bottom",
|
||||||
|
pendingVerification: {
|
||||||
|
requestId: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
harness.context.measurementState.viewportWidth = 390;
|
||||||
|
harness.context.measurementState.viewportHeight = 546;
|
||||||
|
harness.context.measurementState.viewportMeasuredForKey = "native-virtualized";
|
||||||
|
harness.context.measurementState.offsetY = 50;
|
||||||
|
harness.context.nearBottom = false;
|
||||||
|
harness.driver.handleScrollNearBottomChange({
|
||||||
|
nextIsNearBottom: false,
|
||||||
|
scrollDelta: 50,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(harness.driver.getSnapshot().mode).toBe("sticky-bottom");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("controller helper predicates", () => {
|
describe("controller helper predicates", () => {
|
||||||
|
|||||||
@@ -560,6 +560,12 @@ function createBottomAnchorControllerDriver(
|
|||||||
});
|
});
|
||||||
if (shouldRestick && !pendingRequest) {
|
if (shouldRestick && !pendingRequest) {
|
||||||
pendingVerification = { requestId: null, retries: 0 };
|
pendingVerification = { requestId: null, retries: 0 };
|
||||||
|
if (attemptHandle) {
|
||||||
|
input.cancelFrame(attemptHandle);
|
||||||
|
attemptHandle = null;
|
||||||
|
}
|
||||||
|
runAttempt(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (shouldRestick || pendingRequest) {
|
if (shouldRestick || pendingRequest) {
|
||||||
evaluate(false, "content_size_change");
|
evaluate(false, "content_size_change");
|
||||||
@@ -656,11 +662,7 @@ export const __private__ = {
|
|||||||
previousContentHeight: number;
|
previousContentHeight: number;
|
||||||
contentHeight: number;
|
contentHeight: number;
|
||||||
}): boolean {
|
}): boolean {
|
||||||
return (
|
return input.mode === "sticky-bottom" && input.contentHeight > input.previousContentHeight;
|
||||||
input.mode === "sticky-bottom" &&
|
|
||||||
input.previousContentHeight > 0 &&
|
|
||||||
input.contentHeight > input.previousContentHeight
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
shouldDetachFromScrollAway(input: {
|
shouldDetachFromScrollAway(input: {
|
||||||
mode: BottomAnchorMode;
|
mode: BottomAnchorMode;
|
||||||
|
|||||||
Reference in New Issue
Block a user