Skip to content

Commit b716f88

Browse files
committed
Keep hover session rows compact
1 parent 96d1c8c commit b716f88

4 files changed

Lines changed: 48 additions & 21 deletions

File tree

‎Sources/NoturcodeApp/DisplayCoordinator.swift‎

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,12 @@ final class NotchPresentationState: ObservableObject {
295295
@Published private(set) var isExpanded: Bool
296296
@Published private(set) var hoveredSessionID: String?
297297
@Published private(set) var pressedSessionID: String?
298-
@Published private(set) var activityExpandedSessionID: String?
299298
let isUITestSpotlight: Bool
300299
let isUITestRapidHover: Bool
301300

302301
private var isArmed = true
303302
private var pointerInside = false
304303
private let isUITestForcedExpanded: Bool
305-
private let isUITestActivityExpanded: Bool
306304
private var dwellTask: Task<Void, Never>?
307305
private var exitTask: Task<Void, Never>?
308306
private var hoverIntentTask: Task<Void, Never>?
@@ -313,7 +311,6 @@ final class NotchPresentationState: ObservableObject {
313311
isUITestSpotlight = CommandLine.arguments.contains("--ui-test-hover-first")
314312
|| CommandLine.arguments.contains("--ui-test-live-transcript")
315313
isUITestRapidHover = CommandLine.arguments.contains("--ui-test-rapid-hover")
316-
isUITestActivityExpanded = CommandLine.arguments.contains("--ui-test-expanded-activity")
317314
isExpanded = isUITestForcedExpanded
318315
isArmed = !isExpanded
319316
}
@@ -359,9 +356,6 @@ final class NotchPresentationState: ObservableObject {
359356
hoverClearTask?.cancel()
360357
hoverClearTask = nil
361358
if let id {
362-
if hoveredSessionID != id, isUITestActivityExpanded {
363-
activityExpandedSessionID = id
364-
}
365359
if isUITestSpotlight || hoveredSessionID == nil {
366360
hoveredSessionID = id
367361
return
@@ -389,10 +383,6 @@ final class NotchPresentationState: ObservableObject {
389383
}
390384
}
391385

392-
func toggleActivityExpansion(for sessionID: String) {
393-
activityExpandedSessionID = activityExpandedSessionID == sessionID ? nil : sessionID
394-
}
395-
396386
func expand() {
397387
dwellTask?.cancel()
398388
dwellTask = nil
@@ -408,8 +398,7 @@ final class NotchPresentationState: ObservableObject {
408398
$0.state.showsCompletionSummary && NoturcodeSummaryContract.isDisplayable($0.lastAgentMessage)
409399
}.count
410400
let summaryAllowance = min(42, CGFloat(summaryCount) * 14)
411-
if activityExpandedSessionID != nil { return summaryAllowance + 207 }
412-
return summaryAllowance + (hoveredSessionID == nil ? 0 : 95)
401+
return summaryAllowance
413402
}
414403

415404
func select(_ session: TrackedSession, action: @escaping @MainActor () -> Void) {
@@ -444,7 +433,6 @@ final class NotchPresentationState: ObservableObject {
444433
hoverClearTask = nil
445434
isExpanded = false
446435
hoveredSessionID = nil
447-
activityExpandedSessionID = nil
448436
isArmed = false
449437
}
450438
}

‎Sources/NoturcodeApp/SessionViews.swift‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -550,14 +550,9 @@ private struct SessionRow: View {
550550
.font(.system(size: 13, weight: .semibold))
551551
.foregroundStyle(.white.opacity(0.95))
552552
.lineLimit(1)
553+
.fixedSize(horizontal: true, vertical: false)
553554
}
554555
Spacer(minLength: 6)
555-
if let tokens = session.tokens {
556-
Text(DurationFormatting.tokens(tokens))
557-
.font(.system(size: 10.5, weight: .medium))
558-
.monospacedDigit()
559-
.foregroundStyle(.white.opacity(0.46))
560-
}
561556
if !session.activeSubagents.isEmpty {
562557
Text("\(session.activeSubagents.count) agent\(session.activeSubagents.count == 1 ? "" : "s")")
563558
.font(.system(size: 10.5, weight: .medium))

‎Sources/NoturcodeCore/SessionStore.swift‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ public final class SessionStore: ObservableObject {
2222

2323
switch event.kind {
2424
case .connect:
25-
guard let name = event.name?.trimmingCharacters(in: .whitespacesAndNewlines),
26-
!name.isEmpty,
25+
guard let name = Self.normalizedSessionName(event.name),
2726
let terminalSessionID = event.terminalSessionID,
2827
!terminalSessionID.isEmpty else { return nil }
2928
let session = TrackedSession(
@@ -197,6 +196,14 @@ public final class SessionStore: ObservableObject {
197196
sessions.sorted { $0.lastPromptAt > $1.lastPromptAt }
198197
}
199198

199+
private static func normalizedSessionName(_ rawName: String?) -> String? {
200+
rawName?
201+
.components(separatedBy: .newlines)
202+
.lazy
203+
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
204+
.first(where: { !$0.isEmpty })
205+
}
206+
200207
private func session(at index: Int?) -> TrackedSession? {
201208
guard let index else { return nil }
202209
return sessions[index]

‎Tests/NoturcodeCoreTests/NoturcodeCoreTests.swift‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,23 @@ final class NoturcodeCoreTests: XCTestCase {
10861086
XCTAssertEqual(store.sessions.map(\.name), ["two"])
10871087
}
10881088

1089+
@MainActor
1090+
func testSessionStoreUsesOnlyFirstNonEmptyLineOfConnectionName() throws {
1091+
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
1092+
let store = SessionStore(persistence: SessionPersistence(fileURL: directory.appendingPathComponent("sessions.json")))
1093+
1094+
_ = store.apply(BridgeEvent(
1095+
kind: .connect,
1096+
source: .codex,
1097+
sessionID: "multiline-name",
1098+
timestamp: Date(timeIntervalSince1970: 1_000),
1099+
name: " nc \nthis is prompt text, not the session name",
1100+
terminalSessionID: "w0t1:NAME"
1101+
))
1102+
1103+
XCTAssertEqual(store.sessions.first?.name, "nc")
1104+
}
1105+
10891106
@MainActor
10901107
func testHarnessSessionEndDoesNotRemoveExplicitConnection() throws {
10911108
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
@@ -1147,9 +1164,14 @@ final class NoturcodeCoreTests: XCTestCase {
11471164
.deletingLastPathComponent()
11481165
let surface = try String(contentsOf: repository.appendingPathComponent("Sources/NoturcodeApp/NotchSurfaceView.swift"))
11491166
let sessions = try String(contentsOf: repository.appendingPathComponent("Sources/NoturcodeApp/SessionViews.swift"))
1167+
let coordinator = try String(contentsOf: repository.appendingPathComponent("Sources/NoturcodeApp/DisplayCoordinator.swift"))
11501168

11511169
XCTAssertTrue(surface.contains("value: surfaceHeight"))
11521170
XCTAssertFalse(sessions.contains(".transition(.opacity.combined(with: .move(edge: .top)))"))
1171+
XCTAssertTrue(coordinator.contains("return summaryAllowance"))
1172+
XCTAssertFalse(coordinator.contains("activityExpandedSessionID"))
1173+
XCTAssertFalse(coordinator.contains("toggleActivityExpansion"))
1174+
XCTAssertFalse(coordinator.contains("hoveredSessionID == nil ? 0 : 95"))
11531175
}
11541176

11551177
func testExpandedNotchMorphsContentInsideOnePersistentHeader() throws {
@@ -1203,6 +1225,21 @@ final class NoturcodeCoreTests: XCTestCase {
12031225
XCTAssertFalse(sessions.contains("if isHovered || isActivityExpanded"))
12041226
}
12051227

1228+
func testExpandedNotchSessionRowKeepsFullNameAndHidesTokenCounter() throws {
1229+
let repository = URL(fileURLWithPath: #filePath)
1230+
.deletingLastPathComponent()
1231+
.deletingLastPathComponent()
1232+
.deletingLastPathComponent()
1233+
let source = try String(contentsOf: repository.appendingPathComponent("Sources/NoturcodeApp/SessionViews.swift"))
1234+
let rowStart = try XCTUnwrap(source.range(of: "private struct SessionRow"))
1235+
let nextStart = try XCTUnwrap(source.range(of: "private struct ConversationSidebarToggle"))
1236+
let row = String(source[rowStart.lowerBound..<nextStart.lowerBound])
1237+
1238+
XCTAssertTrue(row.contains(".fixedSize(horizontal: true, vertical: false)"))
1239+
XCTAssertFalse(row.contains("if let tokens = session.tokens"))
1240+
XCTAssertFalse(row.contains("DurationFormatting.tokens"))
1241+
}
1242+
12061243
func testExpandedNotchShowsRotatingQuoteAndKeepsEverySessionInList() throws {
12071244
let repository = URL(fileURLWithPath: #filePath)
12081245
.deletingLastPathComponent()

0 commit comments

Comments
 (0)