From 8926fc20d9949e9dda4eade1ae956350f206e13f Mon Sep 17 00:00:00 2001 From: "Vicente J. Ruiz Jurado" Date: Thu, 26 Jul 2018 22:32:30 +0200 Subject: [PATCH] Fire notification map --- lib/activeFires.dart | 4 +-- lib/fireNotificationList.dart | 11 +++--- lib/generated/i18n.dart | 6 ++++ lib/{yourLocationMap.dart => genericMap.dart} | 35 ++++++++++++------- ...onMapBottom.dart => genericMapBottom.dart} | 28 +++++++++++++-- lib/mainDrawer.dart | 2 +- lib/models/fireMapState.dart | 14 ++++++-- lib/redux/fireMapActions.dart | 7 ++++ lib/redux/fireMapReducer.dart | 15 ++++++-- lib/sandbox.dart | 2 +- res/values/strings_en.arb | 2 ++ res/values/strings_es.arb | 2 ++ 12 files changed, 99 insertions(+), 29 deletions(-) rename lib/{yourLocationMap.dart => genericMap.dart} (92%) rename lib/{yourLocationMapBottom.dart => genericMapBottom.dart} (63%) diff --git a/lib/activeFires.dart b/lib/activeFires.dart index c6934f4..8833093 100644 --- a/lib/activeFires.dart +++ b/lib/activeFires.dart @@ -15,7 +15,7 @@ import 'mainDrawer.dart'; import 'models/appState.dart'; import 'placesAutocompleteUtils.dart'; import 'redux/actions.dart'; -import 'yourLocationMap.dart'; +import 'genericMap.dart'; @immutable class _ViewModel { @@ -225,7 +225,7 @@ class _ActiveFiresPageState extends State { Store store, YourLocation loc, BuildContext context) { store.dispatch(new ShowYourLocationMapAction(loc)); Navigator.push(context, - new MaterialPageRoute(builder: (context) => new YourLocationMap())); + new MaterialPageRoute(builder: (context) => new genericMap())); } void onAddYourLocation(AddYourLocationFunction onAdd) { diff --git a/lib/fireNotificationList.dart b/lib/fireNotificationList.dart index 9657ea4..89483b6 100644 --- a/lib/fireNotificationList.dart +++ b/lib/fireNotificationList.dart @@ -11,7 +11,7 @@ import 'generated/i18n.dart'; import 'mainDrawer.dart'; import 'models/appState.dart'; import 'redux/actions.dart'; -// import 'fireNotificationMap.dart'; +import 'genericMap.dart'; @immutable class _ViewModel { @@ -145,6 +145,9 @@ class _FireNotificationListState extends State { store.dispatch(new ReadFireNotificationAction( notif.copyWith(read: true))); } + new Timer(new Duration(milliseconds: 1000), () { + gotoMap(store, notif, context); + }); }, fireNotifications: store.state.fireNotifications); }, @@ -193,11 +196,11 @@ class _FireNotificationListState extends State { }); } - void gotoLocationMap( + void gotoMap( Store store, FireNotification notif, BuildContext context) { - /* store.dispatch(new ShowFireNotificationMapAction(notif)); + store.dispatch(new ShowFireNotificationMapAction(notif)); Navigator.push(context, - new MaterialPageRoute(builder: (context) => new FireNotificationMap())); */ + new MaterialPageRoute(builder: (context) => new genericMap())); } _showConfirmDialog(_ViewModel view) { diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index 48e7497..fb246ec 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -46,8 +46,10 @@ class S implements WidgetsLocalizations { String get confirm => "Confirm"; String get deleteAllFireNotificationsAlertDescription => "This will remove all your fire notifications"; String get errorFirePlaceDialog => "We couldn't get the location of the fire"; + String get fireNotificationTitle => "Fire Notification"; String get fireNotificationsDescription => "Here you will receive fire notifications in locations you are subscribed to"; String get fireNotificationsTitle => "Fire Notifications"; + String get fireNotificationsTitleShort => "Notifications"; String get firesInTheWorld => "Active fires in the world"; String get firesInYourPlaces => "Active fires in your places"; String get firesNearPlace => "Fires near other place"; @@ -127,6 +129,8 @@ class es extends S { @override String get notPermsUbication => "No tenemos permisos para conocer tu ubicación"; @override + String get fireNotificationTitle => "Notificación de fuego"; + @override String get youDeletedThisPlace => "Has borrado este lugar"; @override String get callEmergencyServicesTitle => "Llama al 112"; @@ -151,6 +155,8 @@ class es extends S { @override String get isYourUbicationEnabled => "No podemos saber tu ubicación actual. ¿Están los servicios de ubicación en tu móvil activados?"; @override + String get fireNotificationsTitleShort => "Notificaciones"; + @override String get DELETE => "BORRAR"; @override String get aDay => "un día"; diff --git a/lib/yourLocationMap.dart b/lib/genericMap.dart similarity index 92% rename from lib/yourLocationMap.dart rename to lib/genericMap.dart index f8a3a97..ec85fd1 100644 --- a/lib/yourLocationMap.dart +++ b/lib/genericMap.dart @@ -15,12 +15,12 @@ import 'dummyMapPlugin.dart'; import 'fireMarkType.dart'; import 'fireMarker.dart'; import 'generated/i18n.dart'; +import 'genericMapBottom.dart'; import 'globals.dart' as globals; import 'models/appState.dart'; import 'models/fireMapState.dart'; import 'redux/actions.dart'; import 'slider.dart'; -import 'yourLocationMapBottom.dart'; import 'zoomMapPlugin.dart'; @immutable @@ -57,12 +57,12 @@ class _ViewModel { int get hashCode => mapState.hashCode; } -class YourLocationMap extends StatefulWidget { +class genericMap extends StatefulWidget { @override - _YourLocationMapState createState() => _YourLocationMapState(); + _genericMapState createState() => _genericMapState(); } -class _YourLocationMapState extends State { +class _genericMapState extends State { // This needs to be stateful so when resizes don't get a new globalkey // https://github.com/flutter/flutter/issues/1632#issuecomment-180478202 final GlobalKey _scaffoldKey = new GlobalKey(); @@ -128,7 +128,6 @@ class _YourLocationMapState extends State { // THIS does not works as expected // maxZoom: 6.0, onTap: (callback) { - print('On tap ${callback}'); if (status == FireMapStatus.edit) { _location = _location.copyWith( lat: callback.latitude, lon: callback.longitude); @@ -172,8 +171,12 @@ class _YourLocationMapState extends State { ? new ZoomMapPluginOptions() : new DummyMapPluginOptions(), new MarkerLayerOptions( - markers: buildMarkers(_location, mapState.fires, - mapState.industries, mapState.falsePos), + markers: buildMarkers( + _location, + mapState.fires, + mapState.industries, + mapState.falsePos, + mapState.fireNotification != null), ), ], ); @@ -204,10 +207,13 @@ class _YourLocationMapState extends State { _location = _location.copyWith(description: newDesc); }, ) - : new Text(_location.description), + : status == FireMapStatus.viewFireNotification + ? new Text(S.of(context).fireNotificationTitle) + : new Text(_location.description), actions: buildAppBarActions(status, view, _location), ), - floatingActionButton: status == FireMapStatus.edit + floatingActionButton: status == FireMapStatus.edit || + status == FireMapStatus.viewFireNotification ? null : FloatingActionButton.extended( onPressed: () { @@ -224,6 +230,7 @@ class _YourLocationMapState extends State { view.onUnSubs(_location); break; case FireMapStatus.edit: + case FireMapStatus.viewFireNotification: break; } }, @@ -238,7 +245,7 @@ class _YourLocationMapState extends State { ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, - bottomNavigationBar: new YourLocationMapBottom( + bottomNavigationBar: new GenericMapBottom( onSave: () => view.onEditConfirm(_location), onCancel: () => view.onEditCancel(_initialLocation), state: view.mapState), @@ -298,10 +305,11 @@ class _YourLocationMapState extends State { } List buildMarkers(YourLocation yourLocation, List fires, - List falsePos, List industries) { + List falsePos, List industries, bool isNotif) { List markers = []; const calibrate = false; // useful when we change the fire icons size - markers.add(FireMarker(yourLocation, FireMarkType.position)); + markers.add(FireMarker( + yourLocation, isNotif ? FireMarkType.fire : FireMarkType.position)); if (calibrate) markers.add(FireMarker(yourLocation, FireMarkType.pixel)); falsePos.forEach((fire) { var coords = fire['geo']['coordinates']; @@ -318,7 +326,8 @@ class _YourLocationMapState extends State { }); fires.forEach((fire) { var loc = new BasicLocation(lat: fire['lat'], lon: fire['lon']); - markers.add(FireMarker(loc, FireMarkType.fire, () => print('marker pressed'))); + markers.add( + FireMarker(loc, FireMarkType.fire, () => print('marker pressed'))); markers.add(FireMarker(loc, FireMarkType.pixel)); }); return markers; diff --git a/lib/yourLocationMapBottom.dart b/lib/genericMapBottom.dart similarity index 63% rename from lib/yourLocationMapBottom.dart rename to lib/genericMapBottom.dart index 3fd3b02..77d96ae 100644 --- a/lib/yourLocationMapBottom.dart +++ b/lib/genericMapBottom.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'colors.dart'; import 'customBottomAppBar.dart'; +import 'customMoment.dart'; import 'generated/i18n.dart'; import 'models/appState.dart'; import 'models/fireMapState.dart'; @@ -10,12 +11,13 @@ import 'models/fireMapState.dart'; typedef void OnSave(); typedef void OnCancel(); -class YourLocationMapBottom extends StatelessWidget { +class GenericMapBottom extends StatelessWidget { final OnSave onSave; final OnCancel onCancel; final FireMapState state; - YourLocationMapBottom({@required this.onSave,@required this.onCancel,@required this.state}); + GenericMapBottom( + {@required this.onSave, @required this.onCancel, @required this.state}); @override Widget build(BuildContext context) { @@ -25,7 +27,6 @@ class YourLocationMapBottom extends StatelessWidget { fabLocation: FloatingActionButtonLocation.centerFloat, showNotch: false, color: fires100, - // height: 170.0, mainAxisAlignment: MainAxisAlignment.center, actions: buildActionList(loc, context, kmAround)); } @@ -46,6 +47,27 @@ class YourLocationMapBottom extends StatelessWidget { break; case FireMapStatus.subscriptionConfirm: break; + case FireMapStatus.viewFireNotification: + actionList.add(new Flexible( + child: new Padding( + padding: new EdgeInsets.all(10.0), + child: new Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + new Text(state.fireNotification.description), + new SizedBox(height: 5.0), + new Row( + children: [ + new Icon(Icons.access_time), + new SizedBox(width: 5.0), + new Text(Moment + .now() + .from(context, state.fireNotification.when)) + ], + ) + ])))); + break; case FireMapStatus.unsubscribe: case FireMapStatus.view: if (state.numFires != null) { diff --git a/lib/mainDrawer.dart b/lib/mainDrawer.dart index 8dc2b74..5eaa907 100644 --- a/lib/mainDrawer.dart +++ b/lib/mainDrawer.dart @@ -67,7 +67,7 @@ Widget mainDrawer(BuildContext context) { ), new ListTile( leading: const Icon(Icons.notifications), - title: new Text(S.of(context).fireNotificationsTitle), + title: new Text(S.of(context).fireNotificationsTitleShort), onTap: () { // Then close the drawer Navigator.pop(context); diff --git a/lib/models/fireMapState.dart b/lib/models/fireMapState.dart index 8551aba..08a8961 100644 --- a/lib/models/fireMapState.dart +++ b/lib/models/fireMapState.dart @@ -1,12 +1,14 @@ import 'package:fires_flutter/models/yourLocation.dart'; +import 'package:fires_flutter/models/fireNotification.dart'; import 'package:meta/meta.dart'; -enum FireMapStatus { view, subscriptionConfirm, unsubscribe, edit } +enum FireMapStatus { view, subscriptionConfirm, unsubscribe, edit, viewFireNotification } @immutable class FireMapState { final FireMapStatus status; final int numFires; + final FireNotification fireNotification; final List fires; final List falsePos; final List industries; @@ -15,6 +17,7 @@ class FireMapState { const FireMapState.initial() : this.status = FireMapStatus.view, this.yourLocation = null, + this.fireNotification = null, this.numFires = 0, this.fires = const [], this.falsePos = const [], @@ -24,13 +27,15 @@ class FireMapState { {this.status: FireMapStatus.view, this.yourLocation, this.numFires, - this.fires, + this.fires, + this.fireNotification, this.falsePos, this.industries}); FireMapState copyWith({ FireMapStatus status, YourLocation yourLocation, + FireNotification fireNotication, int numFires, List fires, List falsePos, @@ -38,6 +43,7 @@ class FireMapState { }) { return new FireMapState( yourLocation: yourLocation ?? this.yourLocation, + fireNotification: fireNotication ?? this.fireNotification, numFires: numFires ?? this.numFires, fires: fires ?? this.fires, falsePos: falsePos ?? this.falsePos, @@ -52,6 +58,7 @@ class FireMapState { runtimeType == other.runtimeType && status == other.status && numFires == other.numFires && + fireNotification == other.fireNotification && fires == other.fires && falsePos == other.falsePos && industries == other.industries && @@ -61,6 +68,7 @@ class FireMapState { int get hashCode => status.hashCode ^ numFires.hashCode ^ + fireNotification.hashCode ^ fires.hashCode ^ falsePos.hashCode ^ industries.hashCode ^ @@ -70,6 +78,6 @@ class FireMapState { String toString() { return 'FireMapState{status: $status, numFires: $numFires, fires: ${fires .length}, falsePos: ${falsePos.length}, industries: ${industries - .length}, yourLocation: $yourLocation}'; + .length}, yourLocation: $yourLocation, fireNotification: $fireNotification}'; } } diff --git a/lib/redux/fireMapActions.dart b/lib/redux/fireMapActions.dart index 3ed8d14..0535552 100644 --- a/lib/redux/fireMapActions.dart +++ b/lib/redux/fireMapActions.dart @@ -1,4 +1,5 @@ import 'package:fires_flutter/models/yourLocation.dart'; +import 'package:fires_flutter/models/fireNotification.dart'; import 'package:meta/meta.dart'; abstract class FiresMapActions {} @@ -30,6 +31,12 @@ class ShowYourLocationMapAction extends FiresMapActions { ShowYourLocationMapAction(this.loc); } +class ShowFireNotificationMapAction extends FiresMapActions { + FireNotification notif; + + ShowFireNotificationMapAction(this.notif); +} + class EditYourLocationAction extends FiresMapActions { YourLocation loc; diff --git a/lib/redux/fireMapReducer.dart b/lib/redux/fireMapReducer.dart index f1cd89d..01e84d3 100644 --- a/lib/redux/fireMapReducer.dart +++ b/lib/redux/fireMapReducer.dart @@ -1,11 +1,13 @@ import 'package:redux/redux.dart'; - +import 'package:fires_flutter/models/yourLocation.dart'; import '../models/fireMapState.dart'; import 'actions.dart'; final fireMapReducer = combineReducers([ new TypedReducer( _showYourLocationMap), + new TypedReducer( + _showFireNotificationMap), new TypedReducer( _updateYourLocationMapStats), new TypedReducer(_subscribeYourLocationMap), @@ -45,6 +47,14 @@ FireMapState _showYourLocationMap( yourLocation: action.loc); } +FireMapState _showFireNotificationMap( + FireMapState state, ShowFireNotificationMapAction action) { + // TODO: use here you real location? + YourLocation pseudoLoc = new YourLocation(lat: action.notif.lat, lon: action.notif.lon, description: action.notif.description); + return state.copyWith( + status: FireMapStatus.viewFireNotification, yourLocation: pseudoLoc, fireNotication: action.notif); +} + FireMapState _subscribeYourLocationMap( FireMapState state, SubscribeAction action) { return state.copyWith(status: FireMapStatus.subscriptionConfirm); @@ -52,7 +62,8 @@ FireMapState _subscribeYourLocationMap( FireMapState _subscribeConfirmYourLocationMap( FireMapState state, SubscribeConfirmAction action) { - return state.copyWith(status: FireMapStatus.unsubscribe, yourLocation: action.loc); + return state.copyWith( + status: FireMapStatus.unsubscribe, yourLocation: action.loc); } FireMapState _unsubscribeYourLocationMap( diff --git a/lib/sandbox.dart b/lib/sandbox.dart index 8d312f7..ff0fc35 100644 --- a/lib/sandbox.dart +++ b/lib/sandbox.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; /* Useful for debug import 'package:fluttery/framing.dart'; -new RandomColorBlock( child: +new RandomColorBlock( child */ class Sandbox extends StatelessWidget { diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 1c1d31a..ad04576 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -53,7 +53,9 @@ "tweetAboutAFireTitle": "Tweet about", "tweetAboutAFireDescription": "Additionally if you use twitter you can share additional information with the emergency services, for example, attaching photos to the tweet if you have good visibility of the fire, when you took the photos, exact location, etc. Use #hashtags type #IFMinicipalTerminal for example #IFJumilla (Forest Fire in Jumilla).", "supportPageDescription": "You can support this initiative, spreading the word, helping us to develop our software, translating this app to your language, etc.", + "fireNotificationsTitleShort": "Notifications", "fireNotificationsTitle": "Fire Notifications", + "fireNotificationTitle": "Fire Notification", "fireNotificationsDescription": "Here you will receive fire notifications in locations you are subscribed to", "areYouSureTitle": "Are you sure?", "deleteAllFireNotificationsAlertDescription": "This will remove all your fire notifications", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index d07088f..6dcc371 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -54,6 +54,8 @@ "tweetAboutAFireDescription": "Adicionalmente si usas twitter puedes compartir información adicional con los servicios de emergencia, por ejemplo, adjuntando fotos al tweet si tienes buena visibilidad del fuego, cuando tomaste las fotos, ubicación exacta, etc. Usa #hashtags tipo #IFTerminoMunicipal por ejemplo #IFJumilla (Incendio Forestal en Jumilla).", "supportPageDescription": "Puedes apoyar esta iniciativa, dando difusión, ayudándonos a desarrollar nuestro software, traduciendo esta aplicación a tu idioma, etc.", "fireNotificationsTitle": "Notificaciones de fuegos", + "fireNotificationTitle": "Notificación de fuego", + "fireNotificationsTitleShort": "Notificaciones", "fireNotificationsDescription": "Aquí recibirás las notificaciones de fuegos en los lugares a los que te subscribas", "areYouSureTitle": "¿Seguro?", "deleteAllFireNotificationsAlertDescription": "Esto borrará todas las notificaciones de fuegos",