mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 04:04:18 +00:00 
			
		
		
		
	Start to integrate push notifications
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
				
			|||||||
import 'package:comunic/helpers/api_helper.dart';
 | 
					import 'package:comunic/helpers/api_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/preferences_helper.dart';
 | 
					import 'package:comunic/helpers/preferences_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/push_notifications_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/websocket_helper.dart';
 | 
					import 'package:comunic/helpers/websocket_helper.dart';
 | 
				
			||||||
import 'package:comunic/models/api_request.dart';
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
import 'package:comunic/models/authentication_details.dart';
 | 
					import 'package:comunic/models/authentication_details.dart';
 | 
				
			||||||
@@ -77,6 +78,8 @@ class AccountHelper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /// Sign out user
 | 
					  /// Sign out user
 | 
				
			||||||
  Future<void> signOut() async {
 | 
					  Future<void> signOut() async {
 | 
				
			||||||
 | 
					    await PushNotificationsHelper.clearLocalStatus();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await APIRequest.withLogin("account/logout").exec();
 | 
					    await APIRequest.withLogin("account/logout").exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    final preferencesHelper = await PreferencesHelper.getInstance();
 | 
					    final preferencesHelper = await PreferencesHelper.getInstance();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ enum PreferencesKeyList {
 | 
				
			|||||||
  ENABLE_DARK_THEME,
 | 
					  ENABLE_DARK_THEME,
 | 
				
			||||||
  FORCE_MOBILE_MODE,
 | 
					  FORCE_MOBILE_MODE,
 | 
				
			||||||
  SHOW_PERFORMANCE_OVERLAY,
 | 
					  SHOW_PERFORMANCE_OVERLAY,
 | 
				
			||||||
 | 
					  PUSH_NOTIFICATIONS_STATUS,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _PreferenceKeysName = {
 | 
					const _PreferenceKeysName = {
 | 
				
			||||||
@@ -62,6 +63,10 @@ class PreferencesHelper {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool containsKey(PreferencesKeyList key) {
 | 
				
			||||||
 | 
					    return _sharedPreferences.containsKey(_PreferenceKeysName[key]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<bool> removeKey(PreferencesKeyList key) async {
 | 
					  Future<bool> removeKey(PreferencesKeyList key) async {
 | 
				
			||||||
    return await _sharedPreferences.remove(_PreferenceKeysName[key]);
 | 
					    return await _sharedPreferences.remove(_PreferenceKeysName[key]);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										88
									
								
								lib/helpers/push_notifications_helper.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								lib/helpers/push_notifications_helper.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/helpers/preferences_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Push notifications helper
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum PushNotificationsStatus { UNDEFINED, DISABLED, FIREBASE, INDEPENDENT }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const _PushNotificationsAPIMap = {
 | 
				
			||||||
 | 
					  "undefined": PushNotificationsStatus.UNDEFINED,
 | 
				
			||||||
 | 
					  "disabled": PushNotificationsStatus.DISABLED,
 | 
				
			||||||
 | 
					  "firebase": PushNotificationsStatus.FIREBASE,
 | 
				
			||||||
 | 
					  "independent": PushNotificationsStatus.INDEPENDENT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PushNotificationsHelper {
 | 
				
			||||||
 | 
					  /// Get cached status of push notifications
 | 
				
			||||||
 | 
					  static Future<PushNotificationsStatus> getLocalStatus() async {
 | 
				
			||||||
 | 
					    final pref = await PreferencesHelper.getInstance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!pref.containsKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS))
 | 
				
			||||||
 | 
					      return PushNotificationsStatus.UNDEFINED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return _PushNotificationsAPIMap[
 | 
				
			||||||
 | 
					        pref.getString(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS)];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Refresh local status with information from server
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Throws in case of failure
 | 
				
			||||||
 | 
					  static Future<void> refreshLocalStatus() async {
 | 
				
			||||||
 | 
					    final pref = await PreferencesHelper.getInstance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final response = await APIRequest.withLogin("push_notifications/status")
 | 
				
			||||||
 | 
					        .execWithThrowGetObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (response["status"]) {
 | 
				
			||||||
 | 
					      case "undefined":
 | 
				
			||||||
 | 
					        await pref.removeKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case "disabled":
 | 
				
			||||||
 | 
					        await pref.setString(
 | 
				
			||||||
 | 
					            PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS, "disabled");
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case "firebase":
 | 
				
			||||||
 | 
					        await pref.setString(
 | 
				
			||||||
 | 
					            PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS, "firebase");
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case "independent":
 | 
				
			||||||
 | 
					        await pref.setString(
 | 
				
			||||||
 | 
					            PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS, "independent");
 | 
				
			||||||
 | 
					        // TODO : Invoke plugin to apply new WebSocket URL
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        print(
 | 
				
			||||||
 | 
					            "Push notifications status ${response["status"]} is unknown, defaulting to disabled!");
 | 
				
			||||||
 | 
					        await pref.setString(
 | 
				
			||||||
 | 
					            PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS, "disabled");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Clear local push notifications status
 | 
				
			||||||
 | 
					  static Future<void> clearLocalStatus() async {
 | 
				
			||||||
 | 
					    await (await PreferencesHelper.getInstance())
 | 
				
			||||||
 | 
					        .removeKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO : stop local refresh notification refresh
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Set new push notification status on the server
 | 
				
			||||||
 | 
					  static Future<void> setNewStatus(
 | 
				
			||||||
 | 
					    PushNotificationsStatus newStatus, {
 | 
				
			||||||
 | 
					    String firebaseToken = "",
 | 
				
			||||||
 | 
					  }) async =>
 | 
				
			||||||
 | 
					      await APIRequest.withLogin("push_notifications/configure")
 | 
				
			||||||
 | 
					          .addString(
 | 
				
			||||||
 | 
					              "status",
 | 
				
			||||||
 | 
					              _PushNotificationsAPIMap.entries
 | 
				
			||||||
 | 
					                  .firstWhere((e) => e.value == newStatus)
 | 
				
			||||||
 | 
					                  .key)
 | 
				
			||||||
 | 
					          .addString("firebase_token", firebaseToken)
 | 
				
			||||||
 | 
					          .execWithThrow();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -17,6 +17,7 @@ class ServerConfigurationHelper {
 | 
				
			|||||||
        (await APIRequest.withoutLogin("server/config").execWithThrow())
 | 
					        (await APIRequest.withoutLogin("server/config").execWithThrow())
 | 
				
			||||||
            .getObject();
 | 
					            .getObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final pushNotificationsPolicy = response["push_notifications"];
 | 
				
			||||||
    final passwordPolicy = response["password_policy"];
 | 
					    final passwordPolicy = response["password_policy"];
 | 
				
			||||||
    final dataConservationPolicy = response["data_conservation_policy"];
 | 
					    final dataConservationPolicy = response["data_conservation_policy"];
 | 
				
			||||||
    final conversationsPolicy = response["conversations_policy"];
 | 
					    final conversationsPolicy = response["conversations_policy"];
 | 
				
			||||||
@@ -27,6 +28,10 @@ class ServerConfigurationHelper {
 | 
				
			|||||||
        termsURL: response["terms_url"],
 | 
					        termsURL: response["terms_url"],
 | 
				
			||||||
        playStoreURL: response["play_store_url"],
 | 
					        playStoreURL: response["play_store_url"],
 | 
				
			||||||
        androidDirectDownloadURL: response["android_direct_download_url"],
 | 
					        androidDirectDownloadURL: response["android_direct_download_url"],
 | 
				
			||||||
 | 
					        notificationsPolicy: NotificationsPolicy(
 | 
				
			||||||
 | 
					          hasFirebase: pushNotificationsPolicy["has_firebase"],
 | 
				
			||||||
 | 
					          hasIndependent: pushNotificationsPolicy["has_independent"],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
        passwordPolicy: PasswordPolicy(
 | 
					        passwordPolicy: PasswordPolicy(
 | 
				
			||||||
          allowMailInPassword: passwordPolicy["allow_email_in_password"],
 | 
					          allowMailInPassword: passwordPolicy["allow_email_in_password"],
 | 
				
			||||||
          allowNameInPassword: passwordPolicy["allow_name_in_password"],
 | 
					          allowNameInPassword: passwordPolicy["allow_name_in_password"],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,25 +1,32 @@
 | 
				
			|||||||
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:meta/meta.dart';
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Application configuration model
 | 
					/// Application configuration model
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre HUBERT
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultColor = Color(0xFF1A237E);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Configuration class
 | 
					/// Configuration class
 | 
				
			||||||
class Config {
 | 
					class Config {
 | 
				
			||||||
  final String apiServerName;
 | 
					  final String apiServerName;
 | 
				
			||||||
  final String apiServerUri;
 | 
					  final String apiServerUri;
 | 
				
			||||||
  final bool apiServerSecure;
 | 
					  final bool apiServerSecure;
 | 
				
			||||||
  final String clientName;
 | 
					  final String clientName;
 | 
				
			||||||
 | 
					  final Color splashBackgroundColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Config({
 | 
					  const Config({
 | 
				
			||||||
    @required this.apiServerName,
 | 
					    @required this.apiServerName,
 | 
				
			||||||
    @required this.apiServerUri,
 | 
					    @required this.apiServerUri,
 | 
				
			||||||
    @required this.apiServerSecure,
 | 
					    @required this.apiServerSecure,
 | 
				
			||||||
    @required this.clientName,
 | 
					    @required this.clientName,
 | 
				
			||||||
 | 
					    this.splashBackgroundColor = defaultColor,
 | 
				
			||||||
  })  : assert(apiServerName != null),
 | 
					  })  : assert(apiServerName != null),
 | 
				
			||||||
        assert(apiServerUri != null),
 | 
					        assert(apiServerUri != null),
 | 
				
			||||||
        assert(apiServerSecure != null),
 | 
					        assert(apiServerSecure != null),
 | 
				
			||||||
        assert(clientName != null);
 | 
					        assert(clientName != null),
 | 
				
			||||||
 | 
					        assert(splashBackgroundColor != null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Get and set static configuration
 | 
					  /// Get and set static configuration
 | 
				
			||||||
  static Config _config;
 | 
					  static Config _config;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,17 @@ import 'package:version/version.dart';
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre Hubert
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotificationsPolicy {
 | 
				
			||||||
 | 
					  final bool hasFirebase;
 | 
				
			||||||
 | 
					  final bool hasIndependent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const NotificationsPolicy({
 | 
				
			||||||
 | 
					    @required this.hasFirebase,
 | 
				
			||||||
 | 
					    @required this.hasIndependent,
 | 
				
			||||||
 | 
					  })  : assert(hasFirebase != null),
 | 
				
			||||||
 | 
					        assert(hasIndependent != null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordPolicy {
 | 
					class PasswordPolicy {
 | 
				
			||||||
  final bool allowMailInPassword;
 | 
					  final bool allowMailInPassword;
 | 
				
			||||||
  final bool allowNameInPassword;
 | 
					  final bool allowNameInPassword;
 | 
				
			||||||
@@ -106,6 +117,7 @@ class ServerConfig {
 | 
				
			|||||||
  final String termsURL;
 | 
					  final String termsURL;
 | 
				
			||||||
  final String playStoreURL;
 | 
					  final String playStoreURL;
 | 
				
			||||||
  final String androidDirectDownloadURL;
 | 
					  final String androidDirectDownloadURL;
 | 
				
			||||||
 | 
					  final NotificationsPolicy notificationsPolicy;
 | 
				
			||||||
  final PasswordPolicy passwordPolicy;
 | 
					  final PasswordPolicy passwordPolicy;
 | 
				
			||||||
  final ServerDataConservationPolicy dataConservationPolicy;
 | 
					  final ServerDataConservationPolicy dataConservationPolicy;
 | 
				
			||||||
  final ConversationsPolicy conversationsPolicy;
 | 
					  final ConversationsPolicy conversationsPolicy;
 | 
				
			||||||
@@ -115,6 +127,7 @@ class ServerConfig {
 | 
				
			|||||||
    @required this.termsURL,
 | 
					    @required this.termsURL,
 | 
				
			||||||
    @required this.playStoreURL,
 | 
					    @required this.playStoreURL,
 | 
				
			||||||
    @required this.androidDirectDownloadURL,
 | 
					    @required this.androidDirectDownloadURL,
 | 
				
			||||||
 | 
					    @required this.notificationsPolicy,
 | 
				
			||||||
    @required this.passwordPolicy,
 | 
					    @required this.passwordPolicy,
 | 
				
			||||||
    @required this.dataConservationPolicy,
 | 
					    @required this.dataConservationPolicy,
 | 
				
			||||||
    @required this.conversationsPolicy,
 | 
					    @required this.conversationsPolicy,
 | 
				
			||||||
@@ -122,6 +135,7 @@ class ServerConfig {
 | 
				
			|||||||
        assert(termsURL != null),
 | 
					        assert(termsURL != null),
 | 
				
			||||||
        assert(playStoreURL != null),
 | 
					        assert(playStoreURL != null),
 | 
				
			||||||
        assert(androidDirectDownloadURL != null),
 | 
					        assert(androidDirectDownloadURL != null),
 | 
				
			||||||
 | 
					        assert(notificationsPolicy != null),
 | 
				
			||||||
        assert(passwordPolicy != null),
 | 
					        assert(passwordPolicy != null),
 | 
				
			||||||
        assert(dataConservationPolicy != null),
 | 
					        assert(dataConservationPolicy != null),
 | 
				
			||||||
        assert(conversationsPolicy != null);
 | 
					        assert(conversationsPolicy != null);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										188
									
								
								lib/ui/routes/push_notifications_route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								lib/ui/routes/push_notifications_route.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					  if (!srvConfig.notificationsPolicy.hasIndependent &&
 | 
				
			||||||
 | 
					      (!isAndroid || !srvConfig.notificationsPolicy.hasFirebase)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  await Navigator.of(context).push(
 | 
				
			||||||
 | 
					      MaterialPageRoute(builder: (c) => PushNotificationsConfigurationRoute()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PushNotificationsConfigurationRoute extends StatefulWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  _PushNotificationsConfigurationRouteState createState() =>
 | 
				
			||||||
 | 
					      _PushNotificationsConfigurationRouteState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _PushNotificationsConfigurationRouteState
 | 
				
			||||||
 | 
					    extends State<PushNotificationsConfigurationRoute> {
 | 
				
			||||||
 | 
					  PushNotificationsStatus currStatus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get canSubmit =>
 | 
				
			||||||
 | 
					      (currStatus ?? PushNotificationsStatus.UNDEFINED) !=
 | 
				
			||||||
 | 
					      PushNotificationsStatus.UNDEFINED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> _refresh() async {
 | 
				
			||||||
 | 
					    await PushNotificationsHelper.refreshLocalStatus();
 | 
				
			||||||
 | 
					    currStatus = await PushNotificationsHelper.getLocalStatus();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Material(
 | 
				
			||||||
 | 
					        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),
 | 
				
			||||||
 | 
					            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<void> _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:
 | 
				
			||||||
 | 
					          // TODO: Handle this case.
 | 
				
			||||||
 | 
					          throw new Exception("Independent not supported yet!");
 | 
				
			||||||
 | 
					          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,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            title: Text(title),
 | 
				
			||||||
 | 
					            subtitle: Text(description),
 | 
				
			||||||
 | 
					            contentPadding: EdgeInsets.all(0),
 | 
				
			||||||
 | 
					            onTap: () => onChanged(option),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,13 +1,16 @@
 | 
				
			|||||||
import 'package:comunic/helpers/account_helper.dart';
 | 
					import 'package:comunic/helpers/account_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/events_helper.dart';
 | 
					import 'package:comunic/helpers/events_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/push_notifications_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/server_config_helper.dart';
 | 
					import 'package:comunic/helpers/server_config_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/version_helper.dart';
 | 
					import 'package:comunic/helpers/version_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/websocket_helper.dart';
 | 
					import 'package:comunic/helpers/websocket_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/config.dart';
 | 
				
			||||||
import 'package:comunic/ui/dialogs/deprecation_dialog.dart';
 | 
					import 'package:comunic/ui/dialogs/deprecation_dialog.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/login_route.dart';
 | 
					import 'package:comunic/ui/routes/login_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/main_route/main_route.dart';
 | 
					import 'package:comunic/ui/routes/main_route/main_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/main_route/smartphone_route.dart';
 | 
					import 'package:comunic/ui/routes/main_route/smartphone_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/main_route/tablet_route.dart';
 | 
					import 'package:comunic/ui/routes/main_route/tablet_route.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/routes/push_notifications_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/widgets/safe_state.dart';
 | 
					import 'package:comunic/ui/widgets/safe_state.dart';
 | 
				
			||||||
import 'package:comunic/utils/flutter_utils.dart';
 | 
					import 'package:comunic/utils/flutter_utils.dart';
 | 
				
			||||||
import 'package:comunic/utils/intl_utils.dart';
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
@@ -74,6 +77,11 @@ class _InitializeWidgetState extends SafeState<InitializeWidget> {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print("Check push notifications configuration...");
 | 
				
			||||||
 | 
					      if (await PushNotificationsHelper.getLocalStatus() ==
 | 
				
			||||||
 | 
					          PushNotificationsStatus.UNDEFINED)
 | 
				
			||||||
 | 
					        await showInitialPushNotificationsConfiguration(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      print("Attempting WebSocket connection...");
 | 
					      print("Attempting WebSocket connection...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      setState(() {
 | 
					      setState(() {
 | 
				
			||||||
@@ -107,7 +115,7 @@ class _InitializeWidgetState extends SafeState<InitializeWidget> {
 | 
				
			|||||||
  /// Build loading widget
 | 
					  /// Build loading widget
 | 
				
			||||||
  Widget _buildNonReadyWidget() {
 | 
					  Widget _buildNonReadyWidget() {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      backgroundColor: Colors.indigo.shade900,
 | 
					      backgroundColor: config().splashBackgroundColor,
 | 
				
			||||||
      body: Center(
 | 
					      body: Center(
 | 
				
			||||||
        child: Material(
 | 
					        child: Material(
 | 
				
			||||||
          color: Colors.transparent,
 | 
					          color: Colors.transparent,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,10 @@
 | 
				
			|||||||
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Flutter utilities
 | 
					/// Flutter utilities
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre Hubert
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
import 'package:flutter/foundation.dart' show kIsWeb;
 | 
					import 'package:flutter/foundation.dart' show kIsWeb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool get isWeb => kIsWeb;
 | 
					bool get isWeb => kIsWeb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool get isAndroid => !isWeb && Platform.isAndroid;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user