import React, { useEffect, useState, Component } from 'react'; import { View, StatusBar, Text, ScrollView } from 'react-native'; import { NavigationContainer, DarkTheme } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createStackNavigator } from '@react-navigation/stack'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { Ionicons } from '@expo/vector-icons'; import TrackPlayer, { Event, State } from 'react-native-track-player'; import { setupPlayer } from './src/audio/player'; import { useStore } from './src/store'; import HomeScreen from './src/screens/Home'; import { ArtistsScreen, AlbumsScreen } from './src/screens/Library'; import ArtistDetailScreen from './src/screens/ArtistDetail'; import AlbumDetailScreen from './src/screens/AlbumDetail'; import SearchScreen from './src/screens/Search'; import LoginScreen from './src/screens/Login'; import NowPlayingScreen from './src/screens/NowPlaying'; import PlayerBar from './src/components/PlayerBar'; // ─── ERROR BOUNDARY ─── class ErrorBoundary extends Component { state = { error: null }; static getDerivedStateFromError(e) { return { error: e }; } render() { if (this.state.error) { return ( Fehler beim Starten {this.state.error?.message || String(this.state.error)} {this.state.error?.stack} ); } return this.props.children; } } const Tab = createBottomTabNavigator(); const Stack = createStackNavigator(); function HomeTabs() { return ( ({ headerShown: false, tabBarStyle: { backgroundColor: '#1e1e1e', borderTopColor: '#2a2a2a' }, tabBarActiveTintColor: '#1db954', tabBarInactiveTintColor: '#888', tabBarIcon: ({ color, size }) => { const icons = { Home: 'home', Artists: 'person', Albums: 'disc', Search: 'search', Settings: 'settings-outline' }; return ; }, })} > ); } function RootNavigator() { const currentTrack = useStore(s => s.currentTrack); return ( {currentTrack && } ); } export default function App() { const { loadConfig } = useStore(); const [ready, setReady] = useState(false); const [initError, setInitError] = useState(null); useEffect(() => { (async () => { try { await loadConfig(); await setupPlayer(); } catch (e) { setInitError(e?.message || String(e)); } setReady(true); })(); }, []); useEffect(() => { const sub1 = TrackPlayer.addEventListener(Event.PlaybackActiveTrackChanged, e => { if (e.track) useStore.getState().setCurrentTrack(e.track._song || e.track); }); const sub2 = TrackPlayer.addEventListener(Event.PlaybackState, e => { useStore.getState().setIsPlaying(e.state === State.Playing); }); return () => { sub1.remove(); sub2.remove(); }; }, []); if (!ready) return ( ); if (initError) return ( Init-Fehler {initError} ); return ( ); }