diff --git a/firka/lib/helpers/update_notifier.dart b/firka/lib/helpers/update_notifier.dart new file mode 100644 index 00000000..fd46a460 --- /dev/null +++ b/firka/lib/helpers/update_notifier.dart @@ -0,0 +1,7 @@ +import 'package:flutter/cupertino.dart'; + +class UpdateNotifier with ChangeNotifier { + void update() { + notifyListeners(); + } +} diff --git a/firka/lib/ui/phone/pages/home/home_grades.dart b/firka/lib/ui/phone/pages/home/home_grades.dart index 22fe0a6c..43271487 100644 --- a/firka/lib/ui/phone/pages/home/home_grades.dart +++ b/firka/lib/ui/phone/pages/home/home_grades.dart @@ -10,15 +10,21 @@ import '../../../../helpers/api/model/grade.dart'; import '../../../../helpers/api/model/subject.dart'; import '../../../../helpers/api/model/timetable.dart'; import '../../../../helpers/debug_helper.dart'; +import '../../../../helpers/update_notifier.dart'; import '../../../../main.dart'; import '../../../model/style.dart'; import '../../../widget/delayed_spinner.dart'; class HomeGradesScreen extends StatefulWidget { final AppInitialization data; + final UpdateNotifier updateNotifier; + final UpdateNotifier finishNotifier; + final void Function(ActiveHomePage, bool) cb; - const HomeGradesScreen(this.data, this.cb, {super.key}); + const HomeGradesScreen( + this.data, this.updateNotifier, this.finishNotifier, this.cb, + {super.key}); @override State createState() => _HomeGradesScreen(); @@ -28,10 +34,33 @@ class _HomeGradesScreen extends State { ApiResponse>? grades; ApiResponse>? week; + @override + void didUpdateWidget(HomeGradesScreen oldWidget) { + super.didUpdateWidget(oldWidget); + + widget.updateNotifier.removeListener(updateListener); + widget.updateNotifier.addListener(updateListener); + } + + void updateListener() async { + var now = timeNow(); + var start = now.subtract(Duration(days: now.weekday - 1)); + var end = start.add(Duration(days: 6)); + + grades = await widget.data.client.getGrades(forceCache: false); + week = await widget.data.client.getTimeTable(start, end, forceCache: false); + + if (mounted) setState(() {}); + + widget.finishNotifier.update(); + } + @override void initState() { super.initState(); + widget.updateNotifier.addListener(updateListener); + (() async { var now = timeNow(); var start = now.subtract(Duration(days: now.weekday - 1)); @@ -44,6 +73,12 @@ class _HomeGradesScreen extends State { })(); } + @override + void dispose() { + super.dispose(); + widget.updateNotifier.removeListener(updateListener); + } + @override Widget build(BuildContext context) { if (grades == null || week == null) { diff --git a/firka/lib/ui/phone/pages/home/home_grades_subject.dart b/firka/lib/ui/phone/pages/home/home_grades_subject.dart index 8675ed9a..f23bf744 100644 --- a/firka/lib/ui/phone/pages/home/home_grades_subject.dart +++ b/firka/lib/ui/phone/pages/home/home_grades_subject.dart @@ -4,6 +4,7 @@ import 'package:firka/helpers/ui/firka_card.dart'; import 'package:firka/helpers/ui/grade.dart'; import 'package:flutter/material.dart'; +import '../../../../helpers/update_notifier.dart'; import '../../../../main.dart'; import '../../../model/style.dart'; import '../../../widget/delayed_spinner.dart'; @@ -11,8 +12,12 @@ import '../../../widget/delayed_spinner.dart'; class HomeGradesSubjectScreen extends StatefulWidget { final AppInitialization data; final String subPageUid; + final UpdateNotifier updateNotifier; + final UpdateNotifier finishNotifier; - const HomeGradesSubjectScreen(this.data, this.subPageUid, {super.key}); + const HomeGradesSubjectScreen( + this.data, this.updateNotifier, this.finishNotifier, this.subPageUid, + {super.key}); @override State createState() => _HomeGradesSubjectScreen(); @@ -21,10 +26,31 @@ class HomeGradesSubjectScreen extends StatefulWidget { class _HomeGradesSubjectScreen extends State { Iterable? grades; + @override + void didUpdateWidget(HomeGradesSubjectScreen oldWidget) { + super.didUpdateWidget(oldWidget); + + widget.updateNotifier.removeListener(updateListener); + widget.updateNotifier.addListener(updateListener); + } + + void updateListener() async { + grades = (await widget.data.client.getGrades(forceCache: false)) + .response! + .where((grade) => grade.subject.uid == widget.subPageUid) + .where((grade) => grade.type.name != "felevi_jegy_ertekeles"); + + if (mounted) setState(() {}); + + widget.finishNotifier.update(); + } + @override void initState() { super.initState(); + widget.updateNotifier.addListener(updateListener); + (() async { grades = (await widget.data.client.getGrades()) .response! @@ -35,6 +61,12 @@ class _HomeGradesSubjectScreen extends State { })(); } + @override + void dispose() { + super.dispose(); + widget.updateNotifier.removeListener(updateListener); + } + @override Widget build(BuildContext context) { if (grades != null) { diff --git a/firka/lib/ui/phone/pages/home/home_main.dart b/firka/lib/ui/phone/pages/home/home_main.dart index b62455a8..fe67e384 100644 --- a/firka/lib/ui/phone/pages/home/home_main.dart +++ b/firka/lib/ui/phone/pages/home/home_main.dart @@ -9,14 +9,18 @@ import 'package:flutter/material.dart'; import '../../../../helpers/api/model/student.dart'; import '../../../../helpers/api/model/timetable.dart'; import '../../../../helpers/debug_helper.dart'; +import '../../../../helpers/update_notifier.dart'; import '../../../../main.dart'; import '../../widgets/home_main_welcome.dart'; import '../../widgets/lesson_big.dart'; class HomeMainScreen extends StatefulWidget { final AppInitialization data; + final UpdateNotifier updateNotifier; + final UpdateNotifier finishNotifier; - const HomeMainScreen(this.data, {super.key}); + const HomeMainScreen(this.data, this.updateNotifier, this.finishNotifier, + {super.key}); @override State createState() => _HomeMainScreen(); @@ -29,34 +33,63 @@ class _HomeMainScreen extends State { List? lessons; Student? student; Timer? timer; - bool disposed = false; + + @override + void didUpdateWidget(HomeMainScreen oldWidget) { + super.didUpdateWidget(oldWidget); + + widget.updateNotifier.removeListener(updateListener); + widget.updateNotifier.addListener(updateListener); + } + + void updateListener() async { + final newData = await loadData(now, forceCache: false); + + if (mounted) { + setState(() { + lessons = newData.$1; + student = newData.$2; + }); + } + widget.finishNotifier.update(); + } + + Future<(List, Student)> loadData(DateTime now, + {bool forceCache = true}) async { + var midnight = now.getMidnight(); + + var respTT = await widget.data.client.getTimeTable( + midnight, midnight.add(Duration(hours: 23, minutes: 59)), + forceCache: forceCache); + + var respStudent = + await widget.data.client.getStudent(forceCache: forceCache); + + return Future.value((respTT.response!, respStudent.response!)); + } @override void initState() { super.initState(); + widget.updateNotifier.addListener(updateListener); + now = timeNow(); - var midnight = now.getMidnight(); - (() async { - var resp = await widget.data.client.getTimeTable( - midnight, midnight.add(Duration(hours: 23, minutes: 59))); + if (!mounted) return; - if (disposed) return; - setState(() { - lessons = resp.response!; - }); - })(); (() async { - var resp = await widget.data.client.getStudent(); + final newData = await loadData(now); - if (disposed) return; - setState(() { - student = resp.response!; - }); + if (mounted) { + setState(() { + lessons = newData.$1; + student = newData.$2; + }); + } })(); timer = Timer.periodic(Duration(seconds: 1), (timer) async { - if (disposed) return; + if (!mounted) return; setState(() { now = timeNow(); }); @@ -67,6 +100,8 @@ class _HomeMainScreen extends State { void dispose() { super.dispose(); + widget.updateNotifier.removeListener(updateListener); + timer?.cancel(); } diff --git a/firka/lib/ui/phone/pages/home/home_timetable.dart b/firka/lib/ui/phone/pages/home/home_timetable.dart index 34ab5ea1..875b9290 100644 --- a/firka/lib/ui/phone/pages/home/home_timetable.dart +++ b/firka/lib/ui/phone/pages/home/home_timetable.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import 'package:majesticons_flutter/majesticons_flutter.dart'; import 'package:transparent_pointer/transparent_pointer.dart'; +import '../../../../helpers/update_notifier.dart'; import '../../../../main.dart'; import '../../../widget/firka_icon.dart'; import '../../screens/home/home_screen.dart'; @@ -16,9 +17,14 @@ import '../../widgets/tt_day.dart'; class HomeTimetableScreen extends StatefulWidget { final AppInitialization data; + final UpdateNotifier updateNotifier; + final UpdateNotifier finishNotifier; + final void Function(ActiveHomePage, bool) cb; - const HomeTimetableScreen(this.data, this.cb, {super.key}); + const HomeTimetableScreen( + this.data, this.updateNotifier, this.finishNotifier, this.cb, + {super.key}); @override State createState() => _HomeTimetableScreen(); @@ -33,11 +39,12 @@ class _HomeTimetableScreen extends State { _HomeTimetableScreen(); - Future initForWeek(DateTime now) async { + Future initForWeek(DateTime now, {bool forceCache = true}) async { var monday = now.getMonday().getMidnight(); var sunday = monday.add(Duration(days: 6)); - var lessonsResp = await widget.data.client.getTimeTable(monday, sunday); + var lessonsResp = await widget.data.client + .getTimeTable(monday, sunday, forceCache: forceCache); List dates = List.empty(growable: true); if (lessonsResp.response != null) { @@ -73,14 +80,39 @@ class _HomeTimetableScreen extends State { }); } + void updateListener() async { + if (now != null) { + await initForWeek(now!, forceCache: false); + setState(() {}); + } + widget.finishNotifier.update(); + } + + @override + void didUpdateWidget(HomeTimetableScreen oldWidget) { + super.didUpdateWidget(oldWidget); + + widget.updateNotifier.removeListener(updateListener); + widget.updateNotifier.addListener(updateListener); + } + @override void initState() { super.initState(); + widget.updateNotifier.addListener(updateListener); + now = timeNow(); initForWeek(now!); } + @override + void dispose() { + super.dispose(); + + widget.updateNotifier.removeListener(updateListener); + } + @override Widget build(BuildContext context) { if (lessons != null && dates != null) { diff --git a/firka/lib/ui/phone/pages/home/home_timetable_mo.dart b/firka/lib/ui/phone/pages/home/home_timetable_mo.dart index 02d01956..df210c98 100644 --- a/firka/lib/ui/phone/pages/home/home_timetable_mo.dart +++ b/firka/lib/ui/phone/pages/home/home_timetable_mo.dart @@ -9,15 +9,20 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:majesticons_flutter/majesticons_flutter.dart'; import 'package:transparent_pointer/transparent_pointer.dart'; +import '../../../../helpers/update_notifier.dart'; import '../../../../main.dart'; import '../../../widget/firka_icon.dart'; import '../../screens/home/home_screen.dart'; class HomeTimetableMonthlyScreen extends StatefulWidget { final AppInitialization data; + final UpdateNotifier updateNotifier; + final UpdateNotifier finishNotifier; final void Function(ActiveHomePage, bool) cb; - const HomeTimetableMonthlyScreen(this.data, this.cb, {super.key}); + const HomeTimetableMonthlyScreen( + this.data, this.updateNotifier, this.finishNotifier, this.cb, + {super.key}); @override State createState() => @@ -35,7 +40,7 @@ class _HomeTimetableMonthlyScreen extends State { _HomeTimetableMonthlyScreen(); - Future initForMonth(DateTime now) async { + Future initForMonth(DateTime now, {bool forceCache = true}) async { final monthStart = DateTime.utc(now.year, now.month, 1); final monthEnd = DateTime.utc(now.year, now.month + 1).subtract(Duration(days: 1)); @@ -46,8 +51,8 @@ class _HomeTimetableMonthlyScreen extends State { var days = end.difference(start).inDays; - var lessonsResp = - await widget.data.client.getTimeTable(monthStart, monthEnd); + var lessonsResp = await widget.data.client + .getTimeTable(monthStart, monthEnd, forceCache: forceCache); List dates = List.empty(growable: true); for (var i = 0; i < days; i++) { @@ -65,14 +70,39 @@ class _HomeTimetableMonthlyScreen extends State { } } + @override + void didUpdateWidget(HomeTimetableMonthlyScreen oldWidget) { + super.didUpdateWidget(oldWidget); + + widget.updateNotifier.removeListener(updateListener); + widget.updateNotifier.addListener(updateListener); + } + + void updateListener() async { + if (now != null) { + await initForMonth(now!, forceCache: false); + setState(() {}); + } + widget.finishNotifier.update(); + } + @override void initState() { super.initState(); + widget.updateNotifier.addListener(updateListener); + now = timeNow(); initForMonth(now!); } + @override + void dispose() { + super.dispose(); + + widget.updateNotifier.removeListener(updateListener); + } + @override Widget build(BuildContext context) { if (lessons != null && dates != null) { diff --git a/firka/lib/ui/phone/screens/home/home_screen.dart b/firka/lib/ui/phone/screens/home/home_screen.dart index ab38dd71..1ed1d466 100644 --- a/firka/lib/ui/phone/screens/home/home_screen.dart +++ b/firka/lib/ui/phone/screens/home/home_screen.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:firka/helpers/api/client/kreta_client.dart'; import 'package:firka/helpers/api/exceptions/token.dart'; import 'package:firka/helpers/settings/setting.dart'; +import 'package:firka/helpers/update_notifier.dart'; import 'package:firka/main.dart'; import 'package:firka/ui/model/style.dart'; import 'package:firka/ui/phone/pages/extras/main_wear_pair.dart'; @@ -32,8 +33,10 @@ class HomeScreen extends StatefulWidget { final AppInitialization data; final bool watchPair; final String? model; + final UpdateNotifier updateNotifier = UpdateNotifier(); + final UpdateNotifier updateFinishedNotifier = UpdateNotifier(); - const HomeScreen(this.data, this.watchPair, {this.model, super.key}); + HomeScreen(this.data, this.watchPair, {this.model, super.key}); @override State createState() => _HomeScreenState(); @@ -266,9 +269,15 @@ class _HomeScreenState extends State { } void _onRefresh() async { - await Future.delayed(Duration(milliseconds: 1000)); + late void Function() finishListener; + finishListener = () { + widget.updateFinishedNotifier.removeListener(finishListener); - _refreshController.refreshCompleted(); + _refreshController.refreshCompleted(); + }; + + widget.updateFinishedNotifier.addListener(finishListener); + widget.updateNotifier.update(); } void _onLoading() async { @@ -364,7 +373,14 @@ class _HomeScreenState extends State { children: [ Row( mainAxisAlignment: MainAxisAlignment.center, - children: [HomeSubPage(page, setPageCB, widget.data)], + children: [ + HomeSubPage( + page, + setPageCB, + widget.data, + widget.updateNotifier, + widget.updateFinishedNotifier) + ], ), Container( decoration: BoxDecoration( @@ -501,24 +517,32 @@ class HomeSubPage extends StatelessWidget { final ActiveHomePage page; final void Function(ActiveHomePage, bool) cb; final AppInitialization data; + final UpdateNotifier _updateNotifier; + final UpdateNotifier _updateFinishNotifier; - const HomeSubPage(this.page, this.cb, this.data, {super.key}); + const HomeSubPage(this.page, this.cb, this.data, this._updateNotifier, + this._updateFinishNotifier, + {super.key}); @override Widget build(BuildContext context) { switch (page.page) { case HomePages.home: - return HomeMainScreen(data); + return HomeMainScreen(data, _updateNotifier, _updateFinishNotifier); case HomePages.grades: if (page.subPageUid != null) { - return HomeGradesSubjectScreen(data, page.subPageUid!); + return HomeGradesSubjectScreen( + data, _updateNotifier, _updateFinishNotifier, page.subPageUid!); } else { - return HomeGradesScreen(data, cb); + return HomeGradesScreen( + data, _updateNotifier, _updateFinishNotifier, cb); } case HomePages.timetable: - return HomeTimetableScreen(data, cb); + return HomeTimetableScreen( + data, _updateNotifier, _updateFinishNotifier, cb); case HomePages.timetableMo: - return HomeTimetableMonthlyScreen(data, cb); + return HomeTimetableMonthlyScreen( + data, _updateNotifier, _updateFinishNotifier, cb); } } }