feat: poll to refresh

Closes #22
This commit is contained in:
2025-08-29 12:50:33 +02:00
parent 46b9525230
commit 242c3a910b
7 changed files with 231 additions and 36 deletions

View File

@@ -0,0 +1,7 @@
import 'package:flutter/cupertino.dart';
class UpdateNotifier with ChangeNotifier {
void update() {
notifyListeners();
}
}

View File

@@ -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<StatefulWidget> createState() => _HomeGradesScreen();
@@ -28,10 +34,33 @@ class _HomeGradesScreen extends State<HomeGradesScreen> {
ApiResponse<List<Grade>>? grades;
ApiResponse<List<Lesson>>? 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<HomeGradesScreen> {
})();
}
@override
void dispose() {
super.dispose();
widget.updateNotifier.removeListener(updateListener);
}
@override
Widget build(BuildContext context) {
if (grades == null || week == null) {

View File

@@ -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<StatefulWidget> createState() => _HomeGradesSubjectScreen();
@@ -21,10 +26,31 @@ class HomeGradesSubjectScreen extends StatefulWidget {
class _HomeGradesSubjectScreen extends State<HomeGradesSubjectScreen> {
Iterable<Grade>? 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<HomeGradesSubjectScreen> {
})();
}
@override
void dispose() {
super.dispose();
widget.updateNotifier.removeListener(updateListener);
}
@override
Widget build(BuildContext context) {
if (grades != null) {

View File

@@ -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<HomeMainScreen> createState() => _HomeMainScreen();
@@ -29,34 +33,63 @@ class _HomeMainScreen extends State<HomeMainScreen> {
List<Lesson>? 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<Lesson>, 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<HomeMainScreen> {
void dispose() {
super.dispose();
widget.updateNotifier.removeListener(updateListener);
timer?.cancel();
}

View File

@@ -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<HomeTimetableScreen> createState() => _HomeTimetableScreen();
@@ -33,11 +39,12 @@ class _HomeTimetableScreen extends State<HomeTimetableScreen> {
_HomeTimetableScreen();
Future<void> initForWeek(DateTime now) async {
Future<void> 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<DateTime> dates = List.empty(growable: true);
if (lessonsResp.response != null) {
@@ -73,14 +80,39 @@ class _HomeTimetableScreen extends State<HomeTimetableScreen> {
});
}
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) {

View File

@@ -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<HomeTimetableMonthlyScreen> createState() =>
@@ -35,7 +40,7 @@ class _HomeTimetableMonthlyScreen extends State<HomeTimetableMonthlyScreen> {
_HomeTimetableMonthlyScreen();
Future<void> initForMonth(DateTime now) async {
Future<void> 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<HomeTimetableMonthlyScreen> {
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<DateTime> dates = List.empty(growable: true);
for (var i = 0; i < days; i++) {
@@ -65,14 +70,39 @@ class _HomeTimetableMonthlyScreen extends State<HomeTimetableMonthlyScreen> {
}
}
@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) {

View File

@@ -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<HomeScreen> createState() => _HomeScreenState();
@@ -266,9 +269,15 @@ class _HomeScreenState extends State<HomeScreen> {
}
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<HomeScreen> {
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);
}
}
}