| 3518 | auto& scrollState = getOrCreateScrollState(); |
| 3519 | scrollState.setPreserveScrollPosition(preserve); |
| 3520 | // Capture the anchor immediately on enable, from the current (still valid, pre-insertion) |
| 3521 | // layout. Otherwise the anchor stays empty until the next scroll/layout pass; if that pass is |
| 3522 | // a content insertion (live message / forward page), Step 1 in updateScrollState would be |
| 3523 | // skipped (no anchor) and the viewport would jump before the anchor is first recorded. |
| 3524 | if (preserve && _calculatedFrame.height > 0.0f) { |
| 3525 | refreshPreserveAnchor( |
| 3526 | this, scrollState, scrollState.getDirectionAgnosticContentOffset().y, _calculatedFrame.height); |
| 3527 | } |
| 3528 | } |
| 3529 | |
| 3530 | template<typename F> |
| 3531 | void ViewNode::updateViewportExtension(F&& handler) { |
| 3532 | auto& scrollState = getOrCreateScrollState(); |
| 3533 | handler(scrollState); |
| 3534 | setCalculatedViewportNeedsUpdate(); |
| 3535 | } |
| 3536 | |
| 3537 | void ViewNode::setViewportExtensionTop(float viewportExtensionTop) { |
| 3538 | updateViewportExtension([&](auto& scrollState) { scrollState.setViewportExtensionTop(viewportExtensionTop); }); |
| 3539 | } |
| 3540 | |