Skip to content
Merged
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
8 changes: 3 additions & 5 deletions macos/Sources/RustCode/DebugDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -372,23 +372,21 @@ enum DebugDriver {
}
report("toolstream \(steps): row \(row) from \(Int(start)) scrolled \(Int(scrolled)), now \(Int(last)), worst stray \(Int(worst)), lost \(lost) of \(steps * 2) checks")
case "fold":
// `fold [user|reply] [up]`: opens or folds the first long message
// of that kind in view, as its Show more control does (#2303);
// `fold [user] [up]`: opens or folds the first long user message
// in view, as its Show more control does (#2303);
// with `up`, the chat is first scrolled so the message's top is
// above the view. Reports where its top and end are in the view
// before and over the next frames: opening and folding keep its
// top, folding one whose top is above keeps its end.
guard let state = ChatScrollState.current else { break }
let wantsUser = parts.count < 2 || parts[1] != "reply"
let window = NSApp.windows.first { $0.isVisible && $0.contentView != nil }
func frame(_ id: Int) -> (top: Int, end: Int)? {
guard let top = state.debugScreenTop(id), let height = state.debugFrame(id)?.height else { return nil }
return (Int(top), Int(top + height))
}
let candidates = model.transcript.items.filter { item in
switch item.content {
case .user(let text): wantsUser && MessageCollapse.mayBeLong(text)
case .assistant(let text): !wantsUser && MessageCollapse.mayBeLong(text)
case .user(let text): MessageCollapse.mayBeLong(text)
default: false
}
}
Expand Down
2 changes: 1 addition & 1 deletion macos/Sources/RustCode/TranscriptRows.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ private struct AssistantMessage: View {
var body: some View {
let parsed = parsed
VStack(alignment: .leading, spacing: 10) {
FoldingMessage(id: id, text: text, folds: MessageCollapse.folds(.assistant(text), isStreaming: isStreaming),
FoldingMessage(id: id, text: text, folds: false,
isExpanded: isExpanded) {
VStack(alignment: .leading, spacing: 10) {
ForEach(Array(parsed.blocks.enumerated()), id: \.offset) { index, block in
Expand Down
20 changes: 8 additions & 12 deletions macos/Sources/RustCodeKit/MessageCollapse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import Foundation

/// Long chat messages fold to their first lines behind Show more (#2303).
///
/// A user message or a finished reply taller than `maxLines` lines, and the
/// Show more control, shows its first `maxLines` lines under a fade. Only
/// the drawing changes: copy, the message menu, find and VoiceOver still get
/// the whole text. A reply never folds while it is written.
/// A user message taller than `maxLines` lines, and the Show more control,
/// shows its first `maxLines` lines under a fade. Only the drawing changes:
/// copy, the message menu, find and VoiceOver still get the whole text.
/// Replies never fold.
public enum MessageCollapse {
/// The lines a folded message shows.
public static let maxLines = 12
Expand All @@ -15,14 +15,10 @@ public enum MessageCollapse {
/// The height of the Show more control under a folded message.
public static let controlHeight: Double = 22

/// Whether a message of this kind folds when it is long: what the reader
/// wrote and finished replies, never a reply still being written.
public static func folds(_ content: TranscriptItem.Content, isStreaming: Bool) -> Bool {
switch content {
case .user: true
case .assistant: !isStreaming
case .thinking, .tool, .command: false
}
/// Whether a message of this kind folds when it is long: only what the
/// reader wrote.
public static func folds(_ content: TranscriptItem.Content) -> Bool {
if case .user = content { true } else { false }
}

/// Whether `text` may run past `maxLines` lines: each line wraps every
Expand Down
12 changes: 5 additions & 7 deletions macos/Tests/RustCodeKitTests/MessageCollapseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@ final class MessageCollapseTests: XCTestCase {
XCTAssertTrue(MessageCollapse.isLong(height: 100 * line, lineHeight: line))
}

func testRepliesNeverFoldWhileWritten() {
XCTAssertTrue(MessageCollapse.folds(.user("hi"), isStreaming: false))
XCTAssertTrue(MessageCollapse.folds(.user("hi"), isStreaming: true))
XCTAssertTrue(MessageCollapse.folds(.assistant("hi"), isStreaming: false))
XCTAssertFalse(MessageCollapse.folds(.assistant("hi"), isStreaming: true))
XCTAssertFalse(MessageCollapse.folds(.thinking("hi"), isStreaming: false))
XCTAssertFalse(MessageCollapse.folds(.command(input: "/x", output: lines(40)), isStreaming: false))
func testOnlyUserMessagesFold() {
XCTAssertTrue(MessageCollapse.folds(.user("hi")))
XCTAssertFalse(MessageCollapse.folds(.assistant(lines(40))))
XCTAssertFalse(MessageCollapse.folds(.thinking("hi")))
XCTAssertFalse(MessageCollapse.folds(.command(input: "/x", output: lines(40))))
}

func testReplayedMessagesStartFoldedAndOpenPerChat() {
Expand Down
Loading