From bc3dc2694b5d15613ef610d693d18ebd904b0d56 Mon Sep 17 00:00:00 2001 From: Lars Nieuwenhuis <35393046+lnieuwenhuis@users.noreply.github.com> Date: Mon, 7 Sep 2026 09:18:17 +0200 Subject: [PATCH] fix(mobile): hide changed-files navigator and restore refresh in raw diff fallback (#9828) Co-authored-by: James --- .../src/features/review/ReviewSheet.tsx | 56 +++++++++++++++++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/apps/mobile/src/features/review/ReviewSheet.tsx b/apps/mobile/src/features/review/ReviewSheet.tsx index 9e768112fb4abcfc36d66b2a99ac49fc415cf4dd..b4f57653fb6f6e71ff4ce010d10e3305944b816a 100644 --- a/apps/mobile/src/features/review/ReviewSheet.tsx +++ b/apps/mobile/src/features/review/ReviewSheet.tsx @@ -23,6 +23,7 @@ import { FlatList, Platform, Pressable, + RefreshControl, ScrollView, type NativeSyntheticEvent, StyleSheet, @@ -399,7 +400,11 @@ export function ReviewSheet(props: ReviewSheetProps) { selectedSection, draftMessage, }); - const NativeReviewDiffView = resolveNativeReviewDiffView()!; + // Resolution returns null while Expo registers the native view (or forever + // when the binary lacks it). Rendering a null component type crashes the + // app, so callers must fall back — ThreadFeed's ReviewCommentCard does the + // same check. + const NativeReviewDiffView = resolveNativeReviewDiffView(); const nativeReviewDiffViewRef = useRef(null); const showcasedReviewDrawRef = useRef(null); // Native pull-to-refresh on the diff surface (replaces the old Refresh menu item). @@ -597,11 +602,27 @@ export function ReviewSheet(props: ReviewSheetProps) { .filter((part): part is string => Boolean(part)) .join(" · "); - // The changed-files navigator lives in the workspace inspector column — - // the single right-hand pane per route — instead of an in-screen panel. + // The changed-files navigator drives the native diff surface via + // scrollToFile, so it is only useful when that surface resolved. In raw + // fallback mode the ref is necessarily null and the raw patch neither + // scrolls nor filters — registering the navigator would present working + // controls that cannot navigate. const showChangedFilesPane = - !showConnectionNotice && selectedSection !== null && parsedDiff.kind === "files"; + !showConnectionNotice && + selectedSection !== null && + parsedDiff.kind === "files" && + NativeReviewDiffView !== null; useRegisterWorkspaceInspector(showChangedFilesPane ? renderInspector : undefined); + // Raw fallback renders the patch inline with no inspector content, so the + // pane toggle would open an empty column — hide it in exactly that case. + const showChangedFilesToggle = + panes.supportsAuxiliaryPane && + !( + !showConnectionNotice && + selectedSection !== null && + parsedDiff.kind === "files" && + NativeReviewDiffView === null + ); const listHeader = useMemo(() => { const children: ReactElement[] = []; @@ -688,7 +709,7 @@ export function ReviewSheet(props: ReviewSheetProps) { {!isAndroid && (showSectionToolbar || panes.supportsAuxiliaryPane || gitMenuAvailable) ? ( - {panes.supportsAuxiliaryPane ? ( + {showChangedFilesToggle ? ( - ) : selectedSection && parsedDiff.kind === "files" ? ( + ) : selectedSection && parsedDiff.kind === "files" && NativeReviewDiffView ? ( void handlePullToRefresh()} + /> + } > {listHeader} {!selectedSection ? ( @@ -867,6 +898,19 @@ export function ReviewSheet(props: ReviewSheetProps) { + ) : parsedDiff.kind === "files" ? ( + // The native diff surface could not be resolved on this binary; + // degrade to the raw patch instead of crashing the app. + + + Native diff view unavailable. Showing the raw patch. + + + + {selectedSection?.diff ?? ""} + + + ) : null} )} -- 2.54.0