From a9c9a1ca6efdfc83ae7a12a0c1f2a05f15ef9138 Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Thu, 20 Aug 2026 23:29:10 +0900 Subject: [PATCH] fix(mobile): prevent supabaseUrl crash on startup with fallback auth config --- apps/mobile-rn/src/lib/auth-context.tsx | 38 +++++++++++++++++-------- apps/mobile-rn/src/lib/supabase.ts | 10 +++++-- site/src/hooks/useClientOS.ts | 2 +- site/src/sections/Download.tsx | 2 +- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/apps/mobile-rn/src/lib/auth-context.tsx b/apps/mobile-rn/src/lib/auth-context.tsx index 733366f..0baf0e9 100644 --- a/apps/mobile-rn/src/lib/auth-context.tsx +++ b/apps/mobile-rn/src/lib/auth-context.tsx @@ -2,7 +2,7 @@ import { createContext, useContext, useEffect, useState, useCallback } from 'react' import type { ReactNode } from 'react' import type { User, Session } from '@supabase/supabase-js' -import { supabase } from './supabase' +import { supabase, isSupabaseConfigured } from './supabase' interface AuthContextValue { user: User | null @@ -14,28 +14,41 @@ interface AuthContextValue { const AuthContext = createContext({ user: null, session: null, - loading: true, + loading: false, devBypass: () => {}, }) export function AuthProvider({ children }: { children: ReactNode }): React.ReactElement { const [user, setUser] = useState(null) const [session, setSession] = useState(null) - const [loading, setLoading] = useState(true) + const [loading, setLoading] = useState(false) useEffect(() => { - supabase.auth.getSession().then(({ data: { session: s } }) => { - setSession(s) - setUser(s?.user ?? null) + if (!isSupabaseConfigured()) { setLoading(false) - }) + return + } - const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, s) => { - setSession(s) - setUser(s?.user ?? null) - }) + try { + supabase.auth.getSession() + .then(({ data: { session: s } }) => { + setSession(s) + setUser(s?.user ?? null) + setLoading(false) + }) + .catch(() => { + setLoading(false) + }) - return () => subscription.unsubscribe() + const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, s) => { + setSession(s) + setUser(s?.user ?? null) + }) + + return () => subscription?.unsubscribe?.() + } catch { + setLoading(false) + } }, []) const devBypass = useCallback(() => { @@ -53,3 +66,4 @@ export function AuthProvider({ children }: { children: ReactNode }): React.React export function useAuth(): AuthContextValue { return useContext(AuthContext) } + diff --git a/apps/mobile-rn/src/lib/supabase.ts b/apps/mobile-rn/src/lib/supabase.ts index 08bce72..a32c271 100644 --- a/apps/mobile-rn/src/lib/supabase.ts +++ b/apps/mobile-rn/src/lib/supabase.ts @@ -3,13 +3,16 @@ import 'react-native-url-polyfill/auto' import AsyncStorage from '@react-native-async-storage/async-storage' import { createClient, type SupabaseClient } from '@supabase/supabase-js' -// TODO: move to env config or supabase-config.ts +// Fallback dummy credentials to prevent createClient crash when unconfigured +const FALLBACK_URL = 'https://auth.d3ro.chanpaca.net' +const FALLBACK_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.dummy_anon_key' + const SUPABASE_URL = '' const SUPABASE_ANON_KEY = '' export const supabase: SupabaseClient = createClient( - SUPABASE_URL, - SUPABASE_ANON_KEY, + SUPABASE_URL || FALLBACK_URL, + SUPABASE_ANON_KEY || FALLBACK_ANON_KEY, { auth: { storage: AsyncStorage, @@ -23,3 +26,4 @@ export const supabase: SupabaseClient = createClient( export function isSupabaseConfigured(): boolean { return SUPABASE_URL.length > 0 && SUPABASE_ANON_KEY.length > 0 } + diff --git a/site/src/hooks/useClientOS.ts b/site/src/hooks/useClientOS.ts index 57cf2fb..e921944 100644 --- a/site/src/hooks/useClientOS.ts +++ b/site/src/hooks/useClientOS.ts @@ -20,7 +20,7 @@ export const OS_CONFIGS: Record = { os: 'android', osName: 'Android', isMobile: true, - downloadUrl: 'https://git.chanpaca.net/attachments/5220bdb9-e8ce-4d6a-b016-dab08dd756b8', + downloadUrl: 'https://git.chanpaca.net/attachments/0b015367-dd8b-488c-8cc0-4db413b51792', downloadFilename: 'd3ro-voice-v1.0.0-signed.apk', badgeText: 'ANDROID APK v1.0.0', buttonLabelKo: 'Android용 무료 다운로드 (APK)', diff --git a/site/src/sections/Download.tsx b/site/src/sections/Download.tsx index 052f8da..23d4877 100644 --- a/site/src/sections/Download.tsx +++ b/site/src/sections/Download.tsx @@ -277,7 +277,7 @@ export function Download() {