134 | {/* Normal stack rendering for native & non-modal routes on web */}
135 |
140 |
141 | {/* Render vaul Drawer for active "modal" route on web, with snap points */}
142 | {isWeb &&
143 | state.routes.map((route, i) => {
144 | const descriptor = descriptors[route.key];
145 | const { presentation, sheetAllowedDetents, sheetGrabberVisible } =
146 | descriptor.options || {};
147 |
148 | const isModalType =
149 | presentation === "modal" ||
150 | presentation === "formSheet" ||
151 | presentation === "fullScreenModal" ||
152 | presentation === "containedModal";
153 | const isActive = i === state.index && isModalType;
154 | if (!isActive) return null;
155 |
156 | // Convert numeric detents (e.g. 0.5 => "50%") to a string
157 | // If user passes pixel or percentage strings, we'll keep them as is.
158 | const rawDetents = sheetAllowedDetents || [1];
159 |
160 | return (
161 |
{
170 | if (!open) {
171 | navigation.goBack();
172 | }
173 | }}
174 | >
175 |
176 |
183 |
187 |
188 | {/* Optional "grabber" */}
189 | {sheetGrabberVisible && (
190 |
210 | )}
211 |
212 | {/* Render the actual screen */}
213 | {descriptor.render()}
214 |
215 |
216 |
217 |
218 | );
219 | })}
220 |
221 | );
222 | }
223 |
224 | const createMyModalStack = createNavigatorFactory(MyModalStackNavigator);
225 |
226 | /**
227 | * If you're using Expo Router, wrap with `withLayoutContext`.
228 | * Otherwise, just export the createMyModalStack().Navigator as usual.
229 | */
230 | const RouterModal = withLayoutContext(createMyModalStack().Navigator);
231 |
232 | export default RouterModal;
233 |
--------------------------------------------------------------------------------
/functions/render-person-details.tsx:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import ShowMore from "@/components/ShowMore";
4 | import { Image } from "@/components/img";
5 | import { ParallaxImageWrapper } from "@/components/show-header-background";
6 | import TouchableBounce from "@/components/ui/TouchableBounce";
7 | import * as AC from "@bacons/apple-colors";
8 | import { Link, Stack } from "expo-router";
9 | import { ScrollView, Text, View } from "react-native";
10 |
11 | export async function renderPersonDetails(id: string) {
12 | // Fetch person details
13 | const [person, credits] = await Promise.all([
14 | fetch(`https://api.themoviedb.org/3/person/${id}`, {
15 | headers: {
16 | Authorization: `Bearer ${process.env.TMDB_READ_ACCESS_TOKEN}`,
17 | },
18 | }).then((res) => res.json()),
19 | fetch(`https://api.themoviedb.org/3/person/${id}/combined_credits`, {
20 | headers: {
21 | Authorization: `Bearer ${process.env.TMDB_READ_ACCESS_TOKEN}`,
22 | },
23 | }).then((res) => res.json()),
24 | ]);
25 |
26 | // Process credits into categories
27 | const allCredits = credits.cast.concat(credits.crew);
28 | const actingCredits = credits.cast;
29 | const crewCredits = credits.crew;
30 | const directingCredits = crewCredits.filter(
31 | (credit: any) => credit.job === "Director"
32 | );
33 |
34 | return (
35 |