More redux work
This commit is contained in:
parent
7dddf03e32
commit
657fecdf17
9 changed files with 278 additions and 219 deletions
|
|
@ -13,19 +13,23 @@ import 'globalFiresBottomStats.dart';
|
|||
import 'locationUtils.dart';
|
||||
import 'mainDrawer.dart';
|
||||
import 'models/appState.dart';
|
||||
import 'package:redux/src/store.dart';
|
||||
import 'placesAutocompleteUtils.dart';
|
||||
import 'redux/actions.dart';
|
||||
|
||||
@immutable
|
||||
class _ViewModel {
|
||||
final List<YourLocation> yourLocations;
|
||||
final AddYourLocationFunction onAdd;
|
||||
final DeleteYourLocationFunction onDelete;
|
||||
final ToggleSubscriptionFunction onToggleSubs;
|
||||
final OnLocationTapFunction onTap;
|
||||
|
||||
_ViewModel(
|
||||
{@required this.onAdd,
|
||||
@required this.onDelete,
|
||||
@required this.onToggleSubs,
|
||||
@required this.onTap,
|
||||
@required this.yourLocations});
|
||||
|
||||
@override
|
||||
|
|
@ -36,14 +40,16 @@ class _ViewModel {
|
|||
yourLocations == other.yourLocations &&
|
||||
onAdd == other.onAdd &&
|
||||
onDelete == other.onDelete &&
|
||||
onToggleSubs == other.onToggleSubs;
|
||||
onToggleSubs == other.onToggleSubs &&
|
||||
onTap == other.onTap;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
yourLocations.hashCode ^
|
||||
onAdd.hashCode ^
|
||||
onDelete.hashCode ^
|
||||
onToggleSubs.hashCode;
|
||||
onToggleSubs.hashCode ^
|
||||
onTap.hashCode;
|
||||
}
|
||||
|
||||
class ActiveFiresPage extends StatefulWidget {
|
||||
|
|
@ -81,7 +87,7 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
|
||||
_ActiveFiresPageState();
|
||||
|
||||
Widget _buildRow(YourLocation loc, onToggle) {
|
||||
Widget _buildRow(YourLocation loc, onToggle, onTap) {
|
||||
return new ListTile(
|
||||
dense: true,
|
||||
leading: const Icon(Icons.location_on),
|
||||
|
|
@ -92,44 +98,29 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
onPressed: () {
|
||||
loc.subscribed = !loc.subscribed;
|
||||
onToggle(loc);
|
||||
/* FIXME int i = globals.yourLocations.indexOf(loc);
|
||||
globals.yourLocations.removeAt(i);
|
||||
globals.yourLocations.insert(i, loc);
|
||||
persistYourLocations(); */
|
||||
setState(() {});
|
||||
}),
|
||||
title: new Text(loc.description),
|
||||
onLongPress: () {
|
||||
showSnackMsg(S.of(context).toDeleteThisPlace);
|
||||
},
|
||||
onTap: () {
|
||||
showLocationMap(loc);
|
||||
onTap(loc);
|
||||
});
|
||||
}
|
||||
|
||||
void showLocationMap(YourLocation loc) {
|
||||
// , VoidCallback onSubs
|
||||
Navigator.push(
|
||||
context,
|
||||
new MaterialPageRoute(
|
||||
builder: (context) => new GenericMap(
|
||||
title: loc.description,
|
||||
location: loc,
|
||||
operation: MapOperation.view)));
|
||||
}
|
||||
|
||||
void showSnackMsg(String msg) {
|
||||
_scaffoldKey.currentState.showSnackBar(new SnackBar(
|
||||
content: new Text(msg),
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildSavedLocations(List<YourLocation> yl, onDeleted, onToggle) {
|
||||
Widget _buildSavedLocations(
|
||||
List<YourLocation> yl, onDeleted, onToggle, onTap) {
|
||||
return new ListView.builder(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
itemCount: yl.length,
|
||||
itemBuilder: (BuildContext _context, int i) {
|
||||
return _buildItem(yl.elementAt(i), onDeleted, onToggle);
|
||||
return _buildItem(yl.elementAt(i), onDeleted, onToggle, onTap);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +132,7 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
});
|
||||
}
|
||||
|
||||
Widget _buildItem(YourLocation item, onDelete, onToggle) {
|
||||
Widget _buildItem(YourLocation item, onDelete, onToggle, onTap) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return new Dismissible(
|
||||
key: new ObjectKey(item),
|
||||
|
|
@ -174,7 +165,7 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
color: theme.canvasColor,
|
||||
border: new Border(
|
||||
bottom: new BorderSide(color: theme.dividerColor))),
|
||||
child: _buildRow(item, onToggle)));
|
||||
child: _buildRow(item, onToggle, onTap)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -185,6 +176,7 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
return new _ViewModel(
|
||||
onAdd: (loc) {
|
||||
store.dispatch(new AddYourLocationAction(loc));
|
||||
gotoLocationMap(store, loc, context);
|
||||
},
|
||||
onDelete: (id) {
|
||||
store.dispatch(new DeleteYourLocationAction(id));
|
||||
|
|
@ -192,6 +184,9 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
onToggleSubs: (loc) {
|
||||
store.dispatch(new ToggleSubscriptionAction(loc));
|
||||
},
|
||||
onTap: (loc) {
|
||||
gotoLocationMap(store, loc, context);
|
||||
},
|
||||
yourLocations: store.state.yourLocations);
|
||||
},
|
||||
builder: (context, view) {
|
||||
|
|
@ -219,8 +214,8 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
bottomNavigationBar: new GlobalFiresBottomStats(),
|
||||
body: hasLocations
|
||||
? new Stack(children: <Widget>[
|
||||
_buildSavedLocations(
|
||||
view.yourLocations, view.onDelete, view.onToggleSubs),
|
||||
_buildSavedLocations(view.yourLocations, view.onDelete,
|
||||
view.onToggleSubs, view.onTap),
|
||||
new FabDialer(_fabMiniMenuItemList(view.onAdd), fires600,
|
||||
new Icon(Icons.add))
|
||||
])
|
||||
|
|
@ -242,6 +237,12 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
});
|
||||
}
|
||||
|
||||
void gotoLocationMap(Store<AppState> store, YourLocation loc, BuildContext context) {
|
||||
store.dispatch(new ShowYourLocationMapAction(loc));
|
||||
Navigator.push(
|
||||
context, new MaterialPageRoute(builder: (context) => new GenericMap()));
|
||||
}
|
||||
|
||||
void onAddYourLocation(AddYourLocationFunction onAdd) {
|
||||
Future<YourLocation> location = getUserLocation(_scaffoldKey);
|
||||
_saveLocation(location, onAdd);
|
||||
|
|
@ -256,17 +257,6 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
location.then((newLocation) {
|
||||
if (newLocation != YourLocation.noLocation) {
|
||||
onAdd(newLocation);
|
||||
/* FIXME
|
||||
if (globals.yourLocations.contains(newLocation)) {
|
||||
showSnackMsg(S.of(context).addedThisLocation);
|
||||
} else
|
||||
this.setState(() {
|
||||
globals.yourLocations.add(newLocation);
|
||||
persistYourLocations();
|
||||
new Timer(new Duration(milliseconds: 1000), () {
|
||||
showLocationMap(newLocation);
|
||||
});
|
||||
}); */
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@ import 'dart:core';
|
|||
|
||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:fires_flutter/models/basicLocation.dart';
|
||||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:flutter_map/plugin_api.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:just_debounce_it/just_debounce_it.dart';
|
||||
import 'package:latlong/latlong.dart';
|
||||
|
||||
import 'package:fires_flutter/models/basicLocation.dart';
|
||||
import 'colors.dart';
|
||||
import 'customBottomAppBar.dart';
|
||||
import 'dummyMapPlugin.dart';
|
||||
|
|
@ -18,47 +20,61 @@ import 'fireMarkType.dart';
|
|||
import 'fireMarker.dart';
|
||||
import 'generated/i18n.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'models/appState.dart';
|
||||
import 'models/fireMapState.dart';
|
||||
import 'redux/actions.dart';
|
||||
import 'slider.dart';
|
||||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'zoomMapPlugin.dart';
|
||||
|
||||
enum MapOperation { view, subscriptionConfirm, unsubscribe }
|
||||
@immutable
|
||||
class _ViewModel {
|
||||
final FireMapState mapState;
|
||||
final OnSubscribeFunction onSubs;
|
||||
final OnSubscribeConfirmedFunction onSubsConfirmed;
|
||||
final OnUnSubscribeFunction onUnSubs;
|
||||
|
||||
class GenericMap extends StatefulWidget {
|
||||
final YourLocation location;
|
||||
final String title;
|
||||
final MapOperation operation;
|
||||
|
||||
GenericMap(
|
||||
{@required this.title,
|
||||
@required this.location,
|
||||
@required this.operation});
|
||||
_ViewModel(
|
||||
{@required this.mapState,
|
||||
@required this.onSubs,
|
||||
@required this.onSubsConfirmed,
|
||||
@required this.onUnSubs});
|
||||
|
||||
@override
|
||||
_GenericMapState createState() =>
|
||||
_GenericMapState(title: title, location: location, operation: operation);
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is _ViewModel &&
|
||||
runtimeType == other.runtimeType &&
|
||||
mapState == other.mapState &&
|
||||
onSubs == other.onSubs &&
|
||||
onSubsConfirmed == other.onSubsConfirmed &&
|
||||
onUnSubs == other.onUnSubs;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
mapState.hashCode ^
|
||||
onSubs.hashCode ^
|
||||
onSubsConfirmed.hashCode ^
|
||||
onUnSubs.hashCode;
|
||||
}
|
||||
|
||||
class GenericMap extends StatefulWidget {
|
||||
GenericMap();
|
||||
|
||||
@override
|
||||
_GenericMapState createState() => _GenericMapState();
|
||||
}
|
||||
|
||||
class _GenericMapState extends State<GenericMap> {
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||
final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
|
||||
|
||||
final YourLocation location;
|
||||
final String title;
|
||||
int numFires;
|
||||
int kmAround = 100;
|
||||
List<dynamic> fires = [];
|
||||
List<dynamic> falsePos = [];
|
||||
List<dynamic> industries = [];
|
||||
MapOperation operation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
updateFireStats();
|
||||
}
|
||||
|
||||
void updateFireStats() {
|
||||
void updateFireStats(YourLocation location) {
|
||||
var url = '${globals.firesApiUrl}fires-in-full/${globals
|
||||
.firesApiKey}/${location.lat}/${location.lon}/$kmAround';
|
||||
http.read(url).then((result) {
|
||||
|
|
@ -81,145 +97,170 @@ class _GenericMapState extends State<GenericMap> {
|
|||
});
|
||||
}
|
||||
|
||||
_GenericMapState(
|
||||
{@required this.title,
|
||||
@required this.location,
|
||||
@required this.operation});
|
||||
_GenericMapState();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
print('Build map with operation: $operation');
|
||||
MapOptions mapOptions = new MapOptions(
|
||||
center: new LatLng(this.location.lat, this.location.lon),
|
||||
plugins: globals.isDevelopment
|
||||
? [new ZoomMapPlugin()]
|
||||
: [new DummyMapPlugin()],
|
||||
// this works ?
|
||||
// interactive: false,
|
||||
zoom: 13.0,
|
||||
// THIS does not works as expected
|
||||
// maxZoom: 6.0,
|
||||
onPositionChanged: (positionCallback) {
|
||||
// decouple
|
||||
// print('${positionCallback.center}, ${positionCallback.zoom}');
|
||||
});
|
||||
var mapController = new MapController();
|
||||
// mapController.fitBounds(bounds);
|
||||
// mapController.center
|
||||
var fmap = new Opacity(
|
||||
opacity: operation == MapOperation.subscriptionConfirm ? 0.5 : 1.0,
|
||||
child: new FlutterMap(
|
||||
options: mapOptions,
|
||||
mapController: mapController,
|
||||
layers: [
|
||||
new TileLayerOptions(
|
||||
maxZoom: 6.0,
|
||||
subdomains: ['a', 'b', 'c'],
|
||||
urlTemplate:
|
||||
'https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
|
||||
additionalOptions: {
|
||||
// 'opacity': '0.1',
|
||||
'attribution':
|
||||
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
// print('Build map with operation: $operation');
|
||||
return new StoreConnector<AppState, _ViewModel>(
|
||||
distinct: false, // FIXME
|
||||
converter: (store) {
|
||||
return new _ViewModel(
|
||||
onSubs: (loc) {
|
||||
store.dispatch(new SubscribeAction(loc.id));
|
||||
},
|
||||
),
|
||||
globals.isDevelopment
|
||||
? new ZoomMapPluginOptions()
|
||||
: new DummyMapPluginOptions(),
|
||||
new MarkerLayerOptions(
|
||||
markers: buildMarkers(
|
||||
this.location, this.fires, this.industries, this.falsePos),
|
||||
),
|
||||
],
|
||||
));
|
||||
final btnText = operation == MapOperation.view
|
||||
? S.of(context).toFiresNotifications
|
||||
: operation == MapOperation.subscriptionConfirm
|
||||
? S.of(context).confirm
|
||||
: S.of(context).unsubscribe;
|
||||
final btnIcon = operation == MapOperation.view
|
||||
? Icons.notifications_active
|
||||
: operation == MapOperation.subscriptionConfirm
|
||||
? Icons.check
|
||||
: Icons.notifications_off;
|
||||
return new Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: new AppBar(
|
||||
title: new Text(title),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
switch (operation) {
|
||||
case MapOperation.view:
|
||||
operation = MapOperation.subscriptionConfirm;
|
||||
break;
|
||||
case MapOperation.subscriptionConfirm:
|
||||
// IOS specific
|
||||
_firebaseMessaging.requestNotificationPermissions();
|
||||
operation = MapOperation.unsubscribe;
|
||||
break;
|
||||
case MapOperation.unsubscribe:
|
||||
operation = MapOperation.view;
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
// https://github.com/flutter/flutter/issues/17583
|
||||
heroTag: "firesmap" + location.id.toHexString(),
|
||||
icon: new Icon(btnIcon, color: fires600),
|
||||
label: new Text(
|
||||
btnText,
|
||||
style: const TextStyle(color: fires600),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
bottomNavigationBar: new CustomBottomAppBar(
|
||||
fabLocation: FloatingActionButtonLocation.centerFloat,
|
||||
showNotch: false,
|
||||
color: fires100,
|
||||
// height: 170.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
actions: listWithoutNulls(<Widget>[
|
||||
operation == MapOperation.subscriptionConfirm || numFires == null
|
||||
? null
|
||||
: new Text(numFires > 0
|
||||
? S.of(context).firesAroundThisArea(
|
||||
numFires.toString(), kmAround.toString())
|
||||
: S
|
||||
.of(context)
|
||||
.noFiresAroundThisArea(kmAround.toString())),
|
||||
SizedBox(width: 10.0)
|
||||
])),
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) =>
|
||||
Stack(fit: StackFit.expand, children: <Widget>[
|
||||
// Material(color: Colors.yellowAccent),
|
||||
fmap,
|
||||
Positioned(
|
||||
top: constraints.maxHeight - 200,
|
||||
right: 10.0,
|
||||
left: 10.0,
|
||||
child: new CenteredRow(
|
||||
// Fit sample:
|
||||
// https://github.com/apptreesoftware/flutter_map/blob/master/flutter_map_example/lib/pages/map_controller.dart
|
||||
children: operation == MapOperation.subscriptionConfirm
|
||||
? <Widget>[
|
||||
new FireDistanceSlider(
|
||||
initialValue: kmAround,
|
||||
onSlide: (distance) {
|
||||
setState(() {
|
||||
kmAround = distance;
|
||||
Debounce.seconds(1, updateFireStats);
|
||||
});
|
||||
})
|
||||
]
|
||||
: [],
|
||||
),
|
||||
)
|
||||
]),
|
||||
));
|
||||
onSubsConfirmed: (loc) {
|
||||
store.dispatch(new SubscribeAction(loc.id));
|
||||
},
|
||||
onUnSubs: (loc) {
|
||||
store.dispatch(new UnSubscribeAction(loc.id));
|
||||
},
|
||||
mapState: store.state.fireMapState);
|
||||
},
|
||||
builder: (context, view) {
|
||||
YourLocation location = view.mapState.yourLocation;
|
||||
MapOptions mapOptions = new MapOptions(
|
||||
center: new LatLng(location.lat, location.lon),
|
||||
plugins: globals.isDevelopment
|
||||
? [new ZoomMapPlugin()]
|
||||
: [new DummyMapPlugin()],
|
||||
// this works ?
|
||||
// interactive: false,
|
||||
zoom: 13.0,
|
||||
// THIS does not works as expected
|
||||
// maxZoom: 6.0,
|
||||
onPositionChanged: (positionCallback) {
|
||||
// decouple
|
||||
// print('${positionCallback.center}, ${positionCallback.zoom}');
|
||||
});
|
||||
var mapController = new MapController();
|
||||
// mapController.fitBounds(bounds);
|
||||
// mapController.center
|
||||
|
||||
FireMapStatus operation = view.mapState.status;
|
||||
final btnText = operation == FireMapStatus.view
|
||||
? S.of(context).toFiresNotifications
|
||||
: operation == FireMapStatus.subscriptionConfirm
|
||||
? S.of(context).confirm
|
||||
: S.of(context).unsubscribe;
|
||||
final btnIcon = operation == FireMapStatus.view
|
||||
? Icons.notifications_active
|
||||
: operation == FireMapStatus.subscriptionConfirm
|
||||
? Icons.check
|
||||
: Icons.notifications_off;
|
||||
updateFireStats(location);
|
||||
return new Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: new AppBar(
|
||||
title: new Text(location.description),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
|
||||
switch (operation) {
|
||||
case FireMapStatus.view:
|
||||
view.onSubs(location);
|
||||
break;
|
||||
case FireMapStatus.subscriptionConfirm:
|
||||
view.onSubsConfirmed(location);
|
||||
// IOS specific
|
||||
_firebaseMessaging.requestNotificationPermissions();
|
||||
operation = FireMapStatus.unsubscribe;
|
||||
break;
|
||||
case FireMapStatus.unsubscribe:
|
||||
view.onUnSubs(location);
|
||||
operation = FireMapStatus.view;
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
// https://github.com/flutter/flutter/issues/17583
|
||||
heroTag: "firesmap" + location.id.toHexString(),
|
||||
icon: new Icon(btnIcon, color: fires600),
|
||||
label: new Text(
|
||||
btnText,
|
||||
style: const TextStyle(color: fires600),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
floatingActionButtonLocation:
|
||||
FloatingActionButtonLocation.centerFloat,
|
||||
bottomNavigationBar: new CustomBottomAppBar(
|
||||
fabLocation: FloatingActionButtonLocation.centerFloat,
|
||||
showNotch: false,
|
||||
color: fires100,
|
||||
// height: 170.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
actions: listWithoutNulls(<Widget>[
|
||||
operation == FireMapStatus.subscriptionConfirm ||
|
||||
numFires == null
|
||||
? null
|
||||
: new Text(numFires > 0
|
||||
? S.of(context).firesAroundThisArea(
|
||||
numFires.toString(), kmAround.toString())
|
||||
: S
|
||||
.of(context)
|
||||
.noFiresAroundThisArea(kmAround.toString())),
|
||||
SizedBox(width: 10.0)
|
||||
])),
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) =>
|
||||
Stack(fit: StackFit.expand, children: <Widget>[
|
||||
// Material(color: Colors.yellowAccent),
|
||||
new Opacity(
|
||||
opacity:
|
||||
operation == FireMapStatus.subscriptionConfirm
|
||||
? 0.5
|
||||
: 1.0,
|
||||
child: new FlutterMap(
|
||||
options: mapOptions,
|
||||
mapController: mapController,
|
||||
layers: [
|
||||
new TileLayerOptions(
|
||||
maxZoom: 6.0,
|
||||
subdomains: ['a', 'b', 'c'],
|
||||
urlTemplate:
|
||||
'https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
|
||||
additionalOptions: {
|
||||
// 'opacity': '0.1',
|
||||
'attribution':
|
||||
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
},
|
||||
),
|
||||
globals.isDevelopment
|
||||
? new ZoomMapPluginOptions()
|
||||
: new DummyMapPluginOptions(),
|
||||
new MarkerLayerOptions(
|
||||
markers: buildMarkers(location, this.fires,
|
||||
this.industries, this.falsePos),
|
||||
),
|
||||
],
|
||||
)),
|
||||
Positioned(
|
||||
top: constraints.maxHeight - 200,
|
||||
right: 10.0,
|
||||
left: 10.0,
|
||||
child: new CenteredRow(
|
||||
// Fit sample:
|
||||
// https://github.com/apptreesoftware/flutter_map/blob/master/flutter_map_example/lib/pages/map_controller.dart
|
||||
children: operation ==
|
||||
FireMapStatus.subscriptionConfirm
|
||||
? <Widget>[
|
||||
new FireDistanceSlider(
|
||||
initialValue: kmAround,
|
||||
onSlide: (distance) {
|
||||
setState(() {
|
||||
kmAround = distance;
|
||||
Debounce.seconds(1, updateFireStats);
|
||||
});
|
||||
})
|
||||
]
|
||||
: [],
|
||||
),
|
||||
)
|
||||
]),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
List<Marker> buildMarkers(YourLocation yourLocation, List<dynamic> fires,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import 'models/firesApi.dart';
|
|||
import 'redux/fetchDataMiddleware.dart';
|
||||
import 'redux/reducers.dart';
|
||||
import 'package:fires_flutter/models/yourLocationPersist.dart';
|
||||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
|
||||
Future<Map<String, dynamic>> loadSecrets() async {
|
||||
return await SecretLoader(secretPath: 'assets/private-settings.json').load();
|
||||
|
|
|
|||
|
|
@ -78,7 +78,12 @@ class AppState extends Object with _$AppStateSerializerMixin {
|
|||
|
||||
typedef void AddYourLocationFunction(YourLocation loc);
|
||||
typedef void DeleteYourLocationFunction(ObjectId id);
|
||||
typedef void UpdateYourLocationFunction(ObjectId id, YourLocation loc);
|
||||
typedef void ToggleSubscriptionFunction(YourLocation loc);
|
||||
typedef void SubscribeFunction(ObjectId id);
|
||||
typedef void UnSubscribeFunction(ObjectId id);
|
||||
|
||||
typedef void OnLocationTapFunction(YourLocation loc);
|
||||
typedef void OnSubscribeFunction(YourLocation loc);
|
||||
typedef void OnUnSubscribeFunction(YourLocation loc);
|
||||
typedef void OnSubscribeConfirmedFunction(YourLocation loc);
|
||||
|
||||
// unused
|
||||
// typedef void UpdateYourLocationFunction(ObjectId id, YourLocation loc);
|
||||
|
|
|
|||
|
|
@ -1,27 +1,33 @@
|
|||
import 'package:meta/meta.dart';
|
||||
|
||||
enum FireMapOperation { view, subscriptionConfirm, unsubscribe }
|
||||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
enum FireMapStatus { view, subscriptionConfirm, unsubscribe }
|
||||
|
||||
@immutable
|
||||
class FireMapState {
|
||||
final FireMapOperation currentOperation;
|
||||
final FireMapStatus status;
|
||||
final YourLocation yourLocation;
|
||||
|
||||
const FireMapState.initial(): this.currentOperation = FireMapOperation.view;
|
||||
const FireMapState.initial(): this.status = FireMapStatus.view, this.yourLocation = null;
|
||||
|
||||
FireMapState({this.currentOperation: FireMapOperation.view});
|
||||
FireMapState({this.status: FireMapStatus.view, this.yourLocation});
|
||||
|
||||
FireMapState copyWith({FireMapStatus status, YourLocation yourLocation}) {
|
||||
return new FireMapState(
|
||||
yourLocation: yourLocation ?? this.yourLocation,
|
||||
status: status ?? this.status);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is FireMapState &&
|
||||
runtimeType == other.runtimeType &&
|
||||
currentOperation == other.currentOperation;
|
||||
status == other.status &&
|
||||
yourLocation == other.yourLocation;
|
||||
|
||||
@override
|
||||
int get hashCode => currentOperation.hashCode;
|
||||
|
||||
FireMapState copyWith({FireMapOperation currentOperation}) {
|
||||
return new FireMapState(
|
||||
currentOperation: currentOperation ?? this.currentOperation);
|
||||
}
|
||||
int get hashCode =>
|
||||
status.hashCode ^
|
||||
yourLocation.hashCode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ class FiresApi {
|
|||
var el = dataSubscriptions[i];
|
||||
var lat = el['location']['lat'];
|
||||
var lon = el['location']['lon'];
|
||||
var id = el['_id']['_str'];
|
||||
subscribed.add(new YourLocation(
|
||||
id: ObjectId.fromHexString(el['_id']['_str']),
|
||||
lat: lat,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'actions.dart';
|
||||
import '../models/user.dart';
|
||||
import '../models/appState.dart';
|
||||
|
||||
AppState appReducer(AppState state, action) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
import '../models/fireMapState.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
|
||||
FireMapState fireMapReducer(FireMapState state, action) {
|
||||
return state;
|
||||
}
|
||||
import '../models/fireMapState.dart';
|
||||
import 'actions.dart';
|
||||
|
||||
final fireMapReducer = combineReducers<FireMapState>([
|
||||
new TypedReducer<FireMapState, ShowYourLocationMapAction>(
|
||||
_showYourLocationMap),
|
||||
]);
|
||||
|
||||
FireMapState _showYourLocationMap(
|
||||
FireMapState state, ShowYourLocationMapAction action) {
|
||||
if (action.loc.subscribed) {
|
||||
return state.copyWith(
|
||||
status: action.loc.subscribed
|
||||
? FireMapStatus.unsubscribe
|
||||
: FireMapStatus.view,
|
||||
yourLocation: action.loc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import 'package:bson_objectid/bson_objectid.dart';
|
|||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
|
||||
|
||||
|
||||
abstract class YourLocationActions {}
|
||||
|
||||
class AddYourLocationAction extends YourLocationActions {
|
||||
|
|
@ -17,6 +16,12 @@ class AddedYourLocationAction extends YourLocationActions {
|
|||
AddedYourLocationAction(this.loc);
|
||||
}
|
||||
|
||||
class ShowYourLocationMapAction extends YourLocationActions {
|
||||
YourLocation loc;
|
||||
|
||||
ShowYourLocationMapAction(this.loc);
|
||||
}
|
||||
|
||||
class DeleteYourLocationAction extends YourLocationActions {
|
||||
ObjectId id;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue