Skip to content

Commit

Permalink
Merge pull request #15 from DiFeitoza/7-f06-iniciar-viagem-com-monito…
Browse files Browse the repository at this point in the history
…ramento-em-tempo-real

F06 - Iniciar viagem com monitoramento em tempo real
  • Loading branch information
DiFeitoza authored Dec 28, 2024
2 parents ad25bae + 6e8278e commit 62b7245
Show file tree
Hide file tree
Showing 37 changed files with 2,160 additions and 610 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@
.idea

# Environment
.env
.env

# Project related
pubspec.lock
216 changes: 105 additions & 111 deletions spotholes_android/lib/controllers/base_map_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,69 +6,90 @@ import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:signals/signals_flutter.dart';

import '../models/spothole.dart';
import '../package/custom_info_window.dart';
import '../package/google_places_flutter/model/place_details.dart'
hide Location;
import '../services/geocoding_service.dart';
import '../services/location_service.dart';
import '../services/service_locator.dart';
import '../services/spothole_service.dart';
import '../utilities/constants.dart';
import '../utilities/custom_icons.dart';
import '../utilities/custom_snackbar.dart';
import '../widgets/draggable_scrollable_sheet/draggable_scrollable_sheet_type.dart';
import '../widgets/info_window/marker_info_window.dart';
import '../widgets/modal/register_spothole_modal.dart';
import 'spothole_info_window_controller.dart';

class BaseMapController {
BaseMapController._();
static final BaseMapController _instance = BaseMapController._();
static BaseMapController get instance => _instance;
Function? _dispose;

final LocationService _locationService = LocationService.instance;

late final _currentLocationSignal = _locationService.currentLocationSignal;
Signal<LocationData?> get currentLocationSignal => _currentLocationSignal;

LatLng get currentLocationLatLng => LatLng(
_currentLocationSignal.value!.latitude!,
_currentLocationSignal.value!.longitude!);

final databaseReference = getIt<DatabaseReference>();
late final dataBaseSpotholesRef = databaseReference.child('spotholes');

GoogleMapController? _googleMapController;
final _googleMapControllerCompleter = Completer();
final _googleMapControllerCompleter = Completer<GoogleMapController>();
Future<GoogleMapController> get getGoogleMapController async =>
await _googleMapControllerCompleter.future;

final _customInfoWindowControllerSignal =
Signal<CustomInfoWindowController>(CustomInfoWindowController());
SpotholeInfoWindowController? spotholeInfoWindowController;
final _textEditingController = TextEditingController();
final _searchBarFocusNode = FocusNode();
Signal<CustomInfoWindowController> get customInfoWindowControllerSignal =>
_customInfoWindowControllerSignal;

final _markersSignal = Signal<Map<String, Marker>>({});
Signal<Map<String, Marker>> get markersSignal => _markersSignal;

late Signal draggableScrollableSheetSignal = signal(
DraggableScrollableSheetTypes.initial.widget,
late final _spotholeService = SpotholeService(
_markersSignal,
_customInfoWindowControllerSignal,
);

final _geocodingService = GeocodingService.instance;
final _textEditingController = TextEditingController();
TextEditingController get textEditingController => _textEditingController;

final _location = Location();
final _searchBarFocusNode = FocusNode();
FocusNode get searchBarFocusNode => _searchBarFocusNode;

final _markersSignal = Signal<Map<String, Marker>>({});
final _currentLocationSignal = Signal<LocationData?>(null);

get markersSignal => _markersSignal;
get currentLocationSignal => _currentLocationSignal;
get textEditingController => _textEditingController;
get searchBarFocusNode => _searchBarFocusNode;
get customInfoWindowControllerSignal => _customInfoWindowControllerSignal;
get currentLocationLatLng => LatLng(_currentLocationSignal.value!.latitude!,
_currentLocationSignal.value!.longitude!);
late final _draggableScrollableSheetTypes =
DraggableScrollableSheetTypes(baseMapController: this);

late final _draggableScrollableSheetSignal = signal(
_draggableScrollableSheetTypes.initial.widget,
);
Signal<Widget> get draggableScrollableSheetSignal =>
_draggableScrollableSheetSignal;

String currentLocationLatLngURLPattern() =>
"${_currentLocationSignal.value!.latitude!.toString()}"
"%2C${_currentLocationSignal.value!.longitude!.toString()}";
final _geocodingService = GeocodingService.instance;
final isTrackingLocation = signal(true);
final isProgrammaticMove = signal(true);

void onMapCreated(mapController, context) {
_googleMapControllerCompleter.complete(mapController);
void onMapCreated(mapController) {
_customInfoWindowControllerSignal.value.googleMapController = mapController;
spotholeInfoWindowController = SpotholeInfoWindowController(
_customInfoWindowControllerSignal, _markersSignal);
loadSpotholeMarkers(context);
_googleMapControllerCompleter.complete(mapController);
listenCurrentLocation();
_spotholeService.loadSpotholeMarkers();
}

void updateCameraGoogleMapsController(position, [zoom = defaultZoomMap]) {
_googleMapController!.animateCamera(
void trackLocation() {
if (isTrackingLocation.value) {
isTrackingLocation.value = false;
} else {
isTrackingLocation.value = true;
centerView();
}
}

void updateCameraGoogleMapsController(position,
[zoom = defaultZoomMap]) async {
final mapController = await getGoogleMapController;
isProgrammaticMove.value = true;
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
zoom: zoom,
Expand All @@ -82,28 +103,22 @@ class BaseMapController {
updateCameraGoogleMapsController(currentLocationLatLng);
}

void loadCurrentLocation() async {
_currentLocationSignal.value = await _location.getLocation();
loadCurrentLocationMark();
_location.onLocationChanged.listen((newLoc) {
_currentLocationSignal.value = newLoc;
loadCurrentLocationMark();
});
_googleMapController = await _googleMapControllerCompleter.future;
centerView();
}

void loadCurrentLocationMark() {
final newMarker = Marker(
markerId: const MarkerId("currentLocation"),
icon: CustomIcons.currentLocationIcon,
position: currentLocationLatLng,
onTap: () => _customInfoWindowControllerSignal.value.addInfoWindow!(
const MarkerInfoWindow(
title: 'Localização', textContent: 'Você está aqui!'),
currentLocationLatLng),
void listenCurrentLocation() async {
_dispose = effect(
() {
if (_currentLocationSignal.value != null) {
untracked(
() => _locationService.loadCurrentLocationMark(
_markersSignal,
_customInfoWindowControllerSignal,
),
);
}
if (isTrackingLocation.value) {
centerView();
}
},
);
_markersSignal.value['currentLocationMarker'] = newMarker;
}

changeDraggableSheet(DraggableScrollableSheetType type) {
Expand All @@ -113,7 +128,8 @@ class BaseMapController {
void closeDraggableSheet(String key) {
_customInfoWindowControllerSignal.value.hideInfoWindow!();
removeMarkerByKey(key);
changeDraggableSheet(DraggableScrollableSheetTypes.initial);
changeDraggableSheet(_draggableScrollableSheetTypes.initial);
isTrackingLocation.value = true;
centerView();
}

Expand All @@ -125,61 +141,33 @@ class BaseMapController {
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueAzure),
position: position,
onTap: () => _customInfoWindowControllerSignal.value.addInfoWindow!(
MarkerInfoWindow(
title: 'Resultado da Busca',
textContent: placeDetails.result!.name ??
'Latitude: ${placeLocation.lat!}\rLongitude: ${placeLocation.lng!}'),
position),
MarkerInfoWindow(
title: 'Resultado da Busca',
textContent: placeDetails.result!.name ??
'Latitude: ${placeLocation.lat!}\rLongitude: ${placeLocation.lng!}',
),
position,
),
);
updateCameraGoogleMapsController(position);
changeDraggableSheet(DraggableScrollableSheetTypes.place(
placeDetails: placeDetails, position: position));
placeDetails: placeDetails,
position: position,
baseMapController: this,
));
}

void removeMarkerByKey(key) {
markersSignal.value.remove(key);
}

void loadSpotholeMarkers(context) {
databaseReference.child('spotholes').once().then(
(DatabaseEvent event) {
final spotholesMap = event.snapshot.value as Map?;
if (spotholesMap != null) {
spotholesMap.forEach(
(key, value) {
final spothole =
Spothole.fromJson(Map<String, dynamic>.from(value as Map));
spothole.id = key;
spotholeInfoWindowController!
.addSpotholeMarker(context, spothole);
},
);
}
},
);
}

void registerSpothole(context, position, category, type) {
final newSpotHoleRef = dataBaseSpotholesRef.push();
final newSpothole = Spothole(DateTime.now().toUtc(), DateTime.now().toUtc(),
position, category, type, null, newSpotHoleRef.key);
newSpotHoleRef.set(newSpothole.toJson());
spotholeInfoWindowController!.addSpotholeMarker(context, newSpothole);
void loadSpotholeMarkers() {
_spotholeService.loadSpotholeMarkers();
}

void registerSpotholeModal(context, {LatLng? position}) {
final latLng = position ?? currentLocationLatLng;
showModalBottomSheet(
context: context,
builder: (builder) {
return RegisterSpotholeModal(
title: "Para alertar um risco, selecione:",
textOnRegisterButton: "Adicionar",
onRegister: (riskCategory, type) =>
registerSpothole(context, latLng, riskCategory, type),
);
},
);
void registerSpotholeModal([LatLng? position]) {
final registerPosition = position ?? currentLocationLatLng;
_spotholeService.registerSpotholeModal(registerPosition);
}

void onLongPress(BuildContext context, LatLng position) async {
Expand All @@ -196,28 +184,34 @@ class BaseMapController {
WidgetsBinding.instance.addPostFrameCallback(
(_) {
CustomSnackbar.show(
context: context,
message:
'Não foi possível carregar informações, verifique a conexão com a internet');
context: context,
message:
'Não foi possível carregar informações, verifique a conexão com a internet',
);
},
);
}
_markersSignal.value['longPressed'] = Marker(
markerId: MarkerId(position.toString()),
position: position,
onTap: () => _customInfoWindowControllerSignal.value.addInfoWindow!(
MarkerInfoWindow(
title: 'Local Aproximado',
textContent: windowInfo,
),
position),
MarkerInfoWindow(
title: 'Local Aproximado',
textContent: windowInfo,
),
position,
),
);
changeDraggableSheet(
DraggableScrollableSheetTypes.location(
position: position,
formattedPlacemark: formattedPlacemark,
onRegister: () => registerSpotholeModal(context, position: position),
baseMapController: this,
),
);
}

dispose() {
_dispose!();
}
}
Loading

0 comments on commit 62b7245

Please sign in to comment.