@legendapp/list 3.3.10 → 3.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/keyboard.d.ts +1 -1
- package/keyboard.js +2 -4
- package/keyboard.mjs +2 -4
- package/package.json +1 -1
- package/react-native.js +536 -477
- package/react-native.mjs +536 -477
- package/react-native.web.d.ts +1 -0
- package/react-native.web.js +350 -259
- package/react-native.web.mjs +350 -259
- package/react.d.ts +1 -0
- package/react.js +350 -259
- package/react.mjs +350 -259
package/react-native.mjs
CHANGED
|
@@ -993,6 +993,7 @@ function supersedeInitialScroll(ctx) {
|
|
|
993
993
|
function finishInitialScroll(ctx, options) {
|
|
994
994
|
var _a3, _b, _c;
|
|
995
995
|
const state = ctx.state;
|
|
996
|
+
const freshDataTransitionEpoch = state.freshDataTransitionEpoch;
|
|
996
997
|
if ((options == null ? void 0 : options.resolvedOffset) !== void 0) {
|
|
997
998
|
syncInitialScrollOffset(state, options.resolvedOffset);
|
|
998
999
|
} else if ((options == null ? void 0 : options.syncObservedOffset) && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
|
|
@@ -1002,9 +1003,13 @@ function finishInitialScroll(ctx, options) {
|
|
|
1002
1003
|
}
|
|
1003
1004
|
}
|
|
1004
1005
|
const complete = () => {
|
|
1005
|
-
var _a4, _b2, _c2, _d, _e;
|
|
1006
|
-
|
|
1007
|
-
|
|
1006
|
+
var _a4, _b2, _c2, _d, _e, _f;
|
|
1007
|
+
if (freshDataTransitionEpoch !== state.freshDataTransitionEpoch) {
|
|
1008
|
+
(_a4 = options == null ? void 0 : options.onFinished) == null ? void 0 : _a4.call(options);
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
const shouldReleaseDeferredPublicOnScroll = Platform.OS === "web" && ((_b2 = state.initialScrollSession) == null ? void 0 : _b2.kind) === "bootstrap";
|
|
1012
|
+
const finalScrollOffset = (_e = (_d = (_c2 = options == null ? void 0 : options.resolvedOffset) != null ? _c2 : state.scrollPending) != null ? _d : state.scroll) != null ? _e : 0;
|
|
1008
1013
|
initialScrollWatchdog.clear(state);
|
|
1009
1014
|
if ((options == null ? void 0 : options.preserveTarget) && state.initialScroll) {
|
|
1010
1015
|
state.clearPreservedInitialScrollOnNextFinish = void 0;
|
|
@@ -1033,7 +1038,7 @@ function finishInitialScroll(ctx, options) {
|
|
|
1033
1038
|
if (shouldReleaseDeferredPublicOnScroll) {
|
|
1034
1039
|
releaseDeferredPublicOnScroll(ctx, finalScrollOffset);
|
|
1035
1040
|
}
|
|
1036
|
-
(
|
|
1041
|
+
(_f = options == null ? void 0 : options.onFinished) == null ? void 0 : _f.call(options);
|
|
1037
1042
|
};
|
|
1038
1043
|
if (options == null ? void 0 : options.waitForCompletionFrame) {
|
|
1039
1044
|
requestAnimationFrame(complete);
|
|
@@ -1317,246 +1322,21 @@ function clampScrollOffset(ctx, offset, scrollTarget) {
|
|
|
1317
1322
|
return clampedOffset;
|
|
1318
1323
|
}
|
|
1319
1324
|
|
|
1320
|
-
// src/core/finishScrollTo.ts
|
|
1321
|
-
function finishScrollTo(ctx) {
|
|
1322
|
-
var _a3, _b;
|
|
1323
|
-
const state = ctx.state;
|
|
1324
|
-
if (state == null ? void 0 : state.scrollingTo) {
|
|
1325
|
-
cancelScrollCompletionChecks(state);
|
|
1326
|
-
const resolvePendingScroll = state.pendingScrollResolve;
|
|
1327
|
-
state.pendingScrollResolve = void 0;
|
|
1328
|
-
const scrollingTo = state.scrollingTo;
|
|
1329
|
-
state.scrollHistory.length = 0;
|
|
1330
|
-
state.scrollingTo = void 0;
|
|
1331
|
-
state.scrollTargetPinnedRange = void 0;
|
|
1332
|
-
if (state.pendingTotalSize !== void 0) {
|
|
1333
|
-
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1334
|
-
}
|
|
1335
|
-
if (PlatformAdjustBreaksScroll) {
|
|
1336
|
-
state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
|
|
1337
|
-
}
|
|
1338
|
-
if (scrollingTo.isInitialScroll || state.initialScroll) {
|
|
1339
|
-
const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
|
|
1340
|
-
const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_b = state.initialScroll) == null ? void 0 : _b.viewPosition) === 1;
|
|
1341
|
-
finishInitialScroll(ctx, {
|
|
1342
|
-
onFinished: () => {
|
|
1343
|
-
resolvePendingScroll == null ? void 0 : resolvePendingScroll();
|
|
1344
|
-
},
|
|
1345
|
-
preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
|
|
1346
|
-
recalculateItems: true,
|
|
1347
|
-
schedulePreservedTargetClear: shouldPreserveResizeTarget,
|
|
1348
|
-
syncObservedOffset: isOffsetSession,
|
|
1349
|
-
waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
|
|
1350
|
-
});
|
|
1351
|
-
return;
|
|
1352
|
-
}
|
|
1353
|
-
recalculateSettledScroll(ctx);
|
|
1354
|
-
resolvePendingScroll == null ? void 0 : resolvePendingScroll();
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
// src/core/checkFinishedScroll.ts
|
|
1359
|
-
var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
|
|
1360
|
-
var INITIAL_SCROLL_COMPLETION_TARGET_EPSILON = 1;
|
|
1361
|
-
var INITIAL_SCROLL_ZERO_TARGET_EPSILON = 1;
|
|
1362
|
-
var SILENT_INITIAL_SCROLL_RETRY_DELAY_MS = 16;
|
|
1363
|
-
var SILENT_INITIAL_SCROLL_TARGET_EPSILON = 1;
|
|
1364
|
-
function checkFinishedScroll(ctx, options) {
|
|
1365
|
-
const scrollingTo = ctx.state.scrollingTo;
|
|
1366
|
-
if (options == null ? void 0 : options.onlyIfAligned) {
|
|
1367
|
-
if (!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || scrollingTo.animated) {
|
|
1368
|
-
return;
|
|
1369
|
-
}
|
|
1370
|
-
if (!getResolvedScrollCompletionState(ctx, scrollingTo).isAtResolvedTarget) {
|
|
1371
|
-
return;
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
ctx.state.scheduledWork.frame(() => checkFinishedScrollFrame(ctx), "checkFinishedScrollFrame");
|
|
1375
|
-
}
|
|
1376
|
-
function hasScrollCompletionOwnership(state, options) {
|
|
1377
|
-
const { clampedTargetOffset, scrollingTo } = options;
|
|
1378
|
-
return !scrollingTo.isInitialScroll || state.hasScrolled || clampedTargetOffset <= INITIAL_SCROLL_COMPLETION_TARGET_EPSILON;
|
|
1379
|
-
}
|
|
1380
|
-
function isSilentInitialDispatch(state, scrollingTo) {
|
|
1381
|
-
return !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled;
|
|
1382
|
-
}
|
|
1383
|
-
function getInitialScrollWatchdogTargetOffset(state) {
|
|
1384
|
-
var _a3;
|
|
1385
|
-
return (_a3 = initialScrollWatchdog.get(state)) == null ? void 0 : _a3.targetOffset;
|
|
1386
|
-
}
|
|
1387
|
-
function isNativeInitialNonZeroTarget(state) {
|
|
1388
|
-
const targetOffset = getInitialScrollWatchdogTargetOffset(state);
|
|
1389
|
-
return !state.didFinishInitialScroll && initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset);
|
|
1390
|
-
}
|
|
1391
|
-
function shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) {
|
|
1392
|
-
var _a3, _b;
|
|
1393
|
-
if (!scrollingTo.isInitialScroll || scrollingTo.animated || !state.didContainersLayout) {
|
|
1394
|
-
return false;
|
|
1395
|
-
}
|
|
1396
|
-
if (((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap") {
|
|
1397
|
-
return false;
|
|
1398
|
-
}
|
|
1399
|
-
const targetOffset = (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset;
|
|
1400
|
-
if (initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled) {
|
|
1401
|
-
return false;
|
|
1402
|
-
}
|
|
1403
|
-
if (initialScrollWatchdog.isAtZeroTargetOffset(targetOffset) || Math.abs(state.scroll - targetOffset) > 1 || Math.abs(state.scrollPending - targetOffset) > 1) {
|
|
1404
|
-
return false;
|
|
1405
|
-
}
|
|
1406
|
-
return !!scrollingTo.waitForInitialScrollCompletionFrame || isNativeInitialNonZeroTarget(state);
|
|
1407
|
-
}
|
|
1408
|
-
function shouldFinishInitialZeroTargetScroll(ctx) {
|
|
1409
|
-
var _a3;
|
|
1410
|
-
const { state } = ctx;
|
|
1411
|
-
return !!((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) && state.props.data.length > 0 && getContentSize(ctx) <= state.scrollLength && state.scrollPending <= INITIAL_SCROLL_ZERO_TARGET_EPSILON;
|
|
1412
|
-
}
|
|
1413
|
-
function isEndAlignedLastItemTarget(ctx, scrollingTo) {
|
|
1414
|
-
return scrollingTo.index === ctx.state.props.data.length - 1 && scrollingTo.viewPosition === 1;
|
|
1415
|
-
}
|
|
1416
|
-
function getCurrentTargetOffset(ctx, scrollingTo) {
|
|
1417
|
-
var _a3;
|
|
1418
|
-
const index = scrollingTo.index;
|
|
1419
|
-
const shouldRecomputeEndTarget = isEndAlignedLastItemTarget(ctx, scrollingTo);
|
|
1420
|
-
const requestedTargetOffset = shouldRecomputeEndTarget && index !== void 0 ? calculateOffsetWithOffsetPosition(ctx, calculateOffsetForIndex(ctx, index), scrollingTo) : (_a3 = scrollingTo.targetOffset) != null ? _a3 : clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0), scrollingTo);
|
|
1421
|
-
return clampScrollOffset(ctx, requestedTargetOffset, scrollingTo);
|
|
1422
|
-
}
|
|
1423
|
-
function getResolvedScrollCompletionState(ctx, scrollingTo) {
|
|
1424
|
-
const { state } = ctx;
|
|
1425
|
-
const scroll = state.scrollPending;
|
|
1426
|
-
const adjust = state.scrollAdjustHandler.getAdjust();
|
|
1427
|
-
const clampedTargetOffset = getCurrentTargetOffset(ctx, scrollingTo);
|
|
1428
|
-
const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
|
|
1429
|
-
const diff1 = Math.abs(scroll - clampedTargetOffset);
|
|
1430
|
-
const adjustedTargetOffset = clampedTargetOffset + adjust;
|
|
1431
|
-
const diff2 = Math.abs(scroll - adjustedTargetOffset);
|
|
1432
|
-
const canUseAdjustedCompletion = !scrollingTo.animated || Platform.OS === "ios";
|
|
1433
|
-
return {
|
|
1434
|
-
clampedTargetOffset,
|
|
1435
|
-
isAtResolvedTarget: Math.abs(scroll - maxOffset) < 1 && (diff1 < 1 || canUseAdjustedCompletion && diff2 < 1)
|
|
1436
|
-
};
|
|
1437
|
-
}
|
|
1438
|
-
function checkFinishedScrollFrame(ctx) {
|
|
1439
|
-
const scrollingTo = ctx.state.scrollingTo;
|
|
1440
|
-
if (!scrollingTo) {
|
|
1441
|
-
return;
|
|
1442
|
-
}
|
|
1443
|
-
const { state } = ctx;
|
|
1444
|
-
const completionState = getResolvedScrollCompletionState(ctx, scrollingTo);
|
|
1445
|
-
if (completionState.isAtResolvedTarget && hasScrollCompletionOwnership(state, {
|
|
1446
|
-
clampedTargetOffset: completionState.clampedTargetOffset,
|
|
1447
|
-
scrollingTo
|
|
1448
|
-
})) {
|
|
1449
|
-
finishScrollTo(ctx);
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
function scrollToFallbackOffset(ctx, offset) {
|
|
1453
|
-
var _a3;
|
|
1454
|
-
(_a3 = ctx.state.refScroller.current) == null ? void 0 : _a3.scrollTo({
|
|
1455
|
-
animated: false,
|
|
1456
|
-
x: ctx.state.props.horizontal ? offset : 0,
|
|
1457
|
-
y: ctx.state.props.horizontal ? 0 : offset
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
function checkFinishedScrollFallback(ctx) {
|
|
1461
|
-
const state = ctx.state;
|
|
1462
|
-
if (state.scheduledWork.has("checkFinishedScrollFallback")) {
|
|
1463
|
-
return;
|
|
1464
|
-
}
|
|
1465
|
-
const scrollingTo = state.scrollingTo;
|
|
1466
|
-
const shouldFinishInitialZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
|
|
1467
|
-
const silentInitialDispatch = isSilentInitialDispatch(state, scrollingTo);
|
|
1468
|
-
const canFinishInitialWithoutNativeProgress = scrollingTo !== void 0 ? shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) : false;
|
|
1469
|
-
const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && !shouldFinishInitialZeroTarget && !canFinishInitialWithoutNativeProgress || !state.didContainersLayout;
|
|
1470
|
-
const initialDelay = shouldFinishInitialZeroTarget || canFinishInitialWithoutNativeProgress ? 0 : silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : slowTimeout ? 500 : 100;
|
|
1471
|
-
let numChecks = 0;
|
|
1472
|
-
const scheduleFallbackCheck = (delay) => {
|
|
1473
|
-
state.scheduledWork.timeout(checkHasScrolled, delay, "checkFinishedScrollFallback");
|
|
1474
|
-
};
|
|
1475
|
-
const checkHasScrolled = () => {
|
|
1476
|
-
var _a3, _b, _c, _d;
|
|
1477
|
-
const isStillScrollingTo = state.scrollingTo;
|
|
1478
|
-
if (isStillScrollingTo) {
|
|
1479
|
-
numChecks++;
|
|
1480
|
-
const isNativeInitialPending = isNativeInitialNonZeroTarget(state) && !state.hasScrolled;
|
|
1481
|
-
const maxChecks = silentInitialDispatch ? 5 : isNativeInitialPending ? INITIAL_SCROLL_MAX_FALLBACK_CHECKS : 5;
|
|
1482
|
-
const shouldFinishZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
|
|
1483
|
-
const canFinishInitialScrollWithoutNativeProgress = shouldFinishInitialScrollWithoutNativeProgress(
|
|
1484
|
-
state,
|
|
1485
|
-
isStillScrollingTo
|
|
1486
|
-
);
|
|
1487
|
-
const completionState = getResolvedScrollCompletionState(ctx, isStillScrollingTo);
|
|
1488
|
-
const canFinishAfterSilentNativeDispatch = Platform.OS === "android" && silentInitialDispatch && completionState.isAtResolvedTarget && numChecks >= 1;
|
|
1489
|
-
const shouldRetrySilentInitialNativeScroll = Platform.OS === "android" && canFinishAfterSilentNativeDispatch && !initialScrollCompletion.didRetrySilentInitialScroll(state);
|
|
1490
|
-
const shouldFinishAfterObservedScroll = state.hasScrolled && (!isStillScrollingTo.isInitialScroll || completionState.isAtResolvedTarget);
|
|
1491
|
-
const shouldRetryUnalignedInitialScroll = isStillScrollingTo.isInitialScroll && !completionState.isAtResolvedTarget && numChecks <= maxChecks;
|
|
1492
|
-
const shouldRetryUnalignedEndScroll = Platform.OS === "ios" && !isStillScrollingTo.isInitialScroll && isEndAlignedLastItemTarget(ctx, isStillScrollingTo) && !completionState.isAtResolvedTarget && numChecks <= maxChecks;
|
|
1493
|
-
if (shouldRetrySilentInitialNativeScroll) {
|
|
1494
|
-
const targetOffset = (_b = (_a3 = getInitialScrollWatchdogTargetOffset(state)) != null ? _a3 : isStillScrollingTo.targetOffset) != null ? _b : 0;
|
|
1495
|
-
const jiggleOffset = targetOffset >= SILENT_INITIAL_SCROLL_TARGET_EPSILON ? targetOffset - SILENT_INITIAL_SCROLL_TARGET_EPSILON : targetOffset + SILENT_INITIAL_SCROLL_TARGET_EPSILON;
|
|
1496
|
-
initialScrollCompletion.markSilentInitialScrollRetry(state);
|
|
1497
|
-
scrollToFallbackOffset(ctx, jiggleOffset);
|
|
1498
|
-
state.scheduledWork.frame(
|
|
1499
|
-
() => scrollToFallbackOffset(ctx, targetOffset),
|
|
1500
|
-
"checkFinishedScrollRetryFrame"
|
|
1501
|
-
);
|
|
1502
|
-
scheduleFallbackCheck(SILENT_INITIAL_SCROLL_RETRY_DELAY_MS);
|
|
1503
|
-
} else if (shouldRetryUnalignedEndScroll) {
|
|
1504
|
-
scrollToFallbackOffset(ctx, completionState.clampedTargetOffset);
|
|
1505
|
-
scheduleFallbackCheck(100);
|
|
1506
|
-
} else if (shouldFinishZeroTarget || shouldFinishAfterObservedScroll || canFinishInitialScrollWithoutNativeProgress || canFinishAfterSilentNativeDispatch || numChecks > maxChecks) {
|
|
1507
|
-
finishScrollTo(ctx);
|
|
1508
|
-
} else if ((isNativeInitialPending || shouldRetryUnalignedInitialScroll) && numChecks <= maxChecks) {
|
|
1509
|
-
const targetOffset = (_d = (_c = getInitialScrollWatchdogTargetOffset(state)) != null ? _c : isStillScrollingTo.targetOffset) != null ? _d : state.scrollPending;
|
|
1510
|
-
scrollToFallbackOffset(ctx, targetOffset);
|
|
1511
|
-
scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
|
|
1512
|
-
} else {
|
|
1513
|
-
scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
};
|
|
1517
|
-
scheduleFallbackCheck(initialDelay);
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
// src/core/doScrollTo.native.ts
|
|
1521
|
-
function doScrollTo(ctx, params) {
|
|
1522
|
-
const state = ctx.state;
|
|
1523
|
-
const { animated, horizontal, isInitialScroll, offset } = params;
|
|
1524
|
-
const isAnimated = !!animated;
|
|
1525
|
-
const { refScroller } = state;
|
|
1526
|
-
const scroller = refScroller.current;
|
|
1527
|
-
if (!scroller) {
|
|
1528
|
-
return;
|
|
1529
|
-
}
|
|
1530
|
-
const isHorizontal = !!horizontal;
|
|
1531
|
-
const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
|
|
1532
|
-
const nativeOffset = toNativeHorizontalOffset(state, offset, contentSize);
|
|
1533
|
-
scroller.scrollTo({
|
|
1534
|
-
animated: isAnimated,
|
|
1535
|
-
x: isHorizontal ? nativeOffset : 0,
|
|
1536
|
-
y: isHorizontal ? 0 : offset
|
|
1537
|
-
});
|
|
1538
|
-
if (isInitialScroll) {
|
|
1539
|
-
initialScrollCompletion.markInitialScrollNativeDispatch(state);
|
|
1540
|
-
}
|
|
1541
|
-
if (isAnimated && Math.abs(state.scroll - offset) <= 1) {
|
|
1542
|
-
checkFinishedScroll(ctx);
|
|
1543
|
-
}
|
|
1544
|
-
if (!isAnimated) {
|
|
1545
|
-
state.scroll = offset;
|
|
1546
|
-
checkFinishedScrollFallback(ctx);
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
1325
|
// src/core/scrollRequestTracker.ts
|
|
1551
1326
|
function getScrollRequestTracker(ctx) {
|
|
1552
1327
|
if (!ctx.scrollRequestTracker) {
|
|
1553
1328
|
let currentToken = 0;
|
|
1554
|
-
|
|
1329
|
+
let waitingToken;
|
|
1330
|
+
const start = (resolve, isInternal = false) => {
|
|
1555
1331
|
const state = ctx.state;
|
|
1332
|
+
if (!isInternal && (state.maintainingScrollAtEnd || state.pendingMaintainScrollAtEnd)) {
|
|
1333
|
+
finishMaintainScrollAtEnd(ctx);
|
|
1334
|
+
}
|
|
1556
1335
|
state.scheduledWork.cancel("imperativeScrollReady");
|
|
1557
1336
|
const token = ++currentToken;
|
|
1558
1337
|
settlePendingImperativeScroll(state);
|
|
1559
1338
|
state.pendingScrollResolve = resolve;
|
|
1339
|
+
waitingToken = token;
|
|
1560
1340
|
return token;
|
|
1561
1341
|
};
|
|
1562
1342
|
const runNow = (token, resolve, run) => {
|
|
@@ -1564,6 +1344,7 @@ function getScrollRequestTracker(ctx) {
|
|
|
1564
1344
|
if (token !== currentToken) {
|
|
1565
1345
|
return;
|
|
1566
1346
|
}
|
|
1347
|
+
waitingToken = void 0;
|
|
1567
1348
|
const didStartScroll = run();
|
|
1568
1349
|
if (!didStartScroll || !state.scrollingTo) {
|
|
1569
1350
|
if (state.pendingScrollResolve === resolve) {
|
|
@@ -1574,6 +1355,7 @@ function getScrollRequestTracker(ctx) {
|
|
|
1574
1355
|
};
|
|
1575
1356
|
ctx.scrollRequestTracker = {
|
|
1576
1357
|
isCurrent: (token) => token === currentToken,
|
|
1358
|
+
isWaitingToRun: () => waitingToken === currentToken && !!ctx.state.pendingScrollResolve,
|
|
1577
1359
|
runNow,
|
|
1578
1360
|
runNowIfIdle: (run) => {
|
|
1579
1361
|
const state = ctx.state;
|
|
@@ -1581,7 +1363,7 @@ function getScrollRequestTracker(ctx) {
|
|
|
1581
1363
|
return Promise.resolve();
|
|
1582
1364
|
}
|
|
1583
1365
|
return new Promise((resolve) => {
|
|
1584
|
-
const token = start(resolve);
|
|
1366
|
+
const token = start(resolve, true);
|
|
1585
1367
|
runNow(token, resolve, run);
|
|
1586
1368
|
});
|
|
1587
1369
|
},
|
|
@@ -1645,96 +1427,15 @@ function requestAdjust(ctx, positionDiff, source) {
|
|
|
1645
1427
|
}
|
|
1646
1428
|
}
|
|
1647
1429
|
|
|
1648
|
-
// src/core/
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
set$(ctx, "alignItemsAtEndPadding", nextPadding);
|
|
1658
|
-
state.scrollForNextCalculateItemsInView = void 0;
|
|
1659
|
-
(_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { forceFullItemPositions: true });
|
|
1660
|
-
const nextScroll = clampScrollOffset(ctx, state.scroll + nextPadding - currentPadding);
|
|
1661
|
-
requestAdjust(ctx, nextScroll - state.scroll);
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
function doMaintainScrollAtEnd(ctx) {
|
|
1665
|
-
const state = ctx.state;
|
|
1666
|
-
const {
|
|
1667
|
-
didContainersLayout,
|
|
1668
|
-
didFinishInitialScroll,
|
|
1669
|
-
pendingNativeMVCPAdjust,
|
|
1670
|
-
props: { maintainScrollAtEnd }
|
|
1671
|
-
} = state;
|
|
1672
|
-
const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
|
|
1673
|
-
const isReplayingPendingMaintain = !!state.pendingMaintainScrollAtEnd;
|
|
1674
|
-
const shouldMaintainScrollAtEnd = !!((isWithinMaintainScrollAtEndThreshold || isReplayingPendingMaintain) && maintainScrollAtEnd && didFinishInitialScroll);
|
|
1675
|
-
if (shouldMaintainScrollAtEnd && !didContainersLayout) {
|
|
1676
|
-
state.pendingMaintainScrollAtEnd = true;
|
|
1677
|
-
return false;
|
|
1678
|
-
}
|
|
1679
|
-
if (pendingNativeMVCPAdjust) {
|
|
1680
|
-
state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
|
|
1681
|
-
return false;
|
|
1682
|
-
}
|
|
1683
|
-
if (shouldMaintainScrollAtEnd && didContainersLayout) {
|
|
1684
|
-
state.pendingMaintainScrollAtEnd = false;
|
|
1685
|
-
const contentSize = getContentSize(ctx);
|
|
1686
|
-
if (contentSize < state.scrollLength) {
|
|
1687
|
-
state.scroll = 0;
|
|
1688
|
-
}
|
|
1689
|
-
if (!state.maintainingScrollAtEnd) {
|
|
1690
|
-
const pendingState = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
|
|
1691
|
-
const activeState = maintainScrollAtEnd.animated ? "animated" : "instant";
|
|
1692
|
-
const scrollAtRequest = state.scroll;
|
|
1693
|
-
state.maintainingScrollAtEnd = pendingState;
|
|
1694
|
-
requestAnimationFrame(() => {
|
|
1695
|
-
if (state.maintainingScrollAtEnd !== pendingState) {
|
|
1696
|
-
return;
|
|
1697
|
-
}
|
|
1698
|
-
const isStillWithinThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
|
|
1699
|
-
const didScrollSinceRequest = state.scroll !== scrollAtRequest;
|
|
1700
|
-
if (isReplayingPendingMaintain || isStillWithinThreshold || !didScrollSinceRequest) {
|
|
1701
|
-
state.maintainingScrollAtEnd = activeState;
|
|
1702
|
-
const scrollPromise = getScrollRequestTracker(ctx).runNowIfIdle(
|
|
1703
|
-
() => ctx.scrollToEnd({ animated: maintainScrollAtEnd.animated })
|
|
1704
|
-
);
|
|
1705
|
-
void scrollPromise.then(() => {
|
|
1706
|
-
if (state.maintainingScrollAtEnd !== activeState) {
|
|
1707
|
-
return;
|
|
1708
|
-
}
|
|
1709
|
-
if (state.pendingMaintainScrollAtEnd) {
|
|
1710
|
-
state.maintainingScrollAtEnd = void 0;
|
|
1711
|
-
doMaintainScrollAtEnd(ctx);
|
|
1712
|
-
} else {
|
|
1713
|
-
finishMaintainScrollAtEnd(ctx);
|
|
1714
|
-
}
|
|
1715
|
-
});
|
|
1716
|
-
} else if (state.maintainingScrollAtEnd === pendingState) {
|
|
1717
|
-
finishMaintainScrollAtEnd(ctx);
|
|
1718
|
-
}
|
|
1719
|
-
});
|
|
1720
|
-
} else {
|
|
1721
|
-
state.pendingMaintainScrollAtEnd = true;
|
|
1722
|
-
}
|
|
1723
|
-
return true;
|
|
1724
|
-
}
|
|
1725
|
-
finishMaintainScrollAtEnd(ctx);
|
|
1726
|
-
return false;
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
// src/core/mvcp.ts
|
|
1730
|
-
var MVCP_POSITION_EPSILON = 0.1;
|
|
1731
|
-
var MVCP_ANCHOR_LOCK_TTL_MS = 300;
|
|
1732
|
-
var MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE = 2;
|
|
1733
|
-
var NATIVE_END_CLAMP_EPSILON = 1;
|
|
1734
|
-
function resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) {
|
|
1735
|
-
if (!enableMVCPAnchorLock) {
|
|
1736
|
-
state.mvcpAnchorLock = void 0;
|
|
1737
|
-
return void 0;
|
|
1430
|
+
// src/core/mvcp.ts
|
|
1431
|
+
var MVCP_POSITION_EPSILON = 0.1;
|
|
1432
|
+
var MVCP_ANCHOR_LOCK_TTL_MS = 300;
|
|
1433
|
+
var MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE = 2;
|
|
1434
|
+
var NATIVE_END_CLAMP_EPSILON = 1;
|
|
1435
|
+
function resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) {
|
|
1436
|
+
if (!enableMVCPAnchorLock) {
|
|
1437
|
+
state.mvcpAnchorLock = void 0;
|
|
1438
|
+
return void 0;
|
|
1738
1439
|
}
|
|
1739
1440
|
const lock = state.mvcpAnchorLock;
|
|
1740
1441
|
if (!lock) {
|
|
@@ -2024,144 +1725,494 @@ function prepareMVCP(ctx, dataChanged, adjustmentSource) {
|
|
|
2024
1725
|
};
|
|
2025
1726
|
}
|
|
2026
1727
|
}
|
|
2027
|
-
|
|
2028
|
-
// src/platform/flushSync.native.ts
|
|
2029
|
-
var flushSync = (fn) => {
|
|
2030
|
-
fn();
|
|
2031
|
-
};
|
|
2032
|
-
|
|
2033
|
-
// src/utils/getScrollVelocity.ts
|
|
2034
|
-
var MAX_SCROLL_VELOCITY_WINDOW_MS = 1e3;
|
|
2035
|
-
var SCROLL_VELOCITY_HALF_LIFE_MS = 200;
|
|
2036
|
-
var getScrollVelocity = (state) => {
|
|
2037
|
-
const { scrollHistory } = state;
|
|
2038
|
-
const newestIndex = scrollHistory.length - 1;
|
|
2039
|
-
if (newestIndex < 1) {
|
|
2040
|
-
return 0;
|
|
2041
|
-
}
|
|
2042
|
-
const newest = scrollHistory[newestIndex];
|
|
2043
|
-
if (Date.now() - newest.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
2044
|
-
return 0;
|
|
1728
|
+
|
|
1729
|
+
// src/platform/flushSync.native.ts
|
|
1730
|
+
var flushSync = (fn) => {
|
|
1731
|
+
fn();
|
|
1732
|
+
};
|
|
1733
|
+
|
|
1734
|
+
// src/utils/getScrollVelocity.ts
|
|
1735
|
+
var MAX_SCROLL_VELOCITY_WINDOW_MS = 1e3;
|
|
1736
|
+
var SCROLL_VELOCITY_HALF_LIFE_MS = 200;
|
|
1737
|
+
var getScrollVelocity = (state) => {
|
|
1738
|
+
const { scrollHistory } = state;
|
|
1739
|
+
const newestIndex = scrollHistory.length - 1;
|
|
1740
|
+
if (newestIndex < 1) {
|
|
1741
|
+
return 0;
|
|
1742
|
+
}
|
|
1743
|
+
const newest = scrollHistory[newestIndex];
|
|
1744
|
+
if (Date.now() - newest.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
1745
|
+
return 0;
|
|
1746
|
+
}
|
|
1747
|
+
let direction = 0;
|
|
1748
|
+
let weightedVelocity = 0;
|
|
1749
|
+
let totalWeight = 0;
|
|
1750
|
+
for (let i = newestIndex; i > 0; i--) {
|
|
1751
|
+
const current = scrollHistory[i];
|
|
1752
|
+
const previous = scrollHistory[i - 1];
|
|
1753
|
+
const scrollDiff = current.scroll - previous.scroll;
|
|
1754
|
+
const timeDiff = current.time - previous.time;
|
|
1755
|
+
const deltaSign = Math.sign(scrollDiff);
|
|
1756
|
+
if (deltaSign !== 0) {
|
|
1757
|
+
if (direction === 0) {
|
|
1758
|
+
direction = deltaSign;
|
|
1759
|
+
} else if (deltaSign !== direction) {
|
|
1760
|
+
break;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
if (newest.time - previous.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
1764
|
+
break;
|
|
1765
|
+
}
|
|
1766
|
+
if (scrollDiff === 0 || timeDiff <= 0) {
|
|
1767
|
+
continue;
|
|
1768
|
+
}
|
|
1769
|
+
const age = newest.time - current.time;
|
|
1770
|
+
const weight = Math.exp(-age / SCROLL_VELOCITY_HALF_LIFE_MS);
|
|
1771
|
+
weightedVelocity += scrollDiff / timeDiff * weight;
|
|
1772
|
+
totalWeight += weight;
|
|
1773
|
+
}
|
|
1774
|
+
return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
|
|
1775
|
+
};
|
|
1776
|
+
|
|
1777
|
+
// src/utils/isInMVCPActiveMode.native.ts
|
|
1778
|
+
function isInMVCPActiveMode(state) {
|
|
1779
|
+
return state.dataChangeNeedsScrollUpdate;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
// src/core/updateScroll.ts
|
|
1783
|
+
function updateScroll(ctx, newScroll, forceUpdate, options) {
|
|
1784
|
+
var _a3;
|
|
1785
|
+
const state = ctx.state;
|
|
1786
|
+
const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
|
|
1787
|
+
const prevScroll = state.scroll;
|
|
1788
|
+
if ((options == null ? void 0 : options.markHasScrolled) !== false) {
|
|
1789
|
+
state.hasScrolled = true;
|
|
1790
|
+
}
|
|
1791
|
+
const currentTime = Date.now();
|
|
1792
|
+
state.lastBatchingAction = currentTime;
|
|
1793
|
+
const adjust = scrollAdjustHandler.getAdjust();
|
|
1794
|
+
const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
|
|
1795
|
+
if (adjustChanged) {
|
|
1796
|
+
scrollHistory.length = 0;
|
|
1797
|
+
}
|
|
1798
|
+
state.lastScrollAdjustForHistory = adjust;
|
|
1799
|
+
if (scrollingTo === void 0 && !(scrollHistory.length === 0 && newScroll === state.scroll)) {
|
|
1800
|
+
if (!adjustChanged) {
|
|
1801
|
+
scrollHistory.push({ scroll: newScroll, time: currentTime });
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
if (scrollHistory.length > 5) {
|
|
1805
|
+
scrollHistory.shift();
|
|
1806
|
+
}
|
|
1807
|
+
if (ignoreScrollFromMVCP && !scrollingTo) {
|
|
1808
|
+
const { lt, gt } = ignoreScrollFromMVCP;
|
|
1809
|
+
if (lt && newScroll < lt || gt && newScroll > gt) {
|
|
1810
|
+
state.ignoreScrollFromMVCPIgnored = true;
|
|
1811
|
+
return;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
state.scrollPrev = prevScroll;
|
|
1815
|
+
state.scrollPrevTime = state.scrollTime;
|
|
1816
|
+
state.scroll = newScroll;
|
|
1817
|
+
state.scrollTime = currentTime;
|
|
1818
|
+
const scrollDelta = Math.abs(newScroll - prevScroll);
|
|
1819
|
+
const isUserScrollEvent = !!(options == null ? void 0 : options.fromNativeScrollEvent) && scrollDelta > 0.1 && !adjustChanged && scrollingTo === void 0 && !state.pendingNativeMVCPAdjust;
|
|
1820
|
+
const didCancelMaintainScrollAtEnd = isUserScrollEvent && newScroll < prevScroll && !!(state.maintainingScrollAtEnd || state.pendingMaintainScrollAtEnd);
|
|
1821
|
+
if (didCancelMaintainScrollAtEnd) {
|
|
1822
|
+
finishMaintainScrollAtEnd(ctx);
|
|
1823
|
+
}
|
|
1824
|
+
const allowedEdge = isUserScrollEvent ? beginReachedEdgeUserScroll(ctx, newScroll - prevScroll) : void 0;
|
|
1825
|
+
const didResolvePendingNativeMVCPAdjust = resolvePendingNativeMVCPAdjust(ctx, newScroll);
|
|
1826
|
+
const scrollLength = state.scrollLength;
|
|
1827
|
+
const isLargeUserScrollJump = scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust;
|
|
1828
|
+
const scrollVelocity = getScrollVelocity(state);
|
|
1829
|
+
updateAdaptiveRender(ctx, scrollVelocity, { forceLight: isLargeUserScrollJump });
|
|
1830
|
+
const lastCalculated = state.scrollLastCalculate;
|
|
1831
|
+
const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
|
|
1832
|
+
const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || didCancelMaintainScrollAtEnd || allowedEdge !== void 0 || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
|
|
1833
|
+
if (shouldUpdate) {
|
|
1834
|
+
state.scrollLastCalculate = state.scroll;
|
|
1835
|
+
state.ignoreScrollFromMVCPIgnored = false;
|
|
1836
|
+
state.lastScrollDelta = scrollDelta;
|
|
1837
|
+
const runCalculateItems = () => {
|
|
1838
|
+
var _a4;
|
|
1839
|
+
const calculateItemsParams = {
|
|
1840
|
+
doMVCP: scrollingTo !== void 0,
|
|
1841
|
+
scrollVelocity
|
|
1842
|
+
};
|
|
1843
|
+
if (isLargeUserScrollJump) {
|
|
1844
|
+
calculateItemsParams.drawDistanceMode = "visible-first";
|
|
1845
|
+
}
|
|
1846
|
+
(_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, calculateItemsParams);
|
|
1847
|
+
checkThresholds(ctx, allowedEdge);
|
|
1848
|
+
};
|
|
1849
|
+
if (isLargeUserScrollJump) {
|
|
1850
|
+
state.mvcpAnchorLock = void 0;
|
|
1851
|
+
state.pendingNativeMVCPAdjust = void 0;
|
|
1852
|
+
state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
|
|
1853
|
+
state.scheduledWork.cancel("mvcpRecalculate");
|
|
1854
|
+
flushSync(runCalculateItems);
|
|
1855
|
+
scheduleFullDrawDistancePrewarm(ctx);
|
|
1856
|
+
} else {
|
|
1857
|
+
runCalculateItems();
|
|
1858
|
+
}
|
|
1859
|
+
const shouldMaintainScrollAtEndAfterPendingSettle = !!state.pendingMaintainScrollAtEnd || !!((_a3 = state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onDataChange);
|
|
1860
|
+
if (didResolvePendingNativeMVCPAdjust && shouldMaintainScrollAtEndAfterPendingSettle) {
|
|
1861
|
+
state.pendingMaintainScrollAtEnd = false;
|
|
1862
|
+
doMaintainScrollAtEnd(ctx);
|
|
1863
|
+
}
|
|
1864
|
+
state.dataChangeNeedsScrollUpdate = false;
|
|
1865
|
+
state.lastScrollDelta = 0;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
// src/core/doMaintainScrollAtEnd.ts
|
|
1870
|
+
function interruptMaintainScrollAtEnd(ctx) {
|
|
1871
|
+
var _a3;
|
|
1872
|
+
const { state } = ctx;
|
|
1873
|
+
const maintaining = state.maintainingScrollAtEnd;
|
|
1874
|
+
const cancelActiveScroll = !!(maintaining === "animated" || maintaining === "instant" || maintaining && ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isScrollToEnd));
|
|
1875
|
+
if (cancelActiveScroll) {
|
|
1876
|
+
cancelImperativeScroll(state);
|
|
1877
|
+
}
|
|
1878
|
+
if (maintaining || state.pendingMaintainScrollAtEnd) {
|
|
1879
|
+
finishMaintainScrollAtEnd(ctx);
|
|
1880
|
+
}
|
|
1881
|
+
return cancelActiveScroll;
|
|
1882
|
+
}
|
|
1883
|
+
function finishMaintainScrollAtEnd(ctx) {
|
|
1884
|
+
var _a3;
|
|
1885
|
+
const { state } = ctx;
|
|
1886
|
+
const currentPadding = peek$(ctx, "alignItemsAtEndPadding") || 0;
|
|
1887
|
+
const nextPadding = getAlignItemsAtEndPadding(ctx);
|
|
1888
|
+
state.maintainingScrollAtEnd = void 0;
|
|
1889
|
+
state.pendingMaintainScrollAtEnd = false;
|
|
1890
|
+
if (currentPadding !== nextPadding) {
|
|
1891
|
+
set$(ctx, "alignItemsAtEndPadding", nextPadding);
|
|
1892
|
+
state.scrollForNextCalculateItemsInView = void 0;
|
|
1893
|
+
(_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { forceFullItemPositions: true });
|
|
1894
|
+
const nextScroll = clampScrollOffset(ctx, state.scroll + nextPadding - currentPadding);
|
|
1895
|
+
requestAdjust(ctx, nextScroll - state.scroll);
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
function doMaintainScrollAtEnd(ctx) {
|
|
1899
|
+
var _a3, _b, _c, _d, _e;
|
|
1900
|
+
const state = ctx.state;
|
|
1901
|
+
const {
|
|
1902
|
+
didContainersLayout,
|
|
1903
|
+
didFinishInitialScroll,
|
|
1904
|
+
pendingNativeMVCPAdjust,
|
|
1905
|
+
props: { maintainScrollAtEnd }
|
|
1906
|
+
} = state;
|
|
1907
|
+
const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
|
|
1908
|
+
const isReplayingPendingMaintain = !!state.pendingMaintainScrollAtEnd;
|
|
1909
|
+
const shouldMaintainScrollAtEnd = !!(!((_a3 = ctx.scrollRequestTracker) == null ? void 0 : _a3.isWaitingToRun()) && (!state.scrollingTo || state.scrollingTo.isScrollToEnd) && (isWithinMaintainScrollAtEndThreshold || isReplayingPendingMaintain || ((_b = state.scrollingTo) == null ? void 0 : _b.isScrollToEnd)) && maintainScrollAtEnd && didFinishInitialScroll);
|
|
1910
|
+
if (shouldMaintainScrollAtEnd && !state.scrollingTo) {
|
|
1911
|
+
const scroller = state.refScroller.current;
|
|
1912
|
+
const nativeMax = (_c = scroller == null ? void 0 : scroller.getMaxScrollOffset) == null ? void 0 : _c.call(scroller);
|
|
1913
|
+
const observed = (_d = scroller == null ? void 0 : scroller.getCurrentScrollOffset) == null ? void 0 : _d.call(scroller);
|
|
1914
|
+
if (nativeMax !== void 0 && observed !== void 0 && nativeMax < state.scroll - 1 && Math.abs(observed - nativeMax) <= 1) {
|
|
1915
|
+
state.pendingMaintainScrollAtEnd = true;
|
|
1916
|
+
state.scrollPending = observed;
|
|
1917
|
+
updateScroll(ctx, observed, true, { markHasScrolled: false });
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
if (shouldMaintainScrollAtEnd && !didContainersLayout) {
|
|
1921
|
+
state.pendingMaintainScrollAtEnd = true;
|
|
1922
|
+
return false;
|
|
1923
|
+
}
|
|
1924
|
+
if (pendingNativeMVCPAdjust) {
|
|
1925
|
+
state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
|
|
1926
|
+
return false;
|
|
1927
|
+
}
|
|
1928
|
+
if (shouldMaintainScrollAtEnd && (state.scrollingTo || state.pendingScrollResolve)) {
|
|
1929
|
+
state.pendingMaintainScrollAtEnd = true;
|
|
1930
|
+
(_e = state.maintainingScrollAtEnd) != null ? _e : state.maintainingScrollAtEnd = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
|
|
1931
|
+
return false;
|
|
1932
|
+
}
|
|
1933
|
+
if (shouldMaintainScrollAtEnd && didContainersLayout) {
|
|
1934
|
+
state.pendingMaintainScrollAtEnd = false;
|
|
1935
|
+
const contentSize = getContentSize(ctx);
|
|
1936
|
+
if (contentSize < state.scrollLength) {
|
|
1937
|
+
state.scroll = 0;
|
|
1938
|
+
}
|
|
1939
|
+
if (!state.maintainingScrollAtEnd) {
|
|
1940
|
+
const pendingState = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
|
|
1941
|
+
const activeState = maintainScrollAtEnd.animated ? "animated" : "instant";
|
|
1942
|
+
const scrollAtRequest = state.scroll;
|
|
1943
|
+
state.maintainingScrollAtEnd = pendingState;
|
|
1944
|
+
requestAnimationFrame(() => {
|
|
1945
|
+
if (state.maintainingScrollAtEnd !== pendingState) {
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
const isStillWithinThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
|
|
1949
|
+
const didScrollSinceRequest = state.scroll !== scrollAtRequest;
|
|
1950
|
+
if (isReplayingPendingMaintain || isStillWithinThreshold || !didScrollSinceRequest) {
|
|
1951
|
+
if (state.scrollingTo || state.pendingScrollResolve) {
|
|
1952
|
+
state.pendingMaintainScrollAtEnd = true;
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
state.maintainingScrollAtEnd = activeState;
|
|
1956
|
+
const scrollPromise = getScrollRequestTracker(ctx).runNowIfIdle(
|
|
1957
|
+
() => ctx.scrollToEnd({ animated: maintainScrollAtEnd.animated })
|
|
1958
|
+
);
|
|
1959
|
+
void scrollPromise.then(() => {
|
|
1960
|
+
if (state.maintainingScrollAtEnd !== activeState) {
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
if (state.pendingMaintainScrollAtEnd) {
|
|
1964
|
+
state.maintainingScrollAtEnd = void 0;
|
|
1965
|
+
doMaintainScrollAtEnd(ctx);
|
|
1966
|
+
} else {
|
|
1967
|
+
finishMaintainScrollAtEnd(ctx);
|
|
1968
|
+
}
|
|
1969
|
+
});
|
|
1970
|
+
} else if (state.maintainingScrollAtEnd === pendingState) {
|
|
1971
|
+
finishMaintainScrollAtEnd(ctx);
|
|
1972
|
+
}
|
|
1973
|
+
});
|
|
1974
|
+
} else {
|
|
1975
|
+
state.pendingMaintainScrollAtEnd = true;
|
|
1976
|
+
}
|
|
1977
|
+
return true;
|
|
1978
|
+
}
|
|
1979
|
+
finishMaintainScrollAtEnd(ctx);
|
|
1980
|
+
return false;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
// src/core/finishScrollTo.ts
|
|
1984
|
+
function finishScrollTo(ctx) {
|
|
1985
|
+
var _a3, _b, _c;
|
|
1986
|
+
const state = ctx.state;
|
|
1987
|
+
if (state == null ? void 0 : state.scrollingTo) {
|
|
1988
|
+
cancelScrollCompletionChecks(state);
|
|
1989
|
+
const resolvePendingScroll = ((_a3 = ctx.scrollRequestTracker) == null ? void 0 : _a3.isWaitingToRun()) ? void 0 : state.pendingScrollResolve;
|
|
1990
|
+
if (resolvePendingScroll) {
|
|
1991
|
+
state.pendingScrollResolve = void 0;
|
|
1992
|
+
}
|
|
1993
|
+
const scrollingTo = state.scrollingTo;
|
|
1994
|
+
state.scrollHistory.length = 0;
|
|
1995
|
+
state.scrollingTo = void 0;
|
|
1996
|
+
state.scrollTargetPinnedRange = void 0;
|
|
1997
|
+
if (state.pendingTotalSize !== void 0) {
|
|
1998
|
+
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1999
|
+
}
|
|
2000
|
+
if (PlatformAdjustBreaksScroll) {
|
|
2001
|
+
state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
|
|
2002
|
+
}
|
|
2003
|
+
if (scrollingTo.isInitialScroll || state.initialScroll) {
|
|
2004
|
+
const isOffsetSession = ((_b = state.initialScrollSession) == null ? void 0 : _b.kind) === "offset";
|
|
2005
|
+
const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_c = state.initialScroll) == null ? void 0 : _c.viewPosition) === 1;
|
|
2006
|
+
finishInitialScroll(ctx, {
|
|
2007
|
+
onFinished: () => {
|
|
2008
|
+
resolvePendingScroll == null ? void 0 : resolvePendingScroll();
|
|
2009
|
+
},
|
|
2010
|
+
preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
|
|
2011
|
+
recalculateItems: true,
|
|
2012
|
+
schedulePreservedTargetClear: shouldPreserveResizeTarget,
|
|
2013
|
+
syncObservedOffset: isOffsetSession,
|
|
2014
|
+
waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
|
|
2015
|
+
});
|
|
2016
|
+
return;
|
|
2017
|
+
}
|
|
2018
|
+
recalculateSettledScroll(ctx);
|
|
2019
|
+
resolvePendingScroll == null ? void 0 : resolvePendingScroll();
|
|
2020
|
+
if (state.pendingMaintainScrollAtEnd) {
|
|
2021
|
+
state.maintainingScrollAtEnd = void 0;
|
|
2022
|
+
doMaintainScrollAtEnd(ctx);
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
// src/core/checkFinishedScroll.ts
|
|
2028
|
+
var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
|
|
2029
|
+
var INITIAL_SCROLL_COMPLETION_TARGET_EPSILON = 1;
|
|
2030
|
+
var INITIAL_SCROLL_ZERO_TARGET_EPSILON = 1;
|
|
2031
|
+
var SILENT_INITIAL_SCROLL_RETRY_DELAY_MS = 16;
|
|
2032
|
+
var SILENT_INITIAL_SCROLL_TARGET_EPSILON = 1;
|
|
2033
|
+
function checkFinishedScroll(ctx, options) {
|
|
2034
|
+
const scrollingTo = ctx.state.scrollingTo;
|
|
2035
|
+
if (options == null ? void 0 : options.onlyIfAligned) {
|
|
2036
|
+
if (!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || scrollingTo.animated) {
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
if (!getResolvedScrollCompletionState(ctx, scrollingTo).isAtResolvedTarget) {
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
ctx.state.scheduledWork.frame(() => checkFinishedScrollFrame(ctx), "checkFinishedScrollFrame");
|
|
2044
|
+
}
|
|
2045
|
+
function hasScrollCompletionOwnership(state, options) {
|
|
2046
|
+
const { clampedTargetOffset, scrollingTo } = options;
|
|
2047
|
+
return !scrollingTo.isInitialScroll || state.hasScrolled || clampedTargetOffset <= INITIAL_SCROLL_COMPLETION_TARGET_EPSILON;
|
|
2048
|
+
}
|
|
2049
|
+
function isSilentInitialDispatch(state, scrollingTo) {
|
|
2050
|
+
return !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled;
|
|
2051
|
+
}
|
|
2052
|
+
function getInitialScrollWatchdogTargetOffset(state) {
|
|
2053
|
+
var _a3;
|
|
2054
|
+
return (_a3 = initialScrollWatchdog.get(state)) == null ? void 0 : _a3.targetOffset;
|
|
2055
|
+
}
|
|
2056
|
+
function isNativeInitialNonZeroTarget(state) {
|
|
2057
|
+
const targetOffset = getInitialScrollWatchdogTargetOffset(state);
|
|
2058
|
+
return !state.didFinishInitialScroll && initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset);
|
|
2059
|
+
}
|
|
2060
|
+
function shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) {
|
|
2061
|
+
var _a3, _b;
|
|
2062
|
+
if (!scrollingTo.isInitialScroll || scrollingTo.animated || !state.didContainersLayout) {
|
|
2063
|
+
return false;
|
|
2064
|
+
}
|
|
2065
|
+
if (((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap") {
|
|
2066
|
+
return false;
|
|
2067
|
+
}
|
|
2068
|
+
const targetOffset = (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset;
|
|
2069
|
+
if (initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled) {
|
|
2070
|
+
return false;
|
|
2071
|
+
}
|
|
2072
|
+
if (initialScrollWatchdog.isAtZeroTargetOffset(targetOffset) || Math.abs(state.scroll - targetOffset) > 1 || Math.abs(state.scrollPending - targetOffset) > 1) {
|
|
2073
|
+
return false;
|
|
2074
|
+
}
|
|
2075
|
+
return !!scrollingTo.waitForInitialScrollCompletionFrame || isNativeInitialNonZeroTarget(state);
|
|
2076
|
+
}
|
|
2077
|
+
function shouldFinishInitialZeroTargetScroll(ctx) {
|
|
2078
|
+
var _a3;
|
|
2079
|
+
const { state } = ctx;
|
|
2080
|
+
return !!((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) && state.props.data.length > 0 && getContentSize(ctx) <= state.scrollLength && state.scrollPending <= INITIAL_SCROLL_ZERO_TARGET_EPSILON;
|
|
2081
|
+
}
|
|
2082
|
+
function isEndAlignedLastItemTarget(ctx, scrollingTo) {
|
|
2083
|
+
return scrollingTo.index === ctx.state.props.data.length - 1 && scrollingTo.viewPosition === 1;
|
|
2084
|
+
}
|
|
2085
|
+
function getCurrentTargetOffset(ctx, scrollingTo) {
|
|
2086
|
+
var _a3;
|
|
2087
|
+
const index = scrollingTo.index;
|
|
2088
|
+
const shouldRecomputeEndTarget = isEndAlignedLastItemTarget(ctx, scrollingTo);
|
|
2089
|
+
const requestedTargetOffset = shouldRecomputeEndTarget && index !== void 0 ? calculateOffsetWithOffsetPosition(ctx, calculateOffsetForIndex(ctx, index), scrollingTo) : (_a3 = scrollingTo.targetOffset) != null ? _a3 : clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0), scrollingTo);
|
|
2090
|
+
return clampScrollOffset(ctx, requestedTargetOffset, scrollingTo);
|
|
2091
|
+
}
|
|
2092
|
+
function getResolvedScrollCompletionState(ctx, scrollingTo) {
|
|
2093
|
+
const { state } = ctx;
|
|
2094
|
+
const scroll = state.scrollPending;
|
|
2095
|
+
const adjust = state.scrollAdjustHandler.getAdjust();
|
|
2096
|
+
const clampedTargetOffset = getCurrentTargetOffset(ctx, scrollingTo);
|
|
2097
|
+
const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
|
|
2098
|
+
const diff1 = Math.abs(scroll - clampedTargetOffset);
|
|
2099
|
+
const adjustedTargetOffset = clampedTargetOffset + adjust;
|
|
2100
|
+
const diff2 = Math.abs(scroll - adjustedTargetOffset);
|
|
2101
|
+
const canUseAdjustedCompletion = !scrollingTo.animated || Platform.OS === "ios";
|
|
2102
|
+
return {
|
|
2103
|
+
clampedTargetOffset,
|
|
2104
|
+
isAtResolvedTarget: Math.abs(scroll - maxOffset) < 1 && (diff1 < 1 || canUseAdjustedCompletion && diff2 < 1)
|
|
2105
|
+
};
|
|
2106
|
+
}
|
|
2107
|
+
function checkFinishedScrollFrame(ctx) {
|
|
2108
|
+
const scrollingTo = ctx.state.scrollingTo;
|
|
2109
|
+
if (!scrollingTo) {
|
|
2110
|
+
return;
|
|
2045
2111
|
}
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
const timeDiff = current.time - previous.time;
|
|
2054
|
-
const deltaSign = Math.sign(scrollDiff);
|
|
2055
|
-
if (deltaSign !== 0) {
|
|
2056
|
-
if (direction === 0) {
|
|
2057
|
-
direction = deltaSign;
|
|
2058
|
-
} else if (deltaSign !== direction) {
|
|
2059
|
-
break;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
if (newest.time - previous.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
2063
|
-
break;
|
|
2064
|
-
}
|
|
2065
|
-
if (scrollDiff === 0 || timeDiff <= 0) {
|
|
2066
|
-
continue;
|
|
2067
|
-
}
|
|
2068
|
-
const age = newest.time - current.time;
|
|
2069
|
-
const weight = Math.exp(-age / SCROLL_VELOCITY_HALF_LIFE_MS);
|
|
2070
|
-
weightedVelocity += scrollDiff / timeDiff * weight;
|
|
2071
|
-
totalWeight += weight;
|
|
2112
|
+
const { state } = ctx;
|
|
2113
|
+
const completionState = getResolvedScrollCompletionState(ctx, scrollingTo);
|
|
2114
|
+
if (completionState.isAtResolvedTarget && hasScrollCompletionOwnership(state, {
|
|
2115
|
+
clampedTargetOffset: completionState.clampedTargetOffset,
|
|
2116
|
+
scrollingTo
|
|
2117
|
+
})) {
|
|
2118
|
+
finishScrollTo(ctx);
|
|
2072
2119
|
}
|
|
2073
|
-
return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
|
|
2074
|
-
};
|
|
2075
|
-
|
|
2076
|
-
// src/utils/isInMVCPActiveMode.native.ts
|
|
2077
|
-
function isInMVCPActiveMode(state) {
|
|
2078
|
-
return state.dataChangeNeedsScrollUpdate;
|
|
2079
2120
|
}
|
|
2080
|
-
|
|
2081
|
-
// src/core/updateScroll.ts
|
|
2082
|
-
function updateScroll(ctx, newScroll, forceUpdate, options) {
|
|
2121
|
+
function scrollToFallbackOffset(ctx, offset) {
|
|
2083
2122
|
var _a3;
|
|
2123
|
+
(_a3 = ctx.state.refScroller.current) == null ? void 0 : _a3.scrollTo({
|
|
2124
|
+
animated: false,
|
|
2125
|
+
x: ctx.state.props.horizontal ? offset : 0,
|
|
2126
|
+
y: ctx.state.props.horizontal ? 0 : offset
|
|
2127
|
+
});
|
|
2128
|
+
}
|
|
2129
|
+
function checkFinishedScrollFallback(ctx) {
|
|
2084
2130
|
const state = ctx.state;
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
if ((options == null ? void 0 : options.markHasScrolled) !== false) {
|
|
2088
|
-
state.hasScrolled = true;
|
|
2089
|
-
}
|
|
2090
|
-
const currentTime = Date.now();
|
|
2091
|
-
state.lastBatchingAction = currentTime;
|
|
2092
|
-
const adjust = scrollAdjustHandler.getAdjust();
|
|
2093
|
-
const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
|
|
2094
|
-
if (adjustChanged) {
|
|
2095
|
-
scrollHistory.length = 0;
|
|
2131
|
+
if (state.scheduledWork.has("checkFinishedScrollFallback")) {
|
|
2132
|
+
return;
|
|
2096
2133
|
}
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2134
|
+
const scrollingTo = state.scrollingTo;
|
|
2135
|
+
const shouldFinishInitialZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
|
|
2136
|
+
const silentInitialDispatch = isSilentInitialDispatch(state, scrollingTo);
|
|
2137
|
+
const canFinishInitialWithoutNativeProgress = scrollingTo !== void 0 ? shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) : false;
|
|
2138
|
+
const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && !shouldFinishInitialZeroTarget && !canFinishInitialWithoutNativeProgress || !state.didContainersLayout;
|
|
2139
|
+
const initialDelay = shouldFinishInitialZeroTarget || canFinishInitialWithoutNativeProgress ? 0 : silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : slowTimeout ? 500 : 100;
|
|
2140
|
+
let numChecks = 0;
|
|
2141
|
+
const scheduleFallbackCheck = (delay) => {
|
|
2142
|
+
state.scheduledWork.timeout(checkHasScrolled, delay, "checkFinishedScrollFallback");
|
|
2143
|
+
};
|
|
2144
|
+
const checkHasScrolled = () => {
|
|
2145
|
+
var _a3, _b, _c, _d;
|
|
2146
|
+
const isStillScrollingTo = state.scrollingTo;
|
|
2147
|
+
if (isStillScrollingTo) {
|
|
2148
|
+
numChecks++;
|
|
2149
|
+
const isNativeInitialPending = isNativeInitialNonZeroTarget(state) && !state.hasScrolled;
|
|
2150
|
+
const maxChecks = silentInitialDispatch ? 5 : isNativeInitialPending ? INITIAL_SCROLL_MAX_FALLBACK_CHECKS : 5;
|
|
2151
|
+
const shouldFinishZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
|
|
2152
|
+
const canFinishInitialScrollWithoutNativeProgress = shouldFinishInitialScrollWithoutNativeProgress(
|
|
2153
|
+
state,
|
|
2154
|
+
isStillScrollingTo
|
|
2155
|
+
);
|
|
2156
|
+
const completionState = getResolvedScrollCompletionState(ctx, isStillScrollingTo);
|
|
2157
|
+
const canFinishAfterSilentNativeDispatch = Platform.OS === "android" && silentInitialDispatch && completionState.isAtResolvedTarget && numChecks >= 1;
|
|
2158
|
+
const shouldRetrySilentInitialNativeScroll = Platform.OS === "android" && canFinishAfterSilentNativeDispatch && !initialScrollCompletion.didRetrySilentInitialScroll(state);
|
|
2159
|
+
const shouldFinishAfterObservedScroll = state.hasScrolled && (!isStillScrollingTo.isInitialScroll || completionState.isAtResolvedTarget);
|
|
2160
|
+
const shouldRetryUnalignedInitialScroll = isStillScrollingTo.isInitialScroll && !completionState.isAtResolvedTarget && numChecks <= maxChecks;
|
|
2161
|
+
const shouldRetryUnalignedEndScroll = Platform.OS !== "web" && !isStillScrollingTo.isInitialScroll && isEndAlignedLastItemTarget(ctx, isStillScrollingTo) && !completionState.isAtResolvedTarget && numChecks <= maxChecks;
|
|
2162
|
+
if (shouldRetrySilentInitialNativeScroll) {
|
|
2163
|
+
const targetOffset = (_b = (_a3 = getInitialScrollWatchdogTargetOffset(state)) != null ? _a3 : isStillScrollingTo.targetOffset) != null ? _b : 0;
|
|
2164
|
+
const jiggleOffset = targetOffset >= SILENT_INITIAL_SCROLL_TARGET_EPSILON ? targetOffset - SILENT_INITIAL_SCROLL_TARGET_EPSILON : targetOffset + SILENT_INITIAL_SCROLL_TARGET_EPSILON;
|
|
2165
|
+
initialScrollCompletion.markSilentInitialScrollRetry(state);
|
|
2166
|
+
scrollToFallbackOffset(ctx, jiggleOffset);
|
|
2167
|
+
state.scheduledWork.frame(
|
|
2168
|
+
() => scrollToFallbackOffset(ctx, targetOffset),
|
|
2169
|
+
"checkFinishedScrollRetryFrame"
|
|
2170
|
+
);
|
|
2171
|
+
scheduleFallbackCheck(SILENT_INITIAL_SCROLL_RETRY_DELAY_MS);
|
|
2172
|
+
} else if (shouldRetryUnalignedEndScroll) {
|
|
2173
|
+
scrollToFallbackOffset(ctx, completionState.clampedTargetOffset);
|
|
2174
|
+
scheduleFallbackCheck(100);
|
|
2175
|
+
} else if (shouldFinishZeroTarget || shouldFinishAfterObservedScroll || canFinishInitialScrollWithoutNativeProgress || canFinishAfterSilentNativeDispatch || numChecks > maxChecks) {
|
|
2176
|
+
finishScrollTo(ctx);
|
|
2177
|
+
} else if ((isNativeInitialPending || shouldRetryUnalignedInitialScroll) && numChecks <= maxChecks) {
|
|
2178
|
+
const targetOffset = (_d = (_c = getInitialScrollWatchdogTargetOffset(state)) != null ? _c : isStillScrollingTo.targetOffset) != null ? _d : state.scrollPending;
|
|
2179
|
+
scrollToFallbackOffset(ctx, targetOffset);
|
|
2180
|
+
scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
|
|
2181
|
+
} else {
|
|
2182
|
+
scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
|
|
2183
|
+
}
|
|
2101
2184
|
}
|
|
2185
|
+
};
|
|
2186
|
+
scheduleFallbackCheck(initialDelay);
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
// src/core/doScrollTo.native.ts
|
|
2190
|
+
function doScrollTo(ctx, params) {
|
|
2191
|
+
const state = ctx.state;
|
|
2192
|
+
const { animated, horizontal, isInitialScroll, offset } = params;
|
|
2193
|
+
const isAnimated = !!animated;
|
|
2194
|
+
const { refScroller } = state;
|
|
2195
|
+
const scroller = refScroller.current;
|
|
2196
|
+
if (!scroller) {
|
|
2197
|
+
return;
|
|
2102
2198
|
}
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2199
|
+
const isHorizontal = !!horizontal;
|
|
2200
|
+
const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
|
|
2201
|
+
const nativeOffset = toNativeHorizontalOffset(state, offset, contentSize);
|
|
2202
|
+
scroller.scrollTo({
|
|
2203
|
+
animated: isAnimated,
|
|
2204
|
+
x: isHorizontal ? nativeOffset : 0,
|
|
2205
|
+
y: isHorizontal ? 0 : offset
|
|
2206
|
+
});
|
|
2207
|
+
if (isInitialScroll) {
|
|
2208
|
+
initialScrollCompletion.markInitialScrollNativeDispatch(state);
|
|
2112
2209
|
}
|
|
2113
|
-
state.
|
|
2114
|
-
|
|
2115
|
-
state.scroll = newScroll;
|
|
2116
|
-
state.scrollTime = currentTime;
|
|
2117
|
-
const scrollDelta = Math.abs(newScroll - prevScroll);
|
|
2118
|
-
const isUserScrollEvent = !!(options == null ? void 0 : options.fromNativeScrollEvent) && scrollDelta > 0.1 && !adjustChanged && scrollingTo === void 0 && !state.pendingNativeMVCPAdjust;
|
|
2119
|
-
const didCancelMaintainScrollAtEnd = isUserScrollEvent && newScroll < prevScroll && !!(state.maintainingScrollAtEnd || state.pendingMaintainScrollAtEnd);
|
|
2120
|
-
if (didCancelMaintainScrollAtEnd) {
|
|
2121
|
-
finishMaintainScrollAtEnd(ctx);
|
|
2210
|
+
if (isAnimated && Math.abs(state.scroll - offset) <= 1) {
|
|
2211
|
+
checkFinishedScroll(ctx);
|
|
2122
2212
|
}
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
const isLargeUserScrollJump = scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust;
|
|
2127
|
-
const scrollVelocity = getScrollVelocity(state);
|
|
2128
|
-
updateAdaptiveRender(ctx, scrollVelocity, { forceLight: isLargeUserScrollJump });
|
|
2129
|
-
const lastCalculated = state.scrollLastCalculate;
|
|
2130
|
-
const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
|
|
2131
|
-
const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || didCancelMaintainScrollAtEnd || allowedEdge !== void 0 || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
|
|
2132
|
-
if (shouldUpdate) {
|
|
2133
|
-
state.scrollLastCalculate = state.scroll;
|
|
2134
|
-
state.ignoreScrollFromMVCPIgnored = false;
|
|
2135
|
-
state.lastScrollDelta = scrollDelta;
|
|
2136
|
-
const runCalculateItems = () => {
|
|
2137
|
-
var _a4;
|
|
2138
|
-
const calculateItemsParams = {
|
|
2139
|
-
doMVCP: scrollingTo !== void 0,
|
|
2140
|
-
scrollVelocity
|
|
2141
|
-
};
|
|
2142
|
-
if (isLargeUserScrollJump) {
|
|
2143
|
-
calculateItemsParams.drawDistanceMode = "visible-first";
|
|
2144
|
-
}
|
|
2145
|
-
(_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, calculateItemsParams);
|
|
2146
|
-
checkThresholds(ctx, allowedEdge);
|
|
2147
|
-
};
|
|
2148
|
-
if (isLargeUserScrollJump) {
|
|
2149
|
-
state.mvcpAnchorLock = void 0;
|
|
2150
|
-
state.pendingNativeMVCPAdjust = void 0;
|
|
2151
|
-
state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
|
|
2152
|
-
state.scheduledWork.cancel("mvcpRecalculate");
|
|
2153
|
-
flushSync(runCalculateItems);
|
|
2154
|
-
scheduleFullDrawDistancePrewarm(ctx);
|
|
2155
|
-
} else {
|
|
2156
|
-
runCalculateItems();
|
|
2157
|
-
}
|
|
2158
|
-
const shouldMaintainScrollAtEndAfterPendingSettle = !!state.pendingMaintainScrollAtEnd || !!((_a3 = state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onDataChange);
|
|
2159
|
-
if (didResolvePendingNativeMVCPAdjust && shouldMaintainScrollAtEndAfterPendingSettle) {
|
|
2160
|
-
state.pendingMaintainScrollAtEnd = false;
|
|
2161
|
-
doMaintainScrollAtEnd(ctx);
|
|
2162
|
-
}
|
|
2163
|
-
state.dataChangeNeedsScrollUpdate = false;
|
|
2164
|
-
state.lastScrollDelta = 0;
|
|
2213
|
+
if (!isAnimated) {
|
|
2214
|
+
state.scroll = offset;
|
|
2215
|
+
checkFinishedScrollFallback(ctx);
|
|
2165
2216
|
}
|
|
2166
2217
|
}
|
|
2167
2218
|
|
|
@@ -3170,6 +3221,11 @@ function handleInitialScrollDataChange(ctx, options) {
|
|
|
3170
3221
|
const state = ctx.state;
|
|
3171
3222
|
const previousInitialScrollDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
|
|
3172
3223
|
const shouldUseLatestInitialScroll = dataLength > 0 && (!state.hasHadNonEmptyData || didStartFreshData);
|
|
3224
|
+
if (didStartFreshData) {
|
|
3225
|
+
cancelImperativeScroll(state);
|
|
3226
|
+
state.maintainingScrollAtEnd = void 0;
|
|
3227
|
+
state.pendingMaintainScrollAtEnd = false;
|
|
3228
|
+
}
|
|
3173
3229
|
if (dataLength > 0) {
|
|
3174
3230
|
state.hasHadNonEmptyData = true;
|
|
3175
3231
|
}
|
|
@@ -4714,6 +4770,7 @@ function maybeUpdateAnchoredEndSpace(ctx) {
|
|
|
4714
4770
|
const nextAnchorIndex = anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex;
|
|
4715
4771
|
let nextAnchorKey;
|
|
4716
4772
|
let isReady = true;
|
|
4773
|
+
let canUpdateSize = true;
|
|
4717
4774
|
let nextSize = 0;
|
|
4718
4775
|
if (anchoredEndSpace) {
|
|
4719
4776
|
const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
|
|
@@ -4735,25 +4792,30 @@ function maybeUpdateAnchoredEndSpace(ctx) {
|
|
|
4735
4792
|
contentBelowAnchor = Math.max(0, contentBelowAnchor - ctx.scrollAxisGap);
|
|
4736
4793
|
contentBelowAnchor += (ctx.values.get("footerSize") || 0) + getStylePaddingEnd(state.props);
|
|
4737
4794
|
isReady = !hasUnknownTailSize;
|
|
4738
|
-
|
|
4795
|
+
const knownSizeBound = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
|
|
4796
|
+
nextSize = hasUnknownTailSize ? Math.min(previousSize || 0, knownSizeBound) : knownSizeBound;
|
|
4739
4797
|
} else if (anchorIndex >= 0) {
|
|
4740
4798
|
isReady = false;
|
|
4799
|
+
canUpdateSize = false;
|
|
4741
4800
|
}
|
|
4742
4801
|
}
|
|
4743
4802
|
const didSizeChange = previousSize !== nextSize && (previousSize !== void 0 || anchoredEndSpace !== void 0);
|
|
4744
4803
|
const didEffectiveSizeChange = (previousSize || 0) !== nextSize;
|
|
4804
|
+
const canApplySizeChange = canUpdateSize && (isReady || previousSize !== void 0);
|
|
4745
4805
|
const didReadyAnchorChange = previousReadyAnchorIndex !== nextAnchorIndex || previousReadyAnchorKey !== nextAnchorKey;
|
|
4746
|
-
|
|
4806
|
+
const didBecomeReady = isReady && state.anchoredEndSpacePendingReady;
|
|
4807
|
+
state.anchoredEndSpacePendingReady = !isReady;
|
|
4808
|
+
if (canApplySizeChange && didSizeChange) {
|
|
4809
|
+
set$(ctx, "anchoredEndSpaceSize", nextSize);
|
|
4810
|
+
(_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
|
|
4811
|
+
}
|
|
4812
|
+
if (canApplySizeChange && didEffectiveSizeChange) {
|
|
4813
|
+
updateContentMetricsState(ctx);
|
|
4814
|
+
updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
|
|
4815
|
+
}
|
|
4816
|
+
if (isReady && (didSizeChange || didReadyAnchorChange || didBecomeReady)) {
|
|
4747
4817
|
state.anchoredEndSpaceReadyAnchorIndex = nextAnchorIndex;
|
|
4748
4818
|
state.anchoredEndSpaceReadyAnchorKey = nextAnchorKey;
|
|
4749
|
-
if (didSizeChange) {
|
|
4750
|
-
set$(ctx, "anchoredEndSpaceSize", nextSize);
|
|
4751
|
-
(_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
|
|
4752
|
-
}
|
|
4753
|
-
if (didEffectiveSizeChange) {
|
|
4754
|
-
updateContentMetricsState(ctx);
|
|
4755
|
-
updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
|
|
4756
|
-
}
|
|
4757
4819
|
(_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
|
|
4758
4820
|
}
|
|
4759
4821
|
return nextSize;
|
|
@@ -6657,6 +6719,9 @@ function scrollToEnd(ctx, options) {
|
|
|
6657
6719
|
viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
|
|
6658
6720
|
viewPosition: 1
|
|
6659
6721
|
});
|
|
6722
|
+
if (state.scrollingTo) {
|
|
6723
|
+
state.scrollingTo.isScrollToEnd = true;
|
|
6724
|
+
}
|
|
6660
6725
|
return true;
|
|
6661
6726
|
}
|
|
6662
6727
|
|
|
@@ -7390,6 +7455,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
7390
7455
|
endReachedSnapshot: void 0,
|
|
7391
7456
|
firstFullyOnScreenIndex: -1,
|
|
7392
7457
|
freshDataTransitionEpoch: 0,
|
|
7458
|
+
handledDataChangeEpoch: 0,
|
|
7459
|
+
handledFreshDataTransitionEpoch: 0,
|
|
7393
7460
|
hasHadNonEmptyData: dataProp.length > 0,
|
|
7394
7461
|
idCache: [],
|
|
7395
7462
|
idsInView: [],
|
|
@@ -7449,8 +7516,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
7449
7516
|
refState.current = ctx.state;
|
|
7450
7517
|
}
|
|
7451
7518
|
const state = refState.current;
|
|
7452
|
-
const handledDataChangeEpochRef = useRef(state.dataChangeEpoch);
|
|
7453
|
-
const handledFreshDataTransitionEpochRef = useRef(state.freshDataTransitionEpoch);
|
|
7454
7519
|
const isFirstLocal = state.isFirst;
|
|
7455
7520
|
const previousAdaptiveRender = state.props.adaptiveRender;
|
|
7456
7521
|
const previousHideItemsUntilMeasured = state.props.hideItemsUntilMeasured;
|
|
@@ -7605,10 +7670,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
7605
7670
|
useDevChecks(props);
|
|
7606
7671
|
}
|
|
7607
7672
|
useLayoutEffect(() => {
|
|
7608
|
-
const didDataChange =
|
|
7609
|
-
const didStartFreshData =
|
|
7610
|
-
|
|
7611
|
-
|
|
7673
|
+
const didDataChange = state.handledDataChangeEpoch !== dataChangeEpoch;
|
|
7674
|
+
const didStartFreshData = state.handledFreshDataTransitionEpoch !== freshDataTransitionEpoch;
|
|
7675
|
+
state.handledDataChangeEpoch = dataChangeEpoch;
|
|
7676
|
+
state.handledFreshDataTransitionEpoch = freshDataTransitionEpoch;
|
|
7612
7677
|
if (didStartFreshData) {
|
|
7613
7678
|
resetInitialRenderState(ctx, {
|
|
7614
7679
|
resetInitialScroll: !!initialScrollProp,
|
|
@@ -7812,13 +7877,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
7812
7877
|
onScroll: (event) => onScroll(ctx, event),
|
|
7813
7878
|
onScrollBeginDrag: (event) => {
|
|
7814
7879
|
var _a4, _b2;
|
|
7815
|
-
|
|
7816
|
-
if (maintainingScrollAtEnd === "animated" || maintainingScrollAtEnd === "instant") {
|
|
7817
|
-
cancelImperativeScroll(state);
|
|
7818
|
-
}
|
|
7819
|
-
if (maintainingScrollAtEnd) {
|
|
7820
|
-
finishMaintainScrollAtEnd(ctx);
|
|
7821
|
-
}
|
|
7880
|
+
interruptMaintainScrollAtEnd(ctx);
|
|
7822
7881
|
prepareReachedEdgeForNextUserScroll(ctx);
|
|
7823
7882
|
(_b2 = (_a4 = state.props).onScrollBeginDrag) == null ? void 0 : _b2.call(_a4, event);
|
|
7824
7883
|
},
|