TF-2298 Update expires time when old token has expired

Signed-off-by: dab246 <tdvu@linagora.com>
(cherry picked from commit fb26afe8f52df6e16476aea8a68f9f92c5c4b001)
This commit is contained in:
dab246
2023-12-04 10:53:26 +07:00
committed by Dat H. Pham
parent e3dea129b6
commit f5d878012d
72 changed files with 964 additions and 736 deletions
@@ -0,0 +1,12 @@
import 'package:fcm/model/fcm_token.dart';
import 'package:json_annotation/json_annotation.dart';
class FcmTokenNullableConverter implements JsonConverter<FcmToken?, String?> {
const FcmTokenNullableConverter();
@override
FcmToken? fromJson(String? json) => json != null ? FcmToken(json) : null;
@override
String? toJson(FcmToken? object) => object?.value;
}
@@ -1,20 +0,0 @@
import 'package:fcm/model/firebase_expired_time.dart';
import 'package:jmap_dart_client/http/converter/utc_date_converter.dart';
import 'package:jmap_dart_client/http/converter/utc_date_nullable_converter.dart';
import 'package:json_annotation/json_annotation.dart';
class FirebaseExpiredTimeNullableConverter implements JsonConverter<FirebaseExpiredTime?, String?> {
const FirebaseExpiredTimeNullableConverter();
@override
FirebaseExpiredTime? fromJson(String? json) {
if (json != null) {
return FirebaseExpiredTime(const UTCDateConverter().fromJson(json));
} else {
return null;
}
}
@override
String? toJson(FirebaseExpiredTime? object) => const UTCDateNullableConverter().toJson(object?.value);
}
@@ -0,0 +1,20 @@
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:jmap_dart_client/http/converter/utc_date_converter.dart';
import 'package:jmap_dart_client/http/converter/utc_date_nullable_converter.dart';
import 'package:json_annotation/json_annotation.dart';
class FirebaseRegistrationExpiredTimeNullableConverter implements JsonConverter<FirebaseRegistrationExpiredTime?, String?> {
const FirebaseRegistrationExpiredTimeNullableConverter();
@override
FirebaseRegistrationExpiredTime? fromJson(String? json) {
if (json != null) {
return FirebaseRegistrationExpiredTime(const UTCDateConverter().fromJson(json));
} else {
return null;
}
}
@override
String? toJson(FirebaseRegistrationExpiredTime? object) => const UTCDateNullableConverter().toJson(object?.value);
}
@@ -0,0 +1,13 @@
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:json_annotation/json_annotation.dart';
class FirebaseRegistrationIdNullableConverter implements JsonConverter<FirebaseRegistrationId?, String?> {
const FirebaseRegistrationIdNullableConverter();
@override
FirebaseRegistrationId? fromJson(String? json) => json != null ? FirebaseRegistrationId(Id(json)) : null;
@override
String? toJson(FirebaseRegistrationId? object) => object?.id.value;
}
@@ -1,13 +0,0 @@
import 'package:fcm/model/firebase_subscription_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:json_annotation/json_annotation.dart';
class FirebaseSubscriptionIdNullableConverter implements JsonConverter<FirebaseSubscriptionId?, String?> {
const FirebaseSubscriptionIdNullableConverter();
@override
FirebaseSubscriptionId? fromJson(String? json) => json != null ? FirebaseSubscriptionId(Id(json)) : null;
@override
String? toJson(FirebaseSubscriptionId? object) => object?.id.value;
}
@@ -1,12 +0,0 @@
import 'package:fcm/model/firebase_token.dart';
import 'package:json_annotation/json_annotation.dart';
class FirebaseTokenNullableConverter implements JsonConverter<FirebaseToken?, String?> {
const FirebaseTokenNullableConverter();
@override
FirebaseToken? fromJson(String? json) => json != null ? FirebaseToken(json) : null;
@override
String? toJson(FirebaseToken? object) => object?.value;
}
@@ -7,14 +7,14 @@ import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
import 'package:jmap_dart_client/jmap/core/request/result_reference.dart';
import 'package:json_annotation/json_annotation.dart';
part 'firebase_subscription_get_method.g.dart';
part 'firebase_registration_get_method.g.dart';
@IdConverter()
@PropertiesConverter()
@JsonSerializable(explicitToJson: true)
class FirebaseSubscriptionGetMethod extends GetMethodNoNeedAccountId {
class FirebaseRegistrationGetMethod extends GetMethodNoNeedAccountId {
FirebaseSubscriptionGetMethod() : super();
FirebaseRegistrationGetMethod() : super();
@override
MethodName get methodName => MethodName('FirebaseRegistration/get');
@@ -28,8 +28,8 @@ class FirebaseSubscriptionGetMethod extends GetMethodNoNeedAccountId {
@override
List<Object?> get props => [methodName, ids, requiredCapabilities];
factory FirebaseSubscriptionGetMethod.fromJson(Map<String, dynamic> json) => _$FirebaseSubscriptionGetMethodFromJson(json);
factory FirebaseRegistrationGetMethod.fromJson(Map<String, dynamic> json) => _$FirebaseRegistrationGetMethodFromJson(json);
@override
Map<String, dynamic> toJson() => _$FirebaseSubscriptionGetMethodToJson(this);
Map<String, dynamic> toJson() => _$FirebaseRegistrationGetMethodToJson(this);
}
@@ -0,0 +1,29 @@
import 'package:fcm/model/firebase_registration.dart';
import 'package:jmap_dart_client/http/converter/id_converter.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/response/get_response.dart';
import 'package:json_annotation/json_annotation.dart';
part 'firebase_registration_get_response.g.dart';
@IdConverter()
@JsonSerializable(explicitToJson: true)
class FirebaseRegistrationGetResponse extends GetResponseNoAccountId<FirebaseRegistration> {
FirebaseRegistrationGetResponse(
List<FirebaseRegistration> list,
List<Id>? notFound
) : super(list, notFound);
factory FirebaseRegistrationGetResponse.fromJson(Map<String, dynamic> json) =>
_$FirebaseRegistrationGetResponseFromJson(json);
static FirebaseRegistrationGetResponse deserialize(Map<String, dynamic> json) {
return FirebaseRegistrationGetResponse.fromJson(json);
}
Map<String, dynamic> toJson() => _$FirebaseRegistrationGetResponseToJson(this);
@override
List<Object?> get props => [list, notFound];
}
@@ -1,29 +0,0 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:jmap_dart_client/http/converter/id_converter.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/response/get_response.dart';
import 'package:json_annotation/json_annotation.dart';
part 'firebase_subscription_get_response.g.dart';
@IdConverter()
@JsonSerializable(explicitToJson: true)
class FirebaseSubscriptionGetResponse extends GetResponseNoAccountId<FirebaseSubscription> {
FirebaseSubscriptionGetResponse(
List<FirebaseSubscription> list,
List<Id>? notFound
) : super(list, notFound);
factory FirebaseSubscriptionGetResponse.fromJson(Map<String, dynamic> json) =>
_$FirebaseSubscriptionGetResponseFromJson(json);
static FirebaseSubscriptionGetResponse deserialize(Map<String, dynamic> json) {
return FirebaseSubscriptionGetResponse.fromJson(json);
}
Map<String, dynamic> toJson() => _$FirebaseSubscriptionGetResponseToJson(this);
@override
List<Object?> get props => [list, notFound];
}
@@ -1,4 +1,4 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_capability.dart';
import 'package:jmap_dart_client/http/converter/id_converter.dart';
import 'package:jmap_dart_client/http/converter/set/set_method_properties_converter.dart';
@@ -6,9 +6,9 @@ import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart
import 'package:jmap_dart_client/jmap/core/method/request/set_method.dart';
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
class FirebaseSubscriptionSetMethod extends SetMethodNoNeedAccountId<FirebaseSubscription> {
class FirebaseRegistrationSetMethod extends SetMethodNoNeedAccountId<FirebaseRegistration> {
FirebaseSubscriptionSetMethod() : super();
FirebaseRegistrationSetMethod() : super();
@override
MethodName get methodName => MethodName('FirebaseRegistration/set');
@@ -1,13 +1,13 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:jmap_dart_client/http/converter/id_converter.dart';
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/response/set_response.dart';
class FirebaseSubscriptionSetResponse extends SetResponseNoAccount<FirebaseSubscription> {
FirebaseSubscriptionSetResponse({
Map<Id, FirebaseSubscription>? created,
Map<Id, FirebaseSubscription?>? updated,
class FirebaseRegistrationSetResponse extends SetResponseNoAccount<FirebaseRegistration> {
FirebaseRegistrationSetResponse({
Map<Id, FirebaseRegistration>? created,
Map<Id, FirebaseRegistration?>? updated,
Set<Id>? destroyed,
Map<Id, SetError>? notCreated,
Map<Id, SetError>? notUpdated,
@@ -21,15 +21,15 @@ class FirebaseSubscriptionSetResponse extends SetResponseNoAccount<FirebaseSubsc
notDestroyed: notDestroyed
);
static FirebaseSubscriptionSetResponse deserialize(Map<String, dynamic> json) {
return FirebaseSubscriptionSetResponse(
static FirebaseRegistrationSetResponse deserialize(Map<String, dynamic> json) {
return FirebaseRegistrationSetResponse(
created: (json['created'] as Map<String, dynamic>?)?.map((key, value) => MapEntry(
const IdConverter().fromJson(key),
FirebaseSubscription.fromJson(value as Map<String, dynamic>)
FirebaseRegistration.fromJson(value as Map<String, dynamic>)
)),
updated: (json['updated'] as Map<String, dynamic>?)?.map((key, value) => MapEntry(
const IdConverter().fromJson(key),
value != null ? FirebaseSubscription.fromJson(value as Map<String, dynamic>) : null
value != null ? FirebaseRegistration.fromJson(value as Map<String, dynamic>) : null
)),
destroyed: (json['destroyed'] as List<dynamic>?)?.map((id) => const IdConverter().fromJson(id)).toSet(),
notCreated: (json['notCreated'] as Map<String, dynamic>?)?.map((key, value) => MapEntry(
@@ -1,11 +1,11 @@
import 'package:equatable/equatable.dart';
class FirebaseToken with EquatableMixin {
class FcmToken with EquatableMixin {
final String value;
FirebaseToken(this.value);
FcmToken(this.value);
@override
List<Object?> get props => [value];
+45
View File
@@ -0,0 +1,45 @@
import 'package:equatable/equatable.dart';
import 'package:fcm/converter/device_client_id_nullable_converter.dart';
import 'package:fcm/converter/firebase_registration_expired_time_nullable_converter.dart';
import 'package:fcm/converter/firebase_registration_id_nullable_converter.dart';
import 'package:fcm/converter/fcm_token_nullable_converter.dart';
import 'package:fcm/converter/type_name_converter.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/fcm_token.dart';
import 'package:fcm/model/type_name.dart';
import 'package:json_annotation/json_annotation.dart';
part 'firebase_registration.g.dart';
@DeviceClientIdNullableConverter()
@FirebaseRegistrationIdNullableConverter()
@FcmTokenNullableConverter()
@FirebaseRegistrationExpiredTimeNullableConverter()
@TypeNameConverter()
@JsonSerializable(explicitToJson: true, includeIfNull: false)
class FirebaseRegistration with EquatableMixin {
final FirebaseRegistrationId? id;
final FcmToken? token;
final DeviceClientId? deviceClientId;
final FirebaseRegistrationExpiredTime? expires;
final List<TypeName>? types;
FirebaseRegistration({
this.id,
this.token,
this.deviceClientId,
this.expires,
this.types
});
factory FirebaseRegistration.fromJson(Map<String, dynamic> json) => _$FirebaseRegistrationFromJson(json);
Map<String, dynamic> toJson() => _$FirebaseRegistrationToJson(this);
@override
List<Object?> get props => [id, token, deviceClientId, expires, types];
}
@@ -2,11 +2,11 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
class FirebaseExpiredTime with EquatableMixin {
class FirebaseRegistrationExpiredTime with EquatableMixin {
final UTCDate value;
FirebaseExpiredTime(this.value);
FirebaseRegistrationExpiredTime(this.value);
@override
List<Object?> get props => [value];
@@ -2,11 +2,11 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
class FirebaseSubscriptionId with EquatableMixin {
class FirebaseRegistrationId with EquatableMixin {
final Id id;
FirebaseSubscriptionId(this.id);
FirebaseRegistrationId(this.id);
@override
List<Object?> get props => [id];
-45
View File
@@ -1,45 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:fcm/converter/device_client_id_nullable_converter.dart';
import 'package:fcm/converter/firebase_expired_time_nullable_converter.dart';
import 'package:fcm/converter/firebase_subscription_id_nullable_converter.dart';
import 'package:fcm/converter/firebase_token_nullable_converter.dart';
import 'package:fcm/converter/type_name_converter.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_expired_time.dart';
import 'package:fcm/model/firebase_subscription_id.dart';
import 'package:fcm/model/firebase_token.dart';
import 'package:fcm/model/type_name.dart';
import 'package:json_annotation/json_annotation.dart';
part 'firebase_subscription.g.dart';
@DeviceClientIdNullableConverter()
@FirebaseSubscriptionIdNullableConverter()
@FirebaseTokenNullableConverter()
@FirebaseExpiredTimeNullableConverter()
@TypeNameConverter()
@JsonSerializable(explicitToJson: true, includeIfNull: false)
class FirebaseSubscription with EquatableMixin {
final FirebaseSubscriptionId? id;
final FirebaseToken? token;
final DeviceClientId? deviceClientId;
final FirebaseExpiredTime? expires;
final List<TypeName>? types;
FirebaseSubscription({
this.id,
this.token,
this.deviceClientId,
this.expires,
this.types
});
factory FirebaseSubscription.fromJson(Map<String, dynamic> json) => _$FirebaseSubscriptionFromJson(json);
Map<String, dynamic> toJson() => _$FirebaseSubscriptionToJson(this);
@override
List<Object?> get props => [id, token, deviceClientId, expires, types];
}
@@ -1,10 +1,10 @@
import 'package:dio/dio.dart';
import 'package:fcm/method/get/firebase_subscription_get_method.dart';
import 'package:fcm/method/get/firebase_subscription_get_response.dart';
import 'package:fcm/method/get/firebase_registration_get_method.dart';
import 'package:fcm/method/get/firebase_registration_get_response.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_expired_time.dart';
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/firebase_subscription_id.dart';
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/type_name.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http_mock_adapter/http_mock_adapter.dart';
@@ -14,22 +14,22 @@ import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
void main() {
group('test to json firebase subscription get method', () {
final expectFirebaseSubscription1 = FirebaseSubscription(
id: FirebaseSubscriptionId(Id('e50b2c1d-9553-41a3-b0a7-a7d26b599ee1')),
group('test to json firebase registration get method', () {
final expectFirebaseRegistration1 = FirebaseRegistration(
id: FirebaseRegistrationId(Id('e50b2c1d-9553-41a3-b0a7-a7d26b599ee1')),
deviceClientId: DeviceClientId('b37ff8001ca0'),
expires: FirebaseExpiredTime(UTCDate(DateTime.parse('2018-07-31T00:13:21Z'))),
expires: FirebaseRegistrationExpiredTime(UTCDate(DateTime.parse('2018-07-31T00:13:21Z'))),
types: [TypeName.mailboxType],
);
final expectFirebaseSubscription2 = FirebaseSubscription(
id: FirebaseSubscriptionId(Id('f2d0aab5-e976-4e8b-ad4b-b380a5b987e4')),
final expectFirebaseRegistration2 = FirebaseRegistration(
id: FirebaseRegistrationId(Id('f2d0aab5-e976-4e8b-ad4b-b380a5b987e4')),
deviceClientId: DeviceClientId('X8980fc'),
expires: FirebaseExpiredTime(UTCDate(DateTime.parse('2018-07-12T05:55:00Z'))),
expires: FirebaseRegistrationExpiredTime(UTCDate(DateTime.parse('2018-07-12T05:55:00Z'))),
types: [TypeName.mailboxType, TypeName.emailType, TypeName.emailDelivery],
);
test('firebase subscription get method and response parsing', () async {
test('firebase registration get method and response parsing', () async {
final baseOption = BaseOptions(method: 'POST');
final dio = Dio(baseOption)..options.baseUrl = 'http://domain.com/jmap';
final dioAdapter = DioAdapter(dio: dio);
@@ -84,20 +84,20 @@ void main() {
final processingInvocation = ProcessingInvocation();
final requestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
final firebaseSubscriptionGetMethod = FirebaseSubscriptionGetMethod();
final firebaseSubscriptionGetInvocation = requestBuilder.invocation(firebaseSubscriptionGetMethod);
final firebaseRegistrationGetMethod = FirebaseRegistrationGetMethod();
final firebaseRegistrationGetInvocation = requestBuilder.invocation(firebaseRegistrationGetMethod);
final response = await (requestBuilder
..usings(firebaseSubscriptionGetMethod.requiredCapabilities))
..usings(firebaseRegistrationGetMethod.requiredCapabilities))
.build()
.execute();
final resultList = response.parse<FirebaseSubscriptionGetResponse>(
firebaseSubscriptionGetInvocation.methodCallId,
FirebaseSubscriptionGetResponse.deserialize
final resultList = response.parse<FirebaseRegistrationGetResponse>(
firebaseRegistrationGetInvocation.methodCallId,
FirebaseRegistrationGetResponse.deserialize
);
expect(resultList?.list.length, equals(2));
expect(resultList?.list, containsAll([expectFirebaseSubscription1, expectFirebaseSubscription2]));
expect(resultList?.list, containsAll([expectFirebaseRegistration1, expectFirebaseRegistration2]));
});
});
}
@@ -1,11 +1,11 @@
import 'package:dio/dio.dart';
import 'package:fcm/method/set/firebase_subscription_set_method.dart';
import 'package:fcm/method/set/firebase_subscription_set_response.dart';
import 'package:fcm/method/set/firebase_registration_set_method.dart';
import 'package:fcm/method/set/firebase_registration_set_response.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_expired_time.dart';
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/firebase_subscription_id.dart';
import 'package:fcm/model/firebase_token.dart';
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/fcm_token.dart';
import 'package:fcm/model/type_name.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http_mock_adapter/http_mock_adapter.dart';
@@ -15,13 +15,13 @@ import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
void main() {
group('test to json firebase subscription set method', () {
final expectedFirebaseSubscriptionCreated = FirebaseSubscription(
id: FirebaseSubscriptionId(Id('175dbd70-93d1-11ec-984e-e3f8b83572b4')),
expires: FirebaseExpiredTime(UTCDate(DateTime.parse('2022-03-31T02:14:29Z'))),
group('test to json firebase registration set method', () {
final expectedFirebaseRegistrationCreated = FirebaseRegistration(
id: FirebaseRegistrationId(Id('175dbd70-93d1-11ec-984e-e3f8b83572b4')),
expires: FirebaseRegistrationExpiredTime(UTCDate(DateTime.parse('2022-03-31T02:14:29Z'))),
);
test('firebase subscription set method and response parsing', () async {
test('firebase registration set method and response parsing', () async {
final baseOption = BaseOptions(method: 'POST');
final dio = Dio(baseOption)
..options.baseUrl = 'http://domain.com/jmap';
@@ -75,31 +75,31 @@ void main() {
final createRequestId = Id('dab246');
final firebaseSubscriptionSetMethod = FirebaseSubscriptionSetMethod()
final firebaseRegistrationSetMethod = FirebaseRegistrationSetMethod()
..addCreate(
createRequestId,
FirebaseSubscription(
FirebaseRegistration(
deviceClientId: DeviceClientId('a123-b123-c123'),
token: FirebaseToken('token1'),
token: FcmToken('token1'),
types: [TypeName.mailboxType]
)
);
final httpClient = HttpClient(dio);
final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation());
final firebaseSubscriptionSetInvocation = requestBuilder.invocation(firebaseSubscriptionSetMethod);
final firebaseRegistrationSetInvocation = requestBuilder.invocation(firebaseRegistrationSetMethod);
final response = await (requestBuilder
..usings(firebaseSubscriptionSetMethod.requiredCapabilities))
..usings(firebaseRegistrationSetMethod.requiredCapabilities))
.build()
.execute();
final firebaseSubscriptionSetResponse = response.parse<FirebaseSubscriptionSetResponse>(
firebaseSubscriptionSetInvocation.methodCallId,
FirebaseSubscriptionSetResponse.deserialize);
final firebaseRegistrationSetResponse = response.parse<FirebaseRegistrationSetResponse>(
firebaseRegistrationSetInvocation.methodCallId,
FirebaseRegistrationSetResponse.deserialize);
expect(
firebaseSubscriptionSetResponse!.created![createRequestId]!.id,
equals(expectedFirebaseSubscriptionCreated.id)
firebaseRegistrationSetResponse!.created![createRequestId]!.id,
equals(expectedFirebaseRegistrationCreated.id)
);
});
});
+24 -23
View File
@@ -12,6 +12,7 @@ import 'package:core/utils/fps_manager.dart';
import 'package:core/utils/platform_info.dart';
import 'package:dartz/dartz.dart';
import 'package:fcm/model/firebase_capability.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:forward/forward/capability_forward.dart';
@@ -38,10 +39,10 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oi
import 'package:tmail_ui_user/features/manage_account/presentation/email_rules/bindings/email_rules_interactor_bindings.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/forward/bindings/forwarding_interactors_bindings.dart';
import 'package:tmail_ui_user/features/push_notification/domain/exceptions/fcm_exception.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/destroy_subscription_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_fcm_subscription_local.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/destroy_subscription_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_fcm_subscription_local_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/destroy_firebase_registration_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_stored_firebase_registration_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/destroy_firebase_registration_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_stored_firebase_registration_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/config/fcm_configuration.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/controller/fcm_message_controller.dart';
@@ -76,8 +77,8 @@ abstract class BaseController extends GetxController
final _fcmReceiver = FcmReceiver.instance;
bool _isFcmEnabled = false;
GetFCMSubscriptionLocalInteractor? _getSubscriptionLocalInteractor;
DestroySubscriptionInteractor? _destroySubscriptionInteractor;
GetStoredFirebaseRegistrationInteractor? _getStoredFirebaseRegistrationInteractor;
DestroyFirebaseRegistrationInteractor? _destroyFirebaseRegistrationInteractor;
final viewState = Rx<Either<Failure, Success>>(Right(UIState.idle));
FpsCallback? fpsCallback;
@@ -180,12 +181,12 @@ abstract class BaseController extends GetxController
logError('BaseController::handleFailureViewState(): ${failure.runtimeType}');
if (failure is LogoutOidcFailure) {
if (_isFcmEnabled) {
_getSubscriptionLocalAction();
_getStoredFirebaseRegistrationFromCache();
} else {
await clearDataAndGoToLoginPage();
}
} else if (failure is GetFCMSubscriptionLocalFailure ||
failure is DestroySubscriptionFailure) {
} else if (failure is GetStoredFirebaseRegistrationFailure ||
failure is DestroyFirebaseRegistrationFailure) {
await clearDataAndGoToLoginPage();
}
}
@@ -194,13 +195,13 @@ abstract class BaseController extends GetxController
log('BaseController::handleSuccessViewState(): ${success.runtimeType}');
if (success is LogoutOidcSuccess) {
if (_isFcmEnabled) {
_getSubscriptionLocalAction();
_getStoredFirebaseRegistrationFromCache();
} else {
await clearDataAndGoToLoginPage();
}
} else if (success is GetFCMSubscriptionLocalSuccess) {
_destroySubscriptionAction(success.fcmSubscription.subscriptionId);
} else if (success is DestroySubscriptionSuccess) {
} else if (success is GetStoredFirebaseRegistrationSuccess) {
_destroyFirebaseRegistration(success.firebaseRegistration.id!);
} else if (success is DestroyFirebaseRegistrationSuccess) {
await clearDataAndGoToLoginPage();
}
}
@@ -265,7 +266,7 @@ abstract class BaseController extends GetxController
if (AppConfig.fcmAvailable) {
final mapEnvData = Map<String, String>.from(dotenv.env);
await AppUtils.loadFcmConfigFileToEnv(currentMapEnvData: mapEnvData);
FcmConfiguration.initialize();
await FcmConfiguration.initialize();
FcmInteractorBindings().dependencies();
FcmMessageController.instance.initializeFromAccountId(accountId, session);
} else {
@@ -299,26 +300,26 @@ abstract class BaseController extends GetxController
consumeState(logoutOidcInteractor.execute());
} else {
if (_isFcmEnabled) {
_getSubscriptionLocalAction();
_getStoredFirebaseRegistrationFromCache();
} else {
await clearDataAndGoToLoginPage();
}
}
}
void _destroySubscriptionAction(String subscriptionId) async {
_destroySubscriptionInteractor = getBinding<DestroySubscriptionInteractor>();
if (_destroySubscriptionInteractor != null) {
consumeState(_destroySubscriptionInteractor!.execute(subscriptionId));
void _destroyFirebaseRegistration(FirebaseRegistrationId firebaseRegistrationId) async {
_destroyFirebaseRegistrationInteractor = getBinding<DestroyFirebaseRegistrationInteractor>();
if (_destroyFirebaseRegistrationInteractor != null) {
consumeState(_destroyFirebaseRegistrationInteractor!.execute(firebaseRegistrationId));
} else {
await clearDataAndGoToLoginPage();
}
}
void _getSubscriptionLocalAction() async {
_getSubscriptionLocalInteractor = getBinding<GetFCMSubscriptionLocalInteractor>();
if (_getSubscriptionLocalInteractor != null) {
consumeState(_getSubscriptionLocalInteractor!.execute());
void _getStoredFirebaseRegistrationFromCache() async {
_getStoredFirebaseRegistrationInteractor = getBinding<GetStoredFirebaseRegistrationInteractor>();
if (_getStoredFirebaseRegistrationInteractor != null) {
consumeState(_getStoredFirebaseRegistrationInteractor!.execute());
} else {
await clearDataAndGoToLoginPage();
}
+5 -5
View File
@@ -14,7 +14,7 @@ import 'package:tmail_ui_user/features/caching/clients/hive_cache_version_client
import 'package:tmail_ui_user/features/caching/clients/mailbox_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/recent_search_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/state_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/subscription_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/firebase_registration_cache_client.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_spam_report_manager.dart';
@@ -28,7 +28,7 @@ class CachingManager {
final RecentSearchCacheClient _recentSearchCacheClient;
final AccountCacheClient _accountCacheClient;
final FcmCacheClient _fcmCacheClient;
final FCMSubscriptionCacheClient _fcmSubscriptionCacheClient;
final FirebaseRegistrationCacheClient _firebaseRegistrationCacheClient;
final HiveCacheVersionClient _hiveCacheVersionClient;
final NewEmailHiveCacheClient _newEmailHiveCacheClient;
final OpenedEmailHiveCacheClient _openedEmailHiveCacheClient;
@@ -44,7 +44,7 @@ class CachingManager {
this._recentSearchCacheClient,
this._accountCacheClient,
this._fcmCacheClient,
this._fcmSubscriptionCacheClient,
this._firebaseRegistrationCacheClient,
this._hiveCacheVersionClient,
this._newEmailHiveCacheClient,
this._openedEmailHiveCacheClient,
@@ -60,7 +60,7 @@ class CachingManager {
_mailboxCacheClient.clearAllData(),
_emailCacheClient.clearAllData(),
_fcmCacheClient.clearAllData(),
_fcmSubscriptionCacheClient.clearAllData(),
_firebaseRegistrationCacheClient.clearAllData(),
_recentSearchCacheClient.clearAllData(),
_accountCacheClient.clearAllData(),
_localSpamReportManager.clear(),
@@ -80,7 +80,7 @@ class CachingManager {
_mailboxCacheClient.clearAllData(),
_emailCacheClient.clearAllData(),
_fcmCacheClient.clearAllData(),
_fcmSubscriptionCacheClient.clearAllData(),
_firebaseRegistrationCacheClient.clearAllData(),
_recentSearchCacheClient.clearAllData(),
_localSpamReportManager.clear(),
if (PlatformInfo.isMobile)
@@ -0,0 +1,10 @@
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_registration_cache.dart';
class FirebaseRegistrationCacheClient extends HiveCacheClient<FirebaseRegistrationCache> {
@override
String get tableName => CachingConstants.firebaseRegistrationCacheBoxName;
}
@@ -1,9 +0,0 @@
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
class FCMSubscriptionCacheClient extends HiveCacheClient<FCMSubscriptionCache> {
@override
String get tableName => 'FCMSubscriptionCache';
}
@@ -26,7 +26,7 @@ import 'package:tmail_ui_user/features/offline_mode/model/attachment_hive_cache.
import 'package:tmail_ui_user/features/offline_mode/model/detailed_email_hive_cache.dart';
import 'package:tmail_ui_user/features/offline_mode/model/email_header_hive_cache.dart';
import 'package:tmail_ui_user/features/offline_mode/model/sending_email_hive_cache.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_registration_cache.dart';
import 'package:tmail_ui_user/features/thread/data/model/email_address_hive_cache.dart';
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart';
@@ -145,9 +145,9 @@ class HiveCacheConfig {
RecentLoginUsernameCacheAdapter(),
CachingConstants.RECENT_LOGIN_USERNAME_HIVE_CACHE_IDENTITY
);
registerCacheAdapter<FCMSubscriptionCache>(
FCMSubscriptionCacheAdapter(),
CachingConstants.FCM_SUBSCRIPTION_HIVE_CACHE_IDENTITY
registerCacheAdapter<FirebaseRegistrationCache>(
FirebaseRegistrationCacheAdapter(),
CachingConstants.FIREBASE_REGISTRATION_HIVE_CACHE_IDENTITY
);
registerCacheAdapter<AttachmentHiveCache>(
AttachmentHiveCacheAdapter(),
@@ -13,7 +13,7 @@ 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 FCM_SUBSCRIPTION_HIVE_CACHE_IDENTITY = 14;
static const int FIREBASE_REGISTRATION_HIVE_CACHE_IDENTITY = 14;
static const int ATTACHMENT_HIVE_CACHE_ID = 15;
static const int EMAIL_HEADER_HIVE_CACHE_ID = 16;
static const int DETAILED_EMAIL_HIVE_CACHE_ID = 17;
@@ -25,6 +25,7 @@ class CachingConstants {
static const String openedEmailCacheBoxName = 'opened_email_cache_box';
static const String sendingEmailCacheBoxName = 'sending_email_cache_box';
static const String sessionCacheBoxName = 'session_cache_box';
static const String firebaseRegistrationCacheBoxName = 'firebase_registration_cache_box';
static const String newEmailsContentFolderName = 'new_emails';
static const String openedEmailContentFolderName = 'opened_email';
@@ -1,11 +1,13 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/type_name.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
abstract class FCMDatasource {
Future<void> storeStateToRefresh(AccountId accountId, UserName userName, TypeName typeName, jmap.State newState);
@@ -14,13 +16,17 @@ abstract class FCMDatasource {
Future<void> deleteStateToRefresh(AccountId accountId, UserName userName, TypeName typeName);
Future<void> storeSubscription(FCMSubscriptionCache fcmSubscriptionCache);
Future<void> storeFirebaseRegistration(FirebaseRegistration firebaseRegistration);
Future<FirebaseSubscription> getFirebaseSubscriptionByDeviceId(String deviceId);
Future<FirebaseRegistration> getFirebaseRegistrationByDeviceId(DeviceClientId deviceId);
Future<FirebaseSubscription> registerNewToken(RegisterNewTokenRequest newTokenRequest);
Future<FirebaseRegistration> registerNewFirebaseRegistrationToken(RegisterNewTokenRequest newTokenRequest);
Future<FCMSubscriptionCache> geSubscription();
Future<FirebaseRegistration> getStoredFirebaseRegistration();
Future<bool> destroySubscription(String subscriptionId);
Future<void> deleteFirebaseRegistrationCache();
Future<void> destroyFirebaseRegistration(FirebaseRegistrationId registrationId);
Future<void> updateFirebaseRegistrationToken(UpdateTokenExpiredTimeRequest expiredTimeRequest);
}
@@ -1,12 +1,16 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/type_name.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource/fcm_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/data/extensions/firebase_registration_cache_extension.dart';
import 'package:tmail_ui_user/features/push_notification/data/extensions/firebase_registration_extension.dart';
import 'package:tmail_ui_user/features/push_notification/data/local/fcm_cache_manager.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
class CacheFCMDatasourceImpl extends FCMDatasource {
@@ -38,31 +42,44 @@ class CacheFCMDatasourceImpl extends FCMDatasource {
}
@override
Future<FirebaseSubscription> getFirebaseSubscriptionByDeviceId(String deviceId) {
Future<FirebaseRegistration> getFirebaseRegistrationByDeviceId(DeviceClientId deviceId) {
throw UnimplementedError();
}
@override
Future<FirebaseSubscription> registerNewToken(RegisterNewTokenRequest newTokenRequest) {
Future<FirebaseRegistration> registerNewFirebaseRegistrationToken(RegisterNewTokenRequest newTokenRequest) {
throw UnimplementedError();
}
@override
Future<void> storeSubscription(FCMSubscriptionCache fcmSubscriptionCache) {
Future<void> storeFirebaseRegistration(FirebaseRegistration firebaseRegistration) {
return Future.sync(() async {
return await _firebaseCacheManager.storeSubscription(fcmSubscriptionCache);
return await _firebaseCacheManager.storeFirebaseRegistration(firebaseRegistration.toFirebaseRegistrationCache());
}).catchError(_exceptionThrower.throwException);
}
@override
Future<FCMSubscriptionCache> geSubscription() {
Future<FirebaseRegistration> getStoredFirebaseRegistration() {
return Future.sync(() async {
return await _firebaseCacheManager.getSubscription();
final firebaseRegistrationCache = await _firebaseCacheManager.getStoredFirebaseRegistration();
return firebaseRegistrationCache.toFirebaseRegistration();
}).catchError(_exceptionThrower.throwException);
}
@override
Future<bool> destroySubscription(String subscriptionId) {
Future<void> destroyFirebaseRegistration(FirebaseRegistrationId registrationId) {
throw UnimplementedError();
}
@override
Future<void> updateFirebaseRegistrationToken(UpdateTokenExpiredTimeRequest expiredTimeRequest) {
throw UnimplementedError();
}
@override
Future<void> deleteFirebaseRegistrationCache() {
return Future.sync(() async {
return await _firebaseCacheManager.deleteFirebaseRegistration();
}).catchError(_exceptionThrower.throwException);
}
}
@@ -1,13 +1,15 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/type_name.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource/fcm_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/data/network/fcm_api.dart';
import 'package:tmail_ui_user/features/push_notification/domain/extensions/firebase_subscription_extension.dart';
import 'package:tmail_ui_user/features/push_notification/domain/extensions/firebase_registration_extension.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
class FcmDatasourceImpl extends FCMDatasource {
@@ -18,9 +20,9 @@ class FcmDatasourceImpl extends FCMDatasource {
FcmDatasourceImpl(this._fcmApi, this._exceptionThrower);
@override
Future<FirebaseSubscription> getFirebaseSubscriptionByDeviceId(String deviceId) {
Future<FirebaseRegistration> getFirebaseRegistrationByDeviceId(DeviceClientId deviceId) {
return Future.sync(() async {
return await _fcmApi.getFirebaseSubscriptionByDeviceId(deviceId);
return await _fcmApi.getFirebaseRegistrationByDeviceId(deviceId);
}).catchError(_exceptionThrower.throwException);
}
@@ -40,27 +42,43 @@ class FcmDatasourceImpl extends FCMDatasource {
}
@override
Future<FirebaseSubscription> registerNewToken(RegisterNewTokenRequest newTokenRequest) {
Future<FirebaseRegistration> registerNewFirebaseRegistrationToken(RegisterNewTokenRequest newTokenRequest) {
return Future.sync(() async {
final firebaseSubscription = await _fcmApi.registerNewToken(newTokenRequest);
return firebaseSubscription.fromDeviceId(newDeviceId: newTokenRequest.firebaseSubscription.deviceClientId);
final registrationCreated = await _fcmApi.registerNewFirebaseRegistrationToken(newTokenRequest);
return registrationCreated.syncProperties(
newDeviceId: newTokenRequest.firebaseRegistration.deviceClientId,
newFcmToken: newTokenRequest.firebaseRegistration.token,
newTypes: newTokenRequest.firebaseRegistration.types,
);
}).catchError(_exceptionThrower.throwException);
}
@override
Future<bool> storeSubscription(FCMSubscriptionCache fcmSubscriptionCache) {
Future<bool> storeFirebaseRegistration(FirebaseRegistration firebaseRegistration) {
throw UnimplementedError();
}
@override
Future<FCMSubscriptionCache> geSubscription() {
Future<FirebaseRegistration> getStoredFirebaseRegistration() {
throw UnimplementedError();
}
@override
Future<bool> destroySubscription(String subscriptionId) {
Future<void> destroyFirebaseRegistration(FirebaseRegistrationId registrationId) {
return Future.sync(() async {
return await _fcmApi.destroySubscription(subscriptionId);
return await _fcmApi.destroyFirebaseRegistration(registrationId);
}).catchError(_exceptionThrower.throwException);
}
@override
Future<void> updateFirebaseRegistrationToken(UpdateTokenExpiredTimeRequest expiredTimeRequest) {
return Future.sync(() async {
return await _fcmApi.updateFirebaseRegistrationToken(expiredTimeRequest);
}).catchError(_exceptionThrower.throwException);
}
@override
Future<void> deleteFirebaseRegistrationCache() {
throw UnimplementedError();
}
}
@@ -1,10 +0,0 @@
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart';
extension FCMSubscriptionExtension on FCMSubscription {
FCMSubscriptionCache toFCMSubscriptionCache() {
return FCMSubscriptionCache(deviceId, subscriptionId);
}
}
@@ -0,0 +1,20 @@
import 'package:fcm/converter/device_client_id_nullable_converter.dart';
import 'package:fcm/converter/fcm_token_nullable_converter.dart';
import 'package:fcm/converter/firebase_registration_id_nullable_converter.dart';
import 'package:fcm/converter/type_name_converter.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_registration_cache.dart';
extension FirebaseRegistrationCacheExtension on FirebaseRegistrationCache {
FirebaseRegistration toFirebaseRegistration() {
return FirebaseRegistration(
id: const FirebaseRegistrationIdNullableConverter().fromJson(id),
token: const FcmTokenNullableConverter().fromJson(token),
deviceClientId: const DeviceClientIdNullableConverter().fromJson(deviceClientId),
expires: expires != null ? FirebaseRegistrationExpiredTime(UTCDate(expires!)) : null,
types: types?.map((type) => const TypeNameConverter().fromJson(type)).toList()
);
}
}
@@ -0,0 +1,14 @@
import 'package:fcm/model/firebase_registration.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_registration_cache.dart';
extension FirebaseRegistrationExtension on FirebaseRegistration {
FirebaseRegistrationCache toFirebaseRegistrationCache() {
return FirebaseRegistrationCache(
deviceClientId: deviceClientId!.value,
id: id?.id.value,
token: token?.value,
expires: expires?.value.value,
types: types?.map((type) => type.value).toList(),
);
}
}
@@ -3,17 +3,17 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:model/extensions/account_id_extensions.dart';
import 'package:tmail_ui_user/features/caching/clients/fcm_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/subscription_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/firebase_registration_cache_client.dart';
import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/data/model/firebase_registration_cache.dart';
import 'package:tmail_ui_user/features/push_notification/domain/exceptions/fcm_exception.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
class FCMCacheManager {
final FcmCacheClient _fcmCacheClient;
final FCMSubscriptionCacheClient _fcmSubscriptionCacheClient;
final FirebaseRegistrationCacheClient _firebaseRegistrationCacheClient;
FCMCacheManager(this._fcmCacheClient,this._fcmSubscriptionCacheClient);
FCMCacheManager(this._fcmCacheClient,this._firebaseRegistrationCacheClient);
Future<void> storeStateToRefresh(AccountId accountId, UserName userName, TypeName typeName, jmap.State newState) {
final stateKeyCache = TupleKey(typeName.value, accountId.asString, userName.value).encodeKey;
@@ -43,17 +43,23 @@ class FCMCacheManager {
return _fcmCacheClient.clearAllData();
}
Future<void> storeSubscription(FCMSubscriptionCache fcmSubscriptionCache) {
return _fcmSubscriptionCacheClient.insertItem(
FCMSubscriptionCache.keyCacheValue, fcmSubscriptionCache);
Future<void> storeFirebaseRegistration(FirebaseRegistrationCache firebaseRegistrationCache) {
return _firebaseRegistrationCacheClient.insertItem(
FirebaseRegistrationCache.keyCacheValue,
firebaseRegistrationCache
);
}
Future<FCMSubscriptionCache> getSubscription() async {
final fcmSubscription = await _fcmSubscriptionCacheClient.getItem(FCMSubscriptionCache.keyCacheValue);
if (fcmSubscription == null) {
throw NotFoundSubscriptionException();
Future<FirebaseRegistrationCache> getStoredFirebaseRegistration() async {
final firebaseRegistration = await _firebaseRegistrationCacheClient.getItem(FirebaseRegistrationCache.keyCacheValue);
if (firebaseRegistration == null) {
throw NotFoundFirebaseRegistrationCacheException();
} else {
return fcmSubscription;
return firebaseRegistration;
}
}
Future<void> deleteFirebaseRegistration() async {
await _firebaseRegistrationCacheClient.deleteItem(FirebaseRegistrationCache.keyCacheValue);
}
}
@@ -1,23 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:hive/hive.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
part 'fcm_subscription.g.dart';
@HiveType(typeId: CachingConstants.FCM_SUBSCRIPTION_HIVE_CACHE_IDENTITY)
class FCMSubscriptionCache extends HiveObject with EquatableMixin {
static const String keyCacheValue = 'fcmSubscriptionCache';
@HiveField(0)
final String deviceId;
@HiveField(1)
final String subscriptionId;
FCMSubscriptionCache(this.deviceId, this.subscriptionId);
@override
List<Object?> get props => [deviceId, subscriptionId];
}
@@ -0,0 +1,44 @@
import 'package:equatable/equatable.dart';
import 'package:hive/hive.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
part 'firebase_registration_cache.g.dart';
@HiveType(typeId: CachingConstants.FIREBASE_REGISTRATION_HIVE_CACHE_IDENTITY)
class FirebaseRegistrationCache extends HiveObject with EquatableMixin {
static const String keyCacheValue = 'firebaseRegistrationCache';
@HiveField(0)
final String deviceClientId;
@HiveField(1)
final String? id;
@HiveField(2)
final String? token;
@HiveField(3)
final DateTime? expires;
@HiveField(4)
final List<String>? types;
FirebaseRegistrationCache({
required this.deviceClientId,
this.id,
this.token,
this.expires,
this.types
});
@override
List<Object?> get props => [
deviceClientId,
id,
token,
expires,
types
];
}
@@ -1,16 +1,19 @@
import 'package:fcm/method/set/firebase_subscription_set_method.dart';
import 'package:fcm/method/set/firebase_subscription_set_response.dart';
import 'package:fcm/method/get/firebase_subscription_get_method.dart';
import 'package:fcm/method/get/firebase_subscription_get_response.dart';
import 'package:fcm/model/firebase_capability.dart';
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/converter/firebase_registration_expired_time_nullable_converter.dart';
import 'package:fcm/method/set/firebase_registration_set_method.dart';
import 'package:fcm/method/set/firebase_registration_set_response.dart';
import 'package:fcm/method/get/firebase_registration_get_method.dart';
import 'package:fcm/method/get/firebase_registration_get_response.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/patch_object.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/exceptions/fcm_exception.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/utils/fcm_constants.dart';
class FcmApi {
@@ -18,76 +21,105 @@ class FcmApi {
FcmApi(this._httpClient);
Future<FirebaseSubscription> getFirebaseSubscriptionByDeviceId(String deviceId) async {
Future<FirebaseRegistration> getFirebaseRegistrationByDeviceId(DeviceClientId deviceId) async {
final processingInvocation = ProcessingInvocation();
final requestBuilder = JmapRequestBuilder(_httpClient, processingInvocation);
final firebaseSubscriptionGetMethod = FirebaseSubscriptionGetMethod();
final firebaseSubscriptionGetInvocation = requestBuilder.invocation(firebaseSubscriptionGetMethod);
final firebaseRegistrationGetMethod = FirebaseRegistrationGetMethod();
final firebaseRegistrationGetInvocation = requestBuilder.invocation(firebaseRegistrationGetMethod);
final response = await (requestBuilder
..usings(firebaseSubscriptionGetMethod.requiredCapabilities))
..usings(firebaseRegistrationGetMethod.requiredCapabilities))
.build()
.execute();
final getResponse = response.parse<FirebaseSubscriptionGetResponse>(
firebaseSubscriptionGetInvocation.methodCallId,
FirebaseSubscriptionGetResponse.deserialize);
final getResponse = response.parse<FirebaseRegistrationGetResponse>(
firebaseRegistrationGetInvocation.methodCallId,
FirebaseRegistrationGetResponse.deserialize);
final matchedFirebaseSubscription = getResponse?.list
.where((fcmSub) => fcmSub.deviceClientId?.value == deviceId)
final matchedFirebaseRegistration = getResponse?.list
.where((fcmSub) => fcmSub.deviceClientId == deviceId)
.toList();
if (matchedFirebaseSubscription?.isNotEmpty == true) {
return matchedFirebaseSubscription!.first;
if (matchedFirebaseRegistration?.isNotEmpty == true) {
return matchedFirebaseRegistration!.first;
} else {
throw NotFoundFirebaseSubscriptionException();
throw NotFoundFirebaseRegistrationForDeviceException();
}
}
Future<FirebaseSubscription> registerNewToken(RegisterNewTokenRequest newTokenRequest) async {
Future<FirebaseRegistration> registerNewFirebaseRegistrationToken(RegisterNewTokenRequest newTokenRequest) async {
final processingInvocation = ProcessingInvocation();
final requestBuilder = JmapRequestBuilder(_httpClient, processingInvocation);
final firebaseSubscriptionSetMethod = FirebaseSubscriptionSetMethod()
final firebaseRegistrationSetMethod = FirebaseRegistrationSetMethod()
..addCreate(
newTokenRequest.createRequestId,
newTokenRequest.firebaseSubscription
newTokenRequest.firebaseRegistration
);
final firebaseSubscriptionSetInvocation = requestBuilder.invocation(firebaseSubscriptionSetMethod);
final firebaseRegistrationSetInvocation = requestBuilder.invocation(firebaseRegistrationSetMethod);
final response = await (requestBuilder
..usings(firebaseSubscriptionSetMethod.requiredCapabilities))
..usings(firebaseRegistrationSetMethod.requiredCapabilities))
.build()
.execute();
final firebaseSubscriptionSetResponse = response.parse<FirebaseSubscriptionSetResponse>(
firebaseSubscriptionSetInvocation.methodCallId,
FirebaseSubscriptionSetResponse.deserialize);
final firebaseRegistrationSetResponse = response.parse<FirebaseRegistrationSetResponse>(
firebaseRegistrationSetInvocation.methodCallId,
FirebaseRegistrationSetResponse.deserialize);
return firebaseSubscriptionSetResponse!.created![newTokenRequest.createRequestId]!;
final firebaseRegistration = firebaseRegistrationSetResponse?.created?[newTokenRequest.createRequestId];
if (firebaseRegistration != null) {
return firebaseRegistration;
} else {
throw NotFoundFirebaseRegistrationCreatedException();
}
}
Future<bool> destroySubscription(String subscriptionId) async {
Future<void> destroyFirebaseRegistration(FirebaseRegistrationId registrationId) async {
final processingInvocation = ProcessingInvocation();
final requestBuilder = JmapRequestBuilder(_httpClient, processingInvocation);
final firebaseSubscriptionSetMethod = FirebaseSubscriptionSetMethod()..addDestroy({Id(subscriptionId)});
final firebaseSubscriptionSetInvocation = requestBuilder.invocation(firebaseSubscriptionSetMethod);
final firebaseRegistrationSetMethod = FirebaseRegistrationSetMethod()..addDestroy({registrationId.id});
final firebaseRegistrationSetInvocation = requestBuilder.invocation(firebaseRegistrationSetMethod);
final response = await (requestBuilder
..usings({
CapabilityIdentifier.jmapCore,
FirebaseCapability.fcmIdentifier,
}))
..usings(firebaseRegistrationSetMethod.requiredCapabilities))
.build()
.execute();
final firebaseSubscriptionSetResponse = response.parse<FirebaseSubscriptionSetResponse>(
firebaseSubscriptionSetInvocation.methodCallId,
FirebaseSubscriptionSetResponse.deserialize);
final firebaseRegistrationSetResponse = response.parse<FirebaseRegistrationSetResponse>(
firebaseRegistrationSetInvocation.methodCallId,
FirebaseRegistrationSetResponse.deserialize);
return Future.sync(() async {
return firebaseSubscriptionSetResponse?.destroyed?.contains(Id(subscriptionId)) == true;
}).catchError((error) {
throw error;
});
if (firebaseRegistrationSetResponse?.destroyed?.contains(registrationId.id) == true) {
return;
} else {
throw NotFoundFirebaseRegistrationDestroyedException();
}
}
Future<void> updateFirebaseRegistrationToken(UpdateTokenExpiredTimeRequest expiredTimeRequest) async {
final processingInvocation = ProcessingInvocation();
final requestBuilder = JmapRequestBuilder(_httpClient, processingInvocation);
final firebaseRegistrationSetMethod = FirebaseRegistrationSetMethod()
..addUpdates({
expiredTimeRequest.firebaseRegistrationId.id: PatchObject({
FcmConstants.firebaseRegistrationExpiredTimeProperty: const FirebaseRegistrationExpiredTimeNullableConverter().toJson(expiredTimeRequest.firebaseRegistrationExpiredTime)
})
});
final firebaseRegistrationSetInvocation = requestBuilder.invocation(firebaseRegistrationSetMethod);
final response = await (requestBuilder
..usings(firebaseRegistrationSetMethod.requiredCapabilities))
.build()
.execute();
final firebaseRegistrationSetResponse = response.parse<FirebaseRegistrationSetResponse>(
firebaseRegistrationSetInvocation.methodCallId,
FirebaseRegistrationSetResponse.deserialize);
if (firebaseRegistrationSetResponse?.updated?.containsKey(expiredTimeRequest.firebaseRegistrationId.id) == true) {
return;
} else {
throw NotFoundFirebaseRegistrationUpdatedException();
}
}
}
@@ -1,6 +1,8 @@
import 'package:core/data/model/source_type/data_source_type.dart';
import 'package:core/utils/app_logger.dart';
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/type_name.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
@@ -15,10 +17,9 @@ import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/data/datasource/fcm_datasource.dart';
import 'package:tmail_ui_user/features/push_notification/data/extensions/fcm_subscription_extensions.dart';
import 'package:tmail_ui_user/features/push_notification/domain/exceptions/fcm_exception.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/utils/fcm_constants.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
@@ -94,29 +95,28 @@ class FCMRepositoryImpl extends FCMRepository {
}
@override
Future<FirebaseSubscription> getFirebaseSubscriptionByDeviceId(String deviceId) {
return _fcmDatasource[DataSourceType.network]!.getFirebaseSubscriptionByDeviceId(deviceId);
Future<FirebaseRegistration> getFirebaseRegistrationByDeviceId(DeviceClientId deviceId) {
return _fcmDatasource[DataSourceType.network]!.getFirebaseRegistrationByDeviceId(deviceId);
}
@override
Future<FirebaseSubscription> registerNewToken(RegisterNewTokenRequest newTokenRequest) {
return _fcmDatasource[DataSourceType.network]!.registerNewToken(newTokenRequest);
Future<FirebaseRegistration> registerNewFirebaseRegistrationToken(RegisterNewTokenRequest newTokenRequest) {
return _fcmDatasource[DataSourceType.network]!.registerNewFirebaseRegistrationToken(newTokenRequest);
}
@override
Future<FCMSubscription> getSubscription() async {
final fcmSubScription = await _fcmDatasource[DataSourceType.local]!.geSubscription();
return FCMSubscription(fcmSubScription.deviceId, fcmSubScription.subscriptionId);
Future<FirebaseRegistration> getStoredFirebaseRegistration() {
return _fcmDatasource[DataSourceType.local]!.getStoredFirebaseRegistration();
}
@override
Future<void> storeSubscription(FCMSubscription fcmSubscription) {
return _fcmDatasource[DataSourceType.local]!.storeSubscription(fcmSubscription.toFCMSubscriptionCache());
Future<void> storeFirebaseRegistration(FirebaseRegistration firebaseRegistration) {
return _fcmDatasource[DataSourceType.local]!.storeFirebaseRegistration(firebaseRegistration);
}
@override
Future<bool> destroySubscription(String subscriptionId) {
return _fcmDatasource[DataSourceType.network]!.destroySubscription(subscriptionId);
Future<void> destroyFirebaseRegistration(FirebaseRegistrationId registrationId) {
return _fcmDatasource[DataSourceType.network]!.destroyFirebaseRegistration(registrationId);
}
@override
@@ -127,7 +127,7 @@ class FCMRepositoryImpl extends FCMRepository {
.where((presentationMailbox) => presentationMailbox.pushNotificationDeactivated)
.toList();
log('FCMRepositoryImpl::getMailboxesNotPutNotifications():mailboxesCacheNotPutNotifications: $mailboxesCacheNotPutNotifications');
if (mailboxesCacheNotPutNotifications.isNotEmpty && mailboxesCacheNotPutNotifications.length == FcmConstants.mailboxRuleAllowPushNotifications.length) {
if (mailboxesCacheNotPutNotifications.isNotEmpty && mailboxesCacheNotPutNotifications.length == FcmConstants.mailboxRuleDoNotAllowPushNotifications.length) {
return mailboxesCacheNotPutNotifications;
} else {
final mailboxResponse = await _mapMailboxDataSource[DataSourceType.network]!.getAllMailbox(session, accountId);
@@ -217,4 +217,14 @@ class FCMRepositoryImpl extends FCMRepository {
throw NotFoundNewReceiveEmailException();
}
}
@override
Future<void> updateFirebaseRegistrationToken(UpdateTokenExpiredTimeRequest expiredTimeRequest) {
return _fcmDatasource[DataSourceType.network]!.updateFirebaseRegistrationToken(expiredTimeRequest);
}
@override
Future<void> deleteFirebaseRegistrationCache() {
return _fcmDatasource[DataSourceType.local]!.deleteFirebaseRegistrationCache();
}
}
@@ -6,12 +6,18 @@ class NotFoundStateToRefreshException implements Exception {}
class NotFoundEmailDeliveryStateException implements Exception {}
class NotFoundFirebaseSubscriptionException implements Exception {}
class NotFoundFirebaseRegistrationForDeviceException implements Exception {}
class NotFoundSubscriptionException implements Exception {}
class NotFoundFirebaseRegistrationCacheException implements Exception {}
class NotFoundEmailStateException implements Exception {}
class NotFoundNewReceiveEmailException implements Exception {}
class EmailStateNoChangeException implements Exception {}
class EmailStateNoChangeException implements Exception {}
class NotFoundFirebaseRegistrationCreatedException implements Exception {}
class NotFoundFirebaseRegistrationUpdatedException implements Exception {}
class NotFoundFirebaseRegistrationDestroyedException implements Exception {}
@@ -0,0 +1,22 @@
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/fcm_token.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/type_name.dart';
extension FirebaseRegistrationExtension on FirebaseRegistration {
FirebaseRegistration syncProperties({
DeviceClientId? newDeviceId,
FcmToken? newFcmToken,
List<TypeName>? newTypes,
}) {
return FirebaseRegistration(
id: id,
token: newFcmToken ?? token,
deviceClientId: newDeviceId ?? deviceClientId,
expires: expires,
types: newTypes ?? types
);
}
}
@@ -1,16 +0,0 @@
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_subscription.dart';
extension FirebaseSubscriptionExtension on FirebaseSubscription {
FirebaseSubscription fromDeviceId({DeviceClientId? newDeviceId}) {
return FirebaseSubscription(
id: id,
token: token,
deviceClientId: newDeviceId ?? deviceClientId,
expires: expires,
types: types
);
}
}
@@ -1,16 +0,0 @@
import 'package:equatable/equatable.dart';
class FCMSubscription with EquatableMixin {
final String deviceId;
final String subscriptionId;
FCMSubscription(this.deviceId, this.subscriptionId);
@override
List<Object?> get props => [
deviceId,
subscriptionId
];
}
@@ -1,18 +1,18 @@
import 'package:equatable/equatable.dart';
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
class RegisterNewTokenRequest with EquatableMixin {
final Id createRequestId;
final FirebaseSubscription firebaseSubscription;
final FirebaseRegistration firebaseRegistration;
RegisterNewTokenRequest(this.createRequestId, this.firebaseSubscription);
RegisterNewTokenRequest(this.createRequestId, this.firebaseRegistration);
@override
List<Object?> get props => [
createRequestId,
firebaseSubscription
firebaseRegistration
];
}
@@ -0,0 +1,21 @@
import 'package:equatable/equatable.dart';
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:fcm/model/firebase_registration_id.dart';
class UpdateTokenExpiredTimeRequest with EquatableMixin {
final FirebaseRegistrationId firebaseRegistrationId;
final FirebaseRegistrationExpiredTime firebaseRegistrationExpiredTime;
UpdateTokenExpiredTimeRequest(
this.firebaseRegistrationId,
this.firebaseRegistrationExpiredTime
);
@override
List<Object?> get props => [
firebaseRegistrationId,
firebaseRegistrationExpiredTime
];
}
@@ -1,4 +1,6 @@
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:fcm/model/type_name.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
@@ -6,8 +8,8 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
@@ -28,15 +30,19 @@ abstract class FCMRepository {
Future<void> deleteStateToRefresh(AccountId accountId, UserName userName, TypeName typeName);
Future<void> storeSubscription(FCMSubscription fcmSubscription);
Future<void> storeFirebaseRegistration(FirebaseRegistration firebaseRegistration);
Future<FirebaseSubscription> getFirebaseSubscriptionByDeviceId(String deviceId);
Future<FirebaseRegistration> getFirebaseRegistrationByDeviceId(DeviceClientId deviceId);
Future<FirebaseSubscription> registerNewToken(RegisterNewTokenRequest newTokenRequest);
Future<FirebaseRegistration> registerNewFirebaseRegistrationToken(RegisterNewTokenRequest newTokenRequest);
Future<FCMSubscription> getSubscription();
Future<FirebaseRegistration> getStoredFirebaseRegistration();
Future<bool> destroySubscription(String subscriptionId);
Future<void> deleteFirebaseRegistrationCache();
Future<void> destroyFirebaseRegistration(FirebaseRegistrationId registrationId);
Future<void> updateFirebaseRegistrationToken(UpdateTokenExpiredTimeRequest expiredTimeRequest);
Future<List<PresentationMailbox>> getMailboxesNotPutNotifications(Session session, AccountId accountId);
@@ -0,0 +1,12 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class DeleteFirebaseRegistrationCacheLoading extends LoadingState {}
class DeleteFirebaseRegistrationCacheSuccess extends UIState {}
class DeleteFirebaseRegistrationCacheFailure extends FeatureFailure {
DeleteFirebaseRegistrationCacheFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,11 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class DestroyFirebaseRegistrationLoading extends LoadingState {}
class DestroyFirebaseRegistrationSuccess extends UIState {}
class DestroyFirebaseRegistrationFailure extends FeatureFailure {
DestroyFirebaseRegistrationFailure(dynamic exception) : super(exception: exception);
}
@@ -1,19 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class DestroySubscriptionLoading extends UIState {}
class DestroySubscriptionSuccess extends UIState {
final bool destroyedSubscription;
DestroySubscriptionSuccess(this.destroyedSubscription);
@override
List<Object> get props => [destroyedSubscription];
}
class DestroySubscriptionFailure extends FeatureFailure {
DestroySubscriptionFailure(dynamic exception) : super(exception: exception);
}
@@ -1,21 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart';
class GetFCMSubscriptionLocalLoading extends UIState {}
class GetFCMSubscriptionLocalSuccess extends UIState {
final FCMSubscription fcmSubscription;
GetFCMSubscriptionLocalSuccess(this.fcmSubscription);
@override
List<Object> get props => [fcmSubscription];
}
class GetFCMSubscriptionLocalFailure extends FeatureFailure {
GetFCMSubscriptionLocalFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,27 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:fcm/model/fcm_token.dart';
import 'package:fcm/model/firebase_registration.dart';
class GetFirebaseRegistrationByDeviceIdLoading extends LoadingState {}
class GetFirebaseRegistrationByDeviceIdSuccess extends UIState {
final FirebaseRegistration firebaseRegistration;
final FcmToken? newFcmToken;
GetFirebaseRegistrationByDeviceIdSuccess(this.firebaseRegistration, this.newFcmToken);
@override
List<Object?> get props => [firebaseRegistration, newFcmToken];
}
class GetFirebaseRegistrationByDeviceIdFailure extends FeatureFailure {
final FcmToken? newFcmToken;
GetFirebaseRegistrationByDeviceIdFailure(dynamic exception, this.newFcmToken) : super(exception: exception);
@override
List<Object?> get props => [newFcmToken, ...super.props];
}
@@ -1,21 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:fcm/model/firebase_subscription.dart';
class GetFirebaseSubscriptionLoading extends UIState {}
class GetFirebaseSubscriptionSuccess extends UIState {
final FirebaseSubscription firebaseSubscription;
GetFirebaseSubscriptionSuccess(this.firebaseSubscription);
@override
List<Object> get props => [firebaseSubscription];
}
class GetFirebaseSubscriptionFailure extends FeatureFailure {
GetFirebaseSubscriptionFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,21 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:fcm/model/firebase_registration.dart';
class GetStoredFirebaseRegistrationLoading extends LoadingState {}
class GetStoredFirebaseRegistrationSuccess extends UIState {
final FirebaseRegistration firebaseRegistration;
GetStoredFirebaseRegistrationSuccess(this.firebaseRegistration);
@override
List<Object> get props => [firebaseRegistration];
}
class GetStoredFirebaseRegistrationFailure extends FeatureFailure {
GetStoredFirebaseRegistrationFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,21 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:fcm/model/firebase_registration.dart';
class RegisterNewFirebaseRegistrationTokenLoading extends LoadingState {}
class RegisterNewFirebaseRegistrationTokenSuccess extends UIState {
final FirebaseRegistration firebaseRegistration;
RegisterNewFirebaseRegistrationTokenSuccess(this.firebaseRegistration);
@override
List<Object> get props => [firebaseRegistration];
}
class RegisterNewFirebaseRegistrationTokenFailure extends FeatureFailure {
RegisterNewFirebaseRegistrationTokenFailure(dynamic exception) : super(exception: exception);
}
@@ -1,21 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:fcm/model/firebase_subscription.dart';
class RegisterNewTokenLoading extends UIState {}
class RegisterNewTokenSuccess extends UIState {
final FirebaseSubscription firebaseSubscription;
RegisterNewTokenSuccess(this.firebaseSubscription);
@override
List<Object> get props => [firebaseSubscription];
}
class RegisterNewTokenFailure extends FeatureFailure {
RegisterNewTokenFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,12 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class StoreFirebaseRegistrationLoading extends LoadingState {}
class StoreFirebaseRegistrationSuccess extends UIState {}
class StoreFirebaseRegistrationFailure extends FeatureFailure {
StoreFirebaseRegistrationFailure(dynamic exception) : super(exception: exception);
}
@@ -1,12 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class StoreSubscriptionLoading extends UIState {}
class StoreSubscriptionSuccess extends UIState {}
class StoreSubscriptionFailure extends FeatureFailure {
StoreSubscriptionFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,12 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class UpdateFirebaseRegistrationTokenLoading extends LoadingState {}
class UpdateFirebaseRegistrationTokenSuccess extends UIState {}
class UpdateFirebaseRegistrationTokenFailure extends FeatureFailure {
UpdateFirebaseRegistrationTokenFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,21 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/delete_firebase_registration_cache_state.dart';
class DeleteFirebaseRegistrationCacheInteractor {
final FCMRepository _fcmRepository;
DeleteFirebaseRegistrationCacheInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute() async* {
try {
yield Right<Failure, Success>(DeleteFirebaseRegistrationCacheLoading());
await _fcmRepository.getStoredFirebaseRegistration();
yield Right<Failure, Success>(DeleteFirebaseRegistrationCacheSuccess());
} catch (e) {
yield Left<Failure, Success>(DeleteFirebaseRegistrationCacheFailure(e));
}
}
}
@@ -0,0 +1,23 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:fcm/model/firebase_registration_id.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/destroy_firebase_registration_state.dart';
class DestroyFirebaseRegistrationInteractor {
final FCMRepository _fcmRepository;
DestroyFirebaseRegistrationInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(FirebaseRegistrationId registrationId) async* {
try {
yield Right<Failure, Success>(DestroyFirebaseRegistrationLoading());
await _fcmRepository.destroyFirebaseRegistration(registrationId);
yield Right<Failure, Success>(DestroyFirebaseRegistrationSuccess());
} catch (e) {
yield Left<Failure, Success>(DestroyFirebaseRegistrationFailure(e));
}
}
}
@@ -1,22 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/destroy_subscription_state.dart';
class DestroySubscriptionInteractor {
final FCMRepository _fcmRepository;
DestroySubscriptionInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(String subscriptionId) async* {
try {
yield Right<Failure, Success>(DestroySubscriptionLoading());
final destroyedSubscription = await _fcmRepository.destroySubscription(subscriptionId);
yield Right<Failure, Success>(DestroySubscriptionSuccess(destroyedSubscription));
} catch (e) {
yield Left<Failure, Success>(DestroySubscriptionFailure(e));
}
}
}
@@ -1,21 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_fcm_subscription_local.dart';
class GetFCMSubscriptionLocalInteractor {
final FCMRepository _fcmRepository;
GetFCMSubscriptionLocalInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute() async* {
try {
yield Right<Failure, Success>(GetFCMSubscriptionLocalLoading());
final subscription = await _fcmRepository.getSubscription();
yield Right<Failure, Success>(GetFCMSubscriptionLocalSuccess(subscription));
} catch (e) {
yield Left<Failure, Success>(GetFCMSubscriptionLocalFailure(e));
}
}
}
@@ -0,0 +1,25 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/fcm_token.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_firebase_registration_by_device_id_state.dart';
class GetFirebaseRegistrationByDeviceIdInteractor {
final FCMRepository _fcmRepository;
GetFirebaseRegistrationByDeviceIdInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute({required DeviceClientId deviceClientId, FcmToken? newFcmToken}) async* {
try {
yield Right<Failure, Success>(GetFirebaseRegistrationByDeviceIdLoading());
final firebaseRegistration = await _fcmRepository.getFirebaseRegistrationByDeviceId(deviceClientId);
yield Right<Failure, Success>(GetFirebaseRegistrationByDeviceIdSuccess(firebaseRegistration, newFcmToken));
} catch (e) {
yield Left<Failure, Success>(GetFirebaseRegistrationByDeviceIdFailure(e, newFcmToken));
}
}
}
@@ -1,23 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_firebase_subscription_state.dart';
class GetFirebaseSubscriptionInteractor {
final FCMRepository _fcmRepository;
GetFirebaseSubscriptionInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(String deviceId) async* {
try {
yield Right<Failure, Success>(GetFirebaseSubscriptionLoading());
final firebaseSubscription = await _fcmRepository.getFirebaseSubscriptionByDeviceId(deviceId);
yield Right<Failure, Success>(GetFirebaseSubscriptionSuccess(firebaseSubscription));
} catch (e) {
yield Left<Failure, Success>(GetFirebaseSubscriptionFailure(e));
}
}
}
@@ -0,0 +1,21 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_stored_firebase_registration_state.dart';
class GetStoredFirebaseRegistrationInteractor {
final FCMRepository _fcmRepository;
GetStoredFirebaseRegistrationInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute() async* {
try {
yield Right<Failure, Success>(GetStoredFirebaseRegistrationLoading());
final registration = await _fcmRepository.getStoredFirebaseRegistration();
yield Right<Failure, Success>(GetStoredFirebaseRegistrationSuccess(registration));
} catch (e) {
yield Left<Failure, Success>(GetStoredFirebaseRegistrationFailure(e));
}
}
}
@@ -4,21 +4,21 @@ import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/register_new_token_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/register_new_firebase_registration_token_state.dart';
class RegisterNewTokenInteractor {
class RegisterNewFirebaseRegistrationTokenInteractor {
final FCMRepository _fcmRepository;
RegisterNewTokenInteractor(this._fcmRepository);
RegisterNewFirebaseRegistrationTokenInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(RegisterNewTokenRequest newTokenRequest) async* {
try {
yield Right<Failure, Success>(RegisterNewTokenLoading());
final firebaseSubscription = await _fcmRepository.registerNewToken(newTokenRequest);
yield Right<Failure, Success>(RegisterNewTokenSuccess(firebaseSubscription));
yield Right<Failure, Success>(RegisterNewFirebaseRegistrationTokenLoading());
final firebaseRegistration = await _fcmRepository.registerNewFirebaseRegistrationToken(newTokenRequest);
yield Right<Failure, Success>(RegisterNewFirebaseRegistrationTokenSuccess(firebaseRegistration));
} catch (e) {
yield Left<Failure, Success>(RegisterNewTokenFailure(e));
yield Left<Failure, Success>(RegisterNewFirebaseRegistrationTokenFailure(e));
}
}
}
@@ -0,0 +1,22 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/store_firebase_registration_state.dart';
class StoreFirebaseRegistrationInteractor {
final FCMRepository _fcmRepository;
StoreFirebaseRegistrationInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(FirebaseRegistration firebaseRegistration) async* {
try {
yield Right<Failure, Success>(StoreFirebaseRegistrationLoading());
await _fcmRepository.storeFirebaseRegistration(firebaseRegistration);
yield Right<Failure, Success>(StoreFirebaseRegistrationSuccess());
} catch (e) {
yield Left<Failure, Success>(StoreFirebaseRegistrationFailure(e));
}
}
}
@@ -1,22 +0,0 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/store_subscription_state.dart';
class StoreSubscriptionInteractor {
final FCMRepository _fcmRepository;
StoreSubscriptionInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(FCMSubscription fcmSubscription) async* {
try {
yield Right<Failure, Success>(StoreSubscriptionLoading());
await _fcmRepository.storeSubscription(fcmSubscription);
yield Right<Failure, Success>(StoreSubscriptionSuccess());
} catch (e) {
yield Left<Failure, Success>(StoreSubscriptionFailure(e));
}
}
}
@@ -0,0 +1,24 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/update_firebase_registration_token_state.dart';
class UpdateFirebaseRegistrationTokenInteractor {
final FCMRepository _fcmRepository;
UpdateFirebaseRegistrationTokenInteractor(this._fcmRepository);
Stream<Either<Failure, Success>> execute(UpdateTokenExpiredTimeRequest updateTokenExpiredTimeRequest) async* {
try {
yield Right<Failure, Success>(UpdateFirebaseRegistrationTokenLoading());
await _fcmRepository.updateFirebaseRegistrationToken(updateTokenExpiredTimeRequest);
yield Right<Failure, Success>(UpdateFirebaseRegistrationTokenSuccess());
} catch (e) {
yield Left<Failure, Success>(UpdateFirebaseRegistrationTokenFailure(e));
}
}
}
@@ -3,12 +3,13 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
class FcmConstants {
static final List<Role> mailboxRuleAllowPushNotifications = [
static final List<Role> mailboxRuleDoNotAllowPushNotifications = [
PresentationMailbox.roleDrafts,
PresentationMailbox.roleSent,
PresentationMailbox.roleOutbox,
PresentationMailbox.roleSpam,
PresentationMailbox.roleTrash
];
static const String firebaseRegistrationExpiredTimeProperty = 'expires';
}
@@ -35,21 +35,23 @@ import 'package:tmail_ui_user/features/push_notification/data/network/fcm_api.da
import 'package:tmail_ui_user/features/push_notification/data/repository/fcm_repository_impl.dart';
import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/delete_email_state_to_refresh_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/destroy_subscription_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/delete_firebase_registration_cache_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/destroy_firebase_registration_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_email_changes_to_push_notification_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_email_changes_to_remove_notification_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_email_state_to_refresh_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_fcm_subscription_local_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_firebase_subscription_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_firebase_registration_by_device_id_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_mailbox_state_to_refresh_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_mailboxes_not_put_notifications_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_new_receive_email_from_notification_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_stored_email_delivery_state_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/register_new_token_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_stored_firebase_registration_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/register_new_firebase_registration_token_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_email_delivery_state_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_email_state_to_refresh_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_firebase_registration_interator.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_mailbox_state_to_refresh_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_subscription_interator.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/update_firebase_registration_token_interactor.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
@@ -123,13 +125,16 @@ class FcmInteractorBindings extends InteractorsBindings {
Get.lazyPut(() => StoreEmailStateToRefreshInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetEmailStateToRefreshInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => DeleteEmailStateToRefreshInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetFirebaseSubscriptionInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => RegisterNewTokenInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetFirebaseRegistrationByDeviceIdInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => RegisterNewFirebaseRegistrationTokenInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => StoreMailboxStateToRefreshInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetMailboxStateToRefreshInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => StoreSubscriptionInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetFCMSubscriptionLocalInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => DestroySubscriptionInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => StoreFirebaseRegistrationInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetStoredFirebaseRegistrationInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => DestroyFirebaseRegistrationInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => UpdateFirebaseRegistrationTokenInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => DeleteFirebaseRegistrationCacheInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => DestroyFirebaseRegistrationInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetMailboxesNotPutNotificationsInteractor(Get.find<FCMRepositoryImpl>()));
Get.lazyPut(() => GetNewReceiveEmailFromNotificationInteractor(
Get.find<FCMRepositoryImpl>(),
@@ -6,7 +6,7 @@ import 'package:tmail_ui_user/features/push_notification/presentation/services/f
class FcmConfiguration {
static void initialize() async {
static Future<void> initialize() async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FcmService.instance.recreateStreamController();
_initMessageListener();
@@ -95,7 +95,7 @@ class FcmMessageController extends FcmBaseController {
Future<void> listenTokenStream() {
FcmService.instance.fcmTokenStream
.debounceTime(const Duration(milliseconds: FcmService.durationRefreshToken))
.listen(FcmTokenController.instance.handleTokenAction);
.listen(FcmTokenController.instance.onFcmTokenChanged);
return Future.value();
}
@@ -199,23 +199,18 @@ class FcmMessageController extends FcmBaseController {
FcmInteractorBindings().dependencies();
});
await _getInteractorBindings();
_getInteractorBindings();
await _newEmailCacheManager?.closeNewEmailHiveCacheBox();
}
Future<void> _getInteractorBindings() {
try {
_getAuthenticatedAccountInteractor = getBinding<GetAuthenticatedAccountInteractor>();
_dynamicUrlInterceptors = getBinding<DynamicUrlInterceptors>();
_authorizationInterceptors = getBinding<AuthorizationInterceptors>();
_getSessionInteractor = getBinding<GetSessionInteractor>();
_newEmailCacheManager = getBinding<NewEmailCacheManager>();
FcmTokenController.instance.initialize();
} catch (e) {
logError('FcmMessageController::_getBindings(): ${e.toString()}');
}
return Future.value(null);
void _getInteractorBindings() {
_getAuthenticatedAccountInteractor = getBinding<GetAuthenticatedAccountInteractor>();
_dynamicUrlInterceptors = getBinding<DynamicUrlInterceptors>();
_authorizationInterceptors = getBinding<AuthorizationInterceptors>();
_getSessionInteractor = getBinding<GetSessionInteractor>();
_newEmailCacheManager = getBinding<NewEmailCacheManager>();
FcmTokenController.instance.initialize();
}
void _getAuthenticatedAccount() {
@@ -4,21 +4,22 @@ import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:fcm/model/device_client_id.dart';
import 'package:fcm/model/firebase_expired_time.dart';
import 'package:fcm/model/firebase_subscription.dart';
import 'package:fcm/model/firebase_token.dart';
import 'package:fcm/model/type_name.dart';
import 'package:fcm/model/firebase_registration_expired_time.dart';
import 'package:fcm/model/firebase_registration.dart';
import 'package:fcm/model/fcm_token.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/fcm_subscription.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/register_new_token_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_fcm_subscription_local.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_firebase_subscription_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/register_new_token_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_fcm_subscription_local_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_firebase_subscription_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/register_new_token_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_subscription_interator.dart';
import 'package:tmail_ui_user/features/push_notification/domain/model/update_token_expired_time_request.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_firebase_registration_by_device_id_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/get_stored_firebase_registration_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/state/register_new_firebase_registration_token_state.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/delete_firebase_registration_cache_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_firebase_registration_by_device_id_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_stored_firebase_registration_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/register_new_firebase_registration_token_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_firebase_registration_interator.dart';
import 'package:tmail_ui_user/features/push_notification/domain/usecases/update_firebase_registration_token_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/controller/fcm_base_controller.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/utils/fcm_utils.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -35,146 +36,137 @@ class FcmTokenController extends FcmBaseController {
static const int limitedTimeToExpire = 3;
static const int extensionTimeExpire = 7;
StoreSubscriptionInteractor? _storeSubscriptionInteractor;
GetFirebaseSubscriptionInteractor? _getFirebaseSubscriptionInteractor;
RegisterNewTokenInteractor? _registerNewTokenInteractor;
GetFCMSubscriptionLocalInteractor? _getFCMSubscriptionLocalInteractor;
FirebaseToken? _fcmToken;
DeviceClientId? _deviceClientId;
StoreFirebaseRegistrationInteractor? _storeFirebaseRegistrationInteractor;
GetFirebaseRegistrationByDeviceIdInteractor? _getFirebaseRegistrationByDeviceIdInteractor;
RegisterNewFirebaseRegistrationTokenInteractor? _registerNewFirebaseRegistrationTokenInteractor;
GetStoredFirebaseRegistrationInteractor? _getStoredFirebaseRegistrationInteractor;
UpdateFirebaseRegistrationTokenInteractor? _updateFirebaseRegistrationTokenInteractor;
DeleteFirebaseRegistrationCacheInteractor? _deleteFirebaseRegistrationCacheInteractor;
void initialize() {
try {
_storeSubscriptionInteractor = getBinding<StoreSubscriptionInteractor>();
_getFirebaseSubscriptionInteractor = getBinding<GetFirebaseSubscriptionInteractor>();
_registerNewTokenInteractor = getBinding<RegisterNewTokenInteractor>();
_getFCMSubscriptionLocalInteractor = getBinding<GetFCMSubscriptionLocalInteractor>();
} catch (e) {
logError('FcmTokenController::initialize(): ${e.toString()}');
}
_storeFirebaseRegistrationInteractor = getBinding<StoreFirebaseRegistrationInteractor>();
_getFirebaseRegistrationByDeviceIdInteractor = getBinding<GetFirebaseRegistrationByDeviceIdInteractor>();
_registerNewFirebaseRegistrationTokenInteractor = getBinding<RegisterNewFirebaseRegistrationTokenInteractor>();
_getStoredFirebaseRegistrationInteractor = getBinding<GetStoredFirebaseRegistrationInteractor>();
_updateFirebaseRegistrationTokenInteractor = getBinding<UpdateFirebaseRegistrationTokenInteractor>();
_deleteFirebaseRegistrationCacheInteractor = getBinding<DeleteFirebaseRegistrationCacheInteractor>();
}
void handleTokenAction(String? token) {
log('FcmTokenController::handleTokenAction():token: $token');
if (token != null) {
_fcmToken = FirebaseToken(token);
final deviceId = FcmUtils.instance.hashTokenToDeviceId(token);
_deviceClientId = DeviceClientId(deviceId);
log('FcmTokenController::handleTokenAction(): fcmToken: $_fcmToken');
log('FcmTokenController::handleTokenAction(): deviceId: $deviceId');
_getFcmTokenFromBackend(deviceId);
void onFcmTokenChanged(String? newToken) {
log('FcmTokenController::onFcmTokenChanged():newToken: $newToken');
if (newToken != null) {
_getFirebaseRegistrationFromServer(
newFcmToken: FcmToken(newToken),
deviceClientId: DeviceClientId(FcmUtils.instance.hashTokenToDeviceId(newToken))
);
} else {
_getFCMSubscriptionLocalAction();
_getStoredFirebaseRegistrationFromCache();
}
}
void _getFcmTokenFromBackend(String deviceId) {
if (_getFirebaseSubscriptionInteractor != null) {
consumeState(_getFirebaseSubscriptionInteractor!.execute(deviceId));
void _getFirebaseRegistrationFromServer({
required DeviceClientId deviceClientId,
FcmToken? newFcmToken
}) {
if (_getFirebaseRegistrationByDeviceIdInteractor != null) {
consumeState(
_getFirebaseRegistrationByDeviceIdInteractor!.execute(
deviceClientId: deviceClientId,
newFcmToken: newFcmToken
)
);
} else if (newFcmToken != null) {
_registerNewFirebaseRegistrationToken(newFcmToken);
}
}
void _storeSubscriptionAction(FCMSubscription fcmSubscription){
if (_storeSubscriptionInteractor != null) {
consumeState(_storeSubscriptionInteractor!.execute(fcmSubscription));
void _getStoredFirebaseRegistrationFromCache() {
if (_getStoredFirebaseRegistrationInteractor != null) {
consumeState(_getStoredFirebaseRegistrationInteractor!.execute());
}
}
bool _isTokenExpired(FirebaseExpiredTime? expireTime) {
log('FcmTokenController::_isTokenExpired():expireTime: $expireTime');
if (expireTime != null) {
final expireTimeLocal = expireTime.value.value.toLocal();
void _storeFirebaseRegistrationToCache(FirebaseRegistration firebaseRegistration){
if (_storeFirebaseRegistrationInteractor != null) {
consumeState(_storeFirebaseRegistrationInteractor!.execute(firebaseRegistration));
}
}
bool _validateFirebaseRegistrationTokenExpired(FirebaseRegistration firebaseRegistration) {
log('FcmTokenController::_validateFirebaseRegistrationTokenExpired():firebaseRegistration: $firebaseRegistration');
if (firebaseRegistration.expires != null) {
final expireTimeLocal = firebaseRegistration.expires!.value.value.toLocal();
final currentTime = DateTime.now();
log('FcmTokenController::_isTokenExpired():expireTimeLocal: $expireTimeLocal');
log('FcmTokenController::_isTokenExpired():currentTime: $currentTime');
return currentTime.isBefore(expireTimeLocal) &&
expireTimeLocal.daysBetween(currentTime) <= limitedTimeToExpire;
log('FcmTokenController::_validateFirebaseRegistrationTokenExpired():expireTimeLocal: $expireTimeLocal | currentTime: $currentTime');
final offsetTime = expireTimeLocal.minutesBetween(currentTime);
log('FcmTokenController::_validateFirebaseRegistrationTokenExpired():offsetTime: $offsetTime');
return currentTime.isBefore(expireTimeLocal) && offsetTime <= limitedTimeToExpire;
} else {
return true;
}
}
void _handleWhenTokenExpired() {
if (_fcmToken == null || _deviceClientId == null) {
log('FcmTokenController::_handleSuccessViewState():_fcmToken or _deviceClientId is null');
return;
void _updateNewExpiredTimeForFirebaseRegistration(FirebaseRegistration firebaseRegistration) {
log('FcmTokenController::_updateNewExpiredTimeForFirebaseRegistration():firebaseRegistration: $firebaseRegistration');
if (_updateFirebaseRegistrationTokenInteractor != null && firebaseRegistration.id != null) {
final newExpiredTime = DateTime.now().add(const Duration(days: extensionTimeExpire));
consumeState(
_updateFirebaseRegistrationTokenInteractor!.execute(
UpdateTokenExpiredTimeRequest(
firebaseRegistration.id!,
FirebaseRegistrationExpiredTime(UTCDate(newExpiredTime)),
)
)
);
}
final generateCreationId = Id(const Uuid().v4());
final newExpireTime = DateTime.now().add(const Duration(days: extensionTimeExpire));
log('FcmTokenController::_handleSuccessViewState():newExpireTime: $newExpireTime');
final firebaseSubscription = FirebaseSubscription(
token: _fcmToken!,
expires: FirebaseExpiredTime(newExpireTime.toUTCDate()!),
deviceClientId: _deviceClientId!,
types: [TypeName.emailType, TypeName.mailboxType, TypeName.emailDelivery]
);
log('FcmTokenController::_handleSuccessViewState():firebaseSubscription: $firebaseSubscription');
_invokeRegisterNewTokenAction(RegisterNewTokenRequest(
generateCreationId,
firebaseSubscription
));
}
void _handleRegisterNewToken(FirebaseToken fcmToken, DeviceClientId deviceClientId) {
void _registerNewFirebaseRegistrationToken(FcmToken fcmToken) {
final generateCreationId = Id(const Uuid().v4());
final firebaseSubscription = FirebaseSubscription(
final firebaseRegistration = FirebaseRegistration(
token: fcmToken,
deviceClientId: deviceClientId,
types: [TypeName.emailType, TypeName.mailboxType, TypeName.emailDelivery]
deviceClientId: DeviceClientId(FcmUtils.instance.hashTokenToDeviceId(fcmToken.value)),
types: FcmUtils.defaultFirebaseRegistrationTypes
);
log('FcmTokenController::_handleRegisterNewToken():firebaseSubscription: $firebaseSubscription');
_invokeRegisterNewTokenAction(RegisterNewTokenRequest(
generateCreationId,
firebaseSubscription
));
}
void _invokeRegisterNewTokenAction(RegisterNewTokenRequest newTokenRequest) {
if (_registerNewTokenInteractor != null) {
consumeState(_registerNewTokenInteractor!.execute(newTokenRequest));
log('FcmTokenController::_registerNewFirebaseRegistrationToken():generateCreationId: $generateCreationId | firebaseRegistration: $firebaseRegistration');
if (_registerNewFirebaseRegistrationTokenInteractor != null) {
consumeState(
_registerNewFirebaseRegistrationTokenInteractor!.execute(
RegisterNewTokenRequest(
generateCreationId,
firebaseRegistration
)
)
);
}
}
void _getFCMSubscriptionLocalAction() {
if (_getFCMSubscriptionLocalInteractor != null) {
consumeState(_getFCMSubscriptionLocalInteractor!.execute());
void _deleteFirebaseRegistrationInCache() {
if (_deleteFirebaseRegistrationCacheInteractor != null) {
consumeState(_deleteFirebaseRegistrationCacheInteractor!.execute());
}
}
@override
void handleFailureViewState(Failure failure) {
log('FcmTokenController::_handleFailureViewState(): $failure');
if (failure is GetFirebaseSubscriptionFailure) {
if (_fcmToken != null && _deviceClientId != null) {
_handleRegisterNewToken(_fcmToken!, _deviceClientId!);
}
if (failure is GetFirebaseRegistrationByDeviceIdFailure && failure.newFcmToken != null) {
_registerNewFirebaseRegistrationToken(failure.newFcmToken!);
} else if (failure is RegisterNewFirebaseRegistrationTokenFailure) {
_deleteFirebaseRegistrationInCache();
}
}
@override
void handleSuccessViewState(Success success) {
log('FcmTokenController::_handleSuccessViewState(): $success');
if (success is GetFirebaseSubscriptionSuccess) {
_deviceClientId = success.firebaseSubscription.deviceClientId;
final expireTime = success.firebaseSubscription.expires;
log('FcmTokenController::_handleSuccessViewState():_fcmToken: $_fcmToken');
if (_isTokenExpired(expireTime)) {
log('FcmTokenController::_handleSuccessViewState(): _isTokenExpired true');
_handleWhenTokenExpired();
}
} else if (success is RegisterNewTokenSuccess) {
final deviceId = success.firebaseSubscription.deviceClientId?.value;
final subscriptionId = success.firebaseSubscription.id?.id.value;
if (deviceId != null && subscriptionId != null) {
_storeSubscriptionAction(FCMSubscription(deviceId, subscriptionId));
}
} else if (success is GetFCMSubscriptionLocalSuccess) {
_getFcmTokenFromBackend(success.fcmSubscription.deviceId);
if (success is GetFirebaseRegistrationByDeviceIdSuccess &&
_validateFirebaseRegistrationTokenExpired(success.firebaseRegistration)) {
_updateNewExpiredTimeForFirebaseRegistration(success.firebaseRegistration);
} else if (success is GetStoredFirebaseRegistrationSuccess) {
_getFirebaseRegistrationFromServer(deviceClientId: success.firebaseRegistration.deviceClientId!);
} else if (success is RegisterNewFirebaseRegistrationTokenSuccess) {
_storeFirebaseRegistrationToCache(success.firebaseRegistration);
}
}
}
@@ -18,6 +18,11 @@ class FcmUtils {
static FcmUtils get instance => _instance;
static const String hashCodeKey = 'TeamMail';
static final List<TypeName> defaultFirebaseRegistrationTypes = [
TypeName.emailType,
TypeName.mailboxType,
TypeName.emailDelivery
];
StateChange? convertFirebaseDataMessageToStateChange(Map<String, dynamic> dataMessage) {
log('FcmUtils::convertFirebaseDataMessageToStateChange():dataMessage: $dataMessage');
+4 -4
View File
@@ -18,7 +18,7 @@ import 'package:tmail_ui_user/features/caching/clients/recent_search_cache_clien
import 'package:tmail_ui_user/features/caching/clients/sending_email_hive_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/session_hive_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/state_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/subscription_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/firebase_registration_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/token_oidc_cache_client.dart';
import 'package:tmail_ui_user/features/cleanup/data/local/recent_login_url_cache_manager.dart';
import 'package:tmail_ui_user/features/cleanup/data/local/recent_login_username_cache_manager.dart';
@@ -71,9 +71,9 @@ class LocalBindings extends Bindings {
Get.put(RecentLoginUrlCacheManager((Get.find<RecentLoginUrlCacheClient>())));
Get.put(RecentLoginUsernameCacheClient());
Get.put(RecentLoginUsernameCacheManager(Get.find<RecentLoginUsernameCacheClient>()));
Get.put(FCMSubscriptionCacheClient());
Get.put(FirebaseRegistrationCacheClient());
Get.put(FcmCacheClient());
Get.put(FCMCacheManager(Get.find<FcmCacheClient>(),Get.find<FCMSubscriptionCacheClient>()));
Get.put(FCMCacheManager(Get.find<FcmCacheClient>(),Get.find<FirebaseRegistrationCacheClient>()));
Get.put(HiveCacheVersionClient(Get.find<SharedPreferences>(), Get.find<CacheExceptionThrower>()));
Get.put(NewEmailHiveCacheClient());
Get.put(NewEmailCacheManager(Get.find<NewEmailHiveCacheClient>(), Get.find<FileUtils>()));
@@ -90,7 +90,7 @@ class LocalBindings extends Bindings {
Get.find<RecentSearchCacheClient>(),
Get.find<AccountCacheClient>(),
Get.find<FcmCacheClient>(),
Get.find<FCMSubscriptionCacheClient>(),
Get.find<FirebaseRegistrationCacheClient>(),
Get.find<HiveCacheVersionClient>(),
Get.find<NewEmailHiveCacheClient>(),
Get.find<OpenedEmailHiveCacheClient>(),