simplified code across the app and consolidated duplicated helpers

This commit is contained in:
2026-09-27 17:29:54 +02:00
parent 3e856d0b1c
commit ee1240f71a
155 changed files with 1772 additions and 2546 deletions
+92 -62
View File
@@ -53,6 +53,42 @@ class WidgetDataMapper {
/// native renderers can roll the view forward without fresh data.
static const int weekWindowDays = 14;
/// Day and week payload from the same inputs.
static ({WidgetTimetableData day, WidgetTimetableData week}) buildSnapshot({
required DateTime now,
required Iterable<McTimetableEntry> lessons,
required TimetableGetSubjectsResponse? subjects,
required TimetableGetRoomsResponse? rooms,
required TimetableGetHolidaysResponse? holidays,
TimetableGetTimegridResponse? timegrid,
GetCustomTimetableEventResponse? customEvents,
bool connectDoubleLessons = true,
bool showClassInsteadOfTeacher = false,
}) => (
day: buildDayData(
now: now,
lessons: lessons,
subjects: subjects,
rooms: rooms,
holidays: holidays,
timegrid: timegrid,
customEvents: customEvents,
connectDoubleLessons: connectDoubleLessons,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
week: buildWeekData(
now: now,
lessons: lessons,
subjects: subjects,
rooms: rooms,
holidays: holidays,
timegrid: timegrid,
customEvents: customEvents,
connectDoubleLessons: connectDoubleLessons,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
);
static WidgetTimetableData buildDayData({
required DateTime now,
required Iterable<McTimetableEntry> lessons,
@@ -68,24 +104,23 @@ class WidgetDataMapper {
final holiday = _findHoliday(anchor, holidays);
final dayStart = anchor;
final dayEnd = anchor.add(const Duration(days: 1));
final dayLessons = lessons.where((l) => _onSameDay(l, anchor)).toList();
final dayLessons = lessons.where((l) => l.date.isSameDay(anchor)).toList();
final source = connectDoubleLessons
? LessonMerger.merge(dayLessons)
: dayLessons;
final mapped = <WidgetLesson>[
..._mapAll(
return WidgetTimetableData(
fetchedAt: now,
anchorDate: anchor,
lessons: _mapWindow(
source,
now,
subjects,
rooms,
customEvents,
dayStart,
dayEnd,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
..._expandCustomEvents(customEvents, dayStart, dayEnd),
]..sort((a, b) => a.start.compareTo(b.start));
return WidgetTimetableData(
fetchedAt: now,
anchorDate: anchor,
lessons: _resolveCollisions(mapped),
periods: _resolvePeriods(timegrid),
isHoliday: holiday != null,
holidayName: holiday?.longName,
@@ -118,16 +153,6 @@ class WidgetDataMapper {
final source = connectDoubleLessons
? _mergePerDay(weekLessons)
: weekLessons;
final mapped = <WidgetLesson>[
..._mapAll(
source,
now,
subjects,
rooms,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
..._expandCustomEvents(customEvents, windowStart, endExclusive),
]..sort((a, b) => a.start.compareTo(b.start));
final days = [
for (var i = 0; i < weekWindowDays; i++)
_dayInfo(windowStart.addDays(i), holidays),
@@ -141,7 +166,16 @@ class WidgetDataMapper {
return WidgetTimetableData(
fetchedAt: now,
anchorDate: anchor,
lessons: _resolveCollisions(mapped),
lessons: _mapWindow(
source,
now,
subjects,
rooms,
customEvents,
windowStart,
endExclusive,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
periods: _resolvePeriods(timegrid),
isHoliday: anchorInfo.isHoliday,
holidayName: anchorInfo.holidayName,
@@ -300,28 +334,38 @@ class WidgetDataMapper {
return [for (final group in byDay.values) ...LessonMerger.merge(group)];
}
static Iterable<WidgetLesson> _mapAll(
/// Lessons plus custom events in [start, endExclusive), sorted by start
/// with overlaps resolved.
static List<WidgetLesson> _mapWindow(
Iterable<McTimetableEntry> source,
DateTime now,
TimetableGetSubjectsResponse? subjects,
TimetableGetRoomsResponse? rooms, {
TimetableGetRoomsResponse? rooms,
GetCustomTimetableEventResponse? customEvents,
DateTime start,
DateTime endExclusive, {
required bool showClassInsteadOfTeacher,
}) => source.map(
(l) => _mapLesson(
l,
now,
subjects,
rooms,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
);
}) {
final mapped = <WidgetLesson>[
for (final lesson in source)
_mapLesson(
lesson,
now,
subjects,
rooms,
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
),
..._expandCustomEvents(customEvents, start, endExclusive),
]..sort((a, b) => a.start.compareTo(b.start));
return _resolveCollisions(mapped);
}
static WidgetLesson _mapLesson(
McTimetableEntry lesson,
DateTime now,
TimetableGetSubjectsResponse? subjects,
TimetableGetRoomsResponse? rooms, {
bool showClassInsteadOfTeacher = false,
required bool showClassInsteadOfTeacher,
}) {
final start = lesson.startDateTime;
final end = lesson.endDateTime;
@@ -395,43 +439,29 @@ class WidgetDataMapper {
return '#${rgb.toRadixString(16).padLeft(6, '0').toUpperCase()}';
}
static WidgetLessonStatus _mapStatus(LessonStatus status) {
switch (status) {
case LessonStatus.cancelled:
return WidgetLessonStatus.cancelled;
case LessonStatus.event:
return WidgetLessonStatus.event;
case LessonStatus.irregular:
return WidgetLessonStatus.irregular;
case LessonStatus.teacherChanged:
return WidgetLessonStatus.teacherChanged;
case LessonStatus.duty:
return WidgetLessonStatus.duty;
case LessonStatus.past:
return WidgetLessonStatus.past;
case LessonStatus.ongoing:
return WidgetLessonStatus.ongoing;
case LessonStatus.regular:
return WidgetLessonStatus.regular;
}
}
static bool _onSameDay(McTimetableEntry lesson, DateTime day) {
return lesson.date.year == day.year &&
lesson.date.month == day.month &&
lesson.date.day == day.day;
}
static WidgetLessonStatus _mapStatus(LessonStatus status) =>
switch (status) {
LessonStatus.cancelled => WidgetLessonStatus.cancelled,
LessonStatus.event => WidgetLessonStatus.event,
LessonStatus.irregular => WidgetLessonStatus.irregular,
LessonStatus.teacherChanged => WidgetLessonStatus.teacherChanged,
LessonStatus.duty => WidgetLessonStatus.duty,
LessonStatus.past => WidgetLessonStatus.past,
LessonStatus.ongoing => WidgetLessonStatus.ongoing,
LessonStatus.regular => WidgetLessonStatus.regular,
};
static McHoliday? _findHoliday(
DateTime day,
TimetableGetHolidaysResponse? holidays,
) {
if (holidays == null) return null;
final asDay = DateTime(day.year, day.month, day.day);
final asDay = day.dateOnly;
for (final h in holidays.result) {
final start = DateTime(h.startDate.year, h.startDate.month, h.startDate.day);
final end = DateTime(h.endDate.year, h.endDate.month, h.endDate.day);
if (!asDay.isBefore(start) && !asDay.isAfter(end)) return h;
if (!asDay.isBefore(h.startDate.dateOnly) &&
!asDay.isAfter(h.endDate.dateOnly)) {
return h;
}
}
return null;
}