claude refactor
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../../../api/mhsl/customTimetableEvent/customTimetableEvent.dart';
|
||||
import '../../../../../api/webuntis/queries/getTimetable/getTimetableResponse.dart';
|
||||
import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc.dart';
|
||||
import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc_event.dart';
|
||||
import '../repository/timetable_repository.dart';
|
||||
import 'timetable_event.dart';
|
||||
import 'timetable_state.dart';
|
||||
|
||||
class TimetableBloc extends LoadableHydratedBloc<TimetableEvent, TimetableState, TimetableRepository> {
|
||||
static const Duration _weekSpan = Duration(days: 7);
|
||||
static final DateFormat _weekKeyFormat = DateFormat('yyyyMMdd');
|
||||
|
||||
DateTime _lastWeekRequestStart = DateTime.fromMillisecondsSinceEpoch(0);
|
||||
|
||||
@override
|
||||
TimetableRepository repository() => TimetableRepository();
|
||||
|
||||
@override
|
||||
TimetableState fromNothing() {
|
||||
final reference = DateTime.now().add(const Duration(days: 2));
|
||||
return TimetableState(
|
||||
startDate: _startOfWeek(reference),
|
||||
endDate: _endOfWeek(reference),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
TimetableState fromStorage(Map<String, dynamic> json) => TimetableState.fromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic>? toStorage(TimetableState state) => state.toJson();
|
||||
|
||||
@override
|
||||
Future<void> gatherData() async {
|
||||
final initial = innerState ?? fromNothing();
|
||||
await Future.wait([
|
||||
_loadCurrentWeek(initial.startDate, initial.endDate),
|
||||
_loadStaticReferenceData(),
|
||||
_loadCustomEvents(),
|
||||
]);
|
||||
_prefetchAdjacentWeeks(initial.startDate, initial.endDate);
|
||||
}
|
||||
|
||||
void changeWeek(DateTime startDate, DateTime endDate) {
|
||||
final current = innerState ?? fromNothing();
|
||||
if (current.startDate == startDate && current.endDate == endDate) return;
|
||||
add(Emit((s) => s.copyWith(startDate: startDate, endDate: endDate)));
|
||||
_loadCurrentWeek(startDate, endDate);
|
||||
_prefetchAdjacentWeeks(startDate, endDate);
|
||||
}
|
||||
|
||||
void resetWeek() {
|
||||
final reference = DateTime.now().add(const Duration(days: 2));
|
||||
changeWeek(_startOfWeek(reference), _endOfWeek(reference));
|
||||
}
|
||||
|
||||
void refresh() => fetch();
|
||||
|
||||
Future<void> addCustomEvent(CustomTimetableEvent event) async {
|
||||
await repo.data.addCustomEvent(event);
|
||||
await _refreshCustomEvents();
|
||||
}
|
||||
|
||||
Future<void> updateCustomEvent(String id, CustomTimetableEvent event) async {
|
||||
await repo.data.updateCustomEvent(id, event);
|
||||
await _refreshCustomEvents();
|
||||
}
|
||||
|
||||
Future<void> removeCustomEvent(String id) async {
|
||||
await repo.data.removeCustomEvent(id);
|
||||
await _refreshCustomEvents();
|
||||
}
|
||||
|
||||
Future<void> _loadCurrentWeek(DateTime startDate, DateTime endDate) async {
|
||||
final requestStart = DateTime.now();
|
||||
_lastWeekRequestStart = requestStart;
|
||||
try {
|
||||
final week = await repo.data.getWeek(startDate, endDate);
|
||||
if (_lastWeekRequestStart.isAfter(requestStart)) return;
|
||||
_writeWeekToCache(startDate, week);
|
||||
} catch (_) {
|
||||
// Errors are surfaced via LoadableHydratedBloc.fetch's catchError.
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadStaticReferenceData() async {
|
||||
final (rooms, subjects, schoolHolidays) = await (
|
||||
repo.data.getRooms(),
|
||||
repo.data.getSubjects(),
|
||||
repo.data.getSchoolHolidays(),
|
||||
).wait;
|
||||
|
||||
add(DataGathered((s) => s.copyWith(
|
||||
rooms: rooms,
|
||||
subjects: subjects,
|
||||
schoolHolidays: schoolHolidays,
|
||||
dataVersion: s.dataVersion + 1,
|
||||
)));
|
||||
}
|
||||
|
||||
Future<void> _loadCustomEvents({bool renew = false}) async {
|
||||
final events = await repo.data.getCustomEvents(renew: renew);
|
||||
add(DataGathered((s) => s.copyWith(customEvents: events, dataVersion: s.dataVersion + 1)));
|
||||
}
|
||||
|
||||
Future<void> _refreshCustomEvents() => _loadCustomEvents(renew: true);
|
||||
|
||||
void _prefetchAdjacentWeeks(DateTime start, DateTime end) {
|
||||
_prefetchWeek(start.subtract(_weekSpan), end.subtract(_weekSpan));
|
||||
_prefetchWeek(start.add(_weekSpan), end.add(_weekSpan));
|
||||
}
|
||||
|
||||
void _prefetchWeek(DateTime start, DateTime end) {
|
||||
repo.data.getWeek(start, end).then((week) => _writeWeekToCache(start, week)).catchError((_) {});
|
||||
}
|
||||
|
||||
void _writeWeekToCache(DateTime weekStart, GetTimetableResponse week) {
|
||||
final key = _weekKeyFormat.format(weekStart);
|
||||
add(DataGathered((s) {
|
||||
final updated = Map<String, GetTimetableResponse>.of(s.weekCache);
|
||||
updated[key] = week;
|
||||
return s.copyWith(weekCache: updated, dataVersion: s.dataVersion + 1);
|
||||
}));
|
||||
}
|
||||
|
||||
static DateTime _startOfWeek(DateTime reference) {
|
||||
final monday = reference.subtract(Duration(days: reference.weekday - 1));
|
||||
return DateTime(monday.year, monday.month, monday.day);
|
||||
}
|
||||
|
||||
static DateTime _endOfWeek(DateTime reference) {
|
||||
final friday = reference.add(Duration(days: DateTime.daysPerWeek - reference.weekday - 2));
|
||||
return DateTime(friday.year, friday.month, friday.day);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user