fix: Gruppenansicht – Termine über Cache/Prefetch laden (kein Range-Gap)
Der Gruppen-Modus ersetzte events nur mit dem schmalen aktuellen Fetch, statt denselben Cache/Prefetch-Pfad wie die Normalansicht zu nutzen -> Termine erschienen erst nach Scrollen. Jetzt fetchForMode (personal/group) läuft durch loadEvents + prefetchBackground + refreshFromCache; Moduswechsel lädt breit neu. In der Gruppenansicht greift der "ausgeblendet"-Filter nicht. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -219,6 +219,12 @@ class CalendarStore {
|
|||||||
/// `start` / `end` are kept in the signature for call-site clarity.
|
/// `start` / `end` are kept in the signature for call-site clarity.
|
||||||
func refreshFromCache(start: Date, end: Date) {
|
func refreshFromCache(start: Date, end: Date) {
|
||||||
_ = (start, end)
|
_ = (start, end)
|
||||||
|
// In group overlay mode show everything (the per-calendar hide/banish
|
||||||
|
// toggles are for the personal view only).
|
||||||
|
if activeGroup != nil {
|
||||||
|
events = allCachedEvents
|
||||||
|
return
|
||||||
|
}
|
||||||
events = allCachedEvents.filter { ev in
|
events = allCachedEvents.filter { ev in
|
||||||
let key = Self.calendarKey(source: ev.source, calendarId: ev.calendarId)
|
let key = Self.calendarKey(source: ev.source, calendarId: ev.calendarId)
|
||||||
return !hiddenCalendarKeys.contains(key)
|
return !hiddenCalendarKeys.contains(key)
|
||||||
@@ -242,20 +248,6 @@ class CalendarStore {
|
|||||||
/// unless `force` is set (used after create/edit to pull fresh server data
|
/// unless `force` is set (used after create/edit to pull fresh server data
|
||||||
/// for the visible range, bypassing the cache).
|
/// for the visible range, bypassing the cache).
|
||||||
func loadEvents(api: CalendarrAPI, start: Date, end: Date, force: Bool = false) async {
|
func loadEvents(api: CalendarrAPI, start: Date, end: Date, force: Bool = false) async {
|
||||||
// Group overlay mode: always fetch the combined view for the range
|
|
||||||
// (no personal cache), decorating each event with its owner.
|
|
||||||
if let g = activeGroup {
|
|
||||||
isLoading = true
|
|
||||||
lastError = nil
|
|
||||||
defer { isLoading = false }
|
|
||||||
do {
|
|
||||||
let fetched = try await api.fetchGroupCombined(groupId: g.id, start: start, end: end)
|
|
||||||
events = fetched.map { decorateGroupEvent($0) }
|
|
||||||
} catch {
|
|
||||||
lastError = error.localizedDescription
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !force, isCached(start: start, end: end) {
|
if !force, isCached(start: start, end: end) {
|
||||||
refreshFromCache(start: start, end: end)
|
refreshFromCache(start: start, end: end)
|
||||||
return
|
return
|
||||||
@@ -264,7 +256,7 @@ class CalendarStore {
|
|||||||
lastError = nil
|
lastError = nil
|
||||||
defer { isLoading = false }
|
defer { isLoading = false }
|
||||||
do {
|
do {
|
||||||
let fetched = try await api.fetchEvents(start: start, end: end)
|
let fetched = try await fetchForMode(api: api, start: start, end: end)
|
||||||
mergeIntoCache(fetched, rangeStart: start, rangeEnd: end)
|
mergeIntoCache(fetched, rangeStart: start, rangeEnd: end)
|
||||||
refreshFromCache(start: start, end: end)
|
refreshFromCache(start: start, end: end)
|
||||||
} catch {
|
} catch {
|
||||||
@@ -272,6 +264,17 @@ class CalendarStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetch events for the current mode (personal vs. group overlay). Group
|
||||||
|
/// events go through the same cache/prefetch/refresh path as personal ones,
|
||||||
|
/// so the whole visible grid is covered (no "only the middle weeks" gaps).
|
||||||
|
private func fetchForMode(api: CalendarrAPI, start: Date, end: Date) async throws -> [CalEvent] {
|
||||||
|
if let g = activeGroup {
|
||||||
|
let combined = try await api.fetchGroupCombined(groupId: g.id, start: start, end: end)
|
||||||
|
return combined.map { decorateGroupEvent($0) }
|
||||||
|
}
|
||||||
|
return try await api.fetchEvents(start: start, end: end)
|
||||||
|
}
|
||||||
|
|
||||||
/// Prefix a combined-view event with its owner (others) or 👥 + creator
|
/// Prefix a combined-view event with its owner (others) or 👥 + creator
|
||||||
/// (group calendar). Colour comes from the server's display_color.
|
/// (group calendar). Colour comes from the server's display_color.
|
||||||
private func decorateGroupEvent(_ ev: CalEvent) -> CalEvent {
|
private func decorateGroupEvent(_ ev: CalEvent) -> CalEvent {
|
||||||
@@ -298,7 +301,7 @@ class CalendarStore {
|
|||||||
isCachingBackground = true
|
isCachingBackground = true
|
||||||
defer { isCachingBackground = false }
|
defer { isCachingBackground = false }
|
||||||
do {
|
do {
|
||||||
let fetched = try await api.fetchEvents(start: start, end: end)
|
let fetched = try await fetchForMode(api: api, start: start, end: end)
|
||||||
mergeIntoCache(fetched, rangeStart: start, rangeEnd: end)
|
mergeIntoCache(fetched, rangeStart: start, rangeEnd: end)
|
||||||
// Refresh visible range from newly expanded cache
|
// Refresh visible range from newly expanded cache
|
||||||
let (vs, ve) = rangeForCurrentView()
|
let (vs, ve) = rangeForCurrentView()
|
||||||
|
|||||||
@@ -251,7 +251,9 @@ struct CalendarHostView: View {
|
|||||||
|
|
||||||
private func switchGroup(_ g: CalGroup?) {
|
private func switchGroup(_ g: CalGroup?) {
|
||||||
store.activeGroup = g
|
store.activeGroup = g
|
||||||
Task { await onNavigate() }
|
// The cache holds the previous mode's events — drop it and reload the
|
||||||
|
// visible range + prefetch a wide window so the whole grid is covered.
|
||||||
|
Task { await forceReload() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private var viewPickerMenu: some View {
|
private var viewPickerMenu: some View {
|
||||||
|
|||||||
Reference in New Issue
Block a user