-
Notifications
You must be signed in to change notification settings - Fork 93
perf(chat): replace maxHeight with definite height on ScrollViews inside LazyVStack cells #23611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
59406f7
dfe0823
2e28d64
1a8781f
73e5363
1ea0fe2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import SwiftUI | ||
|
|
||
| extension View { | ||
| /// Applies an adaptive height constraint to a `ScrollView` inside a `LazyVStack` cell. | ||
| /// | ||
| /// For content exceeding `lineThreshold` lines, a definite `frame(height:)` is used so | ||
| /// `LazyVStack` can skip scroll-content measurement during cell sizing. For shorter content | ||
| /// `frame(maxHeight:)` is used so the view collapses to its natural height instead of | ||
| /// rendering with blank space. | ||
| /// | ||
| /// - Parameters: | ||
| /// - text: The string whose line count determines which constraint is applied. | ||
| /// - maxHeight: The height cap applied in both branches. | ||
| /// - lineThreshold: Line count above which the fixed height is used. Default: 500. | ||
| func adaptiveScrollFrame( | ||
| for text: String, | ||
| maxHeight: CGFloat, | ||
| lineThreshold: Int = 500 | ||
| ) -> some View { | ||
| let isLong = VCodeView.countLines(in: text) > lineThreshold | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 In Prompt for agentsWas this helpful? React with 👍 or 👎 to provide feedback. |
||
| return self | ||
| .frame(height: isLong ? maxHeight : nil) | ||
| .frame(maxHeight: isLong ? nil : maxHeight) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,15 +35,6 @@ public struct ToolCallChip: View { | |
| return Int(matched[numRange]) | ||
| } | ||
|
|
||
| /// Count lines in a string without allocating an intermediate array. | ||
| static func countLines(in text: String) -> Int { | ||
| var count = 1 | ||
| for byte in text.utf8 where byte == UInt8(ascii: "\n") { | ||
| count += 1 | ||
| } | ||
| return count | ||
| } | ||
|
|
||
| /// Whether the tool produces diff-formatted output that benefits from line-level highlighting. | ||
| static func isFileEditTool(_ name: String) -> Bool { | ||
| switch name { | ||
|
|
@@ -227,25 +218,18 @@ public struct ToolCallChip: View { | |
| .foregroundStyle(VColor.contentSecondary) | ||
| } | ||
| } else { | ||
| let lineCount = cachedResultLineCount ?? Self.countLines(in: result) | ||
| let lineCount = cachedResultLineCount ?? VCodeView.countLines(in: result) | ||
| if Self.isFileEditTool(toolCall.toolName) { | ||
| VDiffView(result, maxHeight: lineCount > 500 ? 400 : nil) | ||
| } else if lineCount > 500 { | ||
| } else { | ||
| ScrollView { | ||
| Text(result) | ||
| .font(VFont.bodySmallDefault) | ||
| .foregroundStyle(VColor.contentSecondary) | ||
| .frame(maxWidth: .infinity, alignment: .leading) | ||
| .textSelection(.enabled) | ||
| } | ||
| .frame(maxHeight: 400) | ||
| } else { | ||
| Text(result) | ||
| .font(VFont.bodySmallDefault) | ||
| .foregroundStyle(VColor.contentSecondary) | ||
| .frame(maxWidth: .infinity, alignment: .leading) | ||
| .textSelection(.enabled) | ||
| .fixedSize(horizontal: false, vertical: true) | ||
| .adaptiveScrollFrame(for: result, maxHeight: 400) | ||
| } | ||
|
Comment on lines
229
to
233
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚩 Short tool results now always wrapped in ScrollView — behavioral change from plain Text The old code in (Refers to lines 224-233) Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| } | ||
| } | ||
|
|
@@ -266,7 +250,7 @@ public struct ToolCallChip: View { | |
| } | ||
| // Cache the result line count so subsequent renders are O(1). | ||
| if cachedResultLineCount == nil, let result = toolCall.result { | ||
| cachedResultLineCount = Self.countLines(in: result) | ||
| cachedResultLineCount = VCodeView.countLines(in: result) | ||
| } | ||
| // Trigger on-demand rehydration when expanding truncated content. | ||
| onRehydrate?() | ||
|
|
@@ -299,7 +283,7 @@ public struct ToolCallChip: View { | |
| } | ||
| } | ||
| if cachedResultLineCount == nil, let result = toolCall.result { | ||
| cachedResultLineCount = Self.countLines(in: result) | ||
| cachedResultLineCount = VCodeView.countLines(in: result) | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -310,7 +294,7 @@ public struct ToolCallChip: View { | |
| } | ||
| .onChange(of: toolCall.result) { | ||
| if isExpanded, let result = toolCall.result { | ||
| cachedResultLineCount = Self.countLines(in: result) | ||
| cachedResultLineCount = VCodeView.countLines(in: result) | ||
| } else { | ||
| cachedResultLineCount = nil | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Design system modifier
.adaptiveScrollFrame()missing requiredvprefixThe
clients/AGENTS.mdmandates: "All design system types — structs, enums, and view modifiers — must use the V prefix" with examples.vCard(),.vTooltip(),.vShimmer(),.vPanelBackground(). The new modifier.adaptiveScrollFrame()is defined inclients/shared/DesignSystem/Modifiers/LazyVStackScrollFrameModifier.swiftand does not follow this naming convention. It should be named.vAdaptiveScrollFrame()(or similarv-prefixed name). All three call sites (ToolCallChip.swift:232,ToolCallProgressBar.swift:253,ToolConfirmationBubble.swift:325) would need updating.Was this helpful? React with 👍 or 👎 to provide feedback.