Files
Client/lib/state/app/modules/timetable/bloc/week_cache.dart
T

42 lines
1.6 KiB
Dart

import '../../../../../api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart';
import '../../../../../extensions/date_time.dart';
import '../../../../../utils/json_equality.dart';
/// Weeks kept around the viewed week and around today's week. Everything
/// further away is dropped: every state emit re-serializes the whole cache for
/// HydratedBloc and the calendar rebuilds its appointments from all of it, so
/// an unbounded cache makes week swipes slower the longer the app is used.
const int kWeekCacheRadius = 8;
/// Returns the cache with [week] stored under [weekStart], pruned to the
/// weeks near [viewedWeekStart] or [now]. Returns null when the stored week
/// already has identical content, so callers can skip the emit entirely.
Map<String, TimetableGetWeekResponse>? mergeWeekIntoCache(
Map<String, TimetableGetWeekResponse> cache,
DateTime weekStart,
TimetableGetWeekResponse week, {
required DateTime viewedWeekStart,
required DateTime now,
}) {
final key = weekStart.weekKey();
final existing = cache[key];
if (sameJson(existing, week)) return null;
final viewedMonday = viewedWeekStart.mondayOfWeek;
final todayMonday = now.mondayOfWeek;
bool isNear(DateTime monday, DateTime anchor) =>
monday.difference(anchor).inDays.abs() <= kWeekCacheRadius * 7 + 1;
final updated = <String, TimetableGetWeekResponse>{};
for (final entry in cache.entries) {
final monday = DateTime.tryParse(entry.key);
if (monday == null ||
isNear(monday, viewedMonday) ||
isNear(monday, todayMonday)) {
updated[entry.key] = entry.value;
}
}
updated[key] = week;
return updated;
}