Created
March 16, 2022 14:03
-
-
Save frboulais/c47cc0519fe4ce768199cb4297ea25e0 to your computer and use it in GitHub Desktop.
Help Drylendar - Manager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NotificationManager.swift | |
// Drylendar | |
// | |
// Created by François Boulais on 14/03/2022. | |
// Copyright © 2022 App Craft Studio. All rights reserved. | |
// | |
import Foundation | |
import Resolver | |
import UserNotifications | |
final class NotificationManager: NSObject, ObservableObject { | |
@Published private(set) var notifications = [UNNotificationRequest]() | |
@Published private(set) var authorizationStatus: UNAuthorizationStatus? | |
@LazyInjected private var databaseManager: DatabaseManager | |
@LazyInjected private var authenticationManager: AuthenticationManager | |
private let center = UNUserNotificationCenter.current() | |
private let encoder = JSONEncoder() | |
private let decoder = JSONDecoder() | |
override init() { | |
super.init() | |
registerCategories() | |
} | |
// MARK: - NotificationManager | |
func reloadAuthorizationStatus() { | |
center.getNotificationSettings { [weak self] settings in | |
DispatchQueue.main.async { | |
self?.authorizationStatus = settings.authorizationStatus | |
} | |
} | |
} | |
func requestAuthorization() { | |
center.requestAuthorization(options: [.alert, .sound]) { [weak self] granted, error in | |
self?.reloadAuthorizationStatus() | |
} | |
} | |
func removeScheduledNotifications() { | |
center.removeAllPendingNotificationRequests() | |
} | |
func removeNotification(for item: CalendarItem) { | |
center.removeDeliveredNotifications(withIdentifiers: [item.notificationIdentifier]) | |
center.removePendingNotificationRequests(withIdentifiers: [item.notificationIdentifier]) | |
} | |
func reloadScheduledNotifications() { | |
center.getPendingNotificationRequests { [weak self] notifications in | |
DispatchQueue.main.async { | |
self?.notifications = notifications | |
} | |
} | |
} | |
func scheduleNotifications(for date: Date) { | |
removeScheduledNotifications() | |
guard let user = authenticationManager.currentUser else { | |
return | |
} | |
let matchComponents = Calendar.autoupdatingCurrent.dateComponents([.hour, .minute], from: date) | |
let items = Calendar.autoupdatingCurrent.upcomingItems(count: 20, matching: matchComponents) | |
databaseManager.entries(for: user) { [weak self] entries in | |
for item in items { | |
guard entries.contains(where: { item.matches(entry: $0) }) else { | |
return | |
} | |
var dateComponents = item.dateComponents | |
dateComponents.hour = matchComponents.hour | |
dateComponents.minute = matchComponents.minute | |
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true) | |
let content = UNMutableNotificationContent() | |
content.title = "Drylendar" | |
content.body = "How many drinks today?" | |
content.sound = .default | |
content.categoryIdentifier = NotificationCategory.dailyReminder.identifier | |
if let data = try? self?.encoder.encode(item), | |
let jsonObject = try? JSONSerialization.jsonObject(with: data), | |
let userInfo = jsonObject as? [AnyHashable : Any] { | |
content.userInfo = userInfo | |
} | |
let request = UNNotificationRequest(identifier: item.notificationIdentifier, content: content, trigger: trigger) | |
self?.center.add(request) | |
} | |
} | |
} | |
func rescheduleNotifications() { | |
center.getPendingNotificationRequests { [weak self] requests in | |
if let trigger = requests.first?.trigger as? UNTimeIntervalNotificationTrigger, | |
let date = trigger.nextTriggerDate() { | |
self?.scheduleNotifications(for: date) | |
} | |
} | |
} | |
// MARK: - Private functions | |
private func registerCategories() { | |
let actions = CalendarState.allCases.map { state in | |
UNNotificationAction( | |
identifier: state.actionIdentifier, | |
title: state.actionTitle | |
) | |
} | |
let category = UNNotificationCategory( | |
identifier: NotificationCategory.dailyReminder.identifier, | |
actions: actions, | |
intentIdentifiers: [] | |
) | |
center.setNotificationCategories([category]) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment