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
56 changes: 0 additions & 56 deletions Sources/Panels/CloudTerminalAttachmentBanner.swift

This file was deleted.

7 changes: 4 additions & 3 deletions Sources/Panels/TerminalPanelView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,10 @@ struct TerminalPanelView: View {
.id(panel.id)
.background(Color.clear)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.overlay(alignment: .top) {
CloudTerminalAttachmentBanner(status: panel.cloudAttachment)
}
// CloudTerminalOverlayCoordinator is the sole reconnect presenter.
// The attachment status remains available to startup loading, but
// rendering it here would put a second reconnect indicator above
// the native card while the same session is resolving.
.overlay {
CloudTerminalStartupLoadingView(readiness: panel.cloudStartupReadiness)
}
Expand Down
4 changes: 0 additions & 4 deletions cmux.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,6 @@
A38052AB06B7E0B46A215689 /* CloudTelemetrySending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBCFB7E8CD8163F74525C53 /* CloudTelemetrySending.swift */; };
3C939B66FD8358A0E08156BD /* CloudTelemetrySpan.swift in Sources */ = {isa = PBXBuildFile; fileRef = D995157010FFC40EB0D7460B /* CloudTelemetrySpan.swift */; };
B6DE6FA7480373F108723E63 /* CloudTelemetryUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26CFAFFB75F1B752AF93C8F6 /* CloudTelemetryUploader.swift */; };
EEDECB74EF421762EF8B1975 /* CloudTerminalAttachmentBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8DDCF09B5FC1FA72017163A /* CloudTerminalAttachmentBanner.swift */; };
566CF02BA2F7CCC0BD1E387E /* CloudTerminalAttachmentLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79064B52A25D34860A759BF8 /* CloudTerminalAttachmentLog.swift */; };
83EFE46711801D1A82B94FD1 /* CloudTerminalAttachmentRecoveryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC170FBE7AEBB71A5BE2922 /* CloudTerminalAttachmentRecoveryTests.swift */; };
9D73C47C49EF5E117D921D05 /* CloudTerminalAttachmentResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = A29A5C49E1A5590D63BCF886 /* CloudTerminalAttachmentResolver.swift */; };
Expand Down Expand Up @@ -4629,7 +4628,6 @@
3EBCFB7E8CD8163F74525C53 /* CloudTelemetrySending.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CloudTelemetrySending.swift"; sourceTree = "<group>"; };
D995157010FFC40EB0D7460B /* CloudTelemetrySpan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CloudTelemetrySpan.swift"; sourceTree = "<group>"; };
26CFAFFB75F1B752AF93C8F6 /* CloudTelemetryUploader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CloudTelemetryUploader.swift"; sourceTree = "<group>"; };
D8DDCF09B5FC1FA72017163A /* CloudTerminalAttachmentBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/CloudTerminalAttachmentBanner.swift; sourceTree = "<group>"; };
79064B52A25D34860A759BF8 /* CloudTerminalAttachmentLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudTerminalAttachmentLog.swift; sourceTree = "<group>"; };
BBC170FBE7AEBB71A5BE2922 /* CloudTerminalAttachmentRecoveryTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloudTerminalAttachmentRecoveryTests.swift; sourceTree = "<group>"; };
A29A5C49E1A5590D63BCF886 /* CloudTerminalAttachmentResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudTerminalAttachmentResolver.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -9452,7 +9450,6 @@
A5001411 /* TerminalPanel.swift */,
8997F0048997F0048997F004 /* TerminalPanel+AgentHibernation.swift */,
AAAD8854A2CD1387725EEC0A /* TerminalPanel+SurfaceSelection.swift */,
D8DDCF09B5FC1FA72017163A /* CloudTerminalAttachmentBanner.swift */,
A12480000000000000000004 /* CloudPaneCreationFailureView.swift */,
791101020000000000000001 /* TerminalPanel+SessionScrollbackReplay.swift */,
A5F100000000000000000008 /* TerminalPanel+NotificationScroll.swift */,
Expand Down Expand Up @@ -12441,7 +12438,6 @@
A38052AB06B7E0B46A215689 /* CloudTelemetrySending.swift in Sources */,
3C939B66FD8358A0E08156BD /* CloudTelemetrySpan.swift in Sources */,
B6DE6FA7480373F108723E63 /* CloudTelemetryUploader.swift in Sources */,
EEDECB74EF421762EF8B1975 /* CloudTerminalAttachmentBanner.swift in Sources */,
566CF02BA2F7CCC0BD1E387E /* CloudTerminalAttachmentLog.swift in Sources */,
9D73C47C49EF5E117D921D05 /* CloudTerminalAttachmentResolver.swift in Sources */,
4658DA26DAB751A74790718B /* CloudTerminalAttachmentRetryPolicy.swift in Sources */,
Expand Down
45 changes: 45 additions & 0 deletions cmuxTests/CloudManualMirrorPresentationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,51 @@ struct CloudManualMirrorPresentationTests {
#expect(CloudManualMirrorPresentation(phase: .disconnected, replayReceived: true).connectionState == .error)
}

@Test
func firstPresentedFrameDismissesTheReconnectPresentation() {
let state = CloudManualMirrorPresentation(
phase: .attached,
replayReceived: true,
firstFramePresented: true
).connectionState
#expect(state == .connected)
#expect(CloudTerminalReconnectOverlayPolicy.presentation(
isManagedCloudWorkspace: true,
isRemoteTerminalSurface: true,
connectionState: .connected,
detail: nil
) == nil)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

@Test @MainActor
func coordinatorRemovesReconnectCardWhenReadySnapshotArrives() throws {
let owner = CloudTerminalOverlayCoordinator()
let hosted = GhosttySurfaceScrollView(
surfaceView: GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 480, height: 320))
)
let anchor = GhosttyTerminalView.HostContainerView(frame: hosted.bounds)
owner.updateAnchor(anchor, visible: true, ownershipGeneration: 1)
let reconnecting = CloudTerminalReconnectOverlayPolicy.Presentation(
title: "Reconnecting", detail: "Waiting", showsProgress: true, showsReconnectButton: false
)
owner.synchronize(
hostedView: hosted,
contentFrame: hosted.bounds,
legacyPresentation: reconnecting,
onReconnect: {}
)
#expect(owner.overlay != nil)

owner.synchronize(
hostedView: hosted,
contentFrame: hosted.bounds,
legacyPresentation: nil,
onReconnect: {}
)
#expect(owner.overlay == nil)
#expect(anchor.subviews.isEmpty)
}

@Test @MainActor
func replayAloneKeepsTheCardUntilAVisibleFrame() async throws {
let fixture = try CloudManualMirrorSocketFixture()
Expand Down
15 changes: 0 additions & 15 deletions cmuxTests/CloudTerminalAttachmentRecoveryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,21 +197,6 @@ import Testing
#expect(!(await Self.waitUntil(timeout: .milliseconds(200)) { fired.count == 2 }))
}

/// The pane shows nothing while attached and a reason while reconnecting.
@Test
func attachmentBannerNamesTheMachineAndTheReason() {
#expect(CloudTerminalAttachmentBanner.text(for: .attached, machineID: "vm-1") == nil)
#expect(CloudTerminalAttachmentBanner.text(for: .ended, machineID: "vm-1") == nil)
let attaching = CloudTerminalAttachmentBanner.text(for: .attaching(attempt: 1), machineID: "vm-1")
#expect(attaching?.contains("vm-1") == true)
let reconnecting = CloudTerminalAttachmentBanner.text(
for: .reconnecting(attempt: 3, reason: .livenessTimedOut), machineID: "vm-1"
)
#expect(reconnecting?.contains("vm-1") == true)
#expect(reconnecting?.contains("3") == true)
#expect(reconnecting?.contains(CloudTerminalAttachmentInterruption.livenessTimedOut.localizedDescription) == true)
}

/// The raw bridge wraps transport errors inside details.error on some daemons.
@Test(arguments: ["transport.timeout", "transport.closed"])
func nestedTransportFailuresRemainRetryable(code: String) {
Expand Down
Loading