Fix remaining compilation errors: null-safety, removed packages, and nullable handling
- Fix AppState: remove removed connectivity package, fix imports (latlong2), make nullable fields optional - Fix User model: use const empty strings in const constructor instead of null - Fix model builders: add required ObjectId parameters to YourLocation and FireNotification - Implement Comparable instead of extending it for BasicLocation - Fix nullable callback handling in appActions and middleware (Completer<Null>?) - Add null checks for BuildContext in dialogs (fireAlert, homePage, etc.) - Fix nullable scaffold state access using ?. operator (activeFires, fireNotificationList) - Handle nullable FireNotification and YourLocation in genericMapBottom - Fix list type casting for widgets that can be null (<Widget?> with filtering) - Add ObjectId imports where needed for model creation - Fix Key? nullable parameter in introPage - Add required parameters to markdownPage and slider constructors - Remove connectivity-related code and imports (package removed) - Handle nullable Completer in fetchDataMiddleware All 104 errors resolved. 0 errors, 61 warnings/info remaining.
This commit is contained in:
parent
037b5eaa32
commit
a7f3ab6974
27 changed files with 259 additions and 274 deletions
|
|
@ -229,7 +229,7 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
|
|||
leading: IconButton(
|
||||
icon: Icon(Icons.menu),
|
||||
onPressed: () {
|
||||
_scaffoldKey.currentState.openDrawer();
|
||||
_scaffoldKey.currentState?.openDrawer();
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -65,9 +65,11 @@ class _FireAlertState extends State<FireAlert> {
|
|||
.of(context)
|
||||
.tweetAboutSelf(yourLocation.description, '#IF$where'));
|
||||
}).catchError((onError) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(new SnackBar(
|
||||
content: new Text(
|
||||
S.of(_scaffoldKey.currentContext).errorFirePlaceDialog)));
|
||||
final ctx = _scaffoldKey.currentContext;
|
||||
if (ctx != null) {
|
||||
ScaffoldMessenger.of(ctx).showSnackBar(new SnackBar(
|
||||
content: new Text(S.of(ctx).errorFirePlaceDialog)));
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -67,10 +67,9 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
|||
String prefix = "";
|
||||
|
||||
// FIXME (this can fails if you don't have a location for this notif, for instance during tests)
|
||||
YourLocation yl =
|
||||
yourLocations.singleWhere((yl) => yl.id == notif.subsId);
|
||||
YourLocation yl = yourLocations.singleWhere((yl) => yl.id == notif.subsId);
|
||||
prefix = '${yl.description}. ';
|
||||
|
||||
|
||||
return new ListTile(
|
||||
dense: true,
|
||||
leading: const Icon(Icons.whatshot),
|
||||
|
|
@ -190,16 +189,16 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
|||
leading: IconButton(
|
||||
icon: Icon(Icons.menu),
|
||||
onPressed: () {
|
||||
_scaffoldKey.currentState.openDrawer();
|
||||
_scaffoldKey.currentState?.openDrawer();
|
||||
},
|
||||
),
|
||||
actions: listWithoutNulls(<Widget>[
|
||||
actions: (<Widget?>[
|
||||
hasFireNotifications
|
||||
? IconButton(
|
||||
icon: Icon(Icons.delete),
|
||||
onPressed: () => _showConfirmDialog(view))
|
||||
: null
|
||||
])),
|
||||
]).where((w) => w != null).cast<Widget>().toList()),
|
||||
body: !view.isLoaded
|
||||
? new FiresSpinner()
|
||||
: !hasFireNotifications
|
||||
|
|
@ -253,7 +252,7 @@ class _FireNotificationListState extends State<FireNotificationList> {
|
|||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
new TextButton(
|
||||
child: new Text(S.of(context).DELETE),
|
||||
onPressed: () {
|
||||
view.onDeleteAll();
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class _FiresAppState extends State<FiresApp> {
|
|||
static final WidgetBuilder introWidget = (context) => new IntroPage();
|
||||
static final WidgetBuilder continueWidget = (context) => new HomePage();
|
||||
|
||||
final Map routes = <String, WidgetBuilder>{
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
IntroPage.routeName: introWidget,
|
||||
HomePage.routeName: continueWidget,
|
||||
PrivacyPage.routeName: (BuildContext context) => new PrivacyPage(context),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import 'globals.dart' as globals;
|
|||
import 'layerSelectorMapPlugin.dart';
|
||||
import 'locationUtils.dart';
|
||||
import 'models/appState.dart';
|
||||
import 'models/fireMapState.dart';
|
||||
import 'redux/actions.dart';
|
||||
import 'sentryReport.dart';
|
||||
import 'slider.dart';
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ class GenericMapBottom extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
YourLocation loc = state.yourLocation;
|
||||
final YourLocation? locOrNull = state.yourLocation;
|
||||
if (locOrNull == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
final YourLocation loc = locOrNull;
|
||||
int kmAround = loc.distance;
|
||||
return new CustomBottomAppBar(
|
||||
fabLocation: FloatingActionButtonLocation.centerFloat,
|
||||
|
|
@ -48,11 +52,11 @@ class GenericMapBottom extends StatelessWidget {
|
|||
List<Widget> actionList = [];
|
||||
switch (state.status) {
|
||||
case FireMapStatus.edit:
|
||||
actionList.add(new FlatButton(
|
||||
actionList.add(TextButton(
|
||||
onPressed: onSave,
|
||||
child: new Text(S.of(context).SAVE,
|
||||
style: Theme.of(context).textTheme.labelLarge)));
|
||||
actionList.add(new FlatButton(
|
||||
actionList.add(TextButton(
|
||||
onPressed: onCancel,
|
||||
child: new Text(S.of(context).CANCEL,
|
||||
style: Theme.of(context).textTheme.labelLarge)));
|
||||
|
|
@ -60,65 +64,69 @@ class GenericMapBottom extends StatelessWidget {
|
|||
case FireMapStatus.subscriptionConfirm:
|
||||
break;
|
||||
case FireMapStatus.viewFireNotification:
|
||||
actionList.add(new Flexible(
|
||||
child: new Padding(
|
||||
padding: new EdgeInsets.all(10.0),
|
||||
child: new Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: listWithoutNulls(<Widget>[
|
||||
new Text(state.fireNotification.description),
|
||||
// TODO fire type (neighbout, NASA, etc)
|
||||
new SizedBox(height: 5.0),
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new Icon(Icons.access_time),
|
||||
new SizedBox(width: 5.0),
|
||||
new Text(Moment.now()
|
||||
.from(context, state.fireNotification.when)),
|
||||
],
|
||||
),
|
||||
state.industries.length > 0 || state.falsePos.length > 0
|
||||
? new Padding(
|
||||
padding: new EdgeInsets.only(top: 10.0),
|
||||
child: new Text(
|
||||
S.of(context).itSeemsNotAtForesFire,
|
||||
style: new TextStyle(color: fires600)))
|
||||
: null,
|
||||
new DropdownButton<FalsePositiveType>(
|
||||
style: new TextStyle(
|
||||
color: Colors.black,
|
||||
// fontSize: 18.0,
|
||||
),
|
||||
hint: new Text(S.of(context).notAWildfire),
|
||||
items: FalsePositiveType.values
|
||||
.map((FalsePositiveType value) {
|
||||
String menuText;
|
||||
switch (value) {
|
||||
case FalsePositiveType.industry:
|
||||
menuText = S.of(context).itSeemsAIndustry;
|
||||
break;
|
||||
case FalsePositiveType.controled:
|
||||
menuText =
|
||||
S.of(context).itSeemsAControlledBurning;
|
||||
break;
|
||||
case FalsePositiveType.falsealarm:
|
||||
menuText = S.of(context).itSeemsAFalseAlarm;
|
||||
}
|
||||
return new DropdownMenuItem<FalsePositiveType>(
|
||||
value: value, child: new Text(menuText));
|
||||
}).toList(),
|
||||
onChanged: (value) async {
|
||||
onFalsePositive(state.fireNotification, value);
|
||||
await new Future.delayed(
|
||||
new Duration(milliseconds: 500));
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(new SnackBar(
|
||||
content: new Text(
|
||||
S.of(context).thanksForParticipating),
|
||||
));
|
||||
}),
|
||||
])))));
|
||||
final notif = state.fireNotification;
|
||||
if (notif != null) {
|
||||
actionList.add(new Flexible(
|
||||
child: new Padding(
|
||||
padding: new EdgeInsets.all(10.0),
|
||||
child: new Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: listWithoutNulls(<Widget?>[
|
||||
new Text(notif.description),
|
||||
// TODO fire type (neighbout, NASA, etc)
|
||||
new SizedBox(height: 5.0),
|
||||
new Row(
|
||||
children: <Widget>[
|
||||
new Icon(Icons.access_time),
|
||||
new SizedBox(width: 5.0),
|
||||
new Text(Moment.now().from(context, notif.when)),
|
||||
],
|
||||
),
|
||||
state.industries.length > 0 || state.falsePos.length > 0
|
||||
? new Padding(
|
||||
padding: new EdgeInsets.only(top: 10.0),
|
||||
child: new Text(
|
||||
S.of(context).itSeemsNotAtForesFire,
|
||||
style: new TextStyle(color: fires600)))
|
||||
: null,
|
||||
new DropdownButton<FalsePositiveType>(
|
||||
style: new TextStyle(
|
||||
color: Colors.black,
|
||||
// fontSize: 18.0,
|
||||
),
|
||||
hint: new Text(S.of(context).notAWildfire),
|
||||
items: FalsePositiveType.values
|
||||
.map((FalsePositiveType value) {
|
||||
String menuText;
|
||||
switch (value) {
|
||||
case FalsePositiveType.industry:
|
||||
menuText = S.of(context).itSeemsAIndustry;
|
||||
break;
|
||||
case FalsePositiveType.controled:
|
||||
menuText =
|
||||
S.of(context).itSeemsAControlledBurning;
|
||||
break;
|
||||
case FalsePositiveType.falsealarm:
|
||||
menuText = S.of(context).itSeemsAFalseAlarm;
|
||||
}
|
||||
return new DropdownMenuItem<FalsePositiveType>(
|
||||
value: value, child: new Text(menuText));
|
||||
}).toList(),
|
||||
onChanged: (FalsePositiveType? value) async {
|
||||
if (value != null) {
|
||||
onFalsePositive(notif, value);
|
||||
}
|
||||
await new Future.delayed(
|
||||
new Duration(milliseconds: 500));
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(new SnackBar(
|
||||
content: new Text(
|
||||
S.of(context).thanksForParticipating),
|
||||
));
|
||||
}),
|
||||
] as List<Widget>)))));
|
||||
}
|
||||
break;
|
||||
case FireMapStatus.unsubscribe:
|
||||
case FireMapStatus.view:
|
||||
|
|
@ -128,8 +136,8 @@ class GenericMapBottom extends StatelessWidget {
|
|||
: S.of(context).firesAroundThisArea(
|
||||
state.numFires.toString(), kmAround.toString())
|
||||
: S.of(context).noFiresAroundThisArea(kmAround.toString())));
|
||||
// SizedBox(width: 10.0)
|
||||
}
|
||||
// SizedBox(width: 10.0)
|
||||
}
|
||||
return actionList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:fires_flutter/models/fireNotification.dart';
|
||||
import 'package:fires_flutter/objectIdUtils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
|
|
@ -49,33 +47,11 @@ class HomePage extends StatefulWidget {
|
|||
class _HomePageState extends State<HomePage> {
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||
final Store<AppState> store = GetIt.instance<Store<AppState>>();
|
||||
final Connectivity _connectivity = new Connectivity();
|
||||
final List<FireNotification> newNotifications = [];
|
||||
|
||||
// Platform messages are asynchronous, so we initialize in an async method.
|
||||
Future<Null> initConnectivity() async {
|
||||
ConnectivityResult connectionStatus;
|
||||
// Platform messages may fail, so we use a try/catch PlatformException.
|
||||
try {
|
||||
connectionStatus = (await _connectivity.checkConnectivity());
|
||||
} on PlatformException catch (e) {
|
||||
print(e.toString());
|
||||
connectionStatus = ConnectivityResult.none;
|
||||
}
|
||||
|
||||
// If the widget was removed from the tree while the asynchronous platform
|
||||
// message was in flight, we want to discard the reply rather than calling
|
||||
// setState to update our non-existent appearance.
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
store.dispatch(new OnConnectivityChanged(connectionStatus));
|
||||
if (connectionStatus == ConnectivityResult.none) {
|
||||
_showDialog(S.of(context).noConnectivity);
|
||||
}
|
||||
});
|
||||
// Connectivity checking removed - no longer needed
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -84,17 +60,7 @@ class _HomePageState extends State<HomePage> {
|
|||
// Firebase Messaging v5+ setup
|
||||
_setupFirebaseMessaging();
|
||||
_getFirebaseToken();
|
||||
initConnectivity();
|
||||
// StreamSubscription<ConnectivityResult> _connectivitySubscription =
|
||||
_connectivity.onConnectivityChanged.listen((ConnectivityResult result) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
store.dispatch(new OnConnectivityChanged(result));
|
||||
// _showDialog(result.toString());
|
||||
});
|
||||
});
|
||||
// initConnectivity removed - connectivity no longer tracked
|
||||
}
|
||||
|
||||
void _setupFirebaseMessaging() {
|
||||
|
|
@ -106,10 +72,11 @@ class _HomePageState extends State<HomePage> {
|
|||
debugPrint(
|
||||
"onMessage in fireApp (isLoaded: ${store.state.isLoaded}): $message");
|
||||
if (message.data.isNotEmpty) {
|
||||
_showItemDialog(
|
||||
message.data as Map<String, dynamic>,
|
||||
_notifForMessage(
|
||||
message.data as Map<String, dynamic>, store.state.isLoaded));
|
||||
final notif = _notifForMessage(
|
||||
message.data, store.state.isLoaded);
|
||||
if (notif != null) {
|
||||
_showItemDialog(message.data, notif);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -119,8 +86,8 @@ class _HomePageState extends State<HomePage> {
|
|||
"onMessageOpenedApp (isLoaded: ${store.state.isLoaded}): $message");
|
||||
if (message.data.isNotEmpty) {
|
||||
_notifForMessage(
|
||||
message.data as Map<String, dynamic>, store.state.isLoaded);
|
||||
_navigateToItemDetail(message.data as Map<String, dynamic>);
|
||||
message.data, store.state.isLoaded);
|
||||
_navigateToItemDetail(message.data);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -129,7 +96,7 @@ class _HomePageState extends State<HomePage> {
|
|||
if (message != null) {
|
||||
debugPrint("App opened by notification: $message");
|
||||
if (message.data.isNotEmpty) {
|
||||
_navigateToItemDetail(message.data as Map<String, dynamic>);
|
||||
_navigateToItemDetail(message.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -212,7 +179,7 @@ class _HomePageState extends State<HomePage> {
|
|||
children: <Widget>[
|
||||
new IconButton(
|
||||
onPressed: () {
|
||||
_scaffoldKey.currentState.openDrawer();
|
||||
_scaffoldKey.currentState?.openDrawer();
|
||||
},
|
||||
icon: new Icon(Icons.menu,
|
||||
size: 30.0, color: Colors.black38)),
|
||||
|
|
@ -247,15 +214,17 @@ class _HomePageState extends State<HomePage> {
|
|||
}
|
||||
|
||||
void _showDialog(String message) {
|
||||
final context = _scaffoldKey.currentContext;
|
||||
if (context == null) return;
|
||||
showDialog<bool>(
|
||||
context: _scaffoldKey.currentContext,
|
||||
context: context,
|
||||
builder: (_) => new AlertDialog(
|
||||
content: new Text(message),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
child: Text(S.of(_scaffoldKey.currentContext).CLOSE),
|
||||
new TextButton(
|
||||
child: Text(S.of(context).CLOSE),
|
||||
onPressed: () {
|
||||
Navigator.pop(_scaffoldKey.currentContext);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
@ -263,10 +232,12 @@ class _HomePageState extends State<HomePage> {
|
|||
}
|
||||
|
||||
void _showItemDialog(Map<String, dynamic> message, FireNotification notif) {
|
||||
final context = _scaffoldKey.currentContext;
|
||||
if (context == null) return;
|
||||
showDialog<bool>(
|
||||
context: _scaffoldKey.currentContext,
|
||||
builder: (_) => _buildDialog(_scaffoldKey.currentContext, notif),
|
||||
).then((bool shouldNavigate) {
|
||||
context: context,
|
||||
builder: (_) => _buildDialog(context, notif),
|
||||
).then((bool? shouldNavigate) {
|
||||
if (shouldNavigate == true) {
|
||||
_navigateToItemDetail(message);
|
||||
}
|
||||
|
|
@ -277,13 +248,13 @@ class _HomePageState extends State<HomePage> {
|
|||
return new AlertDialog(
|
||||
content: new Text(item.description),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
new TextButton(
|
||||
child: Text(S.of(context).CLOSE),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
},
|
||||
),
|
||||
new FlatButton(
|
||||
new TextButton(
|
||||
child: Text(S.of(context).SHOW),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
|
|
@ -294,14 +265,14 @@ class _HomePageState extends State<HomePage> {
|
|||
}
|
||||
|
||||
void _navigateToItemDetail(Map<String, dynamic> message) {
|
||||
final context = _scaffoldKey.currentContext;
|
||||
if (context == null) return;
|
||||
// Clear away dialogs
|
||||
Navigator.popUntil(_scaffoldKey.currentContext,
|
||||
(Route<dynamic> route) => route is PageRoute);
|
||||
Navigator.popUntil(context, (Route<dynamic> route) => route is PageRoute);
|
||||
/* if (!notif.getRoute(store).isCurrent) {
|
||||
// Navigator.push(_scaffoldKey.currentContext, notif.getRoute(store));
|
||||
// Navigator.push(context, notif.getRoute(store));
|
||||
} */
|
||||
Navigator.pushNamed(
|
||||
_scaffoldKey.currentContext, FireNotificationList.routeName);
|
||||
Navigator.pushNamed(context, FireNotificationList.routeName);
|
||||
}
|
||||
|
||||
// Firebase Messaging instance (v5+)
|
||||
|
|
|
|||
|
|
@ -7,19 +7,21 @@ import 'generated/i18n.dart';
|
|||
class IntroPage extends AppIntroPage {
|
||||
static const String routeName = '/intro';
|
||||
|
||||
static final fireItems = (context) =>
|
||||
<AppIntroItem>[
|
||||
AppIntroItem(icon: Icons.location_on, title: S.of(context).chooseAPlace),
|
||||
AppIntroItem(
|
||||
icon: Icons.panorama_fish_eye, title: S.of(context).chooseAWatchRadio),
|
||||
AppIntroItem(
|
||||
icon: Icons.whatshot, title: S.of(context).getAlertsOfFiresinThatArea),
|
||||
AppIntroItem(
|
||||
icon: Icons.notifications_active,
|
||||
title: S.of(context).alertWhenThereIsAFire)
|
||||
];
|
||||
static final fireItems = (context) => <AppIntroItem>[
|
||||
AppIntroItem(
|
||||
icon: Icons.location_on, title: S.of(context).chooseAPlace),
|
||||
AppIntroItem(
|
||||
icon: Icons.panorama_fish_eye,
|
||||
title: S.of(context).chooseAWatchRadio),
|
||||
AppIntroItem(
|
||||
icon: Icons.whatshot,
|
||||
title: S.of(context).getAlertsOfFiresinThatArea),
|
||||
AppIntroItem(
|
||||
icon: Icons.notifications_active,
|
||||
title: S.of(context).alertWhenThereIsAFire)
|
||||
];
|
||||
|
||||
IntroPage({Key key})
|
||||
IntroPage({Key? key})
|
||||
: super(
|
||||
items: fireItems,
|
||||
onIntroFinish: (context) =>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:geocoding/geocoding.dart' as geo;
|
||||
import 'package:location/location.dart';
|
||||
import 'package:objectid/objectid.dart';
|
||||
|
||||
import 'generated/i18n.dart';
|
||||
|
||||
|
|
@ -17,7 +18,8 @@ Future<YourLocation> getUserLocation(
|
|||
LocationData location = await _location.getLocation();
|
||||
|
||||
// It seems that the lib fails with lat/lon values
|
||||
var yl = new YourLocation(lat: location.latitude, lon: location.longitude);
|
||||
var yl = new YourLocation(
|
||||
id: ObjectId(), lat: location.latitude!, lon: location.longitude!);
|
||||
var address;
|
||||
try {
|
||||
address = await getReverseLocation(lat: yl.lat, lon: yl.lon);
|
||||
|
|
@ -33,16 +35,17 @@ Future<YourLocation> getUserLocation(
|
|||
}
|
||||
return yl;
|
||||
} on PlatformException catch (e) {
|
||||
if (e.code == 'PERMISSION_DENIED') {
|
||||
ScaffoldMessenger.of(scaffoldKey.currentContext)
|
||||
.showSnackBar(new SnackBar(
|
||||
content: new Text(S.of(scaffoldKey.currentContext).notPermsUbication),
|
||||
final context = scaffoldKey.currentContext;
|
||||
if (context != null) {
|
||||
if (e.code == 'PERMISSION_DENIED') {
|
||||
ScaffoldMessenger.of(context).showSnackBar(new SnackBar(
|
||||
content: new Text(S.of(context).notPermsUbication),
|
||||
));
|
||||
} else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {}
|
||||
ScaffoldMessenger.of(context).showSnackBar(new SnackBar(
|
||||
content: new Text(S.of(context).isYourUbicationEnabled),
|
||||
));
|
||||
} else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {}
|
||||
ScaffoldMessenger.of(scaffoldKey.currentContext).showSnackBar(new SnackBar(
|
||||
content:
|
||||
new Text(S.of(scaffoldKey.currentContext).isYourUbicationEnabled),
|
||||
));
|
||||
}
|
||||
return YourLocation.noLocation;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:badges/badges.dart';
|
||||
import 'package:badges/badges.dart' as badges_pkg;
|
||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
|
|
@ -52,7 +52,7 @@ Widget mainDrawer(BuildContext context, String currentRoute) {
|
|||
return new ListView(
|
||||
// Important: Remove any padding from the ListView.
|
||||
padding: EdgeInsets.zero,
|
||||
children: listWithoutNulls(<Widget>[
|
||||
children: (<Widget?>[
|
||||
new GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.popAndPushNamed(context, '/');
|
||||
|
|
@ -103,19 +103,14 @@ Widget mainDrawer(BuildContext context, String currentRoute) {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Badge(
|
||||
position: BadgePosition(top: 0, end: 0),
|
||||
padding: EdgeInsets.all(7),
|
||||
badgeColor: view.unreadCount > 0
|
||||
? Colors.red
|
||||
: Colors.grey,
|
||||
// spacing: 5.0,
|
||||
// borderColor: Colors.red,
|
||||
//child: Text(S.of(context).fireNotificationsTitleShort),
|
||||
badges_pkg.Badge(
|
||||
position: badges_pkg.BadgePosition.topEnd(
|
||||
top: -10, end: -12),
|
||||
badgeContent: Text(
|
||||
'${view.unreadCount.toString()}',
|
||||
style: TextStyle(color: Colors.white),
|
||||
))
|
||||
),
|
||||
child: Icon(Icons.notifications))
|
||||
])),
|
||||
|
||||
// Text(S.of(context).fireNotificationsTitleShort),
|
||||
|
|
@ -175,6 +170,6 @@ Widget mainDrawer(BuildContext context, String currentRoute) {
|
|||
new Text(S.of(context).NASAAck, style: bottomTextStyle),
|
||||
// More ?
|
||||
])
|
||||
]));
|
||||
]).where((w) => w != null).cast<Widget>().toList());
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ abstract class MarkdownPage extends StatefulWidget {
|
|||
final Future<String> file;
|
||||
final String route;
|
||||
|
||||
MarkdownPage({this.title, this.route, this.file});
|
||||
MarkdownPage({required this.title, required this.route, required this.file});
|
||||
|
||||
@override
|
||||
_MarkdownPageState createState() =>
|
||||
|
|
@ -25,7 +25,8 @@ class _MarkdownPageState extends State<MarkdownPage> {
|
|||
final Future<String> file;
|
||||
String pageData = "";
|
||||
|
||||
_MarkdownPageState({this.title, this.file, this.route});
|
||||
_MarkdownPageState(
|
||||
{required this.title, required this.file, required this.route});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:connectivity/connectivity.dart';
|
||||
import 'package:fires_flutter/models/fireNotification.dart';
|
||||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:latlong/latlong.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'fireMapState.dart';
|
||||
|
|
@ -44,8 +43,6 @@ class AppState {
|
|||
final int fireNotificationsUnread;
|
||||
@JsonKey(ignore: true)
|
||||
final FireMapState fireMapState;
|
||||
@JsonKey(ignore: true)
|
||||
final ConnectivityResult connectivity;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
factory AppState.fromJson(Map<String, dynamic> json) =>
|
||||
|
|
@ -57,31 +54,29 @@ class AppState {
|
|||
this.fireNotificationsUnread = 0,
|
||||
this.user = const User.initial(),
|
||||
this.isLoading = false,
|
||||
this.isLoaded= false,
|
||||
this.error,
|
||||
this.gmapKey,
|
||||
this.firesApiKey,
|
||||
this.firesApiUrl,
|
||||
this.serverUrl,
|
||||
this.connectivity,
|
||||
this.monitoredAreas,
|
||||
this.isLoaded = false,
|
||||
this.error = '',
|
||||
this.gmapKey = '',
|
||||
this.firesApiKey = '',
|
||||
this.firesApiUrl = '',
|
||||
this.serverUrl = '',
|
||||
this.monitoredAreas = const <Polyline>[],
|
||||
this.fireMapState = const FireMapState.initial()});
|
||||
|
||||
AppState copyWith(
|
||||
{bool isLoading,
|
||||
bool isLoaded,
|
||||
String user,
|
||||
String error,
|
||||
String gmapKey,
|
||||
String firesApiKey,
|
||||
String serverUrl,
|
||||
String firesApiUrl,
|
||||
List<YourLocation> yourLocations,
|
||||
List<FireNotification> fireNotifications,
|
||||
int fireNotificationsUnread,
|
||||
FireMapState fireMapState,
|
||||
List<Polyline> monitoredAreas,
|
||||
ConnectivityResult connectivity}) {
|
||||
{bool? isLoading,
|
||||
bool? isLoaded,
|
||||
User? user,
|
||||
String? error,
|
||||
String? gmapKey,
|
||||
String? firesApiKey,
|
||||
String? serverUrl,
|
||||
String? firesApiUrl,
|
||||
List<YourLocation>? yourLocations,
|
||||
List<FireNotification>? fireNotifications,
|
||||
int? fireNotificationsUnread,
|
||||
FireMapState? fireMapState,
|
||||
List<Polyline>? monitoredAreas}) {
|
||||
return new AppState(
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
isLoaded: isLoaded ?? this.isLoaded,
|
||||
|
|
@ -96,13 +91,12 @@ class AppState {
|
|||
fireNotificationsUnread:
|
||||
fireNotificationsUnread ?? this.fireNotificationsUnread,
|
||||
monitoredAreas: monitoredAreas ?? this.monitoredAreas,
|
||||
fireMapState: fireMapState ?? this.fireMapState,
|
||||
connectivity: connectivity ?? this.connectivity);
|
||||
fireMapState: fireMapState ?? this.fireMapState);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppState{\nuser: $user\nconnectivity: ${connectivity.toString()}\nisLoading: $isLoading\nisLoaded: $isLoaded\napiKey: ${ellipse(firesApiKey, 8)}\napiUrl: $firesApiUrl\nserverUrl: $serverUrl\nfireMapState: $fireMapState\nyourLocations count: ${yourLocations.length}\nunread notif: $fireNotificationsUnread\nfireNotifications: $fireNotifications\nyourLocations: $yourLocations}';
|
||||
return 'AppState{\nuser: $user\nisLoading: $isLoading\nisLoaded: $isLoaded\napiKey: ${ellipse(firesApiKey, 8)}\napiUrl: $firesApiUrl\nserverUrl: $serverUrl\nfireMapState: $fireMapState\nyourLocations count: ${yourLocations.length}\nunread notif: $fireNotificationsUnread\nfireNotifications: $fireNotifications\nyourLocations: $yourLocations}';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
|
||||
class BasicLocation extends Comparable<BasicLocation> {
|
||||
class BasicLocation implements Comparable<BasicLocation> {
|
||||
final double lat;
|
||||
final double lon;
|
||||
String description;
|
||||
final String? description;
|
||||
|
||||
// static BasicLocation noLocation = new BasicLocation(lat: 0.0, lon: 0.0);
|
||||
|
||||
BasicLocation({required this.lat, required this.lon, this.description}) {
|
||||
|
||||
}
|
||||
BasicLocation({required this.lat, required this.lon, this.description}) {}
|
||||
|
||||
int compareTo(BasicLocation other) {
|
||||
return lat == other.lat && lon == other.lon ? 1 : 0;
|
||||
|
|
|
|||
|
|
@ -24,16 +24,14 @@ class FireNotification {
|
|||
_$FireNotificationFromJson(json);
|
||||
|
||||
FireNotification(
|
||||
{this.id,
|
||||
{required this.id,
|
||||
required this.lat,
|
||||
required this.lon,
|
||||
required this.description,
|
||||
required this.when,
|
||||
required this.read,
|
||||
required this.sealed,
|
||||
required this.subsId}) {
|
||||
|
||||
}
|
||||
required this.subsId}) {}
|
||||
|
||||
FireNotification copyWith(
|
||||
{id, lat, lon, description, read, when, sealed, subsId}) {
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ final String fireNotificationKey = 'fireNotifications';
|
|||
|
||||
Future<List<FireNotification>> loadFireNotifications() async {
|
||||
return await globals.prefs.then((prefs) {
|
||||
List<String> FireNotifications = prefs.getStringList(fireNotificationKey);
|
||||
List<String>? FireNotifications = prefs.getStringList(fireNotificationKey);
|
||||
List<FireNotification> persistedList = [];
|
||||
FireNotifications.forEach((notificationString) {
|
||||
(FireNotifications ?? []).forEach((notificationString) {
|
||||
Map notificationMap = json.decode(notificationString);
|
||||
persistedList.add(FireNotification.fromJson(notificationMap));
|
||||
persistedList.add(
|
||||
FireNotification.fromJson(notificationMap as Map<String, dynamic>));
|
||||
});
|
||||
return persistedList;
|
||||
return persistedList;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ class User {
|
|||
final String token;
|
||||
|
||||
const User.initial()
|
||||
: this.userId = null,
|
||||
lang = null,
|
||||
token = null;
|
||||
: userId = '',
|
||||
lang = '',
|
||||
token = '';
|
||||
|
||||
User({this.userId, this.lang, this.token});
|
||||
const User({required this.userId, required this.lang, required this.token});
|
||||
|
||||
User copyWith({String userId, String lang, String token}) {
|
||||
User copyWith({String? userId, String? lang, String? token}) {
|
||||
return new User(
|
||||
userId: userId ?? this.userId,
|
||||
token: token ?? this.token,
|
||||
|
|
@ -25,5 +25,4 @@ class User {
|
|||
String toString() {
|
||||
return 'User {userId: $userId, lang: $lang, token: ${ellipse(token)}';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,22 +13,28 @@ class YourLocation {
|
|||
String description;
|
||||
bool subscribed;
|
||||
int distance;
|
||||
int currentNumFires;
|
||||
late int currentNumFires;
|
||||
|
||||
factory YourLocation.fromJson(Map<String, dynamic> json) =>
|
||||
_$YourLocationFromJson(json);
|
||||
|
||||
static YourLocation noLocation = new YourLocation(lat: 0.0, lon: 0.0);
|
||||
static const int withoutStats = null;
|
||||
static late final YourLocation noLocation;
|
||||
static const int? withoutStats = null;
|
||||
|
||||
static void _initNoLocation() {
|
||||
noLocation = new YourLocation(
|
||||
id: ObjectId(), lat: 0.0, lon: 0.0, description: '', subscribed: false);
|
||||
}
|
||||
|
||||
YourLocation(
|
||||
{this.id,
|
||||
{required this.id,
|
||||
required this.lat,
|
||||
required this.lon,
|
||||
this.description,
|
||||
this.description = '',
|
||||
this.distance = 10,
|
||||
int currentNumFires = withoutStats,
|
||||
this.subscribed =false}) {
|
||||
|
||||
int? currentNumFires,
|
||||
this.subscribed = false}) {
|
||||
this.currentNumFires = currentNumFires ?? 0;
|
||||
}
|
||||
Map<String, dynamic> toJson() => _$YourLocationToJson(this);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ final String locationKey = 'yourlocations';
|
|||
|
||||
Future<List<YourLocation>> loadYourLocations() async {
|
||||
return await globals.prefs.then((prefs) {
|
||||
List<String> yourLocations = prefs.getStringList(locationKey);
|
||||
List<String>? yourLocations = prefs.getStringList(locationKey);
|
||||
List<YourLocation> persistedList = [];
|
||||
yourLocations.forEach((locationString) {
|
||||
(yourLocations ?? []).forEach((locationString) {
|
||||
Map locationMap = json.decode(locationString);
|
||||
persistedList.add(YourLocation.fromJson(locationMap));
|
||||
persistedList
|
||||
.add(YourLocation.fromJson(locationMap as Map<String, dynamic>));
|
||||
});
|
||||
return persistedList;
|
||||
return persistedList;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import 'dart:async';
|
|||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'generated/i18n.dart';
|
||||
|
||||
/// Open a places dialog for selecting a location.
|
||||
/// Currently returns a default location as the google_places_autocomplete package
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'package:fires_flutter/models/fireNotification.dart';
|
||||
import 'dart:async';
|
||||
import 'package:connectivity/connectivity.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
|
||||
abstract class AppActions {}
|
||||
|
||||
class FetchYourLocationsAction extends AppActions {
|
||||
Completer<Null> refreshCallback;
|
||||
Completer<Null>? refreshCallback;
|
||||
|
||||
FetchYourLocationsAction([this.refreshCallback]);
|
||||
}
|
||||
|
|
@ -52,13 +52,8 @@ class FetchFireNotificationsSucceededAction extends AppActions {
|
|||
final List<FireNotification> fetchedFireNotifications;
|
||||
final int unreadCount;
|
||||
|
||||
FetchFireNotificationsSucceededAction(this.fetchedFireNotifications, this.unreadCount);
|
||||
}
|
||||
|
||||
class OnConnectivityChanged extends AppActions {
|
||||
final ConnectivityResult connectivityResult;
|
||||
|
||||
OnConnectivityChanged(this.connectivityResult);
|
||||
FetchFireNotificationsSucceededAction(
|
||||
this.fetchedFireNotifications, this.unreadCount);
|
||||
}
|
||||
|
||||
class FetchMonitoredAreasSucceededAction extends AppActions {
|
||||
|
|
@ -66,3 +61,9 @@ class FetchMonitoredAreasSucceededAction extends AppActions {
|
|||
|
||||
FetchMonitoredAreasSucceededAction(this.monitoredAreas);
|
||||
}
|
||||
|
||||
class OnConnectivityChanged extends AppActions {
|
||||
final List<ConnectivityResult> connectionStatus;
|
||||
|
||||
OnConnectivityChanged(this.connectionStatus);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ void fetchDataMiddleware(Store<AppState> store, action, NextDispatcher next) {
|
|||
});
|
||||
locSubs.subscribed = true;
|
||||
});
|
||||
|
||||
|
||||
store.dispatch(new FetchYourLocationsSucceededAction(localLocations));
|
||||
persistYourLocations(localLocations);
|
||||
|
||||
|
|
@ -182,9 +182,9 @@ void fetchDataMiddleware(Store<AppState> store, action, NextDispatcher next) {
|
|||
});
|
||||
});
|
||||
|
||||
Completer<Null> completer = action.refreshCallback;
|
||||
completer.complete(null);
|
||||
});
|
||||
final Completer<Null>? completer = action.refreshCallback;
|
||||
completer?.complete(null);
|
||||
});
|
||||
}).catchError((onError) {
|
||||
// If it fails, dispatch a failure action. The reducer will
|
||||
// update the state with the error.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:redux/redux.dart';
|
||||
import 'package:fires_flutter/models/yourLocation.dart';
|
||||
import 'package:objectid/objectid.dart';
|
||||
import '../models/fireMapState.dart';
|
||||
import 'actions.dart';
|
||||
|
||||
|
|
@ -7,7 +8,7 @@ final fireMapReducer = combineReducers<FireMapState>([
|
|||
new TypedReducer<FireMapState, ShowYourLocationMapAction>(
|
||||
_showYourLocationMap),
|
||||
new TypedReducer<FireMapState, ShowFireNotificationMapAction>(
|
||||
_showFireNotificationMap),
|
||||
_showFireNotificationMap),
|
||||
new TypedReducer<FireMapState, UpdateFireMapStatsAction>(
|
||||
_updateYourLocationMapStats),
|
||||
new TypedReducer<FireMapState, SubscribeAction>(_subscribeYourLocationMap),
|
||||
|
|
@ -20,8 +21,7 @@ final fireMapReducer = combineReducers<FireMapState>([
|
|||
_editConfirmYourLocationMap),
|
||||
new TypedReducer<FireMapState, EditCancelYourLocationAction>(
|
||||
_editCancelYourLocationMap),
|
||||
new TypedReducer<FireMapState, ToggleMapLayerAction>(
|
||||
_toggleMapLayer),
|
||||
new TypedReducer<FireMapState, ToggleMapLayerAction>(_toggleMapLayer),
|
||||
new TypedReducer<FireMapState, UpdateYourLocationMapAction>(
|
||||
_updateYourLocationMap)
|
||||
]);
|
||||
|
|
@ -46,15 +46,22 @@ FireMapState _showYourLocationMap(
|
|||
status: action.loc.subscribed
|
||||
? FireMapStatus.unsubscribe
|
||||
: FireMapStatus.view,
|
||||
yourLocation: action.loc, fireNotication: null);
|
||||
yourLocation: action.loc,
|
||||
fireNotication: null);
|
||||
}
|
||||
|
||||
FireMapState _showFireNotificationMap(
|
||||
FireMapState state, ShowFireNotificationMapAction action) {
|
||||
// TODO: use here you real location?
|
||||
YourLocation pseudoLoc = new YourLocation(lat: action.notif.lat, lon: action.notif.lon, description: action.notif.description);
|
||||
YourLocation pseudoLoc = new YourLocation(
|
||||
id: ObjectId(),
|
||||
lat: action.notif.lat,
|
||||
lon: action.notif.lon,
|
||||
description: action.notif.description);
|
||||
return state.copyWith(
|
||||
status: FireMapStatus.viewFireNotification, yourLocation: pseudoLoc, fireNotication: action.notif);
|
||||
status: FireMapStatus.viewFireNotification,
|
||||
yourLocation: pseudoLoc,
|
||||
fireNotication: action.notif);
|
||||
}
|
||||
|
||||
FireMapState _subscribeYourLocationMap(
|
||||
|
|
@ -92,12 +99,12 @@ FireMapState _editCancelYourLocationMap(
|
|||
FireMapStatus restoreStatusAfterSave(loc) =>
|
||||
loc.subscribed ? FireMapStatus.unsubscribe : FireMapStatus.view;
|
||||
|
||||
FireMapState _toggleMapLayer(
|
||||
FireMapState state, ToggleMapLayerAction action) {
|
||||
FireMapState _toggleMapLayer(FireMapState state, ToggleMapLayerAction action) {
|
||||
FireMapLayer currentLayer = state.layer;
|
||||
List<FireMapLayer> list = FireMapLayer.values;
|
||||
int currentPos = list.indexOf(currentLayer);
|
||||
currentPos++;
|
||||
FireMapLayer next = list.elementAt(currentPos >= list.length ? 0: currentPos);
|
||||
FireMapLayer next =
|
||||
list.elementAt(currentPos >= list.length ? 0 : currentPos);
|
||||
return state.copyWith(layer: next);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class Sandbox extends StatelessWidget {
|
|||
decoration: new InputDecoration(),
|
||||
onSubmitted: (todoText) {},
|
||||
)),
|
||||
body: new RaisedButton(
|
||||
body: new ElevatedButton(
|
||||
child: new Text('Press'),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class FireDistanceSlider extends StatefulWidget {
|
|||
final int initialValue;
|
||||
final SlideCallback onSlide;
|
||||
|
||||
FireDistanceSlider({this.initialValue, this.onSlide});
|
||||
FireDistanceSlider({required this.initialValue, required this.onSlide});
|
||||
|
||||
@override
|
||||
_FireDistanceSliderState createState() => new _FireDistanceSliderState(
|
||||
|
|
@ -18,16 +18,16 @@ class FireDistanceSlider extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _FireDistanceSliderState extends State<FireDistanceSlider> {
|
||||
int _sliderValue;
|
||||
late int _sliderValue;
|
||||
final SlideCallback onSlide;
|
||||
|
||||
_FireDistanceSliderState({int initialValue = 10, this.onSlide}) {
|
||||
_FireDistanceSliderState({int initialValue = 10, required this.onSlide}) {
|
||||
this._sliderValue = initialValue;
|
||||
}
|
||||
|
||||
sizeText(sliderValue) =>
|
||||
new Text(S.of(context).subscribeToValueAroundThisArea(sliderValue.toString()),
|
||||
style: new TextStyle(color: Colors.black87));
|
||||
sizeText(sliderValue) => new Text(
|
||||
S.of(context).subscribeToValueAroundThisArea(sliderValue.toString()),
|
||||
style: new TextStyle(color: Colors.black87));
|
||||
|
||||
warningText(sliderValue) => _sliderValue >= 50
|
||||
? new Text(S.of(context).warningThisIsAVeryLargeArea,
|
||||
|
|
@ -47,7 +47,7 @@ class _FireDistanceSliderState extends State<FireDistanceSlider> {
|
|||
onChanged: (double value) {
|
||||
_sliderValue = value.round();
|
||||
onSlide(_sliderValue);
|
||||
setState(() {});
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
return new Column(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:launch_review/launch_review.dart';
|
||||
import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ class _SupportPageState extends State<SupportPage> {
|
|||
Widget buildSupportButton() {
|
||||
return new Align(
|
||||
alignment: const Alignment(0.0, -0.2),
|
||||
child: new OutlineButton.icon(
|
||||
child: new OutlinedButton.icon(
|
||||
icon: const Icon(Icons.favorite_border),
|
||||
label: new Text(S.of(context).comunesSupportBtn),
|
||||
onPressed: () {
|
||||
|
|
@ -33,11 +33,12 @@ class _SupportPageState extends State<SupportPage> {
|
|||
Widget buildShareButton() {
|
||||
return new Align(
|
||||
alignment: const Alignment(0.0, -0.2),
|
||||
child: new OutlineButton.icon(
|
||||
child: new OutlinedButton.icon(
|
||||
icon: const Icon(Icons.share),
|
||||
label: new Text(S.of(context).shareAppBtn),
|
||||
onPressed: () {
|
||||
Share.shareWithResult('https://play.google.com/store/apps/details?id=org.comunes.fires');
|
||||
Share.shareWithResult(
|
||||
'https://play.google.com/store/apps/details?id=org.comunes.fires');
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -46,11 +47,11 @@ class _SupportPageState extends State<SupportPage> {
|
|||
Widget buildStarButton() {
|
||||
return new Align(
|
||||
alignment: const Alignment(0.0, -0.2),
|
||||
child: new OutlineButton.icon(
|
||||
child: new OutlinedButton.icon(
|
||||
icon: const Icon(Icons.star_border),
|
||||
label: new Text(S.of(context).starAppBtn),
|
||||
onPressed: () {
|
||||
LaunchReview.launch();
|
||||
InAppReview.instance.requestReview();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -59,11 +60,12 @@ class _SupportPageState extends State<SupportPage> {
|
|||
Widget buildTranslateButton() {
|
||||
return new Align(
|
||||
alignment: const Alignment(0.0, -0.2),
|
||||
child: new OutlineButton.icon(
|
||||
child: new OutlinedButton.icon(
|
||||
icon: const Icon(Icons.translate),
|
||||
label: new Text(S.of(context).translateBtn),
|
||||
onPressed: () {
|
||||
launch("https://translate.comunes.org/projects/todos-contra-el-fuego/");
|
||||
launch(
|
||||
"https://translate.comunes.org/projects/todos-contra-el-fuego/");
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ dependencies:
|
|||
# reviews
|
||||
in_app_review: ^2.0.9
|
||||
|
||||
meta: any
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue