Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Communication: Add quick reply to notifications #296

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions ArtemisKit/Sources/ArtemisKit/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import UIKit
import UserNotifications
import UserStore
import PushNotifications
import Messages
import Navigation
import Common

Expand All @@ -30,6 +31,7 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {

private func registerForPushNotifications() {
UNUserNotificationCenter.current().delegate = self
PushNotificationHandler.registerNotificationCategories()
}
}

Expand Down Expand Up @@ -88,6 +90,13 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
guard handleNotificationResponse(response) else {
// If handleNotificationResponse returns false, we don't need to perform additional work
log.info("Handled notification action. Not opening deep link.")
completionHandler()
return
}

let userInfo = response.notification.request.content.userInfo
guard let targetURL = PushNotificationResponseHandler.getTarget(userInfo: userInfo) else {
log.error("Could not handle click on push notification!")
Expand All @@ -103,6 +112,27 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
// maybe add as param in handle above
completionHandler()
}

/// Handles actions triggered from a user interacting with a notification.
/// Returns whether the corresponding deep link should be opened.
private func handleNotificationResponse(_ response: UNNotificationResponse) -> Bool {
if response.actionIdentifier == PushNotificationActionIdentifiers.reply {
guard
let infoData = response
.notification.request.content
.userInfo[PushNotificationUserInfoKeys.communicationInfo] as? Data,
let communicationInfo = try? PushNotificationCommunicationInfo(with: infoData),
let textResponse = response as? UNTextInputNotificationResponse else {
return true
}

NotificationMessageResponseHandler.handle(responseText: textResponse.userText,
info: communicationInfo)

return false
}
return true
}
}

// Define initializer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// NotificationMessageResponseHandler.swift
// ArtemisKit
//
// Created by Anian Schleyer on 22.02.25.
//

import PushNotifications
import SharedModels
import UserStore

public struct NotificationMessageResponseHandler {
public static func handle(responseText: String, info: PushNotificationCommunicationInfo) {
let courseId = info.courseId
let channelId = Int64(info.channelId)
let messageId = Int64(info.messageId) ?? 0
Task {
var message = Message(id: messageId)
message.conversation = .channel(conversation: .init(id: channelId))
let result = await MessagesServiceFactory.shared.sendAnswerMessage(for: courseId,
message: message,
content: responseText)
switch result {
case .failure:
// Save message to try again later in case of failure
let host = UserSessionFactory.shared.institution?.baseURL?.host() ?? ""
let repository = await MessagesRepository.shared
_ = try? await repository.insertMessage(host: host,
courseId: courseId,
conversationId: Int(channelId),
messageId: Int(messageId),
answerMessageDraft: responseText)
await repository.save()
default:
break
}
}
}
}