Convert ContactCellConfiguration and ContactCellAccessoryView to structs.

This commit is contained in:
Igor Solomennikov 2026-05-29 06:21:35 -07:00 committed by GitHub
parent d535e8bfe2
commit 2260eb9b8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 180 additions and 210 deletions

View File

@ -125,6 +125,7 @@ extension NewCallViewController: RecipientContextMenuHelperDelegate {
// MARK: - RecipientPickerDelegate
extension NewCallViewController: RecipientPickerDelegate, UsernameLinkScanDelegate {
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
selectionStyleForRecipient recipient: PickedRecipient,
@ -133,7 +134,10 @@ extension NewCallViewController: RecipientPickerDelegate, UsernameLinkScanDelega
return .default
}
func recipientPicker(_ recipientPickerViewController: RecipientPickerViewController, didSelectRecipient recipient: PickedRecipient) {
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
didSelectRecipient recipient: PickedRecipient,
) {
switch recipient.identifier {
case let .address(address):
let thread = TSContactThread.getOrCreateThread(contactAddress: address)
@ -143,7 +147,12 @@ extension NewCallViewController: RecipientPickerDelegate, UsernameLinkScanDelega
}
}
func recipientPicker(_ recipientPickerViewController: RecipientPickerViewController, accessoryViewForRecipient recipient: PickedRecipient, transaction: DBReadTransaction) -> ContactCellAccessoryView? {
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
contactCellAccessoryForRecipient recipient: PickedRecipient,
transaction: DBReadTransaction,
) -> ContactCellView.Accessory? {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.spacing = 20

View File

@ -159,7 +159,7 @@ class MessageUserSubsetSheet: OWSTableSheetViewController {
cell.selectionStyle = .none
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asLocalUser)
var configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .asLocalUser)
configuration.forceDarkAppearance = self?.forceDarkMode ?? false
if

View File

@ -95,10 +95,7 @@ class BlockListViewController: OWSTableViewController2 {
OWSTableItem(
dequeueCellBlock: { [weak self] tableView in
let cell = tableView.dequeueReusableCell(withIdentifier: ContactTableViewCell.reuseIdentifier) as! ContactTableViewCell
let config = ContactCellConfiguration(
address: address,
localUserDisplayMode: .asUser,
)
let config = ContactCellView.Configuration(address: address, localUserDisplayMode: .asUser)
if self != nil {
SSKEnvironment.shared.databaseStorageRef.read { transaction in
cell.configure(configuration: config, transaction: transaction)

View File

@ -89,10 +89,7 @@ class GroupStorySettingsViewController: OWSTableViewController2 {
return UITableViewCell()
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: viewerAddress, localUserDisplayMode: .asLocalUser)
cell.configure(configuration: configuration, transaction: transaction)
}
cell.configureWithSneakyTransaction(address: viewerAddress, localUserDisplayMode: .asLocalUser)
return cell
}, actionBlock: { [weak self] in

View File

@ -121,10 +121,7 @@ final class PrivateStorySettingsViewController: OWSTableViewController2 {
return UITableViewCell()
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: viewerAddress, localUserDisplayMode: .asLocalUser)
cell.configure(configuration: configuration, transaction: transaction)
}
cell.configureWithSneakyTransaction(address: viewerAddress, localUserDisplayMode: .asLocalUser)
return cell
}, actionBlock: { [weak self] in

View File

@ -253,7 +253,7 @@ private class StoryThreadCell: ContactTableViewCell {
// MARK: - ContactTableViewCell
func configure(conversationItem: StoryConversationItem, transaction: DBReadTransaction) {
let configuration: ContactCellConfiguration
var configuration: ContactCellView.Configuration
switch conversationItem.messageRecipient {
case .contact:
owsFailDebug("Unexpected recipient for story")
@ -268,21 +268,21 @@ private class StoryThreadCell: ContactTableViewCell {
owsFailDebug("Failed to find group thread")
return
}
configuration = ContactCellConfiguration(groupThread: groupThread, localUserDisplayMode: .noteToSelf)
configuration = ContactCellView.Configuration(groupThread: groupThread, localUserDisplayMode: .noteToSelf)
case .privateStory(_, let isMyStory):
if isMyStory {
guard let localAddress = DependenciesBridge.shared.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.aciAddress else {
owsFailDebug("Unexpectedly missing local address")
return
}
configuration = ContactCellConfiguration(address: localAddress, localUserDisplayMode: .asUser)
configuration = ContactCellView.Configuration(address: localAddress, localUserDisplayMode: .asUser)
configuration.customName = conversationItem.title(transaction: transaction)
} else {
guard let image = conversationItem.image else {
owsFailDebug("Unexpectedly missing image for private story")
return
}
configuration = ContactCellConfiguration(name: conversationItem.title(transaction: transaction), avatar: image)
configuration = ContactCellView.Configuration(name: conversationItem.title(transaction: transaction), avatar: image)
}
}

View File

@ -301,9 +301,9 @@ class StoryInfoSheet: OWSTableViewController2, DatabaseChangeDelegate, UIAdaptiv
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asUser)
var configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .asUser)
configuration.forceDarkAppearance = true
configuration.accessoryView = self.buildAccessoryView(
configuration.accessory = self.buildContactCellAccessory(
text: accessoryText,
transaction: transaction,
)
@ -325,10 +325,10 @@ class StoryInfoSheet: OWSTableViewController2, DatabaseChangeDelegate, UIAdaptiv
})
}
private func buildAccessoryView(
private func buildContactCellAccessory(
text: String,
transaction: DBReadTransaction,
) -> ContactCellAccessoryView {
) -> ContactCellView.Accessory {
let label = CVLabel()
let labelConfig = CVLabelConfig.unstyledText(
text,
@ -338,7 +338,7 @@ class StoryInfoSheet: OWSTableViewController2, DatabaseChangeDelegate, UIAdaptiv
labelConfig.applyForRendering(label: label)
let labelSize = CVText.measureLabel(config: labelConfig, maxWidth: .greatestFiniteMagnitude)
return ContactCellAccessoryView(accessoryView: label, size: labelSize)
return .init(accessoryView: label, size: labelSize)
}
// MARK: - DatabaseChangeDelegate

View File

@ -501,7 +501,7 @@ class MemberLabelViewController: OWSViewController, UITextFieldDelegate {
for (memberAddress, memberLabel) in sortedNonLocalMembers {
let cell = ContactCellView()
SSKEnvironment.shared.databaseStorageRef.read { tx in
let configuration = ContactCellConfiguration(address: memberAddress, localUserDisplayMode: .asLocalUser)
var configuration = ContactCellView.Configuration(address: memberAddress, localUserDisplayMode: .asLocalUser)
configuration.memberLabel = memberLabel

View File

@ -522,8 +522,8 @@ class MessageDetailViewController: OWSTableViewController2 {
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asUser)
configuration.accessoryView = self.buildAccessoryView(
var configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .asUser)
configuration.accessory = self.buildContactCellAccessory(
text: accessoryText,
displayUDIndicator: displayUDIndicator,
transaction: transaction,
@ -548,11 +548,11 @@ class MessageDetailViewController: OWSTableViewController2 {
expiryLabel?.attributedText = expiryLabelAttributedText
}
private func buildAccessoryView(
private func buildContactCellAccessory(
text: String,
displayUDIndicator: Bool,
transaction: DBReadTransaction,
) -> ContactCellAccessoryView {
) -> ContactCellView.Accessory {
let label = CVLabel()
label.textAlignment = .right
let labelConfig = CVLabelConfig.unstyledText(
@ -566,7 +566,7 @@ class MessageDetailViewController: OWSTableViewController2 {
let shouldShowUD = SSKEnvironment.shared.preferencesRef.shouldShowUnidentifiedDeliveryIndicators(transaction: transaction)
guard displayUDIndicator, shouldShowUD else {
return ContactCellAccessoryView(accessoryView: label, size: labelSize)
return .init(accessoryView: label, size: labelSize)
}
let imageView = CVImageView()
@ -589,7 +589,7 @@ class MessageDetailViewController: OWSTableViewController2 {
],
)
let hStackSize = hStackMeasurement.measuredSize
return ContactCellAccessoryView(accessoryView: hStack, size: hStackSize)
return .init(accessoryView: hStack, size: hStackSize)
}
private static func valueLabelAttributedText(name: String, value: String) -> NSAttributedString {

View File

@ -194,11 +194,8 @@ public class NewGroupConfirmViewController: OWSTableViewController2 {
}
cell.selectionStyle = .none
cell.configureWithSneakyTransaction(address: address, localUserDisplayMode: .asUser)
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asUser)
cell.configure(configuration: configuration, transaction: transaction)
}
return cell
},
))

View File

@ -264,7 +264,7 @@ struct PollDetailsView: View {
private func addressCell(address: SignalServiceAddress) -> ManualStackView? {
let cell = ContactCellView()
let config = ContactCellConfiguration(address: address, localUserDisplayMode: .asLocalUser)
var config = ContactCellView.Configuration(address: address, localUserDisplayMode: .asLocalUser)
config.avatarSizeClass = .twentyEight
SSKEnvironment.shared.databaseStorageRef.read { transaction in

View File

@ -913,7 +913,7 @@ extension ConversationSettingsViewController {
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: memberAddress, localUserDisplayMode: .asLocalUser)
var configuration = ContactCellView.Configuration(address: memberAddress, localUserDisplayMode: .asLocalUser)
let isGroupAdmin = groupMembership.isFullMemberAndAdministrator(memberAddress)
let isVerified = verificationState == .verified
let isNoLongerVerified = verificationState == .noLongerVerified

View File

@ -172,12 +172,12 @@ public class GroupMemberRequestsAndInvitesViewController: OWSTableViewController
let cell = ContactTableViewCell(style: .default, reuseIdentifier: nil)
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asLocalUser)
var configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .asLocalUser)
configuration.allowUserInteraction = true
configuration.avatarSizeClass = .forty
if canApproveMemberRequests {
configuration.accessoryView = self.buildMemberRequestButtons(address: address)
configuration.accessory = self.buildMemberRequestButtons(address: address)
}
if address.isLocalAddress {
@ -204,7 +204,7 @@ public class GroupMemberRequestsAndInvitesViewController: OWSTableViewController
contents.add(section)
}
private func buildMemberRequestButtons(address: SignalServiceAddress) -> ContactCellAccessoryView {
private func buildMemberRequestButtons(address: SignalServiceAddress) -> ContactCellView.Accessory {
let denyButton = UIButton(
configuration: .roundGray(image: UIImage(resource: .x)),
primaryAction: UIAction { [weak self] _ in
@ -242,7 +242,7 @@ public class GroupMemberRequestsAndInvitesViewController: OWSTableViewController
],
)
let stackSize = stackMeasurement.measuredSize
return ContactCellAccessoryView(accessoryView: stackView, size: stackSize)
return ContactCellView.Accessory(accessoryView: stackView, size: stackSize)
}
private func approveMemberRequest(address: SignalServiceAddress) {
@ -311,7 +311,7 @@ public class GroupMemberRequestsAndInvitesViewController: OWSTableViewController
cell.selectionStyle = canRevokeInvites ? .default : .none
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asUser)
var configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .asUser)
configuration.avatarSizeClass = .forty
cell.configure(configuration: configuration, transaction: transaction)
}
@ -366,8 +366,7 @@ public class GroupMemberRequestsAndInvitesViewController: OWSTableViewController
cell.selectionStyle = canRevokeInvites ? .default : .none
databaseStorage.read { transaction in
let configuration = ContactCellConfiguration(address: inviterAddress, localUserDisplayMode: .asUser)
configuration.avatarSizeClass = .forty
var configuration = ContactCellView.Configuration(address: inviterAddress, localUserDisplayMode: .asUser)
let inviterName = contactManager.displayName(for: inviterAddress, tx: transaction).resolvedValue()
let format = OWSLocalizedString(
"PENDING_GROUP_MEMBERS_MEMBER_INVITED_USERS_%d",
@ -375,6 +374,7 @@ public class GroupMemberRequestsAndInvitesViewController: OWSTableViewController
comment: "Format for label indicating the a group member has invited N other users to the group. Embeds {{ %1$@ the number of users they have invited, %2$@ name of the inviting group member }}.",
)
configuration.customName = String.localizedStringWithFormat(format, invitedAddresses.count, inviterName)
configuration.avatarSizeClass = .forty
cell.configure(configuration: configuration, transaction: transaction)
}

View File

@ -82,12 +82,7 @@ class ReplaceAdminViewController: OWSTableViewController2 {
owsFailDebug("Missing cell.")
return UITableViewCell()
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asUser)
cell.configure(configuration: configuration, transaction: transaction)
}
cell.configureWithSneakyTransaction(address: address, localUserDisplayMode: .asUser)
return cell
},
actionBlock: { [weak self] in

View File

@ -399,9 +399,9 @@ extension BaseMemberViewController: RecipientPickerDelegate {
public func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
accessoryViewForRecipient recipient: PickedRecipient,
contactCellAccessoryForRecipient recipient: PickedRecipient,
transaction: DBReadTransaction,
) -> ContactCellAccessoryView? {
) -> ContactCellView.Accessory? {
guard let address = recipient.address else {
owsFailDebug("Missing address.")
return nil
@ -441,7 +441,7 @@ extension BaseMemberViewController: RecipientPickerDelegate {
accessoryView = SelectionIndicatorView()
}
let accessoryViewWrapper = ManualLayoutView.wrapSubviewUsingIOSAutoLayout(accessoryView)
return ContactCellAccessoryView(accessoryView: accessoryViewWrapper, size: .square(24))
return ContactCellView.Accessory(accessoryView: accessoryViewWrapper, size: .square(24))
}
public func recipientPicker(

View File

@ -3,102 +3,88 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public import SignalServiceKit
public class ContactCellAccessoryView: NSObject {
let accessoryView: UIView
let size: CGSize
public init(accessoryView: UIView, size: CGSize) {
self.accessoryView = accessoryView
self.size = size
}
}
// MARK: -
public class ContactCellConfiguration: NSObject {
fileprivate enum CellDataSource {
case address(SignalServiceAddress)
case groupThread(TSGroupThread)
case `static`(name: String, avatar: UIImage)
}
fileprivate let dataSource: CellDataSource
public let localUserDisplayMode: LocalUserDisplayMode
public var forceDarkAppearance = false
public var accessoryMessage: String?
public var customName: String?
public var accessoryView: ContactCellAccessoryView?
public var attributedSubtitle: NSAttributedString?
public var shouldShowContactIcon = false
public var allowUserInteraction = false
public var badged = true // TODO: Badges Default false? Configure each use-case?
public var storyState: StoryContextViewState?
public var hasAccessoryText: Bool {
accessoryMessage?.nilIfEmpty != nil
}
public var avatarSizeClass: ConversationAvatarView.Configuration.SizeClass?
public var memberLabel: MemberLabelForRendering?
public init(address: SignalServiceAddress, localUserDisplayMode: LocalUserDisplayMode) {
self.dataSource = .address(address)
self.localUserDisplayMode = localUserDisplayMode
super.init()
}
public init(groupThread: TSGroupThread, localUserDisplayMode: LocalUserDisplayMode) {
self.dataSource = .groupThread(groupThread)
self.localUserDisplayMode = localUserDisplayMode
super.init()
}
public init(name: String, avatar: UIImage) {
self.dataSource = .static(name: name, avatar: avatar)
self.localUserDisplayMode = .asUser
super.init()
}
public func useVerifiedSubtitle() {
let text = NSMutableAttributedString()
text.append(SignalSymbol.safetyNumber.attributedString(for: .caption1, clamped: true))
text.append(" ", attributes: [:])
text.append(SafetyNumberStrings.verified, attributes: [:])
self.attributedSubtitle = text
}
}
// MARK: -
public class ContactCellView: ManualStackView {
private var configuration: ContactCellConfiguration? {
didSet {
ensureObservers()
public struct Configuration {
fileprivate enum CellDataSource {
case address(SignalServiceAddress)
case groupThread(TSGroupThread)
case `static`(name: String, avatar: UIImage)
}
fileprivate let dataSource: CellDataSource
public let localUserDisplayMode: LocalUserDisplayMode
public var forceDarkAppearance = false
public var accessoryMessage: String?
public var customName: String?
public var accessory: ContactCellView.Accessory?
public var attributedSubtitle: NSAttributedString?
public var shouldShowContactIcon = false
public var allowUserInteraction = false
public var badged = true // TODO: Badges Default false? Configure each use-case?
public var storyState: StoryContextViewState?
public var hasAccessoryText: Bool {
accessoryMessage?.nilIfEmpty != nil
}
public var avatarSizeClass: ConversationAvatarView.Configuration.SizeClass?
public var memberLabel: MemberLabelForRendering?
public init(address: SignalServiceAddress, localUserDisplayMode: LocalUserDisplayMode) {
self.dataSource = .address(address)
self.localUserDisplayMode = localUserDisplayMode
}
public init(groupThread: TSGroupThread, localUserDisplayMode: LocalUserDisplayMode) {
self.dataSource = .groupThread(groupThread)
self.localUserDisplayMode = localUserDisplayMode
}
public init(name: String, avatar: UIImage) {
self.dataSource = .static(name: name, avatar: avatar)
self.localUserDisplayMode = .asUser
}
public mutating func useVerifiedSubtitle() {
let text = NSMutableAttributedString()
text.append(SignalSymbol.safetyNumber.attributedString(for: .caption1, clamped: true))
text.append(" ", attributes: [:])
text.append(SafetyNumberStrings.verified, attributes: [:])
self.attributedSubtitle = text
}
}
public struct Accessory {
let accessoryView: UIView
let size: CGSize
public init(accessoryView: UIView, size: CGSize) {
self.accessoryView = accessoryView
self.size = size
}
}
public static var avatarSizeClass: ConversationAvatarView.Configuration.SizeClass { .thirtySix }
private var avatarDataSource: ConversationAvatarDataSource? {
switch configuration?.dataSource {
private func avatarDataSource(configuration: Configuration) -> ConversationAvatarDataSource {
switch configuration.dataSource {
case .groupThread(let thread): return .thread(thread)
case .address(let address): return .address(address)
case .static(_, let avatar): return .asset(avatar: avatar, badge: nil)
case nil: return nil
}
}
@ -165,15 +151,16 @@ public class ContactCellView: ManualStackView {
}
public func configure(
configuration: ContactCellConfiguration,
configuration: Configuration,
transaction: DBReadTransaction,
) {
AssertIsOnMainThread()
owsAssertDebug(!shouldDeactivateConstraints)
self.configuration = configuration
setupObservations(configuration: configuration)
self.isUserInteractionEnabled = configuration.allowUserInteraction
isUserInteractionEnabled = configuration.allowUserInteraction
let avatarDataSource = avatarDataSource(configuration: configuration)
avatarView.update(transaction) { config in
config.dataSource = avatarDataSource
@ -189,16 +176,13 @@ public class ContactCellView: ManualStackView {
}
}
if
avatarDataSource?.isGroupAvatar ?? false,
let storyState = configuration.storyState
{
if avatarDataSource.isGroupAvatar, let storyState = configuration.storyState {
// Group story. Add badge
avatarView.addSubview(groupStoryBadgeView)
let badgeColor: UIColor
switch storyState {
case .unviewed:
badgeColor = .ows_accentBlue
badgeColor = .Signal.accent
case .viewed, .noStories:
badgeColor = Theme.isDarkThemeEnabled ? .ows_gray65 : .ows_gray25
}
@ -277,17 +261,18 @@ public class ContactCellView: ManualStackView {
rootStackSubviewInfos.append(textStackMeasurement.measuredSize.asManualSubviewInfo)
}
var accessory = configuration.accessory
if let accessoryMessage = configuration.accessoryMessage {
accessoryLabel.text = accessoryMessage
let labelSize = accessoryLabel.sizeThatFits(.square(.greatestFiniteMagnitude))
configuration.accessoryView = ContactCellAccessoryView(
accessory = Accessory(
accessoryView: accessoryLabel,
size: labelSize,
)
}
if let accessoryView = configuration.accessoryView {
rootStackSubviews.append(accessoryView.accessoryView)
rootStackSubviewInfos.append(accessoryView.size.asManualSubviewInfo(hasFixedSize: true))
if let accessory {
rootStackSubviews.append(accessory.accessoryView)
rootStackSubviewInfos.append(accessory.size.asManualSubviewInfo(hasFixedSize: true))
}
let rootStackConfig = ManualStackView.Config(
@ -310,32 +295,44 @@ public class ContactCellView: ManualStackView {
// MARK: - Notifications
private func ensureObservers() {
NotificationCenter.default.removeObserver(self)
if case .address = configuration?.dataSource {
NotificationCenter.default.addObserver(
self,
selector: #selector(otherUsersProfileChanged(notification:)),
private var observation: NotificationCenter.Observer?
private func setupObservations(configuration: Configuration) {
if let observation {
NotificationCenter.default.removeObserver(observation)
self.observation = nil
}
if case .address = configuration.dataSource {
observation = NotificationCenter.default.addObserver(
name: UserProfileNotifications.otherUsersProfileDidChange,
object: nil,
)
) { [weak self] notification in
guard
let changedAddress = notification.userInfo?[UserProfileNotifications.profileAddressKey] as? SignalServiceAddress,
changedAddress.isValid
else {
owsFailDebug("changedAddress was unexpectedly nil")
return
}
if case .address(changedAddress) = configuration.dataSource {
self?.updateNameLabelsWithSneakyTransaction(configuration: configuration)
}
}
}
}
// MARK: -
private func updateNameLabelsWithSneakyTransaction(configuration: ContactCellConfiguration) {
private func updateNameLabelsWithSneakyTransaction(configuration: Configuration) {
SSKEnvironment.shared.databaseStorageRef.read { transaction in
updateNameLabels(configuration: configuration, transaction: transaction)
}
}
private func updateNameLabels(
configuration: ContactCellConfiguration,
configuration: Configuration,
transaction: DBReadTransaction,
) {
AssertIsOnMainThread()
let textColor = self.nameLabelColor(forceDarkAppearance: configuration.forceDarkAppearance)
let nameString = { () -> NSAttributedString in
@ -389,9 +386,10 @@ public class ContactCellView: ManualStackView {
override public func reset() {
super.reset()
NotificationCenter.default.removeObserver(self)
configuration = nil
if let observation {
NotificationCenter.default.removeObserver(observation)
self.observation = nil
}
avatarView.reset()
textStack.reset()
@ -400,24 +398,4 @@ public class ContactCellView: ManualStackView {
subtitleLabel.text = nil
accessoryLabel.text = nil
}
@objc
private func otherUsersProfileChanged(notification: Notification) {
AssertIsOnMainThread()
guard let configuration = self.configuration else {
return
}
guard
let changedAddress = notification.userInfo?[UserProfileNotifications.profileAddressKey] as? SignalServiceAddress,
changedAddress.isValid
else {
owsFailDebug("changedAddress was unexpectedly nil")
return
}
if case .address(changedAddress) = configuration.dataSource {
updateNameLabelsWithSneakyTransaction(configuration: configuration)
}
}
}

View File

@ -56,7 +56,7 @@ open class ContactTableViewCell: UITableViewCell, ReusableTableViewCell {
localUserDisplayMode: LocalUserDisplayMode,
transaction: DBReadTransaction,
) {
let configuration = ContactCellConfiguration(
let configuration = ContactCellView.Configuration(
address: address,
localUserDisplayMode: localUserDisplayMode,
)
@ -68,7 +68,7 @@ open class ContactTableViewCell: UITableViewCell, ReusableTableViewCell {
localUserDisplayMode: LocalUserDisplayMode,
transaction: DBReadTransaction,
) {
let configuration = ContactCellConfiguration(
let configuration = ContactCellView.Configuration(
address: thread.contactAddress,
localUserDisplayMode: localUserDisplayMode,
)
@ -76,7 +76,7 @@ open class ContactTableViewCell: UITableViewCell, ReusableTableViewCell {
}
open func configure(
configuration: ContactCellConfiguration,
configuration: ContactCellView.Configuration,
transaction: DBReadTransaction,
) {
OWSTableItem.configureCell(self)

View File

@ -1295,10 +1295,10 @@ class ConversationPickerCell: ContactTableViewCell {
// MARK: - ContactTableViewCell
func configure(conversationItem: ConversationItem, transaction: DBReadTransaction) {
let configuration: ContactCellConfiguration
var configuration: ContactCellView.Configuration
switch conversationItem.messageRecipient {
case .contact(let address):
configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .noteToSelf)
configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .noteToSelf)
case .group(let groupThreadId):
guard
let groupThread = TSGroupThread.fetchGroupThreadViaCache(
@ -1309,27 +1309,27 @@ class ConversationPickerCell: ContactTableViewCell {
owsFailDebug("Failed to find group thread")
return
}
configuration = ContactCellConfiguration(groupThread: groupThread, localUserDisplayMode: .noteToSelf)
configuration = ContactCellView.Configuration(groupThread: groupThread, localUserDisplayMode: .noteToSelf)
case .privateStory(_, let isMyStory):
if isMyStory {
guard let localAddress = DependenciesBridge.shared.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.aciAddress else {
owsFailDebug("Unexpectedly missing local address")
return
}
configuration = ContactCellConfiguration(address: localAddress, localUserDisplayMode: .asUser)
configuration = ContactCellView.Configuration(address: localAddress, localUserDisplayMode: .asUser)
configuration.customName = conversationItem.title(transaction: transaction)
} else {
guard let image = conversationItem.image else {
owsFailDebug("Unexpectedly missing image for private story")
return
}
configuration = ContactCellConfiguration(name: conversationItem.title(transaction: transaction), avatar: image)
configuration = ContactCellView.Configuration(name: conversationItem.title(transaction: transaction), avatar: image)
}
}
if conversationItem.isBlocked {
configuration.accessoryMessage = MessageStrings.conversationIsBlocked
} else {
configuration.accessoryView = buildAccessoryView(disappearingMessagesConfig: conversationItem.disappearingMessagesConfig)
configuration.accessory = buildContactCellAccessory(disappearingMessagesConfig: conversationItem.disappearingMessagesConfig)
}
if let storyItem = conversationItem as? StoryConversationItem {
@ -1355,7 +1355,7 @@ class ConversationPickerCell: ContactTableViewCell {
private lazy var selectionView = SelectionIndicatorView()
func buildAccessoryView(disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?) -> ContactCellAccessoryView {
func buildContactCellAccessory(disappearingMessagesConfig: DisappearingMessagesConfigurationRecord?) -> ContactCellView.Accessory {
selectionView.removeFromSuperview()
let selectionWrapper = ManualLayoutView.wrapSubviewUsingIOSAutoLayout(selectionView)
@ -1364,7 +1364,7 @@ class ConversationPickerCell: ContactTableViewCell {
let disappearingMessagesConfig,
disappearingMessagesConfig.isEnabled
else {
return ContactCellAccessoryView(
return ContactCellView.Accessory(
accessoryView: selectionWrapper,
size: selectionView.intrinsicContentSize,
)
@ -1389,7 +1389,7 @@ class ConversationPickerCell: ContactTableViewCell {
],
)
let stackSize = stackMeasurement.measuredSize
return ContactCellAccessoryView(accessoryView: stackView, size: stackSize)
return ContactCellView.Accessory(accessoryView: stackView, size: stackSize)
}
}

View File

@ -25,9 +25,9 @@ public protocol RecipientPickerDelegate: RecipientContextMenuHelperDelegate {
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
accessoryViewForRecipient recipient: PickedRecipient,
contactCellAccessoryForRecipient recipient: PickedRecipient,
transaction: DBReadTransaction,
) -> ContactCellAccessoryView?
) -> ContactCellView.Accessory?
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
@ -58,9 +58,9 @@ public extension RecipientPickerDelegate {
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,
accessoryViewForRecipient recipient: PickedRecipient,
contactCellAccessoryForRecipient recipient: PickedRecipient,
transaction: DBReadTransaction,
) -> ContactCellAccessoryView? { nil }
) -> ContactCellView.Accessory? { nil }
func recipientPicker(
_ recipientPickerViewController: RecipientPickerViewController,

View File

@ -1021,11 +1021,11 @@ extension RecipientPickerViewController {
private func addressCell(for address: SignalServiceAddress, recipient: PickedRecipient, tableView: UITableView) -> UITableViewCell? {
guard let cell = tableView.dequeueReusableCell(ContactTableViewCell.self) else { return nil }
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .noteToSelf)
var configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .noteToSelf)
if let delegate {
cell.selectionStyle = delegate.recipientPicker(self, selectionStyleForRecipient: recipient, transaction: transaction)
if let accessoryView = delegate.recipientPicker(self, accessoryViewForRecipient: recipient, transaction: transaction) {
configuration.accessoryView = accessoryView
if let accessory = delegate.recipientPicker(self, contactCellAccessoryForRecipient: recipient, transaction: transaction) {
configuration.accessory = accessory
} else {
let accessoryMessage = delegate.recipientPicker(self, accessoryMessageForRecipient: recipient, transaction: transaction)
configuration.accessoryMessage = accessoryMessage
@ -1051,7 +1051,7 @@ extension RecipientPickerViewController {
SSKEnvironment.shared.databaseStorageRef.read { tx in
cell.selectionStyle = delegate.recipientPicker(self, selectionStyleForRecipient: recipient, transaction: tx)
cell.accessoryMessage = delegate.recipientPicker(self, accessoryMessageForRecipient: recipient, transaction: tx)
cell.customAccessoryView = delegate.recipientPicker(self, accessoryViewForRecipient: recipient, transaction: tx)?.accessoryView
cell.customAccessoryView = delegate.recipientPicker(self, contactCellAccessoryForRecipient: recipient, transaction: tx)?.accessoryView
}
}

View File

@ -682,7 +682,7 @@ private class SafetyNumberCell: ContactTableViewCell {
}
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: item.address, localUserDisplayMode: .asUser)
var configuration = ContactCellView.Configuration(address: item.address, localUserDisplayMode: .asUser)
configuration.allowUserInteraction = true
configuration.forceDarkAppearance = traitCollection.userInterfaceStyle == .dark
@ -690,7 +690,7 @@ private class SafetyNumberCell: ContactTableViewCell {
let buttonSize = button.intrinsicContentSize
button.removeFromSuperview()
let buttonWrapper = ManualLayoutView.wrapSubviewUsingIOSAutoLayout(button)
configuration.accessoryView = ContactCellAccessoryView(
configuration.accessory = ContactCellView.Accessory(
accessoryView: buttonWrapper,
size: buttonSize,
)
@ -720,7 +720,7 @@ private class SafetyNumberCell: ContactTableViewCell {
}
}
override func configure(configuration: ContactCellConfiguration, transaction: DBReadTransaction) {
override func configure(configuration: ContactCellView.Configuration, transaction: DBReadTransaction) {
super.configure(configuration: configuration, transaction: transaction)
backgroundColor = nil
}

View File

@ -142,7 +142,7 @@ public class NewPrivateStoryConfirmViewController: OWSTableViewController2 {
cell.selectionStyle = .none
SSKEnvironment.shared.databaseStorageRef.read { transaction in
let configuration = ContactCellConfiguration(address: address, localUserDisplayMode: .asUser)
let configuration = ContactCellView.Configuration(address: address, localUserDisplayMode: .asUser)
cell.configure(configuration: configuration, transaction: transaction)
}
return cell