mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-18 13:49:40 +02:00
- Add uload project with apps/web structure
- Reorganize from flat to monorepo structure
- Remove PocketBase binary and local data
- Update to pnpm and @uload/web namespace
- Add picture project to monorepo
- Remove embedded git repository
- Unify all package names to @{project}/{app} schema:
- @maerchenzauber/* (was @storyteller/*)
- @manacore/* (was manacore-*, manacore)
- @manadeck/* (was web, backend, manadeck)
- @memoro/* (was memoro-web, landing, memoro)
- @picture/* (already unified)
- @uload/web
- Add convenient dev scripts for all apps:
- pnpm dev:{project}:web
- pnpm dev:{project}:landing
- pnpm dev:{project}:mobile
- pnpm dev:{project}:backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
import '../global.css';
|
||
|
||
import { useEffect, useState } from 'react';
|
||
import { Platform, View, AppState } from 'react-native';
|
||
import { Stack, useRouter, useSegments } from 'expo-router';
|
||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||
import { AuthProvider, useAuth } from '~/contexts/AuthContext';
|
||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||
import { preloadModels } from '~/store/modelStore';
|
||
import { ErrorBoundary } from '~/components/ErrorBoundary';
|
||
import { ThemeProvider } from '~/contexts/ThemeContext';
|
||
import { logger } from '~/utils/logger';
|
||
|
||
export const unstable_settings = {
|
||
// Ensure that reloading on `/modal` keeps a back button present.
|
||
initialRouteName: '(tabs)',
|
||
};
|
||
|
||
function RootLayoutNav() {
|
||
const { user, loading } = useAuth();
|
||
const segments = useSegments();
|
||
const router = useRouter();
|
||
const [isNavigating, setIsNavigating] = useState(false);
|
||
|
||
useEffect(() => {
|
||
// Prevent navigation during loading or if already navigating
|
||
if (loading || isNavigating) {
|
||
console.log('⏳ Skipping navigation:', { loading, isNavigating });
|
||
return;
|
||
}
|
||
|
||
const inAuthGroup = segments[0] === '(auth)';
|
||
|
||
console.log('🔄 Auth routing check:', {
|
||
hasUser: !!user,
|
||
userId: user?.id,
|
||
currentSegment: segments[0],
|
||
inAuthGroup
|
||
});
|
||
|
||
// Use requestAnimationFrame to defer navigation and prevent timing issues
|
||
const navigationTimeout = requestAnimationFrame(() => {
|
||
try {
|
||
if (!user && !inAuthGroup) {
|
||
// Redirect to login if not authenticated
|
||
console.log('🔒 Redirecting to login...');
|
||
setIsNavigating(true);
|
||
router.replace('/(auth)/login');
|
||
setIsNavigating(false);
|
||
} else if (user && inAuthGroup) {
|
||
// Redirect to main app if authenticated
|
||
console.log('✅ Redirecting to tabs...');
|
||
setIsNavigating(true);
|
||
router.replace('/(tabs)');
|
||
setIsNavigating(false);
|
||
|
||
// TEMPORARY FIX: Disabled preload to debug crash
|
||
// TODO: Re-enable with proper error handling after navigation completes
|
||
// setTimeout(() => {
|
||
// preloadModels().catch(err => {
|
||
// logger.error('Failed to preload models:', err);
|
||
// });
|
||
// }, 1000);
|
||
} else {
|
||
console.log('ℹ️ No navigation needed');
|
||
}
|
||
} catch (error) {
|
||
logger.error('Navigation error:', error);
|
||
setIsNavigating(false);
|
||
}
|
||
});
|
||
|
||
return () => {
|
||
cancelAnimationFrame(navigationTimeout);
|
||
};
|
||
}, [user, segments, loading, isNavigating]);
|
||
|
||
return (
|
||
<Stack>
|
||
<Stack.Screen name="(auth)/login" options={{ headerShown: false }} />
|
||
<Stack.Screen name="(auth)/register" options={{ headerShown: false }} />
|
||
<Stack.Screen name="(auth)/reset-password" options={{ headerShown: false }} />
|
||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
|
||
</Stack>
|
||
);
|
||
}
|
||
|
||
export default function RootLayout() {
|
||
// For web, ensure the app fills the viewport
|
||
if (Platform.OS === 'web') {
|
||
return (
|
||
<GestureHandlerRootView style={{ flex: 1 }}>
|
||
<ThemeProvider>
|
||
<ErrorBoundary>
|
||
<View style={{ flex: 1, backgroundColor: '#000000' }}>
|
||
<AuthProvider>
|
||
<RootLayoutNav />
|
||
</AuthProvider>
|
||
</View>
|
||
</ErrorBoundary>
|
||
</ThemeProvider>
|
||
</GestureHandlerRootView>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<GestureHandlerRootView style={{ flex: 1 }}>
|
||
<ThemeProvider>
|
||
<ErrorBoundary>
|
||
<SafeAreaProvider>
|
||
<AuthProvider>
|
||
<RootLayoutNav />
|
||
</AuthProvider>
|
||
</SafeAreaProvider>
|
||
</ErrorBoundary>
|
||
</ThemeProvider>
|
||
</GestureHandlerRootView>
|
||
);
|
||
}
|