Skip to content

Commit

Permalink
First version finished
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandra Makarova authored and Alexandra Makarova committed Dec 16, 2020
1 parent 535841a commit af99b55
Show file tree
Hide file tree
Showing 41 changed files with 2,512 additions and 18 deletions.
3 changes: 3 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linter:
rules:
close_sink: false
4 changes: 4 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
android:name="io.flutter.app.FlutterApplication"
android:label="maps_app"
android:icon="@mipmap/ic_launcher">

<meta-data android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyAL7Puw6dcKE27WtW_IpXUGXngPhyN_odg"/>

<activity
android:name=".MainActivity"
android:launchMode="singleTop"
Expand Down
Binary file added assets/custom-pin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
165 changes: 165 additions & 0 deletions lib/bloc/map/map_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import 'dart:async';
import 'dart:convert';

import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart' show Colors, Offset;
import 'package:maps_app/helpers/helpers.dart';
import 'package:meta/meta.dart';

import 'package:google_maps_flutter/google_maps_flutter.dart';

import '../../themes/uber_style_map_theme.dart';

part 'map_event.dart';
part 'map_state.dart';

class MapBloc extends Bloc<MapEvent, MapState> {
MapBloc() : super(new MapState());

//Map Controller
GoogleMapController _mapController;

//Polylines
Polyline _myRoute = new Polyline(
polylineId: PolylineId('my_route'),
width: 3,
color: Colors.transparent,
);

Polyline _myDestinationRoute = new Polyline(
polylineId: PolylineId('my_destination_route'),
width: 3,
color: Colors.deepPurple[400],
);

void initMap(GoogleMapController controller) {
if (!state.isMapReady) {
this._mapController = controller;

this._mapController.setMapStyle(jsonEncode(uberStyleMapTheme));

add(OnMapLoaded());
}
}

void moveCamera(LatLng destination) {
final cameraUpdate = CameraUpdate.newLatLng(destination);
this._mapController?.animateCamera(cameraUpdate);
}

@override
Stream<MapState> mapEventToState(MapEvent event) async* {
if (event is OnMapLoaded) {
yield state.copyWith(isMapReady: true);
} else if (event is OnMapLocationChange) {
yield* this._onMapLocationChange(event);
} else if (event is OnShowRoute) {
yield* this._onShowRoute(event);
} else if (event is OnFollowLocation) {
yield* this._onFollowLocation(event);
} else if (event is OnMapHasMoved) {
yield state.copyWith(centralLocation: event.mapCenter);
} else if (event is OnCreateRouteStartDestination) {
yield* this._onCreateRouteStartDestination(event);
}
}

Stream<MapState> _onMapLocationChange(OnMapLocationChange event) async* {
if (state.followLocation) {
this.moveCamera(event.location);
}

final points = [...this._myRoute.points, event.location];
this._myRoute = this._myRoute.copyWith(pointsParam: points);

final currentPolylines = state.polylines;
currentPolylines['my_route'] = this._myRoute;

yield state.copyWith(polylines: currentPolylines);
}

Stream<MapState> _onShowRoute(OnShowRoute event) async* {
if (!state.drawRoute) {
this._myRoute = this._myRoute.copyWith(colorParam: Colors.deepPurple);
} else {
this._myRoute = this._myRoute.copyWith(colorParam: Colors.transparent);
}

final currentPolylines = state.polylines;
currentPolylines['my_route'] = this._myRoute;

yield state.copyWith(
drawRoute: !state.drawRoute,
polylines: currentPolylines,
);
}

Stream<MapState> _onFollowLocation(OnFollowLocation event) async* {
if (!state.followLocation) {
this.moveCamera(this._myRoute.points[this._myRoute.points.length - 1]);
}
yield state.copyWith(followLocation: !state.followLocation);
}

Stream<MapState> _onCreateRouteStartDestination(
OnCreateRouteStartDestination event) async* {
this._myDestinationRoute =
this._myDestinationRoute.copyWith(pointsParam: event.coordinatesRoute);

final currentPolylines = state.polylines;
currentPolylines['my_destination_route'] = this._myDestinationRoute;

//Icon Start
// final startIcon = await getAssetImagemMarker();
// final destinationIcon = await getNetworkImageMarker();
final startIcon = await getStartMarkerIcon(event.duration.toInt());

final destinationIcon =
await getDestinationMarkerIcon(event.destinationName, event.distance);

final markerStart = new Marker(
anchor: Offset(0.0, 1.0),
markerId: MarkerId('start'),
position: event.coordinatesRoute[0],
icon: startIcon,
infoWindow: InfoWindow(
title: 'My Location',
snippet: 'Travel duration: ${(event.duration / 60).floor()} minutes',
anchor: Offset(0.5, 0),
onTap: () {
print('infoWindowTap');
},
),
);

double km = (((event.distance / 1000) * 100).floor().toDouble()) / 100;

final markerDestination = new Marker(
anchor: Offset(0.1, 0.9),
markerId: MarkerId('destination'),
position: event.coordinatesRoute[event.coordinatesRoute.length - 1],
icon: destinationIcon,
infoWindow: InfoWindow(
title: event.destinationName,
snippet: 'Distance: ${km} km',
anchor: Offset(0.5, 0),
onTap: () {
print('infoWindowTap');
},
));

final newMarkers = {...state.markers};
newMarkers['start'] = markerStart;
newMarkers['destination'] = markerDestination;

Future.delayed(Duration(microseconds: 300)).then((value) {
// _mapController.showMarkerInfoWindow(MarkerId('start'));
// _mapController.showMarkerInfoWindow(MarkerId('destination'));
});

yield state.copyWith(
polylines: currentPolylines,
markers: newMarkers,
);
}
}
31 changes: 31 additions & 0 deletions lib/bloc/map/map_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
part of 'map_bloc.dart';

@immutable
abstract class MapEvent {}

class OnMapLoaded extends MapEvent {}

class OnShowRoute extends MapEvent {}

class OnFollowLocation extends MapEvent {}

class OnCreateRouteStartDestination extends MapEvent {
final List<LatLng> coordinatesRoute;
final double distance;
final double duration;
final String destinationName;

OnCreateRouteStartDestination(this.coordinatesRoute, this.distance,
this.duration, this.destinationName);
}

class OnMapLocationChange extends MapEvent {
final LatLng location;
OnMapLocationChange(this.location);
}

class OnMapHasMoved extends MapEvent {
final LatLng mapCenter;

OnMapHasMoved(this.mapCenter);
}
40 changes: 40 additions & 0 deletions lib/bloc/map/map_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
part of 'map_bloc.dart';

@immutable
class MapState {
final bool isMapReady;
final bool drawRoute;
final bool followLocation;
final LatLng centralLocation;

//Polylines
final Map<String, Polyline> polylines;
final Map<String, Marker> markers;

MapState({
this.isMapReady = false,
this.drawRoute = false,
this.followLocation = false,
this.centralLocation,
Map<String, Polyline> polylines,
Map<String, Marker> markers,
}) : this.polylines = polylines ?? new Map(),
this.markers = markers ?? new Map();

MapState copyWith({
bool isMapReady,
bool drawRoute,
bool followLocation,
LatLng centralLocation,
Map<String, Polyline> polylines,
Map<String, Marker> markers,
}) =>
MapState(
isMapReady: isMapReady ?? this.isMapReady,
polylines: polylines ?? this.polylines,
markers: markers ?? this.markers,
centralLocation: centralLocation ?? this.centralLocation,
followLocation: followLocation ?? this.followLocation,
drawRoute: drawRoute ?? this.drawRoute,
);
}
39 changes: 39 additions & 0 deletions lib/bloc/my_location/my_location_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart' show LatLng;

part 'my_location_event.dart';
part 'my_location_state.dart';

class MyLocationBloc extends Bloc<MyLocationEvent, MyLocationState> {
MyLocationBloc() : super(MyLocationState());

StreamSubscription<Position> _positionSubscription;

void startFollow() {
this._positionSubscription = Geolocator.getPositionStream(
desiredAccuracy: LocationAccuracy.lowest,
distanceFilter: 10,
).listen((Position position) {
final newLocation = new LatLng(position.latitude, position.longitude);
add(OnLocationChange(newLocation));
});
}

void stopFollow() {
_positionSubscription?.cancel();
}

@override
Stream<MyLocationState> mapEventToState(MyLocationEvent event) async* {
if (event is OnLocationChange) {
yield state.copyWith(
locationExists: true,
location: event.location,
);
}
}
}
9 changes: 9 additions & 0 deletions lib/bloc/my_location/my_location_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
part of 'my_location_bloc.dart';

@immutable
abstract class MyLocationEvent {}

class OnLocationChange extends MyLocationEvent {
final LatLng location;
OnLocationChange(this.location);
}
25 changes: 25 additions & 0 deletions lib/bloc/my_location/my_location_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
part of 'my_location_bloc.dart';

@immutable
class MyLocationState {
final bool follow;
final bool locationExists;
final LatLng location;

MyLocationState({
this.follow = true,
this.locationExists = false,
this.location,
});

MyLocationState copyWith({
bool follow,
bool locationExists,
LatLng location,
}) =>
new MyLocationState(
follow: follow ?? this.follow,
locationExists: locationExists ?? this.locationExists,
location: location ?? this.location,
);
}
32 changes: 32 additions & 0 deletions lib/bloc/search/search_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';

import '../../models/search_result.dart';

part 'search_event.dart';
part 'search_state.dart';

class SearchBloc extends Bloc<SearchEvent, SearchState> {
SearchBloc() : super(SearchState());

@override
Stream<SearchState> mapEventToState(SearchEvent event) async* {
if (event is OnActivateManualMarker) {
yield state.copyWith(manualSelection: true);
} else if (event is OnDesactivateManualMarker) {
yield state.copyWith(manualSelection: false);
} else if (event is OnAddHistorial) {
final isExist = state.historial
.where((result) =>
result.destinationName == event.result.destinationName)
.length;

if (isExist == 0) {
final newHistorial = [...state.historial, event.result];
yield state.copyWith(historial: newHistorial);
}
}
}
}
13 changes: 13 additions & 0 deletions lib/bloc/search/search_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
part of 'search_bloc.dart';

@immutable
abstract class SearchEvent {}

class OnActivateManualMarker extends SearchEvent {}

class OnDesactivateManualMarker extends SearchEvent {}

class OnAddHistorial extends SearchEvent {
final SearchResult result;
OnAddHistorial(this.result);
}
20 changes: 20 additions & 0 deletions lib/bloc/search/search_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
part of 'search_bloc.dart';

@immutable
class SearchState {
final bool manualSelection;
final List<SearchResult> historial;

SearchState({
this.manualSelection = false,
List<SearchResult> historial,
}) : this.historial = (historial == null) ? [] : historial;

SearchState copyWith({
bool manualSelection,
List<SearchResult> historial,
}) =>
SearchState(
manualSelection: manualSelection ?? this.manualSelection,
historial: historial ?? this.historial);
}
Loading

0 comments on commit af99b55

Please sign in to comment.