From 97d8cab82bf43992da4a56af85b4c0391dcdcc45 Mon Sep 17 00:00:00 2001 From: doodlezucc <electerminator@gmail.com> Date: Wed, 25 Oct 2023 09:03:17 +0200 Subject: [PATCH] make context profile listenable --- lib/context.dart | 4 ++-- lib/drawer/class_list_item.dart | 3 ++- lib/drawer/lecture_list_item.dart | 3 ++- lib/main.dart | 35 ++++++++++++++++--------------- lib/timetable/lesson_dialog.dart | 6 +++--- lib/timetable/timetable.dart | 25 +++++++++++++--------- lib/util/listenable.dart | 5 +++++ 7 files changed, 47 insertions(+), 34 deletions(-) diff --git a/lib/context.dart b/lib/context.dart index 19feb26..0240ceb 100644 --- a/lib/context.dart +++ b/lib/context.dart @@ -6,10 +6,10 @@ import 'util/listenable.dart'; class AppContext { final UntisFetch untis; - Profile? profile; + final Listenable<Profile?> profile = Listenable(null); List<Class>? classes; List<Lecture>? lectures; - Listenable<DateTime> date = Listenable(DateTime.now()); + final Listenable<DateTime> date = Listenable(DateTime.now()); AppContext(this.untis); } diff --git a/lib/drawer/class_list_item.dart b/lib/drawer/class_list_item.dart index b979106..d27d5fb 100644 --- a/lib/drawer/class_list_item.dart +++ b/lib/drawer/class_list_item.dart @@ -21,7 +21,8 @@ class ClassListItem extends StatefulWidget { } class _ClassListItemState extends State<ClassListItem> { - Set<int> get selectedClasses => widget.appContext.profile!.selectedClasses; + Set<int> get selectedClasses => + widget.appContext.profile.value!.selectedClasses; bool get isSelected => selectedClasses.contains(widget.cls.id); List<Lecture>? get lectures => widget.appContext.lectures == null diff --git a/lib/drawer/lecture_list_item.dart b/lib/drawer/lecture_list_item.dart index 2e0fea3..ed47fb4 100644 --- a/lib/drawer/lecture_list_item.dart +++ b/lib/drawer/lecture_list_item.dart @@ -20,7 +20,8 @@ class LectureListItem extends StatefulWidget { } class _LectureListItemState extends State<LectureListItem> { - Set<int> get hiddenLectures => widget.appContext.profile!.hiddenLectures; + Set<int> get hiddenLectures => + widget.appContext.profile.value!.hiddenLectures; bool get isVisible => !hiddenLectures.contains(widget.lecture.id); diff --git a/lib/main.dart b/lib/main.dart index 89a72cf..8ae8389 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'toolbar/toolbar.dart'; import 'untis/fetch.dart'; import 'untis/timetable.dart'; import 'user/profile.dart'; +import 'util/listenable.dart'; void main() { runApp(const MyApp()); @@ -59,7 +60,7 @@ class _MyHomePageState extends State<MyHomePage> { final profile = Profile(selectedClasses: {19997, 20000}); final classes = await untis.allClasses.fetched; - appContext.profile = profile; + appContext.profile.value = profile; appContext.classes = classes; fetchTimetable(); @@ -73,24 +74,26 @@ class _MyHomePageState extends State<MyHomePage> { Future<void> fetchTimetable() async { final date = appContext.date.value; - TimetableData? mergedTimetable; - final selectedClasses = appContext.profile!.selectedClasses; + timetable = null; + setState(() {}); + + final profile = await appContext.profile.firstNotNull; + final selectedClasses = profile.selectedClasses; final allTimetables = await Future.wait(selectedClasses.map((classid) { return Future(() => untis.timetableOf(classid, date).fetched); })); - for (var fetched in allTimetables) { - if (mergedTimetable == null) { - mergedTimetable = fetched; + for (final fetched in allTimetables) { + if (timetable == null) { + timetable = fetched; } else { - mergedTimetable = TimetableData.merge(mergedTimetable, fetched); + timetable = TimetableData.merge(timetable!, fetched); } - } - timetable = mergedTimetable; - setState(() {}); + setState(() {}); + } } @override @@ -99,19 +102,17 @@ class _MyHomePageState extends State<MyHomePage> { appBar: AppBar( title: const Text(appName), ), - drawer: appContext.profile == null + drawer: appContext.profile.value == null ? null : ClassDrawer(appContext: appContext), body: Column( children: [ Toolbar(appContext: appContext), Expanded( - child: timetable != null && appContext.profile != null - ? Timetable( - data: timetable!, - appContext: appContext, - ) - : Container(), + child: Timetable( + data: timetable, + appContext: appContext, + ), ), ], ), diff --git a/lib/timetable/lesson_dialog.dart b/lib/timetable/lesson_dialog.dart index c44b1f2..8e3dd0c 100644 --- a/lib/timetable/lesson_dialog.dart +++ b/lib/timetable/lesson_dialog.dart @@ -19,10 +19,10 @@ class LessonDialog extends StatefulWidget { class _LessonDialogState extends State<LessonDialog> { bool get lectureVisible => - !widget.appContext.profile!.hiddenLectures.contains(lectureId); + !widget.appContext.profile.value!.hiddenLectures.contains(lectureId); set lectureVisible(bool value) { - setState(() => - widget.appContext.profile!.hiddenLectures.toggle(lectureId, !value)); + setState(() => widget.appContext.profile.value!.hiddenLectures + .toggle(lectureId, !value)); } Lesson get lesson => widget.lesson; diff --git a/lib/timetable/timetable.dart b/lib/timetable/timetable.dart index 14410c1..1e87eb9 100644 --- a/lib/timetable/timetable.dart +++ b/lib/timetable/timetable.dart @@ -7,6 +7,7 @@ import '../untis/lecture.dart'; import '../untis/lesson.dart'; import '../untis/period.dart'; import '../untis/timetable.dart'; +import '../util/listenable.dart'; import 'period_background.dart'; import 'weekday_content.dart'; import 'weekday_header.dart'; @@ -14,7 +15,7 @@ import 'weekday_header.dart'; class Timetable extends StatefulWidget { static const weekdayCount = 5; static const mergeDistanceInMinutes = 30; - final TimetableData data; + final TimetableData? data; final AppContext appContext; const Timetable({ @@ -28,31 +29,36 @@ class Timetable extends StatefulWidget { } class _TimetableState extends State<Timetable> { - late StreamSubscription _subscription; + StreamSubscription? _subscription; @override void initState() { super.initState(); - final profile = widget.appContext.profile!; - _subscription = - profile.hiddenLectures.onChange.listen((_) => setState(() {})); + widget.appContext.profile.firstNotNull.then((profile) { + _subscription = + profile.hiddenLectures.onChange.listen((_) => setState(() {})); + }); } @override void dispose() { - _subscription.cancel(); + _subscription?.cancel(); super.dispose(); } List<UntisLesson> _getLessonsOfDay(int index) { - return widget.data.lessons + return (widget.data?.lessons ?? <UntisLesson>{}) .where((lesson) => lesson.weekdayIndex == index) .toList(); } List<Lesson> getMergedLessonsOfDay(int index) { - return mergeLessons(_getLessonsOfDay(index)); + final profile = widget.appContext.profile.value; + + return profile == null + ? [] + : mergeLessons(_getLessonsOfDay(index), profile.hiddenLectures); } @override @@ -113,8 +119,7 @@ class _TimetableState extends State<Timetable> { ); } - List<Lesson> mergeLessons(List<UntisLesson> lessons) { - final hiddenIds = widget.appContext.profile!.hiddenLectures; + List<Lesson> mergeLessons(List<UntisLesson> lessons, Set<int> hiddenIds) { final uniqueLectures = <Lecture, List<Lesson>>{}; for (final lesson in lessons) { diff --git a/lib/util/listenable.dart b/lib/util/listenable.dart index 5e9c120..4ed2674 100644 --- a/lib/util/listenable.dart +++ b/lib/util/listenable.dart @@ -13,3 +13,8 @@ class Listenable<T> { Listenable(T value) : _value = value; } + +extension NullListenable<T> on Listenable<T?> { + Future<T> get firstNotNull async => + value ?? (await onChange.firstWhere((element) => element != null))!; +} -- GitLab