flutter_notification_center/example/lib/services/firebase_notification_service.dart
2024-04-10 10:40:54 +02:00

226 lines
7.5 KiB
Dart

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../config/firebase_collections.dart';
import 'package:flutter_notification_center/src/models/notification.dart';
import 'package:flutter_notification_center/src/services/notification_service.dart';
class FirebaseNotificationService with ChangeNotifier
implements NotificationService {
@override
List<NotificationModel> listOfActiveNotifications;
@override
List<NotificationModel> listOfPlannedNotifications;
late Timer _timer;
FirebaseNotificationService(
{this.listOfActiveNotifications = const [],
this.listOfPlannedNotifications = const []}) {
_startTimer();
}
void _startTimer() {
_timer = Timer.periodic(const Duration(seconds: 15), (timer) {
debugPrint('Checking for scheduled notifications');
checkForScheduledNotifications();
});
}
@override
Future<void> pushNotification(NotificationModel notification) async {
try {
CollectionReference notifications = FirebaseFirestore.instance
.collection(FirebaseCollectionNames.active_notifications);
DateTime currentDateTime = DateTime.now();
notification.dateTimePushed = currentDateTime;
Map<String, dynamic> notificationMap = notification.toMap();
await notifications.doc(notification.id).set(notificationMap);
print('--- Trying to notify listeners ---');
listOfActiveNotifications.add(notification);
listOfActiveNotifications.forEach((notification) {
print('Notification ID: ${notification.id}');
});
notifyListeners();
} catch (e) {
debugPrint('Error creating document: $e');
}
}
@override
Future<List<NotificationModel>> getActiveNotifications() async {
try {
CollectionReference activeNotificationsCollection = FirebaseFirestore
.instance
.collection(FirebaseCollectionNames.active_notifications);
QuerySnapshot querySnapshot = await activeNotificationsCollection.get();
List<NotificationModel> activeNotifications =
querySnapshot.docs.map((doc) {
Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
data['id'] = doc.id;
return NotificationModel.fromJson(data);
}).toList();
listOfActiveNotifications = activeNotifications;
print('--- Trying to notify listeners ---');
listOfActiveNotifications.forEach((notification) {
print('Notification ID: ${notification.id}');
});
notifyListeners();
return listOfActiveNotifications;
} catch (e) {
debugPrint('Error getting active notifications: $e');
return [];
}
}
@override
Future<void> createRecurringNotification(
NotificationModel notification) async {
if (notification.recurring) {
switch (notification.occuringInterval) {
case OcurringInterval.daily:
notification.scheduledFor =
DateTime.now().add(const Duration(days: 1));
break;
case OcurringInterval.weekly:
notification.scheduledFor =
DateTime.now().add(const Duration(days: 7));
break;
case OcurringInterval.monthly:
notification.scheduledFor =
DateTime.now().add(const Duration(days: 30));
break;
case OcurringInterval.debug:
notification.scheduledFor =
DateTime.now().add(const Duration(seconds: 10));
break;
case null:
}
createScheduledNotification(notification);
}
}
@override
Future<void> createScheduledNotification(
NotificationModel notification) async {
try {
CollectionReference plannedNotifications = FirebaseFirestore.instance
.collection(FirebaseCollectionNames.planned_notifications);
Map<String, dynamic> notificationMap = notification.toMap();
await plannedNotifications.doc(notification.id).set(notificationMap);
} catch (e) {
debugPrint('Error creating document: $e');
}
}
@override
Future deleteScheduledNotification(
NotificationModel notificationModel) async {
try {
DocumentReference documentReference = FirebaseFirestore.instance
.collection(FirebaseCollectionNames.planned_notifications)
.doc(notificationModel.id);
await documentReference.delete();
QuerySnapshot querySnapshot = await FirebaseFirestore.instance
.collection(FirebaseCollectionNames.planned_notifications)
.get();
if (querySnapshot.docs.isEmpty) {
debugPrint('The collection is now empty');
} else {
debugPrint(
'Deleted planned notification with title: ${notificationModel.title}');
}
} catch (e) {
debugPrint('Error deleting document: $e');
}
}
@override
Future dismissActiveNotification(NotificationModel notificationModel) async {
try {
DocumentReference documentReference = FirebaseFirestore.instance
.collection(FirebaseCollectionNames.active_notifications)
.doc(notificationModel.id);
await documentReference.delete();
} catch (e) {
debugPrint('Error deleting document: $e');
}
}
@override
Future<void> markNotificationAsRead(
NotificationModel notificationModel) async {
try {
DocumentReference documentReference = FirebaseFirestore.instance
.collection(FirebaseCollectionNames.active_notifications)
.doc(notificationModel.id);
await documentReference.update({'isRead': true});
} catch (e) {
debugPrint('Error updating document: $e');
}
}
@override
Future<void> checkForScheduledNotifications() async {
DateTime currentTime = DateTime.now();
try {
CollectionReference plannedNotificationsCollection = FirebaseFirestore
.instance
.collection(FirebaseCollectionNames.planned_notifications);
QuerySnapshot querySnapshot = await plannedNotificationsCollection.get();
if (querySnapshot.docs.isEmpty) {
debugPrint('No scheduled notifications to be pushed');
return;
}
List<NotificationModel> plannedNotifications =
querySnapshot.docs.map((doc) {
Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
return NotificationModel.fromJson(data);
}).toList();
for (NotificationModel notification in plannedNotifications) {
if (notification.scheduledFor!.isBefore(currentTime) ||
notification.scheduledFor!.isAtSameMomentAs(currentTime)) {
await pushNotification(notification);
await deleteScheduledNotification(notification);
//Plan new recurring notification instance
if (notification.recurring) {
NotificationModel newNotification = NotificationModel(
id: UniqueKey().toString(),
title: notification.title,
body: notification.body,
recurring: true,
occuringInterval: notification.occuringInterval,
scheduledFor: DateTime.now().add(const Duration(seconds: 10)),
);
await createScheduledNotification(newNotification);
}
}
}
plannedNotifications.forEach((notification) async {
if (notification.scheduledFor!.isBefore(currentTime) ||
notification.scheduledFor!.isAtSameMomentAs(currentTime)) {
await deleteScheduledNotification(notification);
}
});
} catch (e) {
debugPrint('Error getting planned notifications: $e');
return;
}
}
}