46 lines
1.7 KiB
Dart
46 lines
1.7 KiB
Dart
import 'package:collection/collection.dart';
|
|
|
|
import '../../../../../api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart';
|
|
import '../../../../../extensions/date_time.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 = 4;
|
|
|
|
/// 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 (existing != null &&
|
|
const DeepCollectionEquality().equals(existing.toJson(), week.toJson())) {
|
|
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;
|
|
}
|