Skip to content

Commit

Permalink
[Feat/#71] add sending push notification
Browse files Browse the repository at this point in the history
  • Loading branch information
jihee-daily committed May 26, 2024
1 parent 7d50f36 commit 37f2eac
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 61 deletions.
2 changes: 2 additions & 0 deletions DDooing/DDooing/DDooing.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
Expand Down
2 changes: 2 additions & 0 deletions DDooing/DDooing/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
Expand Down
34 changes: 19 additions & 15 deletions DDooing/DDooing/Views/Auth/RandomCodeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ struct RandomCodeView: View {
@State private var isConnectionMode = true
@State private var code = ""
@State private var randomCode = ""
@AppStorage("userDeviceToken") private var userDeviceToken: String = ""


var body: some View {
NavigationStack{
Expand Down Expand Up @@ -88,32 +90,34 @@ struct RandomCodeView: View {
sendRandomCodeToFirebase(for: user, with: randomCode)
viewModel.observeUserConnectionStatus(userId: user.uid)
}
print("Device Token in HomeView: \(userDeviceToken)")
}
.navigationBarBackButtonHidden(true)
}
private func generateRandomCode(length: Int) -> String {
let lettersAndDigits = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return String((0..<length).compactMap { _ in lettersAndDigits.randomElement() })
}
}


func sendRandomCodeToFirebase(for user: User, with code: String) {
let db = Firestore.firestore()
let docRef = db.collection("Users").document(user.uid)
docRef.setData([
"uid": user.uid,
"code": code,
"isConnected" : false,
], merge: true) { error in
if let error = error {
print("Error writing document: \(error)")
} else {
print("Document successfully written!")
func sendRandomCodeToFirebase(for user: User, with code: String) {
let db = Firestore.firestore()
let docRef = db.collection("Users").document(user.uid)
docRef.setData([
"uid": user.uid,
"code": code,
"isConnected" : false,
"deviceToken" : userDeviceToken,
], merge: true) { error in
if let error = error {
print("Error writing document: \(error)")
} else {
print("Document successfully written!")
}
}
}
}


func connectUsers(with code: String, userAUID: String) {
let db = Firestore.firestore()
db.collection("Users").whereField("code", isEqualTo: code)
Expand Down
14 changes: 5 additions & 9 deletions DDooing/DDooing/Views/DDooingApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,12 @@ class AppDelegate: NSObject, UIApplicationDelegate {

// In order to receive notifications you need implement these methods.
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: any Error) {

print(error.localizedDescription)
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Messaging.messaging().token { token, error in
// if let error = error {
// print("Error fetching FCM registration token: \(error)")
// } else if let token = token {
// print("FCM registration token: \(token)")
//// self.fcmRegTokenMessage.text = "Remote FCM registration token: \(token)"
// }
// }
Messaging.messaging().apnsToken = deviceToken
print("----- \(deviceToken)")
}


Expand All @@ -93,6 +87,7 @@ extension AppDelegate: MessagingDelegate {

if let user = Auth.auth().currentUser {
setUsersFCMToken(token: fcmToken!, userAUID: user.uid)
UserDefaults.standard.set(fcmToken, forKey: "userDeviceToken")
}

// Store token in firestore for sending notifications from server in future
Expand All @@ -112,6 +107,7 @@ extension AppDelegate: MessagingDelegate {
}
}
}

}

// User notifications (InApp Notifications)
Expand Down
179 changes: 142 additions & 37 deletions DDooing/DDooing/Views/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,20 @@ struct HomeView: View {
@State var partnerName: String = ""
@Environment(\.modelContext) private var modelContext
@Query private var messages: [MessageModel]
@State private var randomMessages : String = ""
@State private var pushMessage : String = ""
@State private var showContextMenu = false
let partnerUID: String!
@GestureState private var isPressed = false
@State private var isLongPressed = false
@Query<NotificationDataModel> private var notificationDataList: [NotificationDataModel]
@State var pushMessage = ""
@State var deviceToken = ""
@State var partnerDeviceToken = ""

init(partnerUID: String?) {
self.partnerUID = partnerUID
if messages.randomElement() != nil {
_randomMessages = State(initialValue: randomMessages)
_pushMessage = State(initialValue: pushMessage)
} else {
_randomMessages = State(initialValue: "")
_pushMessage = State(initialValue: "")
}
}

Expand Down Expand Up @@ -66,7 +65,9 @@ struct HomeView: View {
ForEach(messages) { mess in
if mess.isStarred {
Button (action: {
sendMessage(messageText: mess.message, isStarred: true)
pushMessage = mess.message
sendMessage(messageText: pushMessage, isStarred: true)
fetchAccessTokenAndSendPushNotification()
}, label: {
Text(mess.message)
})
Expand All @@ -78,10 +79,11 @@ struct HomeView: View {
if !isLongPressed {
print("짧게누름")
if let randomMessage = messages.randomElement() {
randomMessages = randomMessage.message
pushMessage = randomMessage.message
}
saveRandomMessage()
print("메시지 입력")
sendMessage(messageText: pushMessage, isStarred: false)
fetchAccessTokenAndSendPushNotification()
}
isLongPressed = false
}
Expand All @@ -97,66 +99,169 @@ struct HomeView: View {
name = fetchedName

}

}
}
}
func fetchPartnerDeviceToken(completion: @escaping (String) -> Void) {
let db = Firestore.firestore()
db.collection("Users").document(partnerUID).getDocument { document, error in
if let document = document, document.exists {
partnerDeviceToken = document.data()?["deviceToken"] as? String ?? "Unknown"
completion(partnerDeviceToken)
} else {
completion("Unknown")
}
}
}

func saveRandomMessage() {
guard let partnerUID = partnerUID else { return }
sendMessage(messageText: randomMessages, isStarred: false)
func fetchPartnerConnectedNickname(completion: @escaping (String) -> Void) {
let db = Firestore.firestore()
db.collection("Users").document(partnerUID).getDocument { document, error in
if let document = document, document.exists {
partnerName = document.data()?["ConnectedNickname"] as? String ?? "Unknown"
completion(partnerName)
} else {
completion("Unknown")
}
}
}
private func fetchMyConnectedNickname(completion: @escaping (String) -> Void) {
let db = Firestore.firestore()
guard let currentUid = Auth.auth().currentUser?.uid else {
completion("Unknown")
return
}

db.collection("Users").document(currentUid).getDocument { document, error in
if let document = document, document.exists {
name = document.data()?["ConnectedNickname"] as? String ?? "Unknown"
completion(name)
} else {
completion("Unknown")
}
}
}

func sendMessage(messageText: String, isStarred: Bool) {
let db = Firestore.firestore()

guard let currentUid = Auth.auth().currentUser?.uid else { return }

let currenrUserRef = db.collection("Received-Messages")
.document(currentUid).collection(partnerUID).document()

let PartnerRef = db.collection("Received-Messages")
.document(partnerUID).collection(currentUid)
let currentUserRef = db.collection("Received-Messages")
.document(partnerUID).collection(currentUid).document()

// let recentCurrentUserRef = db.collection("Received-Messages")
// .document(currentUid).collection("recent-messages")
// .document(partnerUID)
// .document(partnerUID).collection("recent-messages")
// .document(currentUid)

let recentPartnerRef = db.collection("Received-Messages")
.document(partnerUID).collection("recent-messages")
.document(currentUid)

let messageId = currenrUserRef.documentID
let messageId = currentUserRef.documentID

let messageData: [String: Any] = [
"fromId": currentUid,
"toId": partnerUID!,
"fromId": partnerUID!,
"toId": currentUid,
"messageText": messageText,
"timeStamp": Timestamp(date: Date()),
"isStarred": isStarred,
"messageId": messageId
]

// currenrUserRef.setData(messageData)
PartnerRef.document(messageId).setData(messageData)
currentUserRef.setData(messageData)
// recentCurrentUserRef.setData(messageData)
recentPartnerRef.setData(messageData)
}

private func fetchMyConnectedNickname(completion: @escaping (String) -> Void) {
let db = Firestore.firestore()
guard let currentUid = Auth.auth().currentUser?.uid else {
completion("Unknown")
func fetchAccessTokenAndSendPushNotification() {
fetchPartnerDeviceToken { fetchedtoken in
partnerDeviceToken = fetchedtoken
}
fetchPartnerConnectedNickname { fetchedName in
partnerName = fetchedName
}

// 서버로부터 OAuth 2.0 액세스 토큰 가져오기
guard let url = URL(string: "") else {
print("Invalid URL for token")
return
}

var request = URLRequest(url: url)
request.httpMethod = "GET"

db.collection("Users").document(currentUid).getDocument { document, error in
if let document = document, document.exists {
name = document.data()?["ConnectedNickname"] as? String ?? "Unknown"
completion(name)
let session = URLSession(configuration: .default)
session.dataTask(with: request) { data, response, err in
if let err = err {
print(err.localizedDescription)
return
}
guard let data = data else {
print("No data received")
return
}

// 서버로부터 받은 응답을 문자열로 변환하여 출력
if let accessToken = String(data: data, encoding: .utf8) {
print("Access Token String: \(accessToken)")
sendPushNotification(with: accessToken)
} else {
completion("Unknown")
print("Invalid token response")
}
}.resume()
}

func sendPushNotification(with accessToken: String) {
guard !accessToken.isEmpty else {
print("Access token is empty")
return
}

// HTTP v1 API의 엔드포인트 URL
guard let url = URL(string: "https://fcm.googleapis.com/v1/projects/ddooing-8881b/messages:send") else {
print("Invalid URL for FCM")
return
}
print("partnerdevicetoken >>> \(partnerDeviceToken)")
print("pushMessage >>> \(pushMessage)")
print("parname >>> \(partnerName)")
let json: [String: Any] = [
"message": [
"token": partnerDeviceToken,
"notification": [
"body": pushMessage,
"title": partnerName
]
]
]

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted])
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

let session = URLSession(configuration: .default)
session.dataTask(with: request) { data, response, err in
if let err = err {
print("Error sending push notification: \(err.localizedDescription)")
return
}

guard let httpResponse = response as? HTTPURLResponse else {
print("Invalid response")
return
}

print("Push notification response status code: \(httpResponse.statusCode)")

if let data = data, let responseBody = String(data: data, encoding: .utf8) {
print("Response Body: \(responseBody)")
}

if httpResponse.statusCode == 200 {
print("Push notification sent successfully")
} else {
print("Failed to send push notification")
}
}.resume()
}

}
Expand Down

0 comments on commit 37f2eac

Please sign in to comment.