From 8a6b7f5288e00499240b8d80b88a892ecb051d1c Mon Sep 17 00:00:00 2001 From: Vishakh Date: Mon, 17 Nov 2025 08:31:27 -0500 Subject: [PATCH 1/8] Delay loading wallet and subscription stuff --- app/components/AuthProvider.tsx | 91 ++++++++++++++++++++++++--------- app/page.tsx | 24 ++++++++- 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/app/components/AuthProvider.tsx b/app/components/AuthProvider.tsx index 48c0f28..a375334 100644 --- a/app/components/AuthProvider.tsx +++ b/app/components/AuthProvider.tsx @@ -20,6 +20,8 @@ interface AuthContextType { checkingSubscription: boolean; subscriptionData: SubscriptionData | null; refreshSubscription: () => Promise; + initializeDynamic: () => void; + isDynamicInitialized: boolean; } const AuthContext = createContext({ @@ -29,17 +31,18 @@ const AuthContext = createContext({ checkingSubscription: true, subscriptionData: null, refreshSubscription: async () => {}, + initializeDynamic: () => {}, + isDynamicInitialized: false, }); export const useAuth = () => useContext(AuthContext); // Inner component to sync Dynamic context with Auth context +// NOTE: No longer automatically checks subscription - must be triggered manually function AuthStateSync({ onAuthStateChange, - onCheckSubscription, }: { onAuthStateChange: (isAuth: boolean, user: any) => void; - onCheckSubscription: (walletAddress: string) => Promise; }) { const { user: dynamicUser } = useDynamicContext(); @@ -54,18 +57,7 @@ function AuthStateSync({ // Sync Dynamic's auth state with our context onAuthStateChange(isAuth, dynamicUser); - - // If we have a user with wallet address, check subscription - if (dynamicUser) { - const walletAddress = dynamicUser?.verifiedCredentials?.[0]?.address; - if (walletAddress) { - console.log('[AuthStateSync] Checking subscription for wallet:', walletAddress); - onCheckSubscription(walletAddress); - } else { - console.warn('[AuthStateSync] User exists but no wallet address found'); - } - } - }, [dynamicUser, onAuthStateChange, onCheckSubscription]); + }, [dynamicUser, onAuthStateChange]); return null; } @@ -75,7 +67,8 @@ export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [hasActiveSubscription, setHasActiveSubscription] = useState(false); const [subscriptionData, setSubscriptionData] = useState(null); - const [checkingSubscription, setCheckingSubscription] = useState(true); + const [checkingSubscription, setCheckingSubscription] = useState(false); // Changed default to false + const [isDynamicInitialized, setIsDynamicInitialized] = useState(false); // If environment ID is not set, render without Dynamic (useful for CI/CD builds) const environmentId = process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID; @@ -128,12 +121,30 @@ export function AuthProvider({ children }: { children: ReactNode }) { } }; - // On mount, if no user is authenticated, stop checking subscription - useEffect(() => { - if (!isAuthenticated && !user) { - setCheckingSubscription(false); + // Initialize Dynamic and trigger subscription check + const initializeDynamic = useCallback(() => { + if (!isDynamicEnabled) { + console.log('[AuthProvider] Dynamic not enabled (missing environment ID)'); + return; + } + + if (isDynamicInitialized) { + console.log('[AuthProvider] Dynamic already initialized'); + return; } - }, [isAuthenticated, user]); + + console.log('[AuthProvider] Initializing Dynamic...'); + setIsDynamicInitialized(true); + + // If we already have a user (from previous session), check subscription + if (user) { + const walletAddress = user?.verifiedCredentials?.[0]?.address; + if (walletAddress) { + console.log('[AuthProvider] Checking subscription for existing user:', walletAddress); + checkSubscription(walletAddress); + } + } + }, [isDynamicEnabled, isDynamicInitialized, user, checkSubscription]); const handleAuthStateChange = useCallback((isAuth: boolean, dynamicUser: any) => { console.log('[AuthProvider] Auth state changed:', { isAuth, hasUser: !!dynamicUser, userAddress: dynamicUser?.verifiedCredentials?.[0]?.address }); @@ -145,8 +156,15 @@ export function AuthProvider({ children }: { children: ReactNode }) { setHasActiveSubscription(false); setSubscriptionData(null); setCheckingSubscription(false); + } else if (dynamicUser && isDynamicInitialized) { + // User logged in and Dynamic is initialized, check subscription + const walletAddress = dynamicUser?.verifiedCredentials?.[0]?.address; + if (walletAddress) { + console.log('[AuthProvider] User logged in, checking subscription:', walletAddress); + checkSubscription(walletAddress); + } } - }, []); + }, [isDynamicInitialized, checkSubscription]); // If Dynamic is not enabled (no environment ID), render children with default auth context if (!isDynamicEnabled) { @@ -159,6 +177,28 @@ export function AuthProvider({ children }: { children: ReactNode }) { checkingSubscription: false, subscriptionData: null, refreshSubscription: async () => {}, + initializeDynamic: () => {}, + isDynamicInitialized: false, + }} + > + {children} + + ); + } + + // Render without Dynamic until explicitly initialized + if (!isDynamicInitialized) { + return ( + {children} @@ -184,7 +224,6 @@ export function AuthProvider({ children }: { children: ReactNode }) { > {children} @@ -203,10 +244,10 @@ export function AuthProvider({ children }: { children: ReactNode }) { } export function AuthButton() { - const environmentId = process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID; + const { isDynamicInitialized } = useAuth(); - // Don't render widget if Dynamic is not enabled - if (!environmentId) { + // Don't render widget if Dynamic is not initialized yet + if (!isDynamicInitialized) { return null; } diff --git a/app/page.tsx b/app/page.tsx index 13f774f..0007a6b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -205,7 +205,7 @@ function MainContent() { const { genotypeData, isUploaded, setOnDataLoadedCallback } = useGenotype(); const { setOnResultsLoadedCallback, addResult, addResultsBatch, hasResult } = useResults(); const resultsContext = useResults(); - const { isAuthenticated, hasActiveSubscription, subscriptionData, checkingSubscription, user } = useAuth(); + const { isAuthenticated, hasActiveSubscription, subscriptionData, checkingSubscription, user, initializeDynamic, isDynamicInitialized } = useAuth(); // Track client-side mounting to prevent hydration errors const [mounted, setMounted] = useState(false); @@ -236,6 +236,15 @@ function MainContent() { localStorage.setItem('activeTab', activeTab); } }, [activeTab]); + + // Initialize Dynamic.xyz when Premium tab is accessed + useEffect(() => { + if (activeTab === 'premium' && !isDynamicInitialized) { + console.log('[MainContent] Premium tab accessed, initializing Dynamic...'); + initializeDynamic(); + } + }, [activeTab, isDynamicInitialized, initializeDynamic]); + const [filters, setFilters] = useState(defaultFilters); const [debouncedSearch, setDebouncedSearch] = useState(defaultFilters.search); const scrollPositionRef = useRef(0); @@ -1091,6 +1100,17 @@ function MainContent() { ) : ( /* Premium Tab - 3 Features with LLM Chat Primary */ <> + {/* Show loading state while Dynamic initializes */} + {!isDynamicInitialized ? ( +
+
+
+ Loading premium features... +
+
+
+ ) : ( + <> {/* Account & Subscription Compact Header */}
@@ -1287,6 +1307,8 @@ function MainContent() {
+ )} + )}