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 ( ) ,
Text (
tr ( " Comunic can send you notifications to your device when the application is closed if you want. " ) ,
textAlign: TextAlign . center ,
) ,
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 ,
this . onChanged ,
} ) : 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-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: [
_NotificationOption (
2021-04-17 17:19:55 +00:00
title: tr ( " Use Google services (recommended) " ) ,
2021-04-12 17:26:05 +00:00
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 ,
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
) ,
_NotificationOption (
title: tr ( " Use independent notifications service " ) ,
description: tr (
2021-04-17 06:53:54 +00:00
" Configure Comunic to use our own self-hosted notifications service. This option is much more privacy-friendly, but it will drain your battery. " ) ,
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
) ,
_NotificationOption (
title: tr ( " Do not send notification " ) ,
description: tr (
2021-04-17 06:54:36 +00:00
" Disable notifications service. You will always be able to change it from application settings. " ) ,
2021-04-12 17:26:05 +00:00
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 ,
@ 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 (
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 ) ) ,
subtitle: Text ( description , style: TextStyle ( color: Colors . white ) ) ,
2021-04-12 17:26:05 +00:00
contentPadding: EdgeInsets . all ( 0 ) ,
onTap: ( ) = > onChanged ( option ) ,
) ,
) ;
}