// // Copyright 2026 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import Foundation public import LibSignalClient @objc(OWSProfileKeyMessage) public final class ProfileKeyMessage: TransientOutgoingMessage { let profileKey: ProfileKey? public init( thread: TSContactThread, profileKey: ProfileKey, tx: DBReadTransaction, ) { self.profileKey = profileKey super.init( outgoingMessageWith: TSOutgoingMessageBuilder.outgoingMessageBuilder(thread: thread), additionalRecipients: [], explicitRecipients: [], skippedRecipients: [], transaction: tx, ) } override public class var supportsSecureCoding: Bool { true } override public func encode(with coder: NSCoder) { super.encode(with: coder) if let profileKey { coder.encode(profileKey.serialize(), forKey: "profileKey") } } public required init?(coder: NSCoder) { self.profileKey = (coder.decodeObject(of: NSData.self, forKey: "profileKey") as Data?).flatMap { try? ProfileKey(contents: $0) } super.init(coder: coder) } override public var hash: Int { var hasher = Hasher() hasher.combine(super.hash) hasher.combine(profileKey?.serialize()) return hasher.finalize() } override public func isEqual(_ object: Any?) -> Bool { guard let object = object as? Self else { return false } guard super.isEqual(object) else { return false } guard self.profileKey?.serialize() == object.profileKey?.serialize() else { return false } return true } override public func shouldSyncTranscript() -> Bool { return false } override public func buildDataMessage(_ thread: TSThread, transaction: DBReadTransaction) -> SSKProtoDataMessage? { let builder = self.dataMessageBuilder(with: thread, transaction: transaction) guard let builder else { owsFailDebug("could not build protobuf") return nil } builder.setTimestamp(self.timestamp) ProtoUtils.addLocalProfileKeyIfNecessary( forThread: thread, profileKeySnapshot: self.profileKey, dataMessageBuilder: builder, transaction: transaction, ) builder.setFlags(UInt32(SSKProtoDataMessageFlags.profileKeyUpdate.rawValue)) let dataProto: SSKProtoDataMessage do { dataProto = try builder.build() } catch { owsFailDebug("could not build protobuf: \(error)") return nil } if dataProto.profileKey == nil { // If we couldn't include the profile key, drop it. Logger.warn("Dropping profile key message without a profile key") return nil } return dataProto } override public var contentHint: SealedSenderContentHint { .implicit } }