import 'package:comunic/helpers/independent_push_notifications_helper.dart'; 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 showInitialPushNotificationsConfiguration( BuildContext context) async { // Check if no notifications service are available if (!PushNotificationsHelper.arePushNotificationsAvailable) return; await Navigator.of(context).push( MaterialPageRoute(builder: (c) => PushNotificationsConfigurationRoute())); } class PushNotificationsConfigurationRoute extends StatefulWidget { @override _PushNotificationsConfigurationRouteState createState() => _PushNotificationsConfigurationRouteState(); } class _PushNotificationsConfigurationRouteState extends State { PushNotificationsStatus currStatus; bool get canSubmit => (currStatus ?? PushNotificationsStatus.UNDEFINED) != PushNotificationsStatus.UNDEFINED; Future _refresh() async { await PushNotificationsHelper.refreshLocalStatus(); currStatus = await PushNotificationsHelper.getLocalStatus(); } @override Widget build(BuildContext context) { return Material( textStyle: TextStyle(color: Colors.white), color: config().splashBackgroundColor, child: Center( child: Padding( padding: const EdgeInsets.all(8.0), child: AsyncScreenWidget( onReload: _refresh, onBuild: _buildForm, errorMessage: tr("Failed to load push notifications settings!"), ), ), )); } Widget _buildForm() => ConstrainedBox( constraints: BoxConstraints(maxWidth: 300), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Spacer(), Icon(Icons.notifications_none, color: Colors.white), Spacer(), Text( tr("Comunic can now send you notifications to your device when the application is closed if you want."), textAlign: TextAlign.center, ), Spacer(), _NotificationOption( title: tr("Use Google services"), description: tr( "Use the Google Play services to send you notifications. This option is less privacy-friendly, but it will work on most phones and will save your battery life."), option: PushNotificationsStatus.FIREBASE, current: currStatus, available: srvConfig.notificationsPolicy.hasFirebase, onChanged: (s) => setState(() => currStatus = s), ), _NotificationOption( title: tr("Use independent notifications service"), description: tr( "Configure Comunic to use your own self-hosted notifications service. This option is much more privacy-friendly, but it will drain your battery life."), option: PushNotificationsStatus.INDEPENDENT, current: currStatus, available: srvConfig.notificationsPolicy.hasIndependent && isAndroid, onChanged: (s) => setState(() => currStatus = s), ), _NotificationOption( title: tr("Do not send notification"), description: tr( "Disable notifications services. You will always be able to change it from application settings."), option: PushNotificationsStatus.DISABLED, current: currStatus, available: true, onChanged: (s) => setState(() => currStatus = s), ), Spacer(), OutlinedButton( onPressed: canSubmit ? _submit : null, child: Text(tr("Configure").toUpperCase()), style: OutlinedButton.styleFrom(primary: Colors.white)), Spacer(), ], ), ); Future _submit() async { try { switch (currStatus) { case PushNotificationsStatus.DISABLED: break; case PushNotificationsStatus.FIREBASE: // TODO: Handle this case. throw new Exception("Firebase not supported yet!"); break; case PushNotificationsStatus.INDEPENDENT: if (await IndependentPushNotificationsHelper.needPreConfiguration()) await IndependentPushNotificationsHelper.preConfigure(context); break; default: throw new Exception("Unknown status!"); } await PushNotificationsHelper.clearLocalStatus(); await PushNotificationsHelper.setNewStatus(currStatus); await PushNotificationsHelper.refreshLocalStatus(); Navigator.of(context).pop(); } catch (e, s) { logError(e, s); showAlert( context: context, message: tr("Failed to configure push notifications!")); } } } 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, @required this.description, @required this.option, @required this.current, @required this.available, @required this.onChanged, }) : assert(title != null), assert(description != 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( splashColor: Colors.transparent, highlightColor: Colors.transparent), child: ListTile( leading: Radio( value: option, groupValue: current, onChanged: onChanged, fillColor: MaterialStateProperty.all(Colors.white), ), title: Text(title, style: TextStyle(color: Colors.white)), subtitle: Text(description, style: TextStyle(color: Colors.white)), contentPadding: EdgeInsets.all(0), onTap: () => onChanged(option), ), ); }