From 940d4872e33daeb5c2c4a2c8cbf5238081e0800e Mon Sep 17 00:00:00 2001 From: jtrzupek Date: Mon, 8 Jun 2026 10:18:48 +0200 Subject: [PATCH] =?UTF-8?q?fix(mobile):=20removeClippedSubviews=3Dfalse=20?= =?UTF-8?q?on=20grids=20=E2=80=94=20stop=20thumbnails=20vanishing=20on=20s?= =?UTF-8?q?croll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Android FlatList defaults removeClippedSubviews=true, which detaches off-viewport subviews; expo-image frequently fails to re-render them when they scroll back in → blank thumbnails (bug-report f181d382 2026-06-07, recurring). Disable on all heavy image grids: scene grids (Scenes/Site/Studio/Tag/Performer) + movie poster grids. Co-Authored-By: Claude Opus 4.8 --- mobile/src/screens/MoviesScreen.tsx | 3 +++ mobile/src/screens/PerformerScenesScreen.tsx | 5 +++++ mobile/src/screens/ScenesScreen.tsx | 3 +++ mobile/src/screens/SiteScenesScreen.tsx | 1 + mobile/src/screens/StudioScenesScreen.tsx | 1 + mobile/src/screens/TagScenesScreen.tsx | 1 + 6 files changed, 14 insertions(+) diff --git a/mobile/src/screens/MoviesScreen.tsx b/mobile/src/screens/MoviesScreen.tsx index c4e16d9..89a16ed 100644 --- a/mobile/src/screens/MoviesScreen.tsx +++ b/mobile/src/screens/MoviesScreen.tsx @@ -133,6 +133,9 @@ export function MoviesScreen() { data={items} numColumns={NUM_COLS} keyExtractor={(m) => m.id} + // Android removeClippedSubviews=true blankuje plakaty po scrollu (expo-image + // nie re-renderuje odpiętych) — ten sam bug co "znikające miniaturki" scen. + removeClippedSubviews={false} renderItem={({ item }) => ( s.id} numColumns={2} + // Android default removeClippedSubviews=true odpina miniaturki poza + // viewportem i expo-image często nie re-renderuje ich po powrocie → + // "miniaturki znikają przy scrollu" (bug-report f181d382 2026-06-07). + removeClippedSubviews={false} renderItem={({ item }) => ( )} @@ -347,6 +351,7 @@ export function PerformerScenesScreen() { key="movies-list" data={movies} numColumns={MOVIE_COLS} + removeClippedSubviews={false} keyExtractor={(m) => m.id} renderItem={({ item }) => { // Defensive: jeśli backend kiedyś wyśle pojedynczy malformed movie, diff --git a/mobile/src/screens/ScenesScreen.tsx b/mobile/src/screens/ScenesScreen.tsx index 19984d3..51109fa 100644 --- a/mobile/src/screens/ScenesScreen.tsx +++ b/mobile/src/screens/ScenesScreen.tsx @@ -129,6 +129,9 @@ export function ScenesScreen() { data={items} keyExtractor={(s) => s.id} numColumns={2} + // Android removeClippedSubviews=true (default) blankuje miniaturki po scrollu — + // expo-image nie re-renderuje odpiętych subview. Bug-report "znikają miniaturki". + removeClippedSubviews={false} renderItem={({ item }) => } columnWrapperStyle={styles.gridRow} ListHeaderComponent={!debouncedQ && activeCount === 0 ? : null} diff --git a/mobile/src/screens/SiteScenesScreen.tsx b/mobile/src/screens/SiteScenesScreen.tsx index 8969329..4b230d3 100644 --- a/mobile/src/screens/SiteScenesScreen.tsx +++ b/mobile/src/screens/SiteScenesScreen.tsx @@ -113,6 +113,7 @@ export function SiteScenesScreen() { data={items} keyExtractor={(s) => s.id} numColumns={2} + removeClippedSubviews={false} renderItem={({ item }) => } columnWrapperStyle={styles.gridRow} refreshing={isRefetching} diff --git a/mobile/src/screens/StudioScenesScreen.tsx b/mobile/src/screens/StudioScenesScreen.tsx index cb3ce06..8f5b8ba 100644 --- a/mobile/src/screens/StudioScenesScreen.tsx +++ b/mobile/src/screens/StudioScenesScreen.tsx @@ -138,6 +138,7 @@ export function StudioScenesScreen() { data={sortedItems} keyExtractor={(s) => s.id} numColumns={2} + removeClippedSubviews={false} renderItem={({ item }) => ( )} diff --git a/mobile/src/screens/TagScenesScreen.tsx b/mobile/src/screens/TagScenesScreen.tsx index ae953ff..61a80f0 100644 --- a/mobile/src/screens/TagScenesScreen.tsx +++ b/mobile/src/screens/TagScenesScreen.tsx @@ -50,6 +50,7 @@ export function TagScenesScreen() { data={data?.items ?? []} keyExtractor={(s) => s.id} numColumns={2} + removeClippedSubviews={false} renderItem={({ item }) => } columnWrapperStyle={styles.gridRow} refreshing={isRefetching}