TM-SGNL-iOS/SignalServiceKit/Messages/BodyRanges/SpoilerRevealState.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

68 lines
2.6 KiB
Swift

//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public import LibSignalClient
/// Used to uniquely identify one iteration of an interaction even if edits are applied.
/// Note that the interaction's uniqueId, rowId, and sortId always point to the latest edit,
/// so when an edit is applied they point to the new version not the old version.
/// This is used instead to continue to point to the old version.
///
/// authorAci is allowed to be null for outgoing or system messages because timestamp can
/// be considered unique on its own for messages generated by oneself.
/// Incoming messages should always have non-null authorAci.
/// NOTE: be careful using this for messages from before the introduction of uuids.
/// Currently used for text formatting spoilers which were introduced after uuids.
public struct InteractionSnapshotIdentifier: Equatable, Hashable {
let timestamp: UInt64
// Note: this will always be the aci for incoming messages
// and nil for local/outgoing messages.
let authorAci: Aci?
public init(timestamp: UInt64, authorAci: Aci?) {
self.timestamp = timestamp
self.authorAci = authorAci
}
public static func fromInteraction(_ interaction: TSInteraction) -> Self {
return .init(timestamp: interaction.timestamp, authorAci: Aci.parseFrom(aciString: (interaction as? TSIncomingMessage)?.authorUUID))
}
// Not strictly an interaction, but can contain spoilers.
public static func fromStoryMessage(_ storyMessage: StoryMessage) -> Self {
return .init(timestamp: storyMessage.timestamp, authorAci: storyMessage.authorAci)
}
}
// MARK: -
@objc
public class SpoilerRevealState: NSObject {
private var revealedSpoilerIdsByMessage = [InteractionSnapshotIdentifier: Set<StyleIdType>]()
/// Returns the set of IDs in the ordered list of spoiler ranges for a given message that
/// should be revealed.
public func revealedSpoilerIds(
interactionIdentifier: InteractionSnapshotIdentifier
) -> Set<StyleIdType> {
return revealedSpoilerIdsByMessage[interactionIdentifier] ?? []
}
public func setSpoilerRevealed(
withID id: StyleIdType,
interactionIdentifier: InteractionSnapshotIdentifier
) {
var revealedIds = revealedSpoilerIdsByMessage[interactionIdentifier] ?? Set()
revealedIds.insert(id)
revealedSpoilerIdsByMessage[interactionIdentifier] = revealedIds
}
public typealias Snapshot = [InteractionSnapshotIdentifier: Set<StyleIdType>]
public func snapshot() -> Snapshot {
return revealedSpoilerIdsByMessage
}
}