LocalNotificationSender.swift
2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import Foundation
import UIKit
import UserNotifications
enum LocalNotificationSenderError: LocalizedError {
case notificationsDenied
case notificationsUnsupportedStatus(Int)
var errorDescription: String? {
switch self {
case .notificationsDenied:
return "Notifications permission is denied."
case .notificationsUnsupportedStatus(let status):
return "Notifications permission status is unsupported: \(status)."
}
}
}
final class LocalNotificationSender {
static let shared = LocalNotificationSender()
private let center: UNUserNotificationCenter
init(center: UNUserNotificationCenter = .current()) {
self.center = center
}
func send(
title: String,
body: String,
link: String,
onlyWhenAppNotActive: Bool = true
) async throws -> Bool {
if onlyWhenAppNotActive, UIApplication.shared.applicationState == .active {
return false
}
try await ensureNotificationPermission()
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = .default
content.userInfo = notificationUserInfo(link: link)
let request = UNNotificationRequest(
identifier: "doublefeel.local.\(UUID().uuidString)",
content: content,
trigger: UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
)
try await center.add(request)
return true
}
private func ensureNotificationPermission() async throws {
let settings = await center.notificationSettings()
switch settings.authorizationStatus {
case .authorized, .provisional, .ephemeral:
return
case .notDetermined:
let granted = try await center.requestAuthorization(options: [.alert, .sound, .badge])
if !granted {
throw LocalNotificationSenderError.notificationsDenied
}
case .denied:
throw LocalNotificationSenderError.notificationsDenied
@unknown default:
throw LocalNotificationSenderError.notificationsUnsupportedStatus(
settings.authorizationStatus.rawValue
)
}
}
private func notificationUserInfo(link: String) -> [String: Any] {
guard !link.isEmpty else { return [:] }
return [
"url": link,
"link": link,
]
}
}