|
347 | 347 | let lastPortrait = isPortraitMobile(); |
348 | 348 | let lastPortraitStableScrollY = lastPortrait ? getScrollTop() : 0; |
349 | 349 | let pendingRecovery = null; |
| 350 | + let finishTimer = 0; |
350 | 351 |
|
351 | 352 | const updateStableState = () => { |
352 | 353 | lastPortrait = isPortraitMobile(); |
|
355 | 356 | } |
356 | 357 | }; |
357 | 358 |
|
| 359 | + const clearFinishTimer = () => { |
| 360 | + if (!finishTimer) return; |
| 361 | + window.clearTimeout(finishTimer); |
| 362 | + finishTimer = 0; |
| 363 | + }; |
| 364 | + |
| 365 | + const queueFinishRecovery = () => { |
| 366 | + if (!pendingRecovery?.restorePortraitScroll) return; |
| 367 | + clearFinishTimer(); |
| 368 | + finishTimer = window.setTimeout(() => { |
| 369 | + pendingRecovery = null; |
| 370 | + updateStableState(); |
| 371 | + }, 220); |
| 372 | + }; |
| 373 | + |
358 | 374 | const settledRecovery = createSettledScheduler(() => { |
359 | 375 | if (pendingRecovery?.restorePortraitScroll && isPortraitMobile()){ |
360 | 376 | const currentY = getScrollTop(); |
361 | | - if (Math.abs(currentY - lastPortraitStableScrollY) > 1){ |
362 | | - window.scrollTo({ top: lastPortraitStableScrollY, behavior: 'auto' }); |
| 377 | + const targetY = pendingRecovery.scrollY; |
| 378 | + if (Math.abs(currentY - targetY) > 1){ |
| 379 | + window.scrollTo({ top: targetY, behavior: 'auto' }); |
363 | 380 | } |
| 381 | + queueFinishRecovery(); |
| 382 | + return; |
364 | 383 | } |
365 | 384 |
|
366 | 385 | pendingRecovery = null; |
367 | 386 | updateStableState(); |
368 | 387 | }); |
369 | 388 |
|
370 | 389 | window.addEventListener('scroll', () => { |
| 390 | + if (pendingRecovery?.restorePortraitScroll && isPortraitMobile()){ |
| 391 | + const currentY = getScrollTop(); |
| 392 | + if (Math.abs(currentY - pendingRecovery.scrollY) > 1){ |
| 393 | + clearFinishTimer(); |
| 394 | + settledRecovery.schedule(80); |
| 395 | + } else { |
| 396 | + queueFinishRecovery(); |
| 397 | + } |
| 398 | + return; |
| 399 | + } |
| 400 | + |
371 | 401 | if (!pendingRecovery && isPortraitMobile()){ |
372 | 402 | lastPortraitStableScrollY = getScrollTop(); |
373 | 403 | } |
|
380 | 410 | } |
381 | 411 |
|
382 | 412 | pendingRecovery = { |
383 | | - restorePortraitScroll: !wasPortrait |
| 413 | + restorePortraitScroll: !wasPortrait, |
| 414 | + scrollY: lastPortraitStableScrollY |
384 | 415 | }; |
385 | | - settledRecovery.schedule(160); |
| 416 | + clearFinishTimer(); |
| 417 | + if (pendingRecovery.restorePortraitScroll){ |
| 418 | + settledRecovery.schedule(160); |
| 419 | + } |
386 | 420 | }); |
387 | 421 |
|
388 | 422 | window.addEventListener('resize', () => { |
389 | 423 | if (pendingRecovery){ |
| 424 | + clearFinishTimer(); |
390 | 425 | settledRecovery.schedule(120); |
391 | 426 | return; |
392 | 427 | } |
393 | 428 | updateStableState(); |
394 | 429 | }); |
395 | 430 |
|
396 | | - window.addEventListener('pageshow', updateStableState); |
| 431 | + window.addEventListener('pageshow', () => { |
| 432 | + pendingRecovery = null; |
| 433 | + clearFinishTimer(); |
| 434 | + updateStableState(); |
| 435 | + }); |
397 | 436 |
|
398 | 437 | if (window.visualViewport){ |
399 | 438 | const syncViewportRecovery = () => { |
400 | 439 | if (!pendingRecovery) return; |
| 440 | + clearFinishTimer(); |
401 | 441 | settledRecovery.schedule(120); |
402 | 442 | }; |
403 | 443 |
|
|
0 commit comments