From 09a3f2b0bbde62b33466dacc721b79fba0936942 Mon Sep 17 00:00:00 2001 From: talksik Date: Thu, 23 Dec 2021 01:26:30 -0800 Subject: [PATCH] updating user device token and starting implementation for sending push notification device to device --- nirvana-ios.xcodeproj/project.pbxproj | 4 ++ nirvana-ios/Models/User.swift | 1 + .../Repositories/FirestoreService.swift | 14 +++++++ nirvana-ios/Services/AuthSessionStore.swift | 2 +- .../Services/PushNotificationService.swift | 38 +++++++++++++++++++ .../InnerCircle/InnerCircleViewModel.swift | 3 ++ nirvana-ios/nirvana_iosApp.swift | 36 ++++++++++++++---- 7 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 nirvana-ios/Services/PushNotificationService.swift diff --git a/nirvana-ios.xcodeproj/project.pbxproj b/nirvana-ios.xcodeproj/project.pbxproj index 0c7e2c9..96d05ab 100644 --- a/nirvana-ios.xcodeproj/project.pbxproj +++ b/nirvana-ios.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ 896CE70727711BAB00DB474E /* FindFriendsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896CE70627711BAB00DB474E /* FindFriendsView.swift */; }; 896CE70927712CED00DB474E /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896CE70827712CED00DB474E /* StringExtension.swift */; }; 89A107E3277446F600B971FD /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 89A107E2277446F600B971FD /* GoogleService-Info.plist */; }; + 89A107E5277476CC00B971FD /* PushNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89A107E4277476CC00B971FD /* PushNotificationService.swift */; }; 89AD5573276DD790001658E0 /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AD5572276DD790001658E0 /* SplashView.swift */; }; 89AD5575276DE724001658E0 /* PhoneCodeVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AD5574276DE724001658E0 /* PhoneCodeVerificationView.swift */; }; 89AD5578276DEAB3001658E0 /* LogoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AD5577276DEAB3001658E0 /* LogoHeaderView.swift */; }; @@ -116,6 +117,7 @@ 896CE70627711BAB00DB474E /* FindFriendsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindFriendsView.swift; sourceTree = ""; }; 896CE70827712CED00DB474E /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; 89A107E2277446F600B971FD /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; + 89A107E4277476CC00B971FD /* PushNotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationService.swift; sourceTree = ""; }; 89AD5572276DD790001658E0 /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 89AD5574276DE724001658E0 /* PhoneCodeVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneCodeVerificationView.swift; sourceTree = ""; }; 89AD5577276DEAB3001658E0 /* LogoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoHeaderView.swift; sourceTree = ""; }; @@ -413,6 +415,7 @@ children = ( 89F05BA3276ACC060002E9C7 /* ContactService.swift */, 89B46E70276893E200B74255 /* AuthSessionStore.swift */, + 89A107E4277476CC00B971FD /* PushNotificationService.swift */, ); path = Services; sourceTree = ""; @@ -585,6 +588,7 @@ 896CE7022770892F00DB474E /* CircleGridView.swift in Sources */, 89BDCDEA27697F9C00577829 /* UserMenu.swift in Sources */, 89BCABE7276B3D64009E9B10 /* InnerCircleViewModel.swift in Sources */, + 89A107E5277476CC00B971FD /* PushNotificationService.swift in Sources */, 89AD557C276DF86A001658E0 /* FirestoreService.swift in Sources */, 891A15FF27656F9200B26659 /* HeaderView.swift in Sources */, 89AD5575276DE724001658E0 /* PhoneCodeVerificationView.swift in Sources */, diff --git a/nirvana-ios/Models/User.swift b/nirvana-ios/Models/User.swift index ffca1e8..3a2c842 100644 --- a/nirvana-ios/Models/User.swift +++ b/nirvana-ios/Models/User.swift @@ -16,6 +16,7 @@ struct User: Identifiable, Codable { var phoneNumber: String? var emailAddress:String? var avatar:String? + var deviceToken: String? @ServerTimestamp var lastLoggedInTimestamp: Date? @ServerTimestamp var createdTimestamp: Date? diff --git a/nirvana-ios/Repositories/FirestoreService.swift b/nirvana-ios/Repositories/FirestoreService.swift index 046410e..6bc1b62 100644 --- a/nirvana-ios/Repositories/FirestoreService.swift +++ b/nirvana-ios/Repositories/FirestoreService.swift @@ -157,4 +157,18 @@ class FirestoreService { } } + func updateUserDeviceToken(userId: String, deviceToken: String, completion: @escaping((_ state: ServiceState) -> ())) { + do { + if userId != nil { + let _ = try db.collection(Collection.users.rawValue).document(userId).setData(["deviceToken": deviceToken], merge: true) + completion(ServiceState.success("Updated user device token")) + } else { + completion(ServiceState.error(ServiceError(description: "No user id given to firestore service"))) + } + } catch { + print("error in updating user \(error.localizedDescription)") + completion(ServiceState.error(ServiceError(description: error.localizedDescription))) + } + } + } diff --git a/nirvana-ios/Services/AuthSessionStore.swift b/nirvana-ios/Services/AuthSessionStore.swift index 4282cbe..4e1a867 100644 --- a/nirvana-ios/Services/AuthSessionStore.swift +++ b/nirvana-ios/Services/AuthSessionStore.swift @@ -241,7 +241,7 @@ extension AuthSessionStore { self.objectWillChange.send() - print("added this user to the array of users for user's circle\(returnedUser)") + print("added this user to the array of users for user's circle\(returnedUser?.nickname)") } } } else { diff --git a/nirvana-ios/Services/PushNotificationService.swift b/nirvana-ios/Services/PushNotificationService.swift new file mode 100644 index 0000000..1fe186a --- /dev/null +++ b/nirvana-ios/Services/PushNotificationService.swift @@ -0,0 +1,38 @@ +// +// PushNotificationService.swift +// nirvana-ios +// +// Created by Arjun Patel on 12/23/21. +// + +import Foundation + +class PushNotificationService { + + func sendPushNotification(to token: String, title: String, body: String) { + let urlString = "https://fcm.googleapis.com/fcm/send" + let url = NSURL(string: urlString)! + let paramString: [String : Any] = ["to" : token, + "notification" : ["title" : title, "body" : body], + "data" : ["user" : "test_id"] + ] + let request = NSMutableURLRequest(url: url as URL) + request.httpMethod = "POST" + request.httpBody = try? JSONSerialization.data(withJSONObject:paramString, options: [.prettyPrinted]) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("key=AAAAFddKFpg:APA91bFHKmsZOg4ltxbmlM-anf8EhdkezjZPxAD__cNzQu4c8azSVbgszqaaO4Ym_NMuHc5MqySuX51T7ejgwqjgAtFA-DGdKJj0XJL4_Sb2ZOztN8c8zC2Et3Y5L8sjDPSFKRP2XuKI", forHTTPHeaderField: "Authorization") + let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in + do { + if let jsonData = data { + if let jsonDataDict = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: AnyObject] { + NSLog("Received data:\n\(jsonDataDict))") + } + } + } catch let err as NSError { + print(err.debugDescription) + } + } + task.resume() + } +} + diff --git a/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift b/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift index fd075c9..3124875 100644 --- a/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift +++ b/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift @@ -20,6 +20,7 @@ class InnerCircleViewModel: ObservableObject { let cloudStorageService = CloudStorageService() let firestoreService = FirestoreService() + let pushNotificationService = pushNotificationService() init() { do { @@ -77,6 +78,8 @@ class InnerCircleViewModel: ObservableObject { self?.firestoreService.createMessage(message: newMessage) {[weak self] res in print(res) + // sending push notification + // delete local audio file from user's phone so that it doesn't get crazy print("stopped recording: file about to get deleted from \(self?.getTemporaryDirectory()) with filename: \(self?.audioLocalUrl)") diff --git a/nirvana-ios/nirvana_iosApp.swift b/nirvana-ios/nirvana_iosApp.swift index 5adc556..9d81ca7 100644 --- a/nirvana-ios/nirvana_iosApp.swift +++ b/nirvana-ios/nirvana_iosApp.swift @@ -63,10 +63,10 @@ class AppDelegate: NSObject, UIApplicationDelegate { } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { - - //MARK: add this when I have APN setup through app // gets the APN token so that firebase can send notifications to app - Auth.auth().setAPNSToken(deviceToken, type: .sandbox) +// Auth.auth().setAPNSToken(deviceToken, type: .sandbox) + +// Messaging.messaging().apnsToken = deviceToken } func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { @@ -89,7 +89,7 @@ class AppDelegate: NSObject, UIApplicationDelegate { completionHandler(UIBackgroundFetchResult.newData) - //MARK: add this when I have APN setup through app + // phone auth if Auth.auth().canHandleNotification(notification) { completionHandler(.noData) return @@ -123,7 +123,7 @@ class AppDelegate: NSObject, UIApplicationDelegate { } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { - + print("failed ot register for remote notifications with error: \(error)") } } @@ -140,8 +140,30 @@ extension AppDelegate: MessagingDelegate { userInfo: dataDict ) - // TODO: If necessary send token to application server...need to use this in cloud functionb to send the message to this user // Note: This callback is fired at each app startup and whenever a new token is generated. + let firestoreService = FirestoreService() + let user = Auth.auth().currentUser + + // TODO: store it on loading of circle view and not on launch as this may just never get called + // use the notification center above + // https://stackoverflow.com/questions/58818046/how-to-set-addobserver-in-swiftui + if user != nil && fcmToken != nil { + // User is signed in. + // ... + print("have access to user Id when I received registration token: \(user!.uid)") + + // kind of have to store in database or update every time, because don't know if the user logged in and out or if there is a new token or not + // https://firebase.google.com/docs/cloud-messaging/ios/client#access_the_registration_token + + firestoreService.updateUserDeviceToken(userId: user!.uid, deviceToken: fcmToken!) { res in + print(res) + } + } else { + // No user is signed in. + // ... + print("can't save user device token to a user") + } + } } @@ -165,7 +187,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate { print(userInfo) // Change this to your preferred presentation option - completionHandler([[.alert, .sound]]) + completionHandler([[.banner, .alert, .sound]]) } func userNotificationCenter(_ center: UNUserNotificationCenter,