|
|
@ -140,83 +140,20 @@ async function fetchHttpGeoRegion(): Promise<UserGeoRegion> { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 2. Secondary fallback: ipapi.co with 2s timeout
|
|
|
|
|
|
const controller = new AbortController(); |
|
|
|
|
|
const timeoutId = setTimeout(() => controller.abort(), 2000); |
|
|
|
|
|
try { |
|
|
|
|
|
console.log("[GEO_BRIDGE_LOG] 🔄 Falling back to ipapi.co..."); |
|
|
|
|
|
const res = await fetch("https://ipapi.co/json/", { |
|
|
|
|
|
signal: controller.signal, |
|
|
|
|
|
}); |
|
|
|
|
|
clearTimeout(timeoutId); |
|
|
|
|
|
if (res?.ok) { |
|
|
|
|
|
const data = await res.json(); |
|
|
|
|
|
|
|
|
// Default fallback: preserve previously cached/stored region if present
|
|
|
|
|
|
const existing = getStoredUserGeoRegion(); |
|
|
if ( |
|
|
if ( |
|
|
data && |
|
|
|
|
|
(data.country_name || data.city || data.country_calling_code) |
|
|
|
|
|
|
|
|
existing && |
|
|
|
|
|
(existing.country || existing.phoneCode || existing.countryCode || existing.city) |
|
|
) { |
|
|
) { |
|
|
const rawPhone = data.country_calling_code |
|
|
|
|
|
? String(data.country_calling_code).trim() |
|
|
|
|
|
: ""; |
|
|
|
|
|
const phoneCode = rawPhone.startsWith("+") |
|
|
|
|
|
? rawPhone |
|
|
|
|
|
: rawPhone |
|
|
|
|
|
? `+${rawPhone}` |
|
|
|
|
|
: "+44"; |
|
|
|
|
|
const region: UserGeoRegion = { |
|
|
|
|
|
ip: data.ip, |
|
|
|
|
|
city: data.city, |
|
|
|
|
|
country: data.country_name, |
|
|
|
|
|
countryCode: data.country_code, |
|
|
|
|
|
phoneCode, |
|
|
|
|
|
}; |
|
|
|
|
|
setStoredUserGeoRegion(region); |
|
|
|
|
|
return region; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch { |
|
|
|
|
|
clearTimeout(timeoutId); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 3. Tertiary fallback: ipwho.is with 2s timeout
|
|
|
|
|
|
const secondaryController = new AbortController(); |
|
|
|
|
|
const secondaryTimeoutId = setTimeout( |
|
|
|
|
|
() => secondaryController.abort(), |
|
|
|
|
|
2000, |
|
|
|
|
|
|
|
|
console.log( |
|
|
|
|
|
"[GEO_BRIDGE_LOG] 📦 Preserving existing stored user geo region:", |
|
|
|
|
|
JSON.stringify(existing), |
|
|
); |
|
|
); |
|
|
try { |
|
|
|
|
|
console.log("[GEO_BRIDGE_LOG] 🔄 Falling back to ipwho.is..."); |
|
|
|
|
|
const res = await fetch("https://ipwho.is/", { |
|
|
|
|
|
signal: secondaryController.signal, |
|
|
|
|
|
}); |
|
|
|
|
|
clearTimeout(secondaryTimeoutId); |
|
|
|
|
|
if (res?.ok) { |
|
|
|
|
|
const data = await res.json(); |
|
|
|
|
|
if (data && (data.country || data.city || data.calling_code)) { |
|
|
|
|
|
const rawPhone = data.calling_code |
|
|
|
|
|
? String(data.calling_code).trim() |
|
|
|
|
|
: ""; |
|
|
|
|
|
const phoneCode = rawPhone.startsWith("+") |
|
|
|
|
|
? rawPhone |
|
|
|
|
|
: rawPhone |
|
|
|
|
|
? `+${rawPhone}` |
|
|
|
|
|
: "+44"; |
|
|
|
|
|
const region: UserGeoRegion = { |
|
|
|
|
|
ip: data.ip, |
|
|
|
|
|
city: data.city, |
|
|
|
|
|
country: data.country, |
|
|
|
|
|
countryCode: data.country_code, |
|
|
|
|
|
phoneCode, |
|
|
|
|
|
}; |
|
|
|
|
|
setStoredUserGeoRegion(region); |
|
|
|
|
|
return region; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch { |
|
|
|
|
|
clearTimeout(secondaryTimeoutId); |
|
|
|
|
|
|
|
|
setStoredUserGeoRegion(existing); |
|
|
|
|
|
return existing; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 4. Default fallback
|
|
|
|
|
|
console.log("[GEO_BRIDGE_LOG] ⚠️ Using default fallback region (+44)..."); |
|
|
console.log("[GEO_BRIDGE_LOG] ⚠️ Using default fallback region (+44)..."); |
|
|
const defaultRegion: UserGeoRegion = { |
|
|
const defaultRegion: UserGeoRegion = { |
|
|
phoneCode: "+44", |
|
|
phoneCode: "+44", |
|
|
@ -224,6 +161,15 @@ async function fetchHttpGeoRegion(): Promise<UserGeoRegion> { |
|
|
setStoredUserGeoRegion(defaultRegion); |
|
|
setStoredUserGeoRegion(defaultRegion); |
|
|
return defaultRegion; |
|
|
return defaultRegion; |
|
|
} catch { |
|
|
} catch { |
|
|
|
|
|
const existing = getStoredUserGeoRegion(); |
|
|
|
|
|
if ( |
|
|
|
|
|
existing && |
|
|
|
|
|
(existing.country || existing.phoneCode || existing.countryCode || existing.city) |
|
|
|
|
|
) { |
|
|
|
|
|
setStoredUserGeoRegion(existing); |
|
|
|
|
|
return existing; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const defaultRegion: UserGeoRegion = { |
|
|
const defaultRegion: UserGeoRegion = { |
|
|
phoneCode: "+44", |
|
|
phoneCode: "+44", |
|
|
}; |
|
|
}; |
|
|
@ -395,14 +341,18 @@ export function getUserGeoRegion(force = false): Promise<UserGeoRegion> { |
|
|
(Boolean(window.HabibApp?.postMessage) || |
|
|
(Boolean(window.HabibApp?.postMessage) || |
|
|
typeof (window as any).sendToFlutter === "function"); |
|
|
typeof (window as any).sendToFlutter === "function"); |
|
|
|
|
|
|
|
|
if (isFlutter) { |
|
|
|
|
|
|
|
|
const isDev = process.env.NODE_ENV === "development"; |
|
|
|
|
|
|
|
|
|
|
|
if (isFlutter && !isDev) { |
|
|
console.log( |
|
|
console.log( |
|
|
"[GEO_BRIDGE_LOG] 📱 Inside Flutter WebView detected, requesting location via Flutter bridge", |
|
|
"[GEO_BRIDGE_LOG] 📱 Inside Flutter WebView detected, requesting location via Flutter bridge", |
|
|
); |
|
|
); |
|
|
geoRegionPromise = fetchFlutterBridgeGeoRegion(); |
|
|
geoRegionPromise = fetchFlutterBridgeGeoRegion(); |
|
|
} else { |
|
|
} else { |
|
|
console.log( |
|
|
console.log( |
|
|
"[GEO_BRIDGE_LOG] 🌐 Standard browser environment detected, requesting location via HTTP", |
|
|
|
|
|
|
|
|
isDev && isFlutter |
|
|
|
|
|
? "[GEO_BRIDGE_LOG] 🛠️ Development environment (npm run dev) detected, skipping Flutter bridge action and requesting location via HTTP" |
|
|
|
|
|
: "[GEO_BRIDGE_LOG] 🌐 Standard browser environment detected, requesting location via HTTP", |
|
|
); |
|
|
); |
|
|
geoRegionPromise = fetchHttpGeoRegion(); |
|
|
geoRegionPromise = fetchHttpGeoRegion(); |
|
|
} |
|
|
} |
|
|
|