import '@expo/metro-runtime' import { PortalProvider } from '@gorhom/portal' import { DefaultTheme, NavigationContainer } from '@react-navigation/native' import { useFonts } from 'expo-font' import * as SplashScreen from 'expo-splash-screen' import { StatusBar } from 'expo-status-bar' import moment from 'moment' import 'moment/locale/fr' import { Platform, Text, TextInput } from 'react-native' import { GestureHandlerRootView } from 'react-native-gesture-handler' import React, { setGlobal, useCallback, useEffect, useGlobal, useState } from 'reactn' import { MainStack, Routes } from './src/navigation' import { Palette } from './src/styles' import { navigationRef, reset } from './src/navigation/NavigationService' import { MenuProvider } from 'react-native-popup-menu' import initialGlobalState from './src/config/initialGlobalState' import { Inter_400Regular, Inter_400Regular_Italic, Inter_500Medium, Inter_600SemiBold, Inter_700Bold, } from '@expo-google-fonts/inter' import firebase from './src/config/firebase' import Providers from './src/providers' import { LogBox } from 'react-native' import CommentsBottomSheet from './src/components/bottomsheets/CommentsBottomSheet' import ShareQrModalContainer from './src/components/modal/ShareQrModalContainer' import AppDownloadBanner from './src/components/AppDownloadBanner' import './src/utils/Sheet' console.disableYellowBox = true console.reportErrorsAsExceptions = false moment.locale('fr') // Keep typography stable regardless of the user's system font scaling on mobile if (Platform.OS !== 'web') { if (Text.defaultProps == null) { Text.defaultProps = {} } if (TextInput.defaultProps == null) { TextInput.defaultProps = {} } Text.defaultProps.allowFontScaling = false TextInput.defaultProps.allowFontScaling = false } setGlobal(initialGlobalState) SplashScreen.preventAutoHideAsync() const App = () => { const [, setCurrentUID] = useGlobal('currentUID') const [, setCurrentUserRoles] = useGlobal('currentUserRoles') const [appIsReady, setAppIsReady] = useState(false) const [isInitializing, setInitializing] = useState(true) const routeNameRef = React.useRef(null) const syncActiveRoute = useCallback(() => { const currentRoute = navigationRef.current?.getCurrentRoute() const currentName = currentRoute?.name ?? null if (routeNameRef.current !== currentName) { routeNameRef.current = currentName setGlobal({ activeRouteName: currentName }) } }, [setGlobal]) const handleNavigationReady = useCallback(() => { syncActiveRoute() }, [syncActiveRoute]) const handleNavigationStateChange = useCallback(() => { syncActiveRoute() }, [syncActiveRoute]) const [loaded] = useFonts({ NewYorkSemibold: require('./src/assets/fonts/NewYork-Semibold.ttf'), OpenSansRegular: require('./src/assets/fonts/OpenSans-Regular.ttf'), InterRegular: Inter_400Regular, InterMedium: Inter_500Medium, InterSemiBold: Inter_600SemiBold, InterBold: Inter_700Bold, InterRegularItalic: Inter_400Regular_Italic, HelveticaNeueRegular: require('./src/assets/fonts/HelveticaNeueRegular.ttf'), HelveticaNeueMedium: require('./src/assets/fonts/HelveticaNeueMedium.ttf'), HelveticaNeueBold: require('./src/assets/fonts/HelveticaNeueBold.ttf'), OwnersRegular: require('./src/assets/fonts/OwnersRegular.ttf'), OwnersMedium: require('./src/assets/fonts/OwnersMedium.ttf'), OwnersBold: require('./src/assets/fonts/OwnersBold.ttf'), }) useEffect(() => { if (loaded) { setAppIsReady(true) LogBox.ignoreAllLogs() } }, [loaded]) const onLayoutRootView = useCallback(async () => { if (appIsReady) { await SplashScreen.hideAsync() } }, [appIsReady, loaded]) useEffect(() => { const subscriber = firebase.auth().onAuthStateChanged(onAuthStateChanged) return subscriber }, []) useEffect(() => { if (Platform.OS === 'web') { const s = document.createElement('script') const isCompactViewport = window.innerWidth < 700 s.src = 'https://minuit.app/embed/report-a-problem.js' s.async = true s.setAttribute('data-project-id', 'playbackproduction') s.setAttribute('data-position', isCompactViewport ? 'custom' : 'right') s.setAttribute('data-offset', isCompactViewport ? '12' : '16') if (isCompactViewport) { s.setAttribute('data-top', '72') } s.setAttribute('data-primary-color', '#FB68A8') s.setAttribute('data-bg-primary-color', '#0E0E12') s.setAttribute('data-bg-secondary-color', '#1D1825') s.setAttribute('data-text-color', '#F3F0F5') document.body.appendChild(s) return () => { try { s.remove() } catch (_) {} } } }, []) const onAuthStateChanged = async (user) => { if (isInitializing) { setInitializing(false) } if (user?.uid) { setCurrentUID(user.uid) const idTokenResult = await user.getIdTokenResult() setCurrentUserRoles(idTokenResult?.claims?.roles || []) } else { setCurrentUID(null) setGlobal(initialGlobalState) reset({ index: 0, routes: [{ name: Routes.Splash }], }) } } if (!loaded || isInitializing) { return null } return ( <> {/* */} options?.title ? `${options?.title} - MusicLand` : 'MusicLand', }} linking={{ prefixes: ['musicland://', 'https://musicland-one.vercel.app'], config: { screens: { // Add any deep link configurations here if needed }, }, }} > {/* */} ) } export default App