From 87718b7ad5c3c395a5ac38980861b8d02eae4eeb Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 5 Jul 2018 12:50:08 +0200 Subject: [PATCH] Location edition --- lib/activeFires.dart | 20 ++++++--- lib/firesApp.dart | 8 ++-- lib/globalFiresBottomStats.dart | 53 ++++++++++++----------- lib/mainCommon.dart | 5 ++- lib/mainDev.dart | 2 +- lib/mainDrawer.dart | 5 +++ lib/models/appState.dart | 1 - lib/models/yourLocation.dart | 18 ++++++++ lib/models/yourLocation.g.dart | 7 --- lib/models/yourLocationPersist.dart | 1 + lib/redux/fetchDataMiddleware.dart | 10 +++-- lib/redux/yourLocationActions.dart | 7 ++- lib/redux/yourLocationsReducer.dart | 8 ++-- lib/sandbox.dart | 2 +- lib/yourLocationMap.dart | 66 ++++++++++++++++++++--------- 15 files changed, 138 insertions(+), 75 deletions(-) diff --git a/lib/activeFires.dart b/lib/activeFires.dart index 1a01812..c6934f4 100644 --- a/lib/activeFires.dart +++ b/lib/activeFires.dart @@ -33,18 +33,25 @@ class _ViewModel { @required this.yourLocations}); @override - bool operator ==(Object other) => - identical(this, other) || + bool operator ==(Object other) { + return identical(this, other) || other is _ViewModel && - runtimeType == other.runtimeType && - yourLocations == other.yourLocations; + runtimeType == other.runtimeType && + yourLocations == other.yourLocations; + } @override int get hashCode => yourLocations.hashCode; } -class ActiveFiresPage extends StatelessWidget { - static const String routeName = '/fires'; +class ActiveFiresPage extends StatefulWidget { +static const String routeName = '/fires'; + + @override + _ActiveFiresPageState createState() => _ActiveFiresPageState(); +} + +class _ActiveFiresPageState extends State { final GlobalKey _scaffoldKey = new GlobalKey(); @@ -134,6 +141,7 @@ class ActiveFiresPage extends StatelessWidget { return new StoreConnector( distinct: true, converter: (store) { + print('New ViewModel of Active Fires'); return new _ViewModel( onAdd: (loc) { if (store.state.yourLocations diff --git a/lib/firesApp.dart b/lib/firesApp.dart index aeee1a2..e3f27b7 100644 --- a/lib/firesApp.dart +++ b/lib/firesApp.dart @@ -31,7 +31,10 @@ class FiresApp extends StatelessWidget { @override Widget build(BuildContext context) { - return new StoreProvider( + StatefulWidget home = new MaterialAppWithIntroHome( + introWidget, continueWidget, 'showInitialWizard-2018-06-27-01'); + return new StoreProvider( + store: this.store, child: new MaterialApp( localizationsDelegates: [ @@ -42,8 +45,7 @@ class FiresApp extends StatelessWidget { supportedLocales: S.delegate.supportedLocales, localeResolutionCallback: S.delegate.resolution(fallback: new Locale("en", "")), - home: new MaterialAppWithIntroHome( - introWidget, continueWidget, 'showInitialWizard-2018-06-27-01'), + home: home, onGenerateTitle: (context) { print('MaterialApp onGenerateTitle'); if (store.state.user.lang == null) { diff --git a/lib/globalFiresBottomStats.dart b/lib/globalFiresBottomStats.dart index b78b90e..05e13fc 100644 --- a/lib/globalFiresBottomStats.dart +++ b/lib/globalFiresBottomStats.dart @@ -1,13 +1,14 @@ -import 'package:flutter/material.dart'; import 'dart:convert'; -import 'globals.dart' as globals; -import 'package:http/http.dart' as http; + import 'package:comunes_flutter/comunes_flutter.dart'; -import 'customBottomAppBar.dart'; -import 'colors.dart'; -import 'generated/i18n.dart'; -import 'customMoment.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_simple_dependency_injection/injector.dart'; +import 'package:http/http.dart' as http; + +import 'colors.dart'; +import 'customBottomAppBar.dart'; +import 'customMoment.dart'; +import 'generated/i18n.dart'; class GlobalFiresBottomStats extends StatefulWidget { @override @@ -22,7 +23,7 @@ class _GlobalFiresBottomStatsState extends State { @override void initState() { super.initState(); - /* http.read('${firesApiUrl}status/last-fire-check').then((result) { + http.read('${firesApiUrl}status/last-fire-check').then((result) { try { var now = Moment.now(); var last = DateTime.parse(json.decode(result)['value']); @@ -42,27 +43,29 @@ class _GlobalFiresBottomStatsState extends State { print('Cannot get the last fire check'); print(e); } - }); */ + }); } @override Widget build(BuildContext context) { return new CustomBottomAppBar( - fabLocation: FloatingActionButtonLocation.centerDocked, - showNotch: true, - color: fires100, - mainAxisAlignment: MainAxisAlignment.center, - actions: listWithoutNulls([ - activeFires > 0 && lastCheck != null - ? new Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - new Text(S.of(context).activeFiresWorldWide(activeFires.toString())), - new Text(S.of(context).updatedLastCheck(lastCheck)) - ]) - : null, - SizedBox(width: 10.0) - ])); + fabLocation: FloatingActionButtonLocation.centerDocked, + showNotch: true, + color: fires100, + mainAxisAlignment: MainAxisAlignment.center, + actions: listWithoutNulls([ + activeFires > 0 && lastCheck != null + ? new Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + new Text(S + .of(context) + .activeFiresWorldWide(activeFires.toString())), + new Text(S.of(context).updatedLastCheck(lastCheck)) + ]) + : null, + SizedBox(width: 10.0) + ])); } } diff --git a/lib/mainCommon.dart b/lib/mainCommon.dart index be0755d..314d78d 100644 --- a/lib/mainCommon.dart +++ b/lib/mainCommon.dart @@ -41,7 +41,8 @@ void mainCommon(List> otherMiddleware) { }); // Listen to store changes, and re-render when the state is updated - // store.onChange.listen((state) { - // }); + store.onChange.listen((state) { + // print('Store onChange'); + }); }); } diff --git a/lib/mainDev.dart b/lib/mainDev.dart index 7bbad21..78d6d8a 100644 --- a/lib/mainDev.dart +++ b/lib/mainDev.dart @@ -14,7 +14,7 @@ void main() { dynamic action, DateTime timestamp, ) { - return "${action.toString().replaceAll('Instance of ', '')}"; + return ">>>>> ${action.toString().replaceAll('Instance of ', '')}"; } LogLevel logRedux = LogLevel.actions; diff --git a/lib/mainDrawer.dart b/lib/mainDrawer.dart index 0031dd3..3eb4d60 100644 --- a/lib/mainDrawer.dart +++ b/lib/mainDrawer.dart @@ -19,6 +19,7 @@ Widget mainDrawer(BuildContext context) { children: listWithoutNulls([ new GestureDetector( onTap: () { + Navigator.pop(context); Navigator.pushNamed(context, '/'); }, child: new DrawerHeader( @@ -46,6 +47,7 @@ Widget mainDrawer(BuildContext context) { leading: const Icon(Icons.whatshot), title: new Text(S.of(context).activeFires), onTap: () { + Navigator.pop(context); Navigator.pushNamed(context, ActiveFiresPage.routeName); }, ), @@ -54,6 +56,7 @@ Widget mainDrawer(BuildContext context) { title: new Text(S.of(context).notifyAFire), onTap: () { // Then close the drawer + Navigator.pop(context); Navigator.pushNamed(context, Sandbox.routeName); }, ), @@ -63,6 +66,7 @@ Widget mainDrawer(BuildContext context) { title: new Text(S.of(context).supportThisInitiative), onTap: () { // Then close the drawer + Navigator.pop(context); Navigator.pushNamed(context, '/subscriptions'); }, ), @@ -71,6 +75,7 @@ Widget mainDrawer(BuildContext context) { leading: const Icon(Icons.bug_report), title: new Text('Sandbox'), onTap: () { + Navigator.pop(context); Navigator.pushNamed(context, Sandbox.routeName); }, ): null, diff --git a/lib/models/appState.dart b/lib/models/appState.dart index 3e86dd0..c965108 100644 --- a/lib/models/appState.dart +++ b/lib/models/appState.dart @@ -1,4 +1,3 @@ -import 'package:bson_objectid/bson_objectid.dart'; import 'package:comunes_flutter/comunes_flutter.dart'; import 'package:fires_flutter/models/yourLocation.dart'; import 'package:json_annotation/json_annotation.dart'; diff --git a/lib/models/yourLocation.dart b/lib/models/yourLocation.dart index d53eece..34e8fb1 100644 --- a/lib/models/yourLocation.dart +++ b/lib/models/yourLocation.dart @@ -39,6 +39,24 @@ class YourLocation extends Object with _$YourLocationSerializerMixin { if (this.id == null) this.id = new ObjectId(); } + YourLocation copyWith( + {id, + lat, + lon, + description, + distance, + subscribed}) { + return new YourLocation( + id: id?? this.id, + lat: lat?? this.lat, + lon: lon?? this.lon, + description: description?? this.description, + distance: distance?? this.distance, + subscribed: subscribed?? this.subscribed + ); + } + + @override bool operator ==(Object other) => identical(this, other) || diff --git a/lib/models/yourLocation.g.dart b/lib/models/yourLocation.g.dart index cae216b..b6cb7dd 100644 --- a/lib/models/yourLocation.g.dart +++ b/lib/models/yourLocation.g.dart @@ -19,23 +19,16 @@ YourLocation _$YourLocationFromJson(Map json) => abstract class _$YourLocationSerializerMixin { ObjectId get id; - double get lat; - double get lon; - String get description; - bool get subscribed; - int get distance; - Map toJson() => new _$YourLocationJsonMapWrapper(this); } class _$YourLocationJsonMapWrapper extends $JsonMapWrapper { final _$YourLocationSerializerMixin _v; - _$YourLocationJsonMapWrapper(this._v); @override diff --git a/lib/models/yourLocationPersist.dart b/lib/models/yourLocationPersist.dart index 4540d83..bce5885 100644 --- a/lib/models/yourLocationPersist.dart +++ b/lib/models/yourLocationPersist.dart @@ -25,6 +25,7 @@ Future> loadYourLocations() async { } persistYourLocations(List yl) { + print('Persisting $yl'); globals.prefs.then((prefs) { List ylAsString = []; yl.forEach((location) { diff --git a/lib/redux/fetchDataMiddleware.dart b/lib/redux/fetchDataMiddleware.dart index e578280..2c85feb 100644 --- a/lib/redux/fetchDataMiddleware.dart +++ b/lib/redux/fetchDataMiddleware.dart @@ -41,15 +41,16 @@ void fetchYourLocationsMiddleware( // FXIME save lat/lon } else { // No subscribed (only local) - store.dispatch(new UpdateYourLocationAction(action.loc)); - persistYourLocations(store.state.yourLocations); } } if (action is AddYourLocationAction) { if (action.loc.subscribed) { subscribeViaApi(store, action.loc, - (sub) => store.dispatch(new AddedYourLocationAction(sub))); + (sub) { + store.dispatch(new AddedYourLocationAction(sub)); + persistYourLocations(store.state.yourLocations); + }); } else { // No subscribed (only local) store.dispatch(new AddedYourLocationAction(action.loc)); @@ -73,7 +74,6 @@ void fetchYourLocationsMiddleware( .getYourLocationFireStats(store.state, action.loc) .then((result) => store.dispatch(result)); } - if (action is UpdateYourLocationAction) { if (action.loc.subscribed) Debounce.seconds( @@ -84,6 +84,8 @@ void fetchYourLocationsMiddleware( else { // FIXME do something? } + store.dispatch(new UpdatedYourLocationAction(action.loc)); + persistYourLocations(store.state.yourLocations); } if (action is SubscribeConfirmAction) { diff --git a/lib/redux/yourLocationActions.dart b/lib/redux/yourLocationActions.dart index 68088d3..47ae75c 100644 --- a/lib/redux/yourLocationActions.dart +++ b/lib/redux/yourLocationActions.dart @@ -1,6 +1,5 @@ import 'package:bson_objectid/bson_objectid.dart'; import 'package:fires_flutter/models/yourLocation.dart'; -import 'package:meta/meta.dart'; abstract class YourLocationActions {} @@ -34,6 +33,12 @@ class UpdateYourLocationAction extends YourLocationActions { UpdateYourLocationAction(this.loc); } +class UpdatedYourLocationAction extends YourLocationActions { + YourLocation loc; + + UpdatedYourLocationAction(this.loc); +} + class ToggleSubscriptionAction extends YourLocationActions { YourLocation loc; diff --git a/lib/redux/yourLocationsReducer.dart b/lib/redux/yourLocationsReducer.dart index ee3557b..aa45662 100644 --- a/lib/redux/yourLocationsReducer.dart +++ b/lib/redux/yourLocationsReducer.dart @@ -8,8 +8,8 @@ final yourLocationsReducer = combineReducers>([ _addedYourLocation), new TypedReducer, DeletedYourLocationAction>( _deletedYourLocation), - new TypedReducer, UpdateYourLocationAction>( - _updateYourLocation), + new TypedReducer, UpdatedYourLocationAction>( + _updatedYourLocation), new TypedReducer, ToggledSubscriptionAction>( _toggledSubscriptionAction) ]); @@ -26,8 +26,8 @@ List _deletedYourLocation( .toList(); } -List _updateYourLocation( - List yourLocations, UpdateYourLocationAction action) { +List _updatedYourLocation( + List yourLocations, UpdatedYourLocationAction action) { return yourLocations .map((yourLocation) => yourLocation.id == action.loc.id ? action.loc : yourLocation) diff --git a/lib/sandbox.dart b/lib/sandbox.dart index db7a095..9f6d47b 100644 --- a/lib/sandbox.dart +++ b/lib/sandbox.dart @@ -15,6 +15,7 @@ class Sandbox extends StatelessWidget { return Scaffold( appBar: new AppBar( title: new TextField( + autofocus: true, controller: new TextEditingController(text: "kk"), decoration: new InputDecoration(), onSubmitted: (todoText) {}, @@ -23,4 +24,3 @@ class Sandbox extends StatelessWidget { ); } } --aƱ \ No newline at end of file diff --git a/lib/yourLocationMap.dart b/lib/yourLocationMap.dart index abc8ba4..b3ec8ba 100644 --- a/lib/yourLocationMap.dart +++ b/lib/yourLocationMap.dart @@ -54,9 +54,17 @@ class _ViewModel { int get hashCode => mapState.hashCode; } -class YourLocationMap extends StatelessWidget { +class YourLocationMap extends StatefulWidget { + @override + _YourLocationMapState createState() => _YourLocationMapState(); +} + +class _YourLocationMapState 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(); final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging(); + YourLocation editingLocation; @override Widget build(BuildContext context) { @@ -80,16 +88,19 @@ class YourLocationMap extends StatelessWidget { store.dispatch(new UpdateYourLocationMapAction(loc)); }, onEdit: (loc) => store.dispatch(new EditYourLocationAction(loc)), - onEditConfirm: (loc) => - store.dispatch(new EditConfirmYourLocationAction(loc)), + onEditConfirm: (loc) { + store.dispatch(new UpdateYourLocationAction(loc)); + store.dispatch(new UpdateYourLocationMapAction(loc)); + store.dispatch(new EditConfirmYourLocationAction(loc)); + }, mapState: store.state.fireMapState); }, builder: (context, view) { - print('New map builder'); YourLocation location = view.mapState.yourLocation; + editingLocation = location.copyWith(); + print('New map builder with ${editingLocation.description}'); + assert(location != null); - TextEditingController textController = - new TextEditingController(text: location.description); MapOptions mapOptions = new MapOptions( center: new LatLng(location.lat, location.lon), @@ -151,29 +162,23 @@ class YourLocationMap extends StatelessWidget { // Do something with it return new Scaffold( key: _scaffoldKey, + resizeToAvoidBottomPadding: true, appBar: new AppBar( title: status == FireMapStatus.edit ? new TextField( // autofocus: true, key: new Key('LocationDescField'), keyboardType: TextInputType.text, - controller: textController, + decoration: new InputDecoration(), - /* onSubmitted: (newDesc) { - // location.description = newDesc; - // view.onEditConfirm(location); - // view.editController.text = ''; - },*/ + controller: new TextEditingController.fromValue(new TextEditingValue(text: editingLocation.description,selection: new TextSelection.collapsed(offset: editingLocation.description.length-1))), + onChanged: (newDesc) { + editingLocation = + location.copyWith(description: newDesc); + }, ) : new Text(location.description), - actions: listWithoutNulls([ - status == FireMapStatus.view || - status == FireMapStatus.unsubscribe - ? new IconButton( - icon: new Icon(Icons.edit), - onPressed: () => view.onEdit(location)) - : null - ]), + actions: buildAppBarActions(status, view, location), ), floatingActionButton: status == FireMapStatus.edit ? null @@ -239,6 +244,27 @@ class YourLocationMap extends StatelessWidget { }); } + List buildAppBarActions( + FireMapStatus status, _ViewModel view, YourLocation location) { + switch (status) { + case FireMapStatus.view: + case FireMapStatus.unsubscribe: + return [ + new IconButton( + icon: new Icon(Icons.edit), + onPressed: () => view.onEdit(location)) + ]; + case FireMapStatus.edit: + return [ + new IconButton( + icon: new Icon(Icons.save), + onPressed: () => view.onEditConfirm(editingLocation)) + ]; + default: + return []; + } + } + List buildMarkers(YourLocation yourLocation, List fires, List falsePos, List industries) { List markers = [];