Widget-Optionen statt „Quellen", Reiterleiste von der Trennlinie herunter
Die Leiste saß mittig auf der Trennlinie unter dem Titelbalken. `titlebarAppearsTransparent` allein reichte nicht — macOS zieht darunter zusätzlich einen Trenner quer durchs Fenster. Der ist jetzt aus. Man setzt keinen Titel auf eine Trennlinie. „Quellen" war die Sicht des Programmierers: für den Nutzer ist die Datenquelle eine Einstellung **des Kalenderwidgets** unter mehreren. Der Bereich heißt jetzt „Widget-Optionen" und hat einen Abschnitt je Widget. Kalender: woher die Daten kommen, Monatsraster oder Terminliste — und endlich, welche Kalender überhaupt mitzählen. Gespeichert werden die **abgewählten**, nicht die gewählten: kommt ein neuer Kalender dazu, ist er damit automatisch dabei, statt dass man ihn suchen müsste, ohne zu wissen, dass es ihn gibt. Der Filter lässt die Abdeckung unberührt — welche Kalender man sehen will, sagt nichts darüber aus, für welchen Zeitraum Daten vorliegen. Wetter: dem Standort folgen oder einen festen Ort setzen, per Stadt oder Postleitzahl. WeatherKit will Koordinaten, der Nutzer kennt Ortsnamen — die Umsetzung passiert einmal beim Einstellen statt bei jedem Abruf. Der Ort überlebt jetzt auch den Neustart; vorher stand nach jedem Start wieder der Aufenthaltsort da. Die Ablage-Einstellungen sind vom Widget-Reiter hierher gewandert, wo die anderen Widget-Optionen stehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -67,3 +67,18 @@ public extension EventWindow {
|
||||
return EventWindow(events: events, coverage: coverage, asOf: asOf)
|
||||
}
|
||||
}
|
||||
|
||||
public extension CalendarSourceState {
|
||||
/// Blendet die abgewählten Kalender aus.
|
||||
///
|
||||
/// Die Abdeckung bleibt unangetastet: welche Kalender man sehen will, sagt
|
||||
/// nichts darüber aus, für welchen Zeitraum Daten vorliegen. Ein Tag ohne
|
||||
/// sichtbare Termine bleibt ein bekannter Tag.
|
||||
func filteringHidden(_ hidden: Set<String>) -> CalendarSourceState {
|
||||
guard case .ready(let window) = self, !hidden.isEmpty else { return self }
|
||||
return .ready(EventWindow(
|
||||
events: window.events.filter { !hidden.contains($0.calendarID) },
|
||||
coverage: window.coverage,
|
||||
asOf: window.asOf))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,24 @@ public final class CalendarModel {
|
||||
didSet { defaults.set(showsMonthGrid, forKey: Self.gridKey) }
|
||||
}
|
||||
|
||||
/// Welche Kalender Daten liefern. `nil` heißt: alle.
|
||||
///
|
||||
/// Bewusst eine Liste der **abgewählten**, nicht der gewählten: kommt ein
|
||||
/// neuer Kalender dazu, ist er dann automatisch dabei. Andersherum müsste
|
||||
/// man ihn suchen und anhaken, ohne zu wissen, dass es ihn gibt.
|
||||
public var hiddenCalendarIDs: Set<String> {
|
||||
didSet {
|
||||
guard hiddenCalendarIDs != oldValue else { return }
|
||||
defaults.set(Array(hiddenCalendarIDs), forKey: Self.hiddenKey)
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
/// Die Kalender, die zur Auswahl stehen.
|
||||
public private(set) var availableCalendars: [OnyxCalendar] = []
|
||||
|
||||
private static let kindKey = "calendar.source"
|
||||
private static let hiddenKey = "calendar.hiddenCalendars"
|
||||
private static let gridKey = "calendar.showsMonthGrid"
|
||||
|
||||
private let appleSource: CalendarSource
|
||||
@@ -51,6 +68,7 @@ public final class CalendarModel {
|
||||
self.kind = defaults.string(forKey: Self.kindKey)
|
||||
.flatMap(CalendarSourceKind.init(rawValue:)) ?? .appleCalendar
|
||||
self.showsMonthGrid = defaults.bool(forKey: Self.gridKey)
|
||||
self.hiddenCalendarIDs = Set(defaults.stringArray(forKey: Self.hiddenKey) ?? [])
|
||||
observeCalendarrIfNeeded()
|
||||
}
|
||||
|
||||
@@ -139,7 +157,16 @@ public final class CalendarModel {
|
||||
states.append(source.isAuthorized ? await source.load(interval) : .denied)
|
||||
}
|
||||
guard !Task.isCancelled else { return }
|
||||
state = CalendarSourceKind.merge(states)
|
||||
state = CalendarSourceKind.merge(states).filteringHidden(hiddenCalendarIDs)
|
||||
|
||||
// Die Liste der wählbaren Kalender nebenbei mitführen — sie ändert
|
||||
// sich, wenn jemand in Kalender einen anlegt oder die Quelle
|
||||
// wechselt.
|
||||
var found: [OnyxCalendar] = []
|
||||
for source in activeSources where source.isAuthorized {
|
||||
found.append(contentsOf: await source.calendars())
|
||||
}
|
||||
availableCalendars = found
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user