TF-4385 Fix spam banner show it once per day
This commit is contained in:
@@ -284,7 +284,7 @@ class MailboxController extends BaseMailboxController
|
|||||||
mailboxDashBoardController.updateRefreshAllMailboxState(Right(RefreshAllMailboxSuccess()));
|
mailboxDashBoardController.updateRefreshAllMailboxState(Right(RefreshAllMailboxSuccess()));
|
||||||
_handleCreateDefaultFolderIfMissing(mailboxDashBoardController.mapDefaultMailboxIdByRole);
|
_handleCreateDefaultFolderIfMissing(mailboxDashBoardController.mapDefaultMailboxIdByRole);
|
||||||
_handleDataFromNavigationRouter();
|
_handleDataFromNavigationRouter();
|
||||||
mailboxDashBoardController.getSpamReportBanner();
|
mailboxDashBoardController.refreshSpamReportBanner();
|
||||||
if (PlatformInfo.isIOS) {
|
if (PlatformInfo.isIOS) {
|
||||||
_updateMailboxIdsBlockNotificationToKeychain(success.mailboxList);
|
_updateMailboxIdsBlockNotificationToKeychain(success.mailboxList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/unread_spa
|
|||||||
abstract class SpamReportDataSource {
|
abstract class SpamReportDataSource {
|
||||||
Future<void> storeLastTimeDismissedSpamReported(DateTime lastTimeDismissedSpamReported);
|
Future<void> storeLastTimeDismissedSpamReported(DateTime lastTimeDismissedSpamReported);
|
||||||
|
|
||||||
Future<DateTime> getLastTimeDismissedSpamReported();
|
Future<int> getLastTimeDismissedSpamReportedMilliseconds();
|
||||||
|
|
||||||
Future<void> deleteLastTimeDismissedSpamReported();
|
Future<void> deleteLastTimeDismissedSpamReported();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ class HiveSpamReportDataSourceImpl extends SpamReportDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<DateTime> getLastTimeDismissedSpamReported() {
|
Future<int> getLastTimeDismissedSpamReportedMilliseconds() {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -21,12 +21,10 @@ class LocalSpamReportDataSourceImpl extends SpamReportDataSource {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<DateTime> getLastTimeDismissedSpamReported() async {
|
Future<int> getLastTimeDismissedSpamReportedMilliseconds() async {
|
||||||
return Future.sync(() async {
|
return Future.sync(() async {
|
||||||
final spamReportConfig = await _preferencesSettingManager.getSpamReportConfig();
|
final spamReportConfig = await _preferencesSettingManager.getSpamReportConfig();
|
||||||
return DateTime.fromMillisecondsSinceEpoch(
|
return spamReportConfig.lastTimeDismissedMilliseconds;
|
||||||
spamReportConfig.lastTimeDismissedMilliseconds,
|
|
||||||
);
|
|
||||||
}).catchError(_exceptionThrower.throwException);
|
}).catchError(_exceptionThrower.throwException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ class SpamReportRepositoryImpl extends SpamReportRepository {
|
|||||||
SpamReportRepositoryImpl(this.mapDataSource);
|
SpamReportRepositoryImpl(this.mapDataSource);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<DateTime> getLastTimeDismissedSpamReported() async {
|
Future<int> getLastTimeDismissedSpamReportedMilliseconds() async {
|
||||||
return await mapDataSource[DataSourceType.local]!.getLastTimeDismissedSpamReported();
|
return await mapDataSource[DataSourceType.local]!.getLastTimeDismissedSpamReportedMilliseconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:core/domain/exceptions/app_base_exception.dart';
|
import 'package:core/domain/exceptions/app_base_exception.dart';
|
||||||
|
|
||||||
class NotFoundLastTimeDismissedSpamReportException extends AppBaseException {
|
class SpamDismissCooldownActiveException extends AppBaseException {
|
||||||
NotFoundLastTimeDismissedSpamReportException([super.message]);
|
SpamDismissCooldownActiveException([super.message]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get exceptionName => 'NotFoundLastTimeDismissedSpamReportException';
|
String get exceptionName => 'SpamDismissCooldownActiveException';
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotFoundSpamMailboxCachedException extends AppBaseException {
|
class NotFoundSpamMailboxCachedException extends AppBaseException {
|
||||||
@@ -20,3 +20,10 @@ class NotFoundSpamMailboxException extends AppBaseException {
|
|||||||
@override
|
@override
|
||||||
String get exceptionName => 'NotFoundSpamMailboxException';
|
String get exceptionName => 'NotFoundSpamMailboxException';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NoUnreadSpamEmailsException extends AppBaseException {
|
||||||
|
NoUnreadSpamEmailsException([super.message]);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get exceptionName => 'NoUnreadSpamEmailsException';
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_repor
|
|||||||
abstract class SpamReportRepository {
|
abstract class SpamReportRepository {
|
||||||
Future<void> storeLastTimeDismissedSpamReported(DateTime lastTimeDismissedSpamReported);
|
Future<void> storeLastTimeDismissedSpamReported(DateTime lastTimeDismissedSpamReported);
|
||||||
|
|
||||||
Future<DateTime> getLastTimeDismissedSpamReported();
|
Future<int> getLastTimeDismissedSpamReportedMilliseconds();
|
||||||
|
|
||||||
Future<void> deleteLastTimeDismissedSpamReported();
|
Future<void> deleteLastTimeDismissedSpamReported();
|
||||||
|
|
||||||
|
|||||||
@@ -18,5 +18,3 @@ class GetSpamMailboxCachedFailure extends FeatureFailure {
|
|||||||
|
|
||||||
GetSpamMailboxCachedFailure(exception) : super(exception: exception);
|
GetSpamMailboxCachedFailure(exception) : super(exception: exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvalidSpamReportCondition extends FeatureFailure {}
|
|
||||||
+24
-10
@@ -1,15 +1,15 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/state/failure.dart';
|
import 'package:core/presentation/state/failure.dart';
|
||||||
import 'package:core/presentation/state/success.dart';
|
import 'package:core/presentation/state/success.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/spam_report_exception.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/spam_report_repository.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/spam_report_repository.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_mailbox_cached_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_mailbox_cached_state.dart';
|
||||||
|
|
||||||
class GetSpamMailboxCachedInteractor {
|
class GetSpamMailboxCachedInteractor {
|
||||||
static const int spamReportBannerDisplayIntervalInHour = 12;
|
static const int spamReportBannerDisplayIntervalInHours = 24;
|
||||||
|
|
||||||
final SpamReportRepository _spamReportRepository;
|
final SpamReportRepository _spamReportRepository;
|
||||||
|
|
||||||
@@ -19,15 +19,19 @@ class GetSpamMailboxCachedInteractor {
|
|||||||
try {
|
try {
|
||||||
yield Right<Failure, Success>(GetSpamMailboxCachedLoading());
|
yield Right<Failure, Success>(GetSpamMailboxCachedLoading());
|
||||||
if (await _validateIntervalToShowBanner()) {
|
if (await _validateIntervalToShowBanner()) {
|
||||||
final spamMailbox = await _spamReportRepository.getSpamMailboxCached(accountId, userName);
|
final spamMailbox = await _spamReportRepository.getSpamMailboxCached(accountId, userName);
|
||||||
final countUnreadSpamMailbox = spamMailbox.unreadEmails?.value.value.toInt() ?? 0;
|
final countUnreadSpamMailbox = spamMailbox.unreadEmails?.value.value.toInt() ?? 0;
|
||||||
if (countUnreadSpamMailbox > 0) {
|
if (countUnreadSpamMailbox > 0) {
|
||||||
yield Right<Failure, Success>(GetSpamMailboxCachedSuccess(spamMailbox));
|
yield Right<Failure, Success>(GetSpamMailboxCachedSuccess(spamMailbox));
|
||||||
} else {
|
} else {
|
||||||
yield Left<Failure, Success>(InvalidSpamReportCondition());
|
yield Left<Failure, Success>(
|
||||||
|
GetSpamMailboxCachedFailure(NoUnreadSpamEmailsException()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yield Left<Failure, Success>(InvalidSpamReportCondition());
|
yield Left<Failure, Success>(
|
||||||
|
GetSpamMailboxCachedFailure(SpamDismissCooldownActiveException()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
yield Left<Failure, Success>(GetSpamMailboxCachedFailure(e));
|
yield Left<Failure, Success>(GetSpamMailboxCachedFailure(e));
|
||||||
@@ -35,9 +39,19 @@ class GetSpamMailboxCachedInteractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _validateIntervalToShowBanner() async {
|
Future<bool> _validateIntervalToShowBanner() async {
|
||||||
final lastTimeDismissedSpamReported = await _spamReportRepository.getLastTimeDismissedSpamReported();
|
final lastTimeDismissedMs = await _spamReportRepository
|
||||||
final currentTime = DateTime.now().difference(lastTimeDismissedSpamReported);
|
.getLastTimeDismissedSpamReportedMilliseconds();
|
||||||
log('GetSpamMailboxCachedInteractor::_compareSpamReportTime:lastTimeDismissedSpamReported: $lastTimeDismissedSpamReported | currentTime: $currentTime');
|
|
||||||
return currentTime.inHours > spamReportBannerDisplayIntervalInHour;
|
if (lastTimeDismissedMs <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final lastTime = DateTime.fromMillisecondsSinceEpoch(lastTimeDismissedMs);
|
||||||
|
final now = DateTime.now();
|
||||||
|
final elapsed = now.difference(lastTime);
|
||||||
|
final isIntervalElapsed =
|
||||||
|
elapsed.inHours > spamReportBannerDisplayIntervalInHours;
|
||||||
|
|
||||||
|
return isIntervalElapsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-18
@@ -2534,24 +2534,6 @@ class MailboxDashBoardController extends ReloadableController
|
|||||||
|
|
||||||
bool get enableSpamReport => spamReportController.enableSpamReport;
|
bool get enableSpamReport => spamReportController.enableSpamReport;
|
||||||
|
|
||||||
void getSpamReportBanner() {
|
|
||||||
if (enableSpamReport) {
|
|
||||||
final spamId = spamMailboxId;
|
|
||||||
if (spamId == null) {
|
|
||||||
spamReportController.setSpamPresentationMailbox(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final spamMailbox = mapMailboxById[spamId];
|
|
||||||
final unreadEmails = spamMailbox?.unreadEmails?.value.value ?? 0;
|
|
||||||
if (unreadEmails > 0) {
|
|
||||||
spamReportController.setSpamPresentationMailbox(spamMailbox);
|
|
||||||
} else {
|
|
||||||
spamReportController.setSpamPresentationMailbox(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void refreshSpamReportBanner() {
|
void refreshSpamReportBanner() {
|
||||||
if (enableSpamReport && sessionCurrent != null && accountId.value != null) {
|
if (enableSpamReport && sessionCurrent != null && accountId.value != null) {
|
||||||
spamReportController.getSpamMailboxCached(accountId.value!, sessionCurrent!.username);
|
spamReportController.getSpamMailboxCached(accountId.value!, sessionCurrent!.username);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'package:model/extensions/presentation_mailbox_extension.dart';
|
|||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/spam_report_exception.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_mailbox_cached_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_mailbox_cached_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_report_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_report_state.dart';
|
||||||
@@ -75,7 +76,7 @@ class SpamReportController extends BaseController {
|
|||||||
@override
|
@override
|
||||||
void handleFailureViewState(Failure failure) {
|
void handleFailureViewState(Failure failure) {
|
||||||
if (failure is GetSpamMailboxCachedFailure) {
|
if (failure is GetSpamMailboxCachedFailure) {
|
||||||
presentationSpamMailbox.value = null;
|
_validateSpamMailboxChanged(failure);
|
||||||
} else if (failure is GetSpamReportStateFailure) {
|
} else if (failure is GetSpamReportStateFailure) {
|
||||||
_spamReportLoaderStatus = LoaderStatus.completed;
|
_spamReportLoaderStatus = LoaderStatus.completed;
|
||||||
} else {
|
} else {
|
||||||
@@ -147,6 +148,16 @@ class SpamReportController extends BaseController {
|
|||||||
presentationSpamMailbox.value = spamMailbox;
|
presentationSpamMailbox.value = spamMailbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _validateSpamMailboxChanged(GetSpamMailboxCachedFailure failure) {
|
||||||
|
if (failure.exception is NoUnreadSpamEmailsException) {
|
||||||
|
final currentSpamMailbox = presentationSpamMailbox.value;
|
||||||
|
if (currentSpamMailbox != null && currentSpamMailbox.countUnreadEmails > 0) {
|
||||||
|
_storeLastTimeDismissedSpamReportedAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setSpamPresentationMailbox(null);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
_appLifecycleListener?.dispose();
|
_appLifecycleListener?.dispose();
|
||||||
|
|||||||
Reference in New Issue
Block a user