// // SetMessageAttributeIntentHandler.swift // Meshtastic // // Handles INSetMessageAttributeIntent for CarPlay and Siri. // Marks messages as read or unread in Core Data. // import CoreData import Intents import OSLog final class SetMessageAttributeIntentHandler: NSObject, INSetMessageAttributeIntentHandling { // MARK: - Resolution func resolveAttribute(for intent: INSetMessageAttributeIntent) async -> INMessageAttributeResolutionResult { let attribute = intent.attribute guard attribute != .unknown else { return .needsValue() } return .success(with: attribute) } // MARK: - Confirmation func confirm(intent: INSetMessageAttributeIntent) async -> INSetMessageAttributeIntentResponse { guard let identifiers = intent.identifiers, !identifiers.isEmpty else { return INSetMessageAttributeIntentResponse(code: .failure, userActivity: nil) } return INSetMessageAttributeIntentResponse(code: .ready, userActivity: nil) } // MARK: - Handling func handle(intent: INSetMessageAttributeIntent) async -> INSetMessageAttributeIntentResponse { guard let identifiers = intent.identifiers, !identifiers.isEmpty else { return INSetMessageAttributeIntentResponse(code: .failure, userActivity: nil) } let attribute = intent.attribute let context = PersistenceController.shared.container.viewContext let success: Bool = await MainActor.run { let messageIds = identifiers.compactMap { Int64($0) } guard !messageIds.isEmpty else { return false } let fetchRequest: NSFetchRequest = MessageEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "messageId IN %@", messageIds) do { let messages = try context.fetch(fetchRequest) guard !messages.isEmpty else { return false } for message in messages { switch attribute { case .read: message.read = true case .unread: message.read = false case .flagged, .unflagged: // Meshtastic does not support message flagging break default: break } } if context.hasChanges { try context.save() } Logger.services.info("CarPlay/Siri: Updated \(messages.count) message(s) to \(String(describing: attribute))") return true } catch { Logger.services.error("CarPlay/Siri: Failed to update message attributes: \(error.localizedDescription)") return false } } return INSetMessageAttributeIntentResponse( code: success ? .success : .failure, userActivity: nil ) } }