diff --git a/app/(auth)/(tabs)/(libraries)/_layout.tsx b/app/(auth)/(tabs)/(libraries)/_layout.tsx index acc7f8173..ed31b438f 100644 --- a/app/(auth)/(tabs)/(libraries)/_layout.tsx +++ b/app/(auth)/(tabs)/(libraries)/_layout.tsx @@ -166,7 +166,7 @@ export default function IndexLayout() { open={dropdownOpen} onOpenChange={setDropdownOpen} trigger={ - + { onPress={() => { router.push("/(auth)/downloads"); }} - className='ml-1.5' style={{ marginRight: Platform.OS === "android" ? 16 : 0 }} > { const { t } = useTranslation(); - const hasMovies = movieResults && movieResults.length > 0; - const hasTv = tvResults && tvResults.length > 0; - const hasPersons = personResults && personResults.length > 0; - if (loading) { return null; } @@ -431,22 +427,26 @@ export const TVJellyseerrSearchResults: React.FC< return ( + {/* No section requests `hasTVPreferredFocus`: the native search field + keeps focus while typing, otherwise the first result would re-grab + focus on every keystroke as results re-render. The user navigates + down to the grid manually. */} diff --git a/components/search/TVSearchPage.tsx b/components/search/TVSearchPage.tsx index ab928d845..580e8a002 100644 --- a/components/search/TVSearchPage.tsx +++ b/components/search/TVSearchPage.tsx @@ -235,10 +235,13 @@ export const TVSearchPage: React.FC = ({ module). It renders the native search bar + grid keyboard and forwards typed text into the existing query pipeline via setSearch; our own results grid renders below. */} + {/* No horizontal margin here: the native tvOS search bar centers itself + and renders a trailing "Hold to Dictate in " hint. Extra + margins squeeze the bar's width and clip that trailing hint, so let + the native view span the full width and own its own insets. */} @@ -280,13 +283,17 @@ export const TVSearchPage: React.FC = ({ {/* Library Search Results */} {isLibraryMode && !loading && ( - {sections.map((section, index) => ( + {sections.map((section) => ( = ({ removeClippedSubviews={false} getItemLayout={getItemLayout} style={{ overflow: "visible" }} - contentInset={{ - left: edgePadding, - right: edgePadding, - }} - contentOffset={{ x: -edgePadding, y: 0 }} + // Edge padding via contentContainerStyle, NOT contentInset+contentOffset. + // contentOffset only applies on initial mount; since this FlatList is + // reused across searches (stable key), a second search left the inset + // without the offset and the grid snapped flush to the left edge. contentContainerStyle={{ + paddingHorizontal: edgePadding, paddingVertical: SCALE_PADDING, }} /> diff --git a/components/video-player/controls/Controls.tv.tsx b/components/video-player/controls/Controls.tv.tsx index 5ddd4bc38..a85f62154 100644 --- a/components/video-player/controls/Controls.tv.tsx +++ b/components/video-player/controls/Controls.tv.tsx @@ -1254,7 +1254,7 @@ export const Controls: FC = ({ - {t("player.ends_at")} {getFinishTime()} + {t("player.ends_at", { time: getFinishTime() })} )} @@ -1448,7 +1448,7 @@ export const Controls: FC = ({ - {t("player.ends_at")} {getFinishTime()} + {t("player.ends_at", { time: getFinishTime() })} )}