Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
bc6b084
wip: dev settings to treat all users a session pro
Aug 13, 2025
2d7554d
Merge branch 'user-profile-modal' into session-pro-badge
Aug 13, 2025
3250738
pro badge in conversation screen
Aug 14, 2025
84ec23f
pro badges in conversation list
Aug 14, 2025
eb178ef
fix the cancel button position in quote draft view
Aug 14, 2025
1340733
feat: label with pro badge and refactor
Aug 15, 2025
3c6e04e
feat: pro badge on App title
Aug 18, 2025
122a1a7
feat: badges in Message info screen
Aug 19, 2025
695dcb6
Merge branch 'dev' into session-pro-badge
Aug 20, 2025
c595c54
feat: contact list with pro badge
Aug 20, 2025
4b5c1f0
wip: pro badges in settings screen
Aug 20, 2025
6696c84
feat: pro badges in settings screen
Aug 20, 2025
f7a720b
wip: conversation setting screen with pro badge
Aug 21, 2025
69cdf8f
feat: profile picture and qrcode in ucs
Aug 22, 2025
86b6eb4
wip: Pro CTA Modal for group activated
Aug 22, 2025
c135636
[Automated] Update translations from Crowdin
Bilb Aug 25, 2025
de7c0b0
feat: group activated pro modal
Aug 25, 2025
4be55d3
Merge branch 'feature/update-crowdin-translations' of https://github.…
Aug 25, 2025
1f979a7
feat: user profile modal in message info screen
Aug 25, 2025
e8d867a
feat: open lightbox for qrcode in ucs
Aug 25, 2025
18920ae
fix: read more for message bubble cells with link preview and other m…
Aug 25, 2025
b6c3a36
[Automated] Update translations from Crowdin
ThomasSession Aug 25, 2025
40aacf4
clean up
Aug 25, 2025
90c07d3
Merge branch 'feature/update-crowdin-translations' of https://github.…
Aug 26, 2025
96175cb
fix unit test
Aug 26, 2025
457f4f9
fix message bubble in message info screen
Aug 26, 2025
97fe404
clean
Aug 26, 2025
fb25784
Merge branch 'dev' into session-pro-badge
Aug 26, 2025
12bdef7
Merge branch 'user-profile-modal' into session-pro-badge
Aug 27, 2025
c3654e0
Merge branch 'user-profile-modal' into session-pro-badge
Sep 8, 2025
3fedbfa
Merge branch 'user-profile-modal' into session-pro-badge
Sep 11, 2025
16bf625
Merge branch 'user-profile-modal' into session-pro-badge
Sep 12, 2025
345ab9b
fix merge
Sep 12, 2025
315d60a
Merge branch 'user-profile-modal' into session-pro-badge
mpretty-cyro Sep 19, 2025
5c12f47
Fixed some merge issues
mpretty-cyro Sep 19, 2025
a64fbc4
Fixed an issue with the dev setting not updating the UI
mpretty-cyro Sep 19, 2025
87f2016
Merge branch 'user-profile-modal' into session-pro-badge
mpretty-cyro Sep 19, 2025
2955d9a
Merge branch 'user-profile-modal' into session-pro-badge
Sep 25, 2025
741c5b2
Merge branch 'user-profile-modal' into session-pro-badge
Oct 1, 2025
959867d
Merge branch 'user-profile-modal' into session-pro-badge
Oct 1, 2025
1f2829a
Merge branch 'user-profile-modal' into session-pro-badge
Oct 1, 2025
57e779c
fix some minor ui issues
Oct 1, 2025
270a5dd
fix: improve `isAnimated`
Oct 1, 2025
09deb0d
feat: add cache for pro badge images and use image for @YOU
Oct 3, 2025
0937356
fix message info screen
Oct 3, 2025
eb45a02
clean up
Oct 3, 2025
7eda203
refactor on session pro badge image cache
Oct 6, 2025
1cc029d
feat: cache for @You image rendering
Oct 6, 2025
07c75d8
fix pro badge or mention in attributed string won't change the color …
Oct 6, 2025
b2c5f88
Merge remote-tracking branch 'upstream/dev' into session-pro-badge
mpretty-cyro Oct 15, 2025
6e593ed
Few very minor tweaks
mpretty-cyro Oct 15, 2025
c26ab50
Fixing CI complaints
mpretty-cyro Oct 15, 2025
1c72f31
fix: plus icon when display picture is null
Oct 16, 2025
5e827ca
fix: update icons to lucide in message info screens
Oct 16, 2025
35898b9
fix: remove pro badge in note-to-self thread settings screen
Oct 16, 2025
002799c
fix: missing pro badge at the end of strings in pro cta modal
Oct 17, 2025
6e82a5b
fix: user profile modal doesn't show "You"
Oct 17, 2025
6fbbe0e
fix: session pro badge for pro settings cell in light mode in setting…
Oct 17, 2025
ca6c352
fix: contact name bottom padding in conversation settings screen
Oct 17, 2025
7abde5a
fix: group avatar was not expandable
Oct 17, 2025
c084157
fix: close button alignment issue on quote view
Oct 17, 2025
c271431
fix: group control messages deformatted
Oct 19, 2025
5dbc58f
fix: confirmation modal save button should be disabled if there is an…
Oct 19, 2025
ec7cf93
fix: pro badge not showing in share extension
Oct 19, 2025
97b63a8
fix: Session Pro wordmark in the app heading should not be flipped in…
Oct 19, 2025
a0e1c14
fix: incorrectly showing long message pro feature in message info screen
Oct 20, 2025
5872478
fix: incorrect pro badge position for community members
Oct 20, 2025
0940dd2
fix: pro badge in quote view
Oct 20, 2025
f16107f
fix: message author UI in message info screen
Oct 20, 2025
9082120
fix: message info screen failed to send status overlaps with message …
Oct 20, 2025
edbc7b1
fix: blinded id incorrectly shown in quote view
Oct 20, 2025
364aefb
fix: qr code generation
Oct 20, 2025
29a4748
fix: light box qr code color
Oct 20, 2025
827a8f3
fix: pro cta ui issues
Oct 21, 2025
560d83e
fix: Pro badge is cut off screen with a long name
Oct 21, 2025
12dd293
fix: pro badge alignment with inline text
Oct 21, 2025
ed61e7f
feat: dev settings for pro message features
Oct 21, 2025
95b0759
fix: message status padding to message bubble in message info screen
Oct 22, 2025
4f2e990
fix: minor QA issues
Oct 24, 2025
20e5594
Merge branch 'dev' into session-pro-badge
Nov 3, 2025
2572ed1
fix: UCS UI & Pro badge tapping issue
Nov 3, 2025
edae077
fix: message info screen tweak
Nov 3, 2025
f1fc05a
Merge branch 'fix/update-string' of https://github.com/mpretty-cyro/s…
Nov 3, 2025
7cb734b
fix: style tags shouldn't show in home screen message cells
Nov 6, 2025
4f85beb
Merge branch 'dev' into session-pro-badge
Nov 6, 2025
c1ebd36
fix: UPM in Message Info Screen
Nov 6, 2025
f3a4a66
clean
Nov 6, 2025
56117d0
fix: Pro badges in Session heading did not respond to dev settings ch…
Nov 6, 2025
c5942a2
fix: remove copy account id action in message info screen
Nov 6, 2025
9f3bebb
fix: Context Menu Screen for RTL
Nov 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 42 additions & 17 deletions Session.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion Session/Closed Groups/EditGroupViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,11 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Observa
font: .title,
accessibility: Accessibility(
identifier: "Contact"
)
),
trailingImage: {
guard (dependencies.mutate(cache: .libSession) { $0.validateProProof(for: memberInfo.profile) }) else { return nil }
return ("ProBadge", { [dependencies] in SessionProBadge(size: .small).toImage(using: dependencies) })
}()
),
subtitle: (!isUpdatedGroup ? nil : SessionCell.TextInfo(
memberInfo.value.statusDescription,
Expand Down
19 changes: 10 additions & 9 deletions Session/Conversations/Context Menu/ContextMenuVC+Action.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ extension ContextMenuVC {

static func retry(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(systemName: "arrow.triangle.2.circlepath"),
icon: Lucide.image(icon: .repeat2, size: 24),
title: (cellViewModel.state == .failedToSync ?
"resync".localized() :
"resend".localized()
Expand All @@ -77,25 +77,25 @@ extension ContextMenuVC {

static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(named: "ic_reply"),
icon: Dependencies.isRTL ? Lucide.image(icon: .reply, size: 24)?.flippedHorizontally() : Lucide.image(icon: .reply, size: 24),
title: "reply".localized(),
shouldDismissInfoScreen: true,
accessibilityLabel: "Reply to message"
) { completion in delegate?.reply(cellViewModel, completion: completion) }
}

static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, forMessageInfoScreen: Bool) -> Action {
return Action(
icon: UIImage(named: "ic_copy"),
title: "copy".localized(),
icon: Lucide.image(icon: .copy, size: 24),
title: forMessageInfoScreen ? "messageCopy".localized() : "copy".localized(),
feedback: "copied".localized(),
accessibilityLabel: "Copy text"
) { completion in delegate?.copy(cellViewModel, completion: completion) }
}

static func copySessionID(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(named: "ic_copy"),
icon: Lucide.image(icon: .copy, size: 24),
title: "accountIDCopy".localized(),
feedback: "copied".localized(),
accessibilityLabel: "Copy Session ID"
Expand All @@ -118,7 +118,7 @@ extension ContextMenuVC {

static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(named: "ic_download"),
icon: Lucide.image(icon: .arrowDownToLine, size: 24),
title: "save".localized(),
feedback: "saved".localized(),
accessibilityLabel: "Save attachment"
Expand Down Expand Up @@ -251,7 +251,8 @@ extension ContextMenuVC {
}()
let canCopySessionId: Bool = (
cellViewModel.variant == .standardIncoming &&
cellViewModel.threadVariant != .community
cellViewModel.threadVariant != .community &&
!forMessageInfoScreen
)
let canDelete: Bool = (MessageViewModel.DeletionBehaviours.deletionActions(
for: [cellViewModel],
Expand Down Expand Up @@ -291,7 +292,7 @@ extension ContextMenuVC {
let generatedActions: [Action] = [
(canRetry ? Action.retry(cellViewModel, delegate) : nil),
(viewModelCanReply(cellViewModel, using: dependencies) ? Action.reply(cellViewModel, delegate) : nil),
(canCopy ? Action.copy(cellViewModel, delegate) : nil),
(canCopy ? Action.copy(cellViewModel, delegate, forMessageInfoScreen: forMessageInfoScreen) : nil),
(canSave ? Action.save(cellViewModel, delegate) : nil),
(canCopySessionId ? Action.copySessionID(cellViewModel, delegate) : nil),
(canDelete ? Action.delete(cellViewModel, delegate) : nil),
Expand Down
46 changes: 26 additions & 20 deletions Session/Conversations/Context Menu/ContextMenuVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ final class ContextMenuVC: UIViewController {
emojiBarBackgroundView.pin(to: emojiBar)

emojiBar.addSubview(emojiPlusButton)
emojiPlusButton.pin(.right, to: .right, of: emojiBar, withInset: -Values.smallSpacing)
emojiPlusButton.pin(.trailing, to: .trailing, of: emojiBar, withInset: -Values.smallSpacing)
emojiPlusButton.center(.vertical, in: emojiBar)

let emojiBarStackView = UIStackView(
Expand All @@ -156,8 +156,8 @@ final class ContextMenuVC: UIViewController {
emojiBarStackView.layoutMargins = UIEdgeInsets(top: 0, left: Values.smallSpacing, bottom: 0, right: Values.smallSpacing)
emojiBarStackView.isLayoutMarginsRelativeArrangement = true
emojiBar.addSubview(emojiBarStackView)
emojiBarStackView.pin([ UIView.HorizontalEdge.left, UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: emojiBar)
emojiBarStackView.pin(.right, to: .left, of: emojiPlusButton)
emojiBarStackView.pin([ UIView.HorizontalEdge.leading, UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: emojiBar)
emojiBarStackView.pin(.trailing, to: .leading, of: emojiPlusButton)

// Hide the emoji bar if we have no emoji actions
emojiBar.isHidden = emojiBarStackView.arrangedSubviews.isEmpty
Expand Down Expand Up @@ -188,25 +188,25 @@ final class ContextMenuVC: UIViewController {
timestampLabel.center(.vertical, in: snapshot)

if cellViewModel.variant == .standardOutgoing {
timestampLabel.pin(.right, to: .left, of: snapshot, withInset: -Values.smallSpacing)
timestampLabel.pin(.trailing, to: .leading, of: snapshot, withInset: -Values.smallSpacing)
}
else {
timestampLabel.pin(.left, to: .right, of: snapshot, withInset: Values.smallSpacing)
timestampLabel.pin(.leading, to: .trailing, of: snapshot, withInset: Values.smallSpacing)
}

view.addSubview(fallbackTimestampLabel)
fallbackTimestampLabel.pin(.top, to: .top, of: menuView)
fallbackTimestampLabel.set(.height, to: ContextMenuVC.actionViewHeight)

if cellViewModel.variant == .standardOutgoing {
fallbackTimestampLabel.textAlignment = .right
fallbackTimestampLabel.pin(.right, to: .left, of: menuView, withInset: -Values.mediumSpacing)
fallbackTimestampLabel.pin(.left, to: .left, of: view, withInset: Values.mediumSpacing)
fallbackTimestampLabel.textAlignment = Dependencies.isRTL ? .left : .right
fallbackTimestampLabel.pin(.trailing, to: .leading, of: menuView, withInset: -Values.mediumSpacing)
fallbackTimestampLabel.pin(.leading, to: .leading, of: view, withInset: Values.mediumSpacing)
}
else {
fallbackTimestampLabel.textAlignment = .left
fallbackTimestampLabel.pin(.left, to: .right, of: menuView, withInset: Values.mediumSpacing)
fallbackTimestampLabel.pin(.right, to: .right, of: view, withInset: -Values.mediumSpacing)
fallbackTimestampLabel.textAlignment = Dependencies.isRTL ? .right : .left
fallbackTimestampLabel.pin(.leading, to: .trailing, of: menuView, withInset: Values.mediumSpacing)
fallbackTimestampLabel.pin(.trailing, to: .trailing, of: view, withInset: -Values.mediumSpacing)
}

// Constrains
Expand All @@ -219,9 +219,15 @@ final class ContextMenuVC: UIViewController {
self.timestampLabel.isHidden = {
switch cellViewModel.variant {
case .standardOutgoing:
if Dependencies.isRTL {
return ((self.targetFrame.maxX + timestampSize.width + Values.mediumSpacing) > UIScreen.main.bounds.width)
}
return ((self.targetFrame.minX - timestampSize.width - Values.mediumSpacing) < 0)

default:
if Dependencies.isRTL {
return ((self.targetFrame.minX - timestampSize.width - Values.mediumSpacing) < 0)
}
return ((self.targetFrame.maxX + timestampSize.width + Values.mediumSpacing) > UIScreen.main.bounds.width)
}
}()
Expand All @@ -234,15 +240,18 @@ final class ContextMenuVC: UIViewController {

switch cellViewModel.variant {
case .standardOutgoing, .standardOutgoingDeleted, .standardOutgoingDeletedLocally:
menuView.pin(.right, to: .right, of: view, withInset: -(UIScreen.main.bounds.width - targetFrame.maxX))
emojiBar.pin(.right, to: .right, of: view, withInset: -(UIScreen.main.bounds.width - targetFrame.maxX))
let inset: CGFloat = Dependencies.isRTL ? -targetFrame.minX : -(UIScreen.main.bounds.width - targetFrame.maxX)
menuView.pin(.trailing, to: .trailing, of: view, withInset: inset)
emojiBar.pin(.trailing, to: .trailing, of: view, withInset: inset)

case .standardIncoming, .standardIncomingDeleted, .standardIncomingDeletedLocally:
menuView.pin(.left, to: .left, of: view, withInset: targetFrame.minX)
emojiBar.pin(.left, to: .left, of: view, withInset: targetFrame.minX)
let inset: CGFloat = Dependencies.isRTL ? (UIScreen.main.bounds.width - targetFrame.maxX) : targetFrame.minX
menuView.pin(.leading, to: .leading, of: view, withInset: inset)
emojiBar.pin(.leading, to: .leading, of: view, withInset: inset)

default: // Should generally only be the 'delete' action
menuView.pin(.left, to: .left, of: view, withInset: targetFrame.minX)
let inset: CGFloat = Dependencies.isRTL ? (UIScreen.main.bounds.width - targetFrame.maxX) : targetFrame.minX
menuView.pin(.leading, to: .leading, of: view, withInset: inset)
}

// Tap gesture
Expand Down Expand Up @@ -281,10 +290,7 @@ final class ContextMenuVC: UIViewController {
initialSpringVelocity: 0.6,
options: .curveEaseInOut,
animations: { [weak self] in
self?.snapshot.pin(.left, to: .left, of: view, withInset: targetFrame.origin.x)
self?.snapshot.pin(.top, to: .top, of: view, withInset: targetFrame.origin.y)
self?.snapshot.set(.width, to: targetFrame.width)
self?.snapshot.set(.height, to: targetFrame.height)
self?.snapshot.frame = targetFrame
self?.snapshot.superview?.setNeedsLayout()
self?.snapshot.superview?.layoutIfNeeded()
},
Expand Down
28 changes: 22 additions & 6 deletions Session/Conversations/ConversationVC+Interaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ extension ConversationVC:
for: snInputView.text.trimmingCharacters(in: .whitespacesAndNewlines),
isSessionPro: viewModel.isCurrentUserSessionPro
) >= 0 else {
showModalForMessagesExceedingCharacterLimit(isSessionPro: viewModel.isCurrentUserSessionPro)
showModalForMessagesExceedingCharacterLimit(viewModel.isCurrentUserSessionPro)
return
}

Expand All @@ -663,7 +663,7 @@ extension ConversationVC:
)
}

@MainActor func showModalForMessagesExceedingCharacterLimit(isSessionPro: Bool) {
@MainActor func showModalForMessagesExceedingCharacterLimit(_ isSessionPro: Bool) {
guard !viewModel.dependencies[singleton: .sessionProState].showSessionProCTAIfNeeded(
.longerMessages,
beforePresented: { [weak self] in
Expand Down Expand Up @@ -1667,6 +1667,11 @@ extension ConversationVC:
dependencies[singleton: .storage].read { db in try? Profile.fetchOne(db, id: sessionId) }
)

let isCurrentUser: Bool = (viewModel.threadData.currentUserSessionIds?.contains(sessionId) == true)
guard !isCurrentUser else {
return ("you".localized(), "you".localized())
}

return (
(profile?.displayName(for: .contact) ?? cellViewModel.authorNameSuppressedId),
profile?.displayName(for: .contact, ignoringNickname: true)
Expand Down Expand Up @@ -2355,6 +2360,14 @@ extension ConversationVC:
let messageInfoViewController = MessageInfoViewController(
actions: actions,
messageViewModel: finalCellViewModel,
threadCanWrite: (viewModel.threadData.threadCanWrite == true),
onStartThread: { [weak self] in
self?.startThread(
with: cellViewModel.authorId,
openGroupServer: cellViewModel.threadOpenGroupServer,
openGroupPublicKey: cellViewModel.threadOpenGroupPublicKey
)
},
using: viewModel.dependencies
)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
Expand Down Expand Up @@ -2906,11 +2919,14 @@ extension ConversationVC:

func startVoiceMessageRecording() {
// Request permission if needed
Permissions.requestMicrophonePermissionIfNeeded(using: viewModel.dependencies) { [weak self] in
DispatchQueue.main.async {
self?.cancelVoiceMessageRecording()
Permissions.requestMicrophonePermissionIfNeeded(
using: viewModel.dependencies,
onNotGranted: { [weak self] in
DispatchQueue.main.async {
self?.cancelVoiceMessageRecording()
}
}
}
)

// Keep screen on
UIApplication.shared.isIdleTimerDisabled = false
Expand Down
4 changes: 3 additions & 1 deletion Session/Conversations/ConversationVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,8 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa
titleView.initialSetup(
with: self.viewModel.initialThreadVariant,
isNoteToSelf: self.viewModel.threadData.threadIsNoteToSelf,
isMessageRequest: (self.viewModel.threadData.threadIsMessageRequest == true)
isMessageRequest: (self.viewModel.threadData.threadIsMessageRequest == true),
isSessionPro: self.viewModel.threadData.isSessionPro(using: self.viewModel.dependencies)
)

// Constraints
Expand Down Expand Up @@ -796,6 +797,7 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa
with: updatedThreadData.displayName,
isNoteToSelf: updatedThreadData.threadIsNoteToSelf,
isMessageRequest: (updatedThreadData.threadIsMessageRequest == true),
isSessionPro: updatedThreadData.isSessionPro(using: viewModel.dependencies),
threadVariant: updatedThreadData.threadVariant,
mutedUntilTimestamp: updatedThreadData.threadMutedUntilTimestamp,
onlyNotifyForMentions: (updatedThreadData.threadOnlyNotifyForMentions == true),
Expand Down
3 changes: 2 additions & 1 deletion Session/Conversations/ConversationViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate, NavigatableStateHold
),
expiresInSeconds: threadData.disappearingMessagesConfiguration?.expiresInSeconds(),
linkPreviewUrl: linkPreviewDraft?.urlString,
isProMessage: dependencies[cache: .libSession].isSessionPro,
isProMessage: (text.defaulting(to: "").utf16.count > LibSession.CharacterLimit),
using: dependencies
)
var optimisticAttachments: [Attachment]?
Expand Down Expand Up @@ -784,6 +784,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate, NavigatableStateHold
body: interaction.body,
expiresStartedAtMs: interaction.expiresStartedAtMs,
expiresInSeconds: interaction.expiresInSeconds,
isProMessage: interaction.isProMessage,
isSenderModeratorOrAdmin: {
switch threadData.threadVariant {
case .group, .legacyGroup:
Expand Down
2 changes: 1 addition & 1 deletion Session/Conversations/Input View/InputView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
}()

private lazy var sessionProBadge: SessionProBadge = {
let result: SessionProBadge = SessionProBadge(size: .small)
let result: SessionProBadge = SessionProBadge(size: .medium)
result.isHidden = !dependencies[feature: .sessionProEnabled] || dependencies[cache: .libSession].isSessionPro

return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ final class LinkPreviewView: UIView {
}()

var bodyTappableLabel: TappableLabel?
var bodyTappableLabelHeight: CGFloat = 0

// MARK: - Initialization

Expand Down Expand Up @@ -222,18 +223,22 @@ final class LinkPreviewView: UIView {
bodyTappableLabelContainer.subviews.forEach { $0.removeFromSuperview() }

if let cellViewModel: MessageViewModel = cellViewModel {
let bodyTappableLabel = VisibleMessageCell.getBodyTappableLabel(
let (bodyTappableLabel, height) = VisibleMessageCell.getBodyTappableLabel(
for: cellViewModel,
with: maxWidth,
textColor: (bodyLabelTextColor ?? .textPrimary),
searchText: lastSearchText,
delegate: delegate,
using: dependencies
).label
)

self.bodyTappableLabel = bodyTappableLabel
self.bodyTappableLabelHeight = height
bodyTappableLabelContainer.addSubview(bodyTappableLabel)
bodyTappableLabel.pin(to: bodyTappableLabelContainer, withInset: 12)
bodyTappableLabel.pin(.leading, to: .leading, of: bodyTappableLabelContainer, withInset: 12)
bodyTappableLabel.pin(.top, to: .top, of: bodyTappableLabelContainer, withInset: 12)
bodyTappableLabel.pin(.trailing, to: .trailing, of: bodyTappableLabelContainer, withInset: -12)
bodyTappableLabel.pin(.bottom, to: .bottom, of: bodyTappableLabelContainer)
}

if state is LinkPreview.DraftState {
Expand Down
Loading