Simplify closure to create CallViewModels
This commit is contained in:
parent
ef678d2720
commit
4e69ff6705
@ -29,9 +29,8 @@ extension CallsListViewController {
|
||||
/// changes. When the user scrolls to the bottom of the list, callers should
|
||||
/// request additional items.
|
||||
struct ViewModelLoader {
|
||||
typealias CreateCallViewModelBlock = (
|
||||
_ primaryCallRecord: CallRecord,
|
||||
_ coalescedCallRecords: [CallRecord],
|
||||
typealias CallViewModelForCallRecords = (
|
||||
_ callRecords: [CallRecord],
|
||||
_ tx: DBReadTransaction
|
||||
) -> CallViewModel
|
||||
|
||||
@ -46,7 +45,7 @@ extension CallsListViewController {
|
||||
}
|
||||
|
||||
private let callRecordLoader: CallRecordLoader
|
||||
private let createCallViewModelBlock: CreateCallViewModelBlock
|
||||
private let callViewModelForCallRecords: CallViewModelForCallRecords
|
||||
private let fetchCallRecordBlock: FetchCallRecordBlock
|
||||
private let viewModelPageSize: Int
|
||||
private let maxCachedViewModelCount: Int
|
||||
@ -54,7 +53,7 @@ extension CallsListViewController {
|
||||
|
||||
init(
|
||||
callRecordLoader: CallRecordLoader,
|
||||
createCallViewModelBlock: @escaping CreateCallViewModelBlock,
|
||||
callViewModelForCallRecords: @escaping CallViewModelForCallRecords,
|
||||
fetchCallRecordBlock: @escaping FetchCallRecordBlock,
|
||||
viewModelPageSize: Int = 50,
|
||||
maxCachedViewModelCount: Int = 150,
|
||||
@ -66,7 +65,7 @@ extension CallsListViewController {
|
||||
)
|
||||
|
||||
self.callRecordLoader = callRecordLoader
|
||||
self.createCallViewModelBlock = createCallViewModelBlock
|
||||
self.callViewModelForCallRecords = callViewModelForCallRecords
|
||||
self.fetchCallRecordBlock = fetchCallRecordBlock
|
||||
self.viewModelPageSize = viewModelPageSize
|
||||
self.maxCachedViewModelCount = maxCachedViewModelCount
|
||||
@ -250,9 +249,8 @@ extension CallsListViewController {
|
||||
callHistoryItemReferences[0] = CallHistoryItemReference(
|
||||
callRecordIds: combinedGroupOfCallRecords.map(\.id)
|
||||
)
|
||||
viewModels[0] = createCallViewModelBlock(
|
||||
combinedGroupOfCallRecords.first,
|
||||
Array(combinedGroupOfCallRecords.rawValue.dropFirst()),
|
||||
viewModels[0] = callViewModelForCallRecords(
|
||||
combinedGroupOfCallRecords.rawValue,
|
||||
tx
|
||||
)
|
||||
fetchResult = fetchResult.dropLast()
|
||||
@ -293,7 +291,7 @@ extension CallsListViewController {
|
||||
let callRecords = reference.callRecordIds.map {
|
||||
return fetchCallRecordBlock($0, tx)!
|
||||
}
|
||||
return createCallViewModelBlock(callRecords.first, Array(callRecords.rawValue.dropFirst()), tx)
|
||||
return callViewModelForCallRecords(callRecords.rawValue, tx)
|
||||
}
|
||||
|
||||
return newViewModels
|
||||
@ -458,7 +456,7 @@ extension CallsListViewController {
|
||||
continue
|
||||
}
|
||||
let newCallRecords = viewModel.callRecords.map(refreshIfPossible(_:))
|
||||
viewModels[index] = createCallViewModelBlock(newCallRecords.first!, Array(newCallRecords.dropFirst()), tx)
|
||||
viewModels[index] = callViewModelForCallRecords(newCallRecords, tx)
|
||||
refreshedViewModelReferences.append(viewModels[index].reference)
|
||||
}
|
||||
|
||||
|
||||
@ -685,10 +685,9 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
// Reset our loaded calls.
|
||||
self.viewModelLoader = ViewModelLoader(
|
||||
callRecordLoader: callRecordLoader,
|
||||
createCallViewModelBlock: { primaryCallRecord, coalescedCallRecords, tx in
|
||||
return Self.createCallViewModel(
|
||||
primaryCallRecord: primaryCallRecord,
|
||||
coalescedCallRecords: coalescedCallRecords,
|
||||
callViewModelForCallRecords: { callRecords, tx in
|
||||
return Self.callViewModel(
|
||||
forCallRecords: callRecords,
|
||||
deps: capturedDeps,
|
||||
tx: SDSDB.shimOnlyBridge(tx)
|
||||
)
|
||||
@ -752,42 +751,44 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
/// - Important
|
||||
/// The primary and and coalesced call records *must* all have the same
|
||||
/// thread, direction, missed status, and call type.
|
||||
private static func createCallViewModel(
|
||||
primaryCallRecord: CallRecord,
|
||||
coalescedCallRecords: [CallRecord],
|
||||
private static func callViewModel(
|
||||
forCallRecords callRecords: [CallRecord],
|
||||
deps: Dependencies,
|
||||
tx: SDSAnyReadTransaction
|
||||
) -> CallViewModel {
|
||||
owsPrecondition(!callRecords.isEmpty)
|
||||
owsPrecondition(
|
||||
coalescedCallRecords.allSatisfy { $0.threadRowId == primaryCallRecord.threadRowId },
|
||||
Set(callRecords.map(\.threadRowId)).count == 1,
|
||||
"Coalesced call records were for a different thread than the primary!"
|
||||
)
|
||||
owsPrecondition(
|
||||
coalescedCallRecords.allSatisfy { $0.callDirection == primaryCallRecord.callDirection },
|
||||
Set(callRecords.map(\.callDirection)).count == 1,
|
||||
"Coalesced call records were of a different direction than the primary!"
|
||||
)
|
||||
owsPrecondition(
|
||||
coalescedCallRecords.allSatisfy { $0.callStatus.isMissedCall == primaryCallRecord.callStatus.isMissedCall },
|
||||
Set(callRecords.map(\.callStatus.isMissedCall)).count == 1,
|
||||
"Coalesced call records were of a different missed status than the primary!"
|
||||
)
|
||||
owsPrecondition(
|
||||
([primaryCallRecord] + coalescedCallRecords).isSortedByTimestamp(.descending),
|
||||
callRecords.isSortedByTimestamp(.descending),
|
||||
"Primary and coalesced call records were not ordered descending by timestamp!"
|
||||
)
|
||||
|
||||
let mostRecentCallRecord = callRecords.first!
|
||||
|
||||
guard let callThread = deps.threadStore.fetchThread(
|
||||
rowId: primaryCallRecord.threadRowId,
|
||||
rowId: mostRecentCallRecord.threadRowId,
|
||||
tx: tx.asV2Read
|
||||
) else {
|
||||
owsFail("Missing thread for call record! This should be impossible, per the DB schema.")
|
||||
}
|
||||
|
||||
let callDirection: CallViewModel.Direction = {
|
||||
if primaryCallRecord.callStatus.isMissedCall {
|
||||
if mostRecentCallRecord.callStatus.isMissedCall {
|
||||
return .missed
|
||||
}
|
||||
|
||||
switch primaryCallRecord.callDirection {
|
||||
switch mostRecentCallRecord.callDirection {
|
||||
case .incoming: return .incoming
|
||||
case .outgoing: return .outgoing
|
||||
}
|
||||
@ -798,9 +799,9 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
let callState: CallViewModel.State = {
|
||||
let currentCallId: UInt64? = deps.callService.callServiceState.currentCall?.callId
|
||||
|
||||
switch primaryCallRecord.callStatus {
|
||||
switch mostRecentCallRecord.callStatus {
|
||||
case .individual:
|
||||
if primaryCallRecord.callId == currentCallId {
|
||||
if mostRecentCallRecord.callId == currentCallId {
|
||||
// We can have at most one 1:1 call active at a time, and if
|
||||
// we have an active 1:1 call we must be in it. All other
|
||||
// 1:1 calls must have ended.
|
||||
@ -809,7 +810,7 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
case .group:
|
||||
guard let groupCallInteraction: OWSGroupCallMessage = deps.interactionStore
|
||||
.fetchAssociatedInteraction(
|
||||
callRecord: primaryCallRecord, tx: tx.asV2Read
|
||||
callRecord: mostRecentCallRecord, tx: tx.asV2Read
|
||||
)
|
||||
else {
|
||||
owsFail("Missing interaction for group call. This should be impossible per the DB schema!")
|
||||
@ -820,7 +821,7 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
// leetle wonky that we use the interaction to store that info,
|
||||
// but such is life.
|
||||
if !groupCallInteraction.hasEnded {
|
||||
if primaryCallRecord.callId == currentCallId {
|
||||
if mostRecentCallRecord.callId == currentCallId {
|
||||
return .participating
|
||||
}
|
||||
|
||||
@ -838,7 +839,7 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
case let contactThread as TSContactThread:
|
||||
title = deps.contactsManager.displayName(for: contactThread.contactAddress, tx: tx).resolvedValue()
|
||||
let callType: CallViewModel.RecipientType.CallType = {
|
||||
switch primaryCallRecord.callType {
|
||||
switch mostRecentCallRecord.callType {
|
||||
case .audioCall:
|
||||
return .audio
|
||||
case .groupCall:
|
||||
@ -857,8 +858,8 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
|
||||
}
|
||||
|
||||
return CallViewModel(
|
||||
reference: .callRecords(primaryId: primaryCallRecord.id, coalescedIds: coalescedCallRecords.map(\.id)),
|
||||
callRecords: [primaryCallRecord] + coalescedCallRecords,
|
||||
reference: .callRecords(primaryId: mostRecentCallRecord.id, coalescedIds: callRecords.dropFirst().map(\.id)),
|
||||
callRecords: callRecords,
|
||||
title: title,
|
||||
recipientType: recipientType,
|
||||
direction: callDirection,
|
||||
|
||||
@ -16,20 +16,16 @@ final class CallsListViewControllerViewModelLoaderTest: XCTestCase {
|
||||
|
||||
private var mockDB: MockDB!
|
||||
private var mockCallRecordLoader: MockCallRecordLoader!
|
||||
private lazy var createCallViewModelBlock: ViewModelLoader.CreateCallViewModelBlock! = {
|
||||
self.createCallViewModel(primaryCallRecord: $0, coalescedCallRecords: $1, tx: $2)
|
||||
private lazy var callViewModelForCallRecords: ViewModelLoader.CallViewModelForCallRecords! = {
|
||||
self.createCallViewModel(callRecords: $0, tx: $1)
|
||||
}
|
||||
private lazy var fetchCallRecordBlock: ViewModelLoader.FetchCallRecordBlock! = { (callRecordId, tx) -> CallRecord? in
|
||||
return self.mockCallRecordLoader.callRecordsById[callRecordId]
|
||||
}
|
||||
|
||||
private func createCallViewModel(
|
||||
primaryCallRecord: CallRecord,
|
||||
coalescedCallRecords: [CallRecord],
|
||||
tx: DBReadTransaction
|
||||
) -> CallViewModel {
|
||||
private func createCallViewModel(callRecords: [CallRecord], tx: DBReadTransaction) -> CallViewModel {
|
||||
let recipientType: CallViewModel.RecipientType = {
|
||||
switch primaryCallRecord.callStatus {
|
||||
switch callRecords.first!.callStatus {
|
||||
case .individual:
|
||||
return .individual(type: .audio, contactThread: TSContactThread(
|
||||
contactUUID: UUID().uuidString,
|
||||
@ -41,19 +37,19 @@ final class CallsListViewControllerViewModelLoaderTest: XCTestCase {
|
||||
}()
|
||||
|
||||
let direction: CallViewModel.Direction = {
|
||||
if primaryCallRecord.callStatus.isMissedCall {
|
||||
if callRecords.first!.callStatus.isMissedCall {
|
||||
return .missed
|
||||
}
|
||||
|
||||
switch primaryCallRecord.callDirection {
|
||||
switch callRecords.first!.callDirection {
|
||||
case .incoming: return .incoming
|
||||
case .outgoing: return .outgoing
|
||||
}
|
||||
}()
|
||||
|
||||
return CallViewModel(
|
||||
reference: .callRecords(primaryId: primaryCallRecord.id, coalescedIds: coalescedCallRecords.map(\.id)),
|
||||
callRecords: [primaryCallRecord] + coalescedCallRecords,
|
||||
reference: .callRecords(primaryId: callRecords.first!.id, coalescedIds: callRecords.dropFirst().map(\.id)),
|
||||
callRecords: callRecords,
|
||||
title: "Hey, I just met you, and this is crazy, but here's my number, so call me maybe?",
|
||||
recipientType: recipientType,
|
||||
direction: direction,
|
||||
@ -68,7 +64,7 @@ final class CallsListViewControllerViewModelLoaderTest: XCTestCase {
|
||||
) {
|
||||
viewModelLoader = ViewModelLoader(
|
||||
callRecordLoader: mockCallRecordLoader,
|
||||
createCallViewModelBlock: { self.createCallViewModelBlock($0, $1, $2) },
|
||||
callViewModelForCallRecords: { self.callViewModelForCallRecords($0, $1) },
|
||||
fetchCallRecordBlock: { self.fetchCallRecordBlock($0, $1) },
|
||||
viewModelPageSize: viewModelPageSize,
|
||||
maxCachedViewModelCount: maxCachedViewModelCount,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user