diff options
| author | JustZvan <justzvan@justzvan.xyz> | 2026-02-06 13:22:33 +0100 |
|---|---|---|
| committer | JustZvan <justzvan@justzvan.xyz> | 2026-02-06 13:22:33 +0100 |
| commit | 7eb8ccae48b0cc18a9dcaa9c3626a02df8e6d919 (patch) | |
| tree | 57b7dd06ac9aa7053c671d916f7183e3b4fa9410 /app/(tabs)/_layout.tsx | |
feat: initial commit!
Diffstat (limited to 'app/(tabs)/_layout.tsx')
| -rw-r--r-- | app/(tabs)/_layout.tsx | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx new file mode 100644 index 0000000..6bd6527 --- /dev/null +++ b/app/(tabs)/_layout.tsx @@ -0,0 +1,188 @@ +import { Ionicons } from "@expo/vector-icons"; +import * as Notifications from "expo-notifications"; +import { Redirect, Tabs, router } from "expo-router"; +import { useEffect, useRef } from "react"; +import { View } from "react-native"; +import { useAuth } from "../../lib/auth"; +import { DeviceProvider } from "../../lib/device"; +import { t } from "../../lib/locales"; +import { + addNotificationReceivedListener, + addNotificationResponseListener, + getLastNotificationResponse, + initializeNotifications, +} from "../../lib/notifications"; +import { colors } from "../../lib/theme"; +import { LoadingScreen } from "../../lib/ui"; + +export default function TabsLayout() { + const { isLoading, isAuthenticated } = useAuth(); + const notificationListener = useRef<Notifications.EventSubscription | null>( + null + ); + const responseListener = useRef<Notifications.EventSubscription | null>(null); + + useEffect(() => { + if (!isAuthenticated) return; + + // Initialize notifications when authenticated + initializeNotifications().then(({ permissionStatus, tokenRegistered }) => { + console.log( + `Notifications initialized: permission=${permissionStatus}, tokenRegistered=${tokenRegistered}` + ); + }); + + // Set up notification listeners + notificationListener.current = addNotificationReceivedListener( + (notification) => { + console.log("Notification received:", notification); + } + ); + + responseListener.current = addNotificationResponseListener((response) => { + console.log("Notification tapped:", response); + const data = response.notification.request.content.data; + + // Navigate based on notification type + if (data?.type === "dangerous_content") { + router.push("/(tabs)/alerts"); + } else if (data?.type === "new_contact") { + // Navigate to contact detail screen with contact info + router.push({ + pathname: "/(tabs)/contact-detail", + params: { + contactName: String(data.contactName || "Unknown"), + contactIdentifier: String(data.contactIdentifier || "Not provided"), + contactType: String(data.contactType || "unknown"), + deviceName: String(data.deviceName || "Unknown Device"), + }, + }); + } + }); + + // Check if app was opened from a notification (cold start) + getLastNotificationResponse().then((response) => { + if (response) { + const data = response.notification.request.content.data; + if (data?.type === "dangerous_content") { + router.push("/(tabs)/alerts"); + } else if (data?.type === "new_contact") { + router.push({ + pathname: "/(tabs)/contact-detail", + params: { + contactName: String(data.contactName || "Unknown"), + contactIdentifier: String( + data.contactIdentifier || "Not provided" + ), + contactType: String(data.contactType || "unknown"), + deviceName: String(data.deviceName || "Unknown Device"), + }, + }); + } + } + }); + + return () => { + if (notificationListener.current) { + notificationListener.current.remove(); + } + if (responseListener.current) { + responseListener.current.remove(); + } + }; + }, [isAuthenticated]); + + if (isLoading) { + return <LoadingScreen />; + } + + if (!isAuthenticated) { + return <Redirect href="/(auth)/welcome" />; + } + + return ( + <DeviceProvider> + <View + style={{ + flex: 1, + backgroundColor: colors.background, + }} + > + <Tabs + screenOptions={{ + tabBarShowLabel: true, + tabBarActiveTintColor: colors.primary, + tabBarInactiveTintColor: colors.onSurfaceVariant, + tabBarLabelStyle: { + fontSize: 11, + fontWeight: "600", + }, + tabBarStyle: { + backgroundColor: colors.surfaceContainer, + borderTopColor: colors.outline, + }, + headerStyle: { + backgroundColor: colors.background, + borderWidth: 0, + marginBottom: 10, + }, + headerTintColor: colors.onBackground, + headerTitleStyle: { + color: colors.onBackground, + fontSize: 30, + fontWeight: "700", + }, + }} + > + <Tabs.Screen + name="index" + options={{ + title: t("home"), + tabBarIcon: ({ color, size }) => ( + <Ionicons name="home" size={size ?? 24} color={color} /> + ), + }} + /> + <Tabs.Screen + name="alerts" + options={{ + title: t("alerts"), + tabBarIcon: ({ color, size }) => ( + <Ionicons name="alert-circle" size={size ?? 24} color={color} /> + ), + }} + /> + <Tabs.Screen + name="controls" + options={{ + title: t("controls"), + tabBarIcon: ({ color, size }) => ( + <Ionicons + name="shield-checkmark" + size={size ?? 24} + color={color} + /> + ), + }} + /> + <Tabs.Screen + name="contact-detail" + options={{ + title: "Contact Details", + href: null, + }} + /> + <Tabs.Screen + name="settings" + options={{ + title: t("settings"), + tabBarIcon: ({ color, size }) => ( + <Ionicons name="settings" size={size ?? 24} color={color} /> + ), + }} + /> + </Tabs> + </View> + </DeviceProvider> + ); +} |