TF-3698 Thread Detail Real time update
TF-3698 Thread Detail update reset RefreshThreadDetailAction position TF-3698 Thread Detail refactor initializeThreadDetailEmails TF-3698 Thread Detail refactor handleRefreshThreadDetailAction TF-3698 Thread Detail create listThreadIds in ListEmailExtension
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
|
|||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
|
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||||
|
|
||||||
class EmailUIAction extends UIAction {
|
class EmailUIAction extends UIAction {
|
||||||
static final idle = EmailUIAction();
|
static final idle = EmailUIAction();
|
||||||
@@ -48,4 +49,13 @@ class PerformEmailActionInThreadDetailAction extends EmailUIAction {
|
|||||||
emailActionType,
|
emailActionType,
|
||||||
presentationEmail,
|
presentationEmail,
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class RefreshThreadDetailAction extends EmailUIAction {
|
||||||
|
RefreshThreadDetailAction(this.emailChangeResponse);
|
||||||
|
|
||||||
|
final EmailChangeResponse emailChangeResponse;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [emailChangeResponse];
|
||||||
}
|
}
|
||||||
@@ -437,9 +437,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
|||||||
),
|
),
|
||||||
child: LayoutBuilder(builder: (context, constraints) {
|
child: LayoutBuilder(builder: (context, constraints) {
|
||||||
return HtmlContentViewer(
|
return HtmlContentViewer(
|
||||||
key: PlatformInfo.isIntegrationTesting
|
key: controller.htmlContentViewKey,
|
||||||
? controller.htmlContentViewKey
|
|
||||||
: null,
|
|
||||||
contentHtml: allEmailContents,
|
contentHtml: allEmailContents,
|
||||||
initialWidth: constraints.maxWidth,
|
initialWidth: constraints.maxWidth,
|
||||||
direction: AppUtils.getCurrentDirection(context),
|
direction: AppUtils.getCurrentDirection(context),
|
||||||
@@ -478,9 +476,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
|||||||
),
|
),
|
||||||
child: LayoutBuilder(builder: (context, constraints) {
|
child: LayoutBuilder(builder: (context, constraints) {
|
||||||
return HtmlContentViewer(
|
return HtmlContentViewer(
|
||||||
key: PlatformInfo.isIntegrationTesting
|
key: controller.htmlContentViewKey,
|
||||||
? controller.htmlContentViewKey
|
|
||||||
: null,
|
|
||||||
contentHtml: allEmailContents,
|
contentHtml: allEmailContents,
|
||||||
initialWidth: constraints.maxWidth,
|
initialWidth: constraints.maxWidth,
|
||||||
direction: AppUtils.getCurrentDirection(context),
|
direction: AppUtils.getCurrentDirection(context),
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ class ThreadRepositoryImpl extends ThreadRepository {
|
|||||||
}
|
}
|
||||||
) async* {
|
) async* {
|
||||||
log('ThreadRepositoryImpl::refreshChanges(): $currentState');
|
log('ThreadRepositoryImpl::refreshChanges(): $currentState');
|
||||||
await _synchronizeCacheWithChanges(
|
final emailChangeResponse = await _synchronizeCacheWithChanges(
|
||||||
session,
|
session,
|
||||||
accountId,
|
accountId,
|
||||||
currentState,
|
currentState,
|
||||||
@@ -305,9 +305,9 @@ class ThreadRepositoryImpl extends ThreadRepository {
|
|||||||
propertiesCreated: propertiesCreated,
|
propertiesCreated: propertiesCreated,
|
||||||
);
|
);
|
||||||
|
|
||||||
yield networkEmailResponse;
|
yield networkEmailResponse.copyWith(emailChangeResponse: emailChangeResponse);
|
||||||
} else {
|
} else {
|
||||||
yield newEmailResponse;
|
yield newEmailResponse.copyWith(emailChangeResponse: emailChangeResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ class ThreadRepositoryImpl extends ThreadRepository {
|
|||||||
return listEmailIdDeleted;
|
return listEmailIdDeleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _synchronizeCacheWithChanges(
|
Future<EmailChangeResponse?> _synchronizeCacheWithChanges(
|
||||||
Session session,
|
Session session,
|
||||||
AccountId accountId,
|
AccountId accountId,
|
||||||
jmap.State currentState,
|
jmap.State currentState,
|
||||||
@@ -452,6 +452,8 @@ class ThreadRepositoryImpl extends ThreadRepository {
|
|||||||
await _updateState(accountId, session.username, emailChangeResponse.newStateEmail!);
|
await _updateState(accountId, session.username, emailChangeResponse.newStateEmail!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return emailChangeResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -2,16 +2,19 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||||
|
|
||||||
class EmailsResponse with EquatableMixin {
|
class EmailsResponse with EquatableMixin {
|
||||||
final List<Email>? emailList;
|
final List<Email>? emailList;
|
||||||
final List<EmailId>? notFoundEmailIds;
|
final List<EmailId>? notFoundEmailIds;
|
||||||
final State? state;
|
final State? state;
|
||||||
|
final EmailChangeResponse? emailChangeResponse;
|
||||||
|
|
||||||
const EmailsResponse({
|
const EmailsResponse({
|
||||||
this.emailList,
|
this.emailList,
|
||||||
this.notFoundEmailIds,
|
this.notFoundEmailIds,
|
||||||
this.state
|
this.state,
|
||||||
|
this.emailChangeResponse,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool hasEmails() => emailList != null && emailList!.isNotEmpty;
|
bool hasEmails() => emailList != null && emailList!.isNotEmpty;
|
||||||
@@ -21,5 +24,24 @@ class EmailsResponse with EquatableMixin {
|
|||||||
bool get existNotFoundEmails => notFoundEmailIds?.isNotEmpty == true;
|
bool get existNotFoundEmails => notFoundEmailIds?.isNotEmpty == true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [emailList, notFoundEmailIds, state];
|
List<Object?> get props => [
|
||||||
|
emailList,
|
||||||
|
notFoundEmailIds,
|
||||||
|
state,
|
||||||
|
emailChangeResponse,
|
||||||
|
];
|
||||||
|
|
||||||
|
EmailsResponse copyWith({
|
||||||
|
List<Email>? emailList,
|
||||||
|
List<EmailId>? notFoundEmailIds,
|
||||||
|
State? state,
|
||||||
|
EmailChangeResponse? emailChangeResponse,
|
||||||
|
}) {
|
||||||
|
return EmailsResponse(
|
||||||
|
emailList: emailList ?? this.emailList,
|
||||||
|
notFoundEmailIds: notFoundEmailIds ?? this.notFoundEmailIds,
|
||||||
|
state: state ?? this.state,
|
||||||
|
emailChangeResponse: emailChangeResponse ?? this.emailChangeResponse,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ import 'package:core/presentation/state/success.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/core/state.dart';
|
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||||
|
|
||||||
class RefreshChangesAllEmailLoading extends LoadingState {}
|
class RefreshChangesAllEmailLoading extends LoadingState {}
|
||||||
|
|
||||||
@@ -10,18 +11,21 @@ class RefreshChangesAllEmailSuccess extends UIState {
|
|||||||
final List<PresentationEmail> emailList;
|
final List<PresentationEmail> emailList;
|
||||||
final State? currentEmailState;
|
final State? currentEmailState;
|
||||||
final MailboxId? currentMailboxId;
|
final MailboxId? currentMailboxId;
|
||||||
|
final EmailChangeResponse? emailChangeResponse;
|
||||||
|
|
||||||
RefreshChangesAllEmailSuccess({
|
RefreshChangesAllEmailSuccess({
|
||||||
required this.emailList,
|
required this.emailList,
|
||||||
this.currentEmailState,
|
this.currentEmailState,
|
||||||
this.currentMailboxId
|
this.currentMailboxId,
|
||||||
|
this.emailChangeResponse,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
emailList,
|
emailList,
|
||||||
currentEmailState,
|
currentEmailState,
|
||||||
currentMailboxId
|
currentMailboxId,
|
||||||
|
emailChangeResponse,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -59,6 +59,8 @@ class RefreshChangesEmailsInMailboxInteractor {
|
|||||||
return Right<Failure, Success>(RefreshChangesAllEmailSuccess(
|
return Right<Failure, Success>(RefreshChangesAllEmailSuccess(
|
||||||
emailList: presentationEmailList,
|
emailList: presentationEmailList,
|
||||||
currentEmailState: emailResponse.state,
|
currentEmailState: emailResponse.state,
|
||||||
currentMailboxId: currentMailboxId));
|
currentMailboxId: currentMailboxId,
|
||||||
|
emailChangeResponse: emailResponse.emailChangeResponse,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart';
|
||||||
|
|
||||||
|
extension RefreshThreadDetailExtension on ThreadController {
|
||||||
|
void refreshThreadDetail(EmailChangeResponse? emailChangeResponse) {
|
||||||
|
if (emailChangeResponse == null) return;
|
||||||
|
|
||||||
|
mailboxDashBoardController
|
||||||
|
.dispatchEmailUIAction(RefreshThreadDetailAction(emailChangeResponse));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_em
|
|||||||
import 'package:tmail_ui_user/features/thread/domain/usecases/search_email_interactor.dart';
|
import 'package:tmail_ui_user/features/thread/domain/usecases/search_email_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/usecases/search_more_email_interactor.dart';
|
import 'package:tmail_ui_user/features/thread/domain/usecases/search_more_email_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/extensions/list_presentation_email_extensions.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/extensions/list_presentation_email_extensions.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/presentation/extensions/refresh_thread_detail_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/mixin/email_action_controller.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/mixin/email_action_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/presentation/model/loading_more_status.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/model/loading_more_status.dart';
|
||||||
@@ -697,7 +698,7 @@ class ThreadController extends BaseController with EmailActionController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Failure, Success>> _refreshChangeListEmailCache() async {
|
Future<Either<Failure, Success>> _refreshChangeListEmailCache() async {
|
||||||
return _refreshChangesEmailsInMailboxInteractor.execute(
|
final refreshState = await _refreshChangesEmailsInMailboxInteractor.execute(
|
||||||
_session!,
|
_session!,
|
||||||
_accountId!,
|
_accountId!,
|
||||||
mailboxDashBoardController.currentEmailState!,
|
mailboxDashBoardController.currentEmailState!,
|
||||||
@@ -716,6 +717,17 @@ class ThreadController extends BaseController with EmailActionController {
|
|||||||
mailboxId: selectedMailboxId,
|
mailboxId: selectedMailboxId,
|
||||||
),
|
),
|
||||||
).last;
|
).last;
|
||||||
|
|
||||||
|
refreshState.fold(
|
||||||
|
(failure) {},
|
||||||
|
(success) {
|
||||||
|
if (success is RefreshChangesAllEmailSuccess) {
|
||||||
|
refreshThreadDetail(success.emailChangeResponse);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return refreshState;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _refreshChangeListEmail() async {
|
Future<void> _refreshChangeListEmail() async {
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ class ThreadDetailRepositoryImpl implements ThreadDetailRepository {
|
|||||||
Session session,
|
Session session,
|
||||||
AccountId accountId,
|
AccountId accountId,
|
||||||
MailboxId sentMailboxId,
|
MailboxId sentMailboxId,
|
||||||
String ownEmailAddress,
|
String ownEmailAddress, {
|
||||||
) async {
|
required EmailId? selectedEmailId,
|
||||||
|
}) async {
|
||||||
final originalEmailIds = await threadDetailDataSource[DataSourceType.network]!
|
final originalEmailIds = await threadDetailDataSource[DataSourceType.network]!
|
||||||
.getThreadById(threadId, accountId);
|
.getThreadById(threadId, accountId);
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ class ThreadDetailRepositoryImpl implements ThreadDetailRepository {
|
|||||||
emailIds,
|
emailIds,
|
||||||
sentMailboxId,
|
sentMailboxId,
|
||||||
ownEmailAddress,
|
ownEmailAddress,
|
||||||
|
selectedEmailId: selectedEmailId,
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -60,8 +62,9 @@ class ThreadDetailRepositoryImpl implements ThreadDetailRepository {
|
|||||||
AccountId accountId,
|
AccountId accountId,
|
||||||
List<EmailId> emailIds,
|
List<EmailId> emailIds,
|
||||||
MailboxId sentMailboxId,
|
MailboxId sentMailboxId,
|
||||||
String ownEmailAddress,
|
String ownEmailAddress, {
|
||||||
) async {
|
required EmailId? selectedEmailId,
|
||||||
|
}) async {
|
||||||
int retry = 3;
|
int retry = 3;
|
||||||
while (retry > 0) {
|
while (retry > 0) {
|
||||||
try {
|
try {
|
||||||
@@ -85,6 +88,7 @@ class ThreadDetailRepositoryImpl implements ThreadDetailRepository {
|
|||||||
email,
|
email,
|
||||||
sentMailboxId,
|
sentMailboxId,
|
||||||
ownEmailAddress,
|
ownEmailAddress,
|
||||||
|
selectedEmailId: selectedEmailId,
|
||||||
))
|
))
|
||||||
.toList();
|
.toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -99,12 +103,14 @@ class ThreadDetailRepositoryImpl implements ThreadDetailRepository {
|
|||||||
bool checkEmailValidForThreadDetail(
|
bool checkEmailValidForThreadDetail(
|
||||||
Email email,
|
Email email,
|
||||||
MailboxId sentMailboxId,
|
MailboxId sentMailboxId,
|
||||||
String ownEmailAddress,
|
String ownEmailAddress, {
|
||||||
) {
|
required EmailId? selectedEmailId
|
||||||
|
}) {
|
||||||
return email.id != null && (
|
return email.id != null && (
|
||||||
!email.inSentMailbox(sentMailboxId)
|
!email.inSentMailbox(sentMailboxId)
|
||||||
|| !email.fromMe(ownEmailAddress)
|
|| !email.fromMe(ownEmailAddress)
|
||||||
|| !email.recipientsHasMe(ownEmailAddress)
|
|| !email.recipientsHasMe(ownEmailAddress)
|
||||||
|
|| email.id == selectedEmailId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ abstract class ThreadDetailRepository {
|
|||||||
Session session,
|
Session session,
|
||||||
AccountId accountId,
|
AccountId accountId,
|
||||||
MailboxId sentMailboxId,
|
MailboxId sentMailboxId,
|
||||||
String ownEmailAddress,
|
String ownEmailAddress, {
|
||||||
);
|
required EmailId? selectedEmailId,
|
||||||
|
});
|
||||||
|
|
||||||
Future<List<Email>> getEmailsByIds(
|
Future<List<Email>> getEmailsByIds(
|
||||||
Session session,
|
Session session,
|
||||||
|
|||||||
@@ -12,14 +12,27 @@ class GettingEmailsByIds extends LoadingState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class GetEmailsByIdsSuccess extends UIState {
|
class GetEmailsByIdsSuccess extends UIState {
|
||||||
GetEmailsByIdsSuccess(this.presentationEmails);
|
GetEmailsByIdsSuccess(
|
||||||
|
this.presentationEmails, {
|
||||||
|
this.updateCurrentThreadDetail = false,
|
||||||
|
});
|
||||||
|
|
||||||
final List<PresentationEmail> presentationEmails;
|
final List<PresentationEmail> presentationEmails;
|
||||||
|
final bool updateCurrentThreadDetail;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [presentationEmails];
|
List<Object?> get props => [presentationEmails, updateCurrentThreadDetail];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetEmailsByIdsFailure extends FeatureFailure {
|
class GetEmailsByIdsFailure extends FeatureFailure {
|
||||||
GetEmailsByIdsFailure({super.exception, super.onRetry});
|
GetEmailsByIdsFailure({
|
||||||
|
super.exception,
|
||||||
|
super.onRetry,
|
||||||
|
required this.updateCurrentThreadDetail,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool updateCurrentThreadDetail;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [...super.props, updateCurrentThreadDetail];
|
||||||
}
|
}
|
||||||
@@ -2,17 +2,34 @@ import 'package:core/presentation/state/failure.dart';
|
|||||||
import 'package:core/presentation/state/success.dart';
|
import 'package:core/presentation/state/success.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
|
|
||||||
class GettingThreadById extends LoadingState {}
|
class GettingThreadById extends LoadingState {
|
||||||
|
final bool updateCurrentThreadDetail;
|
||||||
|
|
||||||
|
GettingThreadById({this.updateCurrentThreadDetail = false});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [updateCurrentThreadDetail];
|
||||||
|
}
|
||||||
|
|
||||||
class GetThreadByIdSuccess extends UIState {
|
class GetThreadByIdSuccess extends UIState {
|
||||||
final List<EmailId> emailIds;
|
final List<EmailId> emailIds;
|
||||||
|
final bool updateCurrentThreadDetail;
|
||||||
|
|
||||||
GetThreadByIdSuccess(this.emailIds);
|
GetThreadByIdSuccess(this.emailIds, {this.updateCurrentThreadDetail = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [emailIds];
|
List<Object> get props => [emailIds, updateCurrentThreadDetail];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetThreadByIdFailure extends FeatureFailure {
|
class GetThreadByIdFailure extends FeatureFailure {
|
||||||
GetThreadByIdFailure({super.exception, super.onRetry});
|
GetThreadByIdFailure({
|
||||||
|
super.exception,
|
||||||
|
super.onRetry,
|
||||||
|
required this.updateCurrentThreadDetail,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool updateCurrentThreadDetail;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [...super.props, updateCurrentThreadDetail];
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ class GetEmailsByIdsInteractor {
|
|||||||
List<EmailId> emailIds, {
|
List<EmailId> emailIds, {
|
||||||
Properties? properties,
|
Properties? properties,
|
||||||
int? loadMoreIndex,
|
int? loadMoreIndex,
|
||||||
|
bool updateCurrentThreadDetail = false,
|
||||||
}) async* {
|
}) async* {
|
||||||
try {
|
try {
|
||||||
if (emailIds.length > 1 && (
|
if (emailIds.length > 1 && (
|
||||||
@@ -41,12 +42,14 @@ class GetEmailsByIdsInteractor {
|
|||||||
);
|
);
|
||||||
yield Right(GetEmailsByIdsSuccess(
|
yield Right(GetEmailsByIdsSuccess(
|
||||||
result.map((e) => e.toPresentationEmail()).toList(),
|
result.map((e) => e.toPresentationEmail()).toList(),
|
||||||
|
updateCurrentThreadDetail: updateCurrentThreadDetail,
|
||||||
));
|
));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('GetEmailsByIdsInteractor::execute(): Exception: $e');
|
logError('GetEmailsByIdsInteractor::execute(): Exception: $e');
|
||||||
yield Left(GetEmailsByIdsFailure(
|
yield Left(GetEmailsByIdsFailure(
|
||||||
exception: e,
|
exception: e,
|
||||||
onRetry: execute(session, accountId, emailIds, properties: properties),
|
onRetry: execute(session, accountId, emailIds, properties: properties),
|
||||||
|
updateCurrentThreadDetail: updateCurrentThreadDetail,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,19 +19,27 @@ class GetThreadByIdInteractor {
|
|||||||
Session session,
|
Session session,
|
||||||
AccountId accountId,
|
AccountId accountId,
|
||||||
MailboxId sentMailboxId,
|
MailboxId sentMailboxId,
|
||||||
String ownEmailAddress,
|
String ownEmailAddress, {
|
||||||
) async* {
|
required EmailId? selectedEmailId,
|
||||||
|
bool updateCurrentThreadDetail = false,
|
||||||
|
}) async* {
|
||||||
try {
|
try {
|
||||||
yield Right(GettingThreadById());
|
yield Right(GettingThreadById(
|
||||||
|
updateCurrentThreadDetail: updateCurrentThreadDetail,
|
||||||
|
));
|
||||||
final result = await _threadDetailRepository.getThreadById(
|
final result = await _threadDetailRepository.getThreadById(
|
||||||
threadId,
|
threadId,
|
||||||
session,
|
session,
|
||||||
accountId,
|
accountId,
|
||||||
sentMailboxId,
|
sentMailboxId,
|
||||||
ownEmailAddress,
|
ownEmailAddress,
|
||||||
|
selectedEmailId: selectedEmailId,
|
||||||
);
|
);
|
||||||
|
|
||||||
yield Right(GetThreadByIdSuccess(result));
|
yield Right(GetThreadByIdSuccess(
|
||||||
|
result,
|
||||||
|
updateCurrentThreadDetail: updateCurrentThreadDetail,
|
||||||
|
));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('GetEmailIdsByThreadIdInteractor::execute(): Exception: $e');
|
logError('GetEmailIdsByThreadIdInteractor::execute(): Exception: $e');
|
||||||
yield Left(GetThreadByIdFailure(
|
yield Left(GetThreadByIdFailure(
|
||||||
@@ -42,7 +50,9 @@ class GetThreadByIdInteractor {
|
|||||||
accountId,
|
accountId,
|
||||||
sentMailboxId,
|
sentMailboxId,
|
||||||
ownEmailAddress,
|
ownEmailAddress,
|
||||||
|
selectedEmailId: selectedEmailId,
|
||||||
),
|
),
|
||||||
|
updateCurrentThreadDetail: updateCurrentThreadDetail,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-5
@@ -1,16 +1,12 @@
|
|||||||
import 'package:core/presentation/views/loading/cupertino_loading_widget.dart';
|
import 'package:core/presentation/views/loading/cupertino_loading_widget.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||||
|
|
||||||
extension GetThreadDetailLoadingView on ThreadDetailController {
|
extension GetThreadDetailLoadingView on ThreadDetailController {
|
||||||
Widget getThreadDetailLoadingView({
|
Widget getThreadDetailLoadingView({
|
||||||
required bool isResponsiveDesktop,
|
required bool isResponsiveDesktop,
|
||||||
|
required bool isLoading,
|
||||||
}) {
|
}) {
|
||||||
final isLoading = viewState.value.fold(
|
|
||||||
(failure) => false,
|
|
||||||
(success) => success is GettingThreadById
|
|
||||||
);
|
|
||||||
if (!isLoading) return const SizedBox.shrink();
|
if (!isLoading) return const SizedBox.shrink();
|
||||||
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
|
|||||||
+21
-3
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||||
|
|
||||||
@@ -5,10 +6,27 @@ extension HandleGetEmailIdsByThreadIdSuccess on ThreadDetailController {
|
|||||||
void handleGetEmailIdsByThreadIdSuccess(
|
void handleGetEmailIdsByThreadIdSuccess(
|
||||||
GetThreadByIdSuccess success,
|
GetThreadByIdSuccess success,
|
||||||
) {
|
) {
|
||||||
|
final newEmailsInThreadDetail = <EmailId>[];
|
||||||
if (success.emailIds.isNotEmpty) {
|
if (success.emailIds.isNotEmpty) {
|
||||||
emailIdsPresentation.value = Map.fromEntries(success.emailIds.map(
|
if (success.updateCurrentThreadDetail) {
|
||||||
(emailId) => MapEntry(emailId, null),
|
newEmailsInThreadDetail.addAll(success
|
||||||
));
|
.emailIds
|
||||||
|
.where(
|
||||||
|
(emailId) => !emailIdsPresentation.keys.contains(emailId),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
emailIdsPresentation
|
||||||
|
..removeWhere(
|
||||||
|
(key, value) => !success.emailIds.contains(key),
|
||||||
|
)
|
||||||
|
..addAll(Map.fromEntries(
|
||||||
|
newEmailsInThreadDetail.map((emailId) => MapEntry(emailId, null)),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
emailIdsPresentation.value = Map.fromEntries(success.emailIds.map(
|
||||||
|
(emailId) => MapEntry(emailId, null),
|
||||||
|
));
|
||||||
|
}
|
||||||
} else if (mailboxDashBoardController.selectedEmail.value?.id != null) {
|
} else if (mailboxDashBoardController.selectedEmail.value?.id != null) {
|
||||||
emailIdsPresentation.value = {
|
emailIdsPresentation.value = {
|
||||||
mailboxDashBoardController.selectedEmail.value!.id!: null,
|
mailboxDashBoardController.selectedEmail.value!.id!: null,
|
||||||
|
|||||||
+9
@@ -18,6 +18,15 @@ extension HandleGetEmailsByIdsSuccess on ThreadDetailController {
|
|||||||
|
|
||||||
for (var presentationEmail in success.presentationEmails) {
|
for (var presentationEmail in success.presentationEmails) {
|
||||||
if (presentationEmail.id == null) continue;
|
if (presentationEmail.id == null) continue;
|
||||||
|
|
||||||
|
if (success.updateCurrentThreadDetail) {
|
||||||
|
emailIdsPresentation[presentationEmail.id!] = presentationEmail.copyWith(
|
||||||
|
emailInThreadStatus: emailIdsPresentation[presentationEmail.id!]
|
||||||
|
?.emailInThreadStatus ?? EmailInThreadStatus.collapsed,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (presentationEmail.id == selectedEmailId) {
|
if (presentationEmail.id == selectedEmailId) {
|
||||||
EmailBindings(currentEmailId: presentationEmail.id).dependencies();
|
EmailBindings(currentEmailId: presentationEmail.id).dependencies();
|
||||||
currentExpandedEmailId.value = presentationEmail.id;
|
currentExpandedEmailId.value = presentationEmail.id;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_
|
|||||||
|
|
||||||
extension HandleGetThreadByIdFailure on ThreadDetailController {
|
extension HandleGetThreadByIdFailure on ThreadDetailController {
|
||||||
void handleGetThreadByIdFailure(GetThreadByIdFailure failure) {
|
void handleGetThreadByIdFailure(GetThreadByIdFailure failure) {
|
||||||
|
if (failure.updateCurrentThreadDetail) return;
|
||||||
|
|
||||||
final selectedEmail = mailboxDashBoardController.selectedEmail.value;
|
final selectedEmail = mailboxDashBoardController.selectedEmail.value;
|
||||||
if (selectedEmail != null) {
|
if (selectedEmail != null) {
|
||||||
consumeState(Stream.value(Right(GetEmailsByIdsSuccess([selectedEmail]))));
|
consumeState(Stream.value(Right(GetEmailsByIdsSuccess([selectedEmail]))));
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:model/extensions/list_email_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_by_id_interactor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||||
|
|
||||||
|
extension HandleRefreshThreadDetailAction on ThreadDetailController {
|
||||||
|
void handleRefreshThreadDetailAction(
|
||||||
|
RefreshThreadDetailAction action,
|
||||||
|
GetThreadByIdInteractor getThreadByIdInteractor,
|
||||||
|
) {
|
||||||
|
if (!isThreadDetailEnabled) {
|
||||||
|
final currentEmailId = mailboxDashBoardController.selectedEmail.value?.id;
|
||||||
|
if (currentEmailId == null) return;
|
||||||
|
|
||||||
|
final updatedEmailIds = action
|
||||||
|
.emailChangeResponse
|
||||||
|
.updated
|
||||||
|
?.listEmailIds ?? [];
|
||||||
|
|
||||||
|
if (updatedEmailIds.contains(currentEmailId)) {
|
||||||
|
consumeState(Stream.value(Right(GetThreadByIdSuccess(
|
||||||
|
[currentEmailId],
|
||||||
|
updateCurrentThreadDetail: true,
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final currentThreadId = mailboxDashBoardController.selectedEmail.value?.threadId;
|
||||||
|
final threadIdsEmailCreated = action
|
||||||
|
.emailChangeResponse
|
||||||
|
.created
|
||||||
|
?.listThreadIds ?? [];
|
||||||
|
final threadIdsEmailUpdated = action
|
||||||
|
.emailChangeResponse
|
||||||
|
.updated
|
||||||
|
?.listThreadIds ?? [];
|
||||||
|
final updatedThreadIds = threadIdsEmailCreated + threadIdsEmailUpdated;
|
||||||
|
final destroyedEmailIds = action.emailChangeResponse.destroyed ?? [];
|
||||||
|
|
||||||
|
if (session != null &&
|
||||||
|
accountId != null &&
|
||||||
|
sentMailboxId != null &&
|
||||||
|
ownEmailAddress != null &&
|
||||||
|
currentThreadId != null && (
|
||||||
|
updatedThreadIds.contains(currentThreadId) ||
|
||||||
|
emailIdsPresentation.keys.any(destroyedEmailIds.contains))) {
|
||||||
|
consumeState(getThreadByIdInteractor.execute(
|
||||||
|
currentThreadId,
|
||||||
|
session!,
|
||||||
|
accountId!,
|
||||||
|
sentMailboxId!,
|
||||||
|
ownEmailAddress!,
|
||||||
|
updateCurrentThreadDetail: true,
|
||||||
|
selectedEmailId: mailboxDashBoardController.selectedEmail.value?.id,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
-6
@@ -1,27 +1,47 @@
|
|||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_emails_by_ids_state.dart';
|
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_emails_by_ids_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/utils/thread_detail_presentation_utils.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/utils/thread_detail_presentation_utils.dart';
|
||||||
|
|
||||||
extension InitializeThreadDetailEmails on ThreadDetailController {
|
extension InitializeThreadDetailEmails on ThreadDetailController {
|
||||||
void initializeThreadDetailEmails() {
|
void initializeThreadDetailEmails(GetThreadByIdSuccess success) {
|
||||||
final threadDetailEnabled = isThreadDetailEnabled;
|
final threadDetailEnabled = isThreadDetailEnabled;
|
||||||
final selectedEmail = mailboxDashBoardController.selectedEmail.value;
|
final selectedEmail = mailboxDashBoardController.selectedEmail.value;
|
||||||
if (!threadDetailEnabled && selectedEmail != null) {
|
if (!threadDetailEnabled &&
|
||||||
|
selectedEmail != null &&
|
||||||
|
!success.updateCurrentThreadDetail) {
|
||||||
consumeState(Stream.value(Right(GetEmailsByIdsSuccess([selectedEmail]))));
|
consumeState(Stream.value(Right(GetEmailsByIdsSuccess([selectedEmail]))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final emailIdsToLoadMetaData = ThreadDetailPresentationUtils.getFirstLoadEmailIds(
|
final existingEmailIds = emailIdsPresentation.keys.toList();
|
||||||
emailIdsPresentation.keys.toList(),
|
final selectedEmailId = mailboxDashBoardController.selectedEmail.value?.id;
|
||||||
selectedEmailId: mailboxDashBoardController.selectedEmail.value?.id,
|
|
||||||
);
|
List<EmailId> emailIdsToLoadMetaData = [];
|
||||||
|
if (success.updateCurrentThreadDetail) {
|
||||||
|
final nonNullEmailIds = emailIdsPresentation.entries
|
||||||
|
.where((entry) => entry.value != null)
|
||||||
|
.map((entry) => entry.key)
|
||||||
|
.toList();
|
||||||
|
final newEmailIds = success.emailIds.where(
|
||||||
|
(emailId) => !existingEmailIds.contains(emailId),
|
||||||
|
);
|
||||||
|
emailIdsToLoadMetaData = [...nonNullEmailIds, ...newEmailIds];
|
||||||
|
} else {
|
||||||
|
emailIdsToLoadMetaData = ThreadDetailPresentationUtils.getFirstLoadEmailIds(
|
||||||
|
existingEmailIds,
|
||||||
|
selectedEmailId: selectedEmailId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (accountId == null || session == null) {
|
if (accountId == null || session == null) {
|
||||||
consumeState(Stream.value(Left(GetEmailsByIdsFailure(
|
consumeState(Stream.value(Left(GetEmailsByIdsFailure(
|
||||||
exception: NotFoundSessionException(),
|
exception: NotFoundSessionException(),
|
||||||
|
updateCurrentThreadDetail: false,
|
||||||
))));
|
))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -33,6 +53,7 @@ extension InitializeThreadDetailEmails on ThreadDetailController {
|
|||||||
session!,
|
session!,
|
||||||
accountId!,
|
accountId!,
|
||||||
).union(additionalProperties),
|
).union(additionalProperties),
|
||||||
|
updateCurrentThreadDetail: success.updateCurrentThreadDetail,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ extension LoadMoreThreadDetailEmails on ThreadDetailController {
|
|||||||
if (accountId == null || session == null) {
|
if (accountId == null || session == null) {
|
||||||
consumeState(Stream.value(Left(GetEmailsByIdsFailure(
|
consumeState(Stream.value(Left(GetEmailsByIdsFailure(
|
||||||
exception: NotFoundSessionException(),
|
exception: NotFoundSessionException(),
|
||||||
|
updateCurrentThreadDetail: false,
|
||||||
))));
|
))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import 'package:model/extensions/keyword_identifier_extension.dart';
|
|||||||
import 'package:model/extensions/session_extension.dart';
|
import 'package:model/extensions/session_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/email/presentation/action/email_ui_action.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
||||||
@@ -43,6 +44,7 @@ import 'package:tmail_ui_user/features/thread_detail/presentation/extension/clos
|
|||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_email_ids_by_thread_id_success.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_email_ids_by_thread_id_success.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_emails_by_ids_success.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_emails_by_ids_success.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_thread_by_id_failure.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_thread_by_id_failure.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/initialize_thread_detail_emails.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/initialize_thread_detail_emails.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/refresh_thread_detail_on_setting_changed.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/refresh_thread_detail_on_setting_changed.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/model/thread_detail_setting_status.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/model/thread_detail_setting_status.dart';
|
||||||
@@ -164,6 +166,7 @@ class ThreadDetailController extends BaseController {
|
|||||||
accountId!,
|
accountId!,
|
||||||
sentMailboxId!,
|
sentMailboxId!,
|
||||||
ownEmailAddress!,
|
ownEmailAddress!,
|
||||||
|
selectedEmailId: presentationEmail.id,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -188,6 +191,15 @@ class ThreadDetailController extends BaseController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ever(mailboxDashBoardController.emailUIAction, (action) {
|
||||||
|
if (action is RefreshThreadDetailAction) {
|
||||||
|
mailboxDashBoardController.dispatchEmailUIAction(EmailUIAction());
|
||||||
|
handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
_getEmailIdsByThreadIdInteractor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
@@ -202,7 +214,7 @@ class ThreadDetailController extends BaseController {
|
|||||||
void handleSuccessViewState(success) {
|
void handleSuccessViewState(success) {
|
||||||
if (success is GetThreadByIdSuccess) {
|
if (success is GetThreadByIdSuccess) {
|
||||||
handleGetEmailIdsByThreadIdSuccess(success);
|
handleGetEmailIdsByThreadIdSuccess(success);
|
||||||
initializeThreadDetailEmails();
|
initializeThreadDetailEmails(success);
|
||||||
} else if (success is GetEmailsByIdsSuccess) {
|
} else if (success is GetEmailsByIdsSuccess) {
|
||||||
handleGetEmailsByIdsSuccess(success);
|
handleGetEmailsByIdsSuccess(success);
|
||||||
} else if (success is MarkAsEmailReadSuccess) {
|
} else if (success is MarkAsEmailReadSuccess) {
|
||||||
@@ -231,6 +243,7 @@ class ThreadDetailController extends BaseController {
|
|||||||
handleGetThreadByIdFailure(failure);
|
handleGetThreadByIdFailure(failure);
|
||||||
}
|
}
|
||||||
if (failure is GetEmailsByIdsFailure) {
|
if (failure is GetEmailsByIdsFailure) {
|
||||||
|
if (failure.updateCurrentThreadDetail) return;
|
||||||
showRetryToast(failure);
|
showRetryToast(failure);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/state/failure.dart';
|
||||||
|
import 'package:core/presentation/state/success.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -27,8 +29,7 @@ class ThreadDetailView extends GetWidget<ThreadDetailController> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Obx(() {
|
Obx(() {
|
||||||
final currentViewState = controller.viewState.value.fold(id, id);
|
if (showLoadingView(controller.viewState.value)) {
|
||||||
if (currentViewState is GettingThreadById) {
|
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,40 +69,35 @@ class ThreadDetailView extends GetWidget<ThreadDetailController> {
|
|||||||
}),
|
}),
|
||||||
Obx(() => controller.getThreadDetailLoadingView(
|
Obx(() => controller.getThreadDetailLoadingView(
|
||||||
isResponsiveDesktop: controller.responsiveUtils.isDesktop(context),
|
isResponsiveDesktop: controller.responsiveUtils.isDesktop(context),
|
||||||
|
isLoading: showLoadingView(controller.viewState.value),
|
||||||
)),
|
)),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
return controller.viewState.value.fold(
|
if (showLoadingView(controller.viewState.value)) {
|
||||||
(failure) => const SizedBox.shrink(),
|
return const SizedBox.shrink();
|
||||||
(success) {
|
}
|
||||||
if (success is GettingThreadById) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: _padding(context),
|
padding: _padding(context),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
const Positioned.fill(
|
const Positioned.fill(
|
||||||
child: ColoredBox(color: Colors.white),
|
child: ColoredBox(color: Colors.white),
|
||||||
),
|
|
||||||
SingleChildScrollView(
|
|
||||||
controller: controller.scrollController,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: controller.getThreadDetailEmailViews()
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
SingleChildScrollView(
|
||||||
);
|
controller: controller.scrollController,
|
||||||
},
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: controller.getThreadDetailEmailViews()
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
final currentViewState = controller.viewState.value.fold(id, id);
|
if (showLoadingView(controller.viewState.value)) {
|
||||||
if (currentViewState is GettingThreadById) {
|
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,10 +162,12 @@ class ThreadDetailView extends GetWidget<ThreadDetailController> {
|
|||||||
));
|
));
|
||||||
|
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final currentViewState = controller.viewState.value.fold(id, id);
|
if (showLoadingView(controller.viewState.value) &&
|
||||||
if (currentViewState is GettingThreadById &&
|
|
||||||
controller.responsiveUtils.isTabletLarge(context)) {
|
controller.responsiveUtils.isTabletLarge(context)) {
|
||||||
return controller.getThreadDetailLoadingView(isResponsiveDesktop: false);
|
return controller.getThreadDetailLoadingView(
|
||||||
|
isResponsiveDesktop: false,
|
||||||
|
isLoading: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller.emailIdsPresentation.length == 1 &&
|
if (controller.emailIdsPresentation.length == 1 &&
|
||||||
@@ -215,4 +213,10 @@ class ThreadDetailView extends GetWidget<ThreadDetailController> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool showLoadingView(Either<Failure, Success> viewState) {
|
||||||
|
final viewStateValue = viewState.fold(id, id);
|
||||||
|
return viewStateValue is GettingThreadById &&
|
||||||
|
!viewStateValue.updateCurrentThreadDetail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,8 @@ extension ListEmailExtension on List<Email> {
|
|||||||
|
|
||||||
List<EmailId> get listEmailIds => map((email) => email.id).whereNotNull().toList();
|
List<EmailId> get listEmailIds => map((email) => email.id).whereNotNull().toList();
|
||||||
|
|
||||||
|
List<ThreadId> get listThreadIds => map((email) => email.threadId).whereNotNull().toList();
|
||||||
|
|
||||||
Email? findEmailById(EmailId emailId) {
|
Email? findEmailById(EmailId emailId) {
|
||||||
try {
|
try {
|
||||||
return firstWhere((email) => email.id == emailId);
|
return firstWhere((email) => email.id == emailId);
|
||||||
|
|||||||
+5
@@ -28,9 +28,14 @@ void main() {
|
|||||||
EmailId(Id('1')),
|
EmailId(Id('1')),
|
||||||
EmailId(Id('2')),
|
EmailId(Id('2')),
|
||||||
]);
|
]);
|
||||||
|
final mailboxDashBoardController = MockMailboxDashBoardController();
|
||||||
when(threadDetailController.emailIdsPresentation).thenReturn(
|
when(threadDetailController.emailIdsPresentation).thenReturn(
|
||||||
<EmailId, PresentationEmail?>{}.obs,
|
<EmailId, PresentationEmail?>{}.obs,
|
||||||
);
|
);
|
||||||
|
when(mailboxDashBoardController.selectedEmail).thenReturn(
|
||||||
|
Rxn(PresentationEmail(id: EmailId(Id('1')))),
|
||||||
|
);
|
||||||
|
when(threadDetailController.mailboxDashBoardController).thenReturn(mailboxDashBoardController);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
threadDetailController.handleGetEmailIdsByThreadIdSuccess(success);
|
threadDetailController.handleGetEmailIdsByThreadIdSuccess(success);
|
||||||
|
|||||||
+316
@@ -0,0 +1,316 @@
|
|||||||
|
import 'package:core/presentation/state/success.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
|
import 'package:mockito/annotations.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:model/email/presentation_email.dart';
|
||||||
|
import 'package:model/extensions/session_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/data/model/email_change_response.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_by_id_interactor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||||
|
|
||||||
|
import '../../../../fixtures/account_fixtures.dart';
|
||||||
|
import '../../../../fixtures/session_fixtures.dart';
|
||||||
|
import 'handle_refresh_thread_detail_action_test.mocks.dart';
|
||||||
|
|
||||||
|
@GenerateNiceMocks([
|
||||||
|
MockSpec<ThreadDetailController>(),
|
||||||
|
MockSpec<MailboxDashBoardController>(),
|
||||||
|
MockSpec<GetThreadByIdInteractor>(),
|
||||||
|
])
|
||||||
|
void main() {
|
||||||
|
late MockThreadDetailController threadDetailController;
|
||||||
|
late MockMailboxDashBoardController mailboxDashBoardController;
|
||||||
|
late MockGetThreadByIdInteractor getThreadByIdInteractor;
|
||||||
|
|
||||||
|
final sentMailboxId = MailboxId(Id('sent'));
|
||||||
|
final ownEmailAddress = SessionFixtures.aliceSession.getOwnEmailAddress();
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
threadDetailController = MockThreadDetailController();
|
||||||
|
mailboxDashBoardController = MockMailboxDashBoardController();
|
||||||
|
getThreadByIdInteractor = MockGetThreadByIdInteractor();
|
||||||
|
});
|
||||||
|
|
||||||
|
group('handle refresh thread detail action test', () {
|
||||||
|
test(
|
||||||
|
'should call getThreadByIdInteractor.execute '
|
||||||
|
'when refreshThreadDetailAction is called '
|
||||||
|
'and list email created contains currentThreadId '
|
||||||
|
'and isThreadDetailEnabled is true',
|
||||||
|
() {
|
||||||
|
// arrange
|
||||||
|
final emailId = EmailId(Id('1'));
|
||||||
|
final threadId = ThreadId(Id('some-id'));
|
||||||
|
final action = RefreshThreadDetailAction(EmailChangeResponse(
|
||||||
|
created: [Email(id: emailId, threadId: threadId)],
|
||||||
|
));
|
||||||
|
when(threadDetailController.mailboxDashBoardController)
|
||||||
|
.thenReturn(mailboxDashBoardController);
|
||||||
|
when(mailboxDashBoardController.selectedEmail)
|
||||||
|
.thenReturn(Rxn(PresentationEmail(id: emailId, threadId: threadId)));
|
||||||
|
when(threadDetailController.session)
|
||||||
|
.thenReturn(SessionFixtures.aliceSession);
|
||||||
|
when(threadDetailController.accountId)
|
||||||
|
.thenReturn(AccountFixtures.aliceAccountId);
|
||||||
|
when(threadDetailController.sentMailboxId).thenReturn(sentMailboxId);
|
||||||
|
when(threadDetailController.ownEmailAddress).thenReturn(ownEmailAddress);
|
||||||
|
when(threadDetailController.isThreadDetailEnabled).thenReturn(true);
|
||||||
|
|
||||||
|
// act
|
||||||
|
threadDetailController.handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
getThreadByIdInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
verify(getThreadByIdInteractor.execute(
|
||||||
|
threadId,
|
||||||
|
SessionFixtures.aliceSession,
|
||||||
|
AccountFixtures.aliceAccountId,
|
||||||
|
sentMailboxId,
|
||||||
|
ownEmailAddress,
|
||||||
|
updateCurrentThreadDetail: true,
|
||||||
|
selectedEmailId: emailId,
|
||||||
|
)).called(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should call getThreadByIdInteractor.execute '
|
||||||
|
'when refreshThreadDetailAction is called '
|
||||||
|
'and list email updated contains currentThreadId '
|
||||||
|
'and isThreadDetailEnabled is true',
|
||||||
|
() {
|
||||||
|
// arrange
|
||||||
|
final emailId = EmailId(Id('1'));
|
||||||
|
final threadId = ThreadId(Id('some-id'));
|
||||||
|
final action = RefreshThreadDetailAction(EmailChangeResponse(
|
||||||
|
updated: [Email(id: emailId, threadId: threadId)],
|
||||||
|
));
|
||||||
|
when(threadDetailController.mailboxDashBoardController)
|
||||||
|
.thenReturn(mailboxDashBoardController);
|
||||||
|
when(mailboxDashBoardController.selectedEmail)
|
||||||
|
.thenReturn(Rxn(PresentationEmail(id: emailId, threadId: threadId)));
|
||||||
|
when(threadDetailController.session)
|
||||||
|
.thenReturn(SessionFixtures.aliceSession);
|
||||||
|
when(threadDetailController.accountId)
|
||||||
|
.thenReturn(AccountFixtures.aliceAccountId);
|
||||||
|
when(threadDetailController.sentMailboxId).thenReturn(sentMailboxId);
|
||||||
|
when(threadDetailController.ownEmailAddress).thenReturn(ownEmailAddress);
|
||||||
|
when(threadDetailController.isThreadDetailEnabled).thenReturn(true);
|
||||||
|
|
||||||
|
// act
|
||||||
|
threadDetailController.handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
getThreadByIdInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
verify(getThreadByIdInteractor.execute(
|
||||||
|
threadId,
|
||||||
|
SessionFixtures.aliceSession,
|
||||||
|
AccountFixtures.aliceAccountId,
|
||||||
|
sentMailboxId,
|
||||||
|
ownEmailAddress,
|
||||||
|
updateCurrentThreadDetail: true,
|
||||||
|
selectedEmailId: emailId,
|
||||||
|
)).called(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should call getThreadByIdInteractor.execute '
|
||||||
|
'when refreshThreadDetailAction is called '
|
||||||
|
'and list email destroyed contains any of emailId in current thread '
|
||||||
|
'and isThreadDetailEnabled is true',
|
||||||
|
() {
|
||||||
|
// arrange
|
||||||
|
final emailId = EmailId(Id('1'));
|
||||||
|
final threadId = ThreadId(Id('some-id'));
|
||||||
|
final action = RefreshThreadDetailAction(EmailChangeResponse(
|
||||||
|
destroyed: [emailId],
|
||||||
|
));
|
||||||
|
when(threadDetailController.mailboxDashBoardController)
|
||||||
|
.thenReturn(mailboxDashBoardController);
|
||||||
|
when(mailboxDashBoardController.selectedEmail)
|
||||||
|
.thenReturn(Rxn(PresentationEmail(id: emailId, threadId: threadId)));
|
||||||
|
when(threadDetailController.session)
|
||||||
|
.thenReturn(SessionFixtures.aliceSession);
|
||||||
|
when(threadDetailController.accountId)
|
||||||
|
.thenReturn(AccountFixtures.aliceAccountId);
|
||||||
|
when(threadDetailController.sentMailboxId).thenReturn(sentMailboxId);
|
||||||
|
when(threadDetailController.ownEmailAddress).thenReturn(ownEmailAddress);
|
||||||
|
when(threadDetailController.emailIdsPresentation).thenReturn({
|
||||||
|
emailId: null
|
||||||
|
}.obs);
|
||||||
|
when(threadDetailController.isThreadDetailEnabled).thenReturn(true);
|
||||||
|
|
||||||
|
// act
|
||||||
|
threadDetailController.handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
getThreadByIdInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
verify(getThreadByIdInteractor.execute(
|
||||||
|
threadId,
|
||||||
|
SessionFixtures.aliceSession,
|
||||||
|
AccountFixtures.aliceAccountId,
|
||||||
|
sentMailboxId,
|
||||||
|
ownEmailAddress,
|
||||||
|
updateCurrentThreadDetail: true,
|
||||||
|
selectedEmailId: emailId,
|
||||||
|
)).called(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should consume GetThreadByIdSuccess with selected email id '
|
||||||
|
'when refreshThreadDetailAction is called '
|
||||||
|
'and isThreadDetailEnabled is false '
|
||||||
|
'and selected email id not null '
|
||||||
|
'and list email updated contains selected email id',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final emailId = EmailId(Id('1'));
|
||||||
|
final action = RefreshThreadDetailAction(EmailChangeResponse(
|
||||||
|
updated: [Email(id: emailId)],
|
||||||
|
));
|
||||||
|
when(threadDetailController.mailboxDashBoardController)
|
||||||
|
.thenReturn(mailboxDashBoardController);
|
||||||
|
when(mailboxDashBoardController.selectedEmail)
|
||||||
|
.thenReturn(Rxn(PresentationEmail(id: emailId)));
|
||||||
|
when(threadDetailController.isThreadDetailEnabled).thenReturn(false);
|
||||||
|
|
||||||
|
// act
|
||||||
|
threadDetailController.handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
getThreadByIdInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
verifyNever(getThreadByIdInteractor.execute(
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
updateCurrentThreadDetail: anyNamed('updateCurrentThreadDetail'),
|
||||||
|
selectedEmailId: anyNamed('selectedEmailId'),
|
||||||
|
));
|
||||||
|
final args = verify(
|
||||||
|
threadDetailController.consumeState(captureAny),
|
||||||
|
).captured.first as Stream;
|
||||||
|
final state = await args.last;
|
||||||
|
expect(
|
||||||
|
state,
|
||||||
|
Right(GetThreadByIdSuccess(
|
||||||
|
[emailId],
|
||||||
|
updateCurrentThreadDetail: true,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should not call getThreadByIdInteractor.execute '
|
||||||
|
'and not consume GetThreadByIdSuccess with selected email id'
|
||||||
|
'when refreshThreadDetailAction is called '
|
||||||
|
'and list email created does not contain currentThreadId '
|
||||||
|
'and list email updated does not contain currentThreadId '
|
||||||
|
'and list email destroyed does not contain any of emailId in current thread '
|
||||||
|
'and isThreadDetailEnabled is true',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final emailId = EmailId(Id('1'));
|
||||||
|
final action = RefreshThreadDetailAction(EmailChangeResponse(
|
||||||
|
created: [
|
||||||
|
Email(id: EmailId(Id('2')), threadId: ThreadId(Id('some-id-2'))),
|
||||||
|
],
|
||||||
|
updated: [
|
||||||
|
Email(id: EmailId(Id('3')), threadId: ThreadId(Id('some-id-3'))),
|
||||||
|
],
|
||||||
|
destroyed: [
|
||||||
|
EmailId(Id('4')),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
when(threadDetailController.mailboxDashBoardController)
|
||||||
|
.thenReturn(mailboxDashBoardController);
|
||||||
|
when(mailboxDashBoardController.selectedEmail)
|
||||||
|
.thenReturn(Rxn(PresentationEmail()));
|
||||||
|
when(threadDetailController.session)
|
||||||
|
.thenReturn(SessionFixtures.aliceSession);
|
||||||
|
when(threadDetailController.accountId)
|
||||||
|
.thenReturn(AccountFixtures.aliceAccountId);
|
||||||
|
when(threadDetailController.sentMailboxId).thenReturn(sentMailboxId);
|
||||||
|
when(threadDetailController.ownEmailAddress).thenReturn(ownEmailAddress);
|
||||||
|
when(threadDetailController.emailIdsPresentation).thenReturn({
|
||||||
|
emailId: null,
|
||||||
|
}.obs);
|
||||||
|
when(threadDetailController.viewState).thenReturn(Rx(Right(UIState.idle)));
|
||||||
|
when(threadDetailController.isThreadDetailEnabled).thenReturn(true);
|
||||||
|
|
||||||
|
// act
|
||||||
|
threadDetailController.handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
getThreadByIdInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
verifyNever(getThreadByIdInteractor.execute(
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
updateCurrentThreadDetail: anyNamed('updateCurrentThreadDetail'),
|
||||||
|
selectedEmailId: anyNamed('selectedEmailId'),
|
||||||
|
));
|
||||||
|
verifyNever(threadDetailController.consumeState(any));
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should not call getThreadByIdInteractor.execute '
|
||||||
|
'and not consume GetThreadByIdSuccess with selected email id'
|
||||||
|
'when refreshThreadDetailAction is called '
|
||||||
|
'and isThreadDetailEnabled is false '
|
||||||
|
'and updated email ids does not contain selected email id',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final emailId = EmailId(Id('1'));
|
||||||
|
final action = RefreshThreadDetailAction(EmailChangeResponse(
|
||||||
|
updated: [
|
||||||
|
Email(id: EmailId(Id('3')), threadId: ThreadId(Id('some-id-3'))),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
when(threadDetailController.mailboxDashBoardController)
|
||||||
|
.thenReturn(mailboxDashBoardController);
|
||||||
|
when(mailboxDashBoardController.selectedEmail)
|
||||||
|
.thenReturn(Rxn(PresentationEmail(id: emailId)));
|
||||||
|
when(threadDetailController.isThreadDetailEnabled).thenReturn(false);
|
||||||
|
|
||||||
|
// act
|
||||||
|
threadDetailController.handleRefreshThreadDetailAction(
|
||||||
|
action,
|
||||||
|
getThreadByIdInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
verifyNever(getThreadByIdInteractor.execute(
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
updateCurrentThreadDetail: anyNamed('updateCurrentThreadDetail'),
|
||||||
|
selectedEmailId: anyNamed('selectedEmailId'),
|
||||||
|
));
|
||||||
|
verifyNever(threadDetailController.consumeState(any));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
+4
-1
@@ -8,6 +8,7 @@ import 'package:mockito/annotations.dart';
|
|||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_emails_by_ids_interactor.dart';
|
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_emails_by_ids_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/initialize_thread_detail_emails.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/initialize_thread_detail_emails.dart';
|
||||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||||
@@ -65,7 +66,9 @@ void main() {
|
|||||||
.thenReturn(Rxn(PresentationEmail()));
|
.thenReturn(Rxn(PresentationEmail()));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
threadDetailController.initializeThreadDetailEmails();
|
threadDetailController.initializeThreadDetailEmails(
|
||||||
|
GetThreadByIdSuccess(emailIds),
|
||||||
|
);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
final captured = verify(getEmailsByIdsInteractor.execute(
|
final captured = verify(getEmailsByIdsInteractor.execute(
|
||||||
|
|||||||
+2
@@ -144,6 +144,7 @@ void main() {
|
|||||||
when(controller.accountId).thenReturn(AccountFixtures.aliceAccountId);
|
when(controller.accountId).thenReturn(AccountFixtures.aliceAccountId);
|
||||||
when(controller.additionalProperties).thenReturn(Properties.empty());
|
when(controller.additionalProperties).thenReturn(Properties.empty());
|
||||||
when(controller.getEmailsByIdsInteractor).thenReturn(getEmailsByIdsInteractor);
|
when(controller.getEmailsByIdsInteractor).thenReturn(getEmailsByIdsInteractor);
|
||||||
|
when(controller.additionalProperties).thenReturn(Properties.empty());
|
||||||
when(controller.mailboxDashBoardController).thenReturn(mailboxDashBoardController);
|
when(controller.mailboxDashBoardController).thenReturn(mailboxDashBoardController);
|
||||||
when(mailboxDashBoardController.selectedEmail).thenReturn(Rxn());
|
when(mailboxDashBoardController.selectedEmail).thenReturn(Rxn());
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ void main() {
|
|||||||
when(controller.accountId).thenReturn(AccountFixtures.aliceAccountId);
|
when(controller.accountId).thenReturn(AccountFixtures.aliceAccountId);
|
||||||
when(controller.additionalProperties).thenReturn(Properties.empty());
|
when(controller.additionalProperties).thenReturn(Properties.empty());
|
||||||
when(controller.getEmailsByIdsInteractor).thenReturn(getEmailsByIdsInteractor);
|
when(controller.getEmailsByIdsInteractor).thenReturn(getEmailsByIdsInteractor);
|
||||||
|
when(controller.additionalProperties).thenReturn(Properties.empty());
|
||||||
when(controller.mailboxDashBoardController).thenReturn(mailboxDashBoardController);
|
when(controller.mailboxDashBoardController).thenReturn(mailboxDashBoardController);
|
||||||
when(mailboxDashBoardController.selectedEmail).thenReturn(Rxn());
|
when(mailboxDashBoardController.selectedEmail).thenReturn(Rxn());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user