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
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ From repo root (`/Users/austinsmith/Developer/Repos/BitDream`), run macOS tests
test
```

Testing guidance:

- Add tests when they protect meaningful user-visible behavior, cross-file integration, bug regressions, or non-trivial logic that is easy to break.
- Do not add dedicated tests for every small helper extraction, straightforward computed property, or internal refactor unless the change introduces real behavioral risk.
- Prefer a small number of high-signal tests over many narrow tests that only restate the implementation.

## Linting

From repo root (`/Users/austinsmith/Developer/Repos/BitDream`), run:
Expand Down
58 changes: 39 additions & 19 deletions BitDream/Views/Shared/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,40 @@ func ensureStartupConnectionBehaviorApplied(store: TransmissionStore, modelConte

// MARK: - Shared Views

struct RatioSummarySnapshot: Equatable {
let uploaded: Int64
let downloaded: Int64

var ratio: Double {
downloaded > 0 ? Double(uploaded) / Double(downloaded) : 0
}
}

@MainActor
func makeRatioSummarySnapshot(store: TransmissionStore, displayMode: RatioDisplayMode) -> RatioSummarySnapshot {
switch displayMode {
case .cumulative:
if let stats = store.sessionStats?.cumulativeStats {
return RatioSummarySnapshot(
uploaded: stats.uploadedBytes,
downloaded: stats.downloadedBytes
)
}
case .current:
if let stats = store.sessionStats?.currentStats {
return RatioSummarySnapshot(
uploaded: stats.uploadedBytes,
downloaded: stats.downloadedBytes
)
}
}

return RatioSummarySnapshot(
uploaded: store.torrents.reduce(0) { $0 + $1.uploadedEver },
downloaded: store.torrents.reduce(0) { $0 + $1.downloadedEver }
)
}

// Stats header view used on both platforms
struct StatsHeaderView: View {
@ObservedObject var store: TransmissionStore
Expand All @@ -154,32 +188,18 @@ struct StatsHeaderView: View {
RatioDisplayMode(rawValue: ratioDisplayModeRaw) ?? AppDefaults.ratioDisplayMode
}

private var overallTotals: (uploaded: Int64, downloaded: Int64) {
switch ratioDisplayMode {
case .cumulative:
if let stats = store.sessionStats?.cumulativeStats {
return (uploaded: stats.uploadedBytes, downloaded: stats.downloadedBytes)
}
case .current:
if let stats = store.sessionStats?.currentStats {
return (uploaded: stats.uploadedBytes, downloaded: stats.downloadedBytes)
}
}
let fallbackDownloaded = store.torrents.reduce(0) { $0 + $1.downloadedEver }
let fallbackUploaded = store.torrents.reduce(0) { $0 + $1.uploadedEver }
return (uploaded: fallbackUploaded, downloaded: fallbackDownloaded)
private var ratioSummary: RatioSummarySnapshot {
makeRatioSummarySnapshot(store: store, displayMode: ratioDisplayMode)
}

private var overallRatio: Double {
let totals = overallTotals
return totals.downloaded > 0 ? Double(totals.uploaded) / Double(totals.downloaded) : 0.0
ratioSummary.ratio
}

private var ratioTooltip: String {
let totals = overallTotals
let mode = ratioDisplayMode == .cumulative ? "Total Ratio" : "Session Ratio"
let uploaded = formatByteCount(totals.uploaded)
let downloaded = formatByteCount(totals.downloaded)
let uploaded = formatByteCount(ratioSummary.uploaded)
let downloaded = formatByteCount(ratioSummary.downloaded)
return "\(mode)\n----------\nUploaded: \(uploaded)\nDownloaded: \(downloaded)"
}

Expand Down
15 changes: 8 additions & 7 deletions BitDream/Views/macOS/MenuBar/MenuBarTorrentSelectors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,24 @@ func menuBarActiveTorrents(from store: TransmissionStore, sortMode: MenuBarSortM

@MainActor
func menuBarSummary(from store: TransmissionStore) -> MenuBarTorrentSummary {
menuBarSummary(from: store, activeTorrents: menuBarActiveTorrents(from: store, sortMode: .activity))
menuBarSummary(
from: store,
activeTorrents: menuBarActiveTorrents(from: store, sortMode: .activity),
ratioDisplayMode: AppDefaults.ratioDisplayMode
)
}

@MainActor
func menuBarSummary(from store: TransmissionStore, activeTorrents: [Torrent]) -> MenuBarTorrentSummary {
func menuBarSummary(from store: TransmissionStore, activeTorrents: [Torrent], ratioDisplayMode: RatioDisplayMode) -> MenuBarTorrentSummary {
let stats = store.sessionStats

let uploaded = stats?.currentStats?.uploadedBytes ?? 0
let downloaded = stats?.currentStats?.downloadedBytes ?? 0
let ratio = downloaded > 0 ? Double(uploaded) / Double(downloaded) : 0
let ratioSummary = makeRatioSummarySnapshot(store: store, displayMode: ratioDisplayMode)

return MenuBarTorrentSummary(
serverName: store.host?.name ?? "No Server",
activeCount: activeTorrents.count,
downloadSpeed: stats?.downloadSpeed ?? 0,
uploadSpeed: stats?.uploadSpeed ?? 0,
ratio: ratio
ratio: ratioSummary.ratio
)
}

Expand Down
13 changes: 10 additions & 3 deletions BitDream/Views/macOS/MenuBar/macOSMenuBarTorrentWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ struct macOSMenuBarTorrentWidget: View {
@EnvironmentObject private var store: TransmissionStore
@State private var torrentRowsHeight: CGFloat = 0
@AppStorage(UserDefaultsKeys.menuBarSortMode) private var menuBarSortModeRaw: String = AppDefaults.menuBarSortMode.rawValue
@AppStorage(UserDefaultsKeys.ratioDisplayMode) private var ratioDisplayModeRaw: String = AppDefaults.ratioDisplayMode.rawValue
let onOpenMainWindow: () -> Void

private let panelWidth: CGFloat = 380
Expand All @@ -21,12 +22,16 @@ struct macOSMenuBarTorrentWidget: View {
MenuBarSortMode(rawValue: menuBarSortModeRaw) ?? AppDefaults.menuBarSortMode
}

private var ratioDisplayMode: RatioDisplayMode {
RatioDisplayMode(rawValue: ratioDisplayModeRaw) ?? AppDefaults.ratioDisplayMode
}

private var activeTorrents: [Torrent] {
menuBarActiveTorrents(from: store, sortMode: menuBarSortMode)
}

private var summary: MenuBarTorrentSummary {
menuBarSummary(from: store, activeTorrents: activeTorrents)
menuBarSummary(from: store, activeTorrents: activeTorrents, ratioDisplayMode: ratioDisplayMode)
}

private var isConnected: Bool {
Expand Down Expand Up @@ -96,10 +101,12 @@ struct macOSMenuBarTorrentWidget: View {
}

HStack(spacing: 8) {
SpeedChip(speed: summary.downloadSpeed, direction: .download, style: .chip, size: .compact)
SpeedChip(speed: summary.uploadSpeed, direction: .upload, style: .chip, size: .compact)
RatioChip(ratio: summary.ratio, size: .compact)
Spacer(minLength: 0)
HStack(spacing: 8) {
SpeedChip(speed: summary.downloadSpeed, direction: .download, style: .chip, size: .compact)
SpeedChip(speed: summary.uploadSpeed, direction: .upload, style: .chip, size: .compact)
}
}
}
}
Expand Down