Repository navigation
[WIP] [HOLD on #104977, #104978] [LegendList 6/9] feat: migrate report actions to chronological LegendList #100733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7d4be68
2a3323a
d815c1a
ba852b2
15312bb
0a811f9
750e92d
332a7b3
e385011
9117baa
e5c4ec3
3a782f9
fa5194f
52df1e9
c80ea5a
5cb81be
c873dca
f91ebe0
255f4d3
62a7c0d
0964d53
09057d5
61dc6ad
ffa18ae
53f3b9f
f12b575
34b345d
da3b443
55cb72a
a5670fa
8188df1
9bd382a
f0b046a
a8fc4fa
6e7f045
ca78b55
59a5397
d2f2cc8
08e1f69
5c7ffc8
84b0f19
a1e0d25
e37edb4
b43b59e
e904b99
40f7719
a68ee3c
e117ffc
4adbdaa
c92613d
7096033
c0751dd
0cb9d7b
0f53485
b611f38
779eaac
5dab08a
519cb5b
8229bce
ed4e31a
d25f5b6
e83aec2
b6c6df2
40a2338
49ab56d
e1bbfda
e8974de
1de8343
bd9ce7c
e60414a
1c04141
c12c90c
89ef8b2
eb148d3
c71756d
9b1bf78
311f777
5c905a6
e3b9d15
c8de6b3
e466ab7
4b8a445
49eafc2
8dc16d8
5c00ae5
e0b5420
df38ea5
be9a884
e01e0fb
2eed882
2891fd8
945622d
c5e8046
8e20b9c
983add0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| diff --git a/node_modules/@legendapp/list/react-native.js b/node_modules/@legendapp/list/react-native.js | ||
| index 59ecd66..432f476 100644 | ||
| --- a/node_modules/@legendapp/list/react-native.js | ||
| +++ b/node_modules/@legendapp/list/react-native.js | ||
| @@ -1642,6 +1642,19 @@ function getPredictedNativeClamp(state, unresolvedAmount, totalSize) { | ||
| } | ||
| return 0; | ||
| } | ||
| +// Android clamps the offset to the new end while mounting a content shrink, then native MVCP adds the | ||
| +// anchor delta on top. Sync JS state to that clamp and only request the rest of the movement. | ||
| +function getAndroidNativeClampedAdjust(ctx, positionDiff) { | ||
| + const state = ctx.state; | ||
| + const maxScroll = Math.max(0, getContentSize(ctx) - state.scrollLength); | ||
| + if (state.scroll <= maxScroll + MVCP_POSITION_EPSILON) { | ||
| + return positionDiff; | ||
| + } | ||
| + const targetScroll = Math.min(state.scroll + positionDiff, maxScroll); | ||
| + state.scroll = maxScroll; | ||
| + state.scrollPending = maxScroll; | ||
| + return targetScroll - maxScroll; | ||
| +} | ||
| function getProgressTowardAmount(targetDelta, nativeDelta) { | ||
| return targetDelta < 0 ? -nativeDelta : nativeDelta; | ||
| } | ||
| @@ -1884,6 +1897,9 @@ function prepareMVCP(ctx, dataChanged, adjustmentSource) { | ||
| now, | ||
| positionDiff | ||
| }); | ||
| + if (Platform.OS === "android" && !dataChanged && scrollTarget === void 0) { | ||
| + positionDiff = getAndroidNativeClampedAdjust(ctx, positionDiff); | ||
| + } | ||
| if (shouldQueueNativeMVCPAdjust(dataChanged, state, positionDiff, prevTotalSize, prevScroll, scrollTarget)) { | ||
| state.pendingNativeMVCPAdjust = { | ||
| amount: positionDiff, | ||
| diff --git a/node_modules/@legendapp/list/react-native.mjs b/node_modules/@legendapp/list/react-native.mjs | ||
| index 5bf1496..8262cbd 100644 | ||
| --- a/node_modules/@legendapp/list/react-native.mjs | ||
| +++ b/node_modules/@legendapp/list/react-native.mjs | ||
| @@ -1621,6 +1621,19 @@ function getPredictedNativeClamp(state, unresolvedAmount, totalSize) { | ||
| } | ||
| return 0; | ||
| } | ||
| +// Android clamps the offset to the new end while mounting a content shrink, then native MVCP adds the | ||
| +// anchor delta on top. Sync JS state to that clamp and only request the rest of the movement. | ||
| +function getAndroidNativeClampedAdjust(ctx, positionDiff) { | ||
| + const state = ctx.state; | ||
| + const maxScroll = Math.max(0, getContentSize(ctx) - state.scrollLength); | ||
| + if (state.scroll <= maxScroll + MVCP_POSITION_EPSILON) { | ||
| + return positionDiff; | ||
| + } | ||
| + const targetScroll = Math.min(state.scroll + positionDiff, maxScroll); | ||
| + state.scroll = maxScroll; | ||
| + state.scrollPending = maxScroll; | ||
| + return targetScroll - maxScroll; | ||
| +} | ||
| function getProgressTowardAmount(targetDelta, nativeDelta) { | ||
| return targetDelta < 0 ? -nativeDelta : nativeDelta; | ||
| } | ||
| @@ -1863,6 +1876,9 @@ function prepareMVCP(ctx, dataChanged, adjustmentSource) { | ||
| now, | ||
| positionDiff | ||
| }); | ||
| + if (Platform.OS === "android" && !dataChanged && scrollTarget === void 0) { | ||
| + positionDiff = getAndroidNativeClampedAdjust(ctx, positionDiff); | ||
| + } | ||
| if (shouldQueueNativeMVCPAdjust(dataChanged, state, positionDiff, prevTotalSize, prevScroll, scrollTarget)) { | ||
| state.pendingNativeMVCPAdjust = { | ||
| amount: positionDiff, |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # `@legendapp/list` patches | ||
|
|
||
| The Fabric content-size fix from https://github.com/LegendApp/legend-list/commit/a2d20a9b is included in [LegendList 3.7.0](https://github.com/LegendApp/legend-list/blob/v3.7.0/CHANGELOG.md#370), so its local patch has been removed. | ||
|
|
||
| ### [@legendapp+list+3.7.0+001+account-for-android-end-clamp.patch](@legendapp+list+3.7.0+001+account-for-android-end-clamp.patch) | ||
|
|
||
| - Reason: On Android, a chat that opens at its newest messages can briefly show older messages before it snaps back to the end. When rows above the viewport get their real, smaller heights, the content shrinks. Android clamps the scroll offset to the new end, and LegendList's scroll-preservation anchor then moves the offset by the full shrink again. The list stays above the end by that amount until the next scroll to the end. Account for Android's clamp and only move the anchor by what the clamp doesn't cover. | ||
| - Scope: Only item-size scroll preservation on Android, and only when the content shrinks below the current offset. Data changes and active scroll targets already handle the clamp and are unchanged. iOS and web are unchanged. | ||
| - Upstream PR/issue: https://github.com/LegendApp/legend-list/pull/582 upstreams this patch. https://github.com/LegendApp/legend-list/pull/481 covers the related bottom-inset case. Keep this patch until the installed LegendList release includes this fix. | ||
| - E/App issue: https://github.com/Expensify/App/pull/100733#issuecomment-6287555197 | ||
| - PR introducing patch: https://github.com/Expensify/App/pull/100733 | ||
| - Reproduction: In a DM, mark the third-newest message as unread and go back to the inbox. Open the DM again. It should open at the newest messages without a frame showing older messages. Also scroll through older history and send a new message to check scroll preservation and end following. | ||
|
|
||
| ### Related upstream work | ||
|
|
||
| - https://github.com/LegendApp/legend-list/pull/583 refreshes the cached end-follow state when `maintainScrollAtEndThreshold` changes. This supports a fixed pixel follow distance across viewport changes when using LegendList's built-in end following. |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MelvinBot Is the change to this patch reflected in the upstream react/react-native#46247?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No — none of this patch is upstream, and the new change in this PR isn't even part of #46247's diff. Two separate gaps:
Suggestion: the How I checked
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @chrispader at some point we need to get this merged upstream. I talked to Janic about this about a month ago, but Expensify didn't want to deal with the overhead of onboarding a new agency just for that.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll look into it!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Chris's AI co-pilot checking in. 🤖 RN #57959 covers the z-index anchor selection fix. I raised the missing LegendList zero-sized anchor guard in that PR's discussion and added RNTester reproducer #59360. The upstream links and patch-removal conditions are now recorded in |
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import {isRecord} from '@libs/ObjectUtils'; | ||
|
|
||
| import type {LegendListRef} from '@legendapp/list/react-native'; | ||
|
|
||
| /** | ||
| * LegendList uses paint containment for web item containers, which clips descendants that render | ||
| * outside their row. Remove only paint containment so inline menus can overflow while layout and | ||
| * style containment keep the rest of the row isolated. | ||
| */ | ||
| function allowLegendListItemOverflow(list: LegendListRef | null, index: number): void { | ||
| const itemContainer: unknown = list?.getState().elementAtIndex(index); | ||
| if (!isRecord(itemContainer) || !isRecord(itemContainer.style) || typeof itemContainer.style.contain !== 'string') { | ||
| return; | ||
| } | ||
|
|
||
| itemContainer.style.contain = 'layout style'; | ||
| } | ||
|
|
||
| export default allowLegendListItemOverflow; |
Uh oh!
There was an error while loading. Please reload this page.