diff --git a/Tarnax/App.swift b/Tarnax/App.swift index fb07c4f..e47c2aa 100644 --- a/Tarnax/App.swift +++ b/Tarnax/App.swift @@ -287,7 +287,7 @@ struct TransferHistoryChart: View { private var end: Date { updatedAt ?? Date() } private var start: Date { end.addingTimeInterval(-Double(minutes * 60)) } - private var samples: [TransferSample] { history.samples.filter { $0.date >= start && $0.date <= end } } + private var samples: [TransferSample] { history.samples(from: start, through: end) } private var selectedSample: TransferSample? { guard let selection else { return nil } return samples.min { abs($0.date.timeIntervalSince(selection)) < abs($1.date.timeIntervalSince(selection)) } diff --git a/Tarnax/Core.swift b/Tarnax/Core.swift index c947621..bd243fc 100644 --- a/Tarnax/Core.swift +++ b/Tarnax/Core.swift @@ -140,9 +140,19 @@ struct TransferHistory { private(set) var samples: [TransferSample] = [] private var segment = 0 + func samples(from start: Date, through end: Date) -> [TransferSample] { + let lower = start.timeIntervalSinceReferenceDate + let upper = end.timeIntervalSinceReferenceDate + // Avoid SDK-new Date >= / <= entry points missing from some iOS betas. + return samples.filter { + let time = $0.date.timeIntervalSinceReferenceDate + return time >= lower && time <= upper + } + } + mutating func record(download: Int64, upload: Int64, at date: Date = Date()) { if let last = samples.last { - guard date >= last.date else { return } + guard date.timeIntervalSinceReferenceDate >= last.date.timeIntervalSinceReferenceDate else { return } if date.timeIntervalSince(last.date) > 10 { segment += 1 } // Extra action/manual refreshes must not inflate the history buffer. if date.timeIntervalSince(last.date) < 1 { samples.removeLast() } diff --git a/Tarnax/Info.plist b/Tarnax/Info.plist index 09f9039..3578bac 100644 --- a/Tarnax/Info.plist +++ b/Tarnax/Info.plist @@ -15,7 +15,7 @@ CFBundleShortVersionString 1.0 CFBundleVersion - 5 + 6 LSRequiresIPhoneOS NSFaceIDUsageDescription diff --git a/Tests/ContractTests.swift b/Tests/ContractTests.swift index cd0fc51..2a769f5 100644 --- a/Tests/ContractTests.swift +++ b/Tests/ContractTests.swift @@ -249,6 +249,10 @@ final class MockProtocol: URLProtocol, @unchecked Sendable { check(liveHistory.transferHistory.samples.count == 1, "Failed refresh never fabricates a speed sample") liveHistory.disconnect() check(liveHistory.transferHistory.samples.isEmpty, "Disconnect removes actual collected history") + var windowHistory = TransferHistory() + for second in [0, 3, 6] { windowHistory.record(download: 1, upload: 2, at: origin.addingTimeInterval(Double(second))) } + check(windowHistory.samples(from: origin.addingTimeInterval(3), through: origin.addingTimeInterval(6)).count == 2, "History window includes exact timestamp boundaries without new Date comparison entry points") + check(windowHistory.samples(from: origin.addingTimeInterval(7), through: origin.addingTimeInterval(9)).isEmpty, "History window excludes samples outside its numeric time range") another.close(); transport.close(); print("\(checks) contract checks passed.") } }