diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index 4946ec5..5c83d9a 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -59,13 +59,19 @@ class S implements WidgetsLocalizations { String get firesNearPlace => "Fires near other place"; String get getAlertsOfFiresinThatArea => "Get alerts of fires in that area"; String get isYourUbicationEnabled => "I cannot get your current location. It's your ubication enabled?"; + String get itSeemsAControlledBurning => "It's a controlled burning"; + String get itSeemsAFalseAlarm => "It seems a false alarm"; + String get itSeemsAIndustry => "It's an industry"; + String get itSeemsNotAtForesFire => "It seems that this is not a forest fire."; String get noConnectivity => "This application needs an Internet connection to work"; String get noFiresAround => "There is no fires"; + String get notAWildfire => "Isn't that a forest fire?"; String get notPermsUbication => "We don't have permission to get your location"; String get notifyAFire => "Notify a fire"; String get privacyPolicy => "Privacy Policy"; String get supportPageDescription => "You can support this initiative, spreading the word, helping us to develop our software, translating this app to your language, suggesting other public data sources of fires to use, etc."; String get supportThisInitiative => "Support this initiative"; + String get thanksForParticipating => "Thanks for participating"; String get toDeleteThisNotification => "Slide horizontally to delete this notification"; String get toDeleteThisPlace => "Slide horizontally to delete this place"; String get toFiresNotifications => "Subscribe to fires notifications"; @@ -142,6 +148,10 @@ class es extends S { @override String get fireNotificationTitle => "Notificación de fuego"; @override + String get itSeemsAControlledBurning => "Es una quema controlada"; + @override + String get itSeemsAIndustry => "Es una industria"; + @override String get youDeletedThisPlace => "Has borrado este lugar"; @override String get callEmergencyServicesTitle => "Llama al 112"; @@ -154,6 +164,8 @@ class es extends S { @override String get aYear => "un año"; @override + String get itSeemsNotAtForesFire => "Parece que este fuego no es un fuego forestal."; + @override String get UNDO => "DESHACER"; @override String get tweetAboutAFireTitle => "Twittea"; @@ -170,6 +182,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 thanksForParticipating => "Gracias por Participar"; + @override String get fireNotificationsTitleShort => "Notificaciones"; @override String get DELETE => "BORRAR"; @@ -180,6 +194,8 @@ class es extends S { @override String get SHOW => "MOSTRAR"; @override + String get itSeemsAFalseAlarm => "Parece una falsa alarma"; + @override String get addedThisLocation => "Ya has añadido este lugar antes"; @override String get typeTheNameOfAPlace => "Escribe el nombre de un lugar, zona, etc"; @@ -210,6 +226,8 @@ class es extends S { @override String get CANCEL => "CANCELAR"; @override + String get notAWildfire => "¿No es un fuego forestal?"; + @override String inMonths(String value) => "$value meses"; @override String inYears(String value) => "$value años"; diff --git a/lib/genericMap.dart b/lib/genericMap.dart index 58ac92a..b2951af 100644 --- a/lib/genericMap.dart +++ b/lib/genericMap.dart @@ -292,7 +292,9 @@ class _genericMapState extends State { bottomNavigationBar: new GenericMapBottom( onSave: () => view.onEditConfirm(_location), onCancel: () => view.onEditCancel(_initialLocation), - state: view.mapState), + state: view.mapState, + scaffoldKey: _scaffoldKey, + ), body: LayoutBuilder( builder: (context, constraints) => Stack(fit: StackFit.expand, children: [ diff --git a/lib/genericMapBottom.dart b/lib/genericMapBottom.dart index 1c27d3d..1c9cff7 100644 --- a/lib/genericMapBottom.dart +++ b/lib/genericMapBottom.dart @@ -7,17 +7,20 @@ import 'customMoment.dart'; import 'generated/i18n.dart'; import 'models/appState.dart'; import 'models/fireMapState.dart'; +import 'package:comunes_flutter/comunes_flutter.dart'; typedef void OnSave(); typedef void OnCancel(); +typedef void OnFalsePositive(); class GenericMapBottom extends StatelessWidget { final OnSave onSave; final OnCancel onCancel; final FireMapState state; + final GlobalKey scaffoldKey; GenericMapBottom( - {@required this.onSave, @required this.onCancel, @required this.state}); + {@required this.onSave, @required this.onCancel, @required this.state, @required this.scaffoldKey}); @override Widget build(BuildContext context) { @@ -28,11 +31,11 @@ class GenericMapBottom extends StatelessWidget { showNotch: false, color: fires100, mainAxisAlignment: MainAxisAlignment.center, - actions: buildActionList(loc, context, kmAround)); + actions: buildActionList(loc, context, kmAround, scaffoldKey)); } List buildActionList( - YourLocation loc, BuildContext context, int kmAround) { + YourLocation loc, BuildContext context, int kmAround, GlobalKey scaffoldState) { List actionList = new List(); switch (state.status) { case FireMapStatus.edit: @@ -54,8 +57,9 @@ class GenericMapBottom extends StatelessWidget { child: new Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: listWithoutNulls([ new Text(state.fireNotification.description), + // TODO fire type (neighbout, NASA, etc) new SizedBox(height: 5.0), new Row( children: [ @@ -63,10 +67,29 @@ class GenericMapBottom extends StatelessWidget { new SizedBox(width: 5.0), new Text(Moment .now() - .from(context, state.fireNotification.when)) + .from(context, state.fireNotification.when)), ], - ) - ])))); + ), + state.industries.length >= 0 || state.falsePos.length > 0 ? new Text(S.of(context).itSeemsNotAtForesFire, style: new TextStyle(color: fires600)): null, + new DropdownButton( + style: new TextStyle( + color: Colors.black, + fontSize: 18.0, + ), + hint: new Text(S.of(context).notAWildfire), + items: [S.of(context).itSeemsAIndustry, S.of(context).itSeemsAControlledBurning, S.of(context).itSeemsAFalseAlarm].map((String value) { + return new DropdownMenuItem ( + value: value, + child: new Text(value) + ); + }).toList(), + onChanged: (value) { + // FIXME api call + scaffoldKey.currentState.showSnackBar(new SnackBar( + content: new Text(S.of(context).thanksForParticipating), + )); + }), + ]))))); break; case FireMapStatus.unsubscribe: case FireMapStatus.view: diff --git a/lib/models/firesApi.dart b/lib/models/firesApi.dart index 29f2754..cc77a5b 100644 --- a/lib/models/firesApi.dart +++ b/lib/models/firesApi.dart @@ -113,16 +113,15 @@ class FiresApi { }); } - Future getYourLocationFireStats( - AppState state, YourLocation location) async { + Future getFiresInLocation( + {AppState state, double lat, double lon, int distance}) async { assert(state.firesApiUrl != null); assert(state.firesApiKey != null); var url = '${state.firesApiUrl}fires-in-full/${state - .firesApiKey}/${location.lat}/${location.lon}/${location.distance}'; + .firesApiKey}/${lat}/${lon}/${distance}'; return await resty.get(url).go().then((response) { if (response.statusCode == 200) { var resultDecoded = json.decode(response.body); - // print(resultDecoded); int numFires = resultDecoded['real']; List fires = resultDecoded['fires']; List falsePos = resultDecoded['falsePos']; @@ -140,7 +139,7 @@ class FiresApi { fires: fires, falsePos: falsePos, industries: industries); - } else throw Exception('Wrong response trying to get stats'); + } else throw Exception('Wrong response trying to get fire data'); }); } } diff --git a/lib/redux/fetchDataMiddleware.dart b/lib/redux/fetchDataMiddleware.dart index df88ea0..2c07021 100644 --- a/lib/redux/fetchDataMiddleware.dart +++ b/lib/redux/fetchDataMiddleware.dart @@ -1,10 +1,11 @@ +import 'dart:async'; + import 'package:bson_objectid/bson_objectid.dart'; -import 'package:fires_flutter/models/yourLocation.dart'; import 'package:fires_flutter/models/fireNotification.dart'; +import 'package:fires_flutter/models/yourLocation.dart'; import 'package:flutter_simple_dependency_injection/injector.dart'; import 'package:just_debounce_it/just_debounce_it.dart'; import 'package:redux/redux.dart'; -import 'dart:async'; import '../models/appState.dart'; import '../models/fireNotificationsPersist.dart'; @@ -87,15 +88,34 @@ void fetchDataMiddleware(Store store, action, NextDispatcher next) { if (action is ShowYourLocationMapAction) { api - .getYourLocationFireStats(store.state, action.loc) + .getFiresInLocation( + state: store.state, + lat: action.loc.lat, + lon: action.loc.lon, + distance: action.loc.distance) .then((result) => store.dispatch(result)); } + + if (action is ShowFireNotificationMapAction) { + api + .getFiresInLocation( + state: store.state, + lat: action.notif.lat, + lon: action.notif.lon, + distance: 1) // FalsePositive/server/publications.js + .then((result) => store.dispatch(result)); + } + if (action is UpdateYourLocationAction) { if (action.loc.subscribed) Debounce.seconds( 2, () => api - .getYourLocationFireStats(store.state, action.loc) + .getFiresInLocation( + state: store.state, + lat: action.loc.lat, + lon: action.loc.lon, + distance: action.loc.distance) .then((result) => store.dispatch(result))); else { // FIXME do something? @@ -147,18 +167,22 @@ void fetchDataMiddleware(Store store, action, NextDispatcher next) { localLocations.forEach((location) => location.subscribed = false); // print('Local persisted: ${localLocations.length}'); subscribedLocations.forEach((subsLoc) { - localLocations - .firstWhere( + localLocations.firstWhere( (localLocation) => localLocation.id == subsLoc.id, orElse: () { localLocations.add(subsLoc); - }) - .subscribed = true; + }).subscribed = true; }); } - localLocations.forEach((yl) { - api.getYourLocationFireStats(store.state, yl).then((value) { + localLocations.forEach((yl) { + api + .getFiresInLocation( + state: store.state, + lat: yl.lat, + lon: yl.lon, + distance: yl.distance) + .then((value) { yl.currentNumFires = value.numFires; - store.dispatch(new UpdateYourLocationAction(yl)); + store.dispatch(new UpdateYourLocationAction(yl)); }); }); @@ -180,7 +204,9 @@ void fetchDataMiddleware(Store store, action, NextDispatcher next) { loadFireNotifications().then((fireNotifications) { int unread = 0; for (FireNotification notif in fireNotifications) { - if (!notif.read) { unread++; } + if (!notif.read) { + unread++; + } } store.dispatch( new FetchFireNotificationsSucceededAction(fireNotifications, unread)); diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 0e27495..77dcc67 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -66,5 +66,11 @@ "CLOSE": "CLOSE", "noConnectivity": "This application needs an Internet connection to work", "NASAAck": "We acknowledge the use of data and imagery from LANCE FIRMS operated by the NASA/GSFC/Earth Science Data and Information System (ESDIS) with funding provided by NASA/HQ.", - "appMoto": "Strengthening neighborhoods against wildfires" + "appMoto": "Strengthening neighborhoods against wildfires", + "itSeemsNotAtForesFire": "It seems that this is not a forest fire.", + "notAWildfire": "Isn't that a forest fire?", + "itSeemsAIndustry": "It's an industry", + "itSeemsAControlledBurning": "It's a controlled burning", + "itSeemsAFalseAlarm": "It seems a false alarm", + "thanksForParticipating": "Thanks for participating" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 619de3b..1aca567 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -66,5 +66,11 @@ "CLOSE": "CERRAR", "noConnectivity": "Esta aplicación necesita una conexión a Internet para funcionar", "NASAAck": "Reconocemos el uso de datos e imágenes de LANCE FIRMS operadas por NASA/GSFC/Earth Science Data and Information System (ESDIS) con fondos proporcionados por NASA/HQ.", - "appMoto": "Fortaleciendo vecindarios contra incendios forestales" + "appMoto": "Fortaleciendo vecindarios contra incendios forestales", + "itSeemsNotAtForesFire": "Parece que este fuego no es un fuego forestal.", + "notAWildfire": "¿No es un fuego forestal?", + "itSeemsAIndustry": "Es una industria", + "itSeemsAControlledBurning": "Es una quema controlada", + "itSeemsAFalseAlarm": "Parece una falsa alarma", + "thanksForParticipating": "Gracias por Participar" } \ No newline at end of file