Propagate ThreadAssociatedData audioPlaybackRate down to CVComponentAudioAttachment
* Propagate ThreadAssociatedData audioPlaybackRate down to CVComponentAudioAttachment * remove audioplaybackrate from component state; keep only on view state
This commit is contained in:
parent
f305b4a2aa
commit
202c137ced
@ -16,6 +16,8 @@ public protocol CVComponentDelegate {
|
||||
|
||||
func cvc_enqueueReload()
|
||||
|
||||
func cvc_enqueueReloadWithoutCaches()
|
||||
|
||||
// MARK: - Body Text Items
|
||||
|
||||
func cvc_didTapBodyTextItem(_ item: CVBodyTextLabel.ItemObject)
|
||||
|
||||
@ -73,8 +73,11 @@ public class CVComponentAudioAttachment: CVComponentBase, CVComponent {
|
||||
} else if let outgoingMessage = interaction as? TSOutgoingMessage {
|
||||
audioMessageView.setViewed(!outgoingMessage.viewedRecipientAddresses().isEmpty, animated: false)
|
||||
}
|
||||
audioMessageView.configureForRendering(cellMeasurement: cellMeasurement,
|
||||
conversationStyle: conversationStyle)
|
||||
audioMessageView.configureForRendering(
|
||||
cellMeasurement: cellMeasurement,
|
||||
conversationStyle: conversationStyle,
|
||||
audioPlaybackRate: itemViewState.audioPlaybackRate
|
||||
)
|
||||
componentView.audioMessageView = audioMessageView
|
||||
stackView.configure(config: stackViewConfig,
|
||||
cellMeasurement: cellMeasurement,
|
||||
@ -108,11 +111,14 @@ public class CVComponentAudioAttachment: CVComponentBase, CVComponent {
|
||||
measurementBuilder.setSize(key: Self.measurementKey_footerSize, size: footerSize)
|
||||
}
|
||||
|
||||
let audioSize = AudioMessageView.measure(maxWidth: maxWidth,
|
||||
audioAttachment: audioAttachment,
|
||||
isIncoming: isIncoming,
|
||||
conversationStyle: conversationStyle,
|
||||
measurementBuilder: measurementBuilder).ceil
|
||||
let audioSize = AudioMessageView.measure(
|
||||
maxWidth: maxWidth,
|
||||
audioAttachment: audioAttachment,
|
||||
isIncoming: isIncoming,
|
||||
conversationStyle: conversationStyle,
|
||||
audioPlaybackRate: itemViewState.audioPlaybackRate,
|
||||
measurementBuilder: measurementBuilder
|
||||
).ceil
|
||||
let audioInfo = audioSize.asManualSubviewInfo
|
||||
let stackMeasurement = ManualStackView.measure(config: stackViewConfig,
|
||||
measurementBuilder: measurementBuilder,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -11,6 +11,7 @@ import Foundation
|
||||
public class CVItemModel: NSObject {
|
||||
public let interaction: TSInteraction
|
||||
public let thread: TSThread
|
||||
public let threadAssociatedData: ThreadAssociatedData
|
||||
|
||||
// The item state loaded from the database.
|
||||
public let componentState: CVComponentState
|
||||
@ -35,12 +36,14 @@ public class CVItemModel: NSObject {
|
||||
|
||||
init(interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
componentState: CVComponentState,
|
||||
itemViewState: CVItemViewState,
|
||||
coreState: CVCoreState) {
|
||||
|
||||
self.interaction = interaction
|
||||
self.thread = thread
|
||||
self.threadAssociatedData = threadAssociatedData
|
||||
self.componentState = componentState
|
||||
self.itemViewState = itemViewState
|
||||
self.coreState = coreState
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalServiceKit
|
||||
|
||||
// CVItemViewState represents the transient, un-persisted values
|
||||
// that may affect item appearance.
|
||||
@ -27,6 +28,7 @@ public struct CVItemViewState: Equatable {
|
||||
let bodyTextState: CVComponentBodyText.State?
|
||||
let giftBadgeState: CVComponentGiftBadge.ViewState?
|
||||
let nextAudioAttachment: AudioAttachment?
|
||||
let audioPlaybackRate: Float
|
||||
|
||||
let uiMode: ConversationUIMode
|
||||
let previousUIMode: ConversationUIMode
|
||||
@ -47,6 +49,7 @@ public struct CVItemViewState: Equatable {
|
||||
var bodyTextState: CVComponentBodyText.State?
|
||||
var giftBadgeState: CVComponentGiftBadge.ViewState?
|
||||
var nextAudioAttachment: AudioAttachment?
|
||||
var audioPlaybackRate: Float = 1
|
||||
var uiMode: ConversationUIMode = .normal
|
||||
var previousUIMode: ConversationUIMode = .normal
|
||||
|
||||
@ -63,6 +66,7 @@ public struct CVItemViewState: Equatable {
|
||||
bodyTextState: bodyTextState,
|
||||
giftBadgeState: giftBadgeState,
|
||||
nextAudioAttachment: nextAudioAttachment,
|
||||
audioPlaybackRate: audioPlaybackRate,
|
||||
uiMode: uiMode,
|
||||
previousUIMode: previousUIMode)
|
||||
}
|
||||
@ -191,6 +195,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
|
||||
public static func buildStandaloneItem(interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
threadViewModel: ThreadViewModel,
|
||||
itemBuildingContext: CVItemBuildingContext,
|
||||
transaction: SDSAnyReadTransaction) -> CVItemModel? {
|
||||
@ -200,6 +205,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
|
||||
guard let itemBuilder = Self.itemBuilder(forInteraction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
itemBuildingContext: itemBuildingContext,
|
||||
componentStateCache: ComponentStateCache()) else {
|
||||
owsFailDebug("Could not create itemBuilder.")
|
||||
@ -259,6 +265,8 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
itemViewState.giftBadgeState = CVComponentGiftBadge.buildViewState(giftBadge)
|
||||
}
|
||||
|
||||
itemViewState.audioPlaybackRate = threadViewModel.associatedData.audioPlaybackRate
|
||||
|
||||
if interaction.interactionType == .dateHeader {
|
||||
itemViewState.dateHeaderState = CVComponentDateHeader.buildState(interaction: interaction)
|
||||
}
|
||||
@ -501,6 +509,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
itemBuildingContext: itemBuildingContext)
|
||||
let item = ItemBuilder(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
componentState: componentState)
|
||||
items.append(item)
|
||||
}
|
||||
@ -527,6 +536,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
itemBuildingContext: itemBuildingContext)
|
||||
let item = ItemBuilder(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
componentState: componentState)
|
||||
items.append(item)
|
||||
}
|
||||
@ -571,6 +581,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
private mutating func addItem(interaction: TSInteraction) -> ItemBuilder? {
|
||||
guard let item = Self.itemBuilder(forInteraction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
itemBuildingContext: itemBuildingContext,
|
||||
componentStateCache: componentStateCache) else {
|
||||
return nil
|
||||
@ -603,6 +614,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
|
||||
private static func itemBuilder(forInteraction interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
itemBuildingContext: CVItemBuildingContext,
|
||||
componentStateCache: ComponentStateCache) -> ItemBuilder? {
|
||||
let componentState: CVComponentState
|
||||
@ -617,6 +629,7 @@ struct CVItemModelBuilder: CVItemBuilding, Dependencies {
|
||||
|
||||
return ItemBuilder(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
componentState: componentState)
|
||||
}
|
||||
|
||||
@ -689,20 +702,24 @@ fileprivate extension CVMessageMapping {
|
||||
private class ItemBuilder {
|
||||
let interaction: TSInteraction
|
||||
let thread: TSThread
|
||||
let threadAssociatedData: ThreadAssociatedData
|
||||
let componentState: CVComponentState
|
||||
var itemViewState = CVItemViewState.Builder()
|
||||
|
||||
required init(interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
componentState: CVComponentState) {
|
||||
self.interaction = interaction
|
||||
self.thread = thread
|
||||
self.threadAssociatedData = threadAssociatedData
|
||||
self.componentState = componentState
|
||||
}
|
||||
|
||||
func build(coreState: CVCoreState) -> CVItemModel {
|
||||
CVItemModel(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
componentState: componentState,
|
||||
itemViewState: itemViewState.build(),
|
||||
coreState: coreState)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -85,6 +85,7 @@ extension CVItemBuilding {
|
||||
// Convenience Accessors
|
||||
var threadViewModel: ThreadViewModel { itemBuildingContext.threadViewModel }
|
||||
var thread: TSThread { itemBuildingContext.thread }
|
||||
var threadAssociatedData: ThreadAssociatedData { threadViewModel.associatedData }
|
||||
var viewStateSnapshot: CVViewStateSnapshot { itemBuildingContext.viewStateSnapshot }
|
||||
var conversationStyle: ConversationStyle { itemBuildingContext.conversationStyle }
|
||||
var mediaCache: CVMediaCache { itemBuildingContext.mediaCache }
|
||||
|
||||
@ -261,6 +261,7 @@ public class CVLoader: NSObject {
|
||||
@objc
|
||||
public static func buildStandaloneRenderItem(interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
containerView: UIView,
|
||||
transaction: SDSAnyReadTransaction) -> CVRenderItem? {
|
||||
let chatColor = ChatColors.chatColorForRendering(thread: thread, transaction: transaction)
|
||||
@ -274,6 +275,7 @@ public class CVLoader: NSObject {
|
||||
mediaCache: CVMediaCache())
|
||||
return CVLoader.buildStandaloneRenderItem(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
coreState: coreState,
|
||||
transaction: transaction)
|
||||
}
|
||||
@ -281,18 +283,21 @@ public class CVLoader: NSObject {
|
||||
@objc
|
||||
public static func buildStandaloneRenderItem(interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
conversationStyle: ConversationStyle,
|
||||
transaction: SDSAnyReadTransaction) -> CVRenderItem? {
|
||||
let coreState = CVCoreState(conversationStyle: conversationStyle,
|
||||
mediaCache: CVMediaCache())
|
||||
return CVLoader.buildStandaloneRenderItem(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
coreState: coreState,
|
||||
transaction: transaction)
|
||||
}
|
||||
|
||||
private static func buildStandaloneRenderItem(interaction: TSInteraction,
|
||||
thread: TSThread,
|
||||
threadAssociatedData: ThreadAssociatedData,
|
||||
coreState: CVCoreState,
|
||||
transaction: SDSAnyReadTransaction) -> CVRenderItem? {
|
||||
AssertIsOnMainThread()
|
||||
@ -308,6 +313,7 @@ public class CVLoader: NSObject {
|
||||
avatarBuilder: avatarBuilder)
|
||||
guard let itemModel = CVItemModelBuilder.buildStandaloneItem(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
threadViewModel: threadViewModel,
|
||||
itemBuildingContext: itemBuildingContext,
|
||||
transaction: transaction) else {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@ -60,8 +60,11 @@ class AudioMessageView: ManualStackView {
|
||||
super.init(name: "AudioMessageView")
|
||||
}
|
||||
|
||||
public func configureForRendering(cellMeasurement: CVCellMeasurement,
|
||||
conversationStyle: ConversationStyle) {
|
||||
public func configureForRendering(
|
||||
cellMeasurement: CVCellMeasurement,
|
||||
conversationStyle: ConversationStyle,
|
||||
audioPlaybackRate: Float
|
||||
) {
|
||||
|
||||
var outerSubviews = [UIView]()
|
||||
|
||||
@ -185,11 +188,14 @@ class AudioMessageView: ManualStackView {
|
||||
private static let measurementKey_bottomInnerStack = "CVComponentAudioAttachment.measurementKey_bottomInnerStack"
|
||||
private static let measurementKey_outerStack = "CVComponentAudioAttachment.measurementKey_outerStack"
|
||||
|
||||
public static func measure(maxWidth: CGFloat,
|
||||
audioAttachment: AudioAttachment,
|
||||
isIncoming: Bool,
|
||||
conversationStyle: ConversationStyle,
|
||||
measurementBuilder: CVCellMeasurement.Builder) -> CGSize {
|
||||
public static func measure(
|
||||
maxWidth: CGFloat,
|
||||
audioAttachment: AudioAttachment,
|
||||
isIncoming: Bool,
|
||||
conversationStyle: ConversationStyle,
|
||||
audioPlaybackRate: Float,
|
||||
measurementBuilder: CVCellMeasurement.Builder
|
||||
) -> CGSize {
|
||||
owsAssertDebug(maxWidth > 0)
|
||||
|
||||
var outerSubviewInfos = [ManualStackSubviewInfo]()
|
||||
|
||||
@ -19,6 +19,10 @@ extension ConversationViewController: CVComponentDelegate {
|
||||
self.loadCoordinator.enqueueReload()
|
||||
}
|
||||
|
||||
public func cvc_enqueueReloadWithoutCaches() {
|
||||
self.loadCoordinator.enqueueReloadWithoutCaches()
|
||||
}
|
||||
|
||||
// MARK: - Body Text Items
|
||||
|
||||
public func cvc_didTapBodyTextItem(_ item: CVBodyTextLabel.ItemObject) {
|
||||
|
||||
@ -1950,11 +1950,13 @@ typedef NS_CLOSED_ENUM(NSUInteger, MessageContentType) {
|
||||
isAttachmentDownloaded:YES
|
||||
quotedMessage:nil
|
||||
transaction:transaction];
|
||||
ThreadAssociatedData *threadAssociatedData = [self createFakeThreadAssociatedData:thread];
|
||||
OWSAssertDebug(messageToQuote);
|
||||
|
||||
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||
CVRenderItem *renderItem = [CVLoader buildStandaloneRenderItemWithInteraction:messageToQuote
|
||||
thread:thread
|
||||
threadAssociatedData:threadAssociatedData
|
||||
containerView:containerView
|
||||
transaction:transaction];
|
||||
CVItemViewModelImpl *itemViewModel = [[CVItemViewModelImpl alloc] initWithRenderItem:renderItem];
|
||||
@ -1975,10 +1977,12 @@ typedef NS_CLOSED_ENUM(NSUInteger, MessageContentType) {
|
||||
messageSticker:nil
|
||||
transaction:transaction];
|
||||
OWSAssertDebug(messageToQuote);
|
||||
ThreadAssociatedData *threadAssociatedData = [self createFakeThreadAssociatedData:thread];
|
||||
|
||||
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||
CVRenderItem *renderItem = [CVLoader buildStandaloneRenderItemWithInteraction:messageToQuote
|
||||
thread:thread
|
||||
threadAssociatedData:threadAssociatedData
|
||||
containerView:containerView
|
||||
transaction:transaction];
|
||||
CVItemViewModelImpl *itemViewModel = [[CVItemViewModelImpl alloc] initWithRenderItem:renderItem];
|
||||
@ -4467,6 +4471,15 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
|
||||
return label;
|
||||
}
|
||||
|
||||
+ (ThreadAssociatedData *)createFakeThreadAssociatedData:(TSThread *)thread
|
||||
{
|
||||
return [[ThreadAssociatedData alloc] initWithThreadUniqueId:thread.uniqueId
|
||||
isArchived:NO
|
||||
isMarkedUnread:NO
|
||||
mutedUntilTimestamp:0
|
||||
audioPlaybackRate:1];
|
||||
}
|
||||
|
||||
+ (TSOutgoingMessage *)createFakeOutgoingMessage:(TSThread *)thread
|
||||
messageBody:(nullable NSString *)messageBody
|
||||
fakeAssetLoader:(nullable DebugUIMessagesAssetLoader *)fakeAssetLoader
|
||||
|
||||
@ -646,8 +646,11 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
||||
owsFailDebug("Missing thread.")
|
||||
return nil
|
||||
}
|
||||
let threadAssociatedData = ThreadAssociatedData.fetchOrDefault(for: thread,
|
||||
transaction: transaction)
|
||||
return CVLoader.buildStandaloneRenderItem(interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
containerView: self.view,
|
||||
transaction: transaction)
|
||||
}
|
||||
|
||||
@ -205,6 +205,7 @@ class MessageDetailViewController: OWSTableViewController2 {
|
||||
owsFailDebug("Missing thread.")
|
||||
return nil
|
||||
}
|
||||
let threadAssociatedData = ThreadAssociatedData.fetchOrDefault(for: thread, transaction: transaction)
|
||||
|
||||
let chatColor = ChatColors.chatColorForRendering(thread: thread, transaction: transaction)
|
||||
|
||||
@ -220,6 +221,7 @@ class MessageDetailViewController: OWSTableViewController2 {
|
||||
return CVLoader.buildStandaloneRenderItem(
|
||||
interaction: interaction,
|
||||
thread: thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
conversationStyle: conversationStyle,
|
||||
transaction: transaction
|
||||
)
|
||||
@ -883,6 +885,10 @@ extension MessageDetailViewController: CVComponentDelegate {
|
||||
self.refreshContent()
|
||||
}
|
||||
|
||||
func cvc_enqueueReloadWithoutCaches() {
|
||||
self.refreshContentForDatabaseUpdate()
|
||||
}
|
||||
|
||||
// MARK: - Body Text Items
|
||||
|
||||
func cvc_didTapBodyTextItem(_ item: CVBodyTextLabel.ItemObject) {}
|
||||
|
||||
@ -128,6 +128,7 @@ class MockConversationView: UIView {
|
||||
isWallpaperPhoto: false,
|
||||
chatColor: chatColor
|
||||
)
|
||||
let threadAssociatedData = ThreadAssociatedData.fetchOrDefault(for: thread, transaction: transaction)
|
||||
for item in model.items {
|
||||
let interaction: TSInteraction
|
||||
switch item {
|
||||
@ -142,6 +143,7 @@ class MockConversationView: UIView {
|
||||
guard let renderItem = CVLoader.buildStandaloneRenderItem(
|
||||
interaction: interaction,
|
||||
thread: self.thread,
|
||||
threadAssociatedData: threadAssociatedData,
|
||||
conversationStyle: conversationStyle,
|
||||
transaction: transaction
|
||||
) else {
|
||||
@ -273,6 +275,8 @@ extension MockConversationView: CVComponentDelegate {
|
||||
|
||||
func cvc_enqueueReload() {}
|
||||
|
||||
func cvc_enqueueReloadWithoutCaches() {}
|
||||
|
||||
func cvc_didTapBodyTextItem(_ item: CVBodyTextLabel.ItemObject) {}
|
||||
|
||||
func cvc_didLongPressBodyTextItem(_ item: CVBodyTextLabel.ItemObject) {}
|
||||
|
||||
@ -126,6 +126,7 @@ public class ThreadAssociatedData: NSObject, Codable, FetchableRecord, Persistab
|
||||
self.id = rowID
|
||||
}
|
||||
|
||||
@objc
|
||||
public init(
|
||||
threadUniqueId: String,
|
||||
isArchived: Bool,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user