Skip to content

Commit 4fa990e

Browse files
fix(mobile): screen lists register with their header, enforced by lint
A screen's list has to scroll in a header-registered scroll view, or its header loses the scroll-edge blur and, on the Duo, the blur's reach under the vertical bar. Archived threads, open source licenses, pull request files, the file tree and the new-task picker now render through NativeScrollView. The new t3code/require-registered-list-scroll rule reports a LegendList without one; lists nested in another scroll surface or in sheets suppress it with a reason. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent 90c455f commit 4fa990e

14 files changed

Lines changed: 85 additions & 1 deletion

‎apps/mobile/src/features/archive/ArchivedThreadsScreen.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NativeScrollView } from "../../native/NativeScrollViewMarker";
12
import { Button } from "../../components/ui/Button";
23
import type {
34
EnvironmentProject,
@@ -428,6 +429,7 @@ export function ArchivedThreadsScreen(props: {
428429
<SettingsScreenContent>
429430
<GestureDetector gesture={archiveScrollGesture}>
430431
<LegendList
432+
renderScrollComponent={Platform.OS === "ios" ? NativeScrollView : undefined}
431433
className="flex-1"
432434
contentContainerStyle={{
433435
paddingBottom: 32,

‎apps/mobile/src/features/files/FileTreeBrowser.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NativeScrollView } from "../../native/NativeScrollViewMarker";
12
import { Button } from "../../components/ui/Button";
23
import { LegendList } from "@legendapp/list/react-native";
34
import type { ProjectEntry } from "@t3tools/contracts";
@@ -221,6 +222,7 @@ export function FileTreeBrowser(props: {
221222
// Keep the list as direct screen content so UIKit can apply header insets.
222223
return (
223224
<LegendList
225+
renderScrollComponent={Platform.OS === "ios" ? NativeScrollView : undefined}
224226
contentInsetStartAdjustment={headerInset}
225227
alwaysBounceVertical
226228
className="flex-1"

‎apps/mobile/src/features/pull-requests/PullRequestFiles.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NativeScrollView } from "../../native/NativeScrollViewMarker";
12
import { sourceControlClients } from "@t3tools/client-runtime/source-control-clients";
23
import { AnimatedLegendList } from "@legendapp/list/reanimated";
34
import {
@@ -440,6 +441,7 @@ export function PullRequestFilesSheet({ route }: StaticScreenProps<PullRequestDi
440441
</Toolbar>
441442
<ScreenContent>
442443
<AnimatedLegendList
444+
renderScrollComponent={Platform.OS === "ios" ? NativeScrollView : undefined}
443445
className="flex-1"
444446
data={parsed.kind === "files" ? groupByDirectory(parsed.files, collapsed) : []}
445447
keyExtractor={(item) => item.key}

‎apps/mobile/src/features/settings/SettingsOpenSourceLicensesRouteScreen.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NativeScrollView } from "../../native/NativeScrollViewMarker";
12
import { SearchField } from "../../components/ui/SearchField";
23
import { Toolbar } from "../../components/ui/Toolbar";
34
import { ScreenScrollView as ScrollView } from "../../components/ui/ScreenScrollView";
@@ -127,6 +128,7 @@ export function SettingsOpenSourceLicensesRouteScreen() {
127128
) : null}
128129

129130
<LegendList
131+
renderScrollComponent={Platform.OS === "ios" ? NativeScrollView : undefined}
130132
className="flex-1"
131133
contentContainerStyle={{
132134
paddingBottom: usesNativeMailSearchToolbar

‎apps/mobile/src/features/threads/NewTaskContextPickerScreens.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NativeScrollView } from "../../native/NativeScrollViewMarker";
12
import { SearchField } from "../../components/ui/SearchField";
23
import { Button } from "../../components/ui/Button";
34
import { Toolbar } from "../../components/ui/Toolbar";
@@ -449,6 +450,7 @@ export function BranchPickerScreen(props: {
449450
</ScrollView>
450451
) : (
451452
<LegendList
453+
renderScrollComponent={Platform.OS === "ios" ? NativeScrollView : undefined}
452454
alwaysBounceVertical={false}
453455
automaticallyAdjustsScrollIndicatorInsets
454456
automaticallyAdjustKeyboardInsets={Platform.OS === "ios"}

‎apps/mobile/src/features/threads/ThreadFeed.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3106,6 +3106,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
31063106
<PresentationSource identifier={fileShareSourceIdentifier} style={{ flex: 1 }}>
31073107
<View className="flex-1" onLayout={handleViewportLayout}>
31083108
<View className="flex-1">
3109+
{/* oxlint-disable-next-line t3code/require-registered-list-scroll -- ThreadFeedScrollView is passed through the iOS-only spread below; the prop rejects undefined. */}
31093110
<KeyboardAwareLegendList
31103111
ref={listRef}
31113112
// LegendList cannot see adjustedContentInset; remount so initial positioning waits for UIKit attachment.

‎apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ function ThreadNavigationSidebarPane(
720720
<View className="flex-1">
721721
<SwipeableScrollGateProvider enabled={swipeEnabled}>
722722
<GestureDetector gesture={sidebarScrollGesture}>
723+
{/* oxlint-disable-next-line t3code/require-registered-list-scroll -- Only the non-native workspace layout (Android and the fallback) renders this sidebar, which has no native header to register with. */}
723724
<AnimatedLegendList
724725
itemLayoutAnimation={THREAD_SIDEBAR_ROW_LAYOUT}
725726
data={listItems}
@@ -789,6 +790,7 @@ function ThreadNavigationSidebarPane(
789790
) : (
790791
<SwipeableScrollGateProvider enabled={swipeEnabled}>
791792
<GestureDetector gesture={sidebarScrollGesture}>
793+
{/* oxlint-disable-next-line t3code/require-registered-list-scroll -- Only the non-native workspace layout (Android and the fallback) renders this sidebar, which has no native header to register with. */}
792794
<AnimatedLegendList
793795
itemLayoutAnimation={THREAD_SIDEBAR_ROW_LAYOUT}
794796
data={listItems}

‎apps/mobile/src/features/threads/ThreadPullRequestsSheet.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export function ThreadPullRequestsSheet(
5050

5151
const content = (
5252
<View className="flex-1 android:bg-sheet-solid ios:bg-screen">
53+
{/* oxlint-disable-next-line t3code/require-registered-list-scroll -- Sheet content; sheets sit outside workspace columns and keep their own header handling. */}
5354
<LegendList
5455
data={lines}
5556
keyExtractor={linkedPullRequestKey}

‎apps/mobile/src/features/threads/ThreadSettingsSheet.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,7 @@ function ThreadSettingsMainContent(props: {
10091009
};
10101010

10111011
return (
1012+
// oxlint-disable-next-line t3code/require-registered-list-scroll -- Sheet content; sheets sit outside workspace columns and keep their own header handling.
10121013
<AnimatedLegendList
10131014
alwaysBounceVertical
10141015
automaticallyAdjustsScrollIndicatorInsets

‎apps/mobile/src/features/threads/thread-work-log.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,7 @@ function ThreadWorkGroupList(props: {
705705

706706
return (
707707
<View style={{ height, overflow: "hidden" }}>
708+
{/* oxlint-disable-next-line t3code/require-registered-list-scroll -- Nested in a fixed-height card inside the thread feed, which owns the header's scroll view. */}
708709
<AnimatedLegendList
709710
ref={listRef}
710711
data={props.activities}

0 commit comments

Comments
 (0)