diff --git a/lib/common/appstart/app_initializer.dart b/lib/common/appstart/app_initializer.dart index 7968c307..e614e19b 100644 --- a/lib/common/appstart/app_initializer.dart +++ b/lib/common/appstart/app_initializer.dart @@ -52,9 +52,9 @@ Future initializeApp(bool isBackground) async { WidgetUpdateCallback(KiwiContainer().resolve()) .registerCallback(KiwiContainer().resolve()); - NotificationsInitialize().setupNotifications(); - BackgroundInitialize().setupBackgroundScheduling(); - NotificationScheduleChangedInitialize().setupNotification(); + const NotificationsInitialize().setupNotifications(); + const BackgroundInitialize().setupBackgroundScheduling(); + const NotificationScheduleChangedInitialize().setupNotification(); if (isBackground) { final setup = KiwiContainer().resolve(); diff --git a/lib/common/appstart/background_initialize.dart b/lib/common/appstart/background_initialize.dart index 1fe025e2..6b5f0c26 100644 --- a/lib/common/appstart/background_initialize.dart +++ b/lib/common/appstart/background_initialize.dart @@ -12,6 +12,8 @@ import 'package:kiwi/kiwi.dart'; /// Note: More or less reliable background scheduling only works on android /// class BackgroundInitialize { + const BackgroundInitialize(); + Future setupBackgroundScheduling() async { WorkSchedulerService scheduler; if (Platform.isAndroid) { diff --git a/lib/common/appstart/localization_initialize.dart b/lib/common/appstart/localization_initialize.dart index 133cde4f..97c0efbb 100644 --- a/lib/common/appstart/localization_initialize.dart +++ b/lib/common/appstart/localization_initialize.dart @@ -9,18 +9,20 @@ import 'package:kiwi/kiwi.dart'; /// correct language /// class LocalizationInitialize { - PreferencesProvider? _preferencesProvider; - String? _languageCode; + final PreferencesProvider? _preferencesProvider; + final String? _languageCode; /// /// Initialize the localization using the provided language code /// - LocalizationInitialize.fromLanguageCode(this._languageCode); + const LocalizationInitialize.fromLanguageCode(this._languageCode) + : _preferencesProvider = null; /// /// Initialize the localization using the locale from the preferences provider /// - LocalizationInitialize.fromPreferences(this._preferencesProvider); + const LocalizationInitialize.fromPreferences(this._preferencesProvider) + : _languageCode = null; Future setupLocalizations() async { final localization = L( diff --git a/lib/common/appstart/notification_schedule_changed_initialize.dart b/lib/common/appstart/notification_schedule_changed_initialize.dart index c5c0209d..f29b69d6 100644 --- a/lib/common/appstart/notification_schedule_changed_initialize.dart +++ b/lib/common/appstart/notification_schedule_changed_initialize.dart @@ -8,6 +8,8 @@ import 'package:kiwi/kiwi.dart'; /// Initializes the notification for when the schedule changed /// class NotificationScheduleChangedInitialize { + const NotificationScheduleChangedInitialize(); + void setupNotification() { final provider = KiwiContainer().resolve(); diff --git a/lib/common/appstart/notifications_initialize.dart b/lib/common/appstart/notifications_initialize.dart index ec9a664d..0bf419c7 100644 --- a/lib/common/appstart/notifications_initialize.dart +++ b/lib/common/appstart/notifications_initialize.dart @@ -9,6 +9,8 @@ import 'package:kiwi/kiwi.dart'; /// won't show the notification /// class NotificationsInitialize { + const NotificationsInitialize(); + Future setupNotifications() async { if (Platform.isAndroid) { final notificationApi = NotificationApi(); @@ -17,7 +19,8 @@ class NotificationsInitialize { await notificationApi.initialize(); } else { - KiwiContainer().registerInstance(VoidNotificationApi()); + KiwiContainer() + .registerInstance(const VoidNotificationApi()); } } } diff --git a/lib/common/appstart/service_injector.dart b/lib/common/appstart/service_injector.dart index 77adf9a3..e5c49f77 100644 --- a/lib/common/appstart/service_injector.dart +++ b/lib/common/appstart/service_injector.dart @@ -30,12 +30,12 @@ void injectServices(bool isBackground) { final KiwiContainer c = KiwiContainer(); c.registerInstance( - PreferencesProvider( + const PreferencesProvider( PreferencesAccess(), SecureStorageAccess(), ), ); - c.registerInstance(DatabaseAccess()); + c.registerInstance(const DatabaseAccess()); c.registerInstance( ScheduleEntryRepository( c.resolve(), @@ -80,7 +80,7 @@ void injectServices(bool isBackground) { ); c.registerInstance( DateEntryProvider( - DateManagementService(), + const DateManagementService(), DateEntryRepository(c.resolve()), ), ); diff --git a/lib/common/background/task_callback.dart b/lib/common/background/task_callback.dart index e2a36a1e..dc3e63cf 100644 --- a/lib/common/background/task_callback.dart +++ b/lib/common/background/task_callback.dart @@ -2,6 +2,8 @@ /// Override this class in order to receive a background callback /// abstract class TaskCallback { + const TaskCallback(); + Future run(); Future schedule(); diff --git a/lib/common/background/work_scheduler_service.dart b/lib/common/background/work_scheduler_service.dart index d11baa58..e692db22 100644 --- a/lib/common/background/work_scheduler_service.dart +++ b/lib/common/background/work_scheduler_service.dart @@ -1,6 +1,8 @@ import 'package:dhbwstudentapp/common/background/task_callback.dart'; abstract class WorkSchedulerService { + const WorkSchedulerService(); + Future scheduleOneShotTaskIn(Duration delay, String id, String name); Future scheduleOneShotTaskAt( diff --git a/lib/common/data/database_access.dart b/lib/common/data/database_access.dart index d03bf55f..87dbb25c 100644 --- a/lib/common/data/database_access.dart +++ b/lib/common/data/database_access.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/common/data/sql_scripts.dart'; import 'package:sqflite/sqflite.dart'; class DatabaseAccess { + const DatabaseAccess(); + static const String _databaseName = "Database.db"; static Database? _databaseInstance; diff --git a/lib/common/data/preferences/preferences_access.dart b/lib/common/data/preferences/preferences_access.dart index ea183eae..08465854 100644 --- a/lib/common/data/preferences/preferences_access.dart +++ b/lib/common/data/preferences/preferences_access.dart @@ -1,6 +1,8 @@ import 'package:shared_preferences/shared_preferences.dart'; class PreferencesAccess { + const PreferencesAccess(); + Future set(String key, T value) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -43,5 +45,5 @@ class PreferencesAccess { class InvalidValueTypeException implements Exception { final Type type; - InvalidValueTypeException(this.type); + const InvalidValueTypeException(this.type); } diff --git a/lib/common/data/preferences/preferences_provider.dart b/lib/common/data/preferences/preferences_provider.dart index 86a4ff4e..e2aad7c9 100644 --- a/lib/common/data/preferences/preferences_provider.dart +++ b/lib/common/data/preferences/preferences_provider.dart @@ -33,7 +33,7 @@ class PreferencesProvider { final PreferencesAccess _preferencesAccess; final SecureStorageAccess _secureStorageAccess; - PreferencesProvider(this._preferencesAccess, this._secureStorageAccess); + const PreferencesProvider(this._preferencesAccess, this._secureStorageAccess); Future appTheme() async { final theme = await _preferencesAccess.get(AppThemeKey); diff --git a/lib/common/data/preferences/secure_storage_access.dart b/lib/common/data/preferences/secure_storage_access.dart index 2f616d2e..e8fe4da4 100644 --- a/lib/common/data/preferences/secure_storage_access.dart +++ b/lib/common/data/preferences/secure_storage_access.dart @@ -1,7 +1,9 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; class SecureStorageAccess { - final _secureStorage = const FlutterSecureStorage(); + static const _secureStorage = FlutterSecureStorage(); + + const SecureStorageAccess(); Future set(String key, String value) async { await _secureStorage.write(key: key, value: value); diff --git a/lib/common/iap/in_app_purchase_helper.dart b/lib/common/iap/in_app_purchase_helper.dart index d469490e..5f0fe27b 100644 --- a/lib/common/iap/in_app_purchase_helper.dart +++ b/lib/common/iap/in_app_purchase_helper.dart @@ -100,8 +100,8 @@ class InAppPurchaseHelper { final productIdPurchases = allPurchases?.where((element) => element.productId == id); - if (productIdPurchases?.isNotEmpty ?? false) { - return productIdPurchases!.any((element) => _isPurchased(element)) + if (productIdPurchases != null && productIdPurchases.isNotEmpty) { + return productIdPurchases.any((element) => _isPurchased(element)) ? PurchaseStateEnum.Purchased : PurchaseStateEnum.NotPurchased; } diff --git a/lib/common/ui/app_launch_dialogs.dart b/lib/common/ui/app_launch_dialogs.dart index 3f3cbe04..3251b313 100644 --- a/lib/common/ui/app_launch_dialogs.dart +++ b/lib/common/ui/app_launch_dialogs.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; class AppLaunchDialog { final PreferencesProvider _preferencesProvider; - AppLaunchDialog(this._preferencesProvider); + const AppLaunchDialog(this._preferencesProvider); Future showAppLaunchDialogs(BuildContext context) async { final appLaunchCounter = await _preferencesProvider.getAppLaunchCounter(); diff --git a/lib/common/ui/app_theme.dart b/lib/common/ui/app_theme.dart index b9f89f43..33d87c59 100644 --- a/lib/common/ui/app_theme.dart +++ b/lib/common/ui/app_theme.dart @@ -4,7 +4,7 @@ import 'package:dhbwstudentapp/common/ui/text_theme.dart'; import 'package:flutter/material.dart'; class AppTheme { - AppTheme._(); + const AppTheme._(); /// Light theme static final lightThemeData = ThemeData( diff --git a/lib/common/ui/donate_to_developer_dialog.dart b/lib/common/ui/donate_to_developer_dialog.dart index dca41ffc..78b5e5f0 100644 --- a/lib/common/ui/donate_to_developer_dialog.dart +++ b/lib/common/ui/donate_to_developer_dialog.dart @@ -14,7 +14,10 @@ class DonateToDeveloperDialog { final PreferencesProvider _preferencesProvider; final int _appLaunchCounter; - DonateToDeveloperDialog(this._preferencesProvider, this._appLaunchCounter); + const DonateToDeveloperDialog( + this._preferencesProvider, + this._appLaunchCounter, + ); Future showIfNeeded(BuildContext context) async { if (await _preferencesProvider.getDidShowDonateDialog()) return; diff --git a/lib/common/ui/notification_api.dart b/lib/common/ui/notification_api.dart index d2338919..3286df1b 100644 --- a/lib/common/ui/notification_api.dart +++ b/lib/common/ui/notification_api.dart @@ -10,6 +10,8 @@ class NotificationApi { final FlutterLocalNotificationsPlugin _localNotificationsPlugin = FlutterLocalNotificationsPlugin(); + NotificationApi(); + /// /// Initialize the notifications. You can't show any notifications before you /// call this method @@ -84,6 +86,8 @@ class NotificationApi { /// This class implements the methods of the NotificationApi with empty stubs /// class VoidNotificationApi implements NotificationApi { + const VoidNotificationApi(); + @override FlutterLocalNotificationsPlugin get _localNotificationsPlugin => throw UnimplementedError(); diff --git a/lib/common/ui/rate_in_store_dialog.dart b/lib/common/ui/rate_in_store_dialog.dart index 936b7612..e21a3f6b 100644 --- a/lib/common/ui/rate_in_store_dialog.dart +++ b/lib/common/ui/rate_in_store_dialog.dart @@ -13,7 +13,7 @@ class RateInStoreDialog { final PreferencesProvider _preferencesProvider; final int _appLaunchCounter; - RateInStoreDialog(this._preferencesProvider, this._appLaunchCounter); + const RateInStoreDialog(this._preferencesProvider, this._appLaunchCounter); Future showIfNeeded(BuildContext context) async { if (!PlatformUtil.isAndroid()) return; diff --git a/lib/common/ui/widget_help_dialog.dart b/lib/common/ui/widget_help_dialog.dart index 060428e0..c41279d5 100644 --- a/lib/common/ui/widget_help_dialog.dart +++ b/lib/common/ui/widget_help_dialog.dart @@ -11,7 +11,7 @@ class WidgetHelpDialog { final PreferencesProvider _preferencesProvider; final int _appLaunchCounter; - WidgetHelpDialog(this._preferencesProvider, this._appLaunchCounter); + const WidgetHelpDialog(this._preferencesProvider, this._appLaunchCounter); Future showIfNeeded(BuildContext context) async { if (!PlatformUtil.isAndroid()) return; diff --git a/lib/common/ui/widgets/dots_indicator.dart b/lib/common/ui/widgets/dots_indicator.dart index 8a89bd4c..4e50d4e0 100644 --- a/lib/common/ui/widgets/dots_indicator.dart +++ b/lib/common/ui/widgets/dots_indicator.dart @@ -5,10 +5,10 @@ class DotsIndicator extends StatelessWidget { final int currentStep; const DotsIndicator({ - Key? key, + super.key, required this.numberSteps, required this.currentStep, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/common/ui/widgets/error_display.dart b/lib/common/ui/widgets/error_display.dart index c254574a..a6d5c631 100644 --- a/lib/common/ui/widgets/error_display.dart +++ b/lib/common/ui/widgets/error_display.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; class ErrorDisplay extends StatelessWidget { final bool show; - const ErrorDisplay({Key? key, required this.show}) : super(key: key); + const ErrorDisplay({super.key, required this.show}); @override Widget build(BuildContext context) { @@ -25,9 +25,9 @@ class ErrorDisplay extends StatelessWidget { child: Text( L.of(context).noConnectionMessage, textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle2!.copyWith( - color: AppTheme.noConnectionForeground, - ), + style: const TextStyle( + color: AppTheme.noConnectionForeground, + ), ), ), ), diff --git a/lib/common/ui/widgets/help_dialog.dart b/lib/common/ui/widgets/help_dialog.dart index e3098298..08b87df3 100644 --- a/lib/common/ui/widgets/help_dialog.dart +++ b/lib/common/ui/widgets/help_dialog.dart @@ -6,6 +6,8 @@ import 'package:flutter/material.dart'; /// Deriving classes only need to implement the title() and content() methods /// abstract class HelpDialog { + const HelpDialog(); + Future show(BuildContext context) async { await showDialog( context: context, diff --git a/lib/common/ui/widgets/title_list_tile.dart b/lib/common/ui/widgets/title_list_tile.dart index 82de6d27..58b6c7d9 100644 --- a/lib/common/ui/widgets/title_list_tile.dart +++ b/lib/common/ui/widgets/title_list_tile.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class TitleListTile extends StatelessWidget { final String title; - const TitleListTile({Key? key, required this.title}) : super(key: key); + const TitleListTile({super.key, required this.title}); @override Widget build(BuildContext context) { diff --git a/lib/common/util/cancelable_mutex.dart b/lib/common/util/cancelable_mutex.dart index 4d79d6fb..fdcb1aa2 100644 --- a/lib/common/util/cancelable_mutex.dart +++ b/lib/common/util/cancelable_mutex.dart @@ -6,6 +6,8 @@ class CancelableMutex { CancellationToken? _token; CancellationToken? get token => _token; + CancelableMutex(); + void cancel() { _token?.cancel(); } diff --git a/lib/date_management/business/date_entry_provider.dart b/lib/date_management/business/date_entry_provider.dart index ad8d762f..a493625c 100644 --- a/lib/date_management/business/date_entry_provider.dart +++ b/lib/date_management/business/date_entry_provider.dart @@ -8,21 +8,21 @@ class DateEntryProvider { final DateManagementService _dateEntryService; final DateEntryRepository _dateEntryRepository; - DateEntryProvider(this._dateEntryService, this._dateEntryRepository); + const DateEntryProvider(this._dateEntryService, this._dateEntryRepository); Future> getCachedDateEntries( DateSearchParameters parameters, ) async { List cachedEntries = []; - if (parameters.includeFuture! && parameters.includePast!) { + if (parameters.includeFuture && parameters.includePast) { cachedEntries = await _dateEntryRepository.queryAllDateEntries( parameters.databaseName, parameters.year, ); } else { final now = DateTime.now(); - if (parameters.includeFuture!) { + if (parameters.includeFuture) { final datesAfter = await _dateEntryRepository.queryDateEntriesAfter( parameters.databaseName, parameters.year, @@ -31,7 +31,7 @@ class DateEntryProvider { cachedEntries.addAll(datesAfter); } - if (parameters.includePast!) { + if (parameters.includePast) { final datesBefore = await _dateEntryRepository.queryDateEntriesBefore( parameters.databaseName, parameters.year, @@ -85,11 +85,11 @@ class DateEntryProvider { continue; } - if (dateEntry.start.isBefore(now) && !parameters.includePast!) { + if (dateEntry.start.isBefore(now) && !parameters.includePast) { continue; } - if (dateEntry.end.isAfter(now) && !parameters.includeFuture!) { + if (dateEntry.end.isAfter(now) && !parameters.includeFuture) { continue; } diff --git a/lib/date_management/data/calendar_access.dart b/lib/date_management/data/calendar_access.dart index 5c410cc3..5be9a092 100644 --- a/lib/date_management/data/calendar_access.dart +++ b/lib/date_management/data/calendar_access.dart @@ -17,6 +17,8 @@ enum CalendarPermission { class CalendarAccess { final DeviceCalendarPlugin _deviceCalendarPlugin = DeviceCalendarPlugin(); + CalendarAccess(); + Future requestCalendarPermission() async { try { var permissionsGranted = await _deviceCalendarPlugin.hasPermissions(); @@ -134,12 +136,10 @@ class CalendarAccess { ), ); - var existingEvents = []; - if (existingEventsResult.isSuccess) { - existingEvents = existingEventsResult.data!.toList(); + return existingEventsResult.data!.toList(); } - return existingEvents; + return []; } DateEntry _findFirstEntry(List entries) { diff --git a/lib/date_management/data/date_entry_repository.dart b/lib/date_management/data/date_entry_repository.dart index 986e6366..86aef15e 100644 --- a/lib/date_management/data/date_entry_repository.dart +++ b/lib/date_management/data/date_entry_repository.dart @@ -4,7 +4,7 @@ import 'package:dhbwstudentapp/date_management/model/date_entry.dart'; class DateEntryRepository { final DatabaseAccess _database; - DateEntryRepository(this._database); + const DateEntryRepository(this._database); Future> queryAllDateEntries( String? databaseName, diff --git a/lib/date_management/model/date_database.dart b/lib/date_management/model/date_database.dart index e9da69ed..a10f437a 100644 --- a/lib/date_management/model/date_database.dart +++ b/lib/date_management/model/date_database.dart @@ -2,5 +2,5 @@ class DateDatabase { final String id; final String displayName; - DateDatabase(this.displayName, this.id); + const DateDatabase(this.displayName, this.id); } diff --git a/lib/date_management/model/date_search_parameters.dart b/lib/date_management/model/date_search_parameters.dart index f686fc9f..430f8298 100644 --- a/lib/date_management/model/date_search_parameters.dart +++ b/lib/date_management/model/date_search_parameters.dart @@ -1,10 +1,10 @@ class DateSearchParameters { - bool? includePast; - bool? includeFuture; - String? year; - String? databaseName; + final bool includePast; + final bool includeFuture; + final String? year; + final String? databaseName; - DateSearchParameters( + const DateSearchParameters( this.includePast, this.includeFuture, this.year, diff --git a/lib/date_management/service/date_management_service.dart b/lib/date_management/service/date_management_service.dart index 3a2e26dd..1f153a82 100644 --- a/lib/date_management/service/date_management_service.dart +++ b/lib/date_management/service/date_management_service.dart @@ -5,6 +5,8 @@ import 'package:dhbwstudentapp/date_management/service/parsing/all_dates_extract import 'package:dhbwstudentapp/dualis/service/session.dart'; class DateManagementService { + const DateManagementService(); + Future> queryAllDates( DateSearchParameters parameters, CancellationToken? cancellationToken, @@ -14,7 +16,7 @@ class DateManagementService { cancellationToken, ); - final allDates = AllDatesExtract().extractAllDates( + final allDates = const AllDatesExtract().extractAllDates( queryResult, parameters.databaseName, ); @@ -28,7 +30,7 @@ class DateManagementService { url += "&sel_typ=pub"; url += "&sel_jahrgang= ${parameters.year ?? "*"}"; url += "&sel_bezeichnung=*"; - url += "&selection=${parameters.includePast! ? "**" : "*"}"; + url += "&selection=${parameters.includePast ? "**" : "*"}"; url += "&permission=show"; url += "&sessionid="; url += "&user=nobody"; diff --git a/lib/date_management/service/parsing/all_dates_extract.dart b/lib/date_management/service/parsing/all_dates_extract.dart index bc48b192..a8e94c55 100644 --- a/lib/date_management/service/parsing/all_dates_extract.dart +++ b/lib/date_management/service/parsing/all_dates_extract.dart @@ -5,6 +5,8 @@ import 'package:intl/intl.dart'; // TODO: Parse exception to common module class AllDatesExtract { + const AllDatesExtract(); + List extractAllDates(String? body, String? databaseName) { if (body == null) return []; try { diff --git a/lib/date_management/ui/calendar_export_page.dart b/lib/date_management/ui/calendar_export_page.dart index 749c3fe5..e0231574 100644 --- a/lib/date_management/ui/calendar_export_page.dart +++ b/lib/date_management/ui/calendar_export_page.dart @@ -15,11 +15,11 @@ class CalendarExportPage extends StatefulWidget { final bool isCalendarSyncEnabled; const CalendarExportPage({ - Key? key, + super.key, required this.entriesToExport, this.isCalendarSyncWidget = false, this.isCalendarSyncEnabled = false, - }) : super(key: key); + }); @override _CalendarExportPageState createState() => _CalendarExportPageState(); @@ -28,6 +28,8 @@ class CalendarExportPage extends StatefulWidget { class _CalendarExportPageState extends State { late CalendarExportViewModel viewModel; + _CalendarExportPageState(); + @override void initState() { super.initState(); diff --git a/lib/date_management/ui/date_management_navigation_entry.dart b/lib/date_management/ui/date_management_navigation_entry.dart index 76340b64..dc46e32b 100644 --- a/lib/date_management/ui/date_management_navigation_entry.dart +++ b/lib/date_management/ui/date_management_navigation_entry.dart @@ -11,6 +11,8 @@ import 'package:property_change_notifier/property_change_notifier.dart'; class DateManagementNavigationEntry extends NavigationEntry { + DateManagementNavigationEntry(); + @override Icon icon = const Icon(Icons.date_range); @@ -33,7 +35,7 @@ class DateManagementNavigationEntry IconButton( icon: const Icon(Icons.help_outline), onPressed: () async { - await DateManagementHelpDialog().show(context); + await const DateManagementHelpDialog().show(context); }, tooltip: L.of(context).helpButtonTooltip, ), @@ -43,7 +45,7 @@ class DateManagementNavigationEntry builder: (BuildContext context, DateManagementViewModel? _, __) => PopupMenuButton( onSelected: (i) async { - await NavigatorKey.rootKey.currentState!.push( + await NavigatorKey.rootKey.currentState?.push( MaterialPageRoute( builder: (BuildContext context) => CalendarExportPage( entriesToExport: model.allDates!, @@ -68,7 +70,7 @@ class DateManagementNavigationEntry @override Widget build(BuildContext context) { - return Scaffold(body: DateManagementPage()); + return const Scaffold(body: DateManagementPage()); } @override diff --git a/lib/date_management/ui/date_management_page.dart b/lib/date_management/ui/date_management_page.dart index 8ceb65cc..e321030e 100644 --- a/lib/date_management/ui/date_management_page.dart +++ b/lib/date_management/ui/date_management_page.dart @@ -11,6 +11,8 @@ import 'package:property_change_notifier/property_change_notifier.dart'; import 'package:provider/provider.dart'; class DateManagementPage extends StatelessWidget { + const DateManagementPage({super.key}); + @override Widget build(BuildContext context) { final DateManagementViewModel viewModel = @@ -145,13 +147,11 @@ class DateManagementPage extends StatelessWidget { return dataRows; } - void showDateEntryDetailBottomSheet(BuildContext context, DateEntry? entry) { + void showDateEntryDetailBottomSheet(BuildContext context, DateEntry entry) { showModalBottomSheet( useRootNavigator: true, context: context, - builder: (context) => DateDetailBottomSheet( - dateEntry: entry, - ), + builder: (context) => DateDetailBottomSheet(dateEntry: entry), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(12.0)), ), diff --git a/lib/date_management/ui/viewmodels/date_management_view_model.dart b/lib/date_management/ui/viewmodels/date_management_view_model.dart index 32296b9f..7cc666e9 100644 --- a/lib/date_management/ui/viewmodels/date_management_view_model.dart +++ b/lib/date_management/ui/viewmodels/date_management_view_model.dart @@ -13,23 +13,26 @@ class DateManagementViewModel extends BaseViewModel { final PreferencesProvider _preferencesProvider; final List _allDateDatabases = [ - DateDatabase("BWL-Bank", "Termine_BWL_Bank"), - DateDatabase("Immobilienwirtschaft", "Termine_BWL_Immo"), - DateDatabase( + const DateDatabase("BWL-Bank", "Termine_BWL_Bank"), + const DateDatabase("Immobilienwirtschaft", "Termine_BWL_Immo"), + const DateDatabase( "Dienstleistungsmanagement Consulting & Sales", "Termine_DLM_Consult", ), - DateDatabase("Dienstleistungsmanagement Logistik", "Termine_DLM_Logistik"), - DateDatabase("Campus Horb Informatik", "Termine_Horb_INF"), - DateDatabase("Campus Horb Maschinenbau", "Termine_Horb_MB"), - DateDatabase("International Business", "Termine_IB"), - DateDatabase("Informatik", "Termine_Informatik"), - DateDatabase("MUK (DLM - C&S, LogM, MUK)", "Termine_MUK"), - DateDatabase( + const DateDatabase( + "Dienstleistungsmanagement Logistik", + "Termine_DLM_Logistik", + ), + const DateDatabase("Campus Horb Informatik", "Termine_Horb_INF"), + const DateDatabase("Campus Horb Maschinenbau", "Termine_Horb_MB"), + const DateDatabase("International Business", "Termine_IB"), + const DateDatabase("Informatik", "Termine_Informatik"), + const DateDatabase("MUK (DLM - C&S, LogM, MUK)", "Termine_MUK"), + const DateDatabase( "SO_GuO (Abweichungen und Ergänzungen zum Vorlesungsplan)", "Termine_SO_GuO", ), - DateDatabase("Wirtschaftsingenieurwesen", "Termine_WIW"), + const DateDatabase("Wirtschaftsingenieurwesen", "Termine_WIW"), ]; List get allDateDatabases => _allDateDatabases; diff --git a/lib/date_management/ui/widgets/date_detail_bottom_sheet.dart b/lib/date_management/ui/widgets/date_detail_bottom_sheet.dart index a715e3ee..656c1bd6 100644 --- a/lib/date_management/ui/widgets/date_detail_bottom_sheet.dart +++ b/lib/date_management/ui/widgets/date_detail_bottom_sheet.dart @@ -6,16 +6,16 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class DateDetailBottomSheet extends StatelessWidget { - final DateEntry? dateEntry; + final DateEntry dateEntry; - const DateDetailBottomSheet({Key? key, this.dateEntry}) : super(key: key); + const DateDetailBottomSheet({super.key, required this.dateEntry}); @override Widget build(BuildContext context) { final date = DateFormat.yMd(L.of(context).locale.languageCode) - .format(dateEntry!.start); + .format(dateEntry.start); final time = DateFormat.Hm(L.of(context).locale.languageCode) - .format(dateEntry!.start); + .format(dateEntry.start); return SizedBox( height: 400, @@ -45,7 +45,7 @@ class DateDetailBottomSheet extends StatelessWidget { children: [ Expanded( child: Text( - dateEntry!.description, + dateEntry.description, style: Theme.of(context).textTheme.headline5, ), ), @@ -59,7 +59,7 @@ class DateDetailBottomSheet extends StatelessWidget { softWrap: true, style: Theme.of(context).textTheme.subtitle2, ), - if (isAtMidnight(dateEntry!.start)) + if (isAtMidnight(dateEntry.start)) Container() else Text( @@ -74,9 +74,7 @@ class DateDetailBottomSheet extends StatelessWidget { ), Padding( padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), - child: Text( - dateEntry!.comment, - ), + child: Text(dateEntry.comment), ), ], ), diff --git a/lib/date_management/ui/widgets/date_filter_options.dart b/lib/date_management/ui/widgets/date_filter_options.dart index 2624293d..25886289 100644 --- a/lib/date_management/ui/widgets/date_filter_options.dart +++ b/lib/date_management/ui/widgets/date_filter_options.dart @@ -6,8 +6,7 @@ import 'package:flutter/material.dart'; class DateFilterOptions extends StatefulWidget { final DateManagementViewModel viewModel; - const DateFilterOptions({Key? key, required this.viewModel}) - : super(key: key); + const DateFilterOptions({super.key, required this.viewModel}); @override _DateFilterOptionsState createState() => _DateFilterOptionsState(); @@ -16,6 +15,8 @@ class DateFilterOptions extends StatefulWidget { class _DateFilterOptionsState extends State { bool _isExpanded = false; + _DateFilterOptionsState(); + @override Widget build(BuildContext context) { return AnimatedCrossFade( @@ -43,11 +44,9 @@ class _DateFilterOptionsState extends State { Widget _buildCollapsed() { return GestureDetector( - onTap: () { - setState(() { - _isExpanded = true; - }); - }, + onTap: () => setState(() { + _isExpanded = true; + }), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ diff --git a/lib/date_management/ui/widgets/date_management_help_dialog.dart b/lib/date_management/ui/widgets/date_management_help_dialog.dart index 55c97285..2b403083 100644 --- a/lib/date_management/ui/widgets/date_management_help_dialog.dart +++ b/lib/date_management/ui/widgets/date_management_help_dialog.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/common/ui/widgets/help_dialog.dart'; import 'package:flutter/material.dart'; class DateManagementHelpDialog extends HelpDialog { + const DateManagementHelpDialog(); + @override String content(BuildContext context) { return L.of(context).dateManagementHelpDialogContent; diff --git a/lib/dualis/model/exam.dart b/lib/dualis/model/exam.dart index 22cf8f93..33d21730 100644 --- a/lib/dualis/model/exam.dart +++ b/lib/dualis/model/exam.dart @@ -12,7 +12,7 @@ class Exam { final String? semester; final ExamState state; - Exam( + const Exam( this.name, this.grade, this.state, diff --git a/lib/dualis/model/exam_grade.dart b/lib/dualis/model/exam_grade.dart index f3ba7598..90c9518f 100644 --- a/lib/dualis/model/exam_grade.dart +++ b/lib/dualis/model/exam_grade.dart @@ -5,19 +5,20 @@ enum ExamGradeState { Failed, } +// TODO: [leptopoda] implement into the enum class ExamGrade { - ExamGradeState state; - String? gradeValue; + final ExamGradeState state; + final String? gradeValue; - ExamGrade.failed() + const ExamGrade.failed() : state = ExamGradeState.Failed, gradeValue = ""; - ExamGrade.notGraded() + const ExamGrade.notGraded() : state = ExamGradeState.NotGraded, gradeValue = ""; - ExamGrade.passed() + const ExamGrade.passed() : state = ExamGradeState.Passed, gradeValue = ""; @@ -25,11 +26,11 @@ class ExamGrade { factory ExamGrade.fromString(String? grade) { if (grade == "noch nicht gesetzt" || grade == "") { - return ExamGrade.notGraded(); + return const ExamGrade.notGraded(); } if (grade == "b") { - return ExamGrade.passed(); + return const ExamGrade.passed(); } // TODO: Determine the value when a exam is in the "failed" state diff --git a/lib/dualis/model/module.dart b/lib/dualis/model/module.dart index c2d1d879..d26a6a96 100644 --- a/lib/dualis/model/module.dart +++ b/lib/dualis/model/module.dart @@ -8,7 +8,7 @@ class Module { final String? grade; final ExamState? state; - Module( + const Module( this.exams, this.id, this.name, diff --git a/lib/dualis/model/semester.dart b/lib/dualis/model/semester.dart index db30676b..d8e73449 100644 --- a/lib/dualis/model/semester.dart +++ b/lib/dualis/model/semester.dart @@ -4,7 +4,7 @@ class Semester { final String? name; final List modules; - Semester( + const Semester( this.name, this.modules, ); diff --git a/lib/dualis/model/study_grades.dart b/lib/dualis/model/study_grades.dart index e5b25ab4..83caee79 100644 --- a/lib/dualis/model/study_grades.dart +++ b/lib/dualis/model/study_grades.dart @@ -4,7 +4,7 @@ class StudyGrades { final double? creditsTotal; final double? creditsGained; - StudyGrades( + const StudyGrades( this.gpaTotal, this.gpaMainModules, this.creditsTotal, diff --git a/lib/dualis/service/dualis_authentication.dart b/lib/dualis/service/dualis_authentication.dart index c1697443..4291f2d9 100644 --- a/lib/dualis/service/dualis_authentication.dart +++ b/lib/dualis/service/dualis_authentication.dart @@ -15,6 +15,8 @@ import 'package:http/http.dart'; /// with the username and password and then use the [authenticatedGet] method. /// class DualisAuthentication { + DualisAuthentication(); + final RegExp _tokenRegex = RegExp("ARGUMENTS=-N([0-9]{15})"); Credentials? _credentials; @@ -51,7 +53,7 @@ class DualisAuthentication { // TODO: Test for login failed page - final redirectUrl = LoginRedirectUrlExtract().getUrlFromHeader( + final redirectUrl = const LoginRedirectUrlExtract().getUrlFromHeader( loginResponse.headers['refresh'], dualisEndpoint, ); @@ -66,7 +68,7 @@ class DualisAuthentication { cancellationToken, ); - dualisUrls.mainPageUrl = LoginRedirectUrlExtract().readRedirectUrl( + dualisUrls.mainPageUrl = const LoginRedirectUrlExtract().readRedirectUrl( redirectPage, dualisEndpoint, ); @@ -83,7 +85,7 @@ class DualisAuthentication { cancellationToken, ); - UrlsFromMainPageExtract().parseMainPage( + const UrlsFromMainPageExtract().parseMainPage( mainPage, dualisUrls, dualisEndpoint, @@ -145,8 +147,8 @@ class DualisAuthentication { cancellationToken?.throwIfCancelled(); - if (!TimeoutExtract().isTimeoutErrorPage(result) && - !AccessDeniedExtract().isAccessDeniedPage(result)) { + if (!const TimeoutExtract().isTimeoutErrorPage(result) && + !const AccessDeniedExtract().isAccessDeniedPage(result)) { return result; } diff --git a/lib/dualis/service/dualis_scraper.dart b/lib/dualis/service/dualis_scraper.dart index dcd2ff83..44bc4629 100644 --- a/lib/dualis/service/dualis_scraper.dart +++ b/lib/dualis/service/dualis_scraper.dart @@ -29,7 +29,7 @@ class DualisScraper { cancellationToken, ); - return AllModulesExtract().extractAllModules(allModulesPageResponse); + return const AllModulesExtract().extractAllModules(allModulesPageResponse); } Future> loadModuleExams( @@ -41,7 +41,7 @@ class DualisScraper { cancellationToken, ); - return ExamsFromModuleDetailsExtract().extractExamsFromModuleDetails( + return const ExamsFromModuleDetailsExtract().extractExamsFromModuleDetails( detailsResponse, ); } @@ -54,7 +54,7 @@ class DualisScraper { cancellationToken, ); - final semesters = SemestersFromCourseResultPageExtract() + final semesters = const SemestersFromCourseResultPageExtract() .extractSemestersFromCourseResults( courseResultsResponse, dualisEndpoint, @@ -89,7 +89,7 @@ class DualisScraper { cancellationToken, ); - return StudyGradesFromStudentResultsPageExtract() + return const StudyGradesFromStudentResultsPageExtract() .extractStudyGradesFromStudentsResultsPage(studentsResultsPage); } @@ -106,7 +106,7 @@ class DualisScraper { ); final schedule = - MonthlyScheduleExtract().extractScheduleFromMonthly(result); + const MonthlyScheduleExtract().extractScheduleFromMonthly(result); schedule.urls.add(dualisEndpoint); diff --git a/lib/dualis/service/dualis_service.dart b/lib/dualis/service/dualis_service.dart index 22311637..fdc6a11d 100644 --- a/lib/dualis/service/dualis_service.dart +++ b/lib/dualis/service/dualis_service.dart @@ -7,6 +7,8 @@ import 'package:dhbwstudentapp/dualis/model/study_grades.dart'; import 'package:dhbwstudentapp/dualis/service/dualis_scraper.dart'; abstract class DualisService { + const DualisService(); + Future login( Credentials credentials, [ CancellationToken? cancellationToken, @@ -44,7 +46,7 @@ enum LoginResult { class DualisServiceImpl extends DualisService { final DualisScraper _dualisScraper; - DualisServiceImpl(this._dualisScraper); + const DualisServiceImpl(this._dualisScraper); @override Future login( diff --git a/lib/dualis/service/dualis_website_model.dart b/lib/dualis/service/dualis_website_model.dart index dc234e45..a3d076c1 100644 --- a/lib/dualis/service/dualis_website_model.dart +++ b/lib/dualis/service/dualis_website_model.dart @@ -14,6 +14,8 @@ class DualisUrls { String? mainPageUrl; String? monthlyScheduleUrl; + DualisUrls(); + Map semesterCourseResultUrls = {}; } @@ -22,7 +24,7 @@ class DualisSemester { final String? semesterCourseResultsUrl; final List modules; - DualisSemester( + const DualisSemester( this.semesterName, this.semesterCourseResultsUrl, this.modules, @@ -37,7 +39,7 @@ class DualisModule { final String? detailsUrl; final ExamState? state; - DualisModule( + const DualisModule( this.id, this.name, this.finalGrade, @@ -54,7 +56,7 @@ class DualisExam { final ExamGrade grade; final String? semester; - DualisExam( + const DualisExam( this.name, this.moduleName, this.grade, diff --git a/lib/dualis/service/fake_data_dualis_scraper.dart b/lib/dualis/service/fake_data_dualis_scraper.dart index 27466fca..93291d68 100644 --- a/lib/dualis/service/fake_data_dualis_scraper.dart +++ b/lib/dualis/service/fake_data_dualis_scraper.dart @@ -14,6 +14,8 @@ import 'package:dhbwstudentapp/schedule/model/schedule.dart'; class FakeDataDualisScraper implements DualisScraper { bool _isLoggedIn = false; + FakeDataDualisScraper(); + @override bool isLoggedIn() { return _isLoggedIn; @@ -26,7 +28,7 @@ class FakeDataDualisScraper implements DualisScraper { await Future.delayed(const Duration(milliseconds: 200)); return Future.value([ - DualisModule( + const DualisModule( "Module1", "Informatik", "1.0", @@ -70,7 +72,7 @@ class FakeDataDualisScraper implements DualisScraper { ]) async { await Future.delayed(const Duration(milliseconds: 200)); return Future.value([ - DualisModule( + const DualisModule( "Module1", "Informatik", "1.0", @@ -86,7 +88,7 @@ class FakeDataDualisScraper implements DualisScraper { CancellationToken? cancellationToken, ]) async { await Future.delayed(const Duration(milliseconds: 200)); - return Future.value([DualisSemester("SoSe2020", "", [])]); + return Future.value([const DualisSemester("SoSe2020", "", [])]); } @override @@ -95,7 +97,7 @@ class FakeDataDualisScraper implements DualisScraper { ) async { await Future.delayed(const Duration(milliseconds: 200)); return Future.value( - StudyGrades( + const StudyGrades( 1.5, 1.5, 210, diff --git a/lib/dualis/service/parsing/access_denied_extract.dart b/lib/dualis/service/parsing/access_denied_extract.dart index d61f47a8..1c2cd464 100644 --- a/lib/dualis/service/parsing/access_denied_extract.dart +++ b/lib/dualis/service/parsing/access_denied_extract.dart @@ -1,4 +1,6 @@ class AccessDeniedExtract { + const AccessDeniedExtract(); + bool isAccessDeniedPage(String body) { return body.contains("Zugang verweigert"); } diff --git a/lib/dualis/service/parsing/all_modules_extract.dart b/lib/dualis/service/parsing/all_modules_extract.dart index 2196b904..bb5baa4d 100644 --- a/lib/dualis/service/parsing/all_modules_extract.dart +++ b/lib/dualis/service/parsing/all_modules_extract.dart @@ -5,6 +5,8 @@ import 'package:html/dom.dart'; import 'package:html/parser.dart'; class AllModulesExtract { + const AllModulesExtract(); + List extractAllModules(String? body) { try { return _extractAllModules(body); diff --git a/lib/dualis/service/parsing/exams_from_module_details_extract.dart b/lib/dualis/service/parsing/exams_from_module_details_extract.dart index 5e4abb4f..689d73ab 100644 --- a/lib/dualis/service/parsing/exams_from_module_details_extract.dart +++ b/lib/dualis/service/parsing/exams_from_module_details_extract.dart @@ -4,6 +4,8 @@ import 'package:dhbwstudentapp/dualis/service/parsing/parsing_utils.dart'; import 'package:html/parser.dart'; class ExamsFromModuleDetailsExtract { + const ExamsFromModuleDetailsExtract(); + List extractExamsFromModuleDetails(String? body) { try { return _extractExamsFromModuleDetails(body); diff --git a/lib/dualis/service/parsing/login_redirect_url_extract.dart b/lib/dualis/service/parsing/login_redirect_url_extract.dart index 7d1d4811..823f2e8b 100644 --- a/lib/dualis/service/parsing/login_redirect_url_extract.dart +++ b/lib/dualis/service/parsing/login_redirect_url_extract.dart @@ -1,6 +1,8 @@ import 'package:html/parser.dart'; class LoginRedirectUrlExtract { + const LoginRedirectUrlExtract(); + String? readRedirectUrl(String? body, String redirectUrl) { final document = parse(body); diff --git a/lib/dualis/service/parsing/modules_from_course_result_page_extract.dart b/lib/dualis/service/parsing/modules_from_course_result_page_extract.dart index 3a540183..106e70b3 100644 --- a/lib/dualis/service/parsing/modules_from_course_result_page_extract.dart +++ b/lib/dualis/service/parsing/modules_from_course_result_page_extract.dart @@ -7,6 +7,8 @@ import 'package:html/parser.dart'; class ModulesFromCourseResultPageExtract { final RegExp _extractUrlRegex = RegExp('dl_popUp\\("(.+?)"'); + ModulesFromCourseResultPageExtract(); + List extractModulesFromCourseResultPage( String? body, String endpointUrl, diff --git a/lib/dualis/service/parsing/monthly_schedule_extract.dart b/lib/dualis/service/parsing/monthly_schedule_extract.dart index 4b17151b..1d18577f 100644 --- a/lib/dualis/service/parsing/monthly_schedule_extract.dart +++ b/lib/dualis/service/parsing/monthly_schedule_extract.dart @@ -6,6 +6,8 @@ import 'package:html/parser.dart'; import 'package:intl/intl.dart'; class MonthlyScheduleExtract { + const MonthlyScheduleExtract(); + Schedule extractScheduleFromMonthly(String? body) { try { return _extractScheduleFromMonthly(body); @@ -36,9 +38,9 @@ class MonthlyScheduleExtract { } ScheduleEntry _extractEntry(Element appointment) { - final date = appointment.parent!.parent! - .querySelector(".tbsubhead a")! - .attributes["title"]; + final date = appointment.parent?.parent + ?.querySelector(".tbsubhead a") + ?.attributes["title"]; final information = appointment.attributes["title"]!; final informationParts = information.split(" / "); diff --git a/lib/dualis/service/parsing/parsing_utils.dart b/lib/dualis/service/parsing/parsing_utils.dart index 9e4caa18..434d8e65 100644 --- a/lib/dualis/service/parsing/parsing_utils.dart +++ b/lib/dualis/service/parsing/parsing_utils.dart @@ -45,10 +45,10 @@ Element getElementById( } class ParseException implements Exception { - Object? innerException; - StackTrace? trace; + final Object? innerException; + final StackTrace? trace; - ParseException.withInner(this.innerException, this.trace); + const ParseException.withInner(this.innerException, this.trace); @override String toString() { diff --git a/lib/dualis/service/parsing/semesters_from_course_result_page_extract.dart b/lib/dualis/service/parsing/semesters_from_course_result_page_extract.dart index 278d4e24..36be55a6 100644 --- a/lib/dualis/service/parsing/semesters_from_course_result_page_extract.dart +++ b/lib/dualis/service/parsing/semesters_from_course_result_page_extract.dart @@ -4,6 +4,8 @@ import 'package:html/dom.dart'; import 'package:html/parser.dart'; class SemestersFromCourseResultPageExtract { + const SemestersFromCourseResultPageExtract(); + List extractSemestersFromCourseResults( String? body, String endpointUrl, diff --git a/lib/dualis/service/parsing/study_grades_from_student_results_page_extract.dart b/lib/dualis/service/parsing/study_grades_from_student_results_page_extract.dart index 0da8da5d..632092cd 100644 --- a/lib/dualis/service/parsing/study_grades_from_student_results_page_extract.dart +++ b/lib/dualis/service/parsing/study_grades_from_student_results_page_extract.dart @@ -4,6 +4,8 @@ import 'package:html/dom.dart'; import 'package:html/parser.dart'; class StudyGradesFromStudentResultsPageExtract { + const StudyGradesFromStudentResultsPageExtract(); + StudyGrades extractStudyGradesFromStudentsResultsPage(String? body) { try { return _extractStudyGradesFromStudentsResultsPage(body); @@ -51,9 +53,10 @@ class StudyGradesFromStudentResultsPageExtract { neededCredits = neededCredits.replaceAll(",", "."); gainedCredits = gainedCredits.replaceAll(",", "."); - final credits = _Credits(); - credits.gainedCredits = double.tryParse(gainedCredits); - credits.totalCredits = double.tryParse(neededCredits); + final credits = _Credits( + double.tryParse(neededCredits), + double.tryParse(gainedCredits), + ); return credits; } @@ -73,20 +76,31 @@ class StudyGradesFromStudentResultsPageExtract { mainCoursesGpaRowCells[1].innerHtml, )!; - final _Gpa gpa = _Gpa(); - gpa.totalGpa = double.tryParse(totalGpa.replaceAll(",", ".")); - gpa.mainModulesGpa = double.tryParse(mainModulesGpa.replaceAll(",", ".")); + final _Gpa gpa = _Gpa( + double.tryParse(totalGpa.replaceAll(",", ".")), + double.tryParse(mainModulesGpa.replaceAll(",", ".")), + ); return gpa; } } class _Credits { - double? totalCredits; - double? gainedCredits; + final double? totalCredits; + final double? gainedCredits; + + const _Credits( + this.totalCredits, + this.gainedCredits, + ); } class _Gpa { - double? totalGpa; - double? mainModulesGpa; + final double? totalGpa; + final double? mainModulesGpa; + + const _Gpa( + this.totalGpa, + this.mainModulesGpa, + ); } diff --git a/lib/dualis/service/parsing/timeout_extract.dart b/lib/dualis/service/parsing/timeout_extract.dart index d63ad874..a565aebe 100644 --- a/lib/dualis/service/parsing/timeout_extract.dart +++ b/lib/dualis/service/parsing/timeout_extract.dart @@ -1,4 +1,6 @@ class TimeoutExtract { + const TimeoutExtract(); + bool isTimeoutErrorPage(String body) { return body.contains("Timeout!") && body.contains("Bitte melden Sie sich erneut"); diff --git a/lib/dualis/service/parsing/urls_from_main_page_extract.dart b/lib/dualis/service/parsing/urls_from_main_page_extract.dart index 9dad754f..94185cf1 100644 --- a/lib/dualis/service/parsing/urls_from_main_page_extract.dart +++ b/lib/dualis/service/parsing/urls_from_main_page_extract.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/dualis/service/parsing/parsing_utils.dart'; import 'package:html/parser.dart'; class UrlsFromMainPageExtract { + const UrlsFromMainPageExtract(); + void parseMainPage( String? body, DualisUrls dualsUrls, diff --git a/lib/dualis/service/session.dart b/lib/dualis/service/session.dart index a60f2e89..21d4eed5 100644 --- a/lib/dualis/service/session.dart +++ b/lib/dualis/service/session.dart @@ -13,7 +13,9 @@ import 'package:http_client_helper/http_client_helper.dart' as http; /// provided get and set methods. /// class Session { - Map _cookies = {}; + final Map cookies = {}; + + Session(); /// /// Execute a GET request and return the result body as string @@ -54,7 +56,7 @@ class Session { ); if (response == null && !requestCancellationToken.isCanceled) { - throw ServiceRequestFailed("Http request failed!"); + throw const ServiceRequestFailed("Http request failed!"); } _updateCookie(response!); @@ -112,7 +114,7 @@ class Session { ); if (response == null && !requestCancellationToken.isCanceled) { - throw ServiceRequestFailed("Http request failed!"); + throw const ServiceRequestFailed("Http request failed!"); } _updateCookie(response!); diff --git a/lib/dualis/ui/dualis_navigation_entry.dart b/lib/dualis/ui/dualis_navigation_entry.dart index 1435aef5..56482fc5 100644 --- a/lib/dualis/ui/dualis_navigation_entry.dart +++ b/lib/dualis/ui/dualis_navigation_entry.dart @@ -9,6 +9,8 @@ import 'package:kiwi/kiwi.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class DualisNavigationEntry extends NavigationEntry { + DualisNavigationEntry(); + @override Icon icon = const Icon(Icons.data_usage); @@ -27,7 +29,7 @@ class DualisNavigationEntry extends NavigationEntry { @override Widget build(BuildContext context) { - return DualisPage(); + return const DualisPage(); } @override @@ -42,7 +44,7 @@ class DualisNavigationEntry extends NavigationEntry { ? IconButton( icon: const Icon(Icons.help_outline), onPressed: () async { - await DualisHelpDialog().show(context); + await const DualisHelpDialog().show(context); }, tooltip: L.of(context).helpButtonTooltip, ) diff --git a/lib/dualis/ui/dualis_page.dart b/lib/dualis/ui/dualis_page.dart index a5ddbf59..1d37e2e7 100644 --- a/lib/dualis/ui/dualis_page.dart +++ b/lib/dualis/ui/dualis_page.dart @@ -9,6 +9,8 @@ import 'package:property_change_notifier/property_change_notifier.dart'; import 'package:provider/provider.dart'; class DualisPage extends StatelessWidget { + const DualisPage({super.key}); + @override Widget build(BuildContext context) { final StudyGradesViewModel viewModel = @@ -17,7 +19,7 @@ class DualisPage extends StatelessWidget { Widget widget; if (viewModel.loginState != LoginState.LoggedIn) { - widget = DualisLoginPage(); + widget = const DualisLoginPage(); } else { widget = PropertyChangeProvider( value: viewModel, @@ -27,12 +29,12 @@ class DualisPage extends StatelessWidget { PageDefinition( text: L.of(context).pageDualisOverview, icon: const Icon(Icons.dashboard), - builder: (BuildContext context) => StudyOverviewPage(), + builder: (BuildContext context) => const StudyOverviewPage(), ), PageDefinition( text: L.of(context).pageDualisExams, icon: const Icon(Icons.book), - builder: (BuildContext context) => ExamResultsPage(), + builder: (BuildContext context) => const ExamResultsPage(), ), ], ), diff --git a/lib/dualis/ui/exam_results_page/exam_results_page.dart b/lib/dualis/ui/exam_results_page/exam_results_page.dart index 1281b9dd..f5a73130 100644 --- a/lib/dualis/ui/exam_results_page/exam_results_page.dart +++ b/lib/dualis/ui/exam_results_page/exam_results_page.dart @@ -7,6 +7,8 @@ import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class ExamResultsPage extends StatelessWidget { + const ExamResultsPage({super.key}); + @override Widget build(BuildContext context) { return SizedBox( @@ -63,8 +65,8 @@ class ExamResultsPage extends StatelessWidget { StudyGradesViewModel? model, Set? properties, ) => - model!.currentSemester != null - ? buildModulesColumn(context, model) + model?.currentSemester != null + ? buildModulesColumn(context, model!) : const Padding( padding: EdgeInsets.fromLTRB(0, 16, 0, 0), child: Center(child: CircularProgressIndicator()), @@ -105,23 +107,26 @@ class ExamResultsPage extends StatelessWidget { ) { final dataTables = []; - var isFirstModule = true; - for (final module in viewModel.currentSemester!.modules) { - dataTables.add( - DataTable( - horizontalMargin: 24, - columnSpacing: 0, - dataRowHeight: 45, - headingRowHeight: 65, - rows: buildModuleDataRows(context, module), - columns: buildModuleColumns( - context, - module, - displayGradeHeader: isFirstModule, + final modules = viewModel.currentSemester?.modules; + if (modules != null) { + var isFirstModule = true; + for (final module in modules) { + dataTables.add( + DataTable( + horizontalMargin: 24, + columnSpacing: 0, + dataRowHeight: 45, + headingRowHeight: 65, + rows: buildModuleDataRows(context, module), + columns: buildModuleColumns( + context, + module, + displayGradeHeader: isFirstModule, + ), ), - ), - ); - isFirstModule = false; + ); + isFirstModule = false; + } } return dataTables; } diff --git a/lib/dualis/ui/login/dualis_login_page.dart b/lib/dualis/ui/login/dualis_login_page.dart index 3d684232..142cade3 100644 --- a/lib/dualis/ui/login/dualis_login_page.dart +++ b/lib/dualis/ui/login/dualis_login_page.dart @@ -5,14 +5,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class DualisLoginPage extends StatelessWidget { + const DualisLoginPage({super.key}); + @override Widget build(BuildContext context) { - final StudyGradesViewModel viewModel = + final StudyGradesViewModel model = Provider.of(context); - return buildLoginPage(context, viewModel); - } - Widget buildLoginPage(BuildContext context, StudyGradesViewModel model) { return SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/dualis/ui/study_overview/study_overview_page.dart b/lib/dualis/ui/study_overview/study_overview_page.dart index 679aa187..e68c14c0 100644 --- a/lib/dualis/ui/study_overview/study_overview_page.dart +++ b/lib/dualis/ui/study_overview/study_overview_page.dart @@ -5,6 +5,8 @@ import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class StudyOverviewPage extends StatelessWidget { + const StudyOverviewPage({super.key}); + @override Widget build(BuildContext context) { return SizedBox( @@ -40,7 +42,7 @@ class StudyOverviewPage extends StatelessWidget { StudyGradesViewModel? model, Set? properties, ) => - model!.studyGrades != null + model?.studyGrades != null ? Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -51,7 +53,7 @@ class StudyOverviewPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.baseline, children: [ Text( - model.studyGrades!.gpaTotal.toString(), + model!.studyGrades!.gpaTotal.toString(), style: Theme.of(context).textTheme.headline3, ), Padding( @@ -129,8 +131,8 @@ class StudyOverviewPage extends StatelessWidget { StudyGradesViewModel? model, Set? properties, ) => - model!.allModules != null - ? buildModulesDataTable(context, model) + model?.allModules != null + ? buildModulesDataTable(context, model!) : buildProgressIndicator(), ), ], diff --git a/lib/dualis/ui/widgets/dualis_help_dialog.dart b/lib/dualis/ui/widgets/dualis_help_dialog.dart index 30b39c0e..489d8743 100644 --- a/lib/dualis/ui/widgets/dualis_help_dialog.dart +++ b/lib/dualis/ui/widgets/dualis_help_dialog.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/common/ui/widgets/help_dialog.dart'; import 'package:flutter/material.dart'; class DualisHelpDialog extends HelpDialog { + const DualisHelpDialog(); + @override String content(BuildContext context) { return L.of(context).dualisHelpDialogContent; diff --git a/lib/dualis/ui/widgets/grade_state_icon.dart b/lib/dualis/ui/widgets/grade_state_icon.dart index 5984b6e4..31729e6d 100644 --- a/lib/dualis/ui/widgets/grade_state_icon.dart +++ b/lib/dualis/ui/widgets/grade_state_icon.dart @@ -4,10 +4,7 @@ import 'package:flutter/material.dart'; class GradeStateIcon extends StatelessWidget { final ExamState? state; - const GradeStateIcon({ - Key? key, - required this.state, - }) : super(key: key); + const GradeStateIcon({super.key, required this.state}); @override Widget build(BuildContext context) { diff --git a/lib/dualis/ui/widgets/login_form_widget.dart b/lib/dualis/ui/widgets/login_form_widget.dart index 0beb44a7..1ebaca9d 100644 --- a/lib/dualis/ui/widgets/login_form_widget.dart +++ b/lib/dualis/ui/widgets/login_form_widget.dart @@ -19,7 +19,7 @@ class LoginForm extends StatefulWidget { final String loginFailedText; const LoginForm({ - Key? key, + super.key, required this.onLogin, required this.title, required this.loginFailedText, @@ -27,7 +27,7 @@ class LoginForm extends StatefulWidget { required this.onSaveCredentials, required this.onClearCredentials, required this.getDoSaveCredentials, - }) : super(key: key); + }); @override _LoginFormState createState() => _LoginFormState(); @@ -41,6 +41,8 @@ class _LoginFormState extends State { final CredentialsEditingController _controller = CredentialsEditingController(); + _LoginFormState(); + @override void initState() { super.initState(); diff --git a/lib/information/ui/useful_information_navigation_entry.dart b/lib/information/ui/useful_information_navigation_entry.dart index 2b05e8b8..d308c6bc 100644 --- a/lib/information/ui/useful_information_navigation_entry.dart +++ b/lib/information/ui/useful_information_navigation_entry.dart @@ -5,9 +5,11 @@ import 'package:dhbwstudentapp/ui/navigation/navigation_entry.dart'; import 'package:flutter/material.dart'; class UsefulInformationNavigationEntry extends NavigationEntry { + UsefulInformationNavigationEntry(); + @override Widget build(BuildContext context) { - return UsefulInformationPage(); + return const UsefulInformationPage(); } @override diff --git a/lib/information/ui/usefulinformation/useful_information_page.dart b/lib/information/ui/usefulinformation/useful_information_page.dart index 61a61a5f..2fb49074 100644 --- a/lib/information/ui/usefulinformation/useful_information_page.dart +++ b/lib/information/ui/usefulinformation/useful_information_page.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; class UsefulInformationPage extends StatelessWidget { + const UsefulInformationPage({super.key}); + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/native/widget/android_widget_helper.dart b/lib/native/widget/android_widget_helper.dart index 68ebf490..f58d734d 100644 --- a/lib/native/widget/android_widget_helper.dart +++ b/lib/native/widget/android_widget_helper.dart @@ -6,6 +6,7 @@ import 'package:flutter/services.dart'; /// class AndroidWidgetHelper implements WidgetHelper { static const platform = MethodChannel('de.bennik2000.dhbwstudentapp/widget'); + const AndroidWidgetHelper(); @override Future disableWidget() async { diff --git a/lib/native/widget/ios_widget_helper.dart b/lib/native/widget/ios_widget_helper.dart index d9a55ab7..c495d12c 100644 --- a/lib/native/widget/ios_widget_helper.dart +++ b/lib/native/widget/ios_widget_helper.dart @@ -8,6 +8,8 @@ import 'package:flutter_widgetkit/flutter_widgetkit.dart'; class IOSWidgetHelper implements WidgetHelper { static const platform = MethodChannel('de.bennik2000.dhbwstudentapp/widget'); + const IOSWidgetHelper(); + @override Future disableWidget() async { try { diff --git a/lib/native/widget/widget_helper.dart b/lib/native/widget/widget_helper.dart index e0f03028..ab972564 100644 --- a/lib/native/widget/widget_helper.dart +++ b/lib/native/widget/widget_helper.dart @@ -8,17 +8,15 @@ import 'package:dhbwstudentapp/native/widget/ios_widget_helper.dart'; /// methods to enable/disable or update the widget /// class WidgetHelper { - static WidgetHelper? _instance; + static late WidgetHelper _instance; WidgetHelper() { - if (_instance != null) return; - if (Platform.isAndroid) { - _instance = AndroidWidgetHelper(); + _instance = const AndroidWidgetHelper(); } else if (Platform.isIOS) { - _instance = IOSWidgetHelper(); + _instance = const IOSWidgetHelper(); } else { - _instance = VoidWidgetHelper(); + _instance = const VoidWidgetHelper(); } } @@ -27,14 +25,14 @@ class WidgetHelper { /// scheduled and will happen soon. /// Future requestWidgetRefresh() { - return _instance!.requestWidgetRefresh(); + return _instance.requestWidgetRefresh(); } /// /// Checks if widgets are supported by the device /// Future areWidgetsSupported() { - return _instance!.areWidgetsSupported(); + return _instance.areWidgetsSupported(); } /// @@ -42,7 +40,7 @@ class WidgetHelper { /// its full functionality. /// Future enableWidget() { - return _instance!.enableWidget(); + return _instance.enableWidget(); } /// @@ -50,7 +48,7 @@ class WidgetHelper { /// only provide placeholder content or limited functionality. /// Future disableWidget() { - return _instance!.disableWidget(); + return _instance.disableWidget(); } } @@ -58,6 +56,8 @@ class WidgetHelper { /// Implementation of the WidgetHelper which does nothing /// class VoidWidgetHelper implements WidgetHelper { + const VoidWidgetHelper(); + @override Future disableWidget() { return Future.value(); diff --git a/lib/native/widget/widget_update_callback.dart b/lib/native/widget/widget_update_callback.dart index 17324ae7..7fb14f42 100644 --- a/lib/native/widget/widget_update_callback.dart +++ b/lib/native/widget/widget_update_callback.dart @@ -9,7 +9,7 @@ import 'package:dhbwstudentapp/schedule/model/schedule.dart'; class WidgetUpdateCallback { final WidgetHelper _widgetHelper; - WidgetUpdateCallback(this._widgetHelper); + const WidgetUpdateCallback(this._widgetHelper); void registerCallback(ScheduleProvider provider) { provider.addScheduleUpdatedCallback(_callback); diff --git a/lib/schedule/background/background_schedule_update.dart b/lib/schedule/background/background_schedule_update.dart index bf7a9f6f..e58ce7e9 100644 --- a/lib/schedule/background/background_schedule_update.dart +++ b/lib/schedule/background/background_schedule_update.dart @@ -10,7 +10,7 @@ class BackgroundScheduleUpdate extends TaskCallback { final ScheduleSourceProvider scheduleSource; final WorkSchedulerService scheduler; - BackgroundScheduleUpdate( + const BackgroundScheduleUpdate( this.scheduleProvider, this.scheduleSource, this.scheduler, diff --git a/lib/schedule/background/calendar_synchronizer.dart b/lib/schedule/background/calendar_synchronizer.dart index 6d04fe49..1bc0477a 100644 --- a/lib/schedule/background/calendar_synchronizer.dart +++ b/lib/schedule/background/calendar_synchronizer.dart @@ -12,7 +12,7 @@ class CalendarSynchronizer { final ScheduleSourceProvider scheduleSourceProvider; final PreferencesProvider preferencesProvider; - CalendarSynchronizer( + const CalendarSynchronizer( this.scheduleProvider, this.scheduleSourceProvider, this.preferencesProvider, diff --git a/lib/schedule/business/schedule_diff_calculator.dart b/lib/schedule/business/schedule_diff_calculator.dart index 80e87cf0..c8e1750d 100644 --- a/lib/schedule/business/schedule_diff_calculator.dart +++ b/lib/schedule/business/schedule_diff_calculator.dart @@ -2,6 +2,8 @@ import 'package:dhbwstudentapp/schedule/model/schedule.dart'; import 'package:dhbwstudentapp/schedule/model/schedule_entry.dart'; class ScheduleDiffCalculator { + const ScheduleDiffCalculator(); + ScheduleDiff calculateDiff( Schedule oldSchedule, Schedule newSchedule, @@ -174,7 +176,7 @@ class ScheduleDiff { final List removedEntries; final List updatedEntries; - ScheduleDiff({ + const ScheduleDiff({ required this.addedEntries, required this.removedEntries, required this.updatedEntries, @@ -191,5 +193,5 @@ class UpdatedEntry { final ScheduleEntry entry; final List properties; - UpdatedEntry(this.entry, this.properties); + const UpdatedEntry(this.entry, this.properties); } diff --git a/lib/schedule/business/schedule_filter.dart b/lib/schedule/business/schedule_filter.dart index 286a03f9..3cd31f32 100644 --- a/lib/schedule/business/schedule_filter.dart +++ b/lib/schedule/business/schedule_filter.dart @@ -5,7 +5,7 @@ import 'package:dhbwstudentapp/schedule/model/schedule_entry.dart'; class ScheduleFilter { final ScheduleFilterRepository _scheduleFilterRepository; - ScheduleFilter(this._scheduleFilterRepository); + const ScheduleFilter(this._scheduleFilterRepository); Future filter(Schedule original) async { final allHiddenNames = diff --git a/lib/schedule/business/schedule_provider.dart b/lib/schedule/business/schedule_provider.dart index d15e1bc5..32345a35 100644 --- a/lib/schedule/business/schedule_provider.dart +++ b/lib/schedule/business/schedule_provider.dart @@ -28,12 +28,11 @@ class ScheduleProvider { final PreferencesProvider _preferencesProvider; final ScheduleSourceProvider _scheduleSource; final ScheduleEntryRepository _scheduleEntryRepository; - final ScheduleFilterRepository _scheduleFilterRepository; final ScheduleQueryInformationRepository _scheduleQueryInformationRepository; final List _scheduleUpdatedCallbacks = []; - late ScheduleFilter _scheduleFilter; + final ScheduleFilter _scheduleFilter; final List _scheduleEntryChangedCallbacks = []; @@ -43,10 +42,8 @@ class ScheduleProvider { this._scheduleEntryRepository, this._scheduleQueryInformationRepository, this._preferencesProvider, - this._scheduleFilterRepository, - ) { - _scheduleFilter = ScheduleFilter(_scheduleFilterRepository); - } + ScheduleFilterRepository scheduleFilterRepository, + ) : _scheduleFilter = ScheduleFilter(scheduleFilterRepository); Future getCachedSchedule(DateTime start, DateTime end) async { var cachedSchedule = @@ -121,8 +118,8 @@ class ScheduleProvider { final oldSchedule = await _scheduleEntryRepository.queryScheduleBetweenDates(start, end); - final diff = - ScheduleDiffCalculator().calculateDiff(oldSchedule, updatedSchedule); + final diff = const ScheduleDiffCalculator() + .calculateDiff(oldSchedule, updatedSchedule); final cleanedDiff = await _cleanDiffFromNewlyQueriedEntries(start, end, diff); diff --git a/lib/schedule/business/schedule_source_provider.dart b/lib/schedule/business/schedule_source_provider.dart index 996b2312..fefc72ed 100644 --- a/lib/schedule/business/schedule_source_provider.dart +++ b/lib/schedule/business/schedule_source_provider.dart @@ -29,7 +29,7 @@ class ScheduleSourceProvider { final ScheduleEntryRepository _scheduleEntryRepository; final ScheduleQueryInformationRepository _scheduleQueryInformationRepository; - ScheduleSource _currentScheduleSource = InvalidScheduleSource(); + ScheduleSource _currentScheduleSource = const InvalidScheduleSource(); ScheduleSource get currentScheduleSource => _currentScheduleSource; @@ -46,7 +46,7 @@ class ScheduleSourceProvider { Future setupScheduleSource() async { final scheduleSourceType = await _getScheduleSourceType(); - ScheduleSource scheduleSource = InvalidScheduleSource(); + ScheduleSource scheduleSource = const InvalidScheduleSource(); final initializer = { ScheduleSourceType.Dualis: () async => _dualisScheduleSource(), @@ -84,7 +84,7 @@ class ScheduleSourceProvider { DualisScheduleSource(KiwiContainer().resolve(), credentials); return ErrorReportScheduleSourceDecorator(dualis); } else { - return InvalidScheduleSource(); + return const InvalidScheduleSource(); } } @@ -104,7 +104,7 @@ class ScheduleSourceProvider { return source; } - return InvalidScheduleSource(); + return const InvalidScheduleSource(); } Future _icalScheduleSource() async { @@ -123,7 +123,7 @@ class ScheduleSourceProvider { } } - return InvalidScheduleSource(); + return const InvalidScheduleSource(); } Future setupForRapla(String? url) async { diff --git a/lib/schedule/data/schedule_entry_repository.dart b/lib/schedule/data/schedule_entry_repository.dart index 039f260d..321b0886 100644 --- a/lib/schedule/data/schedule_entry_repository.dart +++ b/lib/schedule/data/schedule_entry_repository.dart @@ -5,7 +5,7 @@ import 'package:dhbwstudentapp/schedule/model/schedule_entry.dart'; class ScheduleEntryRepository { final DatabaseAccess _database; - ScheduleEntryRepository(this._database); + const ScheduleEntryRepository(this._database); Future queryScheduleForDay(DateTime date) async { return queryScheduleBetweenDates(date, date.add(const Duration(days: 1))); diff --git a/lib/schedule/data/schedule_filter_repository.dart b/lib/schedule/data/schedule_filter_repository.dart index 1ef9e7c3..2aa5c4cb 100644 --- a/lib/schedule/data/schedule_filter_repository.dart +++ b/lib/schedule/data/schedule_filter_repository.dart @@ -3,7 +3,7 @@ import 'package:dhbwstudentapp/common/data/database_access.dart'; class ScheduleFilterRepository { final DatabaseAccess _database; - ScheduleFilterRepository(this._database); + const ScheduleFilterRepository(this._database); Future> queryAllHiddenNames() async { final rows = await _database.queryRows("ScheduleEntryFilters"); diff --git a/lib/schedule/data/schedule_query_information_repository.dart b/lib/schedule/data/schedule_query_information_repository.dart index c76df96d..64d5b716 100644 --- a/lib/schedule/data/schedule_query_information_repository.dart +++ b/lib/schedule/data/schedule_query_information_repository.dart @@ -4,7 +4,7 @@ import 'package:dhbwstudentapp/schedule/model/schedule_query_information.dart'; class ScheduleQueryInformationRepository { final DatabaseAccess _database; - ScheduleQueryInformationRepository(this._database); + const ScheduleQueryInformationRepository(this._database); Future getOldestQueryTimeBetweenDates( DateTime start, diff --git a/lib/schedule/model/schedule_query_result.dart b/lib/schedule/model/schedule_query_result.dart index 421807bc..4b34b5f8 100644 --- a/lib/schedule/model/schedule_query_result.dart +++ b/lib/schedule/model/schedule_query_result.dart @@ -6,7 +6,7 @@ class ScheduleQueryResult { bool get hasError => errors.isNotEmpty; - ScheduleQueryResult(this.schedule, this.errors); + const ScheduleQueryResult(this.schedule, this.errors); } class ParseError { diff --git a/lib/schedule/service/error_report_schedule_source_decorator.dart b/lib/schedule/service/error_report_schedule_source_decorator.dart index 24739d2a..3f5e785f 100644 --- a/lib/schedule/service/error_report_schedule_source_decorator.dart +++ b/lib/schedule/service/error_report_schedule_source_decorator.dart @@ -6,7 +6,7 @@ import 'package:dhbwstudentapp/schedule/service/schedule_source.dart'; class ErrorReportScheduleSourceDecorator extends ScheduleSource { final ScheduleSource _scheduleSource; - ErrorReportScheduleSourceDecorator(this._scheduleSource); + const ErrorReportScheduleSourceDecorator(this._scheduleSource); @override Future querySchedule( diff --git a/lib/schedule/service/ical/ical_parser.dart b/lib/schedule/service/ical/ical_parser.dart index 48fb90e0..f60dd84b 100644 --- a/lib/schedule/service/ical/ical_parser.dart +++ b/lib/schedule/service/ical/ical_parser.dart @@ -6,6 +6,8 @@ import 'package:dhbwstudentapp/schedule/model/schedule_query_result.dart'; /// Parses an ICAL file extracts all schedule entries /// class IcalParser { + IcalParser(); + /// Matches a calendar entry. The first group contains the text between /// the BEGIN:VEVENT and END:VEVENT final String calendarEntryRegex = "BEGIN:VEVENT(.*?)END:VEVENT"; diff --git a/lib/schedule/service/ical/ical_schedule_source.dart b/lib/schedule/service/ical/ical_schedule_source.dart index 6242a8cb..0f7cd4bb 100644 --- a/lib/schedule/service/ical/ical_schedule_source.dart +++ b/lib/schedule/service/ical/ical_schedule_source.dart @@ -60,7 +60,7 @@ class IcalScheduleSource extends ScheduleSource { ); if (response == null && !requestCancellationToken.isCanceled) { - throw ServiceRequestFailed("Http request failed!"); + throw const ServiceRequestFailed("Http request failed!"); } return response; diff --git a/lib/schedule/service/invalid_schedule_source.dart b/lib/schedule/service/invalid_schedule_source.dart index 7f55936b..8a15ce5b 100644 --- a/lib/schedule/service/invalid_schedule_source.dart +++ b/lib/schedule/service/invalid_schedule_source.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/schedule/model/schedule_query_result.dart'; import 'package:dhbwstudentapp/schedule/service/schedule_source.dart'; class InvalidScheduleSource extends ScheduleSource { + const InvalidScheduleSource(); + @override Future querySchedule( DateTime? from, diff --git a/lib/schedule/service/mannheim/mannheim_course_response_parser.dart b/lib/schedule/service/mannheim/mannheim_course_response_parser.dart index 779fe485..eb57d14c 100644 --- a/lib/schedule/service/mannheim/mannheim_course_response_parser.dart +++ b/lib/schedule/service/mannheim/mannheim_course_response_parser.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/schedule/service/mannheim/mannheim_course_scraper import 'package:html/parser.dart'; class MannheimCourseResponseParser { + const MannheimCourseResponseParser(); + List parseCoursePage(String body) { final document = parse(body); diff --git a/lib/schedule/service/mannheim/mannheim_course_scraper.dart b/lib/schedule/service/mannheim/mannheim_course_scraper.dart index b463a118..7b24da9d 100644 --- a/lib/schedule/service/mannheim/mannheim_course_scraper.dart +++ b/lib/schedule/service/mannheim/mannheim_course_scraper.dart @@ -10,10 +10,12 @@ class Course { final String icalUrl; final String scheduleId; - Course(this.name, this.icalUrl, this.title, this.scheduleId); + const Course(this.name, this.icalUrl, this.title, this.scheduleId); } class MannheimCourseScraper { + const MannheimCourseScraper(); + Future> loadCourses([ CancellationToken? cancellationToken, ]) async { @@ -24,7 +26,8 @@ class MannheimCourseScraper { cancellationToken, ); - return MannheimCourseResponseParser().parseCoursePage(coursesPage.body); + return const MannheimCourseResponseParser() + .parseCoursePage(coursesPage.body); } Future _makeRequest( @@ -42,7 +45,7 @@ class MannheimCourseScraper { ); if (response == null && !requestCancellationToken.isCanceled) { - throw ServiceRequestFailed("Http request failed!"); + throw const ServiceRequestFailed("Http request failed!"); } return response!; @@ -51,7 +54,7 @@ class MannheimCourseScraper { throw OperationCancelledException(); } catch (ex) { if (!requestCancellationToken.isCanceled) rethrow; - throw ServiceRequestFailed("Http request failed!"); + throw const ServiceRequestFailed("Http request failed!"); } finally { cancellationToken.cancellationCallback = null; } diff --git a/lib/schedule/service/rapla/rapla_response_parser.dart b/lib/schedule/service/rapla/rapla_response_parser.dart index a8c6ac06..bf5cab4b 100644 --- a/lib/schedule/service/rapla/rapla_response_parser.dart +++ b/lib/schedule/service/rapla/rapla_response_parser.dart @@ -8,6 +8,8 @@ import 'package:html/parser.dart' show parse; /// Parsing implementation which parses the response of the rapla schedule source. /// class RaplaResponseParser { + RaplaResponseParser(); + ScheduleQueryResult parseSchedule(String responseBody) { final document = parse(responseBody); diff --git a/lib/schedule/service/rapla/rapla_schedule_source.dart b/lib/schedule/service/rapla/rapla_schedule_source.dart index 9b870fa2..f1abd688 100644 --- a/lib/schedule/service/rapla/rapla_schedule_source.dart +++ b/lib/schedule/service/rapla/rapla_schedule_source.dart @@ -156,7 +156,7 @@ class RaplaScheduleSource extends ScheduleSource { ); if (response == null && !requestCancellationToken.isCanceled) { - throw ServiceRequestFailed("Http request failed!"); + throw const ServiceRequestFailed("Http request failed!"); } return response; @@ -217,6 +217,7 @@ enum FailureReason { ParseError, } +// TODO: [Leptopoda] make enum class ScheduleOrFailure { final FailureReason reason; final Schedule? schedule; @@ -225,16 +226,16 @@ class ScheduleOrFailure { bool get success => reason == FailureReason.Success; - ScheduleOrFailure.success(this.schedule) + const ScheduleOrFailure.success(this.schedule) : reason = FailureReason.Success, exception = null, trace = null; - ScheduleOrFailure.failParseError(this.exception, this.trace) + const ScheduleOrFailure.failParseError(this.exception, this.trace) : reason = FailureReason.ParseError, schedule = null; - ScheduleOrFailure.failRequestError(this.exception, this.trace) + const ScheduleOrFailure.failRequestError(this.exception, this.trace) : reason = FailureReason.RequestError, schedule = null; } diff --git a/lib/schedule/service/schedule_prettifier.dart b/lib/schedule/service/schedule_prettifier.dart index 37cad3ed..75752cb7 100644 --- a/lib/schedule/service/schedule_prettifier.dart +++ b/lib/schedule/service/schedule_prettifier.dart @@ -2,6 +2,8 @@ import 'package:dhbwstudentapp/schedule/model/schedule.dart'; import 'package:dhbwstudentapp/schedule/model/schedule_entry.dart'; class SchedulePrettifier { + SchedulePrettifier(); + final RegExp onlinePrefixRegExp = RegExp(r'\(?online\)?([ -]*)', caseSensitive: false); final RegExp onlineSuffixRegExp = diff --git a/lib/schedule/service/schedule_source.dart b/lib/schedule/service/schedule_source.dart index f0109365..d09e33b9 100644 --- a/lib/schedule/service/schedule_source.dart +++ b/lib/schedule/service/schedule_source.dart @@ -2,6 +2,8 @@ import 'package:dhbwstudentapp/common/util/cancellation_token.dart'; import 'package:dhbwstudentapp/schedule/model/schedule_query_result.dart'; abstract class ScheduleSource { + const ScheduleSource(); + /// /// Queries the schedule from the implemented service. The resulting schedule /// contains all entries between the `from` and `to` date. @@ -22,7 +24,7 @@ class ScheduleQueryFailedException implements Exception { final dynamic innerException; final StackTrace? trace; - ScheduleQueryFailedException(this.innerException, [this.trace]); + const ScheduleQueryFailedException(this.innerException, [this.trace]); @override String toString() { @@ -33,7 +35,7 @@ class ScheduleQueryFailedException implements Exception { class ServiceRequestFailed implements Exception { final String message; - ServiceRequestFailed(this.message); + const ServiceRequestFailed(this.message); @override String toString() { diff --git a/lib/schedule/ui/dailyschedule/daily_schedule_page.dart b/lib/schedule/ui/dailyschedule/daily_schedule_page.dart index 0bbcb4c7..7f64a5e3 100644 --- a/lib/schedule/ui/dailyschedule/daily_schedule_page.dart +++ b/lib/schedule/ui/dailyschedule/daily_schedule_page.dart @@ -8,18 +8,12 @@ import 'package:intl/intl.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; import 'package:provider/provider.dart'; -class DailySchedulePage extends StatefulWidget { - const DailySchedulePage({Key? key}) : super(key: key); - @override - _DailySchedulePageState createState() => _DailySchedulePageState(); -} - -class _DailySchedulePageState extends State { - late DailyScheduleViewModel viewModel; +class DailySchedulePage extends StatelessWidget { + const DailySchedulePage({super.key}); @override Widget build(BuildContext context) { - viewModel = Provider.of(context); + final viewModel = Provider.of(context); final textTheme = Theme.of(context).textTheme; final dailyScheduleEntryTitle = @@ -84,7 +78,7 @@ class _DailySchedulePageState extends State { ) else Column( - children: buildEntryWidgets(), + children: buildEntryWidgets(viewModel), ) ], ), @@ -93,14 +87,14 @@ class _DailySchedulePageState extends State { ); } - List buildEntryWidgets() { + List buildEntryWidgets(DailyScheduleViewModel viewModel) { final entryWidgets = []; final now = DateTime.now(); var nowIndicatorInserted = false; for (final entry in viewModel.schedule.entries) { if (!nowIndicatorInserted && (entry.end.isAfter(now))) { - entryWidgets.add(CurrentTimeIndicatorWidget()); + entryWidgets.add(const CurrentTimeIndicatorWidget()); nowIndicatorInserted = true; } @@ -113,7 +107,9 @@ class _DailySchedulePageState extends State { ), ); } - if (!nowIndicatorInserted) entryWidgets.add(CurrentTimeIndicatorWidget()); + if (!nowIndicatorInserted) { + entryWidgets.add(const CurrentTimeIndicatorWidget()); + } return entryWidgets; } } diff --git a/lib/schedule/ui/dailyschedule/widgets/current_time_indicator_widget.dart b/lib/schedule/ui/dailyschedule/widgets/current_time_indicator_widget.dart index 25124812..74141dd7 100644 --- a/lib/schedule/ui/dailyschedule/widgets/current_time_indicator_widget.dart +++ b/lib/schedule/ui/dailyschedule/widgets/current_time_indicator_widget.dart @@ -2,6 +2,8 @@ import 'package:dhbwstudentapp/common/ui/schedule_theme.dart'; import 'package:flutter/material.dart'; class CurrentTimeIndicatorWidget extends StatelessWidget { + const CurrentTimeIndicatorWidget({super.key}); + @override Widget build(BuildContext context) { final scheduleTheme = Theme.of(context).extension()!; diff --git a/lib/schedule/ui/dailyschedule/widgets/daily_schedule_entry_widget.dart b/lib/schedule/ui/dailyschedule/widgets/daily_schedule_entry_widget.dart index 569b7906..15068a23 100644 --- a/lib/schedule/ui/dailyschedule/widgets/daily_schedule_entry_widget.dart +++ b/lib/schedule/ui/dailyschedule/widgets/daily_schedule_entry_widget.dart @@ -9,8 +9,7 @@ import 'package:intl/intl.dart'; class DailyScheduleEntryWidget extends StatelessWidget { final ScheduleEntry scheduleEntry; - const DailyScheduleEntryWidget({Key? key, required this.scheduleEntry}) - : super(key: key); + const DailyScheduleEntryWidget({super.key, required this.scheduleEntry}); @override Widget build(BuildContext context) { @@ -87,7 +86,8 @@ class DailyScheduleEntryWidget extends StatelessWidget { scheduleEntry.type, ), style: textTheme.bodyText2?.merge( - customTextThme.dailyScheduleEntryType,), + customTextThme.dailyScheduleEntryType, + ), ), ], ), diff --git a/lib/schedule/ui/notification/next_day_information_notification.dart b/lib/schedule/ui/notification/next_day_information_notification.dart index 4eea6189..54cceeb5 100644 --- a/lib/schedule/ui/notification/next_day_information_notification.dart +++ b/lib/schedule/ui/notification/next_day_information_notification.dart @@ -16,7 +16,7 @@ class NextDayInformationNotification extends TaskCallback { final WorkSchedulerService _scheduler; final L _localization; - NextDayInformationNotification( + const NextDayInformationNotification( this._notificationApi, this._scheduleEntryRepository, this._scheduler, diff --git a/lib/schedule/ui/notification/schedule_changed_notification.dart b/lib/schedule/ui/notification/schedule_changed_notification.dart index 9c57960c..f7f2b0d6 100644 --- a/lib/schedule/ui/notification/schedule_changed_notification.dart +++ b/lib/schedule/ui/notification/schedule_changed_notification.dart @@ -8,7 +8,7 @@ class ScheduleChangedNotification { final NotificationApi notificationApi; final L _localization; - ScheduleChangedNotification(this.notificationApi, this._localization); + const ScheduleChangedNotification(this.notificationApi, this._localization); void showNotification(ScheduleDiff scheduleDiff) { showEntriesAddedNotifications(scheduleDiff); diff --git a/lib/schedule/ui/schedule_navigation_entry.dart b/lib/schedule/ui/schedule_navigation_entry.dart index 19e29b99..0f77d817 100644 --- a/lib/schedule/ui/schedule_navigation_entry.dart +++ b/lib/schedule/ui/schedule_navigation_entry.dart @@ -9,6 +9,8 @@ import 'package:kiwi/kiwi.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class ScheduleNavigationEntry extends NavigationEntry { + ScheduleNavigationEntry(); + @override Icon icon = const Icon(Icons.calendar_today); @@ -42,7 +44,7 @@ class ScheduleNavigationEntry extends NavigationEntry { : IconButton( icon: const Icon(Icons.help_outline), onPressed: () async { - await ScheduleHelpDialog().show(context); + await const ScheduleHelpDialog().show(context); }, tooltip: L.of(context).helpButtonTooltip, ), diff --git a/lib/schedule/ui/schedule_page.dart b/lib/schedule/ui/schedule_page.dart index d8ded79b..f41cf23a 100644 --- a/lib/schedule/ui/schedule_page.dart +++ b/lib/schedule/ui/schedule_page.dart @@ -11,7 +11,7 @@ import 'package:kiwi/kiwi.dart'; import 'package:provider/provider.dart'; class SchedulePage extends StatefulWidget { - const SchedulePage({Key? key}) : super(key: key); + const SchedulePage({super.key}); @override _SchedulePageState createState() => _SchedulePageState(); } @@ -27,12 +27,14 @@ class _SchedulePageState extends State { KiwiContainer().resolve(), ); + _SchedulePageState(); + @override Widget build(BuildContext context) { final ScheduleViewModel viewModel = Provider.of(context); if (!viewModel.didSetupProperly) { - return ScheduleEmptyState(); + return const ScheduleEmptyState(); } else { return PagerWidget( pages: [ diff --git a/lib/schedule/ui/weeklyschedule/filter/filter_view_model.dart b/lib/schedule/ui/weeklyschedule/filter/filter_view_model.dart index fb111d83..98b6ba17 100644 --- a/lib/schedule/ui/weeklyschedule/filter/filter_view_model.dart +++ b/lib/schedule/ui/weeklyschedule/filter/filter_view_model.dart @@ -48,7 +48,7 @@ class FilterViewModel extends BaseViewModel { class ScheduleEntryFilterState { bool? isDisplayed; - String? entryName; + final String? entryName; ScheduleEntryFilterState(this.isDisplayed, this.entryName); } diff --git a/lib/schedule/ui/weeklyschedule/filter/schedule_filter_page.dart b/lib/schedule/ui/weeklyschedule/filter/schedule_filter_page.dart index dbe1ad5b..79c30c74 100644 --- a/lib/schedule/ui/weeklyschedule/filter/schedule_filter_page.dart +++ b/lib/schedule/ui/weeklyschedule/filter/schedule_filter_page.dart @@ -5,6 +5,8 @@ import 'package:kiwi/kiwi.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class ScheduleFilterPage extends StatelessWidget { + ScheduleFilterPage({super.key}); + final FilterViewModel _viewModel = FilterViewModel( KiwiContainer().resolve(), KiwiContainer().resolve(), @@ -80,6 +82,8 @@ class FilterStateRow extends StatefulWidget { class _FilterStateRowState extends State { bool? isChecked = false; + _FilterStateRowState(); + @override void initState() { super.initState(); diff --git a/lib/schedule/ui/weeklyschedule/schedule_entry_detail_bottom_sheet.dart b/lib/schedule/ui/weeklyschedule/schedule_entry_detail_bottom_sheet.dart index a056484c..3691ea78 100644 --- a/lib/schedule/ui/weeklyschedule/schedule_entry_detail_bottom_sheet.dart +++ b/lib/schedule/ui/weeklyschedule/schedule_entry_detail_bottom_sheet.dart @@ -7,19 +7,21 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class ScheduleEntryDetailBottomSheet extends StatelessWidget { - final ScheduleEntry? scheduleEntry; + final ScheduleEntry scheduleEntry; - const ScheduleEntryDetailBottomSheet({Key? key, this.scheduleEntry}) - : super(key: key); + const ScheduleEntryDetailBottomSheet({ + super.key, + required this.scheduleEntry, + }); @override Widget build(BuildContext context) { final formatter = DateFormat.Hm(L.of(context).locale.languageCode); - final timeStart = formatter.format(scheduleEntry!.start); - final timeEnd = formatter.format(scheduleEntry!.end); + final timeStart = formatter.format(scheduleEntry.start); + final timeEnd = formatter.format(scheduleEntry.end); final typeString = - scheduleEntryTypeToReadableString(context, scheduleEntry!.type); + scheduleEntryTypeToReadableString(context, scheduleEntry.type); final textTheme = Theme.of(context).textTheme; final customTextThme = Theme.of(context).extension(); @@ -87,7 +89,7 @@ class ScheduleEntryDetailBottomSheet extends StatelessWidget { child: Padding( padding: const EdgeInsets.fromLTRB(16, 0, 0, 0), child: Text( - scheduleEntry!.title, + scheduleEntry.title, softWrap: true, style: Theme.of(context).textTheme.subtitle2, ), @@ -103,7 +105,7 @@ class ScheduleEntryDetailBottomSheet extends StatelessWidget { children: [ Expanded( child: Text( - scheduleEntry!.professor, + scheduleEntry.professor, ), ), Text( @@ -113,14 +115,14 @@ class ScheduleEntryDetailBottomSheet extends StatelessWidget { ], ), ), - if (scheduleEntry!.room.isEmpty) + if (scheduleEntry.room.isEmpty) Container() else Padding( padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), - child: Text(scheduleEntry!.room.replaceAll(",", "\n")), + child: Text(scheduleEntry.room.replaceAll(",", "\n")), ), - if (scheduleEntry!.details.isEmpty) + if (scheduleEntry.details.isEmpty) Container() else Padding( @@ -130,10 +132,10 @@ class ScheduleEntryDetailBottomSheet extends StatelessWidget { height: 1, ), ), - if (scheduleEntry!.details.isEmpty) + if (scheduleEntry.details.isEmpty) Container() else - Text(scheduleEntry!.details), + Text(scheduleEntry.details), ], ), ), diff --git a/lib/schedule/ui/weeklyschedule/weekly_schedule_page.dart b/lib/schedule/ui/weeklyschedule/weekly_schedule_page.dart index f83f499c..91d9307f 100644 --- a/lib/schedule/ui/weeklyschedule/weekly_schedule_page.dart +++ b/lib/schedule/ui/weeklyschedule/weekly_schedule_page.dart @@ -1,7 +1,6 @@ import 'package:animations/animations.dart'; import 'package:dhbwstudentapp/common/i18n/localizations.dart'; import 'package:dhbwstudentapp/common/ui/widgets/error_display.dart'; -import 'package:dhbwstudentapp/schedule/model/schedule.dart'; import 'package:dhbwstudentapp/schedule/model/schedule_entry.dart'; import 'package:dhbwstudentapp/schedule/ui/viewmodels/weekly_schedule_view_model.dart'; import 'package:dhbwstudentapp/schedule/ui/weeklyschedule/schedule_entry_detail_bottom_sheet.dart'; @@ -12,7 +11,7 @@ import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; class WeeklySchedulePage extends StatefulWidget { - const WeeklySchedulePage({Key? key}) : super(key: key); + const WeeklySchedulePage({super.key}); @override _WeeklySchedulePageState createState() => _WeeklySchedulePageState(); @@ -20,7 +19,6 @@ class WeeklySchedulePage extends StatefulWidget { class _WeeklySchedulePageState extends State { late WeeklyScheduleViewModel viewModel; - Schedule? schedule; _WeeklySchedulePageState(); @@ -42,6 +40,7 @@ class _WeeklySchedulePageState extends State { L.of(context).scheduleQueryFailedOpenInBrowser.toUpperCase(), ), onPressed: () { + // TDOD: [Leptopoda] this can throw a null error launchUrl(Uri.parse(viewModel.scheduleUrl!)); }, ) diff --git a/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_alignment.dart b/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_alignment.dart index f51b27d1..efa8bff6 100644 --- a/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_alignment.dart +++ b/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_alignment.dart @@ -14,6 +14,8 @@ class ScheduleEntryAlignmentInformation { /// https://stackoverflow.com/questions/11311410/visualization-of-calendar-events-algorithm-to-layout-events-with-maximum-width /// class ScheduleEntryAlignmentAlgorithm { + const ScheduleEntryAlignmentAlgorithm(); + List layoutEntries( List entries, ) { diff --git a/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_widget.dart b/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_widget.dart index 5ad83b3e..45ec38e5 100644 --- a/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_widget.dart +++ b/lib/schedule/ui/weeklyschedule/widgets/schedule_entry_widget.dart @@ -6,13 +6,13 @@ typedef ScheduleEntryTapCallback = Function(ScheduleEntry entry); class ScheduleEntryWidget extends StatelessWidget { final ScheduleEntry scheduleEntry; - final ScheduleEntryTapCallback? onScheduleEntryTap; + final ScheduleEntryTapCallback onScheduleEntryTap; const ScheduleEntryWidget({ - Key? key, + super.key, required this.scheduleEntry, - this.onScheduleEntryTap, - }) : super(key: key); + required this.onScheduleEntryTap, + }); @override Widget build(BuildContext context) { @@ -32,7 +32,7 @@ class ScheduleEntryWidget extends StatelessWidget { margin: const EdgeInsets.fromLTRB(1, 0, 1, 0), child: InkWell( onTap: () { - onScheduleEntryTap?.call(scheduleEntry); + onScheduleEntryTap.call(scheduleEntry); }, child: Padding( padding: const EdgeInsets.fromLTRB(4, 4, 4, 4), diff --git a/lib/schedule/ui/weeklyschedule/widgets/schedule_grid.dart b/lib/schedule/ui/weeklyschedule/widgets/schedule_grid.dart index 509b2f5e..9acf73bc 100644 --- a/lib/schedule/ui/weeklyschedule/widgets/schedule_grid.dart +++ b/lib/schedule/ui/weeklyschedule/widgets/schedule_grid.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; class ScheduleGrid extends CustomPaint { - final int? fromHour; - final int? toHour; + final int fromHour; + final int toHour; final double timeLabelsWidth; final double dateLabelsHeight; final int columns; @@ -29,14 +29,14 @@ class ScheduleGrid extends CustomPaint { } class ScheduleGridCustomPaint extends CustomPainter { - final int? fromHour; - final int? toHour; + final int fromHour; + final int toHour; final double timeLabelsWidth; final double dateLabelsHeight; final int columns; final Color gridLineColor; - ScheduleGridCustomPaint( + const ScheduleGridCustomPaint( this.fromHour, this.toHour, this.timeLabelsWidth, @@ -51,7 +51,7 @@ class ScheduleGridCustomPaint extends CustomPainter { ..color = gridLineColor ..strokeWidth = 1; - final lines = toHour! - fromHour!; + final lines = toHour - fromHour; drawHorizontalLines(lines, size, canvas, secondaryPaint); drawVerticalLines(size, canvas, secondaryPaint); diff --git a/lib/schedule/ui/weeklyschedule/widgets/schedule_past_overlay.dart b/lib/schedule/ui/weeklyschedule/widgets/schedule_past_overlay.dart index 96eec88b..344a1a60 100644 --- a/lib/schedule/ui/weeklyschedule/widgets/schedule_past_overlay.dart +++ b/lib/schedule/ui/weeklyschedule/widgets/schedule_past_overlay.dart @@ -43,7 +43,7 @@ class SchedulePastOverlayCustomPaint extends CustomPainter { final int columns; final Color overlayColor; - SchedulePastOverlayCustomPaint( + const SchedulePastOverlayCustomPaint( this.fromDate, this.toDate, this.now, diff --git a/lib/schedule/ui/weeklyschedule/widgets/schedule_widget.dart b/lib/schedule/ui/weeklyschedule/widgets/schedule_widget.dart index 52e0ad10..1c402533 100644 --- a/lib/schedule/ui/weeklyschedule/widgets/schedule_widget.dart +++ b/lib/schedule/ui/weeklyschedule/widgets/schedule_widget.dart @@ -15,43 +15,40 @@ class ScheduleWidget extends StatelessWidget { final Schedule? schedule; final DateTime? displayStart; final DateTime? displayEnd; - final DateTime? now; - final int? displayStartHour; - final int? displayEndHour; - final ScheduleEntryTapCallback? onScheduleEntryTap; + final DateTime now; + final int displayStartHour; + final int displayEndHour; + final ScheduleEntryTapCallback onScheduleEntryTap; const ScheduleWidget({ - Key? key, - this.schedule, - this.displayStart, - this.displayEnd, - this.onScheduleEntryTap, - this.now, - this.displayStartHour, - this.displayEndHour, - }) : super(key: key); + super.key, + required this.schedule, + required this.displayStart, + required this.displayEnd, + required this.onScheduleEntryTap, + required this.now, + required this.displayStartHour, + required this.displayEndHour, + }); @override Widget build(BuildContext context) { return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return buildWithSize( - context, - constraints.biggest.width, - constraints.biggest.height, - ); - }, + builder: buildWithSize, ); } - Widget buildWithSize(BuildContext context, double width, double height) { + Widget buildWithSize(BuildContext context, BoxConstraints constraints) { final scheduleTheme = Theme.of(context).extension()!; + final height = constraints.biggest.height; + final width = constraints.biggest.width; + const dayLabelsHeight = 40.0; const timeLabelsWidth = 50.0; final hourHeight = - (height - dayLabelsHeight) / (displayEndHour! - displayStartHour!); + (height - dayLabelsHeight) / (displayEndHour - displayStartHour); final minuteHeight = hourHeight / 60; final days = calculateDisplayedDays(); @@ -140,12 +137,12 @@ class ScheduleWidget extends StatelessWidget { ) { final labelWidgets = []; - for (var i = displayStartHour!; i < displayEndHour!; i++) { + for (var i = displayStartHour; i < displayEndHour; i++) { final hourLabelText = "$i:00"; labelWidgets.add( Positioned( - top: rowHeight * (i - displayStartHour!) + dayLabelHeight, + top: rowHeight * (i - displayStartHour) + dayLabelHeight, left: 0, child: Padding( padding: const EdgeInsets.fromLTRB(4, 4, 4, 8), @@ -249,15 +246,15 @@ class ScheduleWidget extends StatelessWidget { final entryWidgets = []; final laidOutEntries = - ScheduleEntryAlignmentAlgorithm().layoutEntries(entries); + const ScheduleEntryAlignmentAlgorithm().layoutEntries(entries); for (final value in laidOutEntries) { final entry = value.entry; - final yStart = hourHeight * (entry.start.hour - displayStartHour!) + + final yStart = hourHeight * (entry.start.hour - displayStartHour) + minuteHeight * entry.start.minute; - final yEnd = hourHeight * (entry.end.hour - displayStartHour!) + + final yEnd = hourHeight * (entry.end.hour - displayStartHour) + minuteHeight * entry.end.minute; final entryLeft = maxWidth * value.leftColumn; diff --git a/lib/schedule/ui/widgets/enter_dualis_credentials_dialog.dart b/lib/schedule/ui/widgets/enter_dualis_credentials_dialog.dart index eec5214e..011233c8 100644 --- a/lib/schedule/ui/widgets/enter_dualis_credentials_dialog.dart +++ b/lib/schedule/ui/widgets/enter_dualis_credentials_dialog.dart @@ -23,7 +23,7 @@ class EnterDualisCredentialsDialog { await showDialog( context: context, - builder: (context) => _buildDialog(context), + builder: _buildDialog, ); } diff --git a/lib/schedule/ui/widgets/enter_url_dialog.dart b/lib/schedule/ui/widgets/enter_url_dialog.dart index f266fb3b..80e20976 100644 --- a/lib/schedule/ui/widgets/enter_url_dialog.dart +++ b/lib/schedule/ui/widgets/enter_url_dialog.dart @@ -18,7 +18,7 @@ abstract class EnterUrlDialog { Future show(BuildContext context) async { await showDialog( context: context, - builder: (context) => _buildDialog(context), + builder: _buildDialog, ); } diff --git a/lib/schedule/ui/widgets/schedule_empty_state.dart b/lib/schedule/ui/widgets/schedule_empty_state.dart index 436d26f1..fab8b29e 100644 --- a/lib/schedule/ui/widgets/schedule_empty_state.dart +++ b/lib/schedule/ui/widgets/schedule_empty_state.dart @@ -6,7 +6,9 @@ import 'package:flutter/material.dart'; import 'package:kiwi/kiwi.dart'; class ScheduleEmptyState extends StatelessWidget { - final Map image = { + const ScheduleEmptyState({super.key}); + + static const Map image = { Brightness.dark: Assets.assets_schedule_empty_state_dark_png, Brightness.light: Assets.assets_schedule_empty_state_png, }; diff --git a/lib/schedule/ui/widgets/schedule_help_dialog.dart b/lib/schedule/ui/widgets/schedule_help_dialog.dart index dd5c4335..ebde3d6e 100644 --- a/lib/schedule/ui/widgets/schedule_help_dialog.dart +++ b/lib/schedule/ui/widgets/schedule_help_dialog.dart @@ -3,6 +3,8 @@ import 'package:dhbwstudentapp/common/ui/widgets/help_dialog.dart'; import 'package:flutter/material.dart'; class ScheduleHelpDialog extends HelpDialog { + const ScheduleHelpDialog(); + @override String content(BuildContext context) { return L.of(context).scheduleHelpDialogContent; diff --git a/lib/schedule/ui/widgets/select_mannheim_course_dialog.dart b/lib/schedule/ui/widgets/select_mannheim_course_dialog.dart index 94dfdf5f..c01ac6ea 100644 --- a/lib/schedule/ui/widgets/select_mannheim_course_dialog.dart +++ b/lib/schedule/ui/widgets/select_mannheim_course_dialog.dart @@ -7,20 +7,16 @@ import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class SelectMannheimCourseDialog { - final ScheduleSourceProvider _scheduleSourceProvider; - - late MannheimViewModel _mannheimViewModel; + final MannheimViewModel _mannheimViewModel; SelectMannheimCourseDialog( - this._scheduleSourceProvider, - ); + ScheduleSourceProvider scheduleSourceProvider, + ) : _mannheimViewModel = MannheimViewModel(scheduleSourceProvider); Future show(BuildContext context) async { - _mannheimViewModel = MannheimViewModel(_scheduleSourceProvider); - await showDialog( context: context, - builder: (context) => _buildDialog(context), + builder: _buildDialog, ); } @@ -43,9 +39,9 @@ class SelectMannheimCourseDialog { style: Theme.of(context).textTheme.bodyText2, ), ), - Expanded( + const Expanded( child: Padding( - padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), + padding: EdgeInsets.fromLTRB(8, 0, 8, 0), child: SelectMannheimCourseWidget(), ), ), diff --git a/lib/schedule/ui/widgets/select_source_dialog.dart b/lib/schedule/ui/widgets/select_source_dialog.dart index bb43eb3c..75713d79 100644 --- a/lib/schedule/ui/widgets/select_source_dialog.dart +++ b/lib/schedule/ui/widgets/select_source_dialog.dart @@ -23,7 +23,7 @@ class SelectSourceDialog { await showDialog( context: context, - builder: (context) => _buildDialog(context), + builder: _buildDialog, ); } diff --git a/lib/ui/banner_widget.dart b/lib/ui/banner_widget.dart index fd1c08c8..ad34acc2 100644 --- a/lib/ui/banner_widget.dart +++ b/lib/ui/banner_widget.dart @@ -6,11 +6,11 @@ class BannerWidget extends StatelessWidget { final VoidCallback onButtonTap; const BannerWidget({ - Key? key, + super.key, required this.message, required this.buttonText, required this.onButtonTap, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/ui/login_credentials_widget.dart b/lib/ui/login_credentials_widget.dart index 70670b9a..9e2601ef 100644 --- a/lib/ui/login_credentials_widget.dart +++ b/lib/ui/login_credentials_widget.dart @@ -2,49 +2,42 @@ import 'package:dhbwstudentapp/common/i18n/localizations.dart'; import 'package:dhbwstudentapp/dualis/model/credentials.dart'; import 'package:flutter/material.dart'; -class LoginCredentialsWidget extends StatefulWidget { +class LoginCredentialsWidget extends StatelessWidget { final CredentialsEditingController controller; final VoidCallback onSubmitted; const LoginCredentialsWidget({ - Key? key, + super.key, required this.controller, required this.onSubmitted, - }) : super(key: key); - - @override - _LoginCredentialsWidgetState createState() => _LoginCredentialsWidgetState(); -} - -class _LoginCredentialsWidgetState extends State { - final _focus = FocusNode(); + }); @override Widget build(BuildContext context) { + final focus = FocusNode(); + return Column( children: [ TextField( - controller: widget.controller.username, + controller: controller.username, decoration: InputDecoration( hintText: L.of(context).loginUsername, icon: const Icon(Icons.alternate_email), ), onSubmitted: (v) { - FocusScope.of(context).requestFocus(_focus); + FocusScope.of(context).requestFocus(focus); }, textInputAction: TextInputAction.next, ), TextField( - controller: widget.controller.password, + controller: controller.password, obscureText: true, decoration: InputDecoration( hintText: L.of(context).loginPassword, icon: const Icon(Icons.lock_outline), ), - focusNode: _focus, - onSubmitted: (_) { - widget.onSubmitted(); - }, + focusNode: focus, + onSubmitted: (_) => onSubmitted(), ), ], ); diff --git a/lib/ui/main_page.dart b/lib/ui/main_page.dart index ed435d30..bd70cf86 100644 --- a/lib/ui/main_page.dart +++ b/lib/ui/main_page.dart @@ -15,7 +15,7 @@ import 'package:provider/provider.dart'; /// To navigate to a new route inside this widget use the [NavigatorKey.mainKey] /// class MainPage extends StatefulWidget { - const MainPage({Key? key}) : super(key: key); + const MainPage({super.key}); @override _MainPageState createState() => _MainPageState(); @@ -29,10 +29,7 @@ class _MainPageState extends State with NavigatorObserver { NavigationEntry get currentEntry => navigationEntries[_currentEntryIndex.value]; - @override - void initState() { - super.initState(); - } + _MainPageState(); @override Widget build(BuildContext context) { @@ -175,7 +172,9 @@ class _MainPageState extends State with NavigatorObserver { @override void didPop(Route route, Route? previousRoute) { - updateNavigationDrawer(previousRoute!.settings.name); + if (previousRoute != null) { + updateNavigationDrawer(previousRoute.settings.name); + } } @override @@ -185,6 +184,8 @@ class _MainPageState extends State with NavigatorObserver { @override void didReplace({Route? newRoute, Route? oldRoute}) { - updateNavigationDrawer(newRoute!.settings.name); + if (newRoute != null) { + updateNavigationDrawer(newRoute.settings.name); + } } } diff --git a/lib/ui/navigation/navigation_entry.dart b/lib/ui/navigation/navigation_entry.dart index 4c123c22..128c7772 100644 --- a/lib/ui/navigation/navigation_entry.dart +++ b/lib/ui/navigation/navigation_entry.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; abstract class NavigationEntry { + NavigationEntry(); + T? _viewModel; String get route; diff --git a/lib/ui/navigation_drawer.dart b/lib/ui/navigation_drawer.dart index 0a0e25dd..023b81a4 100644 --- a/lib/ui/navigation_drawer.dart +++ b/lib/ui/navigation_drawer.dart @@ -16,12 +16,12 @@ class NavigationDrawer extends StatelessWidget { final bool isInDrawer; const NavigationDrawer({ - Key? key, + super.key, required this.selectedIndex, required this.onTap, required this.entries, this.isInDrawer = true, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -134,25 +134,23 @@ class NavigationDrawer extends StatelessWidget { child: Container( height: 56, margin: const EdgeInsets.fromLTRB(0, 0, 0, 20), - child: Padding( - padding: const EdgeInsets.fromLTRB(20, 15, 0, 10), - child: Row( - children: [ - Icon( - Icons.settings, - color: Theme.of(context).disabledColor, - ), - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 0), - child: Text( - L.of(context).settingsPageTitle, - style: TextStyle( - color: Theme.of(context).disabledColor, - ), + padding: const EdgeInsets.fromLTRB(20, 15, 0, 10), + child: Row( + children: [ + Icon( + Icons.settings, + color: Theme.of(context).disabledColor, + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 0, 0), + child: Text( + L.of(context).settingsPageTitle, + style: TextStyle( + color: Theme.of(context).disabledColor, ), ), - ], - ), + ), + ], ), ), onTap: () { @@ -173,5 +171,5 @@ class DrawerNavigationEntry { final Icon icon; final String title; - DrawerNavigationEntry(this.icon, this.title); + const DrawerNavigationEntry(this.icon, this.title); } diff --git a/lib/ui/onboarding/onboardin_step.dart b/lib/ui/onboarding/onboardin_step.dart index 5d8c03f9..d36f61f4 100644 --- a/lib/ui/onboarding/onboardin_step.dart +++ b/lib/ui/onboarding/onboardin_step.dart @@ -13,6 +13,8 @@ import 'package:flutter/cupertino.dart'; import 'package:kiwi/kiwi.dart'; abstract class OnboardingStep { + const OnboardingStep(); + Widget buildContent(BuildContext context); OnboardingStepViewModel viewModel(); @@ -21,6 +23,8 @@ abstract class OnboardingStep { } class SelectSourceOnboardingStep extends OnboardingStep { + SelectSourceOnboardingStep(); + final SelectSourceViewModel _viewModel = SelectSourceViewModel( KiwiContainer().resolve(), ); @@ -42,6 +46,8 @@ class SelectSourceOnboardingStep extends OnboardingStep { } class DualisCredentialsOnboardingStep extends OnboardingStep { + DualisCredentialsOnboardingStep(); + final DualisLoginViewModel _viewModel = DualisLoginViewModel( KiwiContainer().resolve(), KiwiContainer().resolve(), @@ -64,6 +70,8 @@ class DualisCredentialsOnboardingStep extends OnboardingStep { } class RaplaOnboardingStep extends OnboardingStep { + RaplaOnboardingStep(); + final RaplaUrlViewModel _viewModel = RaplaUrlViewModel( KiwiContainer().resolve(), KiwiContainer().resolve(), @@ -86,6 +94,8 @@ class RaplaOnboardingStep extends OnboardingStep { } class IcalOnboardingStep extends OnboardingStep { + IcalOnboardingStep(); + final IcalUrlViewModel _viewModel = IcalUrlViewModel( KiwiContainer().resolve(), KiwiContainer().resolve(), @@ -109,6 +119,7 @@ class IcalOnboardingStep extends OnboardingStep { class MannheimOnboardingStep extends OnboardingStep { MannheimViewModel? _viewModel; + MannheimOnboardingStep(); @override Widget buildContent(BuildContext context) { diff --git a/lib/ui/onboarding/onboarding_page.dart b/lib/ui/onboarding/onboarding_page.dart index 35aa2aed..5e832802 100644 --- a/lib/ui/onboarding/onboarding_page.dart +++ b/lib/ui/onboarding/onboarding_page.dart @@ -9,7 +9,7 @@ import 'package:kiwi/kiwi.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class OnboardingPage extends StatefulWidget { - const OnboardingPage({Key? key}) : super(key: key); + const OnboardingPage({super.key}); @override _OnboardingPageState createState() => _OnboardingPageState(); diff --git a/lib/ui/onboarding/viewmodels/mannheim_view_model.dart b/lib/ui/onboarding/viewmodels/mannheim_view_model.dart index 30f17349..4037c0ee 100644 --- a/lib/ui/onboarding/viewmodels/mannheim_view_model.dart +++ b/lib/ui/onboarding/viewmodels/mannheim_view_model.dart @@ -31,7 +31,7 @@ class MannheimViewModel extends OnboardingStepViewModel { try { await Future.delayed(const Duration(seconds: 1)); - _courses = await MannheimCourseScraper().loadCourses(); + _courses = await const MannheimCourseScraper().loadCourses(); _loadingState = LoadCoursesState.Loaded; } catch (ex) { _courses = null; diff --git a/lib/ui/onboarding/viewmodels/onboarding_view_model_base.dart b/lib/ui/onboarding/viewmodels/onboarding_view_model_base.dart index c6be6b65..9504a2b7 100644 --- a/lib/ui/onboarding/viewmodels/onboarding_view_model_base.dart +++ b/lib/ui/onboarding/viewmodels/onboarding_view_model_base.dart @@ -1,6 +1,8 @@ import 'package:dhbwstudentapp/common/ui/viewmodels/base_view_model.dart'; abstract class OnboardingStepViewModel extends BaseViewModel { + OnboardingStepViewModel(); + bool _isValid = false; bool get isValid => _isValid; diff --git a/lib/ui/onboarding/widgets/dualis_login_page.dart b/lib/ui/onboarding/widgets/dualis_login_page.dart index 8b0d2477..b0da52db 100644 --- a/lib/ui/onboarding/widgets/dualis_login_page.dart +++ b/lib/ui/onboarding/widgets/dualis_login_page.dart @@ -11,18 +11,26 @@ import 'package:property_change_notifier/property_change_notifier.dart'; /// credentials. /// class DualisLoginCredentialsPage extends StatefulWidget { - const DualisLoginCredentialsPage({Key? key}) : super(key: key); + const DualisLoginCredentialsPage({super.key}); @override - _DualisLoginCredentialsPageState createState() => + State createState() => _DualisLoginCredentialsPageState(); } class _DualisLoginCredentialsPageState extends State { - final CredentialsEditingController _controller = + final CredentialsEditingController controller = CredentialsEditingController(); + _DualisLoginCredentialsPageState(); + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return PropertyChangeConsumer( @@ -36,7 +44,7 @@ class _DualisLoginCredentialsPageState final credentials = viewModel?.credentials; if (credentials != null) { - _controller.credentials = credentials; + controller.credentials = credentials; } final widgets = []; @@ -44,7 +52,7 @@ class _DualisLoginCredentialsPageState widgets.addAll(_buildHeader()); widgets.add( LoginCredentialsWidget( - controller: _controller, + controller: controller, onSubmitted: () async { await _testCredentials(viewModel); }, @@ -114,7 +122,7 @@ class _DualisLoginCredentialsPageState Future _testCredentials(DualisLoginViewModel? viewModel) async { if (viewModel == null) return; - await viewModel.testCredentials(_controller.credentials); + await viewModel.testCredentials(controller.credentials); } List _buildHeader() { diff --git a/lib/ui/onboarding/widgets/ical_url_page.dart b/lib/ui/onboarding/widgets/ical_url_page.dart index 93ebce5f..29d737d9 100644 --- a/lib/ui/onboarding/widgets/ical_url_page.dart +++ b/lib/ui/onboarding/widgets/ical_url_page.dart @@ -4,18 +4,12 @@ import 'package:dhbwstudentapp/ui/onboarding/viewmodels/onboarding_view_model_ba import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; -class IcalUrlPage extends StatefulWidget { - const IcalUrlPage({Key? key}) : super(key: key); - - @override - _IcalUrlPageState createState() => _IcalUrlPageState(); -} - -class _IcalUrlPageState extends State { - final TextEditingController _urlTextController = TextEditingController(); +class IcalUrlPage extends StatelessWidget { + const IcalUrlPage({super.key}); @override Widget build(BuildContext context) { + final TextEditingController urlTextController = TextEditingController(); return Column( children: [ Padding( @@ -49,8 +43,8 @@ class _IcalUrlPageState extends State { final viewModel = model as IcalUrlViewModel?; if (viewModel?.url != null && - _urlTextController.text != viewModel!.url) { - _urlTextController.text = viewModel.url!; + urlTextController.text != viewModel!.url) { + urlTextController.text = viewModel.url!; } return Padding( @@ -60,7 +54,7 @@ class _IcalUrlPageState extends State { children: [ Expanded( child: TextField( - controller: _urlTextController, + controller: urlTextController, decoration: InputDecoration( errorText: (viewModel?.urlHasError == true) ? L.of(context).onboardingRaplaUrlInvalid diff --git a/lib/ui/onboarding/widgets/mannheim_page.dart b/lib/ui/onboarding/widgets/mannheim_page.dart index 75d2bfac..4a6ff63a 100644 --- a/lib/ui/onboarding/widgets/mannheim_page.dart +++ b/lib/ui/onboarding/widgets/mannheim_page.dart @@ -4,14 +4,9 @@ import 'package:dhbwstudentapp/ui/onboarding/viewmodels/onboarding_view_model_ba import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; -class MannheimPage extends StatefulWidget { - const MannheimPage({Key? key}) : super(key: key); +class MannheimPage extends StatelessWidget { + const MannheimPage({super.key}); - @override - _MannheimPageState createState() => _MannheimPageState(); -} - -class _MannheimPageState extends State { @override Widget build(BuildContext context) { return Column( @@ -35,9 +30,9 @@ class _MannheimPageState extends State { style: Theme.of(context).textTheme.bodyText2, textAlign: TextAlign.center, ), - Expanded( + const Expanded( child: Padding( - padding: const EdgeInsets.fromLTRB(0, 32, 0, 0), + padding: EdgeInsets.fromLTRB(0, 32, 0, 0), child: SelectMannheimCourseWidget(), ), ), @@ -47,6 +42,8 @@ class _MannheimPageState extends State { } class SelectMannheimCourseWidget extends StatelessWidget { + const SelectMannheimCourseWidget({super.key}); + @override Widget build(BuildContext context) { return PropertyChangeConsumer( diff --git a/lib/ui/onboarding/widgets/onboarding_button_bar.dart b/lib/ui/onboarding/widgets/onboarding_button_bar.dart index 44fc6a9d..5b141d39 100644 --- a/lib/ui/onboarding/widgets/onboarding_button_bar.dart +++ b/lib/ui/onboarding/widgets/onboarding_button_bar.dart @@ -8,11 +8,11 @@ class OnboardingButtonBar extends StatelessWidget { final VoidCallback onPrevious; const OnboardingButtonBar({ - Key? key, + super.key, required this.viewModel, required this.onNext, required this.onPrevious, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/ui/onboarding/widgets/onboarding_page_background.dart b/lib/ui/onboarding/widgets/onboarding_page_background.dart index e4bf9fad..5d7e6832 100644 --- a/lib/ui/onboarding/widgets/onboarding_page_background.dart +++ b/lib/ui/onboarding/widgets/onboarding_page_background.dart @@ -11,17 +11,17 @@ class OnboardingPageBackground extends StatelessWidget { final Animation bottomForeground; final Animation bottomBackground; - final Map foreground = { + static const Map foreground = { Brightness.light: Assets.assets_onboarding_bottom_foreground_png, Brightness.dark: Assets.assets_onboarding_bottom_foreground_dark_png, }; - final Map background = { + static const Map background = { Brightness.light: Assets.assets_onboarding_bottom_background_png, Brightness.dark: Assets.assets_onboarding_bottom_background_dark_png, }; - OnboardingPageBackground({Key? key, required this.controller}) + OnboardingPageBackground({super.key, required this.controller}) : angleTopBackground = Tween( begin: PlatformUtil.isPhone() ? -32 : -10, end: PlatformUtil.isPhone() ? -10 : -5, @@ -69,8 +69,7 @@ class OnboardingPageBackground extends StatelessWidget { 1, ), ), - ), - super(key: key); + ); Widget _buildAnimation(BuildContext context, Widget? child) { return Stack( diff --git a/lib/ui/onboarding/widgets/rapla_url_page.dart b/lib/ui/onboarding/widgets/rapla_url_page.dart index db2df414..78e48f05 100644 --- a/lib/ui/onboarding/widgets/rapla_url_page.dart +++ b/lib/ui/onboarding/widgets/rapla_url_page.dart @@ -4,18 +4,12 @@ import 'package:dhbwstudentapp/ui/onboarding/viewmodels/rapla_url_view_model.dar import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; -class RaplaUrlPage extends StatefulWidget { - const RaplaUrlPage({Key? key}) : super(key: key); - - @override - _RaplaUrlPageState createState() => _RaplaUrlPageState(); -} - -class _RaplaUrlPageState extends State { - final TextEditingController _urlTextController = TextEditingController(); +class RaplaUrlPage extends StatelessWidget { + const RaplaUrlPage({super.key}); @override Widget build(BuildContext context) { + final TextEditingController urlTextController = TextEditingController(); return Column( children: [ Padding( @@ -49,8 +43,8 @@ class _RaplaUrlPageState extends State { final viewModel = model as RaplaUrlViewModel?; if (viewModel?.raplaUrl != null && - _urlTextController.text != viewModel!.raplaUrl) { - _urlTextController.text = viewModel.raplaUrl!; + urlTextController.text != viewModel!.raplaUrl) { + urlTextController.text = viewModel.raplaUrl!; } return Padding( @@ -60,7 +54,7 @@ class _RaplaUrlPageState extends State { children: [ Expanded( child: TextField( - controller: _urlTextController, + controller: urlTextController, decoration: InputDecoration( errorText: viewModel?.urlHasError == true ? L.of(context).onboardingRaplaUrlInvalid diff --git a/lib/ui/onboarding/widgets/select_source_page.dart b/lib/ui/onboarding/widgets/select_source_page.dart index 4036d051..baa1984b 100644 --- a/lib/ui/onboarding/widgets/select_source_page.dart +++ b/lib/ui/onboarding/widgets/select_source_page.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class SelectSourcePage extends StatelessWidget { - const SelectSourcePage({Key? key}) : super(key: key); + const SelectSourcePage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/pager_widget.dart b/lib/ui/pager_widget.dart index 3c2286ed..11c75fdc 100644 --- a/lib/ui/pager_widget.dart +++ b/lib/ui/pager_widget.dart @@ -17,8 +17,7 @@ class PagerWidget extends StatefulWidget { final List pages; final String? pagesId; - const PagerWidget({Key? key, required this.pages, this.pagesId}) - : super(key: key); + const PagerWidget({super.key, required this.pages, this.pagesId}); @override _PagerWidgetState createState() => _PagerWidgetState(); @@ -29,6 +28,8 @@ class _PagerWidgetState extends State { int _currentPage = 0; + _PagerWidgetState(); + @override void initState() { super.initState(); @@ -108,7 +109,7 @@ class PageDefinition { final WidgetBuilder builder; final T? viewModel; - PageDefinition({ + const PageDefinition({ required this.icon, required this.text, required this.builder, diff --git a/lib/ui/root_page.dart b/lib/ui/root_page.dart index c3521653..6585369e 100644 --- a/lib/ui/root_page.dart +++ b/lib/ui/root_page.dart @@ -13,25 +13,15 @@ import 'package:property_change_notifier/property_change_notifier.dart'; /// This is the top level widget of the app. It handles navigation of the /// root navigator and rebuilds its child widgets on theme changes /// -class RootPage extends StatefulWidget { +class RootPage extends StatelessWidget { final RootViewModel rootViewModel; - const RootPage({Key? key, required this.rootViewModel}) : super(key: key); - - @override - _RootPageState createState() => _RootPageState(); -} - -class _RootPageState extends State { - @override - void initState() { - super.initState(); - } + const RootPage({super.key, required this.rootViewModel}); @override Widget build(BuildContext context) { return PropertyChangeProvider( - value: widget.rootViewModel, + value: rootViewModel, child: PropertyChangeConsumer( properties: const ["appTheme", "isOnboarding"], builder: @@ -40,8 +30,7 @@ class _RootPageState extends State { theme: AppTheme.lightThemeData, darkTheme: AppTheme.darkThemeData, themeMode: model?.appTheme, - initialRoute: - widget.rootViewModel.isOnboarding ? "onboarding" : "main", + initialRoute: rootViewModel.isOnboarding ? "onboarding" : "main", navigatorKey: NavigatorKey.rootKey, navigatorObservers: [rootNavigationObserver], localizationsDelegates: const [ diff --git a/lib/ui/settings/donate_list_tile.dart b/lib/ui/settings/donate_list_tile.dart index 7b1fea9f..f1c59da9 100644 --- a/lib/ui/settings/donate_list_tile.dart +++ b/lib/ui/settings/donate_list_tile.dart @@ -7,7 +7,7 @@ import 'package:kiwi/kiwi.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class DonateListTile extends StatefulWidget { - const DonateListTile({Key? key}) : super(key: key); + const DonateListTile({super.key}); @override _DonateListTileState createState() => _DonateListTileState(); diff --git a/lib/ui/settings/purchase_widget_list_tile.dart b/lib/ui/settings/purchase_widget_list_tile.dart index 691d9cdb..d519c81b 100644 --- a/lib/ui/settings/purchase_widget_list_tile.dart +++ b/lib/ui/settings/purchase_widget_list_tile.dart @@ -7,7 +7,7 @@ import 'package:kiwi/kiwi.dart'; import 'package:property_change_notifier/property_change_notifier.dart'; class PurchaseWidgetListTile extends StatefulWidget { - const PurchaseWidgetListTile({Key? key}) : super(key: key); + const PurchaseWidgetListTile({super.key}); @override _PurchaseWidgetListTileState createState() => _PurchaseWidgetListTileState(); diff --git a/lib/ui/settings/select_theme_dialog.dart b/lib/ui/settings/select_theme_dialog.dart index f3eb3dd9..3b92fdc5 100644 --- a/lib/ui/settings/select_theme_dialog.dart +++ b/lib/ui/settings/select_theme_dialog.dart @@ -9,7 +9,7 @@ import 'package:property_change_notifier/property_change_notifier.dart'; class SelectThemeDialog { final RootViewModel _rootViewModel; - SelectThemeDialog(this._rootViewModel); + const SelectThemeDialog(this._rootViewModel); Future show(BuildContext context) async { await showDialog( diff --git a/lib/ui/settings/settings_page.dart b/lib/ui/settings/settings_page.dart index 0650f4f1..0bd21eb9 100644 --- a/lib/ui/settings/settings_page.dart +++ b/lib/ui/settings/settings_page.dart @@ -30,7 +30,7 @@ import 'package:url_launcher/url_launcher.dart'; /// of the app /// class SettingsPage extends StatefulWidget { - const SettingsPage({Key? key}) : super(key: key); + const SettingsPage({super.key}); @override _SettingsPageState createState() => _SettingsPageState(); @@ -45,15 +45,17 @@ class _SettingsPageState extends State { KiwiContainer().resolve(), ); + _SettingsPageState(); + @override Widget build(BuildContext context) { - final widgets = []; - - widgets.addAll(buildScheduleSourceSettings(context)); - widgets.addAll(buildDesignSettings(context)); - widgets.addAll(buildNotificationSettings(context)); - widgets.addAll(buildAboutSettings(context)); - widgets.add(buildDisclaimer(context)); + final widgets = [ + ...buildScheduleSourceSettings(), + ...buildDesignSettings(), + ...buildNotificationSettings(), + ...buildAboutSettings(), + buildDisclaimer(), + ]; return Scaffold( appBar: AppBar( @@ -74,7 +76,7 @@ class _SettingsPageState extends State { ); } - Widget buildDisclaimer(BuildContext context) { + Widget buildDisclaimer() { return Padding( padding: const EdgeInsets.all(32), child: Text( @@ -84,7 +86,7 @@ class _SettingsPageState extends State { ); } - List buildAboutSettings(BuildContext context) { + List buildAboutSettings() { return [ TitleListTile(title: L.of(context).settingsAboutTitle), const PurchaseWidgetListTile(), @@ -114,7 +116,7 @@ class _SettingsPageState extends State { ]; } - List buildScheduleSourceSettings(BuildContext context) { + List buildScheduleSourceSettings() { return [ TitleListTile(title: L.of(context).settingsScheduleSourceTitle), ListTile( @@ -141,48 +143,13 @@ class _SettingsPageState extends State { ), ListTile( title: Text(L.of(context).settingsCalendarSync), - onTap: () async { - if (await CalendarAccess().requestCalendarPermission() == - CalendarPermission.PermissionDenied) { - await showDialog( - context: context, - builder: (BuildContext context) => AlertDialog( - title: Text( - L.of(context).dialogTitleCalendarAccessNotGranted, - ), - content: Text(L.of(context).dialogCalendarAccessNotGranted), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(L.of(context).dialogOk), - ) - ], - ), - ); - return; - } - final isCalendarSyncEnabled = await KiwiContainer() - .resolve() - .isCalendarSyncEnabled(); - final List entriesToExport = - KiwiContainer().resolve().listDateEntries; - await NavigatorKey.rootKey.currentState!.push( - MaterialPageRoute( - builder: (BuildContext context) => CalendarExportPage( - entriesToExport: entriesToExport, - isCalendarSyncWidget: true, - isCalendarSyncEnabled: isCalendarSyncEnabled, - ), - settings: const RouteSettings(name: "settings"), - ), - ); - }, + onTap: requestCalendarPermission, ), const Divider(), ]; } - List buildNotificationSettings(BuildContext context) { + List buildNotificationSettings() { final WorkSchedulerService service = KiwiContainer().resolve(); if (service.isSchedulingAvailable()) { return [ @@ -226,7 +193,7 @@ class _SettingsPageState extends State { } } - List buildDesignSettings(BuildContext context) { + List buildDesignSettings() { return [ TitleListTile(title: L.of(context).settingsDesign), PropertyChangeConsumer( @@ -253,6 +220,43 @@ class _SettingsPageState extends State { ]; } + Future requestCalendarPermission() async { + final permission = await CalendarAccess().requestCalendarPermission(); + if (permission == CalendarPermission.PermissionDenied) { + await showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: Text( + L.of(context).dialogTitleCalendarAccessNotGranted, + ), + content: Text(L.of(context).dialogCalendarAccessNotGranted), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(L.of(context).dialogOk), + ) + ], + ), + ); + return; + } + final isCalendarSyncEnabled = await KiwiContainer() + .resolve() + .isCalendarSyncEnabled(); + final List entriesToExport = + KiwiContainer().resolve().listDateEntries; + await NavigatorKey.rootKey.currentState!.push( + MaterialPageRoute( + builder: (BuildContext context) => CalendarExportPage( + entriesToExport: entriesToExport, + isCalendarSyncWidget: true, + isCalendarSyncEnabled: isCalendarSyncEnabled, + ), + settings: const RouteSettings(name: "settings"), + ), + ); + } + @override void dispose() { super.dispose(); diff --git a/test/date_management/service/parsing/all_dates_extract_test.dart b/test/date_management/service/parsing/all_dates_extract_test.dart index 88e72642..14f86bcd 100644 --- a/test/date_management/service/parsing/all_dates_extract_test.dart +++ b/test/date_management/service/parsing/all_dates_extract_test.dart @@ -9,7 +9,7 @@ Future main() async { ).readAsString(); test('AllDatesExtract extract all dates', () async { - final extract = AllDatesExtract(); + const extract = AllDatesExtract(); final dateEntries = extract.extractAllDates(allDatesPage, ""); diff --git a/test/dualis/service/parsing/all_modules_extract_test.dart b/test/dualis/service/parsing/all_modules_extract_test.dart index e637ca0a..eddf4453 100644 --- a/test/dualis/service/parsing/all_modules_extract_test.dart +++ b/test/dualis/service/parsing/all_modules_extract_test.dart @@ -11,7 +11,7 @@ Future main() async { ).readAsString(); test('AllModulesExtract extract all modules', () async { - final extract = AllModulesExtract(); + const extract = AllModulesExtract(); final modules = extract.extractAllModules(studentResultsPage); @@ -27,7 +27,7 @@ Future main() async { }); test('AllModulesExtract invalid html throws exception', () async { - final extract = AllModulesExtract(); + const extract = AllModulesExtract(); try { extract.extractAllModules("Lorem ipsum"); diff --git a/test/dualis/service/parsing/dualis_timeout_extract_test.dart b/test/dualis/service/parsing/dualis_timeout_extract_test.dart index d3cfed2b..8f17eae4 100644 --- a/test/dualis/service/parsing/dualis_timeout_extract_test.dart +++ b/test/dualis/service/parsing/dualis_timeout_extract_test.dart @@ -13,10 +13,13 @@ Future main() async { ).readAsString(); test('DualisTimeoutExtract detect timeout page', () async { - expect(TimeoutExtract().isTimeoutErrorPage(timeoutPage), isTrue); + expect(const TimeoutExtract().isTimeoutErrorPage(timeoutPage), isTrue); }); test('DualisTimeoutExtract detect non timeout page', () async { - expect(TimeoutExtract().isTimeoutErrorPage(monthlySchedulePage), isFalse); + expect( + const TimeoutExtract().isTimeoutErrorPage(monthlySchedulePage), + isFalse, + ); }); } diff --git a/test/dualis/service/parsing/exams_from_module_details_extract_test.dart b/test/dualis/service/parsing/exams_from_module_details_extract_test.dart index 6023bf56..84f3f7de 100644 --- a/test/dualis/service/parsing/exams_from_module_details_extract_test.dart +++ b/test/dualis/service/parsing/exams_from_module_details_extract_test.dart @@ -10,7 +10,7 @@ Future main() async { ).readAsString(); test('ExamsFromModuleDetailsExtract', () async { - final extract = ExamsFromModuleDetailsExtract(); + const extract = ExamsFromModuleDetailsExtract(); final exams = extract.extractExamsFromModuleDetails(moduleDetailsPage); @@ -26,7 +26,7 @@ Future main() async { }); test('ExamsFromModuleDetailsExtract invalid html throws exception', () async { - final extract = ExamsFromModuleDetailsExtract(); + const extract = ExamsFromModuleDetailsExtract(); try { extract.extractExamsFromModuleDetails("Lorem ipsum"); diff --git a/test/dualis/service/parsing/monthly_schedule_extract_test.dart b/test/dualis/service/parsing/monthly_schedule_extract_test.dart index 425a8b25..fa32a675 100644 --- a/test/dualis/service/parsing/monthly_schedule_extract_test.dart +++ b/test/dualis/service/parsing/monthly_schedule_extract_test.dart @@ -9,7 +9,7 @@ Future main() async { ).readAsString(); test('MonthlyScheduleExtract extract all appointments', () async { - final extract = MonthlyScheduleExtract(); + const extract = MonthlyScheduleExtract(); final modules = extract.extractScheduleFromMonthly(monthlySchedulePage); diff --git a/test/dualis/service/parsing/semesters_from_course_result_page_extract_test.dart b/test/dualis/service/parsing/semesters_from_course_result_page_extract_test.dart index abafc0ea..fd336485 100644 --- a/test/dualis/service/parsing/semesters_from_course_result_page_extract_test.dart +++ b/test/dualis/service/parsing/semesters_from_course_result_page_extract_test.dart @@ -10,7 +10,7 @@ Future main() async { ).readAsString(); test('SemestersFromCourseResultPageExtract', () async { - final extract = SemestersFromCourseResultPageExtract(); + const extract = SemestersFromCourseResultPageExtract(); final semesters = extract.extractSemestersFromCourseResults( courseResultsPage, @@ -34,7 +34,7 @@ Future main() async { test('SemestersFromCourseResultPageExtract invalid html throws exception', () async { - final extract = SemestersFromCourseResultPageExtract(); + const extract = SemestersFromCourseResultPageExtract(); try { extract.extractSemestersFromCourseResults("Lorem ipsum", ""); diff --git a/test/dualis/service/parsing/study_grades_from_student_results_page_extract_test.dart b/test/dualis/service/parsing/study_grades_from_student_results_page_extract_test.dart index 374142d4..eb01dc61 100644 --- a/test/dualis/service/parsing/study_grades_from_student_results_page_extract_test.dart +++ b/test/dualis/service/parsing/study_grades_from_student_results_page_extract_test.dart @@ -10,7 +10,7 @@ Future main() async { ).readAsString(); test('StudyGradesFromStudentResultsPageExtract', () async { - final extract = StudyGradesFromStudentResultsPageExtract(); + const extract = StudyGradesFromStudentResultsPageExtract(); final studyGrades = extract.extractStudyGradesFromStudentsResultsPage(studentResultsPage); @@ -24,7 +24,7 @@ Future main() async { test('StudyGradesFromStudentResultsPageExtract invalid html throws exception', () async { - final extract = StudyGradesFromStudentResultsPageExtract(); + const extract = StudyGradesFromStudentResultsPageExtract(); try { extract.extractStudyGradesFromStudentsResultsPage("Lorem ipsum"); diff --git a/test/dualis/service/parsing/urls_from_main_page_extract_test.dart b/test/dualis/service/parsing/urls_from_main_page_extract_test.dart index 12365b16..14d37e37 100644 --- a/test/dualis/service/parsing/urls_from_main_page_extract_test.dart +++ b/test/dualis/service/parsing/urls_from_main_page_extract_test.dart @@ -11,7 +11,7 @@ Future main() async { ).readAsString(); test('UrlsFromMainPageExtract', () async { - final extract = UrlsFromMainPageExtract(); + const extract = UrlsFromMainPageExtract(); final mainPageUrls = DualisUrls(); @@ -33,7 +33,7 @@ Future main() async { }); test('UrlsFromMainPageExtract invalid html throws exception', () async { - final extract = UrlsFromMainPageExtract(); + const extract = UrlsFromMainPageExtract(); try { extract.parseMainPage("Lorem ipsum", DualisUrls(), ""); diff --git a/test/schedule/business/schedule_diff_calculator_test.dart b/test/schedule/business/schedule_diff_calculator_test.dart index c832c658..1bc4c182 100644 --- a/test/schedule/business/schedule_diff_calculator_test.dart +++ b/test/schedule/business/schedule_diff_calculator_test.dart @@ -5,7 +5,7 @@ import 'package:test/test.dart'; void main() { test('Diff detect identical schedules', () async { - final calculator = ScheduleDiffCalculator(); + const calculator = ScheduleDiffCalculator(); final oldSchedule = generateSchedule(); final newSchedule = generateSchedule(); @@ -18,7 +18,7 @@ void main() { }); test('Diff detect removed entry', () async { - final calculator = ScheduleDiffCalculator(); + const calculator = ScheduleDiffCalculator(); final oldSchedule = generateSchedule(); final newSchedule = generateSchedule(); @@ -35,7 +35,7 @@ void main() { }); test('Diff detect new entry', () async { - final calculator = ScheduleDiffCalculator(); + const calculator = ScheduleDiffCalculator(); final oldSchedule = generateSchedule(); final newSchedule = generateSchedule(); @@ -61,7 +61,7 @@ void main() { }); test('Diff detect changed entry (time)', () async { - final calculator = ScheduleDiffCalculator(); + const calculator = ScheduleDiffCalculator(); final oldSchedule = generateSchedule(); final newSchedule = generateSchedule(); @@ -88,7 +88,7 @@ void main() { }); test('Diff detect changed entry (start and room)', () async { - final calculator = ScheduleDiffCalculator(); + const calculator = ScheduleDiffCalculator(); final oldSchedule = generateSchedule(); final newSchedule = generateSchedule(); @@ -116,7 +116,7 @@ void main() { }); test('Diff detect two changed entries of same name (start)', () async { - final calculator = ScheduleDiffCalculator(); + const calculator = ScheduleDiffCalculator(); final oldSchedule = generateSchedule(); final newSchedule = generateSchedule(); diff --git a/test/schedule/service/mannheim/mannheim_course_response_parser_test.dart b/test/schedule/service/mannheim/mannheim_course_response_parser_test.dart index 9a906026..d1db7b28 100644 --- a/test/schedule/service/mannheim/mannheim_course_response_parser_test.dart +++ b/test/schedule/service/mannheim/mannheim_course_response_parser_test.dart @@ -9,7 +9,7 @@ Future main() async { ).readAsString(); test('Mannheim course parser parses correctly', () async { - final parser = MannheimCourseResponseParser(); + const parser = MannheimCourseResponseParser(); final courses = parser.parseCoursePage(coursePage);