feat: add alert grace period controls

This commit is contained in:
2026-04-24 19:16:20 +02:00
parent b4163d8c8b
commit d3af580f07
6 changed files with 189 additions and 14 deletions
+72 -2
View File
@@ -28,15 +28,19 @@ struct PreferencesView: View {
@AppStorage("pingInterval") private var storedPingInterval: Int = 10
@AppStorage("refreshInterval") private var storedRefreshInterval: Int = 60
@AppStorage("showIntervalIndicator") private var showIntervalIndicator: Bool = true
@AppStorage("alertGracePeriod") private var storedAlertGracePeriod: Int = 30
@State private var pingIntervalSlider: Double = 10
@State private var refreshIntervalSlider: Double = 60
@State private var alertGracePeriodSlider: Double = 30
@State private var selection: Tab = .monitor
@State private var hoveredTab: Tab?
private let minimumInterval: Double = 10
private let maximumPingInterval: Double = 60
private let maximumRefreshInterval: Double = 600
private let minimumAlertGracePeriod: Double = 0
private let maximumAlertGracePeriod: Double = 300
var body: some View {
HStack(spacing: 0) {
@@ -53,6 +57,7 @@ struct PreferencesView: View {
.onAppear {
pingIntervalSlider = Double(storedPingInterval)
refreshIntervalSlider = Double(storedRefreshInterval)
alertGracePeriodSlider = Double(storedAlertGracePeriod)
}
.onChange(of: pingIntervalSlider) { _, newValue in
storedPingInterval = Int(newValue)
@@ -60,6 +65,9 @@ struct PreferencesView: View {
.onChange(of: refreshIntervalSlider) { _, newValue in
storedRefreshInterval = Int(newValue)
}
.onChange(of: alertGracePeriodSlider) { _, newValue in
storedAlertGracePeriod = Int(newValue)
}
}
private var sidebar: some View {
@@ -121,7 +129,12 @@ struct PreferencesView: View {
refreshChanged: handleRefreshSliderEditing(_:)
)
case .notifications:
NotificationsPreferencesView()
NotificationsPreferencesView(
alertGracePeriodSlider: $alertGracePeriodSlider,
minimumAlertGracePeriod: minimumAlertGracePeriod,
maximumAlertGracePeriod: maximumAlertGracePeriod,
alertGraceChanged: handleAlertGraceSliderEditing(_:)
)
case .alerts:
AlertsPreferencesView()
case .updates:
@@ -142,6 +155,13 @@ struct PreferencesView: View {
storedRefreshInterval = Int(refreshIntervalSlider)
}
}
private func handleAlertGraceSliderEditing(_ editing: Bool) {
if !editing {
storedAlertGracePeriod = Int(alertGracePeriodSlider)
}
}
private func backgroundColor(for tab: Tab) -> Color {
if selection == tab {
return sidebarSelectionColor
@@ -238,7 +258,7 @@ private struct MonitorPreferencesView: View {
in: range,
step: 5
) {
Text(title)
EmptyView()
} minimumValueLabel: {
Text("\(Int(range.lowerBound))s")
.font(.caption)
@@ -290,12 +310,62 @@ private struct UpdatesPreferencesView: View {
private struct NotificationsPreferencesView: View {
@AppStorage("enableStatusNotifications") private var enableStatusNotifications: Bool = true
@AppStorage("enableAlertNotifications") private var enableAlertNotifications: Bool = true
@Binding var alertGracePeriodSlider: Double
@State private var showAlertGraceHelp = false
let minimumAlertGracePeriod: Double
let maximumAlertGracePeriod: Double
let alertGraceChanged: (Bool) -> Void
var body: some View {
VStack(alignment: .leading, spacing: 18) {
Toggle("Status Notifications", isOn: $enableStatusNotifications)
Toggle("Alert Notifications", isOn: $enableAlertNotifications)
VStack(alignment: .leading, spacing: 8) {
HStack {
HStack(spacing: 6) {
Text("Alert grace period")
.font(.headline)
Button {
showAlertGraceHelp.toggle()
} label: {
Image(systemName: "questionmark.circle")
.foregroundColor(.secondary)
}
.buttonStyle(.plain)
.popover(isPresented: $showAlertGraceHelp, arrowEdge: .bottom) {
Text("Wait this long before raising an alert after a host or service first appears unavailable.")
.font(.callout)
.padding(12)
.frame(width: 280, alignment: .leading)
}
}
Spacer()
Text("\(Int(alertGracePeriodSlider)) seconds")
.font(.subheadline)
.foregroundColor(.secondary)
}
Slider(
value: $alertGracePeriodSlider,
in: minimumAlertGracePeriod...maximumAlertGracePeriod,
step: 5
) {
EmptyView()
} minimumValueLabel: {
Text("\(Int(minimumAlertGracePeriod))s")
.font(.caption)
.foregroundColor(.secondary)
} maximumValueLabel: {
Text("\(Int(maximumAlertGracePeriod))s")
.font(.caption)
.foregroundColor(.secondary)
} onEditingChanged: { editing in
alertGraceChanged(editing)
}
}
Spacer()
}
.toggleStyle(.switch)