diff --git a/backend/public/downloads/yotrip-latest.apk b/backend/public/downloads/yotrip-latest.apk index 5f3acf3..e04b1c6 100644 Binary files a/backend/public/downloads/yotrip-latest.apk and b/backend/public/downloads/yotrip-latest.apk differ diff --git a/frontend/dist/index.html b/frontend/dist/index.html index b7e1c50..a653a34 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -21,13 +21,13 @@ - + - + - - + + diff --git a/frontend/src/components/AddPhotoModal.tsx b/frontend/src/components/AddPhotoModal.tsx index 384d223..a04fcc2 100644 --- a/frontend/src/components/AddPhotoModal.tsx +++ b/frontend/src/components/AddPhotoModal.tsx @@ -4,6 +4,7 @@ import { useNotification } from '@/hooks/useNotification'; import { useTourStore } from '@/store/useTourStore'; import { processImageModeration } from '@/hooks/useImageModeration'; import { processAndResizeImage } from '../utils/imageProcessor'; +import { getDeviceLocation } from '../utils/geolocation'; interface AddPhotoModalProps { isOpen: boolean; @@ -38,20 +39,7 @@ export const AddPhotoModal: React.FC = ({ isOpen, onClose, t try { // Fetch device location once to serve as Priority 2 fallback for files without EXIF - const deviceLocation = await Promise.race([ - new Promise((resolve) => { - if (!navigator.geolocation) { - resolve(null); - } else { - navigator.geolocation.getCurrentPosition( - (pos) => resolve(pos), - () => resolve(null), - { timeout: 3500, enableHighAccuracy: true } - ); - } - }), - new Promise((resolve) => setTimeout(() => resolve(null), 4000)) - ]); + const deviceLocation = await getDeviceLocation(); const newValidPhotos: PendingPhoto[] = []; const newValidPreviews: string[] = []; @@ -89,9 +77,9 @@ export const AddPhotoModal: React.FC = ({ isOpen, onClose, t let finalLng: number | null = exifLng; // Priority 2: Device location - if ((finalLat === null || finalLng === null) && deviceLocation && deviceLocation.coords) { - finalLat = deviceLocation.coords.latitude; - finalLng = deviceLocation.coords.longitude; + if ((finalLat === null || finalLng === null) && deviceLocation) { + finalLat = deviceLocation.latitude; + finalLng = deviceLocation.longitude; } // Priority 3: Map view state diff --git a/frontend/src/pages/LandingPage.tsx b/frontend/src/pages/LandingPage.tsx index ff721f3..9cd8b85 100644 --- a/frontend/src/pages/LandingPage.tsx +++ b/frontend/src/pages/LandingPage.tsx @@ -14,6 +14,7 @@ import { useNotification } from '@/hooks/useNotification'; import { processImageModeration } from '../hooks/useImageModeration'; import { useTranslation } from '../hooks/useTranslation'; import { processAndResizeImage } from '../utils/imageProcessor'; +import { getDeviceLocation } from '../utils/geolocation'; interface LandingPageProps { onContinue?: () => void; @@ -215,23 +216,10 @@ export const LandingPage: React.FC = ({ // 2. Get current mobile/device GPS position of the user if (finalLat === null || finalLng === null) { try { - const pos = await Promise.race([ - new Promise((resolve) => { - if (!navigator.geolocation) { - resolve(null); - } else { - navigator.geolocation.getCurrentPosition( - (p) => resolve(p), - () => resolve(null), - { timeout: 4000, enableHighAccuracy: true } - ); - } - }), - new Promise((resolve) => setTimeout(() => resolve(null), 4500)) - ]); - if (pos && pos.coords) { - finalLat = pos.coords.latitude; - finalLng = pos.coords.longitude; + const deviceLoc = await getDeviceLocation(); + if (deviceLoc) { + finalLat = deviceLoc.latitude; + finalLng = deviceLoc.longitude; console.log('[Upload Location] Priority 2: GPS coordinates found:', finalLat, finalLng); } } catch (e) { diff --git a/frontend/src/utils/geolocation.ts b/frontend/src/utils/geolocation.ts new file mode 100644 index 0000000..1acd556 --- /dev/null +++ b/frontend/src/utils/geolocation.ts @@ -0,0 +1,54 @@ +import { Geolocation } from '@capacitor/geolocation'; + +export interface DeviceLocation { + latitude: number; + longitude: number; +} + +export async function getDeviceLocation(): Promise { + try { + // Request permission at native level (essential for Android app packaging) + const permissionStatus = await Geolocation.requestPermissions(); + if (permissionStatus.location === 'granted' || permissionStatus.coarseLocation === 'granted') { + const position = await Geolocation.getCurrentPosition({ + enableHighAccuracy: true, + timeout: 5000 + }); + if (position && position.coords) { + console.log('[Geolocation] Acquired coordinates via Capacitor Geolocation:', position.coords.latitude, position.coords.longitude); + return { + latitude: position.coords.latitude, + longitude: position.coords.longitude + }; + } + } + } catch (error) { + console.warn('[Geolocation] Capacitor plugin failed/unavailable, falling back to browser Geolocation:', error); + } + + // Fallback to standard web browser Geolocation API + try { + const position = await new Promise((resolve) => { + if (!navigator.geolocation) { + resolve(null); + } else { + navigator.geolocation.getCurrentPosition( + (p) => resolve(p), + () => resolve(null), + { timeout: 4000, enableHighAccuracy: true } + ); + } + }); + if (position && position.coords) { + console.log('[Geolocation] Acquired coordinates via Web Geolocation:', position.coords.latitude, position.coords.longitude); + return { + latitude: position.coords.latitude, + longitude: position.coords.longitude + }; + } + } catch (e) { + console.error('[Geolocation] Browser Geolocation failed:', e); + } + + return null; +}