mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 12:23:31 +00:00
Refactor notifications manager so updates and sorting happen in async operations
This commit is contained in:
parent
3c944378ae
commit
c2ab53b65e
3 changed files with 78 additions and 68 deletions
|
@ -7,7 +7,7 @@ import 'paged_response.dart';
|
|||
import 'paging_data.dart';
|
||||
|
||||
class PagesManager<TResult, TID> {
|
||||
final _pages = <PagedResponse<List<TID>>>[];
|
||||
final _pages = <PagedResponse<bool>>[];
|
||||
final List<TID> Function(TResult) idMapper;
|
||||
final FutureResult<PagedResponse<TResult>, ExecError> Function(PagingData)
|
||||
onRequest;
|
||||
|
@ -15,7 +15,14 @@ class PagesManager<TResult, TID> {
|
|||
PagesManager({
|
||||
required this.idMapper,
|
||||
required this.onRequest,
|
||||
});
|
||||
List<PagedResponse>? initialPages,
|
||||
}) {
|
||||
if (initialPages == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
initialPages.map((op) => _fromResultPage(op)).forEach(_pages.add);
|
||||
}
|
||||
|
||||
UnmodifiableListView<PagedResponse> get pages => UnmodifiableListView(_pages);
|
||||
|
||||
|
@ -23,14 +30,13 @@ class PagesManager<TResult, TID> {
|
|||
_pages.clear();
|
||||
}
|
||||
|
||||
Result<PagedResponse<List<TID>>, ExecError> pageFromId(TID id) {
|
||||
for (final p in _pages) {
|
||||
if (p.data.contains(id)) {
|
||||
return Result.ok(p);
|
||||
}
|
||||
}
|
||||
return buildErrorResult(
|
||||
type: ErrorType.notFound, message: 'ID $id not in any page');
|
||||
PagedResponse<bool> _fromResultPage(PagedResponse newPage) {
|
||||
return PagedResponse(
|
||||
true,
|
||||
id: newPage.id,
|
||||
previous: newPage.previous,
|
||||
next: newPage.next,
|
||||
);
|
||||
}
|
||||
|
||||
FutureResult<PagedResponse<TResult>, ExecError> initialize(int limit) async {
|
||||
|
@ -43,7 +49,7 @@ class PagesManager<TResult, TID> {
|
|||
if (result.isSuccess) {
|
||||
if (result.value.previous != null || result.value.next != null) {
|
||||
final newPage = result.value.map((data) => idMapper(data));
|
||||
_pages.add(newPage);
|
||||
_pages.add(_fromResultPage(newPage));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -107,9 +113,9 @@ class PagesManager<TResult, TID> {
|
|||
if (result.isSuccess && result.value.hasMorePages) {
|
||||
final newPage = result.value.map((data) => idMapper(data));
|
||||
if (asPrevious) {
|
||||
_pages.insert(currentIndex, newPage);
|
||||
_pages.insert(currentIndex, _fromResultPage(newPage));
|
||||
} else {
|
||||
_pages.insert(currentIndex + 1, newPage);
|
||||
_pages.insert(currentIndex + 1, _fromResultPage(newPage));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -20,7 +20,12 @@ import 'network_status_service.dart';
|
|||
|
||||
class NotificationsManager extends ChangeNotifier {
|
||||
static final _logger = Logger('NotificationManager');
|
||||
final _notifications = <String, UserNotification>{};
|
||||
|
||||
final dms = <UserNotification>[];
|
||||
final connectionRequests = <UserNotification>[];
|
||||
final unread = <UserNotification>[];
|
||||
final read = <UserNotification>[];
|
||||
|
||||
final _pm = PagesManager<List<UserNotification>, String>(
|
||||
idMapper: (nn) => nn.map((n) => n.id).toList(),
|
||||
onRequest: _clientGetNotificationsRequest,
|
||||
|
@ -28,43 +33,20 @@ class NotificationsManager extends ChangeNotifier {
|
|||
var _firstLoad = true;
|
||||
|
||||
List<UserNotification> get notifications {
|
||||
if (_notifications.isEmpty && _firstLoad) {
|
||||
if (_firstLoad) {
|
||||
updateNotifications();
|
||||
_firstLoad = false;
|
||||
}
|
||||
final dms = <UserNotification>[];
|
||||
final connectionRequests = <UserNotification>[];
|
||||
final unread = <UserNotification>[];
|
||||
final read = <UserNotification>[];
|
||||
for (final n in _notifications.values) {
|
||||
if (n.dismissed) {
|
||||
read.add(n);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (n.type) {
|
||||
case NotificationType.direct_message:
|
||||
dms.add(n);
|
||||
break;
|
||||
case NotificationType.follow:
|
||||
case NotificationType.follow_request:
|
||||
connectionRequests.add(n);
|
||||
break;
|
||||
default:
|
||||
unread.add(n);
|
||||
}
|
||||
}
|
||||
dms.sort();
|
||||
connectionRequests.sort();
|
||||
unread.sort();
|
||||
read.sort();
|
||||
|
||||
return [...connectionRequests, ...dms, ...unread, ...read];
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_notifications.clear();
|
||||
_pm.clear();
|
||||
dms.clear();
|
||||
connectionRequests.clear();
|
||||
unread.clear();
|
||||
read.clear();
|
||||
_firstLoad = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
@ -166,34 +148,38 @@ class NotificationsManager extends ChangeNotifier {
|
|||
.andThenSuccessAsync((fm) async => fm.update());
|
||||
}
|
||||
|
||||
_notifications.clear();
|
||||
final notifications = <String, UserNotification>{};
|
||||
|
||||
notificationsFromRefresh.removeWhere((n) =>
|
||||
n.type == NotificationType.direct_message ||
|
||||
(useActualRequests && n.type == NotificationType.follow_request));
|
||||
for (final n in notificationsFromRefresh) {
|
||||
_notifications[n.id] = n;
|
||||
notifications[n.id] = n;
|
||||
}
|
||||
|
||||
getIt<NetworkStatusService>().finishNotificationUpdate();
|
||||
for (final n in buildUnreadMessageNotifications(useActualRequests)) {
|
||||
_notifications[n.id] = n;
|
||||
notifications[n.id] = n;
|
||||
}
|
||||
|
||||
_processNewNotifications(notifications.values, clearAtStart: true);
|
||||
|
||||
notifyListeners();
|
||||
return Result.ok(notifications);
|
||||
return Result.ok(notifications.values.toList());
|
||||
}
|
||||
|
||||
FutureResult<List<UserNotification>, ExecError>
|
||||
loadNewerNotifications() async {
|
||||
final notifications = <String, UserNotification>{};
|
||||
final result = await _pm.previousFromBeginning();
|
||||
result.match(onSuccess: (response) {
|
||||
if (response.data.isEmpty) {
|
||||
return;
|
||||
}
|
||||
for (final n in response.data) {
|
||||
_notifications[n.id] = n;
|
||||
notifications[n.id] = n;
|
||||
}
|
||||
_processNewNotifications(notifications.values);
|
||||
notifyListeners();
|
||||
}, onError: (error) {
|
||||
_logger.info('Error getting more updates: $error');
|
||||
|
@ -204,16 +190,18 @@ class NotificationsManager extends ChangeNotifier {
|
|||
|
||||
FutureResult<List<UserNotification>, ExecError>
|
||||
loadOlderNotifications() async {
|
||||
final notifications = <String, UserNotification>{};
|
||||
final result = await _pm.nextFromEnd();
|
||||
result.match(onSuccess: (response) {
|
||||
for (final n in response.data) {
|
||||
_notifications[n.id] = n;
|
||||
notifications[n.id] = n;
|
||||
}
|
||||
notifyListeners();
|
||||
}, onError: (error) {
|
||||
_logger.info('Error getting more updates: $error');
|
||||
});
|
||||
|
||||
_processNewNotifications(notifications.values);
|
||||
return result.mapValue((response) => response.data);
|
||||
}
|
||||
|
||||
|
@ -237,8 +225,6 @@ class NotificationsManager extends ChangeNotifier {
|
|||
return result.errorCast();
|
||||
}
|
||||
|
||||
_pm.clear();
|
||||
_notifications.clear();
|
||||
return updateNotifications();
|
||||
}
|
||||
|
||||
|
@ -277,6 +263,42 @@ class NotificationsManager extends ChangeNotifier {
|
|||
return [...dmsResult, ...followRequestResult];
|
||||
}
|
||||
|
||||
Future<void> _processNewNotifications(
|
||||
Iterable<UserNotification> notifications, {
|
||||
bool clearAtStart = false,
|
||||
}) async {
|
||||
if (clearAtStart) {
|
||||
dms.clear();
|
||||
connectionRequests.clear();
|
||||
unread.clear();
|
||||
read.clear();
|
||||
}
|
||||
|
||||
for (final n in notifications) {
|
||||
if (n.dismissed) {
|
||||
read.add(n);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (n.type) {
|
||||
case NotificationType.direct_message:
|
||||
dms.add(n);
|
||||
break;
|
||||
case NotificationType.follow:
|
||||
case NotificationType.follow_request:
|
||||
connectionRequests.add(n);
|
||||
break;
|
||||
default:
|
||||
unread.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
dms.sort();
|
||||
connectionRequests.sort();
|
||||
unread.sort();
|
||||
read.sort();
|
||||
}
|
||||
|
||||
static FutureResult<PagedResponse<List<UserNotification>>, ExecError>
|
||||
_clientGetNotificationsRequest(PagingData page) async {
|
||||
final result =
|
||||
|
|
|
@ -60,24 +60,6 @@ void main() async {
|
|||
expect(numbers, equals(elements.map((e) => e.id)));
|
||||
_checkPagesOrder(pm.pages);
|
||||
});
|
||||
|
||||
test('Can find page by index', () async {
|
||||
final pm = _buildPagesManager();
|
||||
final initial = await pm.initialize(10);
|
||||
final next = await pm.nextWithResult(initial.value);
|
||||
final previous = await pm.previousWithResult(initial.value);
|
||||
|
||||
final initialFromQuery = pm.pageFromId(initial.value.data.first.id);
|
||||
expect(initialFromQuery.value.id, equals(initial.value.id));
|
||||
|
||||
final nextFromQuery = pm.pageFromId(next.value.data.first.id);
|
||||
expect(nextFromQuery.value.id, equals(next.value.id));
|
||||
|
||||
final previousFromQuery = pm.pageFromId(previous.value.data.first.id);
|
||||
expect(previousFromQuery.value.id, equals(previous.value.id));
|
||||
|
||||
expect(pm.pageFromId(elements.last.id).isFailure, true);
|
||||
});
|
||||
}
|
||||
|
||||
void _checkPagesOrder(UnmodifiableListView<PagedResponse> pages) {
|
||||
|
|
Loading…
Reference in a new issue