Fix: hide repeated avatar and username for grouped messages#82
Fix: hide repeated avatar and username for grouped messages#82beezly wants to merge 3 commits intoviktorstrate:mainfrom
Conversation
|
Nice find! I think the only good fix for this is going to be to float a popover. I'll work on it. Marking this as a draft for now. |
NSHostingView inside NSTableView with usesAutomaticRowHeights enters an infinite layout loop: layout() flushes SwiftUI transactions, which invalidate constraints, which re-enter layout. AppKit detects this and crashes with NSGenericException. Replace the entire auto-sizing mechanism with SelfSizingHostingView: - sizingOptions = [] prevents the hosting view from participating in Auto Layout constraint solving. - invalidateIntrinsicContentSize() is overridden to NOT call super (which would re-enter the constraint system) but instead schedule a coalesced async height update via DispatchQueue.main.async. - measureHeight() uses a temporary NSHostingController.sizeThatFits() to properly measure content at the cell width, including text wrapping. - heightOfRow returns cached heights (default 60px). noteHeightOfRows is called with animation duration 0 to avoid visible row resizing. Also removes the old measurementHostingView and handleTableResize.
…same sender Only show the profile header (avatar + username) on the first message in a consecutive group from the same sender. Timestamps remain visible on every message.
51b7298 to
0a392fa
Compare
Floating panel with quick reactions (👍🎉❤️), reply, reply in thread, and pin actions. Panel is dismissed when scrolling or resizing, and hidden when the row top is outside the visible timeline area.
0a392fa to
d239d3d
Compare
|
Rebased onto #85. Hover actions are now a floating NSPanel (HoverActionsPanel) instead of the inline ZStack |
viktorstrate
left a comment
There was a problem hiding this comment.
I have left some comments that are specific to this PR and not related to #85.
Generally I like this approach and the implementation generally feels solid. I mostly just want to get rid of the timers.
| public var sendReplyTo: MatrixRustSDK.EventTimelineItem? { | ||
| get { _sendReplyTo } | ||
| set { | ||
| let id = newValue?.eventOrTransactionId.id ?? "nil" | ||
| let msg = "sendReplyTo changed to \(id)" | ||
| if newValue == nil && _sendReplyTo != nil { | ||
| let stack = Thread.callStackSymbols.prefix(15).joined(separator: "\n ") | ||
| Self.debugLog("\(msg) — CLEARED\n \(stack)") | ||
| } else { | ||
| Self.debugLog(msg) | ||
| } | ||
| _sendReplyTo = newValue | ||
| } | ||
| } | ||
| private var _sendReplyTo: MatrixRustSDK.EventTimelineItem? |
There was a problem hiding this comment.
You can use willSet to simplify this :)
| .stroke(Color(NSColor.separatorColor), lineWidth: 1) | ||
| .shadow(color: .black.opacity(0.1), radius: 4) |
There was a problem hiding this comment.
This shadow gets clipped by the NSPanel. I think we can remove this shadow and enable hasShadow on the NSPanel.
Also the stroke is clipped, but we can fix that by adding a .padding(1) modifier after the background modifier.
| // Delay hiding so mouse can move from row to panel | ||
| hideTimer = Timer.scheduledTimer(withTimeInterval: 0.15, repeats: false) { [weak self] _ in | ||
| guard let self else { return } | ||
| if !self.hoverPanel.isMouseInside { | ||
| self.dismissHoverPanel() | ||
| } | ||
| } |
There was a problem hiding this comment.
I think we can find a solution to this problem that doesn't require a timer hack. This solution doesn't feel responsive since the hover effect activates and deactivates some time after the mouse enters the area.
If you can not make it work without a timer, I can have a crack at it if you'd like?


Summary
When multiple consecutive messages are from the same sender, the avatar and username are now only shown on the first message in the group. Timestamps remain visible on every message.
Before
After
Changes
shouldIncludeProfileHeader(at:)helper toTimelineViewControllerthat checks whether the previous visible item is a message from the same senderTimelineItemRowViewnow accepts anincludeProfileHeaderparameter (defaults totrue)