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:
@@ -195,9 +195,7 @@ struct AccountsView: View {
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button(L10n.t("accounts.banished_unhide", appLang)) {
|
||||
banishedKeys.remove(key)
|
||||
CalendarStore.saveBanishedKeys(banishedKeys)
|
||||
NotificationCenter.default.post(name: .banishedCalendarsChanged, object: nil)
|
||||
unbanish(key)
|
||||
}
|
||||
.font(.callout)
|
||||
.foregroundStyle(Color.accentColor)
|
||||
@@ -208,6 +206,25 @@ struct AccountsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-show a banished calendar. For server-backed sources this clears the
|
||||
/// server's sidebar_hidden (re-enabling the calendar); for local/ical it's
|
||||
/// just the local set.
|
||||
private func unbanish(_ key: String) {
|
||||
banishedKeys.remove(key)
|
||||
CalendarStore.saveBanishedKeys(banishedKeys)
|
||||
NotificationCenter.default.post(name: .banishedCalendarsChanged, object: nil)
|
||||
if let parsed = CalendarStore.parseCalendarKey(key),
|
||||
CalendarStore.serverManagedSources.contains(parsed.source) {
|
||||
// The server excluded this calendar's events while hidden, so they
|
||||
// aren't in the cache. Re-enable on the server, then force a refetch
|
||||
// so the events actually reappear without a manual sync.
|
||||
Task {
|
||||
try? await api.setCalendarSidebarHidden(source: parsed.source, calendarId: parsed.id, hidden: false)
|
||||
NotificationCenter.default.post(name: .manualSyncRequested, object: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func resolveBanished(_ key: String) -> (name: String, colorHex: String) {
|
||||
let parts = key.split(separator: ":", maxSplits: 1).map(String.init)
|
||||
guard parts.count == 2, let id = Int(parts[1]) else {
|
||||
@@ -282,6 +299,22 @@ struct AccountsView: View {
|
||||
async let g = (try? await api.getGoogleAccounts()) ?? []
|
||||
async let h = (try? await api.getHomeAssistantAccounts()) ?? []
|
||||
(caldavAccounts, localCalendars, icalSubs, googleAccounts, haAccounts) = await (c, l, i, g, h)
|
||||
|
||||
// Reconcile banished list with the server's sidebar_hidden (server wins
|
||||
// for CalDAV/Google/HA; local/ical keep their local state).
|
||||
var b = banishedKeys
|
||||
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) } }
|
||||
if b != banishedKeys {
|
||||
banishedKeys = b
|
||||
CalendarStore.saveBanishedKeys(b)
|
||||
NotificationCenter.default.post(name: .banishedCalendarsChanged, object: nil)
|
||||
}
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user