Fix native chat anchoring while streaming
This commit is contained in:
@@ -608,6 +608,47 @@ describe("bottom anchor controller driver", () => {
|
|||||||
|
|
||||||
expect(harness.driver.getSnapshot().mode).toBe("sticky-bottom");
|
expect(harness.driver.getSnapshot().mode).toBe("sticky-bottom");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("keeps native sticky content changes anchored when measured height is unchanged", () => {
|
||||||
|
const harness = createDriverHarness({
|
||||||
|
transportBehavior: {
|
||||||
|
verificationDelayFrames: 2,
|
||||||
|
verificationRetryMode: "recheck",
|
||||||
|
},
|
||||||
|
measurementState: createMeasurementState({
|
||||||
|
containerKey: "native-virtualized",
|
||||||
|
viewportWidth: 390,
|
||||||
|
viewportHeight: 546,
|
||||||
|
contentHeight: 546,
|
||||||
|
offsetY: 0,
|
||||||
|
viewportMeasuredForKey: "native-virtualized",
|
||||||
|
contentMeasuredForKey: "native-virtualized",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
harness.scrollToBottom.mockImplementation(() => {
|
||||||
|
harness.context.measurementState.offsetY = 0;
|
||||||
|
harness.context.nearBottom = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
harness.driver.prepareForStickyContentChange();
|
||||||
|
|
||||||
|
expect(harness.scrollToBottom).toHaveBeenCalledTimes(1);
|
||||||
|
expect(harness.driver.getSnapshot()).toMatchObject({
|
||||||
|
mode: "sticky-bottom",
|
||||||
|
pendingVerification: {
|
||||||
|
requestId: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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", () => {
|
||||||
|
|||||||
@@ -244,29 +244,6 @@ function createBottomAnchorControllerDriver(
|
|||||||
let stickyMeasurementRevision = 0;
|
let stickyMeasurementRevision = 0;
|
||||||
let lastVerifiedStickyMeasurementRevision = 0;
|
let lastVerifiedStickyMeasurementRevision = 0;
|
||||||
|
|
||||||
const _getLogContext = (extra?: Record<string, unknown>) => {
|
|
||||||
const measurementState = input.getMeasurementState();
|
|
||||||
const distanceFromBottom = Math.max(
|
|
||||||
0,
|
|
||||||
measurementState.contentHeight - (measurementState.offsetY + measurementState.viewportHeight),
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
agentId: input.getAgentId(),
|
|
||||||
requestReason: pendingRequest?.reason ?? null,
|
|
||||||
authoritativeHistoryReady: input.getIsAuthoritativeHistoryReady(),
|
|
||||||
contentHeight: measurementState.contentHeight,
|
|
||||||
viewportHeight: measurementState.viewportHeight,
|
|
||||||
offset: measurementState.offsetY,
|
|
||||||
distanceFromBottom,
|
|
||||||
renderStrategy: input.getRenderStrategy(),
|
|
||||||
blockedReason,
|
|
||||||
mode,
|
|
||||||
containerKey: measurementState.containerKey,
|
|
||||||
transportBehavior: input.getTransportBehavior(),
|
|
||||||
...extra,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const setBlockedReason = (nextBlockedReason: BottomAnchorBlockedReason | null) => {
|
const setBlockedReason = (nextBlockedReason: BottomAnchorBlockedReason | null) => {
|
||||||
if (blockedReason === nextBlockedReason) {
|
if (blockedReason === nextBlockedReason) {
|
||||||
return;
|
return;
|
||||||
@@ -327,7 +304,6 @@ function createBottomAnchorControllerDriver(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const scheduleVerification = (attemptContext: AttemptContext, delayFramesOverride?: number) => {
|
const scheduleVerification = (attemptContext: AttemptContext, delayFramesOverride?: number) => {
|
||||||
const _scheduledMeasurementState = input.getMeasurementState();
|
|
||||||
if (verificationHandle) {
|
if (verificationHandle) {
|
||||||
input.cancelFrame(verificationHandle);
|
input.cancelFrame(verificationHandle);
|
||||||
}
|
}
|
||||||
@@ -582,6 +558,16 @@ function createBottomAnchorControllerDriver(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
markStickyMeasurementChanged();
|
markStickyMeasurementChanged();
|
||||||
|
if (!pendingRequest) {
|
||||||
|
pendingVerification = { requestId: null, retries: 0 };
|
||||||
|
if (attemptHandle) {
|
||||||
|
input.cancelFrame(attemptHandle);
|
||||||
|
attemptHandle = null;
|
||||||
|
}
|
||||||
|
runAttempt(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
evaluate(false, "content_size_change");
|
||||||
},
|
},
|
||||||
handleScrollNearBottomChange(params) {
|
handleScrollNearBottomChange(params) {
|
||||||
const { nextIsNearBottom, scrollDelta } = params;
|
const { nextIsNearBottom, scrollDelta } = params;
|
||||||
|
|||||||
Reference in New Issue
Block a user