More cleanup and comments
This commit is contained in:
parent
2ff702057c
commit
1c7a8a0b72
10 changed files with 42 additions and 53 deletions
|
|
@ -14,8 +14,8 @@
|
|||
filePath = "ntfyNSE/NotificationService.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "25"
|
||||
endingLineNumber = "25"
|
||||
startingLineNumber = "23"
|
||||
endingLineNumber = "23"
|
||||
landmarkName = "didReceive(_:withContentHandler:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import CoreData
|
|||
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
let tag = "AppDelegate"
|
||||
let store = Store.shared
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
|
|
@ -18,8 +17,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
) -> Bool {
|
||||
Log.d(tag, "ApplicationDelegate didFinishLaunchingWithOptions.")
|
||||
|
||||
// FirebaseApp.configure() DOES NOT WORK
|
||||
FirebaseConfiguration.shared.setLoggerLevel(.max)
|
||||
Messaging.messaging().delegate = self
|
||||
|
||||
registerForPushNotifications()
|
||||
|
|
@ -63,15 +60,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
}
|
||||
|
||||
func registerForPushNotifications() {
|
||||
Log.d(tag, "Registering for local push notifications")
|
||||
UNUserNotificationCenter.current()
|
||||
.requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] granted, _ in
|
||||
print("granted: \(granted)")
|
||||
guard granted else { return }
|
||||
self?.getNotificationSettings()
|
||||
.requestAuthorization(options: [.alert, .sound, .badge]) { success, error in
|
||||
guard success else {
|
||||
Log.e(self.tag, "Failed to register for local push notifications", error)
|
||||
return
|
||||
}
|
||||
Log.d(self.tag, "Successfully registered for local push notifications")
|
||||
self.registerForRemoteNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
func getNotificationSettings() {
|
||||
func registerForRemoteNotifications() {
|
||||
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
||||
print("Notification settings: \(settings)")
|
||||
guard settings.authorizationStatus == .authorized else { return }
|
||||
|
|
@ -105,20 +106,10 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
|
|||
}
|
||||
|
||||
extension AppDelegate: MessagingDelegate {
|
||||
func messaging(
|
||||
_ messaging: Messaging,
|
||||
didReceiveRegistrationToken fcmToken: String?
|
||||
) {
|
||||
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
|
||||
Log.d(tag, "Firebase token received: \(String(describing: fcmToken))")
|
||||
|
||||
// FIXME: Is this necessary?
|
||||
|
||||
let dataDict: [String: String] = ["token": fcmToken ?? ""]
|
||||
NotificationCenter.default.post(
|
||||
name: UserNotifications.Notification.Name("FCMToken"),
|
||||
object: nil,
|
||||
userInfo: dataDict
|
||||
)
|
||||
// We don't actually need the FCM token, since we're just using topics.
|
||||
// We still print it so we can see if things were successful.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ struct AppMain: App {
|
|||
@StateObject private var store = Store.shared
|
||||
|
||||
init() {
|
||||
// We must configure Firebase here, and not in the AppDelegate. For some reason
|
||||
// configuring it there did not work.
|
||||
FirebaseApp.configure()
|
||||
FirebaseConfiguration.shared.setLoggerLevel(.max)
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
//
|
||||
// Notification.swift
|
||||
// ntfy
|
||||
//
|
||||
// Created by Philipp Heckel on 5/16/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Extensions to make the notification easier to display
|
||||
extension Notification {
|
||||
func shortDateTime() -> String {
|
||||
let date = Date(timeIntervalSince1970: TimeInterval(self.time))
|
||||
|
|
@ -31,6 +25,7 @@ extension Notification {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is the "on the wire" message as it is received from the ntfy server
|
||||
struct Message: Decodable {
|
||||
var id: String
|
||||
var time: Int64
|
||||
|
|
|
|||
|
|
@ -32,10 +32,12 @@ class Store: ObservableObject {
|
|||
context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyStoreTrumpMergePolicyType) // https://stackoverflow.com/a/60362945/1440785
|
||||
context.transactionAuthor = Bundle.main.bundlePath.hasSuffix(".appex") ? "ntfy.appex" : "ntfy"
|
||||
|
||||
// When a remote change comes in (= the app extension updated entities in Core Data),
|
||||
// we force refresh the view with horrible means. Please help me make this better!
|
||||
NotificationCenter.default
|
||||
.publisher(for: .NSPersistentStoreRemoteChange)
|
||||
.sink {
|
||||
Log.d(Store.tag, "Remote change detected", $0)
|
||||
.sink { value in
|
||||
Log.d(Store.tag, "Remote change detected, refreshing view", value)
|
||||
|
||||
// Hack: This is the only way I could make the UI update the subscription list.
|
||||
// I'm pretty sure I got the @FetchRequest wrong, but I don
|
||||
|
|
@ -67,21 +69,22 @@ class Store: ObservableObject {
|
|||
return try? context.fetch(fetchRequest).first
|
||||
}
|
||||
|
||||
func deleteSubscription(subscription: Subscription) {
|
||||
func delete(subscription: Subscription) {
|
||||
context.delete(subscription)
|
||||
try? context.save()
|
||||
}
|
||||
|
||||
func saveNotification(fromUserInfo userInfo: [AnyHashable: Any]) {
|
||||
func save(notificationFromUserInfo userInfo: [AnyHashable: Any]) {
|
||||
guard let id = userInfo["id"] as? String,
|
||||
let topic = userInfo["topic"] as? String, // FIXME: Notification should also contain baseUrl
|
||||
let topic = userInfo["topic"] as? String,
|
||||
let time = userInfo["time"] as? String,
|
||||
let timeInt = Int64(time),
|
||||
let message = userInfo["message"] as? String else {
|
||||
Log.d(Store.tag, "Unknown or irrelevant message", userInfo)
|
||||
return
|
||||
}
|
||||
guard let subscription = getSubscription(baseUrl: appBaseUrl, topic: topic) else {
|
||||
let baseUrl = appBaseUrl // Firebase messages all come from the main ntfy server
|
||||
guard let subscription = getSubscription(baseUrl: baseUrl, topic: topic) else {
|
||||
Log.d(Store.tag, "Subscription for topic \(topic) unknown")
|
||||
return
|
||||
}
|
||||
|
|
@ -100,7 +103,7 @@ class Store: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func saveNotification(fromMessage message: Message, subscription: Subscription) {
|
||||
func save(notificationFromMessage message: Message, withSubscription subscription: Subscription) {
|
||||
do {
|
||||
let notification = Notification(context: context)
|
||||
notification.id = message.id
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import Foundation
|
||||
|
||||
// FIXME: Store last notification ID in Subscription
|
||||
|
||||
extension Subscription {
|
||||
func urlString() -> String {
|
||||
return topicUrl(baseUrl: baseUrl!, topic: topic!)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import Foundation
|
||||
import FirebaseMessaging
|
||||
|
||||
/// Manager to combine persisting a subscription to the data store and subscribing to Firebase.
|
||||
/// This is to centralize the logic in one place.
|
||||
struct SubscriptionManager {
|
||||
private let tag = "Store"
|
||||
var store: Store
|
||||
|
|
@ -17,7 +19,7 @@ struct SubscriptionManager {
|
|||
if let topic = subscription.topic {
|
||||
Messaging.messaging().unsubscribe(fromTopic: topic)
|
||||
}
|
||||
store.deleteSubscription(subscription: subscription)
|
||||
store.delete(subscription: subscription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,3 @@
|
|||
//
|
||||
// Helpers.swift
|
||||
// ntfy
|
||||
//
|
||||
// Created by Philipp Heckel on 5/16/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
let appBaseUrl = "http://192.168.1.4" // FIXME
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ struct NotificationListView: View {
|
|||
if !messages.isEmpty {
|
||||
DispatchQueue.main.async {
|
||||
for message in messages {
|
||||
store.saveNotification(fromMessage: message, subscription: subscription)
|
||||
store.save(notificationFromMessage: message, withSubscription: subscription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,19 +9,17 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
var contentHandler: ((UNNotificationContent) -> Void)?
|
||||
var bestAttemptContent: UNMutableNotificationContent?
|
||||
|
||||
override func didReceive(
|
||||
_ request: UNNotificationRequest,
|
||||
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
|
||||
) {
|
||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
self.contentHandler = contentHandler
|
||||
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
||||
self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
||||
|
||||
Log.d(tag, "Notification received (in service)") // Logs from extensions are not printed in Xcode!
|
||||
|
||||
if let bestAttemptContent = bestAttemptContent {
|
||||
// bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
|
||||
|
||||
let userInfo = bestAttemptContent.userInfo
|
||||
Store.shared.saveNotification(fromUserInfo: userInfo)
|
||||
Store.shared.save(notificationFromUserInfo: userInfo)
|
||||
|
||||
contentHandler(bestAttemptContent)
|
||||
}
|
||||
|
|
@ -29,7 +27,9 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
|
||||
override func serviceExtensionTimeWillExpire() {
|
||||
// Called just before the extension will be terminated by the system.
|
||||
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
|
||||
// Use this as an opportunity to deliver your "best attempt" at modified content,
|
||||
// otherwise the original push payload will be used.
|
||||
|
||||
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
||||
contentHandler(bestAttemptContent)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue