Settings sync, calendar visibility sync, event refresh & week-view fixes
- Add two-way settings sync (SettingsSync) with toggle, app-start/foreground/ 10-min pull and debounced push; server wins; view/week-start/dim-past always sync. Wire previously-ignored settings (hour height, contrasts, week start, default view, dim past) into the actual UI. - Make AppSettings decoding resilient (decodeIfPresent) so getSettings no longer fails on iOS-only fields the server omits; keep text/bg/line colors local-only; month divider/label colors now sync. - Auto-refresh after create/edit (cache-busting) and optimistic removal on delete; switch delete confirm to a centered alert. Add HA event deletion. - Calendar visibility: fix inverted hide/show toggle; normalize calendar keys so local filtering works for all sources; sync banish with server sidebar_hidden (CalDAV/Google/HA), refetch on un-banish. - Manual "sync with server" button in the menu. - Upcoming widget shows next 5 days (renamed). - Week/Day view: route multi-day timed events to the all-day strip so they no longer render as a full-height block. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -136,7 +136,9 @@ struct CalendarFilterSheet: View {
|
||||
let isVisible = !hidden.contains(key)
|
||||
Button {
|
||||
if isVisible { hidden.insert(key) } else { hidden.remove(key) }
|
||||
store.setCalendarHidden(key, hidden: !isVisible)
|
||||
// New hidden state == was-visible (flip). Previous code passed the
|
||||
// inverse, which persisted the opposite of what the UI showed.
|
||||
store.setCalendarHidden(key, hidden: isVisible)
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
Circle()
|
||||
@@ -158,6 +160,7 @@ struct CalendarFilterSheet: View {
|
||||
hidden.remove(key)
|
||||
banished.insert(key)
|
||||
store.setCalendarBanished(key, banished: true)
|
||||
pushBanishToServer(key: key, hidden: true)
|
||||
} label: {
|
||||
Label(L10n.t("filter.banish", appLang), systemImage: "archivebox")
|
||||
}
|
||||
@@ -175,6 +178,19 @@ struct CalendarFilterSheet: View {
|
||||
async let h = (try? await api.getHomeAssistantAccounts()) ?? []
|
||||
(caldavAccounts, localCalendars, icalSubs, googleAccounts, haAccounts) = await (c, l, i, g, h)
|
||||
|
||||
// Reconcile banished state with the server's sidebar_hidden flags
|
||||
// (server wins for CalDAV/Google/HA; local/ical keep their local state).
|
||||
var b = store.banishedCalendarKeys
|
||||
func applyServerHidden(_ source: String, _ id: Int, _ hidden: Bool) {
|
||||
let key = CalendarStore.calendarKey(source: source, calendarId: "\(id)")
|
||||
if hidden { b.insert(key) } else { b.remove(key) }
|
||||
}
|
||||
for acc in caldavAccounts { for cal in acc.calendars ?? [] { applyServerHidden("caldav", cal.id, cal.sidebarHidden) } }
|
||||
for acc in googleAccounts { for cal in acc.calendars ?? [] { applyServerHidden("google", cal.id, cal.sidebarHidden) } }
|
||||
for acc in haAccounts { for cal in acc.calendars ?? [] { applyServerHidden("homeassistant", cal.id, cal.sidebarHidden) } }
|
||||
store.setBanishedCalendars(b)
|
||||
banished = b
|
||||
|
||||
var keys = Set<String>()
|
||||
for cal in localCalendars {
|
||||
keys.insert(CalendarStore.calendarKey(source: "local", calendarId: "\(cal.id)"))
|
||||
@@ -200,4 +216,11 @@ struct CalendarFilterSheet: View {
|
||||
allKeys = keys
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
/// For server-backed sources, persist the banish on the server too.
|
||||
private func pushBanishToServer(key: String, hidden: Bool) {
|
||||
guard let parsed = CalendarStore.parseCalendarKey(key),
|
||||
CalendarStore.serverManagedSources.contains(parsed.source) else { return }
|
||||
Task { try? await api.setCalendarSidebarHidden(source: parsed.source, calendarId: parsed.id, hidden: hidden) }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user