Advertisement
Guest User

Untitled

a guest
Jun 17th, 2025
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.11 KB | None | 0 0
  1. import 'package:flutter/material.dart';
  2. import 'package:google_maps_flutter/google_maps_flutter.dart';
  3. import 'dart:async';
  4. import 'dart:math';
  5.  
  6. import 'package:soundscape/models/pages/map_screen/buttons_top_main_page.dart';
  7. import 'package:soundscape/models/pages/map_screen/buttons_bottom_main_page.dart';
  8.  
  9. import "package:soundscape/models/shared/bottom_nav_bar.dart";
  10. import 'package:soundscape/shared/managers/markers_manager.dart';
  11.  
  12. import 'package:soundscape/shared/managers/music_manager.dart';
  13. import "package:soundscape/shared/managers/steam_music_manager.dart";
  14. import "package:soundscape/shared/managers/polygons_manager.dart";
  15.  
  16. import 'package:provider/provider.dart';
  17. import 'package:soundscape/shared/providers/location_provider.dart';
  18. import 'package:soundscape/shared/providers/parametre_provider.dart';
  19.  
  20. import 'package:soundscape/shared/managers/backend_manager.dart';
  21.  
  22. import 'package:soundscape/models/backend/polygons.dart';
  23.  
  24. import 'package:soundscape/models/pages/marker_details/marker_details_page.dart';
  25.  
  26. import 'package:soundscape/models/effects/vibration_util.dart';
  27.  
  28. class MapScreen extends StatefulWidget {
  29.  
  30.   const MapScreen({
  31.     Key? key
  32.   }) : super(key: key);
  33.  
  34.   u/override
  35.   State<MapScreen> createState() => _MapScreenState();
  36. }
  37.  
  38. class _MapScreenState extends State<MapScreen> {
  39.   Timer? _locationTimer;
  40.   GoogleMapController? _controller;
  41.  
  42.   final PolygonsManager _polygonsManager = PolygonsManager();
  43.   final StreamMusicManager _streamMusic = StreamMusicManager();
  44.   final MusicManager _musicManager = MusicManager();
  45.   final BackendManager _backendManager = BackendManager();
  46.  
  47.   late ParametreProvider parametreProvider;
  48.  
  49.   String _currentPolygonID = "";
  50.   String _previousPolygonID = "";
  51.  
  52.   Polygon? currentPolygon;
  53.   SoundscapePolygon? currentSoundscapePolygon;
  54.   MarkerData? currentMarkerData;
  55.   bool isInCurrentPolygon = false;
  56.  
  57.   bool _isUpdatingLocation = false;
  58.   bool _isMusicLoading = false;
  59.   bool isInChangement = false;
  60.   bool _isTrackChanging = false;
  61.  
  62.   final Set<Marker> _clickMarkers = {};
  63.   final List<List<double>> _clickPolygons = [];
  64.  
  65.   LatLng _currentPosition = const LatLng(0, 0);
  66.  
  67.   u/override
  68.   void initState() {
  69.     super.initState();
  70.     parametreProvider = Provider.of<ParametreProvider>(context, listen: false);
  71.     _startUpdateLocation();
  72.     _setupMusicQueue();
  73.   }
  74.  
  75.   @override
  76.   void dispose() {
  77.     _locationTimer?.cancel();
  78.     _controller?.dispose();
  79.     super.dispose();
  80.   }
  81.  
  82.  void _setupMusicQueue() {
  83.     _musicManager.onTrackCompleted = (String polygonId) async {
  84.       if (_isTrackChanging) {
  85.         debugPrint("🎵 Changement de piste déjà en cours, ignore");
  86.         return;
  87.       }
  88.      
  89.       _isTrackChanging = true;
  90.       debugPrint("🎵 Piste terminée pour polygone: $polygonId");
  91.      
  92.       try {
  93.         await _streamMusic.onMusicEnded(polygonId);
  94.       } finally {
  95.         await Future.delayed(const Duration(milliseconds: 500));
  96.         _isTrackChanging = false;
  97.       }
  98.     };
  99.  
  100.     _streamMusic.onTrackEnded = (String? nextTrackPath) async {
  101.       if (isInChangement) {
  102.         debugPrint("🎵 Changement de musique en cours, ignore cette demande");
  103.         return;
  104.       }
  105.       if (nextTrackPath != null && currentSoundscapePolygon != null) {
  106.         isInChangement = true;
  107.         debugPrint("🎵 Lancement de la piste suivante ICI: $nextTrackPath");
  108. await _musicManager.play(
  109.           nextTrackPath,
  110.           polygonId: currentSoundscapePolygon!.uuid
  111.         );
  112.         debugPrint("JE SUIS ICICICICICIICICICICICICICICICICICIC");
  113.         refreshCurrentPolygon(currentSoundscapePolygon!.uuid);
  114.         debugPrint("🎵 Mise à jour de l'image du marqueur pour le polygone ${currentSoundscapePolygon!.uuid}");
  115.         if (currentMarkerData != null) {
  116.           final markerId = currentMarkerData!.id;
  117.           final musicImagePath = _streamMusic.getCurrentMusicCoverPath;
  118.           debugPrint("🎵 Mise à jour de l'image du marqueur $markerId avec $musicImagePath");
  119.           await _polygonsManager.getMarkersManager.updateMarkerImage(markerId, musicImagePath);
  120.         } else {
  121.           debugPrint("⚠️ currentMarkerData est null, tentative de récupération...");
  122.           final markerData = _polygonsManager.getMarkersManager.getMarkerDataByPolygonId(currentSoundscapePolygon!.uuid);
  123.          
  124.           if (markerData != null) {
  125.             currentMarkerData = markerData;
  126.             final musicImagePath = _streamMusic.getCurrentMusicCoverPath;
  127.             debugPrint("🎵 Marker récupéré, mise à jour de l'image avec $musicImagePath");
  128.             await _polygonsManager.getMarkersManager.updateMarkerImage(markerData.id, musicImagePath);
  129.           } else {
  130.             debugPrint("❌ Impossible de trouver le marker pour le polygone ${currentSoundscapePolygon!.uuid}");
  131.           }
  132.         }
  133.         isInChangement = false;
  134.         setState(() {});
  135.       }
  136.     };
  137.   }
  138.  
  139.   void _startUpdateLocation() {
  140.     _locationTimer?.cancel();
  141.     _locationTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
  142.       _updateLocation();
  143.     });
  144.   }
  145.  
  146.   void _updateLocation() async {
  147.     if (_isUpdatingLocation) {
  148.       debugPrint("⏸️ Mise à jour en cours, ignore cet appel");
  149.       return;
  150.     }
  151.    
  152.     _isUpdatingLocation = true;
  153.    
  154.     try {
  155.       if (parametreProvider.manualMode) {
  156.         _currentPosition = parametreProvider.manualPosition;
  157.       } else {
  158.         await Provider.of<LocationProvider>(context, listen: false).updateCurrentLocation();
  159.         if (!mounted) return;
  160.         _currentPosition = Provider.of<LocationProvider>(context, listen: false).currentPosition;
  161.       }
  162.  
  163.       if (parametreProvider.manualPolygon == false) {
  164.         _controller?.animateCamera(CameraUpdate.newLatLng(_currentPosition));
  165.       }
  166.  
  167.       String newPolygonID = "";
  168.       try {
  169.         newPolygonID = await getCurrentPolygonID(_currentPosition, _polygonsManager);
  170.       } catch (error) {
  171.         debugPrint("❌ Erreur lors de la récupération du polygon ID: $error");
  172.       }
  173.  
  174.       bool polygonChanged = (newPolygonID != _previousPolygonID);
  175.       _currentPolygonID = newPolygonID;
  176.      
  177.       if (polygonChanged) {
  178.         debugPrint("🔄 Changement de polygone: $_previousPolygonID -> $_currentPolygonID");
  179.         if (parametreProvider.vibration) {
  180.           if (_currentPolygonID.isNotEmpty) {
  181.             debugPrint("🔔 Vibration pour le polygone $_currentPolygonID");
  182.             VibrationUtil.vibrate();
  183.           } else {
  184.             debugPrint("🔕 Pas de vibration, pas de polygone actif");
  185.           }
  186.         } else {
  187.           debugPrint("🔕 Vibration désactivée dans les paramètres");
  188.         }
  189.         _previousPolygonID = _currentPolygonID;
  190.         refreshCurrentPolygon(_currentPolygonID);
  191.        
  192.         _musicManager.stop();
  193.         _streamMusic.currentEqualsToNext(null);
  194.         _isMusicLoading = false;
  195.       }
  196.  
  197.       if (_currentPolygonID != "") {
  198.         await _handleCurrentPolygon();
  199.         _polygonsManager.getMarkersManager.updateMarkerOnTap(_currentPolygonID, () {
  200.           Navigator.push(
  201.           context,
  202.           MaterialPageRoute(
  203.             builder: (context) => MarkerDetailsPage(
  204.               title: currentSoundscapePolygon?.uuid ?? 'Panik',
  205.               description: _streamMusic.getCurrentMusicTitle,
  206.               imagePath: _streamMusic.getCurrentMusicCoverPath,
  207.               nextMusics: _streamMusic.getFullQueue(_currentPolygonID),
  208.               isInPolygon: isInCurrentPolygon,
  209.             ),
  210.           ),
  211.         );
  212.         });
  213.         if (polygonChanged) {
  214.           debugPrint("🔄 Mise à jour des marqueurs pour le polygone $_currentPolygonID");
  215.         }
  216.       } else {
  217.         _handleNoPolygon();
  218.       }
  219.  
  220.       if (_backendManager.backendIsDead && polygonChanged) {
  221.         _polygonsManager.clearPolygons();
  222.         _polygonsManager.clearMarkers();
  223.       }
  224.  
  225.     } finally {
  226.       _isUpdatingLocation = false;
  227.       if (mounted) {
  228.         setState(() {});
  229.       }
  230.     }
  231.   }
  232.  
  233.   Future<void> _handleCurrentPolygon() async {
  234.     setState(() {
  235.       isInCurrentPolygon = true;
  236.       currentPolygon = _polygonsManager.getPolygon(_currentPolygonID);
  237.       currentSoundscapePolygon = _polygonsManager.getSoundscapePolygon(_currentPolygonID);
  238.       currentMarkerData = _polygonsManager.getMarkersManager.getMarkerDataByPolygonId(_currentPolygonID);
  239.     });
  240.  
  241.     if (currentPolygon == null) {
  242.       _musicManager.stop();
  243.       _streamMusic.currentEqualsToNext(null);
  244.       return;
  245.     }
  246.  
  247.     if (parametreProvider.volumne == 0) {
  248.       return;
  249.     }
  250.  
  251.     _musicManager.setVolume(parametreProvider.volumne / 100);
  252.     await _handleMusicForPolygon(currentSoundscapePolygon);
  253.   }
  254.  
  255.   Future<void> _handleMusicForPolygon(SoundscapePolygon? polygon) async {
  256.     if (polygon == null) return;
  257.  
  258.     if (_isTrackChanging) {
  259.       debugPrint("[_handleMusicForPolygon] Changement de piste en cours, ignore la gestion de musique");
  260.       return;
  261.     }
  262.    
  263.     if (_isMusicLoading) {
  264.       debugPrint("[_handleMusicForPolygon] Musique en cours de chargement, ignore cette demande");
  265.       return;
  266.     }
  267.  
  268.     if (_streamMusic.currentEqualsToNext(polygon)) {
  269.       debugPrint("[_handleMusicForPolygon] Même musique, pas de changement nécessaire");
  270.  
  271.       if (!_musicManager.isPlaying()) {
  272.         final musicPath = _streamMusic.getCurrentMusicImagePath;
  273.         if (musicPath.isNotEmpty) {
  274.           debugPrint("[_handleMusicForPolygon] Relance la musique existante");
  275.           _musicManager.play(
  276.             musicPath,
  277.             volume: parametreProvider.volumne / 100,
  278.             polygonId: polygon.uuid,
  279.           );
  280.         }
  281.       }
  282.       setState(() {});
  283.       return;
  284.     }
  285.  
  286.     debugPrint("[_handleMusicForPolygon] Chargement nouvelle musique pour ${polygon.uuid}");
  287.     _isMusicLoading = true;
  288.     try {
  289.       await _streamMusic.chooseMusic(polygon);
  290.       final musicPath = _streamMusic.getCurrentMusicImagePath;
  291.       if (musicPath.isNotEmpty) {
  292.         debugPrint("[_handleMusicForPolygon] Lecture de la nouvelle musique: $musicPath");
  293.         _musicManager.play(
  294.           musicPath,
  295.           volume: parametreProvider.volumne / 100,
  296.           polygonId: polygon.uuid,
  297.         );
  298.         if (currentMarkerData != null) {
  299.           final markerId = currentMarkerData!.id;
  300.           final musicImagePath = _streamMusic.getCurrentMusicCoverPath;
  301.           debugPrint("[_handleMusicForPolygon] Mise à jour de l'image du marqueur $markerId avec $musicImagePath");
  302.           await _polygonsManager.getMarkersManager.updateMarkerImage(markerId, musicImagePath);
  303.         } else {
  304.           debugPrint("[_handleMusicForPolygon] ⚠️ currentMarkerData est null, tentative de récupération...");
  305.           final markerData = _polygonsManager.getMarkersManager.getMarkerDataByPolygonId(polygon.uuid);
  306.          
  307.           if (markerData != null) {
  308.             currentMarkerData = markerData;
  309.             final musicImagePath = _streamMusic.getCurrentMusicCoverPath;
  310.             debugPrint("[_handleMusicForPolygon] Marker récupéré, mise à jour de l'image avec $musicImagePath");
  311.             await _polygonsManager.getMarkersManager.updateMarkerImage(markerData.id, musicImagePath);
  312.           } else {
  313.             debugPrint("[_handleMusicForPolygon] ❌ Impossible de trouver le marker pour le polygone ${polygon.uuid}");
  314.           }
  315.         }
  316.       } else {
  317.         debugPrint("[_handleMusicForPolygon] ❌ Chemin de musique vide après chargement");
  318.       }
  319.     } catch (e) {
  320.       debugPrint("[_handleMusicForPolygon] ❌ Erreur lors du chargement de la musique: $e");
  321.     } finally {
  322.       _isMusicLoading = false;
  323.     }
  324.     setState(() {});
  325.   }
  326.  
  327.   void _handleNoPolygon() {
  328.     setState(() {
  329.       isInCurrentPolygon = false;
  330.       currentPolygon = null;
  331.       currentSoundscapePolygon = null;
  332.       currentMarkerData = null;
  333.     });
  334.     _musicManager.stop();
  335.     _streamMusic.currentEqualsToNext(null);
  336.   }
  337.  
  338.   @override
  339.   Widget build(BuildContext context) {
  340.     bool permissionDenied = Provider.of<LocationProvider>(context).permissionDenied;
  341.  
  342.     return Scaffold(
  343.       bottomNavigationBar: BottomNavBar(
  344.         currentIndex: 0,
  345.         onTap: (index) {},
  346.       ),
  347.       body: permissionDenied
  348.         ? const Center(child: Text('Location permissions are denied'))
  349.         : Stack(
  350.           fit: StackFit.expand,
  351.           children: [
  352.             GoogleMap(
  353.               style: parametreProvider.style,
  354.               initialCameraPosition: CameraPosition(
  355.                 target: _currentPosition,
  356.                 zoom: 14,
  357.               ),
  358.               onMapCreated: (controller) {
  359.                 _controller = controller;
  360.               },
  361.               onTap: parametreProvider.manualPolygon
  362.                 ? (LatLng position) {
  363.                     _handleMapTap(position);
  364.                   }
  365.                 : null,
  366.               // True / False
  367.               myLocationEnabled: !parametreProvider.manualMode,
  368.               myLocationButtonEnabled: false,
  369.               zoomControlsEnabled: false,
  370.               zoomGesturesEnabled: true,
  371.               mapToolbarEnabled: false,
  372.               // Polygons & Markers & Circles
  373.               polygons: _polygonsManager.getPolygons,
  374.               markers: {
  375.                 ..._polygonsManager.getMarkers.toSet(),
  376.                 if (parametreProvider.manualPolygon) ..._clickMarkers,
  377.               },
  378.               circles: parametreProvider.manualCircle,
  379.             ),
  380.             ButtonsBottomMainPage(
  381.               manualPolygon: parametreProvider.manualPolygon,
  382.               manualMode: parametreProvider.manualMode,
  383.               isInCurrentPolygon: isInCurrentPolygon,
  384.               currentMarkerData: currentMarkerData,
  385.               clickPolygons: _clickPolygons,
  386.               onRefreshPolygonFinished: () {
  387.                 parametreProvider.setManualPolygon(false);
  388.                 _clickMarkers.clear();
  389.                 _clickPolygons.clear();
  390.               }
  391.             ),
  392.             ButtonsTopMainPage(
  393.               manualPolygon: parametreProvider.manualPolygon
  394.             ),
  395.           ],
  396.         ),
  397.     );
  398.   }
  399.  
  400.   void _handleMapTap(LatLng position) {
  401.     String markerId = 'click_marker_${position.latitude}_${position.longitude}_${DateTime.now().millisecondsSinceEpoch}';
  402.  
  403.     setState(() {
  404.       _clickMarkers.add(
  405.         Marker(
  406.           markerId: MarkerId(markerId),
  407.           position: position,
  408.           icon: BitmapDescriptor.defaultMarkerWithHue(Random().nextInt(360).toDouble()),
  409.           infoWindow: InfoWindow(
  410.             title: 'Position sélectionnée',
  411.             snippet: '${position.latitude}, ${position.longitude}',
  412.           ),
  413.         ),
  414.       );
  415.       _clickPolygons.add([position.latitude, position.longitude]);
  416.     });
  417.   }
  418.  
  419. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement