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 { final List _notifications = []; final WsManager wsManager; final NotificationsRepository notificationsRepository; StreamSubscription? _newNotificationsSubscription; NotificationsCubit({ required this.wsManager, required this.notificationsRepository, }) : super(const NotificationsState.empty()); Future connectToWebSocket() async { await _newNotificationsSubscription?.cancel(); _newNotificationsSubscription = wsManager.newNotificationsStream?.listen((event) { _handleNotification(event.data); }); } BaseNotificationModel _parseNotification(Map notificationJson, NotificationType type) { try { return switch (type) { NotificationType.planSubscriptionStartedToAuthor => PlanSubscriptionStartedToAuthorNotification.fromJson(notificationJson, type), NotificationType.planSubscriptionCanceledToAuthor => PlanSubscriptionCanceledToAuthorNotification.fromJson(notificationJson, type), NotificationType.chosenPlanStartedToClientNotification => ChosenPlanStartedToClientNotification.fromJson(notificationJson, type), NotificationType.chosenPlanTomorrowReminderToClientNotification => ChosenPlanTomorrowReminderToClientNotification.fromJson(notificationJson, type), NotificationType.diaryReminderNotification => DiaryReminderNotification.fromJson(notificationJson, type), NotificationType.consultantLeftComment => ConsultantLeftCommentNotification.fromJson(notificationJson, type), NotificationType.personalizedDietIsDefined => PersonalizedDietIsDefinedNotification.fromJson(notificationJson, type), NotificationType.chosenPlanFinishedToClient => ChosenPlanFinishedToClientNotification.fromJson(notificationJson, type), NotificationType.planSubscriptionCanceledToCustomer => PlanSubscriptionCanceledToAuthorNotification.fromJson(notificationJson, type), NotificationType.chosenPlanStartedToConsultantNotification => ChosenPlanStartedToConsultantNotification.fromJson(notificationJson, type), NotificationType.chosenPlanTomorrowReminderToConsultantNotification => ChosenPlanTomorrowReminderToConsultantNotification.fromJson(notificationJson, type), NotificationType.planSubscriptionPaidToAuthor => PlanSubscriptionPaidToAuthorNotification.fromJson(notificationJson, type), NotificationType.chosenPlanFinishedToConsultant => ChosenPlanFinishedToConsultantNotification.fromJson(notificationJson, type), NotificationType.unknown => UnknownNotification(type: type), }; } catch (e) { return UnknownNotification(type: NotificationType.unknown); } } void _handleNotification(String notificationData) { final json = jsonDecode(notificationData) as Map; final stringifiedType = json['notification_class_name']; final type = NotificationType.getTypeFromString(stringifiedType); final notification = _parseNotification(json, type); _notifications.insert(0, notification); emit( NotificationsState.loaded( notifications: _notifications, notificationsCount: _notifications.length, hasUnreadNotifications: true, ), ); } Future getNotifications() async { try { final notifications = await notificationsRepository.getNotifications(page: 1); _notifications.clear(); _notifications.addAll(notifications ?? []); emit( NotificationsState.loaded( notifications: _notifications, notificationsCount: _notifications.length, hasUnreadNotifications: (notifications ?? []).where((elem) => elem.isRead == false).isNotEmpty, ), ); } catch (e, st) { log(e.toString(), stackTrace: st); } } Future 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)); } } } }