From ccc7922737aebfa95fbfe6e36ce2abab477a0238 Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Mon, 16 Mar 2026 15:14:32 -0400 Subject: [PATCH] refactor(native): centralize navigation header configuration into dedicated stack components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the `useTabScreenOptions` hook (and its `.android` variant) with a `TabStack` component that encapsulates all tab-level header styling in one place. Introduce `AuthStackHeader` and `DetailStackHeader` components to own header configuration for auth and detail screens respectively, removing scattered `Stack.Screen options` overrides from individual screen files. - Delete `use-tab-screen-options.tsx` and `use-tab-screen-options.android.tsx`; all four tab layouts now render `` instead of manually composing ``. - Add `AuthStackHeader` and swap every `` inside auth screens for it; strip the now-redundant header option overrides from the auth `_layout`. - Add `DetailStackHeader` and remove the hardcoded `headerTransparent`/`headerTintColor`/`headerBackButtonDisplayMode` options from the title and person detail routes in `_layout.tsx`. - Replace remaining `Stack.Screen options={{ title }}` patterns in non-tab screens (`change-password`, `+not-found`) with the `Stack.Screen.Title` helper. - Refactor the search screen to use `Stack.Header`, `Stack.Screen.Title`, and `Stack.SearchBar` instead of an inline `Stack.Screen options` object; add `placement` and `allowToolbarIntegration` for the iOS integrated search bar. - Add `browseTitleIds` server procedure and extend `explore` / `discover` procedures; add corresponding schema fields in `@sofa/api`. --- apps/native/src/app/(auth)/_layout.tsx | 11 +- apps/native/src/app/(auth)/login.tsx | 5 +- apps/native/src/app/(auth)/register.tsx | 7 +- apps/native/src/app/(auth)/server-url.tsx | 5 +- .../src/app/(tabs)/(explore)/_layout.tsx | 5 +- .../native/src/app/(tabs)/(explore)/index.tsx | 2 - apps/native/src/app/(tabs)/(home)/_layout.tsx | 5 +- apps/native/src/app/(tabs)/(home)/index.tsx | 3 +- .../src/app/(tabs)/(search)/_layout.tsx | 9 +- apps/native/src/app/(tabs)/(search)/index.tsx | 27 +++-- .../src/app/(tabs)/(settings)/_layout.tsx | 5 +- .../src/app/(tabs)/(settings)/index.tsx | 4 +- apps/native/src/app/+not-found.tsx | 2 +- apps/native/src/app/_layout.tsx | 10 -- apps/native/src/app/change-password.tsx | 2 +- apps/native/src/app/person/[id].tsx | 43 ++------ apps/native/src/app/title/[id].tsx | 57 ++++------ .../dashboard/continue-watching-card.tsx | 2 +- .../explore/filterable-title-row.tsx | 2 + .../components/explore/hero-banner.ios.tsx | 21 +++- .../src/components/explore/hero-banner.tsx | 21 +++- .../navigation/auth-stack-header.tsx | 22 ++++ .../navigation/detail-stack-header.tsx | 14 +++ .../navigation/native-tab-bar.android.tsx | 22 +++- .../components/navigation/native-tab-bar.tsx | 26 ++++- .../src/components/navigation/tab-stack.tsx | 101 ++++++++++++++++++ apps/native/src/components/ui/poster-card.tsx | 21 ++-- .../hooks/use-tab-screen-options.android.tsx | 29 ----- .../src/hooks/use-tab-screen-options.tsx | 45 -------- .../src/orpc/procedures/browse-title-ids.ts | 35 ++++++ apps/server/src/orpc/procedures/discover.ts | 5 + apps/server/src/orpc/procedures/explore.ts | 32 ++++-- packages/api/src/schemas.ts | 8 ++ 33 files changed, 367 insertions(+), 241 deletions(-) create mode 100644 apps/native/src/components/navigation/auth-stack-header.tsx create mode 100644 apps/native/src/components/navigation/detail-stack-header.tsx create mode 100644 apps/native/src/components/navigation/tab-stack.tsx delete mode 100644 apps/native/src/hooks/use-tab-screen-options.android.tsx delete mode 100644 apps/native/src/hooks/use-tab-screen-options.tsx create mode 100644 apps/server/src/orpc/procedures/browse-title-ids.ts diff --git a/apps/native/src/app/(auth)/_layout.tsx b/apps/native/src/app/(auth)/_layout.tsx index 27cfb9d..59ac4f6 100644 --- a/apps/native/src/app/(auth)/_layout.tsx +++ b/apps/native/src/app/(auth)/_layout.tsx @@ -1,5 +1,5 @@ import { Stack } from "expo-router"; -import { useCSSVariable, useResolveClassNames } from "uniwind"; +import { useResolveClassNames } from "uniwind"; import { hasStoredServerUrl } from "@/lib/server-url"; export const unstable_settings = { @@ -10,20 +10,11 @@ export const unstable_settings = { }; export default function AuthLayout() { - const headerTitleStyle = useResolveClassNames( - "font-display text-base text-foreground", - ); const contentStyle = useResolveClassNames("bg-background"); - const tintColor = useCSSVariable("--color-primary") as string; return ( , - headerTintColor: tintColor, contentStyle, animation: "fade", }} diff --git a/apps/native/src/app/(auth)/login.tsx b/apps/native/src/app/(auth)/login.tsx index 6deb11d..b97f3c4 100644 --- a/apps/native/src/app/(auth)/login.tsx +++ b/apps/native/src/app/(auth)/login.tsx @@ -1,11 +1,12 @@ import { useForm } from "@tanstack/react-form"; import { useQuery } from "@tanstack/react-query"; -import { Link, Stack } from "expo-router"; +import { Link } from "expo-router"; import { useRef } from "react"; import { Alert, Pressable, type TextInput, View } from "react-native"; import Animated, { FadeIn, FadeInDown } from "react-native-reanimated"; import { z } from "zod"; import { AuthScreen } from "@/components/auth-screen"; +import { AuthStackHeader } from "@/components/navigation/auth-stack-header"; import { Button, ButtonLabel } from "@/components/ui/button"; import { Spinner } from "@/components/ui/spinner"; import { Text } from "@/components/ui/text"; @@ -73,7 +74,7 @@ export default function LoginScreen() { return ( - + {showOidc && ( - +