Skip to content

Commit

Permalink
TF-3298 Fix blink when refresh email list (#3299)
Browse files Browse the repository at this point in the history
  • Loading branch information
dab246 authored Nov 25, 2024
1 parent 2678f4b commit d339dd8
Show file tree
Hide file tree
Showing 5 changed files with 399 additions and 88 deletions.
23 changes: 12 additions & 11 deletions lib/features/thread/data/extensions/list_email_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,24 @@ extension ListEmailExtension on List<Email> {
};
}

List<Email> sortingByOrderOfIdList(List<Id> ids) {
if (ids.length != length) {
return this;
}
List<Email> sortEmailsById(List<Id> referenceIds) {
final indexMap = {
for (var i = 0; i < referenceIds.length; i++)
referenceIds[i]: i
};

sort((email1, email2) {
final id1 = email1.id?.id;
final id2 = email2.id?.id;
final emailId1 = email1.id?.id;
final emailId2 = email2.id?.id;

if (id1 == null || id2 == null) {
return 0;
if (emailId1 == null || emailId2 == null) {
return emailId1 == null ? 1 : -1;
}

final index1 = ids.indexWhere((id) => id == id1);
final index2 = ids.indexWhere((id) => id == id2);
final indexEmail1 = indexMap[emailId1] ?? double.maxFinite;
final indexEmail2 = indexMap[emailId2] ?? double.maxFinite;

return index1.compareTo(index2);
return indexEmail1.compareTo(indexEmail2);
});

return this;
Expand Down
49 changes: 26 additions & 23 deletions lib/features/thread/data/network/thread_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import 'package:jmap_dart_client/jmap/mail/email/get/get_email_method.dart';
import 'package:jmap_dart_client/jmap/mail/email/get/get_email_response.dart';
import 'package:jmap_dart_client/jmap/mail/email/query/query_email_method.dart';
import 'package:jmap_dart_client/jmap/mail/email/query/query_email_response.dart';
import 'package:model/extensions/list_email_extension.dart';
import 'package:tmail_ui_user/features/thread/data/extensions/list_email_extension.dart';
import 'package:jmap_dart_client/jmap/mail/email/search_snippet/search_snippet.dart';
import 'package:jmap_dart_client/jmap/mail/email/search_snippet/search_snippet_get_method.dart';
Expand Down Expand Up @@ -91,24 +90,33 @@ class ThreadAPI {
QueryEmailResponse.deserialize,
);

List<Email>? emailList;
final emailList = sortEmails(
getEmailResponse: responseOfGetEmailMethod,
queryEmailResponse: responseOfQueryEmailMethod,
);

if (responseOfGetEmailMethod?.list.isNotEmpty == true &&
responseOfQueryEmailMethod?.ids.isNotEmpty == true) {
log('ThreadAPI::getAllEmail: QUERY_EMAIL_IDS = ${responseOfQueryEmailMethod?.ids}');
final listSortedEmail = responseOfGetEmailMethod!.list
.sortingByOrderOfIdList(responseOfQueryEmailMethod!.ids.toList());
emailList = listSortedEmail;
} else {
emailList = responseOfGetEmailMethod?.list;
}
log('ThreadAPI::getAllEmail: EMAIL_DISPLAYED_IDS = ${emailList?.listEmailIds}');
return EmailsResponse(
emailList: emailList,
state: responseOfGetEmailMethod?.state,
);
}

List<Email>? sortEmails({
GetEmailResponse? getEmailResponse,
QueryEmailResponse? queryEmailResponse,
}) {
final listEmails = getEmailResponse?.list;
final listIds = queryEmailResponse?.ids.toList();

if (listEmails?.isNotEmpty != true || listIds?.isNotEmpty != true) {
return listEmails;
}

final listSortedEmails = listEmails!.sortEmailsById(listIds!);

return listSortedEmails;
}

Future<SearchEmailsResponse> searchEmails(
Session session,
AccountId accountId,
Expand Down Expand Up @@ -166,29 +174,24 @@ class ThreadAPI {
.build()
.execute();

final emailResultList = result.parse<GetEmailResponse>(
final responseOfGetEmailMethod = result.parse<GetEmailResponse>(
getEmailInvocation.methodCallId, GetEmailResponse.deserialize);
final responseOfQueryEmailMethod = result.parse<QueryEmailResponse>(
queryEmailInvocation.methodCallId,
QueryEmailResponse.deserialize);

List<Email>? sortedEmailList;

if (emailResultList?.list.isNotEmpty == true &&
responseOfQueryEmailMethod?.ids.isNotEmpty == true) {
sortedEmailList = emailResultList!.list
.sortingByOrderOfIdList(responseOfQueryEmailMethod!.ids.toList());
} else {
sortedEmailList = emailResultList?.list;
}
final sortedEmailList = sortEmails(
getEmailResponse: responseOfGetEmailMethod,
queryEmailResponse: responseOfQueryEmailMethod,
);

final searchSnippets = _getSearchSnippetsFromResponse(
result,
getSearchSnippetMethodCallId: getSearchSnippetInvocation.methodCallId,
);
return SearchEmailsResponse(
emailList: sortedEmailList,
state: emailResultList?.state,
state: responseOfGetEmailMethod?.state,
searchSnippets: searchSnippets);
}

Expand Down
54 changes: 0 additions & 54 deletions test/features/email/sorting_list_email_by_order_id_list_test.dart

This file was deleted.

166 changes: 166 additions & 0 deletions test/features/thread/data/extensions/list_email_extension_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/extensions/email_id_extensions.dart';
import 'package:tmail_ui_user/features/thread/data/extensions/list_email_extension.dart';

void main() {
group('ListEmailExtension::sortEmailsById::test', () {
test('Sort the full list', () {
final referenceIds = <Id>[
Id('id1'),
Id('id2'),
Id('id3'),
Id('id4'),
];

final emails = <Email>[
Email(id: EmailId(Id('id3'))),
Email(id: EmailId(Id('id1'))),
Email(id: EmailId(Id('id4'))),
Email(id: EmailId(Id('id2'))),
];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
['id1', 'id2', 'id3', 'id4'],
);
});

test('Emails list has more elements than referenceIds', () {
final referenceIds = <Id>[
Id('id1'),
Id('id2'),
Id('id3'),
];

final emails = <Email>[
Email(id: EmailId(Id('id3'))),
Email(id: EmailId(Id('id4'))),
Email(id: EmailId(Id('id1'))),
Email(id: EmailId(Id('id5'))),
Email(id: EmailId(Id('id2'))),
];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
['id1', 'id2', 'id3', 'id4', 'id5'],
);
});

test('Emails list has fewer elements than referenceIds', () {
final referenceIds = <Id>[
Id('id1'),
Id('id2'),
Id('id3'),
Id('id4'),
];

final emails = <Email>[
Email(id: EmailId(Id('id3'))),
Email(id: EmailId(Id('id1'))),
];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
['id1', 'id3'],
);
});

test('Emails list is empty', () {
final referenceIds = <Id>[
Id('id1'),
Id('id2'),
Id('id3'),
];

final emails = <Email>[];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
[],
);
});

test('ReferenceIds list is empty', () {
final referenceIds = <Id>[];

final emails = <Email>[
Email(id: EmailId(Id('id3'))),
Email(id: EmailId(Id('id4'))),
Email(id: EmailId(Id('id1'))),
Email(id: EmailId(Id('id5'))),
];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
['id3', 'id4', 'id1', 'id5'],
);
});

test('Both lists are empty', () {
final referenceIds = <Id>[];
final emails = <Email>[];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
[],
);
});

test('Emails have ids that do not match referenceIds', () {
final referenceIds = <Id>[
Id('id1'),
Id('id2'),
];

final emails = <Email>[
Email(id: EmailId(Id('id3'))),
Email(id: EmailId(Id('id4'))),
Email(id: EmailId(Id('id5'))),
];

final result = emails.sortEmailsById(referenceIds);

expect(
result.map((e) => e.id!.asString).toList(),
['id3', 'id4', 'id5'],
);
});

test('should keep emails with null IDs in their original order at the end', () {
// Arrange
final referenceIds = [
Id('id2'),
Id('id1'),
];

final emails = [
Email(id: EmailId(Id('id1'))),
Email(id: null),
Email(id: EmailId(Id('id2'))),
];

// Act
final sortedEmails = emails.sortEmailsById(referenceIds);

// Assert
expect(
sortedEmails.map((e) => e.id?.asString).toList(),
['id2', 'id1', null],
);
});
});
}
Loading

0 comments on commit d339dd8

Please sign in to comment.