More work with fire notifications
This commit is contained in:
parent
5fdaf239c0
commit
9dd8a7de97
24 changed files with 512 additions and 288 deletions
|
|
@ -5,17 +5,18 @@ import 'package:fires_flutter/models/yourLocation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_fab_dialer/flutter_fab_dialer.dart';
|
import 'package:flutter_fab_dialer/flutter_fab_dialer.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||||
import 'package:redux/src/store.dart';
|
import 'package:redux/src/store.dart';
|
||||||
|
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
import 'generated/i18n.dart';
|
import 'generated/i18n.dart';
|
||||||
|
import 'genericMap.dart';
|
||||||
import 'globalFiresBottomStats.dart';
|
import 'globalFiresBottomStats.dart';
|
||||||
import 'locationUtils.dart';
|
import 'locationUtils.dart';
|
||||||
import 'mainDrawer.dart';
|
import 'mainDrawer.dart';
|
||||||
import 'models/appState.dart';
|
import 'models/appState.dart';
|
||||||
import 'placesAutocompleteUtils.dart';
|
import 'placesAutocompleteUtils.dart';
|
||||||
import 'redux/actions.dart';
|
import 'redux/actions.dart';
|
||||||
import 'genericMap.dart';
|
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class _ViewModel {
|
class _ViewModel {
|
||||||
|
|
@ -24,35 +25,36 @@ class _ViewModel {
|
||||||
final DeleteYourLocationFunction onDelete;
|
final DeleteYourLocationFunction onDelete;
|
||||||
final ToggleSubscriptionFunction onToggleSubs;
|
final ToggleSubscriptionFunction onToggleSubs;
|
||||||
final OnLocationTapFunction onTap;
|
final OnLocationTapFunction onTap;
|
||||||
|
final bool isLoading;
|
||||||
|
|
||||||
_ViewModel(
|
_ViewModel(
|
||||||
{@required this.onAdd,
|
{@required this.onAdd,
|
||||||
@required this.onDelete,
|
@required this.onDelete,
|
||||||
@required this.onToggleSubs,
|
@required this.onToggleSubs,
|
||||||
@required this.onTap,
|
@required this.onTap,
|
||||||
@required this.yourLocations});
|
@required this.yourLocations,
|
||||||
|
@required this.isLoading});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) =>
|
||||||
return identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is _ViewModel &&
|
other is _ViewModel &&
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
yourLocations == other.yourLocations;
|
yourLocations == other.yourLocations &&
|
||||||
}
|
isLoading == other.isLoading;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => yourLocations.hashCode;
|
int get hashCode => yourLocations.hashCode ^ isLoading.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActiveFiresPage extends StatefulWidget {
|
class ActiveFiresPage extends StatefulWidget {
|
||||||
static const String routeName = '/fires';
|
static const String routeName = '/fires';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ActiveFiresPageState createState() => _ActiveFiresPageState();
|
_ActiveFiresPageState createState() => _ActiveFiresPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
||||||
|
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
List<FabMiniMenuItem> _fabMiniMenuItemList(
|
List<FabMiniMenuItem> _fabMiniMenuItemList(
|
||||||
|
|
@ -171,7 +173,8 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
||||||
onTap: (loc) {
|
onTap: (loc) {
|
||||||
gotoLocationMap(store, loc, context);
|
gotoLocationMap(store, loc, context);
|
||||||
},
|
},
|
||||||
yourLocations: store.state.yourLocations);
|
yourLocations: store.state.yourLocations,
|
||||||
|
isLoading: !store.state.isLoaded);
|
||||||
},
|
},
|
||||||
builder: (context, view) {
|
builder: (context, view) {
|
||||||
var hasLocations = view.yourLocations.length > 0;
|
var hasLocations = view.yourLocations.length > 0;
|
||||||
|
|
@ -196,27 +199,29 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
||||||
floatingActionButtonLocation:
|
floatingActionButtonLocation:
|
||||||
FloatingActionButtonLocation.centerFloat,
|
FloatingActionButtonLocation.centerFloat,
|
||||||
bottomNavigationBar: new GlobalFiresBottomStats(),
|
bottomNavigationBar: new GlobalFiresBottomStats(),
|
||||||
body: hasLocations
|
body: view.isLoading
|
||||||
? new Stack(children: <Widget>[
|
? new SpinKitPulse(color: fires600)
|
||||||
_buildSavedLocations(context, view.yourLocations,
|
: hasLocations
|
||||||
view.onDelete, view.onToggleSubs, view.onTap),
|
? new Stack(children: <Widget>[
|
||||||
new FabDialer(_fabMiniMenuItemList(context, view.onAdd),
|
_buildSavedLocations(context, view.yourLocations,
|
||||||
fires600, new Icon(Icons.add))
|
view.onDelete, view.onToggleSubs, view.onTap),
|
||||||
])
|
new FabDialer(_fabMiniMenuItemList(context, view.onAdd),
|
||||||
: new Center(
|
fires600, new Icon(Icons.add))
|
||||||
child: new CenteredColumn(children: <Widget>[
|
])
|
||||||
new RoundedBtn(
|
: new Center(
|
||||||
icon: Icons.location_searching,
|
child: new CenteredColumn(children: <Widget>[
|
||||||
text: S.of(context).addYourCurrentPosition,
|
new RoundedBtn(
|
||||||
onPressed: () => onAddYourLocation(view.onAdd),
|
icon: Icons.location_searching,
|
||||||
backColor: fires600),
|
text: S.of(context).addYourCurrentPosition,
|
||||||
const SizedBox(height: 26.0),
|
onPressed: () => onAddYourLocation(view.onAdd),
|
||||||
new RoundedBtn(
|
backColor: fires600),
|
||||||
icon: Icons.edit_location,
|
const SizedBox(height: 26.0),
|
||||||
text: S.of(context).addSomePlace,
|
new RoundedBtn(
|
||||||
onPressed: () => onAddOtherLocation(view.onAdd),
|
icon: Icons.edit_location,
|
||||||
backColor: fires600),
|
text: S.of(context).addSomePlace,
|
||||||
])),
|
onPressed: () => onAddOtherLocation(view.onAdd),
|
||||||
|
backColor: fires600),
|
||||||
|
])),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -224,8 +229,8 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
||||||
void gotoLocationMap(
|
void gotoLocationMap(
|
||||||
Store<AppState> store, YourLocation loc, BuildContext context) {
|
Store<AppState> store, YourLocation loc, BuildContext context) {
|
||||||
store.dispatch(new ShowYourLocationMapAction(loc));
|
store.dispatch(new ShowYourLocationMapAction(loc));
|
||||||
Navigator.push(context,
|
Navigator.push(
|
||||||
new MaterialPageRoute(builder: (context) => new genericMap()));
|
context, new MaterialPageRoute(builder: (context) => new genericMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onAddYourLocation(AddYourLocationFunction onAdd) {
|
void onAddYourLocation(AddYourLocationFunction onAdd) {
|
||||||
|
|
|
||||||
|
|
@ -2,43 +2,49 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||||
import 'package:fires_flutter/models/fireNotification.dart';
|
import 'package:fires_flutter/models/fireNotification.dart';
|
||||||
|
import 'package:fires_flutter/models/yourLocation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:redux/src/store.dart';
|
import 'package:redux/src/store.dart';
|
||||||
|
|
||||||
import 'customMoment.dart';
|
import 'customMoment.dart';
|
||||||
import 'generated/i18n.dart';
|
import 'generated/i18n.dart';
|
||||||
|
import 'genericMap.dart';
|
||||||
import 'mainDrawer.dart';
|
import 'mainDrawer.dart';
|
||||||
import 'models/appState.dart';
|
import 'models/appState.dart';
|
||||||
import 'redux/actions.dart';
|
import 'redux/actions.dart';
|
||||||
import 'genericMap.dart';
|
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class _ViewModel {
|
class _ViewModel {
|
||||||
final List<FireNotification> fireNotifications;
|
final List<FireNotification> fireNotifications;
|
||||||
|
final int fireNotificationsUnread;
|
||||||
|
final List<YourLocation> yourLocations;
|
||||||
final TapFireNotificationFunction onTap;
|
final TapFireNotificationFunction onTap;
|
||||||
|
|
||||||
//final OnReceivedFireNotificationFunction onReceived;
|
|
||||||
final DeleteFireNotificationFunction onDelete;
|
final DeleteFireNotificationFunction onDelete;
|
||||||
final DeleteAllFireNotificationFunction onDeleteAll;
|
final DeleteAllFireNotificationFunction onDeleteAll;
|
||||||
|
|
||||||
_ViewModel(
|
_ViewModel(
|
||||||
{@required this.onTap,
|
{@required this.onTap,
|
||||||
// @required this.onReceived,
|
|
||||||
@required this.onDelete,
|
@required this.onDelete,
|
||||||
@required this.onDeleteAll,
|
@required this.onDeleteAll,
|
||||||
@required this.fireNotifications});
|
@required this.fireNotifications,
|
||||||
|
@required this.yourLocations,
|
||||||
|
@required this.fireNotificationsUnread});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) =>
|
||||||
return identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is _ViewModel &&
|
other is _ViewModel &&
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
fireNotifications == other.fireNotifications;
|
fireNotifications == other.fireNotifications &&
|
||||||
}
|
fireNotificationsUnread == other.fireNotificationsUnread &&
|
||||||
|
yourLocations == other.yourLocations;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => fireNotifications.hashCode;
|
int get hashCode =>
|
||||||
|
fireNotifications.hashCode ^
|
||||||
|
fireNotificationsUnread.hashCode ^
|
||||||
|
yourLocations.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FireNotificationList extends StatefulWidget {
|
class FireNotificationList extends StatefulWidget {
|
||||||
|
|
@ -51,12 +57,13 @@ class FireNotificationList extends StatefulWidget {
|
||||||
class _FireNotificationListState extends State<FireNotificationList> {
|
class _FireNotificationListState extends State<FireNotificationList> {
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
Widget _buildRow(
|
Widget _buildRow(BuildContext context, List<YourLocation> yourLocations,
|
||||||
BuildContext context, FireNotification notif, onDeleted, onTap) {
|
FireNotification notif, onDeleted, onTap) {
|
||||||
|
YourLocation yl = yourLocations.singleWhere((yl) => yl.id == notif.subsId);
|
||||||
return new ListTile(
|
return new ListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
leading: const Icon(Icons.whatshot),
|
leading: const Icon(Icons.whatshot),
|
||||||
title: new Text(notif.description,
|
title: new Text('${yl.description}. ${notif.description}',
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontWeight: notif.read ? FontWeight.normal : FontWeight.bold)),
|
fontWeight: notif.read ? FontWeight.normal : FontWeight.bold)),
|
||||||
subtitle: new Text(Moment.now().from(context, notif.when)),
|
subtitle: new Text(Moment.now().from(context, notif.when)),
|
||||||
|
|
@ -74,13 +81,17 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSavedFireNotifications(BuildContext context,
|
Widget _buildSavedFireNotifications(
|
||||||
List<FireNotification> notifList, onDeleted, onTap) {
|
BuildContext context,
|
||||||
|
List<YourLocation> yourLocations,
|
||||||
|
List<FireNotification> notifList,
|
||||||
|
onDeleted,
|
||||||
|
onTap) {
|
||||||
return new RefreshIndicator(
|
return new RefreshIndicator(
|
||||||
child: new ListView.builder(
|
child: new ListView.builder(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
reverse: true,
|
// reverse: true,
|
||||||
shrinkWrap: true,
|
// shrinkWrap: true,
|
||||||
itemCount: notifList.length,
|
itemCount: notifList.length,
|
||||||
itemBuilder: (BuildContext _context, int i) {
|
itemBuilder: (BuildContext _context, int i) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
|
|
@ -106,8 +117,8 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
||||||
border: new Border(
|
border: new Border(
|
||||||
bottom:
|
bottom:
|
||||||
new BorderSide(color: theme.dividerColor))),
|
new BorderSide(color: theme.dividerColor))),
|
||||||
child: _buildRow(
|
child: _buildRow(context, yourLocations,
|
||||||
context, notifList.elementAt(i), onDeleted, onTap)));
|
notifList.elementAt(i), onDeleted, onTap)));
|
||||||
}),
|
}),
|
||||||
onRefresh: _handleRefresh);
|
onRefresh: _handleRefresh);
|
||||||
}
|
}
|
||||||
|
|
@ -145,11 +156,13 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
||||||
store.dispatch(new ReadFireNotificationAction(
|
store.dispatch(new ReadFireNotificationAction(
|
||||||
notif.copyWith(read: true)));
|
notif.copyWith(read: true)));
|
||||||
}
|
}
|
||||||
new Timer(new Duration(milliseconds: 1000), () {
|
new Timer(new Duration(milliseconds: 500), () {
|
||||||
gotoMap(store, notif, context);
|
gotoMap(store, notif, context);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fireNotifications: store.state.fireNotifications);
|
yourLocations: store.state.yourLocations,
|
||||||
|
fireNotifications: store.state.fireNotifications,
|
||||||
|
fireNotificationsUnread: store.state.fireNotificationsUnread);
|
||||||
},
|
},
|
||||||
builder: (context, view) {
|
builder: (context, view) {
|
||||||
var hasFireNotifications = view.fireNotifications.length > 0;
|
var hasFireNotifications = view.fireNotifications.length > 0;
|
||||||
|
|
@ -191,16 +204,16 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
height: 1.3, color: Colors.black45))
|
height: 1.3, color: Colors.black45))
|
||||||
]))))
|
]))))
|
||||||
: _buildSavedFireNotifications(context,
|
: _buildSavedFireNotifications(context, view.yourLocations,
|
||||||
view.fireNotifications, view.onDelete, view.onTap));
|
view.fireNotifications, view.onDelete, view.onTap));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void gotoMap(
|
void gotoMap(
|
||||||
Store<AppState> store, FireNotification notif, BuildContext context) {
|
Store<AppState> store, FireNotification notif, BuildContext context) {
|
||||||
store.dispatch(new ShowFireNotificationMapAction(notif));
|
store.dispatch(new ShowFireNotificationMapAction(notif));
|
||||||
Navigator.push(context,
|
Navigator.push(
|
||||||
new MaterialPageRoute(builder: (context) => new genericMap()));
|
context, new MaterialPageRoute(builder: (context) => new genericMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
_showConfirmDialog(_ViewModel view) {
|
_showConfirmDialog(_ViewModel view) {
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import 'package:bson_objectid/bson_objectid.dart';
|
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
||||||
import 'package:fires_flutter/models/fireNotification.dart';
|
|
||||||
import 'package:redux/src/store.dart';
|
|
||||||
|
|
||||||
import 'models/appState.dart';
|
|
||||||
import 'redux/actions.dart';
|
|
||||||
|
|
||||||
final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
|
|
||||||
|
|
||||||
// https://pub.dartlang.org/packages/firebase_messaging#-example-tab-
|
|
||||||
void firebaseConfig(Store<AppState> store) {
|
|
||||||
_firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
|
|
||||||
print("onMessage: $message");
|
|
||||||
onMessage(message, store);
|
|
||||||
//_showItemDialog(message);
|
|
||||||
}, onLaunch: (Map<String, dynamic> message) {
|
|
||||||
print("onLaunch: $message");
|
|
||||||
//_navigateToItemDetail(message);
|
|
||||||
onMessage(message, store);
|
|
||||||
}, onResume: (Map<String, dynamic> message) {
|
|
||||||
print("onResume: $message");
|
|
||||||
//_navigateToItemDetail(message);
|
|
||||||
onMessage(message, store);
|
|
||||||
});
|
|
||||||
|
|
||||||
getToken(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onMessage(Map<String, dynamic> message, Store<AppState> store) {
|
|
||||||
FireNotification notif = new FireNotification(
|
|
||||||
id: new ObjectId.fromHexString(message['id']),
|
|
||||||
lat: double.parse(message['lat']),
|
|
||||||
lon: double.parse(message['lon']),
|
|
||||||
description: message['description'],
|
|
||||||
read: false,
|
|
||||||
when: DateTime.parse(message['when']));
|
|
||||||
print(notif);
|
|
||||||
store.dispatch(new AddFireNotificationAction(notif));
|
|
||||||
}
|
|
||||||
|
|
||||||
getToken(Store<AppState> store) async {
|
|
||||||
String token = await _firebaseMessaging.onTokenRefresh.first;
|
|
||||||
// print(token);
|
|
||||||
store.dispatch(new OnUserTokenAction(token));
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +1,38 @@
|
||||||
|
import 'package:bson_objectid/bson_objectid.dart';
|
||||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||||
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
|
import 'package:fires_flutter/models/fireNotification.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:redux/src/store.dart';
|
||||||
|
|
||||||
import 'activeFires.dart';
|
import 'activeFires.dart';
|
||||||
|
import 'fireAlert.dart';
|
||||||
|
import 'fireNotificationList.dart';
|
||||||
import 'generated/i18n.dart';
|
import 'generated/i18n.dart';
|
||||||
import 'homePage.dart';
|
import 'homePage.dart';
|
||||||
import 'introPage.dart';
|
import 'introPage.dart';
|
||||||
import 'models/appState.dart';
|
import 'models/appState.dart';
|
||||||
|
import 'privacyPage.dart';
|
||||||
import 'redux/actions.dart';
|
import 'redux/actions.dart';
|
||||||
import 'sandbox.dart';
|
import 'sandbox.dart';
|
||||||
import 'theme.dart';
|
|
||||||
import 'privacyPage.dart';
|
|
||||||
import 'fireAlert.dart';
|
|
||||||
import 'supportPage.dart';
|
import 'supportPage.dart';
|
||||||
import 'fireNotificationList.dart';
|
import 'theme.dart';
|
||||||
|
|
||||||
class FiresApp extends StatelessWidget {
|
class FiresApp extends StatefulWidget {
|
||||||
|
FiresApp(this.store);
|
||||||
|
|
||||||
|
final Store<AppState> store;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_FiresAppState createState() => _FiresAppState(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FiresAppState extends State<FiresApp> {
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey =
|
||||||
|
new GlobalKey<NavigatorState>();
|
||||||
static final WidgetBuilder introWidget = (context) => new IntroPage();
|
static final WidgetBuilder introWidget = (context) => new IntroPage();
|
||||||
static final WidgetBuilder continueWidget = (context) => new HomePage();
|
static final WidgetBuilder continueWidget = (context) => new HomePage();
|
||||||
|
|
||||||
|
|
@ -29,22 +44,23 @@ class FiresApp extends StatelessWidget {
|
||||||
Sandbox.routeName: (BuildContext context) => new Sandbox(),
|
Sandbox.routeName: (BuildContext context) => new Sandbox(),
|
||||||
FireAlert.routeName: (BuildContext context) => new FireAlert(),
|
FireAlert.routeName: (BuildContext context) => new FireAlert(),
|
||||||
SupportPage.routeName: (BuildContext context) => new SupportPage(),
|
SupportPage.routeName: (BuildContext context) => new SupportPage(),
|
||||||
FireNotificationList.routeName: (BuildContext context) => new FireNotificationList(),
|
FireNotificationList.routeName: (BuildContext context) =>
|
||||||
|
new FireNotificationList(),
|
||||||
};
|
};
|
||||||
|
|
||||||
final Store<AppState> store;
|
final Store<AppState> store;
|
||||||
|
|
||||||
// globals.getIt.registerSingleton
|
// globals.getIt.registerSingleton
|
||||||
FiresApp(this.store);
|
_FiresAppState(this.store);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
StatefulWidget home = new MaterialAppWithIntroHome(
|
StatefulWidget home = new MaterialAppWithIntroHome(
|
||||||
introWidget, continueWidget, 'showInitialWizard-2018-06-27-01');
|
introWidget, continueWidget, 'showInitialWizard-2018-06-27-01');
|
||||||
return new StoreProvider<AppState>(
|
return new StoreProvider<AppState>(
|
||||||
|
|
||||||
store: this.store,
|
store: this.store,
|
||||||
child: new MaterialApp(
|
child: new MaterialApp(
|
||||||
|
navigatorKey: navigatorKey,
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
S.delegate,
|
S.delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
|
@ -65,4 +81,97 @@ class FiresApp extends StatelessWidget {
|
||||||
theme: firesTheme,
|
theme: firesTheme,
|
||||||
routes: routes));
|
routes: routes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
|
||||||
|
print("onMessage in fireApp: $message");
|
||||||
|
_showItemDialog(message, store);
|
||||||
|
}, onLaunch: (Map<String, dynamic> message) {
|
||||||
|
print("onLaunch: $message");
|
||||||
|
_navigateToItemDetail(message, store);
|
||||||
|
}, onResume: (Map<String, dynamic> message) {
|
||||||
|
print("onResume: $message");
|
||||||
|
_navigateToItemDetail(message, store);
|
||||||
|
});
|
||||||
|
_firebaseMessaging.requestNotificationPermissions(
|
||||||
|
const IosNotificationSettings(sound: true, badge: true, alert: true));
|
||||||
|
_firebaseMessaging.onIosSettingsRegistered
|
||||||
|
.listen((IosNotificationSettings settings) {
|
||||||
|
print("Settings registered: $settings");
|
||||||
|
});
|
||||||
|
_firebaseMessaging.getToken().then((String token) {
|
||||||
|
assert(token != null);
|
||||||
|
store.dispatch(new OnUserTokenAction(token));
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showItemDialog(Map<String, dynamic> message, Store store) {
|
||||||
|
final notif = _notifForMessage(message);
|
||||||
|
showDialog<bool>(
|
||||||
|
context: navigatorKey.currentContext,
|
||||||
|
builder: (_) => _buildDialog(navigatorKey.currentContext, notif),
|
||||||
|
).then((bool shouldNavigate) {
|
||||||
|
if (shouldNavigate == true) {
|
||||||
|
_navigateToItemDetail(message, store);
|
||||||
|
}
|
||||||
|
}).catchError((e) => print("$e"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDialog(BuildContext context, FireNotification item) {
|
||||||
|
return new AlertDialog(
|
||||||
|
content: new Text(item.description),
|
||||||
|
actions: <Widget>[
|
||||||
|
new FlatButton(
|
||||||
|
child: Text(S.of(context).CLOSE),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, false);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
new FlatButton(
|
||||||
|
child: Text(S.of(context).SHOW),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _navigateToItemDetail(Map<String, dynamic> message, Store store) {
|
||||||
|
FireNotification notif = _notifForMessage(message);
|
||||||
|
// Clear away dialogs
|
||||||
|
Navigator.popUntil(navigatorKey.currentContext,
|
||||||
|
(Route<dynamic> route) => route is PageRoute);
|
||||||
|
if (!notif.getRoute(store).isCurrent) {
|
||||||
|
Navigator.push(navigatorKey.currentContext, notif.getRoute(store));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://pub.dartlang.org/packages/firebase_messaging#-example-tab-
|
||||||
|
final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
|
||||||
|
|
||||||
|
FireNotification _notifForMessage(Map<String, dynamic> message) {
|
||||||
|
FireNotification notif;
|
||||||
|
print('start parse notif');
|
||||||
|
try {
|
||||||
|
notif = new FireNotification(
|
||||||
|
id: new ObjectId.fromHexString(message['id']),
|
||||||
|
lat: double.parse(message['lat']),
|
||||||
|
lon: double.parse(message['lon']),
|
||||||
|
description: message['description'],
|
||||||
|
read: false,
|
||||||
|
when: DateTime.parse(message['when']),
|
||||||
|
sealed: message['sealed'],
|
||||||
|
subsId: new ObjectId.fromHexString(message['subsId']));
|
||||||
|
print('end parse notif');
|
||||||
|
debugPrint(notif.toString());
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint(e.toString());
|
||||||
|
}
|
||||||
|
store.dispatch(new AddFireNotificationAction(notif));
|
||||||
|
return notif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,10 @@ class S implements WidgetsLocalizations {
|
||||||
|
|
||||||
String get AvoidThisStringsIfisNotPlural => "Zero One Two Few Many Other";
|
String get AvoidThisStringsIfisNotPlural => "Zero One Two Few Many Other";
|
||||||
String get CANCEL => "CANCEL";
|
String get CANCEL => "CANCEL";
|
||||||
|
String get CLOSE => "CLOSE";
|
||||||
String get DELETE => "DELETE";
|
String get DELETE => "DELETE";
|
||||||
String get SAVE => "SAVE";
|
String get SAVE => "SAVE";
|
||||||
|
String get SHOW => "SHOW";
|
||||||
String get UNDO => "UNDO";
|
String get UNDO => "UNDO";
|
||||||
String get aDay => "a day";
|
String get aDay => "a day";
|
||||||
String get aF3wSeconds => "a few seconds";
|
String get aF3wSeconds => "a few seconds";
|
||||||
|
|
@ -111,6 +113,8 @@ class es extends S {
|
||||||
@override
|
@override
|
||||||
String get callEmergencyServicesDescription => "Deberías llamar al 112 si no lo has hecho ya para avisar a los servicios de emergencia.";
|
String get callEmergencyServicesDescription => "Deberías llamar al 112 si no lo has hecho ya para avisar a los servicios de emergencia.";
|
||||||
@override
|
@override
|
||||||
|
String get CLOSE => "CERRAR";
|
||||||
|
@override
|
||||||
String get errorFirePlaceDialog => "No hemos podido obtener la ubicación del fuego";
|
String get errorFirePlaceDialog => "No hemos podido obtener la ubicación del fuego";
|
||||||
@override
|
@override
|
||||||
String get toDeleteThisPlace => "Desliza horizontalmente para borrar este lugar";
|
String get toDeleteThisPlace => "Desliza horizontalmente para borrar este lugar";
|
||||||
|
|
@ -163,6 +167,8 @@ class es extends S {
|
||||||
@override
|
@override
|
||||||
String get SAVE => "GUARDAR";
|
String get SAVE => "GUARDAR";
|
||||||
@override
|
@override
|
||||||
|
String get SHOW => "MOSTRAR";
|
||||||
|
@override
|
||||||
String get addedThisLocation => "Ya has añadido este lugar antes";
|
String get addedThisLocation => "Ya has añadido este lugar antes";
|
||||||
@override
|
@override
|
||||||
String get typeTheNameOfAPlace => "Escribe el nombre de un lugar, zona, etc";
|
String get typeTheNameOfAPlace => "Escribe el nombre de un lugar, zona, etc";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
|
||||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
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/basicLocation.dart';
|
||||||
import 'package:fires_flutter/models/yourLocation.dart';
|
import 'package:fires_flutter/models/yourLocation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -9,6 +8,7 @@ import 'package:flutter_map/flutter_map.dart';
|
||||||
import 'package:flutter_map/plugin_api.dart';
|
import 'package:flutter_map/plugin_api.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:latlong/latlong.dart';
|
import 'package:latlong/latlong.dart';
|
||||||
|
import 'package:share/share.dart';
|
||||||
|
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
import 'dummyMapPlugin.dart';
|
import 'dummyMapPlugin.dart';
|
||||||
|
|
@ -25,6 +25,7 @@ import 'zoomMapPlugin.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class _ViewModel {
|
class _ViewModel {
|
||||||
|
final String serverUrl;
|
||||||
final FireMapState mapState;
|
final FireMapState mapState;
|
||||||
final OnSubscribeFunction onSubs;
|
final OnSubscribeFunction onSubs;
|
||||||
final OnSubscribeConfirmedFunction onSubsConfirmed;
|
final OnSubscribeConfirmedFunction onSubsConfirmed;
|
||||||
|
|
@ -37,6 +38,7 @@ class _ViewModel {
|
||||||
|
|
||||||
_ViewModel(
|
_ViewModel(
|
||||||
{@required this.mapState,
|
{@required this.mapState,
|
||||||
|
@required this.serverUrl,
|
||||||
@required this.onSubs,
|
@required this.onSubs,
|
||||||
@required this.onSubsConfirmed,
|
@required this.onSubsConfirmed,
|
||||||
@required this.onUnSubs,
|
@required this.onUnSubs,
|
||||||
|
|
@ -66,7 +68,7 @@ class _genericMapState extends State<genericMap> {
|
||||||
// This needs to be stateful so when resizes don't get a new globalkey
|
// This needs to be stateful so when resizes don't get a new globalkey
|
||||||
// https://github.com/flutter/flutter/issues/1632#issuecomment-180478202
|
// https://github.com/flutter/flutter/issues/1632#issuecomment-180478202
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
|
|
||||||
YourLocation _location;
|
YourLocation _location;
|
||||||
YourLocation _initialLocation;
|
YourLocation _initialLocation;
|
||||||
|
|
||||||
|
|
@ -105,6 +107,7 @@ class _genericMapState extends State<genericMap> {
|
||||||
store.dispatch(new UpdateYourLocationMapAction(loc));
|
store.dispatch(new UpdateYourLocationMapAction(loc));
|
||||||
store.dispatch(new EditConfirmYourLocationAction(loc));
|
store.dispatch(new EditConfirmYourLocationAction(loc));
|
||||||
},
|
},
|
||||||
|
serverUrl: store.state.firesApiUrl,
|
||||||
mapState: store.state.fireMapState);
|
mapState: store.state.fireMapState);
|
||||||
},
|
},
|
||||||
builder: (context, view) {
|
builder: (context, view) {
|
||||||
|
|
@ -223,8 +226,6 @@ class _genericMapState extends State<genericMap> {
|
||||||
break;
|
break;
|
||||||
case FireMapStatus.subscriptionConfirm:
|
case FireMapStatus.subscriptionConfirm:
|
||||||
view.onSubsConfirmed(_location);
|
view.onSubsConfirmed(_location);
|
||||||
// IOS specific
|
|
||||||
_firebaseMessaging.requestNotificationPermissions();
|
|
||||||
break;
|
break;
|
||||||
case FireMapStatus.unsubscribe:
|
case FireMapStatus.unsubscribe:
|
||||||
view.onUnSubs(_location);
|
view.onUnSubs(_location);
|
||||||
|
|
@ -299,6 +300,14 @@ class _genericMapState extends State<genericMap> {
|
||||||
icon: new Icon(Icons.save),
|
icon: new Icon(Icons.save),
|
||||||
onPressed: () => view.onEditConfirm(_location))
|
onPressed: () => view.onEditConfirm(_location))
|
||||||
];
|
];
|
||||||
|
case FireMapStatus.viewFireNotification:
|
||||||
|
return <Widget>[
|
||||||
|
new IconButton(
|
||||||
|
icon: new Icon(Icons.share),
|
||||||
|
onPressed: () {
|
||||||
|
Share.share('${view.mapState.fireNotification.description}. ${view.serverUrl}fire/${view.mapState.fireNotification.sealed}');
|
||||||
|
})
|
||||||
|
];
|
||||||
default:
|
default:
|
||||||
return <Widget>[];
|
return <Widget>[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import 'package:flutter_simple_dependency_injection/injector.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:sentry/sentry.dart';
|
import 'package:sentry/sentry.dart';
|
||||||
|
|
||||||
import 'firebaseMessagingConf.dart';
|
|
||||||
import 'firesApp.dart';
|
import 'firesApp.dart';
|
||||||
import 'globals.dart' as globals;
|
import 'globals.dart' as globals;
|
||||||
import 'models/appState.dart';
|
import 'models/appState.dart';
|
||||||
|
|
@ -27,6 +26,7 @@ void mainCommon(List<Middleware<AppState>> otherMiddleware) {
|
||||||
initialState: new AppState(
|
initialState: new AppState(
|
||||||
gmapKey: secrets['gmapKey'],
|
gmapKey: secrets['gmapKey'],
|
||||||
firesApiKey: secrets['firesApiKey'],
|
firesApiKey: secrets['firesApiKey'],
|
||||||
|
serverUrl: secrets['firesApiUrl'],
|
||||||
firesApiUrl: secrets['firesApiUrl'] + "api/v1/"),
|
firesApiUrl: secrets['firesApiUrl'] + "api/v1/"),
|
||||||
middleware: List.from(otherMiddleware)
|
middleware: List.from(otherMiddleware)
|
||||||
..add(fetchDataMiddleware));
|
..add(fetchDataMiddleware));
|
||||||
|
|
@ -37,8 +37,6 @@ void mainCommon(List<Middleware<AppState>> otherMiddleware) {
|
||||||
|
|
||||||
VoidCallback mainFn = () {
|
VoidCallback mainFn = () {
|
||||||
loadYourLocations().then((yl) {
|
loadYourLocations().then((yl) {
|
||||||
firebaseConfig(store);
|
|
||||||
|
|
||||||
// Run baby run!
|
// Run baby run!
|
||||||
runApp(new FiresApp(store));
|
runApp(new FiresApp(store));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ void main() {
|
||||||
return ">>>>> ${action.toString().replaceAll('Instance of ', '')}";
|
return ">>>>> ${action.toString().replaceAll('Instance of ', '')}";
|
||||||
}
|
}
|
||||||
|
|
||||||
LogLevel logRedux = LogLevel.actions;
|
LogLevel logRedux = LogLevel.full;
|
||||||
|
|
||||||
List<Middleware> devMiddlewares = logRedux == LogLevel.none
|
List<Middleware> devMiddlewares = logRedux == LogLevel.none
|
||||||
? []
|
? []
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,38 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:badge/badge.dart';
|
||||||
|
|
||||||
import 'colors.dart';
|
|
||||||
import 'sandbox.dart';
|
|
||||||
import 'activeFires.dart';
|
|
||||||
import 'globals.dart' as globals;
|
|
||||||
import 'generated/i18n.dart';
|
|
||||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||||
import 'privacyPage.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
|
||||||
|
import 'activeFires.dart';
|
||||||
|
import 'colors.dart';
|
||||||
import 'fireAlert.dart';
|
import 'fireAlert.dart';
|
||||||
import 'supportPage.dart';
|
|
||||||
import 'fireNotificationList.dart';
|
import 'fireNotificationList.dart';
|
||||||
import 'package:community_material_icon/community_material_icon.dart';
|
import 'generated/i18n.dart';
|
||||||
|
import 'globals.dart' as globals;
|
||||||
|
import 'models/appState.dart';
|
||||||
|
import 'privacyPage.dart';
|
||||||
|
import 'sandbox.dart';
|
||||||
|
import 'supportPage.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class _ViewModel {
|
||||||
|
final int unreadCount;
|
||||||
|
|
||||||
|
_ViewModel({
|
||||||
|
@required this.unreadCount,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
other is _ViewModel &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
unreadCount == other.unreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => unreadCount.hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
class MainDrawer extends Drawer {
|
class MainDrawer extends Drawer {
|
||||||
MainDrawer(BuildContext context, {key})
|
MainDrawer(BuildContext context, {key})
|
||||||
|
|
@ -18,101 +40,115 @@ class MainDrawer extends Drawer {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget mainDrawer(BuildContext context) {
|
Widget mainDrawer(BuildContext context) {
|
||||||
return new ListView(
|
return new StoreConnector<AppState, _ViewModel>(
|
||||||
// Important: Remove any padding from the ListView.
|
distinct: true,
|
||||||
padding: EdgeInsets.zero,
|
converter: (store) {
|
||||||
children: listWithoutNulls(<Widget>[
|
return new _ViewModel(unreadCount: store.state.fireNotificationsUnread);
|
||||||
new GestureDetector(
|
},
|
||||||
onTap: () {
|
builder: (context, view) {
|
||||||
Navigator.pop(context);
|
return new ListView(
|
||||||
Navigator.pushNamed(context, '/');
|
// Important: Remove any padding from the ListView.
|
||||||
},
|
padding: EdgeInsets.zero,
|
||||||
child: new DrawerHeader(
|
children: listWithoutNulls(<Widget>[
|
||||||
child: new Column(
|
new GestureDetector(
|
||||||
children: <Widget>[
|
onTap: () {
|
||||||
new Image.asset(
|
Navigator.pop(context);
|
||||||
'images/logo-200.png',
|
Navigator.pushNamed(context, '/');
|
||||||
fit: BoxFit.scaleDown,
|
},
|
||||||
height: 80.0,
|
child: new DrawerHeader(
|
||||||
|
child: new Column(
|
||||||
|
children: <Widget>[
|
||||||
|
new Image.asset(
|
||||||
|
'images/logo-200.png',
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
height: 80.0,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20.0),
|
||||||
|
new Text(S.of(context).appName,
|
||||||
|
style: new TextStyle(
|
||||||
|
fontSize: 24.0,
|
||||||
|
color: Colors.white,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
color: fires300,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
new ListTile(
|
||||||
new Text(S.of(context).appName,
|
leading: const Icon(Icons.whatshot),
|
||||||
style: new TextStyle(
|
title: new Text(S.of(context).activeFires),
|
||||||
fontSize: 24.0,
|
onTap: () {
|
||||||
color: Colors.white,
|
Navigator.pop(context);
|
||||||
)),
|
Navigator.pushNamed(context, ActiveFiresPage.routeName);
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
decoration: new BoxDecoration(
|
new ListTile(
|
||||||
color: fires300,
|
leading: const Icon(Icons.notifications_active),
|
||||||
),
|
title: new Text(S.of(context).notifyAFire),
|
||||||
),
|
onTap: () {
|
||||||
),
|
// Then close the drawer
|
||||||
new ListTile(
|
Navigator.pop(context);
|
||||||
leading: const Icon(Icons.whatshot),
|
Navigator.pushNamed(context, FireAlert.routeName);
|
||||||
title: new Text(S.of(context).activeFires),
|
},
|
||||||
onTap: () {
|
),
|
||||||
Navigator.pop(context);
|
new ListTile(
|
||||||
Navigator.pushNamed(context, ActiveFiresPage.routeName);
|
leading: const Icon(Icons.notifications),
|
||||||
},
|
title: view.unreadCount > 0
|
||||||
),
|
? Badge.after(
|
||||||
new ListTile(
|
spacing: 5.0,
|
||||||
leading: const Icon(Icons.notifications_active),
|
borderColor: Colors.red,
|
||||||
title: new Text(S.of(context).notifyAFire),
|
child: Text(S.of(context).fireNotificationsTitleShort),
|
||||||
onTap: () {
|
value: ' ${view.unreadCount.toString()} ')
|
||||||
// Then close the drawer
|
: Text(S.of(context).fireNotificationsTitleShort),
|
||||||
Navigator.pop(context);
|
onTap: () {
|
||||||
Navigator.pushNamed(context, FireAlert.routeName);
|
// Then close the drawer
|
||||||
},
|
Navigator.pop(context);
|
||||||
),
|
Navigator.pushNamed(context, FireNotificationList.routeName);
|
||||||
new ListTile(
|
},
|
||||||
leading: const Icon(Icons.notifications),
|
),
|
||||||
title: new Text(S.of(context).fireNotificationsTitleShort),
|
new Divider(),
|
||||||
onTap: () {
|
new ListTile(
|
||||||
// Then close the drawer
|
leading: const Icon(Icons.favorite),
|
||||||
Navigator.pop(context);
|
title: new Text(S.of(context).supportThisInitiative),
|
||||||
Navigator.pushNamed(context, FireNotificationList.routeName);
|
onTap: () {
|
||||||
},
|
// Then close the drawer
|
||||||
),
|
Navigator.pop(context);
|
||||||
new Divider(),
|
Navigator.pushNamed(context, SupportPage.routeName);
|
||||||
new ListTile(
|
},
|
||||||
leading: const Icon(Icons.favorite),
|
),
|
||||||
title: new Text(S.of(context).supportThisInitiative),
|
new ListTile(
|
||||||
onTap: () {
|
leading: const Icon(Icons.lock),
|
||||||
// Then close the drawer
|
title: new Text(S.of(context).privacyPolicy),
|
||||||
Navigator.pop(context);
|
onTap: () {
|
||||||
Navigator.pushNamed(context, SupportPage.routeName);
|
// Then close the drawer
|
||||||
},
|
Navigator.pop(context);
|
||||||
),
|
Navigator.pushNamed(context, PrivacyPage.routeName);
|
||||||
new ListTile(
|
},
|
||||||
leading: const Icon(Icons.lock),
|
),
|
||||||
title: new Text(S.of(context).privacyPolicy),
|
globals.isDevelopment
|
||||||
onTap: () {
|
? new ListTile(
|
||||||
// Then close the drawer
|
leading: const Icon(Icons.bug_report),
|
||||||
Navigator.pop(context);
|
title: new Text('Sandbox'),
|
||||||
Navigator.pushNamed(context, PrivacyPage.routeName);
|
onTap: () {
|
||||||
},
|
Navigator.pop(context);
|
||||||
),
|
Navigator.pushNamed(context, Sandbox.routeName);
|
||||||
globals.isDevelopment ?
|
},
|
||||||
new ListTile(
|
)
|
||||||
leading: const Icon(Icons.bug_report),
|
: null,
|
||||||
title: new Text('Sandbox'),
|
new AboutListTile(
|
||||||
onTap: () {
|
icon: globals.appIcon,
|
||||||
Navigator.pop(context);
|
applicationName: S.of(context).appName,
|
||||||
Navigator.pushNamed(context, Sandbox.routeName);
|
applicationVersion: globals.appVersion,
|
||||||
},
|
applicationIcon: globals.appMediumIcon,
|
||||||
): null,
|
applicationLegalese:
|
||||||
new AboutListTile(
|
S.of(context).appLicense(DateTime.now().year.toString()),
|
||||||
icon: globals.appIcon,
|
aboutBoxChildren: <Widget>[
|
||||||
applicationName: S.of(context).appName,
|
// new Text('What?')
|
||||||
applicationVersion: globals.appVersion,
|
]
|
||||||
applicationIcon: globals.appMediumIcon,
|
// FIXME
|
||||||
applicationLegalese: S.of(context).appLicense(DateTime.now().year.toString()),
|
)
|
||||||
aboutBoxChildren: <Widget> [
|
]));
|
||||||
// new Text('What?')
|
});
|
||||||
]
|
|
||||||
// FIXME
|
|
||||||
)
|
|
||||||
])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||||
import 'package:fires_flutter/models/yourLocation.dart';
|
|
||||||
import 'package:fires_flutter/models/fireNotification.dart';
|
import 'package:fires_flutter/models/fireNotification.dart';
|
||||||
|
import 'package:fires_flutter/models/yourLocation.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
|
@ -25,12 +25,16 @@ class AppState extends Object with _$AppStateSerializerMixin {
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
final String gmapKey;
|
final String gmapKey;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
|
final String serverUrl;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
final String firesApiKey;
|
final String firesApiKey;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
final String firesApiUrl;
|
final String firesApiUrl;
|
||||||
final List<YourLocation> yourLocations;
|
final List<YourLocation> yourLocations;
|
||||||
final List<FireNotification> fireNotifications;
|
final List<FireNotification> fireNotifications;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
|
final int fireNotificationsUnread;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
final FireMapState fireMapState;
|
final FireMapState fireMapState;
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
|
|
@ -40,13 +44,15 @@ class AppState extends Object with _$AppStateSerializerMixin {
|
||||||
AppState(
|
AppState(
|
||||||
{this.yourLocations: const <YourLocation>[],
|
{this.yourLocations: const <YourLocation>[],
|
||||||
this.fireNotifications: const <FireNotification>[],
|
this.fireNotifications: const <FireNotification>[],
|
||||||
|
this.fireNotificationsUnread: 0,
|
||||||
this.user: const User.initial(),
|
this.user: const User.initial(),
|
||||||
this.isLoading: false,
|
this.isLoading: false,
|
||||||
this.isLoaded: false,
|
this.isLoaded: false,
|
||||||
this.error: null,
|
this.error: null,
|
||||||
this.gmapKey,
|
this.gmapKey,
|
||||||
this.firesApiKey,
|
this.firesApiKey,
|
||||||
this.firesApiUrl,
|
this.firesApiUrl,
|
||||||
|
this.serverUrl,
|
||||||
this.fireMapState: const FireMapState.initial()});
|
this.fireMapState: const FireMapState.initial()});
|
||||||
|
|
||||||
AppState copyWith(
|
AppState copyWith(
|
||||||
|
|
@ -55,10 +61,12 @@ class AppState extends Object with _$AppStateSerializerMixin {
|
||||||
String user,
|
String user,
|
||||||
String error,
|
String error,
|
||||||
String gmapKey,
|
String gmapKey,
|
||||||
String firesApiKey,
|
String firesApiKey,
|
||||||
|
String serverUrl,
|
||||||
String firesApiUrl,
|
String firesApiUrl,
|
||||||
List<YourLocation> yourLocations,
|
List<YourLocation> yourLocations,
|
||||||
List<FireNotification> fireNotifications,
|
List<FireNotification> fireNotifications,
|
||||||
|
int fireNotificationsUnread,
|
||||||
FireMapState fireMapState}) {
|
FireMapState fireMapState}) {
|
||||||
return new AppState(
|
return new AppState(
|
||||||
isLoading: isLoading ?? this.isLoading,
|
isLoading: isLoading ?? this.isLoading,
|
||||||
|
|
@ -67,9 +75,12 @@ class AppState extends Object with _$AppStateSerializerMixin {
|
||||||
error: error ?? this.error,
|
error: error ?? this.error,
|
||||||
gmapKey: gmapKey ?? this.gmapKey,
|
gmapKey: gmapKey ?? this.gmapKey,
|
||||||
firesApiKey: firesApiKey ?? this.firesApiKey,
|
firesApiKey: firesApiKey ?? this.firesApiKey,
|
||||||
firesApiUrl: firesApiUrl ?? this.firesApiUrl,
|
firesApiUrl: firesApiUrl ?? this.firesApiUrl,
|
||||||
|
serverUrl: serverUrl ?? this.serverUrl,
|
||||||
yourLocations: yourLocations ?? this.yourLocations,
|
yourLocations: yourLocations ?? this.yourLocations,
|
||||||
fireNotifications: fireNotifications ?? this.fireNotifications,
|
fireNotifications: fireNotifications ?? this.fireNotifications,
|
||||||
|
fireNotificationsUnread:
|
||||||
|
fireNotificationsUnread ?? this.fireNotificationsUnread,
|
||||||
fireMapState: fireMapState ?? this.fireMapState);
|
fireMapState: fireMapState ?? this.fireMapState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,8 +88,8 @@ class AppState extends Object with _$AppStateSerializerMixin {
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppState{\nuser: ${user}\nisLoading: $isLoading\nisLoaded: $isLoaded\napiKey: ${ellipse(
|
return 'AppState{\nuser: ${user}\nisLoading: $isLoading\nisLoaded: $isLoaded\napiKey: ${ellipse(
|
||||||
firesApiKey, 8)}\napiUrl: ${ellipse(
|
firesApiKey, 8)}\napiUrl: ${ellipse(
|
||||||
firesApiUrl, 8)}\nyourLocations count: ${yourLocations
|
firesApiUrl, 8)}\nserverUrl: ${serverUrl}\nfireNotifications: ${fireNotifications}\nyourLocations count: ${yourLocations
|
||||||
.length}\nyourLocations: ${yourLocations}\nfireNotifications: ${fireNotifications}\nfireMapState: $fireMapState}';
|
.length}\nunread notif: ${fireNotificationsUnread}\nyourLocations: ${yourLocations}\nfireMapState: $fireMapState}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,53 @@
|
||||||
import 'package:bson_objectid/bson_objectid.dart';
|
import 'package:bson_objectid/bson_objectid.dart';
|
||||||
|
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:redux/src/store.dart';
|
||||||
|
|
||||||
|
import '../genericMap.dart';
|
||||||
|
import '../objectIdUtils.dart';
|
||||||
|
import '../redux/actions.dart';
|
||||||
|
|
||||||
part 'fireNotification.g.dart';
|
part 'fireNotification.g.dart';
|
||||||
|
|
||||||
_objectIdFromJson(String json) {
|
|
||||||
return new ObjectId.fromHexString(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
_objectIdToJson(ObjectId o) {
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonSerializable(nullable: false)
|
@JsonSerializable(nullable: false)
|
||||||
class FireNotification extends Object with _$FireNotificationSerializerMixin {
|
class FireNotification extends Object with _$FireNotificationSerializerMixin {
|
||||||
@JsonKey(toJson: _objectIdToJson, fromJson: _objectIdFromJson)
|
@JsonKey(toJson: objectIdToJson, fromJson: objectIdFromJson)
|
||||||
ObjectId id;
|
ObjectId id;
|
||||||
final double lat;
|
final double lat;
|
||||||
final double lon;
|
final double lon;
|
||||||
final String description;
|
final String description;
|
||||||
final DateTime when;
|
final DateTime when;
|
||||||
|
final String sealed;
|
||||||
|
@JsonKey(toJson: objectIdToJson, fromJson: objectIdFromJson)
|
||||||
|
final ObjectId subsId;
|
||||||
final bool read;
|
final bool read;
|
||||||
|
|
||||||
factory FireNotification.fromJson(Map<String, dynamic> json) => _$FireNotificationFromJson(json);
|
factory FireNotification.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$FireNotificationFromJson(json);
|
||||||
|
|
||||||
FireNotification({this.id, @required this.lat, @required this.lon, @required this.description, @required this.when, @required this.read}) {
|
FireNotification(
|
||||||
|
{this.id,
|
||||||
|
@required this.lat,
|
||||||
|
@required this.lon,
|
||||||
|
@required this.description,
|
||||||
|
@required this.when,
|
||||||
|
@required this.read,
|
||||||
|
@required this.sealed,
|
||||||
|
@required this.subsId}) {
|
||||||
if (this.id == null) this.id = new ObjectId();
|
if (this.id == null) this.id = new ObjectId();
|
||||||
}
|
}
|
||||||
|
|
||||||
FireNotification copyWith({id, lat, lon, description, read, when}) {
|
FireNotification copyWith(
|
||||||
|
{id, lat, lon, description, read, when, sealed, subsId}) {
|
||||||
return new FireNotification(
|
return new FireNotification(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
lat: lat ?? this.lat,
|
lat: lat ?? this.lat,
|
||||||
lon: lon ?? this.lon,
|
lon: lon ?? this.lon,
|
||||||
read: read ?? this.read,
|
read: read ?? this.read,
|
||||||
description: description ?? this.description,
|
description: description ?? this.description,
|
||||||
|
sealed: sealed ?? this.sealed,
|
||||||
|
subsId: subsId ?? this.subsId,
|
||||||
when: when ?? this.when);
|
when: when ?? this.when);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,16 +58,46 @@ class FireNotification extends Object with _$FireNotificationSerializerMixin {
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
id == other.id &&
|
id == other.id &&
|
||||||
lat == other.lat &&
|
lat == other.lat &&
|
||||||
lon == other.lon &&
|
lon == other.lon &&
|
||||||
read == other.read &&
|
read == other.read &&
|
||||||
description == other.description &&
|
description == other.description &&
|
||||||
|
sealed == other.sealed &&
|
||||||
|
subsId == other.subsId &&
|
||||||
when == other.when;
|
when == other.when;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => id.hashCode ^ lat.hashCode ^ lon.hashCode ^ description.hashCode ^ when.hashCode ^ read.hashCode;
|
int get hashCode =>
|
||||||
|
id.hashCode ^
|
||||||
|
lat.hashCode ^
|
||||||
|
lon.hashCode ^
|
||||||
|
description.hashCode ^
|
||||||
|
when.hashCode ^
|
||||||
|
read.hashCode ^
|
||||||
|
sealed.hashCode ^
|
||||||
|
subsId.hashCode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'FireNotification {id: $id, lat: $lat, lon: $lon, description: $description, when: $when, read: $read}';
|
return 'FireNotification {id: $id, lat: $lat, lon: $lon, when: $when, read: $read, subsId: $subsId, sealed ${ellipse(
|
||||||
|
sealed)}';
|
||||||
|
}
|
||||||
|
|
||||||
|
static final Map<String, Route<Null>> routes = <String, Route<Null>>{};
|
||||||
|
|
||||||
|
Route<Null> getRoute(Store store) {
|
||||||
|
final String routeName = '/fire/${id}';
|
||||||
|
return routes.putIfAbsent(
|
||||||
|
routeName,
|
||||||
|
() => new MaterialPageRoute<Null>(
|
||||||
|
settings: new RouteSettings(name: routeName),
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
store.dispatch(new ShowFireNotificationMapAction(this));
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
new MaterialPageRoute(
|
||||||
|
builder: (context) => new genericMap()));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@ part of 'fireNotification.dart';
|
||||||
|
|
||||||
FireNotification _$FireNotificationFromJson(Map<String, dynamic> json) =>
|
FireNotification _$FireNotificationFromJson(Map<String, dynamic> json) =>
|
||||||
new FireNotification(
|
new FireNotification(
|
||||||
id: _objectIdFromJson(json['id'] as String),
|
id: objectIdFromJson(json['id'] as String),
|
||||||
lat: (json['lat'] as num).toDouble(),
|
lat: (json['lat'] as num).toDouble(),
|
||||||
lon: (json['lon'] as num).toDouble(),
|
lon: (json['lon'] as num).toDouble(),
|
||||||
description: json['description'] as String,
|
description: json['description'] as String,
|
||||||
when: DateTime.parse(json['when'] as String),
|
when: DateTime.parse(json['when'] as String),
|
||||||
read: json['read'] as bool);
|
read: json['read'] as bool,
|
||||||
|
sealed: json['sealed'] as String,
|
||||||
|
subsId: objectIdFromJson(json['subsId'] as String));
|
||||||
|
|
||||||
abstract class _$FireNotificationSerializerMixin {
|
abstract class _$FireNotificationSerializerMixin {
|
||||||
ObjectId get id;
|
ObjectId get id;
|
||||||
|
|
@ -23,6 +25,8 @@ abstract class _$FireNotificationSerializerMixin {
|
||||||
double get lon;
|
double get lon;
|
||||||
String get description;
|
String get description;
|
||||||
DateTime get when;
|
DateTime get when;
|
||||||
|
String get sealed;
|
||||||
|
ObjectId get subsId;
|
||||||
bool get read;
|
bool get read;
|
||||||
Map<String, dynamic> toJson() => new _$FireNotificationJsonMapWrapper(this);
|
Map<String, dynamic> toJson() => new _$FireNotificationJsonMapWrapper(this);
|
||||||
}
|
}
|
||||||
|
|
@ -32,15 +36,23 @@ class _$FireNotificationJsonMapWrapper extends $JsonMapWrapper {
|
||||||
_$FireNotificationJsonMapWrapper(this._v);
|
_$FireNotificationJsonMapWrapper(this._v);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<String> get keys =>
|
Iterable<String> get keys => const [
|
||||||
const ['id', 'lat', 'lon', 'description', 'when', 'read'];
|
'id',
|
||||||
|
'lat',
|
||||||
|
'lon',
|
||||||
|
'description',
|
||||||
|
'when',
|
||||||
|
'sealed',
|
||||||
|
'subsId',
|
||||||
|
'read'
|
||||||
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
dynamic operator [](Object key) {
|
dynamic operator [](Object key) {
|
||||||
if (key is String) {
|
if (key is String) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'id':
|
case 'id':
|
||||||
return _objectIdToJson(_v.id);
|
return objectIdToJson(_v.id);
|
||||||
case 'lat':
|
case 'lat':
|
||||||
return _v.lat;
|
return _v.lat;
|
||||||
case 'lon':
|
case 'lon':
|
||||||
|
|
@ -49,6 +61,10 @@ class _$FireNotificationJsonMapWrapper extends $JsonMapWrapper {
|
||||||
return _v.description;
|
return _v.description;
|
||||||
case 'when':
|
case 'when':
|
||||||
return _v.when.toIso8601String();
|
return _v.when.toIso8601String();
|
||||||
|
case 'sealed':
|
||||||
|
return _v.sealed;
|
||||||
|
case 'subsId':
|
||||||
|
return objectIdToJson(_v.subsId);
|
||||||
case 'read':
|
case 'read':
|
||||||
return _v.read;
|
return _v.read;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
import 'package:bson_objectid/bson_objectid.dart';
|
import 'package:bson_objectid/bson_objectid.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:fires_flutter/objectIdUtils.dart';
|
||||||
|
|
||||||
part 'yourLocation.g.dart';
|
part 'yourLocation.g.dart';
|
||||||
|
|
||||||
_objectIdFromJson(String json) {
|
|
||||||
return new ObjectId.fromHexString(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
_objectIdToJson(ObjectId o) {
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonSerializable(nullable: false)
|
@JsonSerializable(nullable: false)
|
||||||
class YourLocation extends Object with _$YourLocationSerializerMixin {
|
class YourLocation extends Object with _$YourLocationSerializerMixin {
|
||||||
@JsonKey(toJson: _objectIdToJson, fromJson: _objectIdFromJson)
|
@JsonKey(toJson: objectIdToJson, fromJson: objectIdFromJson)
|
||||||
ObjectId id;
|
ObjectId id;
|
||||||
final double lat;
|
final double lat;
|
||||||
final double lon;
|
final double lon;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ part of 'yourLocation.dart';
|
||||||
|
|
||||||
YourLocation _$YourLocationFromJson(Map<String, dynamic> json) =>
|
YourLocation _$YourLocationFromJson(Map<String, dynamic> json) =>
|
||||||
new YourLocation(
|
new YourLocation(
|
||||||
id: _objectIdFromJson(json['id'] as String),
|
id: objectIdFromJson(json['id'] as String),
|
||||||
lat: (json['lat'] as num).toDouble(),
|
lat: (json['lat'] as num).toDouble(),
|
||||||
lon: (json['lon'] as num).toDouble(),
|
lon: (json['lon'] as num).toDouble(),
|
||||||
description: json['description'] as String,
|
description: json['description'] as String,
|
||||||
|
|
@ -40,7 +40,7 @@ class _$YourLocationJsonMapWrapper extends $JsonMapWrapper {
|
||||||
if (key is String) {
|
if (key is String) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'id':
|
case 'id':
|
||||||
return _objectIdToJson(_v.id);
|
return objectIdToJson(_v.id);
|
||||||
case 'lat':
|
case 'lat':
|
||||||
return _v.lat;
|
return _v.lat;
|
||||||
case 'lon':
|
case 'lon':
|
||||||
|
|
|
||||||
9
lib/objectIdUtils.dart
Normal file
9
lib/objectIdUtils.dart
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import 'package:bson_objectid/bson_objectid.dart';
|
||||||
|
|
||||||
|
objectIdFromJson(String json) {
|
||||||
|
return new ObjectId.fromHexString(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
objectIdToJson(ObjectId o) {
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,7 @@ class OnUserLangAction extends AppActions {
|
||||||
|
|
||||||
class FetchFireNotificationsSucceededAction extends AppActions {
|
class FetchFireNotificationsSucceededAction extends AppActions {
|
||||||
final List<FireNotification> fetchedFireNotifications;
|
final List<FireNotification> fetchedFireNotifications;
|
||||||
|
final int unreadCount;
|
||||||
|
|
||||||
FetchFireNotificationsSucceededAction(this.fetchedFireNotifications);
|
FetchFireNotificationsSucceededAction(this.fetchedFireNotifications, this.unreadCount);
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,16 @@ AppState appReducer(AppState state, action) {
|
||||||
return state.copyWith(yourLocations: action.fetchedYourLocations);
|
return state.copyWith(yourLocations: action.fetchedYourLocations);
|
||||||
}
|
}
|
||||||
if (action is FetchFireNotificationsSucceededAction) {
|
if (action is FetchFireNotificationsSucceededAction) {
|
||||||
return state.copyWith(fireNotifications: action.fetchedFireNotifications);
|
return state.copyWith(fireNotifications: action.fetchedFireNotifications,
|
||||||
|
fireNotificationsUnread: action.unreadCount);
|
||||||
}
|
}
|
||||||
|
if (action is AddedFireNotificationAction)
|
||||||
|
return state.copyWith(
|
||||||
|
fireNotificationsUnread: state.fireNotificationsUnread + 1);
|
||||||
|
|
||||||
|
if (action is ReadedFireNotificationAction)
|
||||||
|
return state.copyWith(
|
||||||
|
fireNotificationsUnread: state.fireNotificationsUnread - 1);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:bson_objectid/bson_objectid.dart';
|
import 'package:bson_objectid/bson_objectid.dart';
|
||||||
import 'package:fires_flutter/models/yourLocation.dart';
|
import 'package:fires_flutter/models/yourLocation.dart';
|
||||||
|
import 'package:fires_flutter/models/fireNotification.dart';
|
||||||
import 'package:flutter_simple_dependency_injection/injector.dart';
|
import 'package:flutter_simple_dependency_injection/injector.dart';
|
||||||
import 'package:just_debounce_it/just_debounce_it.dart';
|
import 'package:just_debounce_it/just_debounce_it.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
|
|
@ -161,8 +162,12 @@ void fetchDataMiddleware(Store<AppState> store, action, NextDispatcher next) {
|
||||||
|
|
||||||
if (action is FetchFireNotificationsAction) {
|
if (action is FetchFireNotificationsAction) {
|
||||||
loadFireNotifications().then((fireNotifications) {
|
loadFireNotifications().then((fireNotifications) {
|
||||||
|
int unread = 0;
|
||||||
|
for (FireNotification notif in fireNotifications) {
|
||||||
|
if (!notif.read) { unread++; }
|
||||||
|
}
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
new FetchFireNotificationsSucceededAction(fireNotifications));
|
new FetchFireNotificationsSucceededAction(fireNotifications, unread));
|
||||||
persistFireNotifications(fireNotifications);
|
persistFireNotifications(fireNotifications);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ FireMapState _showYourLocationMap(
|
||||||
status: action.loc.subscribed
|
status: action.loc.subscribed
|
||||||
? FireMapStatus.unsubscribe
|
? FireMapStatus.unsubscribe
|
||||||
: FireMapStatus.view,
|
: FireMapStatus.view,
|
||||||
yourLocation: action.loc);
|
yourLocation: action.loc, fireNotication: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
FireMapState _showFireNotificationMap(
|
FireMapState _showFireNotificationMap(
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ final fireNotificationReducer = combineReducers<List<FireNotification>>([
|
||||||
|
|
||||||
List<FireNotification> _receivedFireNotification(
|
List<FireNotification> _receivedFireNotification(
|
||||||
List<FireNotification> notifications, AddedFireNotificationAction action) {
|
List<FireNotification> notifications, AddedFireNotificationAction action) {
|
||||||
return new List.from(notifications)..add(action.notif);
|
return new List.from(notifications)..insert(0, action.notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FireNotification> _deletedFireNotification(
|
List<FireNotification> _deletedFireNotification(
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,28 @@
|
||||||
import '../models/appState.dart';
|
import '../models/appState.dart';
|
||||||
|
import 'appReducer.dart';
|
||||||
import 'errorReducer.dart';
|
import 'errorReducer.dart';
|
||||||
import 'fireMapReducer.dart';
|
import 'fireMapReducer.dart';
|
||||||
|
import 'fireNotificationReducer.dart';
|
||||||
import 'loadedReducer.dart';
|
import 'loadedReducer.dart';
|
||||||
import 'loadingReducer.dart';
|
import 'loadingReducer.dart';
|
||||||
import 'userReducer.dart';
|
import 'userReducer.dart';
|
||||||
import 'yourLocationsReducer.dart';
|
import 'yourLocationsReducer.dart';
|
||||||
import 'actions.dart';
|
|
||||||
import 'appReducer.dart';
|
|
||||||
import 'fireNotificationReducer.dart';
|
|
||||||
|
|
||||||
// We create the State reducer by combining many smaller reducers into one!
|
// We create the State reducer by combining many smaller reducers into one!
|
||||||
AppState appStateReducer(AppState prevState, action) {
|
AppState appStateReducer(AppState prevState, action) {
|
||||||
var state = prevState;
|
var state = appReducer(prevState, action);
|
||||||
if (action is AppActions)
|
|
||||||
state = appReducer(prevState, action);
|
|
||||||
return AppState(
|
return AppState(
|
||||||
yourLocations: yourLocationsReducer(state.yourLocations, action),
|
yourLocations: yourLocationsReducer(state.yourLocations, action),
|
||||||
fireNotifications: fireNotificationReducer(state.fireNotifications, action),
|
fireNotifications:
|
||||||
|
fireNotificationReducer(state.fireNotifications, action),
|
||||||
|
fireNotificationsUnread: state.fireNotificationsUnread,
|
||||||
user: userReducer(state.user, action),
|
user: userReducer(state.user, action),
|
||||||
isLoading: loadingReducer(state.isLoading, action),
|
isLoading: loadingReducer(state.isLoading, action),
|
||||||
isLoaded: loadedReducer(state.isLoaded, action),
|
isLoaded: loadedReducer(state.isLoaded, action),
|
||||||
error: errorReducer(state.error, action),
|
error: errorReducer(state.error, action),
|
||||||
fireMapState: fireMapReducer(state.fireMapState, action),
|
fireMapState: fireMapReducer(state.fireMapState, action),
|
||||||
firesApiKey: state.firesApiKey,
|
firesApiKey: state.firesApiKey,
|
||||||
firesApiUrl: state.firesApiUrl,
|
firesApiUrl: state.firesApiUrl,
|
||||||
gmapKey: state.gmapKey
|
serverUrl: state.serverUrl,
|
||||||
);
|
gmapKey: state.gmapKey);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ dependencies:
|
||||||
# https://pub.dartlang.org/packages/padder
|
# https://pub.dartlang.org/packages/padder
|
||||||
padder: "^1.0.1"
|
padder: "^1.0.1"
|
||||||
flutter_fab_dialer: "^0.0.5"
|
flutter_fab_dialer: "^0.0.5"
|
||||||
|
badge: "^0.0.2"
|
||||||
|
flutter_spinkit: "^1.0.0"
|
||||||
|
|
||||||
# firebase
|
# firebase
|
||||||
firebase_messaging: "^1.0.4"
|
firebase_messaging: "^1.0.4"
|
||||||
|
|
|
||||||
|
|
@ -59,5 +59,7 @@
|
||||||
"fireNotificationsDescription": "Here you will receive fire notifications in locations you are subscribed to",
|
"fireNotificationsDescription": "Here you will receive fire notifications in locations you are subscribed to",
|
||||||
"areYouSureTitle": "Are you sure?",
|
"areYouSureTitle": "Are you sure?",
|
||||||
"deleteAllFireNotificationsAlertDescription": "This will remove all your fire notifications",
|
"deleteAllFireNotificationsAlertDescription": "This will remove all your fire notifications",
|
||||||
"DELETE": "DELETE"
|
"DELETE": "DELETE",
|
||||||
|
"SHOW": "SHOW",
|
||||||
|
"CLOSE": "CLOSE"
|
||||||
}
|
}
|
||||||
|
|
@ -59,5 +59,7 @@
|
||||||
"fireNotificationsDescription": "Aquí recibirás las notificaciones de fuegos en los lugares a los que te subscribas",
|
"fireNotificationsDescription": "Aquí recibirás las notificaciones de fuegos en los lugares a los que te subscribas",
|
||||||
"areYouSureTitle": "¿Seguro?",
|
"areYouSureTitle": "¿Seguro?",
|
||||||
"deleteAllFireNotificationsAlertDescription": "Esto borrará todas las notificaciones de fuegos",
|
"deleteAllFireNotificationsAlertDescription": "Esto borrará todas las notificaciones de fuegos",
|
||||||
"DELETE": "BORRAR"
|
"DELETE": "BORRAR",
|
||||||
|
"SHOW": "MOSTRAR",
|
||||||
|
"CLOSE": "CERRAR"
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue