diff --git a/filcnaplo/lib/api/providers/status_provider.dart b/filcnaplo/lib/api/providers/status_provider.dart index ca4cd5a..5822366 100644 --- a/filcnaplo/lib/api/providers/status_provider.dart +++ b/filcnaplo/lib/api/providers/status_provider.dart @@ -2,7 +2,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/widgets.dart'; import 'package:http/http.dart' as http; -enum Status { network, maintenance, syncing } +enum Status { network, maintenance, syncing, apiError } class StatusProvider extends ChangeNotifier { final List _stack = []; @@ -37,7 +37,8 @@ class StatusProvider extends ChangeNotifier { } void triggerRequest(http.Response res) { - if (res.headers.containsKey("x-maintenance-mode") || res.statusCode == 503) { + if (res.headers.containsKey("x-maintenance-mode") || + res.statusCode == 503) { if (!_stack.contains(Status.maintenance)) { _stack.insert(0, Status.maintenance); notifyListeners(); @@ -48,6 +49,21 @@ class StatusProvider extends ChangeNotifier { notifyListeners(); } } + + if (res.body == "invalid_grant" || + res.body.replaceAll(' ', '') == '' || + res.statusCode == 400) { + if (!_stack.contains(Status.apiError)) { + _stack.insert(0, Status.apiError); + notifyListeners(); + } + } else { + if (_stack.contains(Status.apiError) && + res.request?.url.path != '/nonce') { + _stack.remove(Status.apiError); + notifyListeners(); + } + } } void triggerSync({required int current, required int max}) { diff --git a/filcnaplo_kreta_api/lib/client/client.dart b/filcnaplo_kreta_api/lib/client/client.dart index 5217a76..f150e3b 100644 --- a/filcnaplo_kreta_api/lib/client/client.dart +++ b/filcnaplo_kreta_api/lib/client/client.dart @@ -89,6 +89,9 @@ class KretaClient { } if (res == null) throw "Login error"; + if (res.body == 'invalid_grant' || res.body.replaceAll(' ', '') == '') { + throw "Auth error"; + } if (json) { return jsonDecode(res.body); diff --git a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart index 1e31308..1b9a3ef 100644 --- a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart +++ b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart @@ -67,15 +67,21 @@ class TimetableProvider with ChangeNotifier { String iss = user.instituteCode; List? lessonsJson = await _kreta .getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end)); - if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}"; - List lessonsList = lessonsJson.map((e) => Lesson.fromJson(e)).toList(); - if (lessons.isEmpty && lessons.isEmpty) return; + if (lessonsJson == null) { + return; + // throw "Cannot fetch Lessons for User ${user.id}"; + } else { + List lessonsList = + lessonsJson.map((e) => Lesson.fromJson(e)).toList(); - lessons[week] = lessonsList; + if (lessons.isEmpty) return; - await store(); - await convertBySettings(); + lessons[week] = lessonsList; + + await store(); + await convertBySettings(); + } } // Stores Lessons in the database diff --git a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart b/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart index 53bf9ca..6178cc7 100755 --- a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart +++ b/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart @@ -15,7 +15,8 @@ class MissedExamView extends StatelessWidget { final List missedExams; - static show(List missedExams, {required BuildContext context}) => showRoundedModalBottomSheet(context, child: MissedExamView(missedExams)); + static show(List missedExams, {required BuildContext context}) => + showRoundedModalBottomSheet(context, child: MissedExamView(missedExams)); @override Widget build(BuildContext context) { @@ -25,7 +26,8 @@ class MissedExamView extends StatelessWidget { } class MissedExamViewTile extends StatelessWidget { - const MissedExamViewTile(this.lesson, {Key? key, this.padding}) : super(key: key); + const MissedExamViewTile(this.lesson, {Key? key, this.padding}) + : super(key: key); final EdgeInsetsGeometry? padding; final Lesson lesson; @@ -33,23 +35,36 @@ class MissedExamViewTile extends StatelessWidget { @override Widget build(BuildContext context) { SettingsProvider settingsProvider = Provider.of(context); + + String? teacherName = lesson.teacher.isRenamed + ? lesson.teacher.renamedTo + : lesson.teacher.name; + return Material( type: MaterialType.transparency, child: Padding( - padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + padding: padding ?? + const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), child: ListTile( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)), leading: Icon( - SubjectIcon.resolveVariant(subject: lesson.subject, context: context), + SubjectIcon.resolveVariant( + subject: lesson.subject, context: context), color: AppColors.of(context).text.withOpacity(.8), size: 32.0, ), title: Text( "${lesson.subject.renamedTo ?? lesson.subject.name.capital()} • ${lesson.date.format(context)}", - style: TextStyle(fontWeight: FontWeight.w600, fontStyle: lesson.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null), + style: TextStyle( + fontWeight: FontWeight.w600, + fontStyle: lesson.subject.isRenamed && + settingsProvider.renamedSubjectsItalics + ? FontStyle.italic + : null), ), subtitle: Text( - "missed_exam_contact".i18n.fill([lesson.teacher]), + "missed_exam_contact".i18n.fill([teacherName ?? '']), style: const TextStyle(fontWeight: FontWeight.w500), ), trailing: const Icon(FeatherIcons.arrowRight), diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart index 8bcbd39..d79078f 100755 --- a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart +++ b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart @@ -39,7 +39,9 @@ class _StatusBarState extends State { height: currentStatus != null ? 28.0 : 0, decoration: BoxDecoration( color: backgroundColor, - boxShadow: [BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)], + boxShadow: [ + BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0) + ], borderRadius: BorderRadius.circular(45.0), ), ), @@ -53,9 +55,12 @@ class _StatusBarState extends State { height: currentStatus != null ? 28.0 : 0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut, - width: MediaQuery.of(context).size.width * statusProvider.progress - 16.0, + width: MediaQuery.of(context).size.width * + statusProvider.progress - + 16.0, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondary.withOpacity(0.8), + color: + Theme.of(context).colorScheme.secondary.withOpacity(0.8), borderRadius: BorderRadius.circular(45.0), ), ), @@ -82,6 +87,8 @@ class _StatusBarState extends State { return "Syncing data".i18n; case Status.maintenance: return "KRETA Maintenance".i18n; + case Status.apiError: + return "KRETA API error".i18n; case Status.network: return "No connection".i18n; default: @@ -93,10 +100,13 @@ class _StatusBarState extends State { switch (status) { case Status.maintenance: return AppColors.of(context).red; + case Status.apiError: + return AppColors.of(context).red; case Status.network: case Status.syncing: default: - HSLColor color = HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor); + HSLColor color = + HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor); if (color.lightness >= 0.5) { color = color.withSaturation(0.3); color = color.withLightness(color.lightness - 0.1); diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart index ca3acb8..e86b9d2 100755 --- a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart +++ b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart @@ -6,16 +6,19 @@ extension Localization on String { "en_en": { "Syncing data": "Syncing data", "KRETA Maintenance": "KRETA Maintenance", + "KRETA API error": "KRETA API Error", "No connection": "No connection", }, "hu_hu": { "Syncing data": "Adatok frissítése", "KRETA Maintenance": "KRÉTA Karbantartás", + "KRETA API error": "KRÉTA API Hiba", "No connection": "Nincs kapcsolat", }, "de_de": { "Syncing data": "Daten aktualisieren", "KRETA Maintenance": "KRETA Wartung", + "KRETA API error": "KRETA API Fehler", "No connection": "Keine Verbindung", }, };