Line data Source code
1 : import 'dart:async';
2 :
3 : import 'package:app_pym/core/constants/mobility.dart';
4 : import 'package:app_pym/core/permission_handler/permission_handler.dart';
5 : import 'package:app_pym/core/utils/icons_utils.dart';
6 : import 'package:app_pym/domain/entities/mobility/trip.dart';
7 : import 'package:app_pym/presentation/blocs/mobility/trips/trips_bloc.dart';
8 : import 'package:app_pym/presentation/widgets/mobility/details_bottom_sheet.dart';
9 : import 'package:flutter/foundation.dart';
10 : import 'package:flutter/material.dart'
11 : show
12 : BorderRadiusDirectional,
13 : Color,
14 : Colors,
15 : Icons,
16 : Offset,
17 : Radius,
18 : RoundedRectangleBorder,
19 : ScaffoldState,
20 : TextStyle;
21 : import 'package:flutter_bloc/flutter_bloc.dart';
22 : import 'package:freezed_annotation/freezed_annotation.dart';
23 : import 'package:google_maps_flutter/google_maps_flutter.dart';
24 : import 'package:injectable/injectable.dart';
25 :
26 : part 'maps_bloc.freezed.dart';
27 : part 'maps_event.dart';
28 : part 'maps_state.dart';
29 :
30 : @prod
31 : @injectable
32 : class MapsBloc extends Bloc<MapsEvent, MapsState> {
33 : final PermissionHandler permissionHandler;
34 : Completer<GoogleMapController> controller = Completer<GoogleMapController>();
35 : final Set<Polyline> polylines = <Polyline>{};
36 : final Set<Marker> markers = <Marker>{};
37 :
38 0 : MapsBloc({
39 : @required this.permissionHandler,
40 : });
41 :
42 0 : @override
43 0 : MapsState get initialState => MapsState.initial();
44 :
45 : @override
46 0 : Stream<MapsState> mapEventToState(
47 : MapsEvent event,
48 : ) async* {
49 0 : yield* event.when(
50 0 : load: _mapLoadEventToState,
51 0 : appStarted: _mapAppStartedToState,
52 : );
53 : }
54 :
55 0 : Stream<MapsState> _mapAppStartedToState() async* {
56 0 : await permissionHandler.requestPermissionLocationWhenInUse;
57 0 : await permissionHandler.locationIsEnabled;
58 0 : yield state;
59 : }
60 :
61 0 : Stream<MapsState> _mapLoadEventToState(
62 : TripsState tripsState,
63 : ScaffoldState scaffoldState,
64 : ) async* {
65 0 : yield state.loading();
66 0 : markers.clear();
67 0 : polylines.clear();
68 : try {
69 0 : final busEndCap = await Icons.arrow_upward.toBitmapDescriptor(
70 : const TextStyle(color: Colors.blueGrey),
71 : size: 100,
72 : offset: const Offset(0.0, 48.0),
73 : );
74 0 : final trainEndCap = await Icons.arrow_upward.toBitmapDescriptor(
75 : const TextStyle(color: Colors.orange),
76 : size: 100,
77 : offset: const Offset(0.0, 48.0),
78 : );
79 0 : final busMarker = await Icons.fiber_manual_record.toBitmapDescriptor(
80 : const TextStyle(color: Colors.blue),
81 : size: 64,
82 : );
83 0 : final trainMarker = await Icons.fiber_manual_record.toBitmapDescriptor(
84 : const TextStyle(color: Colors.red),
85 : size: 64,
86 : );
87 :
88 0 : if (tripsState.isBusLoaded) {
89 0 : await Future.wait<void>([
90 0 : tripsState.busTrips[0].trace(
91 0 : markers,
92 0 : direction: tripsState.direction,
93 : isBus: true,
94 : markerIcon: busMarker,
95 0 : endCapIcon: Cap.customCapFromBitmap(busEndCap),
96 0 : polylineId: "bus_${tripsState.direction}_${Sens.Aller}_",
97 : color: Colors.blueGrey,
98 0 : onTapMarker: (markerId) {
99 0 : scaffoldState.showBottomSheet<void>(
100 0 : (context) => DetailsBottomSheet(
101 0 : tripsState.busTrips,
102 : isBus: true,
103 : markerId: markerId,
104 : ),
105 : shape: const RoundedRectangleBorder(
106 : borderRadius: BorderRadiusDirectional.only(
107 : topStart: Radius.circular(10.0),
108 : topEnd: Radius.circular(10.0),
109 : ),
110 : ),
111 : );
112 : },
113 0 : ).then(polylines.add),
114 0 : tripsState.busTrips[1].trace(
115 0 : markers,
116 0 : direction: tripsState.direction,
117 : isBus: true,
118 : markerIcon: busMarker,
119 0 : endCapIcon: Cap.customCapFromBitmap(busEndCap),
120 0 : polylineId: "bus_${tripsState.direction}_${Sens.Retour}_",
121 : color: Colors.blueGrey,
122 0 : onTapMarker: (markerId) {
123 0 : scaffoldState.showBottomSheet<void>(
124 0 : (context) => DetailsBottomSheet(
125 0 : tripsState.busTrips,
126 : isBus: true,
127 : markerId: markerId,
128 : ),
129 : shape: const RoundedRectangleBorder(
130 : borderRadius: BorderRadiusDirectional.only(
131 : topStart: Radius.circular(10.0),
132 : topEnd: Radius.circular(10.0),
133 : ),
134 : ),
135 : );
136 : },
137 0 : ).then(polylines.add),
138 : ]);
139 0 : yield state.busLoaded();
140 : }
141 0 : if (tripsState.isTrainLoaded) {
142 : //pour les trains, on traite différemment Aller et Partir car tous les trains ne vont pas à Aix
143 0 : if (tripsState.direction == Direction.Aller) {
144 0 : await Future.wait<void>([
145 0 : tripsState.trainTrips[0].trace(
146 0 : markers,
147 0 : direction: tripsState.direction,
148 : isBus: false,
149 : markerIcon: trainMarker,
150 0 : endCapIcon: Cap.customCapFromBitmap(trainEndCap),
151 0 : polylineId: "train_${tripsState.direction}_${Sens.Aller}_",
152 : color: Colors.orange,
153 0 : onTapMarker: (markerId) {
154 0 : scaffoldState.showBottomSheet<void>(
155 0 : (context) => DetailsBottomSheet(
156 0 : tripsState.trainTrips,
157 : isBus: false,
158 : markerId: markerId,
159 : ),
160 : shape: const RoundedRectangleBorder(
161 : borderRadius: BorderRadiusDirectional.only(
162 : topStart: Radius.circular(10.0),
163 : topEnd: Radius.circular(10.0),
164 : ),
165 : ),
166 : );
167 : },
168 0 : ).then(polylines.add),
169 0 : tripsState.trainTrips[7].trace(
170 0 : markers,
171 0 : direction: tripsState.direction,
172 : isBus: false,
173 : markerIcon: trainMarker,
174 0 : endCapIcon: Cap.customCapFromBitmap(trainEndCap),
175 0 : polylineId: "train_${tripsState.direction}_${Sens.Retour}_",
176 : color: Colors.orange,
177 0 : onTapMarker: (markerId) {
178 0 : scaffoldState.showBottomSheet<void>(
179 0 : (context) => DetailsBottomSheet(
180 0 : tripsState.trainTrips,
181 : isBus: false,
182 : markerId: markerId,
183 : ),
184 : shape: const RoundedRectangleBorder(
185 : borderRadius: BorderRadiusDirectional.only(
186 : topStart: Radius.circular(10.0),
187 : topEnd: Radius.circular(10.0),
188 : ),
189 : ),
190 : );
191 : },
192 0 : ).then(polylines.add),
193 : ]);
194 0 : yield state.trainLoaded();
195 : } else {
196 0 : await Future.wait<void>([
197 0 : tripsState.trainTrips[6].trace(
198 0 : markers,
199 0 : direction: tripsState.direction,
200 : isBus: false,
201 : markerIcon: trainMarker,
202 0 : endCapIcon: Cap.customCapFromBitmap(trainEndCap),
203 0 : polylineId: "train_${tripsState.direction}_${Sens.Aller}_",
204 : color: Colors.orange,
205 0 : onTapMarker: (markerId) {
206 0 : scaffoldState.showBottomSheet<void>(
207 0 : (context) => DetailsBottomSheet(
208 0 : tripsState.trainTrips,
209 : isBus: false,
210 : markerId: markerId,
211 : ),
212 : shape: const RoundedRectangleBorder(
213 : borderRadius: BorderRadiusDirectional.only(
214 : topStart: Radius.circular(10.0),
215 : topEnd: Radius.circular(10.0),
216 : ),
217 : ),
218 : );
219 : },
220 0 : ).then(polylines.add),
221 0 : tripsState.trainTrips[1].trace(
222 0 : markers,
223 0 : direction: tripsState.direction,
224 : isBus: false,
225 : markerIcon: trainMarker,
226 0 : endCapIcon: Cap.customCapFromBitmap(trainEndCap),
227 0 : polylineId: "train_${tripsState.direction}_${Sens.Retour}_",
228 : color: Colors.orange,
229 0 : onTapMarker: (markerId) {
230 0 : scaffoldState.showBottomSheet<void>(
231 0 : (context) => DetailsBottomSheet(
232 0 : tripsState.trainTrips,
233 : isBus: false,
234 : markerId: markerId,
235 : ),
236 : shape: const RoundedRectangleBorder(
237 : borderRadius: BorderRadiusDirectional.only(
238 : topStart: Radius.circular(10.0),
239 : topEnd: Radius.circular(10.0),
240 : ),
241 : ),
242 : );
243 : },
244 0 : ).then(polylines.add),
245 : ]);
246 0 : yield state.trainLoaded();
247 : }
248 : }
249 0 : } on Exception catch (e) {
250 0 : yield state.error(e);
251 : }
252 : }
253 : }
254 :
255 : extension on Trip {
256 0 : Future<Polyline> trace(
257 : Set<Marker> markers, {
258 : @required Direction direction,
259 : @required bool isBus,
260 : @required BitmapDescriptor markerIcon,
261 : @required Color color,
262 : @required String polylineId,
263 : @required void Function(String) onTapMarker,
264 : Cap endCapIcon = Cap.buttCap,
265 : Cap startCapIcon = Cap.buttCap,
266 : }) async {
267 : final points =
268 0 : await this.toPoints(direction, polylineId: polylineId).map((point) {
269 : final BitmapDescriptor icone =
270 0 : point.name.compareTo(MobilityConstants.gareGardanne) == 0 ||
271 0 : point.name.compareTo(MobilityConstants.pymStop) == 0
272 : ? BitmapDescriptor.defaultMarker
273 : : markerIcon;
274 : final String transportType = isBus ? 'Bus ' : 'TER ';
275 0 : final marker = point.toMarker(
276 : icon: icone,
277 0 : infoWindow: InfoWindow(
278 0 : title: transportType + this.route_id,
279 : snippet: this
280 0 : .stop_time
281 0 : .firstWhere(
282 0 : (stopTime) => stopTime.stop.stop_name == point.name)
283 0 : .arrival_time +
284 0 : ' -> ' +
285 0 : this.stop_time.last.stop.stop_name,
286 0 : onTap: () =>
287 0 : onTapMarker(point.name + '_${direction}_${this.direction_id}'),
288 : ),
289 : );
290 0 : markers.add(marker);
291 : return point;
292 0 : }).toList();
293 :
294 0 : return Polyline(
295 0 : polylineId: PolylineId(polylineId),
296 : color: color,
297 : points: points,
298 : endCap: endCapIcon,
299 : startCap: startCapIcon,
300 : visible: true,
301 : width: 4,
302 : );
303 : }
304 : }
|