Skip to content

[LUM-833] Fix long user messages getting cut off in chat view#25579

Closed
devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
devin/1776190869-lum-833-fix-user-message-truncation
Closed

[LUM-833] Fix long user messages getting cut off in chat view#25579
devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
devin/1776190869-lum-833-fix-user-message-truncation

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Apr 14, 2026

Removes the aggressive 150pt height-based collapse (userMessageHeightWrapper) that clipped all moderate user messages to ~7-8 lines, causing normal-length messages to appear visually cut off. Moderate messages (< 3,000 chars / < 40 lines) now render at full height, while very large messages continue using the heuristic text-truncation path (1,200 chars / 24 lines preview + "Show more" button) which provides a proper expand flow without height clipping. Also updates the MessageListContentView minHeight estimate to reflect that non-collapsed messages render at full height, fixes an NSString.length vs String.count mismatch in the heuristic threshold check, and replaces the stale 260pt attachment height estimate with per-attachment height estimation.



Open with Devin

Moderate user messages (< 3,000 chars / < 40 lines) now render at full
height without any collapse wrapper. The measurement-based height cap
(userMessageHeightWrapper) clipped all user messages to 150pt (~7-8 lines),
causing normal-length messages to appear cut off.

Very large messages (> 3,000 chars or > 40 lines) continue to use the
heuristic text-truncation path (1,200 chars / 24 lines preview with
Show more button).

Also removes redundant height clipping from the heuristic collapse path
that was added in 7e98382, and updates the minHeight estimate in
MessageListContentView to reflect that non-collapsed messages render at
full height.

Closes LUM-833

Co-Authored-By: tkheyfets <timur@vellum.ai>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment thread clients/macos/vellum-assistant/Features/Chat/MessageListContentView.swift Outdated
Comment on lines 593 to 599
@ViewBuilder
private func heuristicUserMessageCollapseWrapper<Content: View>(@ViewBuilder _ content: () -> Content) -> some View {
VStack(alignment: .leading, spacing: 0) {
content()
// Clip to same height as the measurement-based collapse path
// so both produce a consistent collapsed height.
.frame(height: isUserMessageExpanded ? nil : userMessageMaxCollapsedHeight, alignment: .top)
.clipped()
.overlay(alignment: .bottom) {
if !isUserMessageExpanded {
LinearGradient(
colors: [
VColor.surfaceLift.opacity(0),
VColor.surfaceLift
],
startPoint: .init(x: 0.5, y: 0),
endPoint: .init(x: 0.5, y: 1)
)
.frame(height: 40)
.allowsHitTesting(false)
}
}
collapseToggleButton
.padding(.horizontal, VSpacing.lg)
.padding(.bottom, VSpacing.sm)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Heuristic collapse wrapper no longer clips content height — relies entirely on text truncation

The old heuristicUserMessageCollapseWrapper had .frame(height: isUserMessageExpanded ? nil : userMessageMaxCollapsedHeight) + .clipped() + gradient overlay. The new version removes all of these, relying entirely on effectiveRenderingText being set to collapsedUserMessagePreviewText (1200 chars / 24 lines + ...) at ChatBubble.swift:669-670. This means the collapsed height is now determined by the preview text's natural rendered height rather than a fixed 150pt cap. The visual result is different: no gradient fade, and the collapsed height varies based on preview text content. The "Show more" button is always visible (not gated on isCollapsible), which is correct since the wrapper is only used when shouldUseHeuristicCollapse is true. One side effect: since attachments (images, files, videos, audio) are rendered inside bubbleChrome at ChatBubble.swift:708-743, they are always displayed at full size even when the text is collapsed — the old height clipping would have hidden them if they were below the 150pt line.

(Refers to lines 593-605)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — the heuristic collapse wrapper now relies entirely on text truncation (1,200 chars / 24 lines) rather than height clipping. This is intentional: the text truncation provides a proper expand flow with "Show more" button, while the old height clipping just cut content off visually. The attachment visibility change is also intentional — attachments should be visible even when the text portion is collapsed, since they're the primary content the user shared.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17bf7de3ba

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 756 to +759
if shouldUseHeuristicCollapse {
heuristicUserMessageCollapseWrapper { chrome }
} else {
userMessageHeightWrapper { chrome }
chrome
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep attachment bubbles in active-turn height calculation

Switching non-heuristic user messages to render chrome directly means attachment messages are no longer collapsed by default, but MessageListContentView.estimatedUserHeight still assumes any attachment message is capped at 260. For large image/file previews this underestimates the real user-row height and inflates turnMinHeight, which can break the active-turn scroll behavior (extra blank space / user message no longer pinned as intended) whenever the latest user message includes attachments.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b2286e3. Removed the stale 260pt early return for attachment messages and added a per-attachment height estimate (~200pt each) to the minHeight calculation for both heuristic-collapsed and non-collapsed paths.

…achment estimate

- Use String.count instead of NSString.length for heuristic threshold
  check to match ChatBubble.shouldUseHeuristicUserCollapse (avoids
  mismatch with multi-code-unit characters like emoji)
- Remove stale 260pt early return for attachment messages; let them
  fall through to text measurement with per-attachment height estimate
- Include attachment height in both heuristic and non-heuristic paths

Co-Authored-By: tkheyfets <timur@vellum.ai>
devin-ai-integration[bot]

This comment was marked as resolved.

Differentiate by MIME type to match actual rendering heights:
- Images: grid layout (~130pt per row, adaptive columns at min 160px)
- Videos: ~200pt each (InlineVideoAttachmentView)
- Audio: ~60pt each (InlineAudioAttachmentView)
- Files: ~40pt each (file chips)

Prevents over-estimation that would push turnMinHeight to 0 and
break the 'user message pinned at top' scroll invariant.

Co-Authored-By: tkheyfets <timur@vellum.ai>
devin-ai-integration[bot]

This comment was marked as resolved.

…hresholds

Widen access on heuristicUserCollapseCharacterThreshold and
heuristicUserCollapseLineThreshold from private to internal so
MessageListContentView references the single source of truth.

Co-Authored-By: tkheyfets <timur@vellum.ai>
devin-ai-integration[bot]

This comment was marked as resolved.

Reflects three-path estimation (no user message, heuristic-collapsed,
normal), per-type attachment height, and removed 260pt cap.

Co-Authored-By: tkheyfets <timur@vellum.ai>
@github-actions
Copy link
Copy Markdown
Contributor

This PR has been inactive for 30 days. It will be closed in 7 days unless there is new activity.

@github-actions github-actions Bot added the stale label May 15, 2026
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Devin is archived and cannot be woken up. Please unarchive Devin if you want to continue using it.

@github-actions
Copy link
Copy Markdown
Contributor

Closed due to inactivity. Feel free to reopen if you'd like to continue working on this.

@github-actions github-actions Bot closed this May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant