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;
+}