// // Copyright 2018 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import Foundation public enum TypingIndicatorAction { case started case stopped } public final class TypingIndicatorMessage: TransientOutgoingMessage { override public class var supportsSecureCoding: Bool { true } public required init?(coder: NSCoder) { // Doesn't support serialization. return nil } override public func encode(with coder: NSCoder) { owsFail("Doesn't support serialization.") } override public var hash: Int { var hasher = Hasher() hasher.combine(super.hash) hasher.combine(action) 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.action == object.action else { return false } return true } private let action: TypingIndicatorAction // MARK: Initializers public init( thread: TSThread, action: TypingIndicatorAction, transaction: DBReadTransaction, ) { self.action = action let builder: TSOutgoingMessageBuilder = .withDefaultValues(thread: thread) super.init( outgoingMessageWith: builder, additionalRecipients: [], explicitRecipients: [], skippedRecipients: [], transaction: transaction, ) } @objc override public func shouldSyncTranscript() -> Bool { return false } @objc override public var isOnline: Bool { return true } @objc override public var isUrgent: Bool { false } private func protoAction(forAction action: TypingIndicatorAction) -> SSKProtoTypingMessageAction { switch action { case .started: return .started case .stopped: return .stopped } } override public func contentBuilder( thread: TSThread, transaction: DBReadTransaction, ) -> SSKProtoContentBuilder? { let typingBuilder = SSKProtoTypingMessage.builder(timestamp: self.timestamp) typingBuilder.setAction(protoAction(forAction: action)) if let groupThread = thread as? TSGroupThread { typingBuilder.setGroupID(groupThread.groupModel.groupId) } let contentBuilder = SSKProtoContent.builder() do { contentBuilder.setTypingMessage(try typingBuilder.build()) return contentBuilder } catch let error { owsFailDebug("failed to build protobuf: \(error)") return nil } } // MARK: TSYapDatabaseObject overrides @objc override public var debugDescription: String { return "typingIndicatorMessage" } @objc override var shouldRecordSendLog: Bool { false } @objc override var contentHint: SealedSenderContentHint { .implicit } }