2021-04-15 11:34:49 +00:00
|
|
|
import 'package:comunic/helpers/firebase_messaging_helper.dart';
|
2021-04-13 15:56:55 +00:00
|
|
|
import 'package:comunic/helpers/independent_push_notifications_helper.dart';
|
2021-04-12 17:26:05 +00:00
|
|
|
import 'package:comunic/helpers/push_notifications_helper.dart';
|
|
|
|
import 'package:comunic/helpers/server_config_helper.dart';
|
|
|
|
import 'package:comunic/models/config.dart';
|
|
|
|
import 'package:comunic/ui/widgets/async_screen_widget.dart';
|
|
|
|
import 'package:comunic/utils/flutter_utils.dart';
|
|
|
|
import 'package:comunic/utils/intl_utils.dart';
|
|
|
|
import 'package:comunic/utils/log_utils.dart';
|
|
|
|
import 'package:comunic/utils/ui_utils.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
|
|
/// Push notifications configuration route
|
|
|
|
///
|
|
|
|
/// @author Pierre Hubert
|
|
|
|
|
|
|
|
Future<void> showInitialPushNotificationsConfiguration(
|
|
|
|
BuildContext context) async {
|
|
|
|
// Check if no notifications service are available
|
2021-04-13 15:56:55 +00:00
|
|
|
if (!PushNotificationsHelper.arePushNotificationsAvailable) return;
|
2021-04-12 17:26:05 +00:00
|
|
|
|
|
|
|
await Navigator.of(context).push(
|
|
|
|
MaterialPageRoute(builder: (c) => PushNotificationsConfigurationRoute()));
|
|
|
|
}
|
|
|
|
|
|
|
|
class PushNotificationsConfigurationRoute extends StatefulWidget {
|
|
|
|
@override
|
|
|
|
_PushNotificationsConfigurationRouteState createState() =>
|
|
|
|
_PushNotificationsConfigurationRouteState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _PushNotificationsConfigurationRouteState
|
|
|
|
extends State<PushNotificationsConfigurationRoute> {
|
2021-04-17 17:19:55 +00:00
|
|
|
final _key = GlobalKey<PushNotificationsConfigurationWidgetState>();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) => Material(
|
|
|
|
textStyle: TextStyle(color: Colors.white),
|
|
|
|
color: config().splashBackgroundColor,
|
|
|
|
child: Center(
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.all(8.0),
|
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: [
|
|
|
|
Spacer(),
|
|
|
|
Icon(Icons.notifications_none, color: Colors.white),
|
|
|
|
Spacer(),
|
|
|
|
PushNotificationsConfigurationWidget(
|
|
|
|
key: _key,
|
|
|
|
onConfigured: () => (Navigator.of(context).pop()),
|
|
|
|
onChanged: () => setState(() {}),
|
|
|
|
),
|
|
|
|
Spacer(),
|
|
|
|
OutlinedButton(
|
|
|
|
onPressed: _key?.currentState?.canSubmit ?? false
|
|
|
|
? _key.currentState.submit
|
|
|
|
: null,
|
|
|
|
child: Text(tr("Configure").toUpperCase()),
|
|
|
|
style: OutlinedButton.styleFrom(primary: Colors.white)),
|
|
|
|
Spacer(),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
class PushNotificationsConfigurationWidget extends StatefulWidget {
|
|
|
|
final Function() onConfigured;
|
|
|
|
final Function() onChanged;
|
|
|
|
|
|
|
|
const PushNotificationsConfigurationWidget({
|
|
|
|
Key key,
|
|
|
|
@required this.onConfigured,
|
2021-04-17 17:23:06 +00:00
|
|
|
@required this.onChanged,
|
2021-04-17 17:19:55 +00:00
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
PushNotificationsConfigurationWidgetState createState() =>
|
|
|
|
PushNotificationsConfigurationWidgetState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class PushNotificationsConfigurationWidgetState
|
|
|
|
extends State<PushNotificationsConfigurationWidget> {
|
2021-04-12 17:26:05 +00:00
|
|
|
PushNotificationsStatus currStatus;
|
|
|
|
|
|
|
|
bool get canSubmit =>
|
|
|
|
(currStatus ?? PushNotificationsStatus.UNDEFINED) !=
|
|
|
|
PushNotificationsStatus.UNDEFINED;
|
|
|
|
|
|
|
|
Future<void> _refresh() async {
|
|
|
|
await PushNotificationsHelper.refreshLocalStatus();
|
|
|
|
currStatus = await PushNotificationsHelper.getLocalStatus();
|
2021-04-17 17:19:55 +00:00
|
|
|
|
|
|
|
if (currStatus == PushNotificationsStatus.UNDEFINED &&
|
|
|
|
srvConfig.notificationsPolicy.hasFirebase)
|
|
|
|
currStatus = PushNotificationsStatus.FIREBASE;
|
2021-04-17 17:23:06 +00:00
|
|
|
|
|
|
|
widget.onChanged();
|
2021-04-12 17:26:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2021-04-17 17:19:55 +00:00
|
|
|
return AsyncScreenWidget(
|
|
|
|
onReload: _refresh,
|
|
|
|
onBuild: _buildForm,
|
|
|
|
errorMessage: tr("Failed to load push notifications settings!"),
|
|
|
|
);
|
2021-04-12 17:26:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Widget _buildForm() => ConstrainedBox(
|
|
|
|
constraints: BoxConstraints(maxWidth: 300),
|
|
|
|
child: Column(
|
|
|
|
children: [
|
2021-04-17 17:29:22 +00:00
|
|
|
Text(
|
2021-04-24 06:51:56 +00:00
|
|
|
tr("%app% can send you push notifications to your device.",
|
|
|
|
args: {
|
|
|
|
"app": config().appName,
|
|
|
|
}),
|
2021-04-17 17:29:22 +00:00
|
|
|
textAlign: TextAlign.center,
|
|
|
|
),
|
|
|
|
SizedBox(height: 10),
|
2021-04-12 17:26:05 +00:00
|
|
|
_NotificationOption(
|
2021-04-17 17:19:55 +00:00
|
|
|
title: tr("Use Google services (recommended)"),
|
2021-04-17 17:29:22 +00:00
|
|
|
description: tr("Save your battery life."),
|
2021-04-12 17:26:05 +00:00
|
|
|
option: PushNotificationsStatus.FIREBASE,
|
|
|
|
current: currStatus,
|
|
|
|
available: srvConfig.notificationsPolicy.hasFirebase,
|
2021-04-17 17:19:55 +00:00
|
|
|
onChanged: (s) {
|
|
|
|
setState(() => currStatus = s);
|
|
|
|
if (widget.onChanged != null) widget.onChanged();
|
|
|
|
},
|
2021-04-12 17:26:05 +00:00
|
|
|
),
|
2021-04-18 12:14:21 +00:00
|
|
|
SizedBox(height: 5),
|
2021-04-12 17:26:05 +00:00
|
|
|
_NotificationOption(
|
|
|
|
title: tr("Use independent notifications service"),
|
2021-04-18 12:14:21 +00:00
|
|
|
description: tr(
|
|
|
|
"Protect more your privacy, but drains battery and is less reliable."),
|
2021-04-12 17:26:05 +00:00
|
|
|
option: PushNotificationsStatus.INDEPENDENT,
|
|
|
|
current: currStatus,
|
|
|
|
available:
|
|
|
|
srvConfig.notificationsPolicy.hasIndependent && isAndroid,
|
2021-04-17 17:19:55 +00:00
|
|
|
onChanged: (s) {
|
|
|
|
setState(() => currStatus = s);
|
|
|
|
if (widget.onChanged != null) widget.onChanged();
|
|
|
|
},
|
2021-04-12 17:26:05 +00:00
|
|
|
),
|
2021-04-18 12:14:21 +00:00
|
|
|
SizedBox(height: 5),
|
2021-04-12 17:26:05 +00:00
|
|
|
_NotificationOption(
|
|
|
|
title: tr("Do not send notification"),
|
|
|
|
option: PushNotificationsStatus.DISABLED,
|
|
|
|
current: currStatus,
|
|
|
|
available: true,
|
2021-04-17 17:19:55 +00:00
|
|
|
onChanged: (s) {
|
|
|
|
setState(() => currStatus = s);
|
|
|
|
if (widget.onChanged != null) widget.onChanged();
|
|
|
|
},
|
2021-04-12 17:26:05 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2021-04-17 17:19:55 +00:00
|
|
|
Future<bool> submit() async {
|
2021-04-12 17:26:05 +00:00
|
|
|
try {
|
2021-04-15 11:34:49 +00:00
|
|
|
String firebaseToken = "";
|
|
|
|
|
2021-04-16 06:22:05 +00:00
|
|
|
if (currStatus == await PushNotificationsHelper.getLocalStatus()) {
|
2021-04-17 17:19:55 +00:00
|
|
|
widget.onConfigured();
|
|
|
|
return true;
|
2021-04-16 06:22:05 +00:00
|
|
|
}
|
|
|
|
|
2021-04-12 17:26:05 +00:00
|
|
|
switch (currStatus) {
|
|
|
|
case PushNotificationsStatus.DISABLED:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PushNotificationsStatus.FIREBASE:
|
2021-04-15 11:34:49 +00:00
|
|
|
await FirebaseMessagingHelper.preConfigure();
|
|
|
|
firebaseToken = await FirebaseMessagingHelper.getToken();
|
2021-04-12 17:26:05 +00:00
|
|
|
break;
|
2021-04-13 15:56:55 +00:00
|
|
|
|
2021-04-12 17:26:05 +00:00
|
|
|
case PushNotificationsStatus.INDEPENDENT:
|
2021-04-13 17:45:18 +00:00
|
|
|
if (await IndependentPushNotificationsHelper.needPreConfiguration())
|
|
|
|
await IndependentPushNotificationsHelper.preConfigure(context);
|
2021-04-12 17:26:05 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new Exception("Unknown status!");
|
|
|
|
}
|
|
|
|
|
|
|
|
await PushNotificationsHelper.clearLocalStatus();
|
2021-04-15 11:34:49 +00:00
|
|
|
await PushNotificationsHelper.setNewStatus(currStatus,
|
|
|
|
firebaseToken: firebaseToken);
|
2021-04-12 17:26:05 +00:00
|
|
|
await PushNotificationsHelper.refreshLocalStatus();
|
|
|
|
|
2021-04-17 17:19:55 +00:00
|
|
|
widget.onConfigured();
|
2021-04-12 17:26:05 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
logError(e, s);
|
|
|
|
showAlert(
|
|
|
|
context: context,
|
|
|
|
message: tr("Failed to configure push notifications!"));
|
2021-04-17 17:19:55 +00:00
|
|
|
return false;
|
2021-04-12 17:26:05 +00:00
|
|
|
}
|
2021-04-17 17:19:55 +00:00
|
|
|
return true;
|
2021-04-12 17:26:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _NotificationOption extends StatelessWidget {
|
|
|
|
final String title;
|
|
|
|
final String description;
|
|
|
|
final PushNotificationsStatus option;
|
|
|
|
final PushNotificationsStatus current;
|
|
|
|
final bool available;
|
|
|
|
final Function(PushNotificationsStatus) onChanged;
|
|
|
|
|
|
|
|
const _NotificationOption({
|
|
|
|
Key key,
|
|
|
|
@required this.title,
|
2021-04-17 17:29:22 +00:00
|
|
|
this.description,
|
2021-04-12 17:26:05 +00:00
|
|
|
@required this.option,
|
|
|
|
@required this.current,
|
|
|
|
@required this.available,
|
|
|
|
@required this.onChanged,
|
|
|
|
}) : assert(title != null),
|
|
|
|
assert(option != null),
|
|
|
|
assert(current != null),
|
|
|
|
assert(available != null),
|
|
|
|
assert(onChanged != null),
|
|
|
|
super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) => !available
|
|
|
|
? Container()
|
|
|
|
: Theme(
|
|
|
|
data: Theme.of(context).copyWith(
|
2021-04-13 17:06:31 +00:00
|
|
|
splashColor: Colors.transparent,
|
|
|
|
highlightColor: Colors.transparent),
|
2021-04-12 17:26:05 +00:00
|
|
|
child: ListTile(
|
|
|
|
leading: Radio(
|
|
|
|
value: option,
|
|
|
|
groupValue: current,
|
|
|
|
onChanged: onChanged,
|
2021-04-13 17:06:31 +00:00
|
|
|
fillColor: MaterialStateProperty.all(Colors.white),
|
2021-04-12 17:26:05 +00:00
|
|
|
),
|
2021-04-13 17:06:31 +00:00
|
|
|
title: Text(title, style: TextStyle(color: Colors.white)),
|
2021-04-17 17:29:22 +00:00
|
|
|
subtitle: description == null
|
|
|
|
? null
|
|
|
|
: Text(description, style: TextStyle(color: Colors.white)),
|
2021-04-12 17:26:05 +00:00
|
|
|
contentPadding: EdgeInsets.all(0),
|
|
|
|
onTap: () => onChanged(option),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|