{/* Main buttons */}
-
+
+
diff --git a/src/lib/geo-region.ts b/src/lib/geo-region.ts
index c7e23db..c038b49 100644
--- a/src/lib/geo-region.ts
+++ b/src/lib/geo-region.ts
@@ -9,6 +9,8 @@ export type UserGeoRegion = {
country?: string;
countryCode?: string; // e.g. "IR", "US", "GB"
phoneCode?: string; // e.g. "+98", "+1", "+44"
+ latitude?: number;
+ longitude?: number;
};
const phoneUtil = PhoneNumberUtil.getInstance();
@@ -201,6 +203,8 @@ function fetchFlutterBridgeGeoRegion(): Promise {
country: countryName,
countryCode: isoCode,
phoneCode: phoneCode || "+44",
+ latitude: (data as any).latitude,
+ longitude: (data as any).longitude,
};
setStoredUserGeoRegion(region);
finish(region);
diff --git a/src/lib/webview-actions.ts b/src/lib/webview-actions.ts
index d7c1050..7ef7f5a 100644
--- a/src/lib/webview-actions.ts
+++ b/src/lib/webview-actions.ts
@@ -180,3 +180,99 @@ export function openConsultantPage(username: string): boolean {
return postActionToFlutter("open_consultant_page", { consultant: username });
}
+// ─── Location Actions (Auto GPS & Manual Map) ─────────────
+
+export interface LocationResultData {
+ latitude: number;
+ longitude: number;
+ city?: string;
+ country?: string;
+ country_code?: string;
+}
+
+/**
+ * Ask Flutter to request GPS permissions and return precise device location
+ * with reverse-geocoded city and country.
+ */
+export function requestAutoLocation(
+ timeoutMs = 15000,
+): Promise {
+ return new Promise((resolve, reject) => {
+ if (!isInFlutterWebView()) {
+ reject(new Error("Not in Flutter WebView"));
+ return;
+ }
+
+ let timer: ReturnType | null = null;
+
+ const cleanup = () => {
+ if (timer) clearTimeout(timer);
+ unsubscribe?.();
+ };
+
+ const unsubscribe = window.addFlutterResponseListener?.((event) => {
+ if (event.action === "get_auto_location") {
+ cleanup();
+ if (event.success && event.data) {
+ resolve(event.data as LocationResultData);
+ } else {
+ reject(new Error(event.error || "Failed to get auto location"));
+ }
+ }
+ });
+
+ timer = setTimeout(() => {
+ cleanup();
+ reject(new Error("Timeout waiting for auto location"));
+ }, timeoutMs);
+
+ postActionToFlutter("get_auto_location");
+ });
+}
+
+/**
+ * Ask Flutter to open native map dialog for manual location selection.
+ * Returns selected coordinates and geocoded info, or null if user cancelled.
+ */
+export function pickManualLocation(
+ initialCoords?: { latitude?: number; longitude?: number },
+ timeoutMs = 120000,
+): Promise {
+ return new Promise((resolve, reject) => {
+ if (!isInFlutterWebView()) {
+ reject(new Error("Not in Flutter WebView"));
+ return;
+ }
+
+ let timer: ReturnType | null = null;
+
+ const cleanup = () => {
+ if (timer) clearTimeout(timer);
+ unsubscribe?.();
+ };
+
+ const unsubscribe = window.addFlutterResponseListener?.((event) => {
+ if (event.action === "pick_manual_location") {
+ cleanup();
+ if (event.success && event.data) {
+ resolve(event.data as LocationResultData);
+ } else if (event.cancelled) {
+ resolve(null);
+ } else {
+ reject(new Error(event.error || "Failed to pick manual location"));
+ }
+ }
+ });
+
+ timer = setTimeout(() => {
+ cleanup();
+ reject(new Error("Timeout waiting for manual location pick"));
+ }, timeoutMs);
+
+ postActionToFlutter(
+ "pick_manual_location",
+ initialCoords as Record | undefined,
+ );
+ });
+}
+
diff --git a/src/types/window.d.ts b/src/types/window.d.ts
index a72dd9d..6798bbe 100644
--- a/src/types/window.d.ts
+++ b/src/types/window.d.ts
@@ -15,6 +15,8 @@ declare global {
status?: string;
/** Top-level error/info message */
message?: string;
+ error?: string;
+ cancelled?: boolean;
data?: {
// get_location
latitude?: number;