Skip to content

Instantly share code, notes, and snippets.

@locskot
Created June 11, 2021 05:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save locskot/a35b8c345b07c9049cf19b9635be85d0 to your computer and use it in GitHub Desktop.
Save locskot/a35b8c345b07c9049cf19b9635be85d0 to your computer and use it in GitHub Desktop.
import 'package:components/api/graphql_api.dart';
import 'package:components/base/base_viewmodel.dart';
import 'package:components/events/event_sender.dart';
import 'package:components/model/request_result_model.dart';
import 'package:rxdart/rxdart.dart';
import 'notification.dart';
import 'notifications_repository.dart';
enum NotificationsViewEvent { requestUpdateRead, onNotificationTap }
abstract class NotificationsViewModel extends BaseViewModel<MockNotification, NotificationsViewEvent, bool> {
NotificationsViewModel(GraphqlAPI graphqlAPI, EventSender eventSender) : super(graphqlAPI, eventSender);
factory NotificationsViewModel.create(GraphqlAPI graphqlAPI, EventSender eventSender) {
return NotificationsViewModelImpl(graphqlAPI, eventSender);
}
MockNotification pressedNotification;
Stream<int> get unreadCountStream;
void requestReadUpdate();
void showUnreadCount();
Future<void> loadNotifications();
Future<void> processReadUpdate(List<MockNotification> notifications);
Future<void> repeatProcessReadUpdate();
Future<void> onNotificationPress(MockNotification notification);
}
class NotificationsViewModelImpl extends NotificationsViewModel {
NotificationsRepository notificationsRepository;
final unreadCountSubject = PublishSubject<int>();
final processingIds = <String>[];
final repeatProcessingIds = <String>[];
NotificationsViewModelImpl(GraphqlAPI graphqlAPI, EventSender eventSender) : super(graphqlAPI, eventSender) {
notificationsRepository = NotificationsRepository.create(graphqlAPI);
super.startSocketListening((connected) async {
if (connected) {
await repeatProcessReadUpdate();
loadNotifications();
} else {
loading = false;
}
});
super.startServerListening((event) async {
//TODO react on imcoming events here
});
}
@override
void onRemove() {
stopSocketListening();
stopServerListening();
}
Stream<int> get unreadCountStream => unreadCountSubject.stream;
@override
void requestReadUpdate() => uiEventSubject.add(NotificationsViewEvent.requestUpdateRead);
@override
Future<void> loadNotifications() async {
if (loading == true) {
return;
}
loading = true;
final result = await notificationsRepository.loadNotifications();
if (result.result) {
silenceClearItems();
silenceAddRange(result.value);
}
loading = false;
showUnreadCount();
await Future.delayed(Duration(milliseconds: 100));
requestReadUpdate();
}
@override
Future<void> processReadUpdate(List<MockNotification> notifications) async {
final currentRunProcessingIds = <String>[];
for (var i = 0; i < notifications.length; i++) {
final notification = notifications[i];
if (!processingIds.contains(notification.id)) {
processingIds.add(notification.id);
currentRunProcessingIds.add(notification.id);
}
}
if (currentRunProcessingIds.isEmpty) {
//notifications are already processing, but a result is undetermined yet.
return;
}
final result = await notificationsRepository.markAsRead(currentRunProcessingIds);
if (result.result) {
updateItemsOnRead(result);
} else {
repeatProcessingIds.addAll(currentRunProcessingIds);
}
}
@override
Future<void> repeatProcessReadUpdate() async {
final result = await notificationsRepository.markAsRead(repeatProcessingIds);
if (result.result) {
updateItemsOnRead(result);
}
}
@override
Future<void> onNotificationPress(MockNotification notification) async {
if (pressedNotification != null) {
return;
}
pressedNotification = notification;
uiEventSubject.add(NotificationsViewEvent.onNotificationTap);
}
void updateItemsOnRead(RequestResultModel result) {
final processedData = result.value as List<String>;
for (var i = 0; i < processedData.length; i++) {
final id = processedData[i];
final item = items.firstWhere((e) => e.id == id, orElse: () => null);
if (item != null) {
item.readIsSent = true;
}
repeatProcessingIds.remove(id);
processingIds.remove(id);
}
showUnreadCount();
}
@override
void showUnreadCount() {
final unreadCount = items.where((e) => !e.isRead && !e.readIsSent).toList().length;
unreadCountSubject.add(unreadCount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment