Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,22 @@ class PaddedTextField: CCTextField {

override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
DispatchQueue.main.async {
self.setupPaddedCell()
}
// Set up synchronously so that the PaddedTextFieldCell (with its horizontal
// insets) is installed before Auto Layout's first intrinsicContentSize call.
// Async dispatch caused a one-frame race where self.cell was still a plain
// NSTextFieldCell with no insets, producing an under-estimated height that
// clipped text on the first render pass.
setupPaddedCell()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
DispatchQueue.main.async {
self.setupPaddedCell()
}
setupPaddedCell()
}

override func awakeFromNib() {
super.awakeFromNib()
DispatchQueue.main.async {
self.setupPaddedCell()
}
setupPaddedCell()
}

private func setupPaddedCell() {
Expand Down Expand Up @@ -139,10 +138,17 @@ class PaddedTextField: CCTextField {
size.height = ceil(height) + vPad
return size
}
// Fallback when bounds aren't established yet
// Fallback: bounds haven't been established yet (zero-width first pass).
// Rather than committing a magic overestimate (+40 was undocumented), trigger
// a deferred re-measurement once the view has real bounds, and return a
// minimal valid size for now. The deferred invalidation ensures Auto Layout
// re-runs intrinsicContentSize as soon as the view's bounds are known.
DispatchQueue.main.async { [weak self] in
self?.invalidateIntrinsicContentSize()
}
var size = super.intrinsicContentSize
size.width += hPad
size.height += vPad + 40
size.height += vPad
return size
}

Expand Down
35 changes: 22 additions & 13 deletions com.stakwork.sphinx.desktop/Helpers/ChatHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -494,68 +494,77 @@ class ChatHelper {
) -> CGFloat {
var mutableTableCellState = tableCellState
var textHeight: CGFloat = 0.0


// Use direction-aware outer margin so the measurement width matches
// the actual text-drawing width at render time.
// Received: 16(leading) + 40(avatar) + 4(spacer) + 7(trailing spacer) + 16(trailing) = 83
// Outgoing: 16(leading) + 0(no avatar/spacer) + 7(trailing spacer) + 16(trailing) = 39
let isOutgoing = mutableTableCellState.bubble?.direction.isOutgoing() == true
let outerMargins = isOutgoing
? CommonNewMessageCollectionViewitem.kTextLabelMarginsOutgoing
: CommonNewMessageCollectionViewitem.kTextLabelMargins

var maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumLabelBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)

if let _ = mutableTableCellState.directPayment {
if let _ = mutableTableCellState.messageMedia {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumDirectPaymentWithMediaBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = mutableTableCellState.messageContent {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumDirectPaymentWithTextBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumDirectPaymentBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
}
} else if let _ = mutableTableCellState.messageMedia {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumMediaBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = mutableTableCellState.genericFile {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumFileBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = mutableTableCellState.audio {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumAudioBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = linkData {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumLinksBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = tribeData {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumLinksBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = mutableTableCellState.contactLink {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumLinksBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = mutableTableCellState.podcastComment {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumPodcastAudioBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
} else if let _ = mutableTableCellState.messageContent, let _ = mutableTableCellState.paidContent {
maxWidth = min(
CommonNewMessageCollectionViewitem.kMaximumPaidTextViewBubbleWidth,
collectionViewWidth - CommonNewMessageCollectionViewitem.kTextLabelMargins
collectionViewWidth - outerMargins
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ class CommonNewMessageCollectionViewitem : NSCollectionViewItem {
static let kMaximumPaidTextViewBubbleWidth: CGFloat = 400
static let kMaximumInvoiceBubbleWidth: CGFloat = 300
static let kMaximumThreadBubbleWidth: CGFloat = 400
/// Outer horizontal margin consumed by the layout for **received** messages:
/// 16 (outer leading) + 40 (avatar container) + 4 (avatar spacer) + 7 (trailing spacer) + 16 (outer trailing) = 83
static let kTextLabelMargins: CGFloat = 83

/// Outer horizontal margin consumed by the layout for **outgoing** messages:
/// 16 (outer leading) + 0 (no avatar/spacer) + 7 (trailing spacer) + 16 (outer trailing) = 39
/// Using the received margin (83) for outgoing over-estimates the horizontal space consumed,
/// which narrows the measurement width and causes height over-estimation (not clipping),
/// but using the accurate value ensures heights are correct for both directions.
static let kTextLabelMarginsOutgoing: CGFloat = 39

static let kHighlightedTextVerticalExtraPadding: CGFloat = 12

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,20 @@ class NewOnlyTextMessageCollectionViewitem: CommonNewMessageCollectionViewitem,
)
configureWith(bubble: bubble)

/// Set bubble width programmatically to match the pre-calculation in getTextMessageHeightFor.
/// The XIB has a fixed 500pt equality constraint on NNK-2K-vda (the bubble container),
/// which causes Auto Layout conflicts when the collection view is narrower (e.g. thread panel).
/// Clamping to the same maxBubbleWidth used during height pre-calculation ensures the
/// render-time bubble width equals the measured width, preventing text clipping.
let outerMargins = bubble.direction.isOutgoing()
? CommonNewMessageCollectionViewitem.kTextLabelMarginsOutgoing
: CommonNewMessageCollectionViewitem.kTextLabelMargins
let maxBubbleWidth = min(
CommonNewMessageCollectionViewitem.kMaximumLabelBubbleWidth,
collectionViewWidth - outerMargins
)
bubbleWidthConstraint.constant = max(maxBubbleWidth, 0)

///Invoice Lines
configureWith(invoiceLines: mutableMessageCellState.invoicesLines)
}
Expand Down
Loading