feat: event reminders + default reminder setting + local notifications (iOS)
Per-event reminders (multiple, local calendars only) in the editor, prefilled from a new "default reminder" setting that applies to all events otherwise. CalEvent gains `reminders`; AppSettings/SettingsSync sync default_reminder_minutes (always group). New NotificationScheduler requests permission and schedules the soonest ≤60 upcoming reminders via UNUserNotificationCenter, rescheduling on load/sync/edit and when the default changes (skipped in group overlay). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ struct SettingsView: View {
|
||||
@AppStorage("defaultView") private var defaultView = "month"
|
||||
@AppStorage("weekStartDay") private var weekStartDay = "monday"
|
||||
@AppStorage("dimPastEvents") private var dimPastEvents = false
|
||||
@AppStorage("defaultReminderMinutes") private var defaultReminderMinutes = -1
|
||||
|
||||
// Profile chapter (server-backed; loaded on appear).
|
||||
@State private var displayName = ""
|
||||
@@ -37,6 +38,7 @@ struct SettingsView: View {
|
||||
Form {
|
||||
profilSection
|
||||
privatsphaereSection
|
||||
benachrichtigungenSection
|
||||
geteilterKalenderSection
|
||||
liquidGlassSection
|
||||
cacheSection
|
||||
@@ -105,6 +107,27 @@ struct SettingsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: – Benachrichtigungen
|
||||
|
||||
var benachrichtigungenSection: some View {
|
||||
Section {
|
||||
Picker(ReminderOptions.defaultTitle(appLang), selection: $defaultReminderMinutes) {
|
||||
Text(ReminderOptions.off(appLang)).tag(-1)
|
||||
ForEach(ReminderOptions.all, id: \.self) { m in
|
||||
Text(ReminderOptions.label(m, appLang)).tag(m)
|
||||
}
|
||||
}
|
||||
.onChange(of: defaultReminderMinutes) { _, _ in
|
||||
SettingsSync.push(api: api)
|
||||
NotificationCenter.default.post(name: .rescheduleReminders, object: nil)
|
||||
}
|
||||
} header: {
|
||||
Text(ReminderOptions.sectionTitle(appLang))
|
||||
} footer: {
|
||||
Text(ReminderOptions.defaultFooter(appLang)).font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: – Privatsphäre
|
||||
|
||||
var privatsphaereSection: some View {
|
||||
|
||||
Reference in New Issue
Block a user