Signal-iOS/SignalServiceKit/Messages/TypingIndicatorMessage.swift
2026-01-26 12:17:57 -06:00

117 lines
3.0 KiB
Swift

//
// 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 }
}