Member Label view controller UI

This commit is contained in:
kate-signal 2026-01-16 16:04:28 -05:00 committed by GitHub
parent 212cefb9ec
commit 3b6d3f5e0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 497 additions and 16 deletions

View File

@ -52,6 +52,7 @@
04441DDE2F115CAF0095E1F4 /* chat_item_pin_message_04.txtproto in Resources */ = {isa = PBXBuildFile; fileRef = 04441DA02F115CAF0095E1F4 /* chat_item_pin_message_04.txtproto */; };
04441DEA2F17EF6C0095E1F4 /* CVMemberLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04441DE92F17EF690095E1F4 /* CVMemberLabel.swift */; };
04441DED2F1816BB0095E1F4 /* MemberLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04441DEB2F18121C0095E1F4 /* MemberLabel.swift */; };
04441DEF2F194B800095E1F4 /* MemberLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04441DEE2F194B770095E1F4 /* MemberLabelViewController.swift */; };
04472D5E2E8AD74200D69EE0 /* OutgoingPollVote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04472D5D2E8AD73A00D69EE0 /* OutgoingPollVote.swift */; };
044A2C6E2EEB444E00AA3CA0 /* BackupArchivePinMessageChatUpdateArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044A2C6D2EEB443E00AA3CA0 /* BackupArchivePinMessageChatUpdateArchiver.swift */; };
044D77782E5E6D750048C21A /* PollVoteRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044D77772E5E6D700048C21A /* PollVoteRecord.swift */; };
@ -4108,6 +4109,7 @@
04441DBA2F115CAF0095E1F4 /* chat_item_pin_message_update_02.txtproto */ = {isa = PBXFileReference; lastKnownFileType = text; path = chat_item_pin_message_update_02.txtproto; sourceTree = "<group>"; };
04441DE92F17EF690095E1F4 /* CVMemberLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CVMemberLabel.swift; sourceTree = "<group>"; };
04441DEB2F18121C0095E1F4 /* MemberLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberLabel.swift; sourceTree = "<group>"; };
04441DEE2F194B770095E1F4 /* MemberLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberLabelViewController.swift; sourceTree = "<group>"; };
04472D5D2E8AD73A00D69EE0 /* OutgoingPollVote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingPollVote.swift; sourceTree = "<group>"; };
044A2C6D2EEB443E00AA3CA0 /* BackupArchivePinMessageChatUpdateArchiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupArchivePinMessageChatUpdateArchiver.swift; sourceTree = "<group>"; };
044D77772E5E6D700048C21A /* PollVoteRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollVoteRecord.swift; sourceTree = "<group>"; };
@ -9172,6 +9174,7 @@
76C87FE028BE8E2400BD8709 /* LinkPreviewAttachmentViewController.swift */,
88A9729322FB4D02004B4FBF /* LocationPicker.swift */,
3496744E2076ACCE00080B5F /* LongTextViewController.swift */,
04441DEE2F194B770095E1F4 /* MemberLabelViewController.swift */,
4CFF4C0920F55BBA005DA313 /* MessageActionsToolbar.swift */,
34CA1C261F7156F300E51C51 /* MessageDetailViewController.swift */,
881218EF238CA51600E6F271 /* MessageReactionPicker.swift */,
@ -18134,6 +18137,7 @@
4C8A6DFC22E5499300469AE7 /* MediaZoomAnimationController.swift in Sources */,
8837F74123DA0B0F00772A32 /* MegaphoneView.swift in Sources */,
88A357B923639384009D6B9A /* MemberActionSheet.swift in Sources */,
04441DEF2F194B800095E1F4 /* MemberLabelViewController.swift in Sources */,
346EAA14250199A400E8AB6F /* MemberRequestView.swift in Sources */,
4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */,
4CB5F26720F6E1E2004D1B42 /* MessageActionsToolbar.swift in Sources */,

View File

@ -0,0 +1,438 @@
//
// Copyright 2026 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import LibSignalClient
import SignalServiceKit
import SignalUI
import SwiftUI
class MemberLabelViewController: OWSViewController {
override init() {
super.init()
view.backgroundColor = UIColor.Signal.groupedBackground
navigationItem.title = OWSLocalizedString("MEMBER_LABEL_VIEW_TITLE", comment: "Title for a view where users can edit and preview their member label.")
// TODO: fade if text field empty
navigationItem.rightBarButtonItem = .init(barButtonSystemItem: .done, target: self, action: #selector(didTapDone))
navigationItem.leftBarButtonItem = .init(barButtonSystemItem: .cancel, target: self, action: #selector(didTapCancel))
navigationItem.rightBarButtonItem?.tintColor = UIColor.Signal.ultramarine
}
override func viewDidLoad() {
super.viewDidLoad()
createViews()
}
private func createViews() {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.spacing = 20
let subtitleLabel = UILabel()
subtitleLabel.text = OWSLocalizedString(
"MEMBER_LABEL_VIEW_SUBTITLE",
comment: "Subtitle for a view where users can edit and preview their member label.",
)
subtitleLabel.numberOfLines = 0
subtitleLabel.font = .dynamicTypeCaption1Clamped
subtitleLabel.textColor = UIColor.Signal.secondaryLabel
subtitleLabel.textAlignment = .center
stackView.addArrangedSubview(subtitleLabel)
let textFieldStack = UIStackView()
textFieldStack.layer.cornerRadius = 27
textFieldStack.backgroundColor = UIColor.Signal.tertiaryBackground
textFieldStack.axis = .horizontal
textFieldStack.alignment = .center
textFieldStack.distribution = .fill
textFieldStack.spacing = 8
textFieldStack.isLayoutMarginsRelativeArrangement = true
textFieldStack.layoutMargins = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
let addEmojiButton = UIButton(type: .system)
addEmojiButton.setImage(UIImage(named: "emoji-plus"), for: .normal)
addEmojiButton.tintColor = UIColor.Signal.secondaryLabel
addEmojiButton.setContentHuggingPriority(.required, for: .horizontal)
addEmojiButton.setContentCompressionResistancePriority(.required, for: .horizontal)
let textField = UITextField()
textField.placeholder = OWSLocalizedString(
"MEMBER_LABEL_VIEW_PLACEHOLDER_TEXT",
comment: "Placeholder text in text field where user can edit their member label.",
)
textField.font = .dynamicTypeBodyClamped
textFieldStack.addArrangedSubview(addEmojiButton)
textFieldStack.addArrangedSubview(textField)
stackView.addArrangedSubview(textFieldStack)
stackView.setCustomSpacing(34, after: textFieldStack)
textFieldStack.translatesAutoresizingMaskIntoConstraints = false
textFieldStack.heightAnchor.constraint(equalToConstant: 52).isActive = true
guard
let mockConversationItem = buildMockConversationItem(),
let previewContainer = messageBubblePreviewContainer(renderItem: mockConversationItem)
else {
return
}
stackView.addArrangedSubview(previewContainer)
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 22),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -22),
])
}
private func buildMockConversationItem() -> CVRenderItem? {
let db = DependenciesBridge.shared.db
let attachmentContentValidator = DependenciesBridge.shared.attachmentContentValidator
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let messageBody = db.write { tx in
attachmentContentValidator.truncatedMessageBodyForInlining(
MessageBody(text: OWSLocalizedString(
"MEMBER_LABEL_VIEW_MESSAGE_PREVIEW_TEXT",
comment: "Text shown in the preview message bubble when a user is editing their member label.",
), ranges: .empty),
tx: tx,
)
}
guard
let localAci = db.read(block: { tx in
tsAccountManager.localIdentifiers(tx: tx)?.aci
}),
let secretParams = try? GroupSecretParams.generate()
else {
return nil
}
var groupModelBuilder = TSGroupModelBuilder(secretParams: secretParams)
var groupMembershipBuilder = groupModelBuilder.groupMembership.asBuilder
groupMembershipBuilder.setMemberLabel(label: "test123", aci: localAci)
groupModelBuilder.groupMembership = groupMembershipBuilder.build()
guard let groupModel = try? groupModelBuilder.buildAsV2() else {
return nil
}
let mockGroupThread = MockGroupThread(groupModel: groupModel)
let mockMessage = MockIncomingMessage(messageBody: messageBody, thread: mockGroupThread, authorAci: localAci)
let renderItem = db.read { tx in
let threadAssociatedData = ThreadAssociatedData.fetchOrDefault(for: mockGroupThread, ignoreMissing: true, transaction: tx)
let conversationStyle = ConversationStyle(
type: .`default`,
thread: mockGroupThread,
viewWidth: view.width - 44, // stack view padding
hasWallpaper: false,
isWallpaperPhoto: false,
chatColor: PaletteChatColor.ultramarine.colorSetting,
)
return CVLoader.buildStandaloneRenderItem(
interaction: mockMessage,
thread: mockGroupThread,
threadAssociatedData: threadAssociatedData,
conversationStyle: conversationStyle,
spoilerState: SpoilerRenderState(),
transaction: tx,
)
}
return renderItem
}
func messageBubblePreviewContainer(renderItem: CVRenderItem) -> UIView? {
let previewTitle = UILabel()
previewTitle.text = OWSLocalizedString(
"MEMBER_LABEL_PREVIEW_HEADING",
comment: "Heading shown above the preview of a message bubble with the edited member label.",
)
previewTitle.font = .dynamicTypeBodyClamped.semibold()
let cellView = CVCellView()
cellView.configure(renderItem: renderItem, componentDelegate: self)
cellView.isCellVisible = true
cellView.autoSetDimension(.height, toSize: renderItem.cellMeasurement.cellSize.height)
cellView.autoSetDimension(.width, toSize: renderItem.cellMeasurement.cellSize.width)
let cellContainer = UIView()
cellContainer.layer.cornerRadius = 27
cellContainer.layer.masksToBounds = true
cellContainer.backgroundColor = UIColor.Signal.tertiaryBackground
cellContainer.addSubview(cellView)
cellView.autoPinEdge(toSuperviewEdge: .top, withInset: 20)
cellView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 20)
let previewContainer = UIStackView()
previewContainer.axis = .vertical
previewContainer.spacing = 8
previewContainer.addArrangedSubview(previewTitle)
previewContainer.addArrangedSubview(cellContainer)
return previewContainer
}
@objc
private func didTapDone() {
dismiss(animated: true)
}
@objc
private func didTapCancel() {
dismiss(animated: true)
}
}
// MARK: -
extension MemberLabelViewController: CVComponentDelegate {
var spoilerState: SignalUI.SpoilerRenderState {
return SpoilerRenderState()
}
func enqueueReload() {}
func enqueueReloadWithoutCaches() {}
func didTapBodyTextItem(_ item: CVTextLabel.Item) {}
func didLongPressBodyTextItem(_ item: CVTextLabel.Item) {}
func didTapSystemMessageItem(_ item: CVTextLabel.Item) {}
func didDoubleTapTextViewItem(_ itemViewModel: CVItemViewModelImpl) {}
func didLongPressTextViewItem(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
shouldAllowReply: Bool,
) {}
func didLongPressMediaViewItem(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
shouldAllowReply: Bool,
) {}
func didLongPressQuote(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
shouldAllowReply: Bool,
) {}
func didLongPressSystemMessage(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
) {}
func didLongPressSticker(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
shouldAllowReply: Bool,
) {}
func didLongPressPaymentMessage(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
shouldAllowReply: Bool,
) {}
func didLongPressPoll(
_ cell: CVCell,
itemViewModel: CVItemViewModelImpl,
shouldAllowReply: Bool,
) {}
func didTapPayment(_ payment: PaymentsHistoryItem) {}
func didChangeLongPress(_ itemViewModel: CVItemViewModelImpl) {}
func didEndLongPress(_ itemViewModel: CVItemViewModelImpl) {}
func didCancelLongPress(_ itemViewModel: CVItemViewModelImpl) {}
// MARK: -
func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage) {}
func didTapFailedOrPendingDownloads(_ message: TSMessage) {}
func didCancelDownload(_ message: TSMessage, attachmentId: Attachment.IDType) {}
// MARK: -
func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {}
func didTapSenderAvatar(_ interaction: TSInteraction) {}
func shouldAllowReplyForItem(_ itemViewModel: CVItemViewModelImpl) -> Bool { false }
func didTapReactions(
reactionState: InteractionReactionState,
message: TSMessage,
) {}
func didTapTruncatedTextMessage(_ itemViewModel: CVItemViewModelImpl) {}
func didTapShowEditHistory(_ itemViewModel: CVItemViewModelImpl) {}
var hasPendingMessageRequest: Bool { false }
func didTapUndownloadableMedia() {}
func didTapUndownloadableGenericFile() {}
func didTapUndownloadableOversizeText() {}
func didTapUndownloadableAudio() {}
func didTapUndownloadableSticker() {}
func didTapBrokenVideo() {}
func didTapBodyMedia(
itemViewModel: CVItemViewModelImpl,
attachmentStream: ReferencedAttachmentStream,
imageView: UIView,
) {}
func didTapGenericAttachment(
_ attachment: CVComponentGenericAttachment,
) -> CVAttachmentTapAction { .default }
func didTapQuotedReply(_ quotedReply: QuotedReplyModel) {}
func didTapLinkPreview(_ linkPreview: OWSLinkPreview) {}
func didTapContactShare(_ contactShare: ContactShareViewModel) {}
func didTapSendMessage(to phoneNumbers: [String]) {}
func didTapSendInvite(toContactShare contactShare: ContactShareViewModel) {}
func didTapAddToContacts(contactShare: ContactShareViewModel) {}
func didTapStickerPack(_ stickerPackInfo: StickerPackInfo) {}
func didTapGroupInviteLink(url: URL) {}
func didTapProxyLink(url: URL) {}
func didTapShowMessageDetail(_ itemViewModel: CVItemViewModelImpl) {}
func willWrapGift(_ messageUniqueId: String) -> Bool { false }
func willShakeGift(_ messageUniqueId: String) -> Bool { false }
func willUnwrapGift(_ itemViewModel: CVItemViewModelImpl) {}
func didTapGiftBadge(
_ itemViewModel: CVItemViewModelImpl,
profileBadge: ProfileBadge,
isExpired: Bool,
isRedeemed: Bool,
) {}
func prepareMessageDetailForInteractivePresentation(_ itemViewModel: CVItemViewModelImpl) {}
func beginCellAnimation(maximumDuration: TimeInterval) -> EndCellAnimation {
return {}
}
var wallpaperBlurProvider: WallpaperBlurProvider? { nil }
var selectionState: CVSelectionState { CVSelectionState() }
func didTapPreviouslyVerifiedIdentityChange(_ address: SignalServiceAddress) {}
func didTapUnverifiedIdentityChange(_ address: SignalServiceAddress) {}
func didTapCorruptedMessage(_ message: TSErrorMessage) {}
func didTapSessionRefreshMessage(_ message: TSErrorMessage) {}
func didTapResendGroupUpdateForErrorMessage(_ errorMessage: TSErrorMessage) {}
func didTapShowFingerprint(_ address: SignalServiceAddress) {}
func didTapIndividualCall(_ call: TSCall) {}
func didTapLearnMoreMissedCallFromBlockedContact(_ call: TSCall) {}
func didTapGroupCall() {}
func didTapPendingOutgoingMessage(_ message: TSOutgoingMessage) {}
func didTapFailedOutgoingMessage(_ message: TSOutgoingMessage) {}
func didTapGroupMigrationLearnMore() {}
func didTapGroupInviteLinkPromotion(groupModel: TSGroupModel) {}
func didTapViewGroupDescription(newGroupDescription: String) {}
func didTapNameEducation(type: SafetyTipsType) {}
func didTapShowConversationSettings() {}
func didTapShowConversationSettingsAndShowMemberRequests() {}
func didTapBlockRequest(
groupModel: TSGroupModelV2,
requesterName: String,
requesterAci: Aci,
) {}
func didTapShowUpgradeAppUI() {}
func didTapUpdateSystemContact(
_ address: SignalServiceAddress,
newNameComponents: PersonNameComponents,
) {}
func didTapPhoneNumberChange(aci: Aci, phoneNumberOld: String, phoneNumberNew: String) {}
func didTapViewOnceAttachment(_ interaction: TSInteraction) {}
func didTapViewOnceExpired(_ interaction: TSInteraction) {}
func didTapContactName(thread: TSContactThread) {}
func didTapUnknownThreadWarningGroup() {}
func didTapUnknownThreadWarningContact() {}
func didTapDeliveryIssueWarning(_ message: TSErrorMessage) {}
func didTapActivatePayments() {}
func didTapSendPayment() {}
func didTapThreadMergeLearnMore(phoneNumber: String) {}
func didTapReportSpamLearnMore() {}
func didTapMessageRequestAcceptedOptions() {}
func didTapJoinCallLinkCall(callLink: CallLink) {}
func didTapViewVotes(poll: OWSPoll) {}
func didTapViewPoll(pollInteractionUniqueId: String) {}
func didTapVoteOnPoll(poll: OWSPoll, optionIndex: UInt32, isUnvote: Bool) {}
func didTapViewPinnedMessage(pinnedMessageUniqueId: String) {}
}

View File

@ -896,8 +896,9 @@ extension ConversationSettingsViewController {
"CONVERSATION_SETTINGS_MEMBER_TAG",
comment: "Label for 'member label' action in conversation settings view.",
),
actionBlock: {
print("Unimplemented!")
actionBlock: { [weak self] in
let memberLabelViewController = MemberLabelViewController()
self?.present(OWSNavigationController(rootViewController: memberLabelViewController), animated: true)
},
),
)

View File

@ -4,7 +4,7 @@
//
import LibSignalClient
import SignalServiceKit
public import SignalServiceKit
import SignalUI
protocol MockConversationDelegate: AnyObject {
@ -215,10 +215,23 @@ private class MockThread: TSContactThread {
}
}
public class MockGroupThread: TSGroupThread {
override public var shouldBeSaved: Bool {
return false
}
override public var uniqueId: String { "MockGroupThread" }
override public func anyWillInsert(with transaction: DBWriteTransaction) {
// no - op
owsFailDebug("shouldn't save mock thread")
}
}
// MARK: -
private class MockIncomingMessage: TSIncomingMessage {
init(messageBody: ValidatedInlineMessageBody, thread: MockThread) {
public class MockIncomingMessage: TSIncomingMessage {
fileprivate init(messageBody: ValidatedInlineMessageBody, thread: MockThread) {
let builder: TSIncomingMessageBuilder = .withDefaultValues(
thread: thread,
authorAci: thread.contactAddress.aci!,
@ -227,18 +240,27 @@ private class MockIncomingMessage: TSIncomingMessage {
super.init(incomingMessageWithBuilder: builder)
}
override var shouldBeSaved: Bool {
init(messageBody: ValidatedInlineMessageBody, thread: MockGroupThread, authorAci: Aci) {
let builder: TSIncomingMessageBuilder = .withDefaultValues(
thread: thread,
authorAci: authorAci,
messageBody: messageBody,
)
super.init(incomingMessageWithBuilder: builder)
}
override public var shouldBeSaved: Bool {
return false
}
override func anyWillInsert(with transaction: DBWriteTransaction) {
override public func anyWillInsert(with transaction: DBWriteTransaction) {
owsFailDebug("shouldn't save mock message")
}
}
// MARK: -
private class MockOutgoingMessage: TSOutgoingMessage {
public class MockOutgoingMessage: TSOutgoingMessage {
init(messageBody: ValidatedInlineMessageBody, thread: TSThread, transaction: DBReadTransaction) {
let builder: TSOutgoingMessageBuilder = .withDefaultValues(thread: thread, messageBody: messageBody)
super.init(
@ -254,22 +276,22 @@ private class MockOutgoingMessage: TSOutgoingMessage {
fatalError("init(coder:) has not been implemented")
}
override var shouldBeSaved: Bool {
override public var shouldBeSaved: Bool {
return false
}
override func anyWillInsert(with transaction: DBWriteTransaction) {
override public func anyWillInsert(with transaction: DBWriteTransaction) {
owsFailDebug("shouldn't save mock message")
}
override var messageState: TSOutgoingMessageState { .sent }
override public var messageState: TSOutgoingMessageState { .sent }
override func readRecipientAddresses() -> [SignalServiceAddress] {
override public func readRecipientAddresses() -> [SignalServiceAddress] {
// makes message appear as read
return [MockConversationView.mockAddress]
}
override func recipientState(for recipientAddress: SignalServiceAddress) -> TSOutgoingMessageRecipientState? {
override public func recipientState(for recipientAddress: SignalServiceAddress) -> TSOutgoingMessageRecipientState? {
return TSOutgoingMessageRecipientState(
status: .read,
statusTimestamp: Date().ows_millisecondsSince1970,

View File

@ -4987,6 +4987,21 @@
/* Label for an action to add a member label */
"MEMBER_LABEL_ADD" = "Add a Member Label";
/* Heading shown above the preview of a message bubble with the edited member label. */
"MEMBER_LABEL_PREVIEW_HEADING" = "Preview";
/* Text shown in the preview message bubble when a user is editing their member label. */
"MEMBER_LABEL_VIEW_MESSAGE_PREVIEW_TEXT" = "Hello!";
/* Placeholder text in text field where user can edit their member label. */
"MEMBER_LABEL_VIEW_PLACEHOLDER_TEXT" = "Add your label";
/* Subtitle for a view where users can edit and preview their member label. */
"MEMBER_LABEL_VIEW_SUBTITLE" = "Set a member label to describe yourself or your role in this group. Member labels are only visible within this group.";
/* Title for a view where users can edit and preview their member label. */
"MEMBER_LABEL_VIEW_TITLE" = "Member Label";
/* Action sheet button title */
"MESSAGE_ACTION_COPY_TEXT" = "Copy Message Text";

View File

@ -9,9 +9,10 @@ extension TSMessage {
/// Dangerous to use for uninserted messages; exposed only in the Signal target because most rendering
/// uses already-inserted messages, obviating the concern.
/// There are some exceptions to this, such as mock messages we insert for purely UI previewing purposes.
public func hasRenderableContent(tx: DBReadTransaction) -> Bool {
guard let rowId = self.sqliteRowId else {
owsFailDebug("Checking renderable content for uninserted message!")
owsAssertDebug(((self as? MockIncomingMessage) != nil) || ((self as? MockOutgoingMessage) != nil), "Checking renderable content for uninserted message")
return TSMessageBuilder.hasRenderableContent(
hasNonemptyBody: body?.nilIfEmpty != nil,
hasBodyAttachmentsOrOversizeText: false,

View File

@ -71,7 +71,7 @@ public class ThreadAssociatedData: NSObject, Codable, FetchableRecord, Persistab
) -> ThreadAssociatedData {
DependenciesBridge.shared.threadAssociatedDataStore.fetchOrDefault(
for: threadUniqueId,
ignoreMissing: ignoreMissing || CurrentAppContext().isRunningTests || threadUniqueId == "MockThread",
ignoreMissing: ignoreMissing || CurrentAppContext().isRunningTests || threadUniqueId == "MockThread" || threadUniqueId == "MockGroupThread",
tx: transaction,
)
}

View File

@ -111,7 +111,7 @@ public class ThreadViewModel: NSObject {
if let threadId = thread.grdbId?.int64Value {
pinnedMessages = DependenciesBridge.shared.pinnedMessageManager.fetchPinnedMessagesForThread(threadId: threadId, tx: transaction)
} else {
owsFailDebug("missing thread Id")
owsAssertDebug(thread.uniqueId == "MockThread" || thread.uniqueId == "MockGroupThread", "missing thread Id")
pinnedMessages = []
}
}