diff --git a/README.md b/README.md
index 13787ab54..68355e652 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@
[![Build badge](https://img.shields.io/github/actions/workflow/status/NIAEFEUP/uni/format_lint_test.yaml?style=for-the-badge)](https://github.com/NIAEFEUP/uni/actions)
[![Deploy badge](https://img.shields.io/github/actions/workflow/status/NIAEFEUP/uni/deploy.yaml?label=Deploy&style=for-the-badge)](https://github.com/NIAEFEUP/uni/actions)
+
+[![style: very good analysis](https://img.shields.io/badge/style-very_good_analysis-B22C89.svg?style=for-the-badge)](https://pub.dev/packages/very_good_analysis)
[![License badge](https://img.shields.io/github/license/NIAEFEUP/uni?style=for-the-badge)](https://github.com/NIAEFEUP/uni/blob/develop/LICENSE)
diff --git a/uni/analysis_options.yaml b/uni/analysis_options.yaml
index adeb51dc6..be33d4712 100644
--- a/uni/analysis_options.yaml
+++ b/uni/analysis_options.yaml
@@ -1,38 +1,16 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
+include: package:very_good_analysis/analysis_options.yaml
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
+analyzer:
+ # Exclude auto-generated files from dart analysis
+ exclude:
+ - '**.g.dart'
+ - '**.freezed.dart'
+# Custom linter rules. A list of all rules can be found at
+# https://dart-lang.github.io/linter/lints/options/options.html
linter:
- # The lint rules applied to this project can be customized in the
- # section below to disable rules from the `package:flutter_lints/flutter.yaml`
- # included above or to enable additional rules. A list of all available lints
- # and their documentation is published at
- # https://dart-lang.github.io/linter/lints/index.html.
- #
- # Instead of disabling a lint rule for the entire project in the
- # section below, it can also be suppressed for a single line of code
- # or a specific dart file by using the `// ignore: name_of_lint` and
- # `// ignore_for_file: name_of_lint` syntax on the line or in the file
- # producing the lint.
rules:
- # avoid_print: false # Uncomment to disable the `avoid_print` rule
- # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
- always_use_package_imports: true
- prefer_final_locals: true
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+ public_member_api_docs: false
+ avoid_equals_and_hash_code_on_mutable_classes: false
+ one_member_abstracts: false
-analyzer:
- errors:
- # allow for asset_does_not_exist
- unrecognized_error_code: ignore
- # ignore this in pubspec.yaml
- asset_directory_does_not_exist: ignore
\ No newline at end of file
diff --git a/uni/lib/controller/background_workers/background_callback.dart b/uni/lib/controller/background_workers/background_callback.dart
index 2c0833c0f..9c9f45536 100644
--- a/uni/lib/controller/background_workers/background_callback.dart
+++ b/uni/lib/controller/background_workers/background_callback.dart
@@ -7,24 +7,26 @@ import 'package:workmanager/workmanager.dart';
/// the bool is all functions that are ran by backgroundfetch in iOS
/// (they must not take any arguments, not checked)
const taskMap = {
- "pt.up.fe.ni.uni.notificationworker":
+ 'pt.up.fe.ni.uni.notificationworker':
Tuple2(NotificationManager.updateAndTriggerNotifications, true)
};
@pragma('vm:entry-point')
-// This function is android only and only executes when the app is complety terminated
-void workerStartCallback() async {
+// This function is android only and only executes
+// when the app is completely terminated
+Future workerStartCallback() async {
Workmanager().executeTask((taskName, inputData) async {
try {
- Logger().d("""[$taskName]: Start executing job...""");
+ Logger().d('''[$taskName]: Start executing job...''');
- //iOSBackgroundTask is a special task, that iOS runs whenever it deems necessary
- //and will run all tasks with the flag true
- //NOTE: keep the total execution time under 30s to avoid being punished by the iOS scheduler.
+ // iOSBackgroundTask is a special task, that iOS runs whenever
+ // it deems necessary and will run all tasks with the flag true
+ // NOTE: keep the total execution time under 30s to avoid being punished
+ // by the iOS scheduler.
if (taskName == Workmanager.iOSBackgroundTask) {
taskMap.forEach((key, value) async {
if (value.item2) {
- Logger().d("""[$key]: Start executing job...""");
+ Logger().d('''[$key]: Start executing job...''');
await value.item1();
}
});
@@ -34,7 +36,7 @@ void workerStartCallback() async {
//to not be punished by the scheduler in future runs.
await taskMap[taskName]!.item1();
} catch (err, stackstrace) {
- Logger().e("Error while running $taskName job:", err, stackstrace);
+ Logger().e('Error while running $taskName job:', err, stackstrace);
return false;
}
return true;
diff --git a/uni/lib/controller/background_workers/notifications.dart b/uni/lib/controller/background_workers/notifications.dart
index d614116db..f6c7f52f8 100644
--- a/uni/lib/controller/background_workers/notifications.dart
+++ b/uni/lib/controller/background_workers/notifications.dart
@@ -14,37 +14,49 @@ import 'package:uni/model/entities/session.dart';
import 'package:workmanager/workmanager.dart';
///
-/// Stores all notifications that will be checked and displayed in the background.
+/// Stores notifications that will be checked and displayed in the background.
/// Add your custom notification here, because it will NOT be added at runtime.
/// (due to background worker limitations).
///
Map notificationMap = {
- TuitionNotification: () => TuitionNotification(),
+ TuitionNotification: TuitionNotification.new,
};
abstract class Notification {
+ Notification(this.uniqueID, this.timeout);
+
String uniqueID;
Duration timeout;
- Notification(this.uniqueID, this.timeout);
-
Future> buildNotificationContent(Session session);
Future shouldDisplay(Session session);
- void displayNotification(Tuple2 content,
- FlutterLocalNotificationsPlugin localNotificationsPlugin);
+ void displayNotification(
+ Tuple2 content,
+ FlutterLocalNotificationsPlugin localNotificationsPlugin,
+ );
- Future displayNotificationIfPossible(Session session,
- FlutterLocalNotificationsPlugin localNotificationsPlugin) async {
+ Future displayNotificationIfPossible(
+ Session session,
+ FlutterLocalNotificationsPlugin localNotificationsPlugin,
+ ) async {
if (await shouldDisplay(session)) {
displayNotification(
- await buildNotificationContent(session), localNotificationsPlugin);
+ await buildNotificationContent(session),
+ localNotificationsPlugin,
+ );
}
}
}
class NotificationManager {
+ factory NotificationManager() {
+ return _notificationManager;
+ }
+
+ NotificationManager._internal();
+
static final NotificationManager _notificationManager =
NotificationManager._internal();
@@ -55,71 +67,77 @@ class NotificationManager {
static const Duration _notificationWorkerPeriod = Duration(hours: 1);
- factory NotificationManager() {
- return _notificationManager;
- }
-
static Future updateAndTriggerNotifications() async {
final userInfo = await AppSharedPreferences.getPersistentUserInfo();
final faculties = await AppSharedPreferences.getUserFaculties();
- final Session? session = await NetworkRouter.login(
- userInfo.item1, userInfo.item2, faculties, false);
+ final session = await NetworkRouter.login(
+ userInfo.item1,
+ userInfo.item2,
+ faculties,
+ persistentSession: false,
+ );
if (session == null) {
return;
}
- // Get the .json file that contains the last time that the notification has ran
- _initFlutterNotificationsPlugin();
+ // Get the .json file that contains the last time that the
+ // notification has ran
+ await _initFlutterNotificationsPlugin();
final notificationStorage = await NotificationTimeoutStorage.create();
- for (Notification Function() value in notificationMap.values) {
- final Notification notification = value();
- final DateTime lastRan = notificationStorage
+ for (final value in notificationMap.values) {
+ final notification = value();
+ final lastRan = notificationStorage
.getLastTimeNotificationExecuted(notification.uniqueID);
if (lastRan.add(notification.timeout).isBefore(DateTime.now())) {
await notification.displayNotificationIfPossible(
- session, _localNotificationsPlugin);
+ session,
+ _localNotificationsPlugin,
+ );
await notificationStorage.addLastTimeNotificationExecuted(
- notification.uniqueID, DateTime.now());
+ notification.uniqueID,
+ DateTime.now(),
+ );
}
}
}
- void initializeNotifications() async {
- // guarantees that the execution is only done once in the lifetime of the app.
+ Future initializeNotifications() async {
+ // guarantees that the execution is only done
+ // once in the lifetime of the app.
if (_initialized) return;
_initialized = true;
- _initFlutterNotificationsPlugin();
- _buildNotificationWorker();
+ await _initFlutterNotificationsPlugin();
+ await _buildNotificationWorker();
}
- static void _initFlutterNotificationsPlugin() async {
- const AndroidInitializationSettings initializationSettingsAndroid =
+ static Future _initFlutterNotificationsPlugin() async {
+ const initializationSettingsAndroid =
AndroidInitializationSettings('ic_notification');
//request for notifications immediatly on iOS
- const DarwinInitializationSettings darwinInitializationSettings =
- DarwinInitializationSettings(
- requestAlertPermission: true,
- requestBadgePermission: true,
- requestCriticalPermission: true);
-
- const InitializationSettings initializationSettings =
- InitializationSettings(
- android: initializationSettingsAndroid,
- iOS: darwinInitializationSettings,
- macOS: darwinInitializationSettings);
+ const darwinInitializationSettings = DarwinInitializationSettings(
+ requestCriticalPermission: true,
+ );
+
+ const initializationSettings = InitializationSettings(
+ android: initializationSettingsAndroid,
+ iOS: darwinInitializationSettings,
+ macOS: darwinInitializationSettings,
+ );
await _localNotificationsPlugin.initialize(initializationSettings);
- //specific to android 13+, 12 or lower permission is requested when the first notification channel opens
+ // specific to android 13+, 12 or lower permission is requested when
+ // the first notification channel opens
if (Platform.isAndroid) {
- final AndroidFlutterLocalNotificationsPlugin androidPlugin =
- _localNotificationsPlugin.resolvePlatformSpecificImplementation()!;
+ final androidPlugin =
+ _localNotificationsPlugin.resolvePlatformSpecificImplementation<
+ AndroidFlutterLocalNotificationsPlugin>()!;
try {
- final bool? permissionGranted = await androidPlugin.requestPermission();
+ final permissionGranted = await androidPlugin.requestPermission();
if (permissionGranted != true) {
return;
}
@@ -127,31 +145,33 @@ class NotificationManager {
}
}
- NotificationManager._internal();
-
- static void _buildNotificationWorker() async {
+ static Future _buildNotificationWorker() async {
if (Platform.isAndroid) {
- Workmanager().cancelByUniqueName(
- "pt.up.fe.ni.uni.notificationworker"); //stop task if it's already running
- Workmanager().registerPeriodicTask(
- "pt.up.fe.ni.uni.notificationworker",
- "pt.up.fe.ni.uni.notificationworker",
+ await Workmanager().cancelByUniqueName(
+ 'pt.up.fe.ni.uni.notificationworker',
+ ); //stop task if it's already running
+ await Workmanager().registerPeriodicTask(
+ 'pt.up.fe.ni.uni.notificationworker',
+ 'pt.up.fe.ni.uni.notificationworker',
constraints: Constraints(networkType: NetworkType.connected),
frequency: _notificationWorkerPeriod,
);
} else if (Platform.isIOS || kIsWeb) {
- //This is to guarentee that the notification will be run at least the app starts.
- //NOTE (luisd): This is not an isolate because we can't register plugins in a isolate, in the current version of flutter
- // so we just do it after login
- Logger().d("Running notification worker on main isolate...");
+ // This is to guarantee that the notification
+ // will be run at least once the app starts.
+ // NOTE (luisd): This is not an isolate because we can't register plugins
+ // in a isolate, in the current version of flutter
+ // so we just do it after login
+ Logger().d('Running notification worker on main isolate...');
await updateAndTriggerNotifications();
Timer.periodic(_notificationWorkerPeriod, (timer) {
- Logger().d("Running notification worker on periodic timer...");
+ Logger().d('Running notification worker on periodic timer...');
updateAndTriggerNotifications();
});
} else {
throw PlatformException(
- code: "WorkerManager is only supported in iOS and android...");
+ code: 'WorkerManager is only supported in iOS and android...',
+ );
}
}
}
diff --git a/uni/lib/controller/background_workers/notifications/tuition_notification.dart b/uni/lib/controller/background_workers/notifications/tuition_notification.dart
index db6e43abd..738b5ce24 100644
--- a/uni/lib/controller/background_workers/notifications/tuition_notification.dart
+++ b/uni/lib/controller/background_workers/notifications/tuition_notification.dart
@@ -8,45 +8,57 @@ import 'package:uni/model/entities/session.dart';
import 'package:uni/utils/duration_string_formatter.dart';
class TuitionNotification extends Notification {
- late DateTime _dueDate;
-
TuitionNotification()
- : super("tuition-notification", const Duration(hours: 12));
+ : super('tuition-notification', const Duration(hours: 12));
+ late DateTime _dueDate;
@override
Future> buildNotificationContent(
- Session session) async {
- //We must add one day because the time limit is actually at 23:59 and not at 00:00 of the same day
+ Session session,
+ ) async {
+ // We must add one day because the time limit is actually at 23:59 and
+ // not at 00:00 of the same day
if (_dueDate.add(const Duration(days: 1)).isBefore(DateTime.now())) {
- final Duration duration = DateTime.now().difference(_dueDate);
+ final duration = DateTime.now().difference(_dueDate);
if (duration.inDays == 0) {
- return const Tuple2("⚠️ Ainda não pagaste as propinas ⚠️",
- "O prazo para pagar as propinas acabou ontem");
+ return const Tuple2(
+ '⚠️ Ainda não pagaste as propinas ⚠️',
+ 'O prazo para pagar as propinas acabou ontem',
+ );
}
return Tuple2(
- "⚠️ Ainda não pagaste as propinas ⚠️",
- duration.toFormattedString("Já passou {} desde a data limite",
- "Já passaram {} desde a data limite"));
+ '⚠️ Ainda não pagaste as propinas ⚠️',
+ duration.toFormattedString(
+ 'Já passou {} desde a data limite',
+ 'Já passaram {} desde a data limite',
+ ),
+ );
}
- final Duration duration = _dueDate.difference(DateTime.now());
+ final duration = _dueDate.difference(DateTime.now());
if (duration.inDays == 0) {
- return const Tuple2("O prazo limite para as propinas está a acabar",
- "Hoje acaba o prazo para pagamento das propinas!");
+ return const Tuple2(
+ 'O prazo limite para as propinas está a acabar',
+ 'Hoje acaba o prazo para pagamento das propinas!',
+ );
}
return Tuple2(
- "O prazo limite para as propinas está a acabar",
- duration.toFormattedString(
- "Falta {} para a data limite", "Faltam {} para a data limite"));
+ 'O prazo limite para as propinas está a acabar',
+ duration.toFormattedString(
+ 'Falta {} para a data limite',
+ 'Faltam {} para a data limite',
+ ),
+ );
}
@override
Future shouldDisplay(Session session) async {
- final bool notificationsAreDisabled =
+ final notificationsAreDisabled =
!(await AppSharedPreferences.getTuitionNotificationToggle());
if (notificationsAreDisabled) return false;
- final FeesFetcher feesFetcher = FeesFetcher();
- final DateTime? dueDate = await parseFeesNextLimit(
- await feesFetcher.getUserFeesResponse(session));
+ final feesFetcher = FeesFetcher();
+ final dueDate = parseFeesNextLimit(
+ await feesFetcher.getUserFeesResponse(session),
+ );
if (dueDate == null) return false;
@@ -55,25 +67,33 @@ class TuitionNotification extends Notification {
}
@override
- void displayNotification(Tuple2 content,
- FlutterLocalNotificationsPlugin localNotificationsPlugin) {
- const AndroidNotificationDetails androidNotificationDetails =
- AndroidNotificationDetails(
- "propinas-notificacao", "propinas-notificacao",
- importance: Importance.high);
+ void displayNotification(
+ Tuple2 content,
+ FlutterLocalNotificationsPlugin localNotificationsPlugin,
+ ) {
+ const androidNotificationDetails = AndroidNotificationDetails(
+ 'propinas-notificacao',
+ 'propinas-notificacao',
+ importance: Importance.high,
+ );
- const DarwinNotificationDetails darwinNotificationDetails =
- DarwinNotificationDetails(
- presentAlert: true,
- presentBadge: true,
- interruptionLevel: InterruptionLevel.active);
+ const darwinNotificationDetails = DarwinNotificationDetails(
+ presentAlert: true,
+ presentBadge: true,
+ interruptionLevel: InterruptionLevel.active,
+ );
- const NotificationDetails notificationDetails = NotificationDetails(
- android: androidNotificationDetails,
- iOS: darwinNotificationDetails,
- macOS: darwinNotificationDetails);
+ const notificationDetails = NotificationDetails(
+ android: androidNotificationDetails,
+ iOS: darwinNotificationDetails,
+ macOS: darwinNotificationDetails,
+ );
localNotificationsPlugin.show(
- 2, content.item1, content.item2, notificationDetails);
+ 2,
+ content.item1,
+ content.item2,
+ notificationDetails,
+ );
}
}
diff --git a/uni/lib/controller/fetchers/calendar_fetcher_html.dart b/uni/lib/controller/fetchers/calendar_fetcher_html.dart
index ea4ec32a9..e08119850 100644
--- a/uni/lib/controller/fetchers/calendar_fetcher_html.dart
+++ b/uni/lib/controller/fetchers/calendar_fetcher_html.dart
@@ -1,4 +1,3 @@
-import 'package:http/http.dart';
import 'package:uni/controller/fetchers/session_dependant_fetcher.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_calendar.dart';
@@ -9,19 +8,17 @@ import 'package:uni/model/entities/session.dart';
class CalendarFetcherHtml implements SessionDependantFetcher {
@override
List getEndpoints(Session session) {
- // TO DO: Implement parsers for all faculties
+ // TODO(bdmendes): Implement parsers for all faculties
// and dispatch for different fetchers
- final String url =
- '${NetworkRouter.getBaseUrl('feup')}web_base.gera_pagina?p_pagina=página%20estática%20genérica%20106';
+ final url = '${NetworkRouter.getBaseUrl('feup')}'
+ 'web_base.gera_pagina?p_pagina=página%20estática%20genérica%20106';
return [url];
}
Future> getCalendar(Session session) async {
- final String url = getEndpoints(session)[0];
- final Future response =
- NetworkRouter.getWithCookies(url, {}, session);
- final List calendar =
- await response.then((response) => getCalendarFromHtml(response));
+ final url = getEndpoints(session)[0];
+ final response = NetworkRouter.getWithCookies(url, {}, session);
+ final calendar = await response.then(getCalendarFromHtml);
return calendar;
}
}
diff --git a/uni/lib/controller/fetchers/course_units_fetcher/all_course_units_fetcher.dart b/uni/lib/controller/fetchers/course_units_fetcher/all_course_units_fetcher.dart
index 4cb53205e..c6dbdc8e2 100644
--- a/uni/lib/controller/fetchers/course_units_fetcher/all_course_units_fetcher.dart
+++ b/uni/lib/controller/fetchers/course_units_fetcher/all_course_units_fetcher.dart
@@ -6,35 +6,41 @@ import 'package:uni/model/entities/course_units/course_unit.dart';
import 'package:uni/model/entities/session.dart';
class AllCourseUnitsFetcher {
- Future> getAllCourseUnitsAndCourseAverages(
- List courses, Session session) async {
- final List allCourseUnits = [];
- for (Course course in courses) {
+ Future?> getAllCourseUnitsAndCourseAverages(
+ List courses,
+ Session session,
+ ) async {
+ final allCourseUnits = [];
+
+ for (final course in courses) {
try {
- final List courseUnits =
- await _getAllCourseUnitsAndCourseAveragesFromCourse(
- course, session);
+ final courseUnits = await _getAllCourseUnitsAndCourseAveragesFromCourse(
+ course,
+ session,
+ );
allCourseUnits.addAll(courseUnits.where((c) => c.enrollmentIsValid()));
} catch (e) {
Logger().e('Failed to fetch course units for ${course.name}', e);
+ return null;
}
}
+
return allCourseUnits;
}
Future> _getAllCourseUnitsAndCourseAveragesFromCourse(
- Course course, Session session) async {
- if (course.faculty == null) {
- return [];
- }
- final String url =
- '${NetworkRouter.getBaseUrl(course.faculty!)}fest_geral.curso_percurso_academico_view';
+ Course course,
+ Session session,
+ ) async {
+ final url = '${NetworkRouter.getBaseUrl(course.faculty!)}'
+ 'fest_geral.curso_percurso_academico_view';
final response = await NetworkRouter.getWithCookies(
- url,
- {
- 'pv_fest_id': course.festId.toString(),
- },
- session);
+ url,
+ {
+ 'pv_fest_id': course.festId.toString(),
+ },
+ session,
+ );
return parseCourseUnitsAndCourseAverage(response, course);
}
}
diff --git a/uni/lib/controller/fetchers/course_units_fetcher/course_units_info_fetcher.dart b/uni/lib/controller/fetchers/course_units_fetcher/course_units_info_fetcher.dart
index f2e39788c..608a23f6c 100644
--- a/uni/lib/controller/fetchers/course_units_fetcher/course_units_info_fetcher.dart
+++ b/uni/lib/controller/fetchers/course_units_fetcher/course_units_info_fetcher.dart
@@ -1,5 +1,4 @@
import 'package:html/parser.dart';
-import 'package:http/http.dart';
import 'package:uni/controller/fetchers/session_dependant_fetcher.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_course_unit_info.dart';
@@ -14,43 +13,51 @@ class CourseUnitsInfoFetcher implements SessionDependantFetcher {
}
Future fetchCourseUnitSheet(
- Session session, int occurrId) async {
+ Session session,
+ int occurrId,
+ ) async {
// if course unit is not from the main faculty, Sigarra redirects
- final String url = '${getEndpoints(session)[0]}ucurr_geral.ficha_uc_view';
- final Response response = await NetworkRouter.getWithCookies(
- url, {'pv_ocorrencia_id': occurrId.toString()}, session);
+ final url = '${getEndpoints(session)[0]}ucurr_geral.ficha_uc_view';
+ final response = await NetworkRouter.getWithCookies(
+ url,
+ {'pv_ocorrencia_id': occurrId.toString()},
+ session,
+ );
return parseCourseUnitSheet(response);
}
Future> fetchCourseUnitClasses(
- Session session, int occurrId) async {
- List courseUnitClasses = [];
+ Session session,
+ int occurrId,
+ ) async {
+ var courseUnitClasses = [];
- for (String endpoint in getEndpoints(session)) {
+ for (final endpoint in getEndpoints(session)) {
// Crawl classes from all courses that the course unit is offered in
- final String courseChoiceUrl =
- '${endpoint}it_listagem.lista_cursos_disciplina?pv_ocorrencia_id=$occurrId';
- final Response courseChoiceResponse =
+ final courseChoiceUrl = '$endpoint'
+ 'it_listagem.lista_cursos_disciplina?pv_ocorrencia_id=$occurrId';
+ final courseChoiceResponse =
await NetworkRouter.getWithCookies(courseChoiceUrl, {}, session);
final courseChoiceDocument = parse(courseChoiceResponse.body);
- final List urls = courseChoiceDocument
+ final urls = courseChoiceDocument
.querySelectorAll('a')
- .where((element) =>
- element.attributes['href'] != null &&
- element.attributes['href']!
- .contains('it_listagem.lista_turma_disciplina'))
+ .where(
+ (element) =>
+ element.attributes['href'] != null &&
+ element.attributes['href']!
+ .contains('it_listagem.lista_turma_disciplina'),
+ )
.map((e) {
- String? url = e.attributes['href']!;
+ var url = e.attributes['href']!;
if (!url.contains('sigarra.up.pt')) {
url = endpoint + url;
}
return url;
}).toList();
- for (String url in urls) {
+ for (final url in urls) {
try {
- final Response response =
- await NetworkRouter.getWithCookies(url, {}, session);
+ final response = await NetworkRouter.getWithCookies(url, {}, session);
courseUnitClasses += parseCourseUnitClasses(response, endpoint);
} catch (_) {
continue;
diff --git a/uni/lib/controller/fetchers/course_units_fetcher/current_course_units_fetcher.dart b/uni/lib/controller/fetchers/course_units_fetcher/current_course_units_fetcher.dart
index 7160c5369..e4250858a 100644
--- a/uni/lib/controller/fetchers/course_units_fetcher/current_course_units_fetcher.dart
+++ b/uni/lib/controller/fetchers/course_units_fetcher/current_course_units_fetcher.dart
@@ -1,6 +1,5 @@
import 'dart:convert';
-import 'package:http/http.dart';
import 'package:uni/controller/fetchers/session_dependant_fetcher.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/model/entities/course_units/course_unit.dart';
@@ -10,28 +9,38 @@ class CurrentCourseUnitsFetcher implements SessionDependantFetcher {
@override
List getEndpoints(Session session) {
// all faculties list user course units on all faculties
- final String url =
- '${NetworkRouter.getBaseUrlsFromSession(session)[0]}mob_fest_geral.ucurr_inscricoes_corrente';
+ final url = '${NetworkRouter.getBaseUrlsFromSession(session)[0]}'
+ 'mob_fest_geral.ucurr_inscricoes_corrente';
return [url];
}
Future> getCurrentCourseUnits(Session session) async {
- final String url = getEndpoints(session)[0];
- final Response response = await NetworkRouter.getWithCookies(
- url, {'pv_codigo': session.username}, session);
- if (response.statusCode == 200) {
- final responseBody = json.decode(response.body);
- final List ucs = [];
- for (var course in responseBody) {
- for (var uc in course['inscricoes']) {
- final CourseUnit? courseUnit = CourseUnit.fromJson(uc);
- if (courseUnit != null) {
- ucs.add(courseUnit);
- }
+ final url = getEndpoints(session)[0];
+ final response = await NetworkRouter.getWithCookies(
+ url,
+ {'pv_codigo': session.username},
+ session,
+ );
+
+ if (response.statusCode != 200) {
+ return [];
+ }
+
+ final responseBody = json.decode(response.body) as List;
+
+ final ucs = [];
+
+ for (final course in responseBody) {
+ final enrollments =
+ (course as Map)['inscricoes'] as List;
+ for (final uc in enrollments) {
+ final courseUnit = CourseUnit.fromJson(uc as Map);
+ if (courseUnit != null) {
+ ucs.add(courseUnit);
}
}
- return ucs;
}
- return [];
+
+ return ucs;
}
}
diff --git a/uni/lib/controller/fetchers/courses_fetcher.dart b/uni/lib/controller/fetchers/courses_fetcher.dart
index 2e0f50808..776e042e1 100644
--- a/uni/lib/controller/fetchers/courses_fetcher.dart
+++ b/uni/lib/controller/fetchers/courses_fetcher.dart
@@ -17,8 +17,13 @@ class CoursesFetcher implements SessionDependantFetcher {
List> getCoursesListResponses(Session session) {
final urls = getEndpoints(session);
return urls
- .map((url) => NetworkRouter.getWithCookies(
- url, {'pv_num_unico': session.username}, session))
+ .map(
+ (url) => NetworkRouter.getWithCookies(
+ url,
+ {'pv_num_unico': session.username},
+ session,
+ ),
+ )
.toList();
}
}
diff --git a/uni/lib/controller/fetchers/departures_fetcher.dart b/uni/lib/controller/fetchers/departures_fetcher.dart
index 4c63c0211..921c42113 100644
--- a/uni/lib/controller/fetchers/departures_fetcher.dart
+++ b/uni/lib/controller/fetchers/departures_fetcher.dart
@@ -1,23 +1,24 @@
import 'dart:convert';
+import 'package:html/dom.dart';
+import 'package:html/parser.dart';
+import 'package:http/http.dart' as http;
+import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/model/entities/bus.dart';
import 'package:uni/model/entities/bus_stop.dart';
-import 'package:http/http.dart' as http;
-import 'package:html/parser.dart';
import 'package:uni/model/entities/trip.dart';
-import 'package:uni/controller/networking/network_router.dart';
class DeparturesFetcher {
+ DeparturesFetcher(this._stopCode, this._stopData);
+
final String _stopCode;
final BusStopData _stopData;
- DeparturesFetcher(this._stopCode, this._stopData);
-
Future _getCSRFToken() async {
final url =
'https://www.stcp.pt/en/travel/timetables/?paragem=$_stopCode&t=smsbus';
- final http.Response response = await http.get(url.toUri());
+ final response = await http.get(url.toUri());
final htmlResponse = parse(response.body);
final scriptText = htmlResponse
@@ -32,7 +33,9 @@ class DeparturesFetcher {
.firstWhere((element) => element.contains(')'));
final csrfToken = callParam.substring(
- callParam.indexOf('\'') + 1, callParam.lastIndexOf('\''));
+ callParam.indexOf("'") + 1,
+ callParam.lastIndexOf("'"),
+ );
return csrfToken;
}
@@ -47,7 +50,7 @@ class DeparturesFetcher {
final url =
'https://www.stcp.pt/pt/itinerarium/soapclient.php?codigo=$_stopCode&hash123=$csrfToken';
- final http.Response response = await http.get(url.toUri());
+ final response = await http.get(url.toUri());
final htmlResponse = parse(response.body);
final tableEntries =
@@ -57,7 +60,7 @@ class DeparturesFetcher {
final tripList = [];
- for (var entry in tableEntries) {
+ for (final entry in tableEntries) {
final rawBusInformation = entry.querySelectorAll('td');
final busLine =
@@ -75,12 +78,13 @@ class DeparturesFetcher {
.replaceAll('-', '')
.substring(busLine!.length + 1);
- final busTimeRemaining = getBusTimeRemaining(rawBusInformation);
+ final busTimeRemaining = _getBusTimeRemaining(rawBusInformation);
- final Trip newTrip = Trip(
- line: busLine,
- destination: busDestination,
- timeRemaining: busTimeRemaining);
+ final newTrip = Trip(
+ line: busLine,
+ destination: busDestination,
+ timeRemaining: busTimeRemaining,
+ );
tripList.add(newTrip);
}
@@ -88,28 +92,31 @@ class DeparturesFetcher {
}
/// Extracts the time remaining for a bus to reach a stop.
- static int getBusTimeRemaining(rawBusInformation) {
+ static int _getBusTimeRemaining(List rawBusInformation) {
if (rawBusInformation[1].text.trim() == 'a passar') {
return 0;
} else {
- final regex = RegExp(r'([0-9]+)');
+ final regex = RegExp('([0-9]+)');
- return int.parse(regex.stringMatch(rawBusInformation[2].text).toString());
+ return int.parse(
+ regex.stringMatch(rawBusInformation[2].text).toString(),
+ );
}
}
/// Retrieves the name and code of the stops with code [stopCode].
static Future> getStopsByName(String stopCode) async {
- final List stopsList = [];
+ final stopsList = [];
- //Search by approximate name
- final String url =
+ // Search by approximate name
+ final url =
'https://www.stcp.pt/pt/itinerarium/callservice.php?action=srchstoplines&stopname=$stopCode';
- final http.Response response = await http.post(url.toUri());
- final List json = jsonDecode(response.body);
- for (var busKey in json) {
- final String stop = busKey['name'] + ' [' + busKey['code'] + ']';
- stopsList.add(stop);
+ final response = await http.post(url.toUri());
+ final json = jsonDecode(response.body) as List;
+ for (final busKey in json) {
+ final bus = busKey as Map;
+ final stopDescription = '${bus['name']} [${bus['code']}]';
+ stopsList.add(stopDescription);
}
return stopsList;
@@ -117,27 +124,31 @@ class DeparturesFetcher {
/// Retrieves real-time information about the user's selected bus lines.
static Future> getNextArrivalsStop(
- String stopCode, BusStopData stopData) {
+ String stopCode,
+ BusStopData stopData,
+ ) {
return DeparturesFetcher(stopCode, stopData).getDepartures();
}
/// Returns the bus lines that stop at the given [stop].
static Future> getBusesStoppingAt(String stop) async {
- final String url =
+ final url =
'https://www.stcp.pt/pt/itinerarium/callservice.php?action=srchstoplines&stopcode=$stop';
- final http.Response response = await http.post(url.toUri());
+ final response = await http.post(url.toUri());
- final List json = jsonDecode(response.body);
+ final json = jsonDecode(response.body) as List;
- final List buses = [];
+ final buses = [];
- for (var busKey in json) {
- final lines = busKey['lines'];
- for (var bus in lines) {
- final Bus newBus = Bus(
- busCode: bus['code'],
- destination: bus['description'],
- direction: (bus['dir'] == 0 ? false : true));
+ for (final data in json) {
+ final lines = (data as Map)['lines'] as List;
+ for (final busInfo in lines) {
+ final bus = busInfo as Map;
+ final newBus = Bus(
+ busCode: bus['code'] as String,
+ destination: bus['description'] as String,
+ direction: bus['dir'] != 0,
+ );
buses.add(newBus);
}
}
diff --git a/uni/lib/controller/fetchers/exam_fetcher.dart b/uni/lib/controller/fetchers/exam_fetcher.dart
index 4ddd49076..9231eff88 100644
--- a/uni/lib/controller/fetchers/exam_fetcher.dart
+++ b/uni/lib/controller/fetchers/exam_fetcher.dart
@@ -7,9 +7,9 @@ import 'package:uni/model/entities/exam.dart';
import 'package:uni/model/entities/session.dart';
class ExamFetcher implements SessionDependantFetcher {
+ ExamFetcher(this.courses, this.userUcs);
List courses;
List userUcs;
- ExamFetcher(this.courses, this.userUcs);
@override
List getEndpoints(Session session) {
@@ -20,24 +20,31 @@ class ExamFetcher implements SessionDependantFetcher {
}
Future> extractExams(
- Session session, ParserExams parserExams) async {
- Set courseExams = {};
+ Session session,
+ ParserExams parserExams,
+ ) async {
+ var courseExams = {};
final urls = getEndpoints(session);
- for (Course course in courses) {
+ for (final course in courses) {
for (final url in urls) {
- final Set currentCourseExams = await parserExams.parseExams(
- await NetworkRouter.getWithCookies(
- url, {'p_curso_id': course.id.toString()}, session),
- course);
+ final currentCourseExams = await parserExams.parseExams(
+ await NetworkRouter.getWithCookies(
+ url,
+ {'p_curso_id': course.id.toString()},
+ session,
+ ),
+ course,
+ );
courseExams = Set.from(courseExams)..addAll(currentCourseExams);
}
}
- final Set exams = {};
- for (Exam courseExam in courseExams) {
- for (CourseUnit uc in userUcs) {
+ final exams = {};
+ for (final courseExam in courseExams) {
+ for (final uc in userUcs) {
if (!courseExam.type.contains(
- '''Exames ao abrigo de estatutos especiais - Port.Est.Especiais''') &&
+ '''Exames ao abrigo de estatutos especiais - Port.Est.Especiais''',
+ ) &&
courseExam.type != 'EE' &&
courseExam.type != 'EAE' &&
courseExam.subject == uc.abbreviation &&
diff --git a/uni/lib/controller/fetchers/fees_fetcher.dart b/uni/lib/controller/fetchers/fees_fetcher.dart
index edd225aae..c08a35164 100644
--- a/uni/lib/controller/fetchers/fees_fetcher.dart
+++ b/uni/lib/controller/fetchers/fees_fetcher.dart
@@ -8,14 +8,14 @@ class FeesFetcher implements SessionDependantFetcher {
List getEndpoints(Session session) {
// TO DO: Check balance on all faculties and discard if user is not enrolled
// Some shared courses (such as L.EIC) do not put fees on both faculties
- final url =
- '${NetworkRouter.getBaseUrlsFromSession(session)[0]}gpag_ccorrente_geral.conta_corrente_view';
+ final url = '${NetworkRouter.getBaseUrlsFromSession(session)[0]}'
+ 'gpag_ccorrente_geral.conta_corrente_view';
return [url];
}
Future getUserFeesResponse(Session session) {
- final String url = getEndpoints(session)[0];
- final Map query = {'pct_cod': session.username};
+ final url = getEndpoints(session)[0];
+ final query = {'pct_cod': session.username};
return NetworkRouter.getWithCookies(url, query, session);
}
}
diff --git a/uni/lib/controller/fetchers/library_occupation_fetcher.dart b/uni/lib/controller/fetchers/library_occupation_fetcher.dart
index eb0c989b2..1c7efae69 100644
--- a/uni/lib/controller/fetchers/library_occupation_fetcher.dart
+++ b/uni/lib/controller/fetchers/library_occupation_fetcher.dart
@@ -1,4 +1,3 @@
-import 'package:http/http.dart';
import 'package:uni/controller/fetchers/session_dependant_fetcher.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_library_occupation.dart';
@@ -9,22 +8,19 @@ import 'package:uni/model/entities/session.dart';
class LibraryOccupationFetcherSheets implements SessionDependantFetcher {
@override
List getEndpoints(Session session) {
- // TODO:: Implement parsers for all faculties
- // and dispatch for different fetchers
- const String baseUrl = 'https://docs.google.com/spreadsheets/d/';
- const String sheetId = '1gZRbEX4y8vNW7vrl15FCdAQ3pVNRJw_uRZtVL6ORP0g';
- const String url =
+ const baseUrl = 'https://docs.google.com/spreadsheets/d/';
+ const sheetId = '1gZRbEX4y8vNW7vrl15FCdAQ3pVNRJw_uRZtVL6ORP0g';
+ const url =
'$baseUrl$sheetId/gviz/tq?tqx=out:json&sheet=MANUAL&range=C2:E7&tq=SELECT+C,E';
return [url];
}
Future getLibraryOccupationFromSheets(
- Session session) async {
- final String url = getEndpoints(session)[0];
- final Future response =
- NetworkRouter.getWithCookies(url, {}, session);
- final LibraryOccupation occupation = await response
- .then((response) => parseLibraryOccupationFromSheets(response));
+ Session session,
+ ) async {
+ final url = getEndpoints(session)[0];
+ final response = NetworkRouter.getWithCookies(url, {}, session);
+ final occupation = await response.then(parseLibraryOccupationFromSheets);
return occupation;
}
}
diff --git a/uni/lib/controller/fetchers/location_fetcher/location_fetcher.dart b/uni/lib/controller/fetchers/location_fetcher/location_fetcher.dart
index e464ce430..6bbdf2623 100644
--- a/uni/lib/controller/fetchers/location_fetcher/location_fetcher.dart
+++ b/uni/lib/controller/fetchers/location_fetcher/location_fetcher.dart
@@ -8,27 +8,36 @@ abstract class LocationFetcher {
Future> getLocations();
Future> getFromJSON(String jsonStr) async {
- final Map json = jsonDecode(jsonStr);
- final List groupsMap = json['data'];
- final List groups = [];
+ final json = jsonDecode(jsonStr) as Map;
+ final groupsMap = json['data'] as List;
+ final groups = [];
- for (Map groupMap in groupsMap) {
- final int id = groupMap['id'];
- final double lat = groupMap['lat'];
- final double lng = groupMap['lng'];
- final bool isFloorless = groupMap['isFloorless'];
+ for (final groupMap in groupsMap) {
+ final map = groupMap as Map;
+ final id = map['id'] as int;
+ final lat = map['lat'] as double;
+ final lng = map['lng'] as double;
+ final isFloorless = map['isFloorless'] as bool;
- final Map locationsMap = groupMap['locations'];
+ final locationsMap = map['locations'] as Map;
- final List locations = [];
+ final locations = [];
locationsMap.forEach((key, value) {
- final int floor = int.parse(key);
- value.forEach((locationJson) {
- locations.add(Location.fromJSON(locationJson, floor));
- });
+ final floor = int.parse(key);
+ for (final locationJson in value as List) {
+ locations.add(
+ Location.fromJSON(locationJson as Map, floor),
+ );
+ }
});
- groups.add(LocationGroup(LatLng(lat, lng),
- locations: locations, isFloorless: isFloorless, id: id));
+ groups.add(
+ LocationGroup(
+ LatLng(lat, lng),
+ locations: locations,
+ isFloorless: isFloorless,
+ id: id,
+ ),
+ );
}
return groups;
diff --git a/uni/lib/controller/fetchers/location_fetcher/location_fetcher_asset.dart b/uni/lib/controller/fetchers/location_fetcher/location_fetcher_asset.dart
index cf2249986..621adf857 100644
--- a/uni/lib/controller/fetchers/location_fetcher/location_fetcher_asset.dart
+++ b/uni/lib/controller/fetchers/location_fetcher/location_fetcher_asset.dart
@@ -5,8 +5,7 @@ import 'package:uni/model/entities/location_group.dart';
class LocationFetcherAsset extends LocationFetcher {
@override
Future> getLocations() async {
- final String json =
- await rootBundle.loadString('assets/text/locations/feup.json');
+ final json = await rootBundle.loadString('assets/text/locations/feup.json');
return getFromJSON(json);
}
}
diff --git a/uni/lib/controller/fetchers/print_fetcher.dart b/uni/lib/controller/fetchers/print_fetcher.dart
index 9907dac03..e48e46d35 100644
--- a/uni/lib/controller/fetchers/print_fetcher.dart
+++ b/uni/lib/controller/fetchers/print_fetcher.dart
@@ -6,32 +6,34 @@ import 'package:uni/model/entities/session.dart';
class PrintFetcher implements SessionDependantFetcher {
@override
List getEndpoints(Session session) {
- final url =
- '${NetworkRouter.getBaseUrl('feup')}imp4_impressoes.atribs'; // endpoint only available for feup
+ final url = '${NetworkRouter.getBaseUrl('feup')}imp4_impressoes.atribs';
+ // endpoint only available for feup
return [url];
}
- getUserPrintsResponse(Session session) {
- final String url = getEndpoints(session)[0];
- final Map query = {'p_codigo': session.username};
+ Future getUserPrintsResponse(Session session) {
+ final url = getEndpoints(session)[0];
+ final query = {'p_codigo': session.username};
return NetworkRouter.getWithCookies(url, query, session);
}
- static Future generatePrintMoneyReference(
- double amount, Session session) async {
+ static Future generatePrintMoneyReference(
+ double amount,
+ Session session,
+ ) async {
if (amount < 1.0) return Future.error('Amount less than 1,00€');
- final url =
- '${NetworkRouter.getBaseUrlsFromSession(session)[0]}gpag_ccorrentes_geral.gerar_mb';
+ final url = '${NetworkRouter.getBaseUrlsFromSession(session)[0]}'
+ 'gpag_ccorrentes_geral.gerar_mb';
- final Map data = {
+ final data = {
'p_tipo_id': '3',
'pct_codigo': session.username,
'p_valor': '1',
'p_valor_livre': amount.toStringAsFixed(2).trim().replaceAll('.', ',')
};
- final Map headers = {};
+ final headers = {};
headers['cookie'] = session.cookies;
headers['content-type'] = 'application/x-www-form-urlencoded';
diff --git a/uni/lib/controller/fetchers/profile_fetcher.dart b/uni/lib/controller/fetchers/profile_fetcher.dart
index d15a4ef1d..56a239d64 100644
--- a/uni/lib/controller/fetchers/profile_fetcher.dart
+++ b/uni/lib/controller/fetchers/profile_fetcher.dart
@@ -1,10 +1,8 @@
-import 'package:http/http.dart';
import 'package:logger/logger.dart';
import 'package:uni/controller/fetchers/courses_fetcher.dart';
import 'package:uni/controller/fetchers/session_dependant_fetcher.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_courses.dart';
-import 'package:uni/model/entities/course.dart';
import 'package:uni/model/entities/profile.dart';
import 'package:uni/model/entities/session.dart';
@@ -12,41 +10,47 @@ class ProfileFetcher implements SessionDependantFetcher {
@override
List getEndpoints(Session session) {
final url = NetworkRouter.getBaseUrlsFromSession(
- session)[0]; // user profile is the same on all faculties
+ session,
+ )[0]; // user profile is the same on all faculties
return [url];
}
/// Returns the user's [Profile].
- static Future getProfile(Session session) async {
- final url =
- '${NetworkRouter.getBaseUrlsFromSession(session)[0]}mob_fest_geral.perfil?';
+ static Future fetchProfile(Session session) async {
+ final url = '${NetworkRouter.getBaseUrlsFromSession(session)[0]}'
+ 'mob_fest_geral.perfil?';
final response = await NetworkRouter.getWithCookies(
- url, {'pv_codigo': session.username}, session);
+ url,
+ {'pv_codigo': session.username},
+ session,
+ );
- if (response.statusCode == 200) {
- final Profile profile = Profile.fromResponse(response);
- try {
- final List> coursesResponses =
- CoursesFetcher().getCoursesListResponses(session);
- final List courses =
- parseMultipleCourses(await Future.wait(coursesResponses));
- for (Course course in courses) {
- if (profile.courses
- .map((c) => c.festId)
- .toList()
- .contains(course.festId)) {
- final Course matchingCourse =
- profile.courses.where((c) => c.festId == course.festId).first;
- matchingCourse.state ??= course.state;
- continue;
- }
- profile.courses.add(course);
+ if (response.statusCode != 200) {
+ return null;
+ }
+
+ final profile = Profile.fromResponse(response);
+ try {
+ final coursesResponses = await Future.wait(
+ CoursesFetcher().getCoursesListResponses(session),
+ );
+ final courses = parseMultipleCourses(coursesResponses);
+ for (final course in courses) {
+ if (profile.courses
+ .map((c) => c.festId)
+ .toList()
+ .contains(course.festId)) {
+ profile.courses
+ .where((c) => c.festId == course.festId)
+ .first
+ .state ??= course.state;
+ continue;
}
- } catch (e) {
- Logger().e('Failed to get user courses via scrapping: $e');
+ profile.courses.add(course);
}
- return profile;
+ } catch (e) {
+ Logger().e('Failed to get user courses via scrapping: $e');
}
- return Profile();
+ return profile;
}
}
diff --git a/uni/lib/controller/fetchers/reference_fetcher.dart b/uni/lib/controller/fetchers/reference_fetcher.dart
index f1258cc6a..3179bff82 100644
--- a/uni/lib/controller/fetchers/reference_fetcher.dart
+++ b/uni/lib/controller/fetchers/reference_fetcher.dart
@@ -6,19 +6,18 @@ import 'package:uni/model/entities/session.dart';
class ReferenceFetcher implements SessionDependantFetcher {
@override
List getEndpoints(Session session) {
- final List baseUrls =
- NetworkRouter.getBaseUrlsFromSession(session) +
- [NetworkRouter.getBaseUrl('sasup')];
- final List urls = baseUrls
+ final baseUrls = NetworkRouter.getBaseUrlsFromSession(session) +
+ [NetworkRouter.getBaseUrl('sasup')];
+ final urls = baseUrls
.map((url) => '${url}gpag_ccorrente_geral.conta_corrente_view')
.toList();
return urls;
}
Future getUserReferenceResponse(Session session) {
- final List urls = getEndpoints(session);
- final String url = urls[0];
- final Map query = {'pct_cod': session.username};
+ final urls = getEndpoints(session);
+ final url = urls[0];
+ final query = {'pct_cod': session.username};
return NetworkRouter.getWithCookies(url, query, session);
}
}
diff --git a/uni/lib/controller/fetchers/restaurant_fetcher.dart b/uni/lib/controller/fetchers/restaurant_fetcher.dart
index d089a0ce4..deb0cf0c3 100644
--- a/uni/lib/controller/fetchers/restaurant_fetcher.dart
+++ b/uni/lib/controller/fetchers/restaurant_fetcher.dart
@@ -1,9 +1,7 @@
-import 'package:http/http.dart';
-import 'package:uni/model/entities/restaurant.dart';
-import 'package:uni/model/entities/session.dart';
-
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_restaurants.dart';
+import 'package:uni/model/entities/restaurant.dart';
+import 'package:uni/model/entities/session.dart';
/// Class for fetching the menu
class RestaurantFetcher {
@@ -13,7 +11,7 @@ class RestaurantFetcher {
// Format: Date(dd/mm/yyyy), Meal("Almoço", "Jantar), Dish("Sopa", "Carne",
// "Peixe", "Dieta", "Vegetariano", "Salada"), Description(String)
- final String sheetsColumnRange = "A:D";
+ final String sheetsColumnRange = 'A:D';
// List the Restaurant sheet names in the Google Sheets Document
final List restaurantSheets = ['Cantina'];
@@ -21,22 +19,29 @@ class RestaurantFetcher {
// Generate the Gsheets endpoints list based on a list of sheets
String buildGSheetsEndpoint(String sheet) {
return Uri.encodeFull(
- "$spreadSheetUrl$jsonEndpoint&sheet=$sheet&range=$sheetsColumnRange");
+ '$spreadSheetUrl$jsonEndpoint&sheet=$sheet&range=$sheetsColumnRange',
+ );
}
String getRestaurantGSheetName(Restaurant restaurant) {
return restaurantSheets.firstWhere(
- (sheetName) =>
- restaurant.name.toLowerCase().contains(sheetName.toLowerCase()),
- orElse: () => '');
+ (sheetName) =>
+ restaurant.name.toLowerCase().contains(sheetName.toLowerCase()),
+ orElse: () => '',
+ );
}
Future fetchGSheetsRestaurant(
- String url, String restaurantName, session,
- {isDinner = false}) async {
+ String url,
+ String restaurantName,
+ Session session, {
+ bool isDinner = false,
+ }) async {
return getRestaurantFromGSheets(
- await NetworkRouter.getWithCookies(url, {}, session), restaurantName,
- isDinner: isDinner);
+ await NetworkRouter.getWithCookies(url, {}, session),
+ restaurantName,
+ isDinner: isDinner,
+ );
}
final List sigarraMenuEndpoints = [
@@ -44,13 +49,13 @@ class RestaurantFetcher {
];
Future> fetchSigarraRestaurants(Session session) async {
- final List restaurants = [];
+ final restaurants = [];
- final Iterable> responses = sigarraMenuEndpoints
+ final responses = sigarraMenuEndpoints
.map((url) => NetworkRouter.getWithCookies(url, {}, session));
await Future.wait(responses).then((value) {
- for (var response in value) {
+ for (final response in value) {
restaurants.addAll(getRestaurantsFromHtml(response));
}
});
@@ -59,26 +64,31 @@ class RestaurantFetcher {
}
Future> getRestaurants(Session session) async {
- final List restaurants = await fetchSigarraRestaurants(session);
+ final restaurants = await fetchSigarraRestaurants(session);
- // Check for restaurants without associated meals and attempt to parse them from GSheets
- final List restaurantsWithoutMeals =
+ // Check for restaurants without associated meals and attempt to parse them
+ // from GSheets
+ final restaurantsWithoutMeals =
restaurants.where((restaurant) => restaurant.meals.isEmpty).toList();
- for (var restaurant in restaurantsWithoutMeals) {
+ for (final restaurant in restaurantsWithoutMeals) {
final sheetName = getRestaurantGSheetName(restaurant);
if (sheetName.isEmpty) {
continue;
}
- final Restaurant gSheetsRestaurant = await fetchGSheetsRestaurant(
- buildGSheetsEndpoint(sheetName), restaurant.name, session,
- isDinner: restaurant.name.toLowerCase().contains('jantar'));
-
- restaurants.removeWhere(
- (restaurant) => restaurant.name == gSheetsRestaurant.name);
-
- restaurants.insert(0, gSheetsRestaurant);
+ final gSheetsRestaurant = await fetchGSheetsRestaurant(
+ buildGSheetsEndpoint(sheetName),
+ restaurant.name,
+ session,
+ isDinner: restaurant.name.toLowerCase().contains('jantar'),
+ );
+
+ restaurants
+ ..removeWhere(
+ (restaurant) => restaurant.name == gSheetsRestaurant.name,
+ )
+ ..insert(0, gSheetsRestaurant);
}
return restaurants;
diff --git a/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher.dart b/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher.dart
index 3990f3ba8..b9e6a8cce 100644
--- a/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher.dart
+++ b/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher.dart
@@ -12,12 +12,12 @@ abstract class ScheduleFetcher extends SessionDependantFetcher {
Dates getDates() {
var date = DateTime.now();
- final String beginWeek = date.year.toString().padLeft(4, '0') +
+ final beginWeek = date.year.toString().padLeft(4, '0') +
date.month.toString().padLeft(2, '0') +
date.day.toString().padLeft(2, '0');
date = date.add(const Duration(days: 6));
- final String endWeek = date.year.toString().padLeft(4, '0') +
+ final endWeek = date.year.toString().padLeft(4, '0') +
date.month.toString().padLeft(2, '0') +
date.day.toString().padLeft(2, '0');
@@ -28,9 +28,8 @@ abstract class ScheduleFetcher extends SessionDependantFetcher {
/// Stores the start and end dates of the week and the current lective year.
class Dates {
+ Dates(this.beginWeek, this.endWeek, this.lectiveYear);
final String beginWeek;
final String endWeek;
final int lectiveYear;
-
- Dates(this.beginWeek, this.endWeek, this.lectiveYear);
}
diff --git a/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_api.dart b/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_api.dart
index 71b60501f..24f8e4346 100644
--- a/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_api.dart
+++ b/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_api.dart
@@ -1,3 +1,4 @@
+import 'package:http/http.dart';
import 'package:uni/controller/fetchers/schedule_fetcher/schedule_fetcher.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_schedule.dart';
@@ -20,18 +21,19 @@ class ScheduleFetcherApi extends ScheduleFetcher {
Future> getLectures(Session session, Profile profile) async {
final dates = getDates();
final urls = getEndpoints(session);
- final responses = [];
- for (var url in urls) {
+ final responses = [];
+ for (final url in urls) {
final response = await NetworkRouter.getWithCookies(
- url,
- {
- 'pv_codigo': session.username,
- 'pv_semana_ini': dates.beginWeek,
- 'pv_semana_fim': dates.endWeek
- },
- session);
+ url,
+ {
+ 'pv_codigo': session.username,
+ 'pv_semana_ini': dates.beginWeek,
+ 'pv_semana_fim': dates.endWeek
+ },
+ session,
+ );
responses.add(response);
}
- return await parseScheduleMultipleRequests(responses);
+ return parseScheduleMultipleRequests(responses);
}
}
diff --git a/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_html.dart b/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_html.dart
index b78cdd7d5..6d9594a4b 100644
--- a/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_html.dart
+++ b/uni/lib/controller/fetchers/schedule_fetcher/schedule_fetcher_html.dart
@@ -21,25 +21,27 @@ class ScheduleFetcherHtml extends ScheduleFetcher {
Future> getLectures(Session session, Profile profile) async {
final dates = getDates();
final urls = getEndpoints(session);
- final List lectureResponses = [];
+ final lectureResponses = [];
for (final course in profile.courses) {
for (final url in urls) {
final response = await NetworkRouter.getWithCookies(
- url,
- {
- 'pv_fest_id': course.festId.toString(),
- 'pv_ano_lectivo': dates.lectiveYear.toString(),
- 'p_semana_inicio': dates.beginWeek,
- 'p_semana_fim': dates.endWeek
- },
- session);
+ url,
+ {
+ 'pv_fest_id': course.festId.toString(),
+ 'pv_ano_lectivo': dates.lectiveYear.toString(),
+ 'p_semana_inicio': dates.beginWeek,
+ 'p_semana_fim': dates.endWeek
+ },
+ session,
+ );
lectureResponses.add(response);
}
}
- final List lectures = await Future.wait(lectureResponses
- .map((response) => getScheduleFromHtml(response, session)))
- .then((schedules) => schedules.expand((schedule) => schedule).toList());
+ final lectures = await Future.wait(
+ lectureResponses
+ .map((response) => getScheduleFromHtml(response, session)),
+ ).then((schedules) => schedules.expand((schedule) => schedule).toList());
lectures.sort((l1, l2) => l1.compare(l2));
return lectures;
diff --git a/uni/lib/controller/load_static/terms_and_conditions.dart b/uni/lib/controller/load_static/terms_and_conditions.dart
index dd1cecb17..ba6945175 100644
--- a/uni/lib/controller/load_static/terms_and_conditions.dart
+++ b/uni/lib/controller/load_static/terms_and_conditions.dart
@@ -14,29 +14,31 @@ import 'package:uni/controller/local_storage/app_shared_preferences.dart';
Future fetchTermsAndConditions() async {
if (await Connectivity().checkConnectivity() != ConnectivityResult.none) {
try {
- const String url = 'https://raw.githubusercontent.com/NIAEFEUP/'
- 'uni/develop/uni/assets/text/TermsAndConditions.md';
- final http.Response response = await http.get(Uri.parse(url));
+ const url =
+ 'https://raw.githubusercontent.com/NIAEFEUP/project-schrodinger/develop/uni/assets/text/TermsAndConditions.md';
+ final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
return response.body;
}
} catch (e) {
- Logger().e('Failed to fetch Terms and Conditions: ${e.toString()}');
+ Logger().e('Failed to fetch Terms and Conditions: $e');
}
}
try {
return await rootBundle.loadString('assets/text/TermsAndConditions.md');
} catch (e) {
- Logger().e('Failed to read Terms and Conditions: ${e.toString()}');
+ Logger().e('Failed to read Terms and Conditions: $e');
return 'Não foi possível carregar os Termos e Condições. '
'Por favor tente mais tarde.';
}
}
/// Checks if the current Terms and Conditions have been accepted by the user,
-/// by fetching the current terms, hashing them and comparing with the stored hash.
-/// Sets the acceptance to false if the terms have changed, or true if they haven't.
+/// by fetching the current terms, hashing them and comparing
+/// with the stored hash.
+/// Sets the acceptance to false if the terms have changed,
+/// or true if they haven't.
/// Returns the updated value.
Future updateTermsAndConditionsAcceptancePreference() async {
final hash = await AppSharedPreferences.getTermsAndConditionHash();
@@ -44,18 +46,22 @@ Future updateTermsAndConditionsAcceptancePreference() async {
final currentHash = md5.convert(utf8.encode(termsAndConditions)).toString();
if (hash == null) {
- await AppSharedPreferences.setTermsAndConditionsAcceptance(true);
+ await AppSharedPreferences.setTermsAndConditionsAcceptance(
+ areAccepted: true,
+ );
await AppSharedPreferences.setTermsAndConditionHash(currentHash);
return true;
}
if (currentHash != hash) {
- await AppSharedPreferences.setTermsAndConditionsAcceptance(false);
+ await AppSharedPreferences.setTermsAndConditionsAcceptance(
+ areAccepted: false,
+ );
await AppSharedPreferences.setTermsAndConditionHash(currentHash);
return false;
}
- await AppSharedPreferences.setTermsAndConditionsAcceptance(true);
+ await AppSharedPreferences.setTermsAndConditionsAcceptance(areAccepted: true);
return true;
}
@@ -64,5 +70,5 @@ Future acceptTermsAndConditions() async {
final termsAndConditions = await fetchTermsAndConditions();
final currentHash = md5.convert(utf8.encode(termsAndConditions)).toString();
await AppSharedPreferences.setTermsAndConditionHash(currentHash);
- await AppSharedPreferences.setTermsAndConditionsAcceptance(true);
+ await AppSharedPreferences.setTermsAndConditionsAcceptance(areAccepted: true);
}
diff --git a/uni/lib/controller/local_storage/app_bus_stop_database.dart b/uni/lib/controller/local_storage/app_bus_stop_database.dart
index e13fdbe92..a62476004 100644
--- a/uni/lib/controller/local_storage/app_bus_stop_database.dart
+++ b/uni/lib/controller/local_storage/app_bus_stop_database.dart
@@ -24,7 +24,7 @@ class AppBusStopDatabase extends AppDatabase {
/// * a value in this map is the corresponding [BusStopData] instance.
Future