diff --git a/filcnaplo/lib/app.dart b/filcnaplo/lib/app.dart index 17cda83..efc5414 100644 --- a/filcnaplo/lib/app.dart +++ b/filcnaplo/lib/app.dart @@ -11,6 +11,7 @@ import 'package:filcnaplo/models/config.dart'; import 'package:filcnaplo/theme/observer.dart'; import 'package:filcnaplo/theme/theme.dart'; import 'package:filcnaplo_kreta_api/client/client.dart'; +import 'package:filcnaplo_kreta_api/providers/grade_provider.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -22,13 +23,18 @@ import 'package:provider/provider.dart'; import 'package:filcnaplo_mobile_ui/common/system_chrome.dart' as mobile; import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart' as mobile; import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart' as mobile; -import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart' as mobile; -import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart' as mobile; -import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart' as mobile; +import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart' + as mobile; +import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart' + as mobile; +import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart' + as mobile; // Desktop UI -import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart' as desktop; -import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart' as desktop; +import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart' + as desktop; +import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart' + as desktop; import 'package:filcnaplo_desktop_ui/screens/login/login_route.dart' as desktop; // Providers @@ -36,7 +42,6 @@ import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo_kreta_api/providers/absence_provider.dart'; import 'package:filcnaplo_kreta_api/providers/event_provider.dart'; import 'package:filcnaplo_kreta_api/providers/exam_provider.dart'; -import 'package:filcnaplo_kreta_api/providers/grade_provider.dart'; import 'package:filcnaplo_kreta_api/providers/homework_provider.dart'; import 'package:filcnaplo_kreta_api/providers/message_provider.dart'; import 'package:filcnaplo_kreta_api/providers/note_provider.dart'; @@ -52,7 +57,12 @@ class App extends StatelessWidget { final UserProvider user; final DatabaseProvider database; - const App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key); + const App( + {Key? key, + required this.database, + required this.settings, + required this.user}) + : super(key: key); @override Widget build(BuildContext context) { @@ -65,7 +75,8 @@ class App extends StatelessWidget { final status = StatusProvider(); final kreta = KretaClient(user: user, settings: settings, status: status); - final timetable = TimetableProvider(user: user, database: database, kreta: kreta); + final timetable = + TimetableProvider(user: user, database: database, kreta: kreta); final premium = PremiumProvider(settings: settings); WidgetsBinding.instance.addPostFrameCallback((_) { @@ -83,23 +94,44 @@ class App extends StatelessWidget { ChangeNotifierProvider(create: (_) => status), Provider(create: (_) => kreta), Provider(create: (context) => database), - ChangeNotifierProvider(create: (context) => ThemeModeObserver(initialTheme: settings.theme)), - ChangeNotifierProvider(create: (context) => NewsProvider(context: context)), - ChangeNotifierProvider(create: (context) => UpdateProvider(context: context)), + ChangeNotifierProvider( + create: (context) => + ThemeModeObserver(initialTheme: settings.theme)), + ChangeNotifierProvider( + create: (context) => NewsProvider(context: context)), + ChangeNotifierProvider( + create: (context) => UpdateProvider(context: context)), // User data providers - ChangeNotifierProvider(create: (_) => GradeProvider(settings: settings, user: user, database: database, kreta: kreta)), + ChangeNotifierProvider( + create: (_) => GradeProvider( + settings: settings, + user: user, + database: database, + kreta: kreta)), ChangeNotifierProvider(create: (_) => timetable), - ChangeNotifierProvider(create: (context) => ExamProvider(context: context)), - ChangeNotifierProvider(create: (context) => HomeworkProvider(context: context)), - ChangeNotifierProvider(create: (context) => MessageProvider(context: context)), - ChangeNotifierProvider(create: (context) => NoteProvider(context: context)), - ChangeNotifierProvider(create: (context) => EventProvider(context: context)), - ChangeNotifierProvider(create: (context) => AbsenceProvider(context: context)), + ChangeNotifierProvider( + create: (context) => ExamProvider(context: context)), + ChangeNotifierProvider( + create: (context) => HomeworkProvider(context: context)), + ChangeNotifierProvider( + create: (context) => MessageProvider(context: context)), + ChangeNotifierProvider( + create: (context) => NoteProvider(context: context)), + ChangeNotifierProvider( + create: (context) => EventProvider(context: context)), + ChangeNotifierProvider( + create: (context) => AbsenceProvider(context: context)), ChangeNotifierProvider( - create: (_) => GradeCalculatorProvider(settings: settings, user: user, database: database, kreta: kreta)), - ChangeNotifierProvider(create: (context) => LiveCardProvider(timetable: timetable, settings: settings)) + create: (_) => GradeCalculatorProvider( + settings: settings, + user: user, + database: database, + kreta: kreta)), + ChangeNotifierProvider( + create: (context) => + LiveCardProvider(timetable: timetable, settings: settings)) ], child: Consumer( builder: (context, themeMode, child) { @@ -110,12 +142,15 @@ class App extends StatelessWidget { return MaterialApp( builder: (context, child) { // Limit font size scaling to 1.0 - double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0); + double textScaleFactor = + min(MediaQuery.of(context).textScaleFactor, 1.0); return I18n( - initialLocale: Locale(settings.language, settings.language.toUpperCase()), + initialLocale: Locale( + settings.language, settings.language.toUpperCase()), child: MediaQuery( - data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor), + data: MediaQuery.of(context) + .copyWith(textScaleFactor: textScaleFactor), child: child ?? Container(), ), ); @@ -148,7 +183,8 @@ class App extends StatelessWidget { return locale; }, onGenerateRoute: (settings) => rootNavigator(settings), - initialRoute: user.getUsers().isNotEmpty ? "navigation" : "login", + initialRoute: + user.getUsers().isNotEmpty ? "navigation" : "login", ); }, ); @@ -162,7 +198,8 @@ class App extends StatelessWidget { if (Platform.isAndroid || Platform.isIOS) { switch (route.name) { case "login_back": - return CupertinoPageRoute(builder: (context) => const mobile.LoginScreen(back: true)); + return CupertinoPageRoute( + builder: (context) => const mobile.LoginScreen(back: true)); case "login": return _rootRoute(const mobile.LoginScreen()); case "navigation": @@ -175,7 +212,8 @@ class App extends StatelessWidget { } else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { switch (route.name) { case "login_back": - return CupertinoPageRoute(builder: (context) => const desktop.LoginScreen(back: true)); + return CupertinoPageRoute( + builder: (context) => const desktop.LoginScreen(back: true)); case "login": return _rootRoute(const desktop.LoginScreen()); case "navigation": diff --git a/filcnaplo_kreta_api/lib/providers/grade_provider.dart b/filcnaplo_kreta_api/lib/providers/grade_provider.dart index f6519ab..a85153b 100644 --- a/filcnaplo_kreta_api/lib/providers/grade_provider.dart +++ b/filcnaplo_kreta_api/lib/providers/grade_provider.dart @@ -6,6 +6,7 @@ import 'package:filcnaplo_kreta_api/client/api.dart'; import 'package:filcnaplo_kreta_api/client/client.dart'; import 'package:filcnaplo_kreta_api/models/grade.dart'; import 'package:filcnaplo_kreta_api/models/group_average.dart'; +import 'package:filcnaplo_kreta_api/providers/grade_provider.i18n.dart'; import 'package:flutter/material.dart'; class GradeProvider with ChangeNotifier { @@ -21,7 +22,8 @@ class GradeProvider with ChangeNotifier { // Public List get grades => _grades; - DateTime get lastSeenDate => _settings.gradeOpeningFun ? _lastSeen : DateTime(3000); + DateTime get lastSeenDate => + _settings.gradeOpeningFun ? _lastSeen : DateTime(3000); String get groups => _groups; List get groupAverages => _groupAvg; @@ -65,7 +67,9 @@ class GradeProvider with ChangeNotifier { _groupAvg = await userQuery.getGroupAverages(userId: userId); notifyListeners(); DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId); - if (lastSeenDB.millisecondsSinceEpoch == 0 || lastSeenDB.year == 0 || !_settings.gradeOpeningFun) { + if (lastSeenDB.millisecondsSinceEpoch == 0 || + lastSeenDB.year == 0 || + !_settings.gradeOpeningFun) { _lastSeen = DateTime.now(); await seenAll(); } else { @@ -77,13 +81,25 @@ class GradeProvider with ChangeNotifier { // good student mode, renamed subjects Future convertBySettings() async { - Map renamedSubjects = _settings.renamedSubjectsEnabled ? await _database.userQuery.renamedSubjects(userId: _user.user!.id) : {}; + Map renamedSubjects = _settings.renamedSubjectsEnabled + ? await _database.userQuery.renamedSubjects(userId: _user.user!.id) + : {}; for (Grade grade in _grades) { - grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null; - grade.value.value = _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0; - grade.value.valueName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtek"] ?? ""; - grade.value.shortName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtekelesRovidNev"] ?? ""; + //grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null; + grade.subject.renamedTo = null; + if (renamedSubjects.isNotEmpty) { + grade.subject.name = + renamedSubjects[grade.subject.id] ?? grade.subject.name; + } + grade.value.value = + _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0; + grade.value.valueName = _settings.goodStudent + ? "Jeles".i18n + : grade.json!["SzovegesErtek"].i18n ?? ""; + grade.value.shortName = _settings.goodStudent + ? "Jeles".i18n + : grade.json!["SzovegesErtekelesRovidNev"].i18n ?? ""; } notifyListeners(); @@ -102,12 +118,16 @@ class GradeProvider with ChangeNotifier { if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades); List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss)); - if (groupsJson == null || groupsJson.isEmpty) throw "Cannot fetch Groups for User ${user.id}"; + if (groupsJson == null || groupsJson.isEmpty) + throw "Cannot fetch Groups for User ${user.id}"; _groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? ""; - List? groupAvgJson = await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups)); - if (groupAvgJson == null) throw "Cannot fetch Class Averages for User ${user.id}"; - final groupAvgs = groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList(); + List? groupAvgJson = + await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups)); + if (groupAvgJson == null) + throw "Cannot fetch Class Averages for User ${user.id}"; + final groupAvgs = + groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList(); await storeGroupAvg(groupAvgs); } diff --git a/filcnaplo_kreta_api/lib/providers/grade_provider.i18n.dart b/filcnaplo_kreta_api/lib/providers/grade_provider.i18n.dart new file mode 100644 index 0000000..1a3cfe2 --- /dev/null +++ b/filcnaplo_kreta_api/lib/providers/grade_provider.i18n.dart @@ -0,0 +1,33 @@ +import 'package:i18n_extension/i18n_extension.dart'; + +extension Localization on String { + static final _t = Translations.byLocale("hu_hu") + + { + "en_en": { + "Elégtelen": "Fail", + "Elégséges": "Warning but passing", + "Közepes": "Passed", + "Jó": "Good", + "Jeles": "Excellent" + }, + "hu_hu": { + "Elégtelen": "Elégtelen", + "Elégséges": "Elégséges", + "Közepes": "Közepes", + "Jó": "Jó", + "Jeles": "Jeles" + }, + "de_de": { + "Elégtelen": "Ungenügend", + "Elégséges": "Mangelhaft", + "Közepes": "Ausreichend", + "Jó": "Befriedigend", + "Jeles": "Gut" + }, + }; + + String get i18n => localize(this, _t); + String fill(List params) => localizeFill(this, params); + String plural(int value) => localizePlural(value, this, _t); + String version(Object modifier) => localizeVersion(modifier, this, _t); +} diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart b/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart index 59d999d..ef5ae89 100755 --- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart +++ b/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart @@ -6,7 +6,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart'; class HomeworkTile extends StatelessWidget { - const HomeworkTile(this.homework, {Key? key, this.onTap, this.padding, this.censored = false}) : super(key: key); + const HomeworkTile(this.homework, + {Key? key, this.onTap, this.padding, this.censored = false}) + : super(key: key); final Homework homework; final void Function()? onTap; @@ -24,7 +26,8 @@ class HomeworkTile extends StatelessWidget { visualDensity: VisualDensity.compact, contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0), onTap: onTap, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)), leading: SizedBox( width: 44, height: 44, @@ -38,7 +41,8 @@ class HomeworkTile extends StatelessWidget { : Padding( padding: const EdgeInsets.only(top: 2.0), child: Icon( - SubjectIcon.resolveVariant(subjectName: homework.subjectName, context: context), + SubjectIcon.resolveVariant( + subjectName: homework.subjectName, context: context), size: 28.0, color: AppColors.of(context).text.withOpacity(.75), ), diff --git a/filcnaplo_mobile_ui/lib/screens/news/news_screen.dart b/filcnaplo_mobile_ui/lib/screens/news/news_screen.dart index 92f5ff4..164afa3 100755 --- a/filcnaplo_mobile_ui/lib/screens/news/news_screen.dart +++ b/filcnaplo_mobile_ui/lib/screens/news/news_screen.dart @@ -6,6 +6,7 @@ import 'package:filcnaplo_mobile_ui/common/panel/panel.dart'; import 'package:filcnaplo_mobile_ui/screens/news/news_tile.dart'; import 'package:filcnaplo/models/news.dart'; import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart'; +import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:filcnaplo/api/providers/news_provider.dart'; @@ -24,24 +25,28 @@ class NewsScreen extends StatelessWidget { appBar: AppBar( surfaceTintColor: Theme.of(context).scaffoldBackgroundColor, leading: BackButton(color: AppColors.of(context).text), - title: Text("News", style: TextStyle(color: AppColors.of(context).text)), + title: Text("news".i18n, + style: TextStyle(color: AppColors.of(context).text)), ), body: SafeArea( child: RefreshIndicator( onRefresh: () => newsProvider.fetch(), child: ListView.builder( - physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics()), itemCount: max(news.length, 1), itemBuilder: (context, index) { if (news.isNotEmpty) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + padding: const EdgeInsets.symmetric( + horizontal: 24.0, vertical: 12.0), child: Panel( child: Material( type: MaterialType.transparency, child: NewsTile( news[index], - onTap: () => NewsView.show(news[index], context: context, force: true), + onTap: () => NewsView.show(news[index], + context: context, force: true), ), ), ),