Skip to content
Open
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
15 changes: 14 additions & 1 deletion LoopFollow/Controllers/Graphs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,15 @@ extension MainViewController {
func createMidnightLines() {
// Draw a line at midnight: useful when showing multiple days of data
if Storage.shared.showMidnightLines.value {
var midnightTimeInterval = dateTimeUtils.getTimeIntervalMidnightToday()
var midnightTimeInterval: TimeInterval
if Storage.shared.graphTimeZoneEnabled.value,
let tz = TimeZone(identifier: Storage.shared.graphTimeZoneIdentifier.value) {
var cal = Calendar.current
cal.timeZone = tz
midnightTimeInterval = cal.startOfDay(for: Date()).timeIntervalSince1970
} else {
midnightTimeInterval = dateTimeUtils.getTimeIntervalMidnightToday()
}
let graphHours = 24 * Storage.shared.downloadDays.value
let graphStart = dateTimeUtils.getTimeIntervalNHoursAgo(N: graphHours)
while midnightTimeInterval > graphStart {
Expand Down Expand Up @@ -1881,6 +1889,11 @@ extension MainViewController {
dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm")
}

if Storage.shared.graphTimeZoneEnabled.value,
let tz = TimeZone(identifier: Storage.shared.graphTimeZoneIdentifier.value) {
dateFormatter.timeZone = tz
}

let wrappedLine1 = wrapText(line1, maxLineLength: 40)

let date = Date(timeIntervalSince1970: time)
Expand Down
5 changes: 5 additions & 0 deletions LoopFollow/Helpers/Chart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ final class ChartXValueFormatter: AxisValueFormatter {
dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm")
}

if Storage.shared.graphTimeZoneEnabled.value,
let tz = TimeZone(identifier: Storage.shared.graphTimeZoneIdentifier.value) {
dateFormatter.timeZone = tz
}

// let date = Date(timeIntervalSince1970: epochTimezoneOffset)
let date = Date(timeIntervalSince1970: value)
let formattedDate = dateFormatter.string(from: date)
Expand Down
29 changes: 29 additions & 0 deletions LoopFollow/Settings/GraphSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ struct GraphSettingsView: View {
@ObservedObject private var show90MinLine = Storage.shared.show90MinLine
@ObservedObject private var showMidnightLines = Storage.shared.showMidnightLines
@ObservedObject private var smallGraphTreatments = Storage.shared.smallGraphTreatments
@ObservedObject private var graphTimeZoneEnabled = Storage.shared.graphTimeZoneEnabled
@ObservedObject private var graphTimeZoneIdentifier = Storage.shared.graphTimeZoneIdentifier

@ObservedObject private var smallGraphHeight = Storage.shared.smallGraphHeight
@ObservedObject private var predictionToLoad = Storage.shared.predictionToLoad
Expand Down Expand Up @@ -48,6 +50,18 @@ struct GraphSettingsView: View {

Toggle("Show Midnight Lines", isOn: $showMidnightLines.value)
.onChange(of: showMidnightLines.value) { _ in markDirty() }

Toggle("Time Zone Override", isOn: $graphTimeZoneEnabled.value)
.onChange(of: graphTimeZoneEnabled.value) { _ in markDirty() }

if graphTimeZoneEnabled.value {
Picker("Time Zone", selection: $graphTimeZoneIdentifier.value) {
ForEach(Self.sortedTimeZones, id: \.identifier) { tz in
Text(Self.timeZoneLabel(tz)).tag(tz.identifier)
}
}
.onChange(of: graphTimeZoneIdentifier.value) { _ in markDirty() }
}
}

// ── Treatments ───────────────────────────────────────────────
Expand Down Expand Up @@ -140,4 +154,19 @@ struct GraphSettingsView: View {
private func markDirty() {
Observable.shared.chartSettingsChanged.value = true
}

// MARK: - Time Zone Helpers

private static let sortedTimeZones: [TimeZone] = {
TimeZone.knownTimeZoneIdentifiers
.compactMap { TimeZone(identifier: $0) }
.sorted { $0.secondsFromGMT() < $1.secondsFromGMT() }
}()

private static func timeZoneLabel(_ tz: TimeZone) -> String {
let offsetMinutes = tz.secondsFromGMT() / 60
let sign = offsetMinutes >= 0 ? "+" : "-"
let offsetString = String(format: "UTC%@%02d:%02d", sign, abs(offsetMinutes) / 60, abs(offsetMinutes) % 60)
return "(\(offsetString)) \(tz.identifier)"
}
}
2 changes: 2 additions & 0 deletions LoopFollow/Storage/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class Storage {
var lowLine = StorageValue<Double>(key: "lowLine", defaultValue: 70.0)
var highLine = StorageValue<Double>(key: "highLine", defaultValue: 180.0)
var downloadDays = StorageValue<Int>(key: "downloadDays", defaultValue: 1)
var graphTimeZoneEnabled = StorageValue<Bool>(key: "graphTimeZoneEnabled", defaultValue: false)
var graphTimeZoneIdentifier = StorageValue<String>(key: "graphTimeZoneIdentifier", defaultValue: TimeZone.current.identifier)
// Graph Settings [END]

// Calendar entries [BEGIN]
Expand Down