129 lines
4.2 KiB
Swift
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)]"
|
|
}
|
|
}
|