From 7eb8ccae48b0cc18a9dcaa9c3626a02df8e6d919 Mon Sep 17 00:00:00 2001
From: JustZvan <justzvan@justzvan.xyz>
Date: Fri, 6 Feb 2026 13:22:33 +0100
Subject: feat: initial commit!

---
 app/(tabs)/_layout.tsx | 188 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 app/(tabs)/_layout.tsx

(limited to 'app/(tabs)/_layout.tsx')

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>
+  );
+}
-- 
cgit v1.2.3

