import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import 'package:geolocator/geolocator.dart'; import 'package:provider/provider.dart'; import '../providers/auth_provider.dart'; import '../providers/map_provider.dart'; import '../providers/share_provider.dart'; import '../services/geo_service.dart'; class MapScreen extends StatefulWidget { const MapScreen({super.key}); @override State createState() => _MapScreenState(); } class _MapScreenState extends State { LatLng _center = const LatLng(40.7128, -74.0060); bool _loading = true; Timer? _trackingTimer; Timer? _geoTimer; @override void initState() { super.initState(); _initLocationAndShare(); } @override void dispose() { _trackingTimer?.cancel(); _geoTimer?.cancel(); super.dispose(); } Future _initLocationAndShare() async { try { if (!await Geolocator.isLocationServiceEnabled()) { setState(() => _loading = false); return; } final position = await Geolocator.getCurrentPosition(); setState(() { _center = LatLng(position.latitude, position.longitude); }); if (!mounted) return; final authProvider = context.read(); final shareProvider = context.read(); if (authProvider.token.isNotEmpty) { await shareProvider.createShare( authProvider.token, position.longitude, position.latitude, ); } if (!mounted) return; setState(() => _loading = false); _geoTimer = Timer.periodic( const Duration(seconds: 30), (_) => _updateGeolocation(), ); } catch (_) { setState(() => _loading = false); } } Future _updateGeolocation() async { try { final position = await Geolocator.getCurrentPosition(); setState(() { _center = LatLng(position.latitude, position.longitude); }); if (!mounted) return; final authProvider = context.read(); final shareProvider = context.read(); await GeoService().updatePosition( authProvider.token, shareProvider.geoId, position.longitude, position.latitude, ); } catch (_) {} } void _copyShareLink() { final shareProvider = context.read(); if (shareProvider.shareId.isNotEmpty) { Clipboard.setData(ClipboardData(text: 'watch/${shareProvider.shareId}')); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Ссылка скопирована')), ); } } void _startTracking() { final authProvider = context.read(); final shareProvider = context.read(); if (shareProvider.trackingShareId.isEmpty) { showDialog( context: context, builder: (context) { final TextEditingController _controller = TextEditingController(); return AlertDialog( title: const Text('Отслеживание'), content: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Введите Share ID для отслеживания:'), const SizedBox(height: 16), TextField( controller: _controller, decoration: const InputDecoration( hintText: 'Введите Share ID', border: OutlineInputBorder(), ), ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Отмена'), ), TextButton( onPressed: () async { final shareId = _controller.text.trim(); if (shareId.isNotEmpty) { Navigator.pop(context); final token = authProvider.token; await shareProvider.startTracking(shareId, token); _trackingTimer = Timer.periodic( const Duration(seconds: 5), (_) => shareProvider.updateTrackedPosition(), ); } }, child: const Text('Начать'), ), ], ); }, ); } else { shareProvider.stopTracking(); _trackingTimer?.cancel(); } } @override Widget build(BuildContext context) { final authProvider = context.watch(); final _ = context.watch(); final shareProvider = context.watch(); if (_loading) { return Scaffold( body: const Center(child: CircularProgressIndicator()), ); } Marker? trackedMarker; if (shareProvider.trackedPosition != null) { final pos = shareProvider.trackedPosition!; final lat = pos['y'] as double; final lng = pos['x'] as double; trackedMarker = Marker( point: LatLng(lat, lng), width: 40, height: 40, child: const Icon( Icons.person, color: Colors.red, size: 30, ), ); } return Scaffold( appBar: AppBar( title: Text( 'Family Safety Map\n${_center.latitude.toStringAsFixed(4)}, ${_center.longitude.toStringAsFixed(4)}', textAlign: TextAlign.center, ), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _updateGeolocation, ), IconButton( icon: const Icon(Icons.share), onPressed: _copyShareLink, ), IconButton( icon: Icon( shareProvider.trackingShareId.isEmpty ? Icons.person_search : Icons.person, color: shareProvider.trackingShareId.isEmpty ? null : Colors.red, ), onPressed: _startTracking, ), IconButton( icon: const Icon(Icons.logout), onPressed: () { _geoTimer?.cancel(); authProvider.logout(); Navigator.of(context).pushReplacementNamed('/'); }, ), ], ), body: FlutterMap( options: MapOptions( center: _center, zoom: 12.0, ), children: [ TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', ), MarkerLayer( markers: [ Marker( point: _center, width: 40, height: 40, child: const Icon( Icons.my_location, color: Colors.blue, size: 30,) ), if (trackedMarker != null) trackedMarker, ], ), ], ), ); } }