TF-1202: Configure FCM

This commit is contained in:
ManhNTX
2022-11-17 13:07:26 +07:00
committed by Dat H. Pham
parent 8276f5b041
commit f94cfe7ee8
34 changed files with 718 additions and 25 deletions
+13 -4
View File
@@ -22,6 +22,7 @@ if (flutterVersionName == null) {
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@@ -32,7 +33,7 @@ if (keystorePropertiesFile.exists()) {
}
android {
compileSdkVersion 32
compileSdkVersion 33
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -40,8 +41,8 @@ android {
defaultConfig {
applicationId "com.linagora.android.teammail"
minSdkVersion 16
targetSdkVersion 31
minSdkVersion 19
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
// The number of method references in a .dex file cannot exceed 64K
@@ -51,6 +52,12 @@ android {
]
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// Use key information file
signingConfigs {
release {
@@ -74,7 +81,9 @@ flutter {
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:multidex:1.0.3'
implementation 'androidx.work:work-runtime-ktx:2.7.0'
implementation 'com.android.support:multidex:1.0.3'
implementation 'androidx.window:window:1.0.0'
}
+3 -4
View File
@@ -32,12 +32,15 @@
</queries>
<application
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
@@ -56,10 +59,6 @@
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
+2 -1
View File
@@ -6,8 +6,9 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.google.gms:google-services:4.3.10'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:4.2.2'
}
}
+1 -1
View File
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
+4 -2
View File
@@ -1,19 +1,19 @@
import 'package:flutter/foundation.dart';
import 'package:tmail_ui_user/features/caching/account_cache_client.dart';
import 'package:tmail_ui_user/features/caching/email_cache_client.dart';
import 'package:tmail_ui_user/features/caching/firebase_config_cache_client.dart';
import 'package:tmail_ui_user/features/caching/mailbox_cache_client.dart';
import 'package:tmail_ui_user/features/caching/recent_search_cache_client.dart';
import 'package:tmail_ui_user/features/caching/state_cache_client.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart';
class CachingManager {
final MailboxCacheClient _mailboxCacheClient;
final StateCacheClient _stateCacheClient;
final EmailCacheClient _emailCacheClient;
final RecentSearchCacheClient _recentSearchCacheClient;
final AccountCacheClient _accountCacheClient;
final FirebaseCacheClient _firebaseCacheClient;
CachingManager(
this._mailboxCacheClient,
@@ -21,6 +21,7 @@ class CachingManager {
this._emailCacheClient,
this._recentSearchCacheClient,
this._accountCacheClient,
this._firebaseCacheClient,
);
Future<void> clearAll() async {
@@ -39,6 +40,7 @@ class CachingManager {
_emailCacheClient.deleteBox(),
_recentSearchCacheClient.deleteBox(),
_accountCacheClient.deleteBox(),
_firebaseCacheClient.deleteBox(),
]);
}
}
@@ -0,0 +1,8 @@
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_cache.dart';
class FirebaseCacheClient extends HiveCacheClient<FirebaseCache> {
@override
String get tableName => 'FirebaseCache';
}
@@ -13,4 +13,5 @@ class CachingConstants {
static const int AUTHENTICATION_INFO_HIVE_CACHE_IDENTIFY = 11;
static const int RECENT_LOGIN_URL_HIVE_CACHE_IDENTITY = 12;
static const int RECENT_LOGIN_USERNAME_HIVE_CACHE_IDENTITY = 13;
static const int FIREBASE_CONFIG_CACHE_IDENTITY = 14;
}
@@ -124,7 +124,6 @@ class MailboxDashBoardController extends ReloadableController {
final viewStateMarkAsReadMailbox = Rx<Either<Failure, Success>>(Right(UIState.idle));
final vacationResponse = Rxn<VacationResponse>();
final routerParameters = Rxn<Map<String, String?>>();
Session? sessionCurrent;
Map<Role, MailboxId> mapDefaultMailboxIdByRole = {};
Map<MailboxId, PresentationMailbox> mapMailboxById = {};
@@ -0,0 +1,9 @@
import 'package:model/firebase/firebase_dto.dart';
abstract class FirebaseDatasource {
Future<FirebaseDto> getCurrentFirebase();
Future<void> setCurrentFirebase(FirebaseDto newCurrentFirebase);
Future<void> deleteCurrentFirebase(String token);
}
@@ -0,0 +1,39 @@
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource/firebase_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/data/local/firebase_cache_manager.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
class HiveFirebaseDatasourceImpl extends FirebaseDatasource {
final FirebaseCacheManager _firebaseCacheManager;
final ExceptionThrower _exceptionThrower;
HiveFirebaseDatasourceImpl(this._firebaseCacheManager, this._exceptionThrower);
@override
Future<FirebaseDto> getCurrentFirebase() {
return Future.sync(() async {
return await _firebaseCacheManager.getFirebase();
}).catchError((error) {
_exceptionThrower.throwException(error);
});
}
@override
Future<void> setCurrentFirebase(FirebaseDto newCurrentFirebase) {
return Future.sync(() async {
return await _firebaseCacheManager.setFirebase(newCurrentFirebase);
}).catchError((error) {
_exceptionThrower.throwException(error);
});
}
@override
Future<void> deleteCurrentFirebase(String token) {
return Future.sync(() async {
return await _firebaseCacheManager.deleteFirebase(token);
}).catchError((error) {
_exceptionThrower.throwException(error);
});
}
}
@@ -0,0 +1,10 @@
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_cache.dart';
extension FirebaseCacheExtension on FirebaseCache {
FirebaseDto toFirebaseDto() {
return FirebaseDto(token);
}
}
@@ -0,0 +1,8 @@
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_cache.dart';
extension FirebaseExtensions on FirebaseDto {
FirebaseCache toCache() {
return FirebaseCache(token);
}
}
@@ -0,0 +1,37 @@
import 'package:core/utils/app_logger.dart';
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/caching/firebase_config_cache_client.dart';
import 'package:tmail_ui_user/features/push_notification/data/extensions/firebase_extensions.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_cache.dart';
import 'package:tmail_ui_user/features/push_notification/data/extensions/firebase_cache_extensions.dart';
import 'package:tmail_ui_user/features/push_notification/domain/exceptions/firebase_exception.dart';
class FirebaseCacheManager {
final FirebaseCacheClient _firebaseCacheClient;
FirebaseCacheManager(this._firebaseCacheClient);
Future<FirebaseDto> getFirebase() async {
try {
final firebase = await _firebaseCacheClient.getItem(FirebaseCache.keyCacheValue);
if(firebase != null ) {
return firebase.toFirebaseDto();
} else {
throw NotFoundStoredFirebaseException();
}
} catch (e) {
logError('FirebaseCacheManager::getFirebase(): $e');
throw NotFoundStoredFirebaseException();
}
}
Future<void> setFirebase(FirebaseDto firebaseDto) {
log('FirebaseCacheManager::setFirebase(): $_firebaseCacheClient');
return _firebaseCacheClient.insertItem(firebaseDto.token, firebaseDto.toCache());
}
Future<void> deleteFirebase(String token) {
log('FirebaseCacheManager::deleteSelectedFirebase(): $token');
return _firebaseCacheClient.deleteItem(token);
}
}
@@ -0,0 +1,19 @@
import 'package:equatable/equatable.dart';
import 'package:hive/hive.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
part 'firebase_cache.g.dart';
@HiveType(typeId: CachingConstants.FIREBASE_CONFIG_CACHE_IDENTITY)
class FirebaseCache extends HiveObject with EquatableMixin {
static const String keyCacheValue = 'firebaseCache';
@HiveField(0)
final String token;
FirebaseCache(this.token);
@override
List<Object?> get props => [token];
}
@@ -0,0 +1,27 @@
import 'package:core/utils/app_logger.dart';
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource/firebase_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/firebase_repository.dart';
class FirebaseRepositoryImpl extends FirebaseRepository {
final FirebaseDatasource _firebaseDatasource;
FirebaseRepositoryImpl(this._firebaseDatasource);
@override
Future<FirebaseDto> getCurrentFirebase() {
return _firebaseDatasource.getCurrentFirebase();
}
@override
Future<void> setCurrentFirebase(FirebaseDto newCurrentFirebase) {
log('FirebaseRepositoryImpl::setCurrentFirebase(): $newCurrentFirebase');
return _firebaseDatasource.setCurrentFirebase(newCurrentFirebase);
}
@override
Future<void> deleteCurrentFirebase(String token) {
return _firebaseDatasource.deleteCurrentFirebase(token);
}
}
@@ -0,0 +1,2 @@
class NotFoundStoredFirebaseException implements Exception {}
@@ -0,0 +1,9 @@
import 'package:model/firebase/firebase_dto.dart';
abstract class FirebaseRepository {
Future<FirebaseDto> getCurrentFirebase();
Future<void> setCurrentFirebase(FirebaseDto newCurrentFirebase);
Future<void> deleteCurrentFirebase(String token);
}
@@ -0,0 +1,19 @@
import 'package:core/core.dart';
class DeleteFirebaseSuccess extends UIState {
DeleteFirebaseSuccess();
@override
List<Object> get props => [];
}
class DeleteFirebaseFailure extends FeatureFailure {
final dynamic exception;
DeleteFirebaseFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,21 @@
import 'package:core/core.dart';
import 'package:model/firebase/firebase_dto.dart';
class GetFirebaseSuccess extends UIState {
final FirebaseDto firebaseDto;
GetFirebaseSuccess(this.firebaseDto);
@override
List<Object> get props => [firebaseDto];
}
class GetFirebaseFailure extends FeatureFailure {
final dynamic exception;
GetFirebaseFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,19 @@
import 'package:core/core.dart';
class SaveFirebaseSuccess extends UIState {
SaveFirebaseSuccess();
@override
List<Object> get props => [];
}
class SaveFirebaseFailure extends FeatureFailure {
final dynamic exception;
SaveFirebaseFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,20 @@
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/firebase_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/delete_firebase_state.dart';
class DeleteFirebaseCacheInteractor {
final FirebaseRepository _firebaseRepository;
DeleteFirebaseCacheInteractor(this._firebaseRepository);
Future<Either<Failure, Success>> execute(String token) async {
try {
await _firebaseRepository.deleteCurrentFirebase(token);
return Right<Failure, Success>(DeleteFirebaseSuccess());
} catch (e) {
logError('DeleteFirebaseCacheInteractor::execute(): $e');
return Left<Failure, Success>(DeleteFirebaseFailure(e));
}
}
}
@@ -0,0 +1,25 @@
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/firebase_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_firebase_state.dart';
class GetFirebaseCacheInteractor {
final FirebaseRepository _firebaseRepository;
GetFirebaseCacheInteractor(this._firebaseRepository);
Future<Either<Failure, Success>> execute(
OIDCConfiguration config,
String refreshToken) async {
try {
final firebase = await _firebaseRepository.getCurrentFirebase();
return Right<Failure, Success>(GetFirebaseSuccess(firebase));
} catch (e) {
logError('GetFirebaseCacheInteractor::execute(): $e');
return Left<Failure, Success>(GetFirebaseFailure(e));
}
}
}
@@ -0,0 +1,21 @@
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/firebase_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/save_firebase_state.dart';
class SaveFirebaseCacheInteractor {
final FirebaseRepository _firebaseRepository;
SaveFirebaseCacheInteractor(this._firebaseRepository);
Future<Either<Failure, Success>> execute(FirebaseDto firebaseDto) async {
try {
await _firebaseRepository.setCurrentFirebase(firebaseDto);
return Right<Failure, Success>(SaveFirebaseSuccess());
} catch (e) {
logError('SaveFirebaseCacheInteractor::execute(): $e');
return Left<Failure, Success>(SaveFirebaseFailure(e));
}
}
}
@@ -0,0 +1,46 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource/firebase_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource_impl/hive_account_datasource_impl.dart';
import 'package:tmail_ui_user/features/push_notification/data/local/firebase_cache_manager.dart';
import 'package:tmail_ui_user/features/push_notification/data/repository/firebase_repository_impl.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/firebase_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/delete_firebase_cache_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_firebase_cache_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
class FireBaseBindings extends BaseBindings {
@override
void bindingsController() {}
@override
void bindingsDataSource() {
Get.put<FirebaseDatasource>(Get.find<HiveFirebaseDatasourceImpl>());
}
@override
void bindingsDataSourceImpl() {
Get.put(HiveFirebaseDatasourceImpl(
Get.find<FirebaseCacheManager>(),
Get.find<CacheExceptionThrower>(),
));
}
@override
void bindingsInteractor() {
Get.put(DeleteFirebaseCacheInteractor(Get.find<FirebaseRepositoryImpl>()));
Get.put(SaveFirebaseCacheInteractor(Get.find<FirebaseRepositoryImpl>()));
Get.put(GetFirebaseCacheInteractor(Get.find<FirebaseRepositoryImpl>()));
}
@override
void bindingsRepository() {
Get.put<FirebaseRepository>(Get.find<FirebaseRepositoryImpl>());
}
@override
void bindingsRepositoryImpl() {
Get.put(FirebaseRepositoryImpl(Get.find<FirebaseDatasource>()));
}
}
@@ -0,0 +1,155 @@
import 'dart:async';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:model/firebase/firebase_dto.dart';
import 'package:rxdart/rxdart.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart';
import 'package:tmail_ui_user/firebase_options.dart';
import 'notification_strings.dart';
final StreamController<NotificationResponse?> selectNotificationStream =
StreamController<NotificationResponse?>.broadcast();
@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await NotificationService.displayPushNotification(message);
}
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
//handle action
}
void onDidReceiveNotificationResponse(
NotificationResponse details,
) {
selectNotificationStream.add(details);
}
class NotificationService {
factory NotificationService() => _instance;
NotificationService._internal();
static final NotificationService _instance = NotificationService._internal();
static get _firebaseMessaging => FirebaseMessaging.instance;
static get _flutterLocalNotificationsPlugin =>
FlutterLocalNotificationsPlugin();
static final BehaviorSubject<NotificationResponse?>
_notificationActionStream =
BehaviorSubject<NotificationResponse?>.seeded(null);
static Stream<NotificationResponse?> get notificationActionStream =>
_notificationActionStream.stream;
static Stream<String> get onTokenRefresh => _firebaseMessaging.onTokenRefresh;
static bool _isFlutterLocalNotificationsInitialized = false;
static Future<void> initializeNotificationService(
Function(NotificationResponse)? onDidReceiveNotificationResponse,
) async {
if (_isFlutterLocalNotificationsInitialized) return;
final _saveFirebaseCacheInteractor = Get.find<SaveFirebaseCacheInteractor>();
final token = await _firebaseMessaging.getToken();
_saveFirebaseCacheInteractor.execute(FirebaseDto(token));
await _initFirebaseMessaging();
await _flutterLocalNotificationsPlugin.initialize(
InitializationSettings(
android: androidInitializationSettings,
iOS: iosInitializationSettings,
),
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
await _requestPermissions();
await _createNotificationChannels();
_listenNotificationActionStream();
_isFlutterLocalNotificationsInitialized = true;
}
static Future<void> displayPushNotification(
RemoteMessage notification,
) async {
try {
await _flutterLocalNotificationsPlugin.show(
createUniqueId,
channelName,
notification.data.toString(),
pushNotificationDetails,
);
} catch (e) {
debugPrint(e.toString());
}
}
static Future<void> cancelAllNotifications() async {
await _flutterLocalNotificationsPlugin.cancelAll();
}
static Future<void> _initFirebaseMessaging() async {
FirebaseMessaging.onMessage.listen(_handleIncomingForegroundNotification);
FirebaseMessaging.onMessageOpenedApp.listen(_handleOpenedAppNotification);
}
static Future<void> _handleIncomingForegroundNotification(
RemoteMessage remoteMessage,
) async {
await displayPushNotification(remoteMessage);
}
static void _handleOpenedAppNotification(RemoteMessage remoteMessage) {}
static Future<void> _requestPermissions() async {
if (Platform.isAndroid) {
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.requestPermission();
} else {
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
}
static Future<void> _listenNotificationActionStream() async {
selectNotificationStream.stream
.listen((event) => event)
.onData((data) async {
_notificationActionStream.add(data);
switch (data?.notificationResponseType) {
case NotificationResponseType.selectedNotification:
break;
case NotificationResponseType.selectedNotificationAction:
break;
default:
}
});
}
static Future<void> _createNotificationChannels() async {
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(androidChannel);
}
static Future<void> deleteToken() async => _firebaseMessaging.deleteToken();
}
int get createUniqueId =>
DateTime.now().millisecondsSinceEpoch.remainder(100000);
@@ -0,0 +1,54 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
const channelId = 'team_mail_channel_id';
const channelKey = 'team_mail_channel_key';
const channelName = 'Team Mail notifications';
const channelDescription = 'Team Mail notifications';
final iosInitializationSettings = DarwinInitializationSettings(
notificationCategories: [
DarwinNotificationCategory(
channelId,
actions: <DarwinNotificationAction>[
DarwinNotificationAction.plain(
channelKey,
channelName,
options: {
DarwinNotificationActionOption.foreground,
},
),
],
),
],
onDidReceiveLocalNotification:
(int id, String? title, String? body, String? payload) {},
);
const androidInitializationSettings =
AndroidInitializationSettings('background');
const androidChannel = AndroidNotificationChannel(
channelId,
channelName,
description: channelDescription,
importance: Importance.max,
enableLights: true,
);
const pushNotificationDetails = NotificationDetails(
android: AndroidNotificationDetails(
channelId,
channelName,
channelDescription: channelDescription,
visibility: NotificationVisibility.public,
importance: Importance.max,
ledOnMs: 100,
ledOffMs: 1000,
category: AndroidNotificationCategory.message,
),
iOS: DarwinNotificationDetails(
presentSound: true,
presentAlert: true,
presentBadge: true,
),
);
@@ -3,6 +3,7 @@ import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/utils/app_toast.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:model/firebase/firebase_dto.dart';
import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart';
@@ -11,6 +12,8 @@ import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oi
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_account_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/notification_service.dart';
import 'package:tmail_ui_user/features/session/domain/state/get_session_state.dart';
import 'package:tmail_ui_user/features/session/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
@@ -26,6 +29,7 @@ class SessionController extends ReloadableController {
final CachingManager _cachingManager;
final DeleteAuthorityOidcInteractor _deleteAuthorityOidcInteractor;
final AuthorizationInterceptors _authorizationInterceptors;
final SaveFirebaseCacheInteractor _saveFirebaseCacheInteractor;
final AppToast _appToast;
final DynamicUrlInterceptors _dynamicUrlInterceptors;
@@ -40,13 +44,19 @@ class SessionController extends ReloadableController {
this._authorizationInterceptors,
this._appToast,
this._dynamicUrlInterceptors,
this._saveFirebaseCacheInteractor,
) : super(logoutOidcInteractor,
deleteAuthorityOidcInteractor,
getAuthenticatedAccountInteractor);
@override
void onReady() {
Future<void> onReady() async {
super.onReady();
NotificationService.initializeNotificationService(
onDidReceiveNotificationResponse);
NotificationService.onTokenRefresh.listen((token) {
_saveFirebaseCacheInteractor.execute(FirebaseDto(token));
});
final arguments = Get.arguments;
if (arguments != null && arguments is String) {
_getSession();
@@ -24,6 +24,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_a
import 'package:tmail_ui_user/features/login/domain/usecases/get_credential_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_token_oidc_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart';
import 'package:tmail_ui_user/features/session/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/session/presentation/session_controller.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
@@ -44,6 +45,7 @@ class SessionPageBindings extends BaseBindings {
Get.find<AuthorizationInterceptors>(),
Get.find<AppToast>(),
Get.find<DynamicUrlInterceptors>(),
Get.find<SaveFirebaseCacheInteractor>(),
));
}
+11
View File
@@ -1,10 +1,14 @@
import 'package:core/core.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/notification_service.dart';
import 'package:tmail_ui_user/firebase_options.dart';
import 'package:tmail_ui_user/main/bindings/main_bindings.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations_delegate.dart';
@@ -22,6 +26,13 @@ void main() async {
statusBarColor: Colors.black,
statusBarIconBrightness: Brightness.light,
));
try {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
} on FirebaseException catch (e) {
debugPrint(e.toString());
}
await MainBindings().dependencies();
await HiveCacheConfig().setUp();
await HiveCacheConfig.initializeEncryptionKey();
@@ -6,6 +6,7 @@ import 'package:tmail_ui_user/features/caching/authentication_info_cache_client.
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/caching/email_cache_client.dart';
import 'package:tmail_ui_user/features/caching/encryption_key_cache_client.dart';
import 'package:tmail_ui_user/features/caching/firebase_config_cache_client.dart';
import 'package:tmail_ui_user/features/caching/mailbox_cache_client.dart';
import 'package:tmail_ui_user/features/caching/recent_login_url_cache_client.dart';
import 'package:tmail_ui_user/features/caching/recent_login_username_cache_client.dart';
@@ -22,6 +23,7 @@ import 'package:tmail_ui_user/features/login/data/local/oidc_configuration_cache
import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart';
import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart';
import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart';
import 'package:tmail_ui_user/features/push_notification/data/local/firebase_cache_manager.dart';
import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
@@ -55,12 +57,15 @@ class LocalBindings extends Bindings {
Get.put(RecentLoginUrlCacheManager((Get.find<RecentLoginUrlCacheClient>())));
Get.put(RecentLoginUsernameCacheClient());
Get.put(RecentLoginUsernameCacheManager(Get.find<RecentLoginUsernameCacheClient>()));
Get.put(FirebaseCacheClient());
Get.put(FirebaseCacheManager(Get.find<FirebaseCacheClient>()));
Get.put(CachingManager(
Get.find<MailboxCacheClient>(),
Get.find<StateCacheClient>(),
Get.find<EmailCacheClient>(),
Get.find<RecentSearchCacheClient>(),
Get.find<AccountCacheClient>(),
Get.find<FirebaseCacheClient>(),
));
}
+2
View File
@@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/firebase_bindings.dart';
import 'package:tmail_ui_user/main/bindings/core/core_bindings.dart';
import 'package:tmail_ui_user/main/bindings/credential/credential_bindings.dart';
import 'package:tmail_ui_user/main/bindings/local/local_bindings.dart';
@@ -17,5 +18,6 @@ class MainBindings extends Bindings {
CredentialBindings().dependencies();
NetWorkConnectionBindings().dependencies();
SessionBindings().dependencies();
FireBaseBindings().dependencies();
}
}
+10
View File
@@ -0,0 +1,10 @@
import 'package:equatable/equatable.dart';
class FirebaseDto with EquatableMixin {
final String token;
FirebaseDto(this.token);
@override
List<Object?> get props => [token];
}
+99 -8
View File
@@ -8,6 +8,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "47.0.0"
_flutterfire_internals:
dependency: transitive
description:
name: _flutterfire_internals
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.8"
analyzer:
dependency: transitive
description:
@@ -141,6 +148,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
cloud_firestore_platform_interface:
dependency: transitive
description:
name: cloud_firestore_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "5.8.5"
cloud_firestore_web:
dependency: transitive
description:
name: cloud_firestore_web
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.5"
code_builder:
dependency: transitive
description:
@@ -364,9 +385,9 @@ packages:
dependency: transitive
description:
path: "."
ref: email_supported
resolved-ref: "241d7ba620137d6534cc9bbb5fd10e182b93b94a"
url: "https://github.com/linagora/enough_html_editor.git"
ref: "feature/update_inapp_webview"
resolved-ref: a805acd03aae48997b4e9625412a02aff975747e
url: "https://github.com/ManhNTX/enough_html_editor.git"
source: git
version: "0.0.5"
enough_platform_widgets:
@@ -432,6 +453,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "4.5.2"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
firebase_messaging:
dependency: "direct main"
description:
name: firebase_messaging
url: "https://pub.dartlang.org"
source: hosted
version: "14.0.4"
firebase_messaging_platform_interface:
dependency: transitive
description:
name: firebase_messaging_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.6"
firebase_messaging_web:
dependency: transitive
description:
name: firebase_messaging_web
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.6"
fixnum:
dependency: transitive
description:
@@ -524,7 +587,7 @@ packages:
name: flutter_inappwebview
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.3+8"
version: "5.7.1"
flutter_keyboard_visibility:
dependency: transitive
description:
@@ -560,6 +623,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
url: "https://pub.dartlang.org"
source: hosted
version: "12.0.3+1"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
@@ -998,14 +1082,14 @@ packages:
name: permission_handler
url: "https://pub.dartlang.org"
source: hosted
version: "9.2.0"
version: "10.2.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
url: "https://pub.dartlang.org"
source: hosted
version: "9.0.2+1"
version: "10.2.0"
permission_handler_apple:
dependency: transitive
description:
@@ -1110,8 +1194,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: master
resolved-ref: d6c954206ac885a6f269f8be06dfd914a6393e89
ref: demo
resolved-ref: "70cea1832b0e93bce515d4641f96cd1b12366725"
url: "https://github.com/linagora/rich-text-composer.git"
source: git
version: "0.0.1"
@@ -1323,6 +1407,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.2"
timezone:
dependency: transitive
description:
name: timezone
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
timing:
dependency: transitive
description:
+5 -2
View File
@@ -48,7 +48,7 @@ dependencies:
rich_text_composer:
git:
url: https://github.com/linagora/rich-text-composer.git
ref: master
ref: demo
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
@@ -117,7 +117,7 @@ dependencies:
device_info_plus: 4.0.2
# permission_handler
permission_handler: 9.2.0
permission_handler: 10.2.0
# share
share: 2.0.4
@@ -196,6 +196,9 @@ dependencies:
ref: master
url_launcher: 6.1.5
firebase_core: ^2.2.0
firebase_messaging: 14.0.4
flutter_local_notifications: ^12.0.3
dev_dependencies:
flutter_test: