TM-SGNL-iOS/Signal/ConversationView/Loading/CVRenderState.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

129 lines
4.2 KiB
Swift

//
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import SignalServiceKit
import SignalUI
// This captures all of the state loaded by the CVLoadCoordinator.
//
// It is intended to be an immutable, comprehensive snapshot of all
// loaded state needed to render CVC at a given state of time.
class CVRenderState {
public static let renderStateId_unknown: UInt = 0
private static let idCounter = AtomicUInt(1, lock: .sharedGlobal)
let renderStateId: UInt
let threadViewModel: ThreadViewModel
let prevThreadViewModel: ThreadViewModel?
var isEmptyInitialState: Bool {
prevThreadViewModel == nil
}
let conversationViewModel: ConversationViewModel
var isFirstLoad: Bool {
if let loadType = self.loadType,
case CVLoadType.loadInitialMapping = loadType {
return true
}
return false
}
// All of CVRenderState's state should be immutable.
let items: [CVRenderItem]
let canLoadOlderItems: Bool
let canLoadNewerItems: Bool
// The "view state" values that were used when loading this render state.
let viewStateSnapshot: CVViewStateSnapshot
let loadType: CVLoadType?
let loadDate = Date()
// These values reflect the style and view state at the time
// was load began. They may be obsolete.
var conversationStyle: ConversationStyle {
viewStateSnapshot.conversationStyle
}
// TODO: We might want to precompute: interactionIndexMap, focusItemIndex, unreadIndicatorIndex
var disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration {
threadViewModel.disappearingMessagesConfiguration
}
public let indexPathOfUnreadIndicator: IndexPath?
private let interactionIdToIndexPathMap: [String: IndexPath]
public let allIndexPaths: [IndexPath]
init(
threadViewModel: ThreadViewModel,
prevThreadViewModel: ThreadViewModel?,
conversationViewModel: ConversationViewModel,
items: [CVRenderItem],
canLoadOlderItems: Bool,
canLoadNewerItems: Bool,
viewStateSnapshot: CVViewStateSnapshot,
loadType: CVLoadType?
) {
self.threadViewModel = threadViewModel
self.prevThreadViewModel = prevThreadViewModel
self.conversationViewModel = conversationViewModel
self.items = items
self.canLoadOlderItems = canLoadOlderItems
self.canLoadNewerItems = canLoadNewerItems
self.viewStateSnapshot = viewStateSnapshot
self.loadType = loadType
self.renderStateId = Self.idCounter.increment()
let messageSection = CVLoadCoordinator.messageSection
var indexPathOfUnreadIndicator: IndexPath?
var interactionIdToIndexPathMap = [String: IndexPath]()
var allIndexPaths = [IndexPath]()
for (index, item) in items.enumerated() {
let indexPath = IndexPath(row: index, section: messageSection)
interactionIdToIndexPathMap[item.interaction.uniqueId] = indexPath
allIndexPaths.append(indexPath)
if item.interactionType == .unreadIndicator {
indexPathOfUnreadIndicator = indexPath
}
}
self.indexPathOfUnreadIndicator = indexPathOfUnreadIndicator
self.interactionIdToIndexPathMap = interactionIdToIndexPathMap
self.allIndexPaths = allIndexPaths
}
static func defaultRenderState(
threadViewModel: ThreadViewModel,
conversationViewModel: ConversationViewModel,
viewStateSnapshot: CVViewStateSnapshot
) -> CVRenderState {
CVRenderState(
threadViewModel: threadViewModel,
prevThreadViewModel: nil,
conversationViewModel: conversationViewModel,
items: [],
canLoadOlderItems: false,
canLoadNewerItems: false,
viewStateSnapshot: viewStateSnapshot,
loadType: nil
)
}
public func indexPath(forInteractionUniqueId interactionUniqueId: String) -> IndexPath? {
interactionIdToIndexPathMap[interactionUniqueId]
}
public var debugDescription: String {
isEmptyInitialState ? "empty" : "[items: \(items.count)]"
}
}