Files

157 lines
5.0 KiB
JavaScript

import React, { useEffect, useState } from 'react';
import { StatusBar } from 'expo-status-bar';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { registerRootComponent } from 'expo';
import * as WebBrowser from 'expo-web-browser';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ThemeProvider, useTheme } from './src/services/ThemeContext';
import DatabaseService from './src/services/DatabaseService';
import { getStoredUserId } from './src/services/AuthSession';
import CenteredState from './src/components/CenteredState';
import LoginScreen from './src/screens/LoginScreen';
import RegisterScreen from './src/screens/RegisterScreen';
import OnboardingScreen from './src/screens/OnboardingScreen';
import HomeScreen from './src/screens/HomeScreen';
import SearchScreen from './src/screens/SearchScreen';
import CollectionsScreen from './src/screens/AlbumsScreen';
import SettingsScreen from './src/screens/SettingsScreen';
import FolderIcon from './assets/icons/folder.svg';
import LibraryGridIcon from './assets/icons/library-grid.svg';
import SearchIcon from './assets/icons/search.svg';
WebBrowser.maybeCompleteAuthSession();
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function MainTabs({ route }) {
const { userId } = route.params || {};
const { theme } = useTheme();
const insets = useSafeAreaInsets();
const bottomInset = Math.max(insets.bottom, 8);
return (
<Tab.Navigator
id="MainTabsNavigator"
screenOptions={{
headerShown: false,
tabBarActiveTintColor: theme.tabActive,
tabBarInactiveTintColor: theme.tabInactive,
tabBarStyle: {
backgroundColor: theme.tabBar,
borderTopColor: theme.tabBarBorder,
borderTopWidth: 1,
height: 56 + bottomInset,
paddingBottom: bottomInset,
paddingTop: 6,
},
tabBarLabelStyle: { fontSize: 11, fontWeight: '500' },
}}
>
<Tab.Screen
name="Library"
component={HomeScreen}
initialParams={{ userId }}
options={{
tabBarLabel: 'Library',
tabBarIcon: ({ color }) => <LibraryGridIcon width={20} height={20} color={color} />,
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
initialParams={{ userId }}
options={{
tabBarLabel: 'Search',
tabBarIcon: ({ color }) => <SearchIcon width={20} height={20} color={color} />,
}}
/>
<Tab.Screen
name="Collections"
component={CollectionsScreen}
initialParams={{ userId }}
options={{
tabBarLabel: 'Collections',
tabBarIcon: ({ color }) => <FolderIcon width={20} height={20} color={color} />,
}}
/>
</Tab.Navigator>
);
}
// App navigation is initialized inside AppInner.
function AppInner() {
const { theme } = useTheme();
const [isReady, setIsReady] = useState(false);
const [error, setError] = useState(null);
const [bootUserId, setBootUserId] = useState(null);
const [bootChecked, setBootChecked] = useState(false);
useEffect(() => { initializeApp(); }, []);
const initializeApp = async () => {
try {
setError(null);
await DatabaseService.initDatabase();
const stored = await getStoredUserId();
setBootUserId(stored);
setBootChecked(true);
setIsReady(true);
} catch (err) {
console.error('Database initialization failed:', err);
setError(err.message || 'Database initialization failed');
setIsReady(false);
}
};
if ((!isReady || !bootChecked) && !error) {
return <CenteredState loading title="Loading app…" containerStyle={{ backgroundColor: theme.background }} />;
}
if (error) {
return (
<CenteredState
title="Unable to start app"
description={error}
actionLabel="Retry"
onAction={initializeApp}
containerStyle={{ backgroundColor: theme.background }}
/>
);
}
return (
<>
<NavigationContainer>
<Stack.Navigator
id="RootStackNavigator"
screenOptions={{ headerShown: false }}
initialRouteName={bootUserId ? 'MainTabs' : 'Login'}
>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
<Stack.Screen name="Onboarding" component={OnboardingScreen} />
<Stack.Screen
name="MainTabs"
component={MainTabs}
initialParams={bootUserId ? { userId: bootUserId } : undefined}
/>
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
<StatusBar style={theme.statusBarStyle} />
</>
);
}
function App() {
return (
<ThemeProvider>
<AppInner />
</ThemeProvider>
);
}
registerRootComponent(App);