diff --git a/docs/fork/0012-timeline-scrolls-only-as-far-as-its-content.md b/docs/fork/0012-timeline-scrolls-only-as-far-as-its-content.md new file mode 100644 index 000000000000..9dd888596ad7 --- /dev/null +++ b/docs/fork/0012-timeline-scrolls-only-as-far-as-its-content.md @@ -0,0 +1,42 @@ +# 0012: The timeline scrolls only as far as its content + +- PR: [TrogonStack/t3code#21](https://github.com/TrogonStack/t3code/pull/21) +- Status: active + +## What you can do now + +- Drag the timeline scrollbar and land where the thumb says you will. A long + thread no longer grows an empty region below the last message that the + scrollbar still counts, so the thumb stays proportional to the conversation + instead of shrinking to a sliver. +- Keep a thread open all day without its scroll range drifting. The dead space + used to compound with every turn, several times over, until scrolling to the + bottom meant travelling multiples of the thread's real height through + nothing. +- Flick to the end on a phone and stop at the last message rather than + somewhere in the blank area past it. + +## Why + +The timeline is the one surface a user never leaves, and its scrollbar is how +they judge how much thread there is. When the scroll range says a thread is +eight times longer than it is, every estimate the user makes from it is wrong, +and the flick that should reach the newest message lands nowhere. + +It also degraded the longer someone stayed, which is the worst shape for this +kind of bug: the threads worst affected are exactly the ones people care most +about, and closing and reopening the thread was the only way out. That is not +something we can ask of people who drive agents all day. + +## Upstream considerations + +This one is not going upstream, by our choice: it lives in a patch against a +third-party list dependency rather than in T3 Code's own code, so there is no +upstream T3 Code change to submit. The fix belongs to the list library, and we +are carrying it locally instead of taking on that project's release cycle. + +The rebase burden is small and self-contained. It survives a sync untouched +unless the dependency version moves; a version bump means regenerating the +patch, and the affected code was unchanged in the next upstream release, so it +should reapply. Anyone bumping that dependency needs to confirm the fix is +still present rather than assume the new version carries it. diff --git a/docs/fork/README.md b/docs/fork/README.md index 324bc69819ed..e65ccd798b48 100644 --- a/docs/fork/README.md +++ b/docs/fork/README.md @@ -27,12 +27,19 @@ Each entry uses these sections: ## Ledger -| # | Divergence | PR | Status | -| ---- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------ | -| 0003 | [Native subagent threads for Claude orchestrators](./0003-native-subagent-threads.md) | [#3](https://github.com/TrogonStack/t3code/pull/3) | active | -| 0006 | [Fork schema on its own migration ledger](./0006-fork-migration-ledger.md) | [#13](https://github.com/TrogonStack/t3code/pull/13), [#16](https://github.com/TrogonStack/t3code/pull/16) | active | -| 0007 | [API-key Codex installs are not reported as broken](./0007-codex-api-key-auth-is-supported.md) | [#15](https://github.com/TrogonStack/t3code/pull/15) | active | -| 0008 | [Drop a folder on the sidebar to add a project](./0008-drop-a-folder-to-add-a-project.md) | [#17](https://github.com/TrogonStack/t3code/pull/17) | active | -| 0009 | [Grok reports the account it is signed in as](./0009-grok-reports-its-authenticated-account.md) | [#18](https://github.com/TrogonStack/t3code/pull/18) | active | -| 0010 | [Pull request conventions of our own](./0010-fork-pull-request-conventions.md) | [#19](https://github.com/TrogonStack/t3code/pull/19) | active | -| 0011 | [Follow the background work a thread left running](./0011-follow-background-work.md) | [#20](https://github.com/TrogonStack/t3code/pull/20) | active | +- **0003** [Native subagent threads for Claude orchestrators](./0003-native-subagent-threads.md) + active, [#3](https://github.com/TrogonStack/t3code/pull/3) +- **0006** [Fork schema on its own migration ledger](./0006-fork-migration-ledger.md) + active, [#13](https://github.com/TrogonStack/t3code/pull/13), [#16](https://github.com/TrogonStack/t3code/pull/16) +- **0007** [API-key Codex installs are not reported as broken](./0007-codex-api-key-auth-is-supported.md) + active, [#15](https://github.com/TrogonStack/t3code/pull/15) +- **0008** [Drop a folder on the sidebar to add a project](./0008-drop-a-folder-to-add-a-project.md) + active, [#17](https://github.com/TrogonStack/t3code/pull/17) +- **0009** [Grok reports the account it is signed in as](./0009-grok-reports-its-authenticated-account.md) + active, [#18](https://github.com/TrogonStack/t3code/pull/18) +- **0010** [Pull request conventions of our own](./0010-fork-pull-request-conventions.md) + active, [#19](https://github.com/TrogonStack/t3code/pull/19) +- **0011** [Follow the background work a thread left running](./0011-follow-background-work.md) + active, [#20](https://github.com/TrogonStack/t3code/pull/20) +- **0012** [The timeline scrolls only as far as its content](./0012-timeline-scrolls-only-as-far-as-its-content.md) + active, [#21](https://github.com/TrogonStack/t3code/pull/21) diff --git a/patches/@legendapp__list@3.3.5.patch b/patches/@legendapp__list@3.3.5.patch index 60a5954d8f28..79050f556357 100644 --- a/patches/@legendapp__list@3.3.5.patch +++ b/patches/@legendapp__list@3.3.5.patch @@ -925,6 +925,366 @@ index 40e87cda8c9bc79a889e5542f29af429a24b24d4..2d556eecb0bafe2f54084c809f82144c onScroll: onScrollHandler, recycleItems, refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React2.cloneElement(refreshControlElement, { +diff --git a/react-native.web.js b/react-native.web.js +index 914d2dafaafa001c9ab6791a0a0581659295e333..fb0d4157bea1bd2314b98955d2daf3ae8847b121 100644 +--- a/react-native.web.js ++++ b/react-native.web.js +@@ -6407,6 +6407,25 @@ function getScrollAdjustTarget(ctx, contentNode) { + function scrollAdjustBy(el, left, top) { + el.scrollBy({ behavior: "auto", left, top }); + } ++var SCROLL_ADJUST_PADDING_TOLERANCE = 1e-4; ++function isScrollAdjustPaddingOurs(temporaryPadding) { ++ const current = temporaryPadding.node.style[temporaryPadding.prop]; ++ if (current === temporaryPadding.value) { ++ return true; ++ } ++ const currentValue = Number.parseFloat(current); ++ if (!Number.isFinite(currentValue)) { ++ return false; ++ } ++ const writtenValue = Number.parseFloat(temporaryPadding.value); ++ const tolerance = Math.max(1, Math.abs(writtenValue) * SCROLL_ADJUST_PADDING_TOLERANCE); ++ return Math.abs(currentValue - writtenValue) <= tolerance; ++} ++function restoreScrollAdjustPadding(temporaryPadding) { ++ if (temporaryPadding && isScrollAdjustPaddingOurs(temporaryPadding)) { ++ temporaryPadding.node.style[temporaryPadding.prop] = temporaryPadding.baseline; ++ } ++} + function ScrollAdjust() { + const ctx = useStateContext(); + const lastScrollOffsetRef = React3__namespace.useRef(0); +@@ -6438,15 +6457,24 @@ function ScrollAdjust() { + const nextScroll = currentScroll + scrollDelta; + const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize; + if (needsTemporaryPadding) { +- const currentInlinePaddingEnd = contentNode.style[axis.paddingEndProp]; + const previousTemporaryPadding = temporaryPaddingRef.current; +- const baselinePaddingEnd = (previousTemporaryPadding == null ? void 0 : previousTemporaryPadding.value) === currentInlinePaddingEnd ? previousTemporaryPadding.baseline : currentInlinePaddingEnd; ++ const isStackedInflation = previousTemporaryPadding !== void 0 && previousTemporaryPadding.node === contentNode && previousTemporaryPadding.prop === axis.paddingEndProp; ++ if (!isStackedInflation) { ++ restoreScrollAdjustPadding(previousTemporaryPadding); ++ } ++ const baselinePaddingEnd = isStackedInflation ? previousTemporaryPadding.baseline : contentNode.style[axis.paddingEndProp]; + const pad = (nextScroll + viewportSize - totalSize) * 2; + const currentPaddingEnd = Number.parseFloat( + window.getComputedStyle(contentNode)[axis.paddingEndProp] + ); + const temporaryPaddingEnd = `${(currentPaddingEnd || 0) + pad}px`; +- temporaryPaddingRef.current = { baseline: baselinePaddingEnd, value: temporaryPaddingEnd }; ++ const temporaryPadding = { ++ baseline: baselinePaddingEnd, ++ node: contentNode, ++ prop: axis.paddingEndProp, ++ value: temporaryPaddingEnd ++ }; ++ temporaryPaddingRef.current = temporaryPadding; + contentNode.style[axis.paddingEndProp] = temporaryPaddingEnd; + void contentNode.offsetHeight; + scrollBy(); +@@ -6454,12 +6482,11 @@ function ScrollAdjust() { + cancelAnimationFrame(resetPaddingRafRef.current); + } + resetPaddingRafRef.current = requestAnimationFrame(() => { +- const temporaryPadding = temporaryPaddingRef.current; + resetPaddingRafRef.current = void 0; +- temporaryPaddingRef.current = void 0; +- if (contentNode.style[axis.paddingEndProp] === (temporaryPadding == null ? void 0 : temporaryPadding.value)) { +- contentNode.style[axis.paddingEndProp] = temporaryPadding.baseline; ++ if (temporaryPaddingRef.current === temporaryPadding) { ++ temporaryPaddingRef.current = void 0; + } ++ restoreScrollAdjustPadding(temporaryPadding); + }); + } else { + scrollBy(); +@@ -6472,6 +6499,15 @@ function ScrollAdjust() { + lastScrollAdjustUserOffsetRef.current = scrollAdjustUserOffset || 0; + } + }, [ctx]); ++ React3__namespace.useEffect(() => () => { ++ if (resetPaddingRafRef.current !== void 0) { ++ cancelAnimationFrame(resetPaddingRafRef.current); ++ resetPaddingRafRef.current = void 0; ++ } ++ const temporaryPadding = temporaryPaddingRef.current; ++ temporaryPaddingRef.current = void 0; ++ restoreScrollAdjustPadding(temporaryPadding); ++ }, []); + useValueListener$("scrollAdjust", callback); + useValueListener$("scrollAdjustUserOffset", callback); + return null; +diff --git a/react-native.web.mjs b/react-native.web.mjs +index 95465f2ab89ce41a10553f58af83618f7310e83c..b27eecb6096b531f523df8204384ab58017cd04d 100644 +--- a/react-native.web.mjs ++++ b/react-native.web.mjs +@@ -6386,6 +6386,25 @@ function getScrollAdjustTarget(ctx, contentNode) { + function scrollAdjustBy(el, left, top) { + el.scrollBy({ behavior: "auto", left, top }); + } ++var SCROLL_ADJUST_PADDING_TOLERANCE = 1e-4; ++function isScrollAdjustPaddingOurs(temporaryPadding) { ++ const current = temporaryPadding.node.style[temporaryPadding.prop]; ++ if (current === temporaryPadding.value) { ++ return true; ++ } ++ const currentValue = Number.parseFloat(current); ++ if (!Number.isFinite(currentValue)) { ++ return false; ++ } ++ const writtenValue = Number.parseFloat(temporaryPadding.value); ++ const tolerance = Math.max(1, Math.abs(writtenValue) * SCROLL_ADJUST_PADDING_TOLERANCE); ++ return Math.abs(currentValue - writtenValue) <= tolerance; ++} ++function restoreScrollAdjustPadding(temporaryPadding) { ++ if (temporaryPadding && isScrollAdjustPaddingOurs(temporaryPadding)) { ++ temporaryPadding.node.style[temporaryPadding.prop] = temporaryPadding.baseline; ++ } ++} + function ScrollAdjust() { + const ctx = useStateContext(); + const lastScrollOffsetRef = React3.useRef(0); +@@ -6417,15 +6436,24 @@ function ScrollAdjust() { + const nextScroll = currentScroll + scrollDelta; + const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize; + if (needsTemporaryPadding) { +- const currentInlinePaddingEnd = contentNode.style[axis.paddingEndProp]; + const previousTemporaryPadding = temporaryPaddingRef.current; +- const baselinePaddingEnd = (previousTemporaryPadding == null ? void 0 : previousTemporaryPadding.value) === currentInlinePaddingEnd ? previousTemporaryPadding.baseline : currentInlinePaddingEnd; ++ const isStackedInflation = previousTemporaryPadding !== void 0 && previousTemporaryPadding.node === contentNode && previousTemporaryPadding.prop === axis.paddingEndProp; ++ if (!isStackedInflation) { ++ restoreScrollAdjustPadding(previousTemporaryPadding); ++ } ++ const baselinePaddingEnd = isStackedInflation ? previousTemporaryPadding.baseline : contentNode.style[axis.paddingEndProp]; + const pad = (nextScroll + viewportSize - totalSize) * 2; + const currentPaddingEnd = Number.parseFloat( + window.getComputedStyle(contentNode)[axis.paddingEndProp] + ); + const temporaryPaddingEnd = `${(currentPaddingEnd || 0) + pad}px`; +- temporaryPaddingRef.current = { baseline: baselinePaddingEnd, value: temporaryPaddingEnd }; ++ const temporaryPadding = { ++ baseline: baselinePaddingEnd, ++ node: contentNode, ++ prop: axis.paddingEndProp, ++ value: temporaryPaddingEnd ++ }; ++ temporaryPaddingRef.current = temporaryPadding; + contentNode.style[axis.paddingEndProp] = temporaryPaddingEnd; + void contentNode.offsetHeight; + scrollBy(); +@@ -6433,12 +6461,11 @@ function ScrollAdjust() { + cancelAnimationFrame(resetPaddingRafRef.current); + } + resetPaddingRafRef.current = requestAnimationFrame(() => { +- const temporaryPadding = temporaryPaddingRef.current; + resetPaddingRafRef.current = void 0; +- temporaryPaddingRef.current = void 0; +- if (contentNode.style[axis.paddingEndProp] === (temporaryPadding == null ? void 0 : temporaryPadding.value)) { +- contentNode.style[axis.paddingEndProp] = temporaryPadding.baseline; ++ if (temporaryPaddingRef.current === temporaryPadding) { ++ temporaryPaddingRef.current = void 0; + } ++ restoreScrollAdjustPadding(temporaryPadding); + }); + } else { + scrollBy(); +@@ -6451,6 +6478,15 @@ function ScrollAdjust() { + lastScrollAdjustUserOffsetRef.current = scrollAdjustUserOffset || 0; + } + }, [ctx]); ++ React3.useEffect(() => () => { ++ if (resetPaddingRafRef.current !== void 0) { ++ cancelAnimationFrame(resetPaddingRafRef.current); ++ resetPaddingRafRef.current = void 0; ++ } ++ const temporaryPadding = temporaryPaddingRef.current; ++ temporaryPaddingRef.current = void 0; ++ restoreScrollAdjustPadding(temporaryPadding); ++ }, []); + useValueListener$("scrollAdjust", callback); + useValueListener$("scrollAdjustUserOffset", callback); + return null; +diff --git a/react.js b/react.js +index 914d2dafaafa001c9ab6791a0a0581659295e333..fb0d4157bea1bd2314b98955d2daf3ae8847b121 100644 +--- a/react.js ++++ b/react.js +@@ -6407,6 +6407,25 @@ function getScrollAdjustTarget(ctx, contentNode) { + function scrollAdjustBy(el, left, top) { + el.scrollBy({ behavior: "auto", left, top }); + } ++var SCROLL_ADJUST_PADDING_TOLERANCE = 1e-4; ++function isScrollAdjustPaddingOurs(temporaryPadding) { ++ const current = temporaryPadding.node.style[temporaryPadding.prop]; ++ if (current === temporaryPadding.value) { ++ return true; ++ } ++ const currentValue = Number.parseFloat(current); ++ if (!Number.isFinite(currentValue)) { ++ return false; ++ } ++ const writtenValue = Number.parseFloat(temporaryPadding.value); ++ const tolerance = Math.max(1, Math.abs(writtenValue) * SCROLL_ADJUST_PADDING_TOLERANCE); ++ return Math.abs(currentValue - writtenValue) <= tolerance; ++} ++function restoreScrollAdjustPadding(temporaryPadding) { ++ if (temporaryPadding && isScrollAdjustPaddingOurs(temporaryPadding)) { ++ temporaryPadding.node.style[temporaryPadding.prop] = temporaryPadding.baseline; ++ } ++} + function ScrollAdjust() { + const ctx = useStateContext(); + const lastScrollOffsetRef = React3__namespace.useRef(0); +@@ -6438,15 +6457,24 @@ function ScrollAdjust() { + const nextScroll = currentScroll + scrollDelta; + const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize; + if (needsTemporaryPadding) { +- const currentInlinePaddingEnd = contentNode.style[axis.paddingEndProp]; + const previousTemporaryPadding = temporaryPaddingRef.current; +- const baselinePaddingEnd = (previousTemporaryPadding == null ? void 0 : previousTemporaryPadding.value) === currentInlinePaddingEnd ? previousTemporaryPadding.baseline : currentInlinePaddingEnd; ++ const isStackedInflation = previousTemporaryPadding !== void 0 && previousTemporaryPadding.node === contentNode && previousTemporaryPadding.prop === axis.paddingEndProp; ++ if (!isStackedInflation) { ++ restoreScrollAdjustPadding(previousTemporaryPadding); ++ } ++ const baselinePaddingEnd = isStackedInflation ? previousTemporaryPadding.baseline : contentNode.style[axis.paddingEndProp]; + const pad = (nextScroll + viewportSize - totalSize) * 2; + const currentPaddingEnd = Number.parseFloat( + window.getComputedStyle(contentNode)[axis.paddingEndProp] + ); + const temporaryPaddingEnd = `${(currentPaddingEnd || 0) + pad}px`; +- temporaryPaddingRef.current = { baseline: baselinePaddingEnd, value: temporaryPaddingEnd }; ++ const temporaryPadding = { ++ baseline: baselinePaddingEnd, ++ node: contentNode, ++ prop: axis.paddingEndProp, ++ value: temporaryPaddingEnd ++ }; ++ temporaryPaddingRef.current = temporaryPadding; + contentNode.style[axis.paddingEndProp] = temporaryPaddingEnd; + void contentNode.offsetHeight; + scrollBy(); +@@ -6454,12 +6482,11 @@ function ScrollAdjust() { + cancelAnimationFrame(resetPaddingRafRef.current); + } + resetPaddingRafRef.current = requestAnimationFrame(() => { +- const temporaryPadding = temporaryPaddingRef.current; + resetPaddingRafRef.current = void 0; +- temporaryPaddingRef.current = void 0; +- if (contentNode.style[axis.paddingEndProp] === (temporaryPadding == null ? void 0 : temporaryPadding.value)) { +- contentNode.style[axis.paddingEndProp] = temporaryPadding.baseline; ++ if (temporaryPaddingRef.current === temporaryPadding) { ++ temporaryPaddingRef.current = void 0; + } ++ restoreScrollAdjustPadding(temporaryPadding); + }); + } else { + scrollBy(); +@@ -6472,6 +6499,15 @@ function ScrollAdjust() { + lastScrollAdjustUserOffsetRef.current = scrollAdjustUserOffset || 0; + } + }, [ctx]); ++ React3__namespace.useEffect(() => () => { ++ if (resetPaddingRafRef.current !== void 0) { ++ cancelAnimationFrame(resetPaddingRafRef.current); ++ resetPaddingRafRef.current = void 0; ++ } ++ const temporaryPadding = temporaryPaddingRef.current; ++ temporaryPaddingRef.current = void 0; ++ restoreScrollAdjustPadding(temporaryPadding); ++ }, []); + useValueListener$("scrollAdjust", callback); + useValueListener$("scrollAdjustUserOffset", callback); + return null; +diff --git a/react.mjs b/react.mjs +index 95465f2ab89ce41a10553f58af83618f7310e83c..b27eecb6096b531f523df8204384ab58017cd04d 100644 +--- a/react.mjs ++++ b/react.mjs +@@ -6386,6 +6386,25 @@ function getScrollAdjustTarget(ctx, contentNode) { + function scrollAdjustBy(el, left, top) { + el.scrollBy({ behavior: "auto", left, top }); + } ++var SCROLL_ADJUST_PADDING_TOLERANCE = 1e-4; ++function isScrollAdjustPaddingOurs(temporaryPadding) { ++ const current = temporaryPadding.node.style[temporaryPadding.prop]; ++ if (current === temporaryPadding.value) { ++ return true; ++ } ++ const currentValue = Number.parseFloat(current); ++ if (!Number.isFinite(currentValue)) { ++ return false; ++ } ++ const writtenValue = Number.parseFloat(temporaryPadding.value); ++ const tolerance = Math.max(1, Math.abs(writtenValue) * SCROLL_ADJUST_PADDING_TOLERANCE); ++ return Math.abs(currentValue - writtenValue) <= tolerance; ++} ++function restoreScrollAdjustPadding(temporaryPadding) { ++ if (temporaryPadding && isScrollAdjustPaddingOurs(temporaryPadding)) { ++ temporaryPadding.node.style[temporaryPadding.prop] = temporaryPadding.baseline; ++ } ++} + function ScrollAdjust() { + const ctx = useStateContext(); + const lastScrollOffsetRef = React3.useRef(0); +@@ -6417,15 +6436,24 @@ function ScrollAdjust() { + const nextScroll = currentScroll + scrollDelta; + const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize; + if (needsTemporaryPadding) { +- const currentInlinePaddingEnd = contentNode.style[axis.paddingEndProp]; + const previousTemporaryPadding = temporaryPaddingRef.current; +- const baselinePaddingEnd = (previousTemporaryPadding == null ? void 0 : previousTemporaryPadding.value) === currentInlinePaddingEnd ? previousTemporaryPadding.baseline : currentInlinePaddingEnd; ++ const isStackedInflation = previousTemporaryPadding !== void 0 && previousTemporaryPadding.node === contentNode && previousTemporaryPadding.prop === axis.paddingEndProp; ++ if (!isStackedInflation) { ++ restoreScrollAdjustPadding(previousTemporaryPadding); ++ } ++ const baselinePaddingEnd = isStackedInflation ? previousTemporaryPadding.baseline : contentNode.style[axis.paddingEndProp]; + const pad = (nextScroll + viewportSize - totalSize) * 2; + const currentPaddingEnd = Number.parseFloat( + window.getComputedStyle(contentNode)[axis.paddingEndProp] + ); + const temporaryPaddingEnd = `${(currentPaddingEnd || 0) + pad}px`; +- temporaryPaddingRef.current = { baseline: baselinePaddingEnd, value: temporaryPaddingEnd }; ++ const temporaryPadding = { ++ baseline: baselinePaddingEnd, ++ node: contentNode, ++ prop: axis.paddingEndProp, ++ value: temporaryPaddingEnd ++ }; ++ temporaryPaddingRef.current = temporaryPadding; + contentNode.style[axis.paddingEndProp] = temporaryPaddingEnd; + void contentNode.offsetHeight; + scrollBy(); +@@ -6433,12 +6461,11 @@ function ScrollAdjust() { + cancelAnimationFrame(resetPaddingRafRef.current); + } + resetPaddingRafRef.current = requestAnimationFrame(() => { +- const temporaryPadding = temporaryPaddingRef.current; + resetPaddingRafRef.current = void 0; +- temporaryPaddingRef.current = void 0; +- if (contentNode.style[axis.paddingEndProp] === (temporaryPadding == null ? void 0 : temporaryPadding.value)) { +- contentNode.style[axis.paddingEndProp] = temporaryPadding.baseline; ++ if (temporaryPaddingRef.current === temporaryPadding) { ++ temporaryPaddingRef.current = void 0; + } ++ restoreScrollAdjustPadding(temporaryPadding); + }); + } else { + scrollBy(); +@@ -6451,6 +6478,15 @@ function ScrollAdjust() { + lastScrollAdjustUserOffsetRef.current = scrollAdjustUserOffset || 0; + } + }, [ctx]); ++ React3.useEffect(() => () => { ++ if (resetPaddingRafRef.current !== void 0) { ++ cancelAnimationFrame(resetPaddingRafRef.current); ++ resetPaddingRafRef.current = void 0; ++ } ++ const temporaryPadding = temporaryPaddingRef.current; ++ temporaryPaddingRef.current = void 0; ++ restoreScrollAdjustPadding(temporaryPadding); ++ }, []); + useValueListener$("scrollAdjust", callback); + useValueListener$("scrollAdjustUserOffset", callback); + return null; diff --git a/reanimated.d.ts b/reanimated.d.ts index e5043320700b12f34f4c0babbc341f85ca8135c1..2ce63830a28636b21937a0741fd0e613dae950fe 100644 --- a/reanimated.d.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c79aea36a0e..97980591ed8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,7 +76,7 @@ patchedDependencies: '@effect/vitest@4.0.0-beta.103': a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b '@expo/metro-config@56.0.14': 8cb08b5bb7051ed9d2dbe46a2c293c5a1e17f1bd6ddf30de27909e18c921ff46 '@ff-labs/fff-node@0.9.4': ab9ff544009e1891cfe3930105862d3699007f38922a79f3c98d90018deca368 - '@legendapp/list@3.3.5': 6befc76c7f590a0b0915b531386ce7e3bbb364612868e1f04e4ac84f60a39ab5 + '@legendapp/list@3.3.5': 897638cce5599b31551c2a3169d4bcbaf88ed27db0b0af66ea01972cc0370813 '@pierre/diffs@1.3.0-beta.10': 7ef7cb0cbabb17c15cdb137554068b36f15f6f5265e73fb51452aa3380db91aa '@react-native-menu/menu@2.0.0': c7f66d121c726ade4f5c4e1aed11a691e5711d244c544084e289ac26132a0045 '@react-native/gradle-plugin@0.85.3': c1b594a16e682d621b6a960926f8ce13fc92edfb397884cfe7fcb0518996a784 @@ -216,7 +216,7 @@ importers: version: 56.0.18(3cdc0dde9f93166d952f1e1bd0cb25c0) '@legendapp/list': specifier: 'catalog:' - version: 3.3.5(patch_hash=6befc76c7f590a0b0915b531386ce7e3bbb364612868e1f04e4ac84f60a39ab5)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + version: 3.3.5(patch_hash=897638cce5599b31551c2a3169d4bcbaf88ed27db0b0af66ea01972cc0370813)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) '@noble/curves': specifier: 'catalog:' version: 1.9.1 @@ -545,7 +545,7 @@ importers: version: 0.9.0 '@legendapp/list': specifier: 'catalog:' - version: 3.3.5(patch_hash=6befc76c7f590a0b0915b531386ce7e3bbb364612868e1f04e4ac84f60a39ab5)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 3.3.5(patch_hash=897638cce5599b31551c2a3169d4bcbaf88ed27db0b0af66ea01972cc0370813)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@lexical/react': specifier: ^0.41.0 version: 0.41.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(yjs@13.6.31) @@ -13015,7 +13015,7 @@ snapshots: dependencies: jsbi: 4.3.2 - '@legendapp/list@3.3.5(patch_hash=6befc76c7f590a0b0915b531386ce7e3bbb364612868e1f04e4ac84f60a39ab5)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)': + '@legendapp/list@3.3.5(patch_hash=897638cce5599b31551c2a3169d4bcbaf88ed27db0b0af66ea01972cc0370813)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)': dependencies: react: 19.2.3 use-sync-external-store: 1.6.0(react@19.2.3) @@ -13023,7 +13023,7 @@ snapshots: react-dom: 19.2.3(react@19.2.3) react-native: 0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) - '@legendapp/list@3.3.5(patch_hash=6befc76c7f590a0b0915b531386ce7e3bbb364612868e1f04e4ac84f60a39ab5)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@legendapp/list@3.3.5(patch_hash=897638cce5599b31551c2a3169d4bcbaf88ed27db0b0af66ea01972cc0370813)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: react: 19.2.6 use-sync-external-store: 1.6.0(react@19.2.6)