@@ -8,7 +8,7 @@ import React, {
88} from 'react' ;
99import type { QueryObserverResult } from '@tanstack/react-query' ;
1010import { useRouter } from 'next/router' ;
11- import { useFeatureValue } from '@growthbook/growthbook-react' ;
11+ import { GrowthBookContext } from '@growthbook/growthbook-react' ;
1212import type { AnonymousUser , LoggedUser } from '../lib/user' ;
1313import { deleteAccount , logout as dispatchLogout } from '../lib/user' ;
1414import type { AccessToken , Boot , Visit } from '../lib/boot' ;
@@ -79,9 +79,12 @@ export interface AuthContextData {
7979 isGdprCovered ?: boolean ;
8080 isValidRegion ?: boolean ;
8181 isFunnel ?: boolean ;
82+ inlineLoginEnabled ?: boolean ;
8283}
8384
8485const isExtension = checkIsExtension ( ) ;
86+ const inlineLoginFeatureId = 'inline_login' ;
87+ const inlineLoginDefaultValue = false ;
8588const AuthContext = React . createContext < AuthContextData > ( null ) ;
8689export const useAuthContext = ( ) : AuthContextData => useContext ( AuthContext ) ;
8790export default AuthContext ;
@@ -159,20 +162,35 @@ export const AuthContextProvider = ({
159162 isAndroidApp,
160163} : AuthContextProviderProps ) : ReactElement => {
161164 const [ loginState , setLoginState ] = useState < LoginState | null > ( null ) ;
165+ const [ inlineLoginEnabled , setInlineLoginEnabled ] = useState < boolean > ( ) ;
166+ const inlineLoginEnabledRef = useRef < boolean > ( ) ;
162167 const endUser = user && 'providers' in user ? user : null ;
163168 const referral = user ?. referralId || user ?. referrer ;
164169 const referralOrigin = user ?. referralOrigin ;
165170 const router = useRouter ( ) ;
166171 const isFunnelRef = useRef ( ! ! router ?. pathname ?. startsWith ( webFunnelPrefix ) ) ;
172+ const growthbookContext = useContext ( GrowthBookContext ) ;
173+ const growthbook = growthbookContext ?. growthbook ;
167174 const isValidRegion = useMemo (
168175 ( ) => ! invalidPlusRegions . includes ( geo ?. region ) ,
169176 [ geo ?. region ] ,
170177 ) ;
171- // Inline-login experiment flag. Source of truth for the local default lives
172- // in `lib/featureManagement.ts` as `featureInlineLogin`. We can't import it
173- // here because `featureManagement` → `graphql/posts` → `AuthContext` would
174- // be a cycle, so the default is duplicated below; keep them in sync.
175- const isInlineLoginEnabled = useFeatureValue < boolean > ( 'inline_login' , true ) ;
178+ const evaluateInlineLogin = useCallback ( ( ) : boolean => {
179+ if ( ! isNullOrUndefined ( inlineLoginEnabledRef . current ) ) {
180+ return inlineLoginEnabledRef . current ;
181+ }
182+
183+ const isEnabled =
184+ growthbook ?. getFeatureValue (
185+ inlineLoginFeatureId ,
186+ inlineLoginDefaultValue ,
187+ ) === true ;
188+
189+ inlineLoginEnabledRef . current = isEnabled ;
190+ setInlineLoginEnabled ( isEnabled ) ;
191+
192+ return isEnabled ;
193+ } , [ growthbook ] ) ;
176194
177195 return (
178196 < AuthContext . Provider
@@ -186,6 +204,7 @@ export const AuthContextProvider = ({
186204 firstVisit : user ?. firstVisit ,
187205 trackingId : user ?. id ,
188206 shouldShowLogin : loginState !== null ,
207+ inlineLoginEnabled,
189208 showLogin : useCallback (
190209 ( { trigger, options = { } } ) => {
191210 const hasCompanion = ! ! isCompanionActivated ( ) ;
@@ -196,6 +215,7 @@ export const AuthContextProvider = ({
196215 }
197216
198217 const params = new URLSearchParams ( globalThis ?. location . search ) ;
218+ const shouldUseInlineLogin = ! isExtension && evaluateInlineLogin ( ) ;
199219
200220 setLoginState ( { ...options , trigger } ) ;
201221 if ( isExtension ) {
@@ -206,19 +226,20 @@ export const AuthContextProvider = ({
206226 params . set ( AFTER_AUTH_PARAM , window . location . pathname ) ;
207227 }
208228
229+ const onboardingPath = isExtension
230+ ? `${ onboardingUrl } ?${ params . toString ( ) } `
231+ : `/onboarding?${ params . toString ( ) } ` ;
232+
209233 // Inline login experiment: render the modal in-place instead of
210234 // redirecting to /onboarding. Extension keeps the redirect because
211235 // it has no host page to mount the modal on.
212- if ( isInlineLoginEnabled && ! isExtension ) {
236+ if ( shouldUseInlineLogin ) {
213237 return ;
214238 }
215239
216- const onboardingPath = `${ onboardingUrl } ?${ params . toString ( ) } ` ;
217- router . push (
218- isExtension ? onboardingPath : `/onboarding?${ params . toString ( ) } ` ,
219- ) ;
240+ router . push ( onboardingPath ) ;
220241 } ,
221- [ router , isInlineLoginEnabled ] ,
242+ [ evaluateInlineLogin , router ] ,
222243 ) ,
223244 closeLogin : useCallback ( ( ) => setLoginState ( null ) , [ ] ) ,
224245 loginState,
0 commit comments