forked from eatvio/eatvio_app
218 lines
8.6 KiB
Dart
218 lines
8.6 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:developer';
|
|
|
|
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
|
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
|
|
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_state.dart';
|
|
import 'package:eatvio_app/features/notifications/repository/notifications_repository.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
class NotificationsCubit extends Cubit<NotificationsState> {
|
|
final List<BaseNotificationModel> _notifications = [];
|
|
final WsManager wsManager;
|
|
final NotificationsRepository notificationsRepository;
|
|
StreamSubscription? _newNotificationsSubscription;
|
|
NotificationsCubit({required this.wsManager, required this.notificationsRepository}) : super(const NotificationsState.empty());
|
|
|
|
Future<void> connectToWebSocket() async {
|
|
await _newNotificationsSubscription?.cancel();
|
|
_newNotificationsSubscription = wsManager.newNotificationsStream?.listen((event) {
|
|
_handleNotification(event.data);
|
|
});
|
|
}
|
|
|
|
BaseNotificationModel _parseNotification(Map<String, dynamic> notificationJson, NotificationType type) {
|
|
try {
|
|
final createdAt = notificationJson['created_at'];
|
|
final isRead = notificationJson['read_at'] != null;
|
|
|
|
return switch (type) {
|
|
NotificationType.planSubscriptionStartedToAuthor => PlanSubscriptionStartedToAuthorNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.planSubscriptionCanceledToAuthor => PlanSubscriptionCanceledToAuthorNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanStartedToClientNotification => ChosenPlanStartedToClientNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanTomorrowReminderToClientNotification => ChosenPlanTomorrowReminderToClientNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanConsultantLastDayStarted => ChosenPlanConsultantLastDayStarted.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.diaryReminderNotification => DiaryReminderNotification.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
|
NotificationType.consultantLeftComment => ConsultantLeftCommentNotification.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
|
NotificationType.personalizedDietIsDefined => PersonalizedDietIsDefinedNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanFinishedToClient => ChosenPlanFinishedToClientNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.planSubscriptionCanceledToCustomer => PlanSubscriptionCanceledToAuthorNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanStartedToConsultantNotification => ChosenPlanStartedToConsultantNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanTomorrowReminderToConsultantNotification => ChosenPlanTomorrowReminderToConsultantNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.planSubscriptionPaidToAuthor => PlanSubscriptionPaidToAuthorNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanFinishedToConsultant => ChosenPlanFinishedToConsultantNotification.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
NotificationType.chosenPlanLastDayFinishedForUser => ChosenPlanLastDayFinishedForUser.fromJson(
|
|
notificationJson,
|
|
type,
|
|
isRead: isRead,
|
|
createdAt: createdAt,
|
|
),
|
|
// New notification types
|
|
NotificationType.complaintToModerationForUser => ComplaintToModerationForUser.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
|
NotificationType.commentReplied => CommentReplied.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
|
NotificationType.scoreAdded => ScoreAdded.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
|
NotificationType.entityCommented => EntityCommented.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
|
NotificationType.unknown => UnknownNotification(type: type),
|
|
};
|
|
} catch (e) {
|
|
return UnknownNotification(type: NotificationType.unknown);
|
|
}
|
|
}
|
|
|
|
void _handleNotification(String notificationData) {
|
|
final json = jsonDecode(notificationData) as Map<String, dynamic>;
|
|
final stringifiedType = json['notification_class_name'];
|
|
final type = NotificationType.getTypeFromString(stringifiedType);
|
|
final notification = _parseNotification(json, type);
|
|
_notifications.insert(0, notification);
|
|
|
|
final currentState = state;
|
|
if (currentState is NotificationsStateLoaded) {
|
|
emit(currentState.copyWith(notifications: _notifications, notificationsCount: _notifications.length, hasUnreadNotifications: true));
|
|
}
|
|
}
|
|
|
|
Future<void> getNotifications() async {
|
|
try {
|
|
final result = await notificationsRepository.getNotifications(page: 1);
|
|
if (result != null) {
|
|
final notifications = result['notifications'] as List<BaseNotificationModel>;
|
|
final pagination = result['pagination'] as Map<String, dynamic>;
|
|
|
|
_notifications.clear();
|
|
_notifications.addAll(notifications);
|
|
|
|
final currentPage = pagination['current_page'] as int;
|
|
final lastPage = pagination['last_page'] as int;
|
|
final hasNextPage = currentPage < lastPage;
|
|
|
|
emit(
|
|
NotificationsState.loaded(
|
|
notifications: _notifications,
|
|
notificationsCount: _notifications.length,
|
|
hasUnreadNotifications: notifications.where((elem) => elem.isRead == false).isNotEmpty,
|
|
currentPage: currentPage,
|
|
hasNextPage: hasNextPage,
|
|
),
|
|
);
|
|
}
|
|
} catch (e, st) {
|
|
log(e.toString(), stackTrace: st);
|
|
}
|
|
}
|
|
|
|
Future<void> loadMoreNotifications() async {
|
|
final currentState = state;
|
|
if (currentState is NotificationsStateLoaded && currentState.hasNextPage && !currentState.isLoadingMore) {
|
|
try {
|
|
emit(currentState.copyWith(isLoadingMore: true));
|
|
|
|
final nextPage = currentState.currentPage + 1;
|
|
final result = await notificationsRepository.getNotifications(page: nextPage);
|
|
|
|
if (result != null) {
|
|
final newNotifications = result['notifications'] as List<BaseNotificationModel>;
|
|
final pagination = result['pagination'] as Map<String, dynamic>;
|
|
|
|
_notifications.addAll(newNotifications);
|
|
|
|
final currentPage = pagination['current_page'] as int;
|
|
final lastPage = pagination['last_page'] as int;
|
|
final hasNextPage = currentPage < lastPage;
|
|
|
|
emit(
|
|
currentState.copyWith(
|
|
notifications: _notifications,
|
|
notificationsCount: _notifications.length,
|
|
currentPage: currentPage,
|
|
hasNextPage: hasNextPage,
|
|
isLoadingMore: false,
|
|
),
|
|
);
|
|
} else {
|
|
emit(currentState.copyWith(isLoadingMore: false));
|
|
}
|
|
} catch (e, st) {
|
|
log(e.toString(), stackTrace: st);
|
|
emit(currentState.copyWith(isLoadingMore: false));
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> markNotificationsAsRead() async {
|
|
final currentState = state;
|
|
if (currentState is NotificationsStateLoaded) {
|
|
try {
|
|
emit(currentState.copyWith(isLoading: true));
|
|
await notificationsRepository.markNotificationsAsRead();
|
|
await getNotifications();
|
|
emit(currentState.copyWith(isLoading: false, hasUnreadNotifications: false));
|
|
} catch (e, st) {
|
|
log(e.toString(), stackTrace: st);
|
|
emit(currentState.copyWith(isLoading: false));
|
|
}
|
|
}
|
|
}
|
|
}
|