diff --git a/lib/src/services/geolocation_service.dart b/lib/src/services/geolocation_service.dart index 270289d..2317f4c 100644 --- a/lib/src/services/geolocation_service.dart +++ b/lib/src/services/geolocation_service.dart @@ -1,87 +1,109 @@ // src/services/geolocation_service.dart import 'package:geolocator/geolocator.dart'; -import 'dart:async'; // ← IMPORTANTE: Para TimeoutException +import 'dart:async'; +import 'package:universal_platform/universal_platform.dart'; class GeolocationService { - // Verificar servicios de ubicación static Future isLocationServiceEnabled() async { + if (UniversalPlatform.isWeb) return true; // Web no necesita GPS activado return await Geolocator.isLocationServiceEnabled(); } - // Verificar permiso static Future checkPermission() async { + if (UniversalPlatform.isWeb) return LocationPermission.always; return await Geolocator.checkPermission(); } - // Solicitar permiso static Future requestPermission() async { + if (UniversalPlatform.isWeb) return LocationPermission.always; return await Geolocator.requestPermission(); } - // Verificar si hay permiso concedido static Future hasPermission() async { + if (UniversalPlatform.isWeb) return true; LocationPermission permission = await Geolocator.checkPermission(); return permission == LocationPermission.always || permission == LocationPermission.whileInUse; } - // Obtener ubicación actual con timeout static Future getCurrentLocation() async { try { - // Verificar servicios + // Web usa la API de navegador + if (UniversalPlatform.isWeb) { + return await _getWebLocation(); + } + + // Móvil: usar menor precisión para más velocidad bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { - print('❌ Servicios de ubicación desactivados'); + print('❌ GPS desactivado'); return null; } - print('✅ Servicios de ubicación activados'); - // Verificar permisos LocationPermission permission = await Geolocator.checkPermission(); - print('📌 Permiso actual: $permission'); - if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); - print('📌 Permiso solicitado: $permission'); - if (permission == LocationPermission.denied) { - print('❌ Permiso denegado'); - return null; - } + if (permission == LocationPermission.denied) return null; } - if (permission == LocationPermission.deniedForever) { - print('❌ Permiso denegado permanentemente'); - return null; - } - - // Obtener ubicación - print('📍 Obteniendo ubicación...'); + if (permission == LocationPermission.deniedForever) return null; + // Usar menor precisión para obtener ubicación más rápido Position position = await Geolocator.getCurrentPosition( - desiredAccuracy: LocationAccuracy.best, + desiredAccuracy: LocationAccuracy.low, // ← Cambiado de best a low para más velocidad + timeLimit: const Duration(seconds: 5), ); - print('✅ Ubicación obtenida: ${position.latitude}, ${position.longitude}'); return position; } catch (e) { - print('❌ Error general: $e'); + print('Error: $e'); return null; } } - // Obtener ubicación con reintentos (sin timeout que da problemas) + // Método específico para web + static Future _getWebLocation() async { + try { + // Usar la API de geolocalización del navegador + final GeolocationPosition position = await _getWebPosition(); + return Position( + latitude: position.latitude, + longitude: position.longitude, + timestamp: DateTime.now(), + accuracy: 0, + altitude: 0, + heading: 0, + speed: 0, + speedAccuracy: 0, + altitudeAccuracy: 0, + headingAccuracy: 0, + ); + } catch (e) { + print('Error en web: $e'); + return null; + } + } + + // Placeholder para web - usar HTML5 geolocation + static Future _getWebPosition() async { + // Implementación simplificada - en realidad usarías js_interop + throw UnimplementedError('Usar package:geolocator_web'); + } + static Future getCurrentLocationWithRetry({int maxRetries = 3}) async { for (int i = 0; i < maxRetries; i++) { print('🔄 Intento ${i + 1} de $maxRetries'); final position = await getCurrentLocation(); - if (position != null) { - return position; - } - if (i < maxRetries - 1) { - await Future.delayed(const Duration(seconds: 2)); - } + if (position != null) return position; + if (i < maxRetries - 1) await Future.delayed(const Duration(seconds: 1)); } - print('❌ No se pudo obtener ubicación después de $maxRetries intentos'); return null; } +} + +// Clase auxiliar para web +class GeolocationPosition { + final double latitude; + final double longitude; + GeolocationPosition({required this.latitude, required this.longitude}); } \ No newline at end of file diff --git a/lib/src/views/mapa_expandible.dart b/lib/src/views/mapa_expandible.dart index 190a1da..cec452c 100644 --- a/lib/src/views/mapa_expandible.dart +++ b/lib/src/views/mapa_expandible.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; +import 'package:universal_platform/universal_platform.dart'; +import 'rutas.dart'; class MapaExpandible extends StatefulWidget { final double latitud; @@ -20,16 +22,20 @@ class MapaExpandible extends StatefulWidget { class _MapaExpandibleState extends State { bool _isExpanded = false; + bool _hasError = false; @override Widget build(BuildContext context) { + // Verificar coordenadas válidas + final isValid = widget.latitud.isFinite && widget.longitud.isFinite; + return Column( children: [ - // Botón para expandir/colapsar GestureDetector( onTap: () { setState(() { _isExpanded = !_isExpanded; + _hasError = false; }); }, child: Container( @@ -59,7 +65,6 @@ class _MapaExpandibleState extends State { ), ), ), - // Mapa (visible solo cuando está expandido) if (_isExpanded) Padding( padding: const EdgeInsets.only(top: 12), @@ -69,32 +74,60 @@ class _MapaExpandibleState extends State { borderRadius: BorderRadius.circular(15), border: Border.all(color: colorAzul.withOpacity(0.3), width: 1), ), - child: ClipRRect( + child: _hasError + ? Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.map_outlined, size: 50, color: Colors.grey), + const SizedBox(height: 10), + Text( + 'No se pudo cargar el mapa', + style: TextStyle(color: Colors.grey[600]), + ), + const SizedBox(height: 5), + Text( + 'Coordenadas: ${widget.latitud.toStringAsFixed(4)}, ${widget.longitud.toStringAsFixed(4)}', + style: TextStyle(fontSize: 12, color: Colors.grey[500]), + ), + ], + ), + ) + : ClipRRect( borderRadius: BorderRadius.circular(15), child: FlutterMap( options: MapOptions( - initialCenter: LatLng(widget.latitud, widget.longitud), + initialCenter: LatLng( + isValid ? widget.latitud : 20.5111, + isValid ? widget.longitud : -100.9037, + ), initialZoom: 15, ), children: [ TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: 'com.example.app', + errorCallback: (error, stackTrace) { + setState(() { + _hasError = true; + }); + }, ), - MarkerLayer( - markers: [ - Marker( - point: LatLng(widget.latitud, widget.longitud), - width: 40, - height: 40, - child: const Icon( - Icons.location_pin, - color: Colors.red, - size: 40, + if (isValid) + MarkerLayer( + markers: [ + Marker( + point: LatLng(widget.latitud, widget.longitud), + width: 40, + height: 40, + child: const Icon( + Icons.location_pin, + color: Colors.red, + size: 40, + ), ), - ), - ], - ), + ], + ), ], ), ),