From a7d3a8acc74cdc48be1a26f2bb15618a8542a39c Mon Sep 17 00:00:00 2001 From: tapframe Date: Fri, 26 Sep 2025 21:58:24 +0530 Subject: [PATCH] some fixes --- App.tsx | 24 ++++++---- src/components/icons/PluginIcon.tsx | 65 ++++++++++++++++++++++++++++ src/components/icons/ProfileIcon.tsx | 35 +++++++++++++++ src/contexts/AccountContext.tsx | 24 +++++++--- src/navigation/AppNavigator.tsx | 10 ++--- src/screens/OnboardingScreen.tsx | 8 ---- src/screens/SettingsScreen.tsx | 30 +++++++++---- 7 files changed, 158 insertions(+), 38 deletions(-) create mode 100644 src/components/icons/PluginIcon.tsx create mode 100644 src/components/icons/ProfileIcon.tsx diff --git a/App.tsx b/App.tsx index 206b593..4fe3dc6 100644 --- a/App.tsx +++ b/App.tsx @@ -35,6 +35,7 @@ import * as Sentry from '@sentry/react-native'; import UpdateService from './src/services/updateService'; import { memoryMonitorService } from './src/services/memoryMonitorService'; import { aiService } from './src/services/aiService'; +import { AccountProvider, useAccount } from './src/contexts/AccountContext'; Sentry.init({ dsn: 'https://1a58bf436454d346e5852b7bfd3c95e8@o4509536317276160.ingest.de.sentry.io/4509536317734992', @@ -143,21 +144,18 @@ const ThemedApp = () => { const shouldShowApp = isAppReady && hasCompletedOnboarding !== null; const initialRouteName = hasCompletedOnboarding ? 'MainTabs' : 'Onboarding'; - return ( - + const NavigationWithRef = () => { + const { navigationRef } = useAccount() as any; + return ( - + {!isAppReady && } {shouldShowApp && } - - {/* Update Popup */} {Platform.OS === 'ios' && ( { )} - + ); + }; + + return ( + + + + + ); } diff --git a/src/components/icons/PluginIcon.tsx b/src/components/icons/PluginIcon.tsx new file mode 100644 index 0000000..e056e0d --- /dev/null +++ b/src/components/icons/PluginIcon.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { View } from 'react-native'; +import Svg, { Path, Line } from 'react-native-svg'; + +interface PluginIconProps { + size?: number; + color?: string; +} + +const PluginIcon: React.FC = ({ size = 24, color = '#FFFFFF' }) => { + return ( + + + + + + + + + ); +}; + +export default PluginIcon; diff --git a/src/components/icons/ProfileIcon.tsx b/src/components/icons/ProfileIcon.tsx new file mode 100644 index 0000000..db5aaec --- /dev/null +++ b/src/components/icons/ProfileIcon.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { View } from 'react-native'; +import Svg, { Path } from 'react-native-svg'; + +interface ProfileIconProps { + size?: number; + color?: string; +} + +const ProfileIcon: React.FC = ({ size = 24, color = '#FFFFFF' }) => { + return ( + + + + + + + + ); +}; + +export default ProfileIcon; diff --git a/src/contexts/AccountContext.tsx b/src/contexts/AccountContext.tsx index 0359d3e..85c4cfb 100644 --- a/src/contexts/AccountContext.tsx +++ b/src/contexts/AccountContext.tsx @@ -49,20 +49,32 @@ export const AccountProvider: React.FC<{ children: React.ReactNode }> = ({ child // Auth state listener const { data: subscription } = supabase.auth.onAuthStateChange(async (_event, session) => { + // Do not block UI on auth transitions setLoading(true); try { const fullUser = session?.user ? await accountService.getCurrentUser() : null; setUser(fullUser); + // Immediately clear loading so UI can transition to MainTabs/Auth + setLoading(false); if (fullUser) { - await syncService.migrateLocalScopeToUser(); - await syncService.subscribeRealtime(); - // Pull first to hydrate local state, then push to avoid wiping server with empty local - await syncService.fullPull(); - await syncService.fullPush(); + // Run sync in background without blocking UI + setTimeout(async () => { + try { + await syncService.migrateLocalScopeToUser(); + await new Promise(r => setTimeout(r, 0)); + await syncService.subscribeRealtime(); + await new Promise(r => setTimeout(r, 0)); + await syncService.fullPull(); + await new Promise(r => setTimeout(r, 0)); + await syncService.fullPush(); + } catch (error) { + console.warn('[AccountContext] Background sync failed:', error); + } + }, 0); } else { syncService.unsubscribeRealtime(); } - } finally { + } catch (e) { setLoading(false); } }); diff --git a/src/navigation/AppNavigator.tsx b/src/navigation/AppNavigator.tsx index 7a9df57..40c6687 100644 --- a/src/navigation/AppNavigator.tsx +++ b/src/navigation/AppNavigator.tsx @@ -44,7 +44,7 @@ import ThemeScreen from '../screens/ThemeScreen'; import OnboardingScreen from '../screens/OnboardingScreen'; import AuthScreen from '../screens/AuthScreen'; import AccountManageScreen from '../screens/AccountManageScreen'; -import { AccountProvider, useAccount } from '../contexts/AccountContext'; +import { useAccount } from '../contexts/AccountContext'; import { LoadingProvider, useLoading } from '../contexts/LoadingContext'; import PluginsScreen from '../screens/PluginsScreen'; import CastMoviesScreen from '../screens/CastMoviesScreen'; @@ -1336,11 +1336,9 @@ const AppNavigator = ({ initialRouteName }: { initialRouteName?: keyof RootStack host: "https://us.i.posthog.com", }} > - - - - - + + + ); diff --git a/src/screens/OnboardingScreen.tsx b/src/screens/OnboardingScreen.tsx index 967eaea..3b445dd 100644 --- a/src/screens/OnboardingScreen.tsx +++ b/src/screens/OnboardingScreen.tsx @@ -74,14 +74,6 @@ const onboardingData: OnboardingSlide[] = [ icon: 'library-books', gradient: ['#43e97b', '#38f9d7'], }, - { - id: '5', - title: 'Plugins', - subtitle: 'Stream Sources Only', - description: 'Plugins add streaming sources to Nuvio.', - icon: 'widgets', - gradient: ['#ff9a9e', '#fad0c4'], - }, ]; const OnboardingScreen = () => { diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index 9c0022e..8cf773e 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -31,6 +31,8 @@ import { catalogService } from '../services/catalogService'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import * as Sentry from '@sentry/react-native'; import CustomAlert from '../components/CustomAlert'; +import ProfileIcon from '../components/icons/ProfileIcon'; +import PluginIcon from '../components/icons/PluginIcon'; const { width, height } = Dimensions.get('window'); const isTablet = width >= 768; @@ -91,7 +93,8 @@ const SettingsCard: React.FC = ({ children, title, isTablet = interface SettingItemProps { title: string; description?: string; - icon: keyof typeof MaterialIcons.glyphMap; + icon?: keyof typeof MaterialIcons.glyphMap; + customIcon?: React.ReactNode; renderControl?: () => React.ReactNode; isLast?: boolean; onPress?: () => void; @@ -103,6 +106,7 @@ const SettingItem: React.FC = ({ title, description, icon, + customIcon, renderControl, isLast = false, onPress, @@ -124,14 +128,22 @@ const SettingItem: React.FC = ({ > - + {customIcon ? ( + customIcon + ) : ( + + )} @@ -426,7 +438,7 @@ const SettingsScreen: React.FC = () => { } onPress={() => navigation.navigate('AccountManage')} isTablet={isTablet} /> @@ -473,7 +485,7 @@ const SettingsScreen: React.FC = () => { } renderControl={ChevronRight} onPress={() => navigation.navigate('ScraperSettings')} isTablet={isTablet}