import { Component, useEffect, useState } from 'react'; import type { ReactNode } from 'react'; import { ActivityIndicator, StatusBar, StyleSheet, Text, View } from 'react-native'; import * as SplashScreen from 'expo-splash-screen'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { NavigationContainer } from '@react-navigation/native'; import { initDatabase } from './src/db/database'; import { checkRecurringDue, getSetting } from './src/db/repositories'; import { scheduleDailyReminder } from './src/utils/notifications'; import { RootNavigator } from './src/navigation'; import { colors } from './src/theme/colors'; SplashScreen.preventAutoHideAsync().catch(() => {}); /** Tangkap error render agar tidak force-close: tampilkan layar aman. */ class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean; message: string }> { state = { hasError: false, message: '' }; static getDerivedStateFromError(e: unknown) { return { hasError: true, message: e instanceof Error ? e.message : String(e) }; } render() { if (this.state.hasError) { return ( Terjadi kesalahan 😢 {this.state.message} ); } return this.props.children; } } export default function App() { const [ready, setReady] = useState(false); const [error, setError] = useState(null); const [initialRoute, setInitialRoute] = useState<'Main' | 'Onboarding'>('Onboarding'); useEffect(() => { initDatabase() .then(async () => { try { // Buat transaksi berulang yang jatuh tempo hari ini await checkRecurringDue(); } catch { // jangan sampai mengganggu startup } const onboarded = await getSetting('onboarded'); const userName = await getSetting('user_name'); setInitialRoute(onboarded === '1' && userName ? 'Main' : 'Onboarding'); // Reschedule pengingat harian kalau aktif try { if ((await getSetting('reminder_enabled')) === '1') { const h = Number(await getSetting('reminder_hour')); await scheduleDailyReminder(Number.isFinite(h) ? h : 20, 0); } } catch { // abaikan } setReady(true); SplashScreen.hideAsync().catch(() => {}); }) .catch((e) => setError(String(e))); }, []); if (error) { return ( Terjadi kesalahan 😢 {error} ); } if (!ready) { return ( Menyiapkan Kantongku... ); } return ( ); } const styles = StyleSheet.create({ center: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.background, padding: 24, }, loadingText: { marginTop: 12, color: colors.textMuted, fontSize: 14 }, errorTitle: { fontSize: 16, fontWeight: '700', color: colors.text, marginBottom: 8 }, errorText: { color: colors.expense, fontSize: 13, textAlign: 'center' }, });