Fix SFTP status bar transfer direction

This commit is contained in:
Kaede Akino committed 2026-09-17 15:10:26 +08:00
1 parent 781dbcdfc9
commit 42660095a5
2 files changed
+95 -4

No files matched your search

+27 -4
View File
@@ -33,6 +33,24 @@ nonisolated enum StatusBarPresentation {
}
}
/// The direction worth showing inside the active transfer progress ring.
///
/// Only work that is actually moving bytes participates. Queued and historical
/// transfers still contribute to the transfer center's existing counts and
/// state, but they must not make a running upload or download look mixed.
nonisolated enum StatusBarTransferPresentation {
static func runningDirectionSymbol(for transfers: [SFTPTransfer]) -> String {
let directions = Set(
transfers.lazy
.filter { $0.state == .running }
.map(\.direction)
)
if directions == [.upload] { return "arrow.up" }
if directions == [.download] { return "arrow.down" }
return "arrow.up.arrow.down"
}
}
/// Focused-session context and app-wide transfers, as one floating capsule.
///
/// It used to be a docked strip with a hairline above it, which read as a piece
@@ -179,8 +197,11 @@ struct StatusBarView: View {
height: Metrics.Sidebar.statusDot
)
case .transfers:
TransferGlyph(summary: app.sftpTransfers.summary)
.frame(width: 18, height: 18)
TransferGlyph(
summary: app.sftpTransfers.summary,
transfers: app.sftpTransfers.sftpTransfers
)
.frame(width: 18, height: 18)
}
}
.frame(
@@ -372,6 +393,7 @@ private struct StatusBarPathLabel: View {
/// front of it.
private struct TransferGlyph: View {
let summary: SFTPTransferSummary
let transfers: [SFTPTransfer]
@ViewBuilder
var body: some View {
@@ -389,7 +411,7 @@ private struct TransferGlyph: View {
} else {
ProgressView().controlSize(.mini)
}
Image(systemName: "arrow.up")
Image(systemName: StatusBarTransferPresentation.runningDirectionSymbol(for: transfers))
.font(.system(size: 8, weight: .bold))
}
} else if summary.failedCount > 0 {
@@ -414,7 +436,8 @@ private struct TransferCenterButton: View {
isPresented.toggle()
} label: {
HStack(spacing: Metrics.Space.xs) {
TransferGlyph(summary: summaryValue).frame(width: 18, height: 18)
TransferGlyph(summary: summaryValue, transfers: coordinator.sftpTransfers)
.frame(width: 18, height: 18)
if summaryValue.activeCount > 0 {
Text(summaryValue.activeCount, format: .number)
.monospacedDigit()
+68
View File
@@ -82,4 +82,72 @@ struct StatusBarPresentationTests {
)
#expect(Metrics.StatusBar.overlayClearance > Metrics.StatusBar.height)
}
@Test
func runningUploadsUseTheUploadSymbol() {
let transfers = [
transfer(direction: .upload, state: .running),
transfer(direction: .upload, state: .running),
]
#expect(StatusBarTransferPresentation.runningDirectionSymbol(for: transfers) == "arrow.up")
}
@Test
func runningDownloadsUseTheDownloadSymbol() {
let transfers = [
transfer(direction: .download, state: .running),
transfer(direction: .download, state: .running),
]
#expect(StatusBarTransferPresentation.runningDirectionSymbol(for: transfers) == "arrow.down")
}
@Test
func copiesAndMixedDirectionsUseTheBidirectionalSymbol() {
#expect(
StatusBarTransferPresentation.runningDirectionSymbol(
for: [transfer(direction: .copy, state: .running)]
) == "arrow.up.arrow.down"
)
#expect(
StatusBarTransferPresentation.runningDirectionSymbol(
for: [
transfer(direction: .upload, state: .running),
transfer(direction: .download, state: .running),
]
) == "arrow.up.arrow.down"
)
}
@Test
func onlyRunningTransfersChooseTheDirectionSymbol() {
let transfers = [
transfer(direction: .upload, state: .running),
transfer(direction: .download, state: .queued),
transfer(direction: .download, state: .paused),
transfer(direction: .download, state: .completed),
transfer(direction: .download, state: .cancelled),
transfer(direction: .download, state: .failed("Offline")),
]
#expect(StatusBarTransferPresentation.runningDirectionSymbol(for: transfers) == "arrow.up")
#expect(
StatusBarTransferPresentation.runningDirectionSymbol(
for: [transfer(direction: .download, state: .queued)]
) == "arrow.up.arrow.down"
)
}
private func transfer(
direction: SFTPTransfer.Direction,
state: SFTPTransfer.State
) -> SFTPTransfer {
SFTPTransfer(
direction: direction,
localPath: "/tmp/file.txt",
remotePath: "/srv/file.txt",
state: state
)
}
}