fix(mobile): correct asset logo path depth and add expo-router app/ routes for web support

- Fix fatal crash: require('../../../assets/logo.png') in LoginScreen and
  WelcomeScreen resolved 3 levels above mobile/src/screens/ — outside the
  mobile/ directory. Changed to ../../assets/logo.png which correctly
  resolves to the existing mobile/assets/logo.png.
- Add expo-router app/ directory (root cause of missing welcome screen and
  web support): app/_layout.tsx, (auth)/, (tabs)/ with all route files
- Add WelcomeScreen.tsx: branded intro screen with feature highlights
- Update LoginScreen/WelcomeScreen to use useRouter() (expo-router style)
- Add react-native-web ~0.20.0 and react-dom 19.2.4 for web channel
- Add expo-device ~7.0.3 (was imported but missing from package.json)
- Remove android.googleServicesFile from app.json (file is gitignored;
  README documents how to restore it for Android FCM builds)
- Add web.bundler: metro and web.output: single to app.json
- Fix aria-hidden to explicit boolean value in WelcomeScreen

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-15 16:02:02 +00:00
parent a2de72ab72
commit 82d90b48e2
15 changed files with 467 additions and 179 deletions
+6 -137
View File
@@ -1,140 +1,9 @@
/**
* App.tsx root component for the DocuElevate mobile app.
* App.tsx legacy root component (not the active entry point).
*
* Wraps the entire app in the AuthProvider and renders either the
* authenticated tab navigator or an unauthenticated auth stack that takes
* the user through WelcomeScreen → LoginScreen.
* Push notification registration is handled by the usePushNotifications hook.
* The app uses expo-router as its entry point ("main": "expo-router/entry"
* in package.json). Routing, authentication, and navigation are all handled
* by the file-based routes in the `app/` directory.
*
* This file is retained for reference only and is not executed at runtime.
*/
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { Ionicons } from "@expo/vector-icons";
import React from "react";
import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { AuthProvider, useAuth } from "./src/context/AuthContext";
import { usePushNotifications } from "./src/hooks/usePushNotifications";
import FilesScreen from "./src/screens/FilesScreen";
import LoginScreen from "./src/screens/LoginScreen";
import ProfileScreen from "./src/screens/ProfileScreen";
import UploadScreen from "./src/screens/UploadScreen";
import WelcomeScreen, { type AuthStackParamList } from "./src/screens/WelcomeScreen";
const Tab = createBottomTabNavigator();
const AuthStack = createNativeStackNavigator<AuthStackParamList>();
function AuthNavigator() {
return (
<AuthStack.Navigator screenOptions={{ headerShown: false }}>
<AuthStack.Screen name="Welcome" component={WelcomeScreen} />
<AuthStack.Screen name="Login" component={LoginScreen} />
</AuthStack.Navigator>
);
}
function TabNavigator() {
const { isAuthenticated } = useAuth();
usePushNotifications(isAuthenticated);
return (
<Tab.Navigator
screenOptions={{
tabBarActiveTintColor: "#1e40af",
tabBarInactiveTintColor: "#9ca3af",
tabBarStyle: {
borderTopColor: "#e5e7eb",
backgroundColor: "#ffffff",
},
headerStyle: {
backgroundColor: "#1e40af",
},
headerTintColor: "#ffffff",
headerTitleStyle: {
fontWeight: "700",
},
}}
>
<Tab.Screen
name="Upload"
component={UploadScreen}
options={{
title: "Upload",
tabBarLabel: "Upload",
tabBarIcon: ({ color, size }) => (
<Ionicons name="cloud-upload-outline" size={size} color={color} />
),
headerTitle: "DocuElevate",
}}
/>
<Tab.Screen
name="Files"
component={FilesScreen}
options={{
title: "Files",
tabBarLabel: "Files",
tabBarIcon: ({ color, size }) => (
<Ionicons name="document-text-outline" size={size} color={color} />
),
headerTitle: "My Documents",
}}
/>
<Tab.Screen
name="Profile"
component={ProfileScreen}
options={{
title: "Profile",
tabBarLabel: "Profile",
tabBarIcon: ({ color, size }) => (
<Ionicons name="person-circle-outline" size={size} color={color} />
),
headerTitle: "Profile",
}}
/>
</Tab.Navigator>
);
}
function AppContent() {
const { isLoading, isAuthenticated } = useAuth();
if (isLoading) {
return (
<View style={styles.loading}>
<ActivityIndicator size="large" color="#1e40af" />
<Text style={styles.loadingText}>Loading</Text>
</View>
);
}
return (
<NavigationContainer>
{isAuthenticated ? <TabNavigator /> : <AuthNavigator />}
</NavigationContainer>
);
}
export default function App() {
return (
<SafeAreaProvider>
<AuthProvider>
<AppContent />
</AuthProvider>
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
loading: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#f9fafb",
gap: 12,
},
loadingText: {
color: "#6b7280",
fontSize: 15,
},
});