Fire notification map

This commit is contained in:
Vicente J. Ruiz Jurado 2018-07-26 22:32:30 +02:00
parent b7468de0d1
commit 8926fc20d9
12 changed files with 99 additions and 29 deletions

View file

@ -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<ActiveFiresPage> {
Store<AppState> 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) {

View file

@ -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<FireNotificationList> {
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<FireNotificationList> {
});
}
void gotoLocationMap(
void gotoMap(
Store<AppState> 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) {

View file

@ -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";

View file

@ -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<YourLocationMap> {
class _genericMapState extends State<genericMap> {
// 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<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@ -128,7 +128,6 @@ class _YourLocationMapState extends State<YourLocationMap> {
// 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<YourLocationMap> {
? 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<YourLocationMap> {
_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<YourLocationMap> {
view.onUnSubs(_location);
break;
case FireMapStatus.edit:
case FireMapStatus.viewFireNotification:
break;
}
},
@ -238,7 +245,7 @@ class _YourLocationMapState extends State<YourLocationMap> {
),
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<YourLocationMap> {
}
List<Marker> buildMarkers(YourLocation yourLocation, List<dynamic> fires,
List<dynamic> falsePos, List<dynamic> industries) {
List<dynamic> falsePos, List<dynamic> industries, bool isNotif) {
List<Marker> 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<YourLocationMap> {
});
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;

View file

@ -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: <Widget>[
new Text(state.fireNotification.description),
new SizedBox(height: 5.0),
new Row(
children: <Widget>[
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) {

View file

@ -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);

View file

@ -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<dynamic> fires;
final List<dynamic> falsePos;
final List<dynamic> 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<dynamic> fires,
List<dynamic> 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}';
}
}

View file

@ -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;

View file

@ -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<FireMapState>([
new TypedReducer<FireMapState, ShowYourLocationMapAction>(
_showYourLocationMap),
new TypedReducer<FireMapState, ShowFireNotificationMapAction>(
_showFireNotificationMap),
new TypedReducer<FireMapState, UpdateYourLocationMapStatsAction>(
_updateYourLocationMapStats),
new TypedReducer<FireMapState, SubscribeAction>(_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(

View file

@ -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 {

View file

@ -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",

View file

@ -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",