Skip to content

Commit

Permalink
Bump packages, bump courses db version, further remove try/catch, fix…
Browse files Browse the repository at this point in the history
… forced logout
  • Loading branch information
bdmendes committed Oct 2, 2023
1 parent 1c8ed10 commit a3f3b4c
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ Future<void> workerStartCallback() async {
//try to keep the usage of this function BELOW +-30 seconds
//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);
} catch (err, stackTrace) {
Logger().e(
'Error while running $taskName job:',
error: err,
stackTrace: stackTrace,
);
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:logger/logger.dart';
import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/controller/parsers/parser_course_units.dart';
import 'package:uni/model/entities/course.dart';
Expand All @@ -14,17 +13,12 @@ class AllCourseUnitsFetcher {
final allCourseUnits = <CourseUnit>[];

for (final course in courses) {
try {
final courseUnits = await _getAllCourseUnitsAndCourseAveragesFromCourse(
course,
session,
currentCourseUnits: currentCourseUnits,
);
allCourseUnits.addAll(courseUnits.where((c) => c.enrollmentIsValid()));
} catch (e) {
Logger().e('Failed to fetch course units for ${course.name}', e);
return null;
}
final courseUnits = await _getAllCourseUnitsAndCourseAveragesFromCourse(
course,
session,
currentCourseUnits: currentCourseUnits,
);
allCourseUnits.addAll(courseUnits.where((c) => c.enrollmentIsValid()));
}

return allCourseUnits;
Expand Down
35 changes: 15 additions & 20 deletions uni/lib/controller/fetchers/profile_fetcher.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
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';
Expand Down Expand Up @@ -30,27 +29,23 @@ class ProfileFetcher implements SessionDependantFetcher {
}

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;
}
profile.courses.add(course);
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;
}
}
24 changes: 6 additions & 18 deletions uni/lib/controller/load_static/terms_and_conditions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:http/http.dart' as http;
import 'package:logger/logger.dart';
import 'package:uni/controller/local_storage/app_shared_preferences.dart';

/// Returns the content of the Terms and Conditions remote file,
Expand All @@ -13,25 +12,14 @@ import 'package:uni/controller/local_storage/app_shared_preferences.dart';
/// If this operation is unsuccessful, an error message is returned.
Future<String> fetchTermsAndConditions() async {
if (await Connectivity().checkConnectivity() != ConnectivityResult.none) {
try {
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');
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;
}
}

try {
return await rootBundle.loadString('assets/text/TermsAndConditions.md');
} catch (e) {
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.';
}
return rootBundle.loadString('assets/text/TermsAndConditions.md');
}

/// Checks if the current Terms and Conditions have been accepted by the user,
Expand Down
2 changes: 1 addition & 1 deletion uni/lib/controller/local_storage/app_courses_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:uni/model/entities/course.dart';
/// See the [Course] class to see what data is stored in this database.
class AppCoursesDatabase extends AppDatabase {
AppCoursesDatabase()
: super('courses.db', [createScript], onUpgrade: migrate, version: 2);
: super('courses.db', [createScript], onUpgrade: migrate, version: 3);
static const String createScript =
'''CREATE TABLE courses(id INTEGER, fest_id INTEGER, name TEXT, '''
'''abbreviation TEXT, currYear TEXT, firstEnrollment INTEGER, state TEXT, '''
Expand Down
28 changes: 17 additions & 11 deletions uni/lib/controller/local_storage/app_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ class AppDatabase {
/// A list of commands to be executed on database creation.
List<String> commands;

// A lock that synchronizes all database insertions.
/// The lock timeout for database operations.
static const Duration lockTimeout = Duration(seconds: 10);

/// A lock that synchronizes all database insertions.
static Lock lock = Lock();

/// A function that is called when the [version] changes.
Expand All @@ -42,16 +45,19 @@ class AppDatabase {
String? nullColumnHack,
ConflictAlgorithm? conflictAlgorithm,
}) async {
await lock.synchronized(() async {
final db = await getDatabase();

await db.insert(
table,
values,
nullColumnHack: nullColumnHack,
conflictAlgorithm: conflictAlgorithm,
);
});
await lock.synchronized(
() async {
final db = await getDatabase();

await db.insert(
table,
values,
nullColumnHack: nullColumnHack,
conflictAlgorithm: conflictAlgorithm,
);
},
timeout: lockTimeout,
);
}

/// Initializes this database.
Expand Down
2 changes: 1 addition & 1 deletion uni/lib/controller/local_storage/app_exams_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:uni/model/entities/exam.dart';
/// See the [Exam] class to see what data is stored in this database.
class AppExamsDatabase extends AppDatabase {
AppExamsDatabase()
: super('exams.db', [_createScript], onUpgrade: migrate, version: 4);
: super('exams.db', [_createScript], onUpgrade: migrate, version: 5);
Map<String, String> months = {
'Janeiro': '01',
'Fevereiro': '02',
Expand Down
73 changes: 39 additions & 34 deletions uni/lib/controller/networking/network_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,44 +44,47 @@ class NetworkRouter {
List<String> faculties, {
required bool persistentSession,
}) async {
return _loginLock.synchronized(() async {
if (_lastLoginTime != null &&
DateTime.now().difference(_lastLoginTime!) <
const Duration(minutes: 1) &&
_cachedSession != null) {
Logger().d('Login request ignored due to recent login');
return _cachedSession;
}
return _loginLock.synchronized(
() async {
if (_lastLoginTime != null &&
DateTime.now().difference(_lastLoginTime!) <
const Duration(minutes: 1) &&
_cachedSession != null) {
Logger().d('Login request ignored due to recent login');
return _cachedSession;
}

final url =
'${NetworkRouter.getBaseUrls(faculties)[0]}mob_val_geral.autentica';
final response = await http.post(
url.toUri(),
body: {'pv_login': username, 'pv_password': password},
).timeout(_requestTimeout);
final url =
'${NetworkRouter.getBaseUrls(faculties)[0]}mob_val_geral.autentica';
final response = await http.post(
url.toUri(),
body: {'pv_login': username, 'pv_password': password},
).timeout(_requestTimeout);

if (response.statusCode != 200) {
Logger().e('Login failed with status code ${response.statusCode}');
return null;
}
if (response.statusCode != 200) {
Logger().e('Login failed with status code ${response.statusCode}');
return null;
}

final session = Session.fromLogin(
response,
faculties,
persistentSession: persistentSession,
);
final session = Session.fromLogin(
response,
faculties,
persistentSession: persistentSession,
);

if (session == null) {
Logger().e('Login failed: user not authenticated');
return null;
}
if (session == null) {
Logger().e('Login failed: user not authenticated');
return null;
}

Logger().i('Login successful');
_lastLoginTime = DateTime.now();
_cachedSession = session;
Logger().i('Login successful');
_lastLoginTime = DateTime.now();
_cachedSession = session;

return session;
});
return session;
},
timeout: _requestTimeout,
);
}

/// Re-authenticates the user via the Sigarra API
Expand Down Expand Up @@ -182,8 +185,10 @@ class NetworkRouter {
final newSession = await reLoginFromSession(session);

if (newSession == null) {
NavigationService.logoutAndPopHistory(null);
return Future.error('Login failed');
NavigationService.logoutAndPopHistory();
return Future.error(
'Re-login failed; user might have changed password',
);
}

session
Expand Down
2 changes: 1 addition & 1 deletion uni/lib/controller/parsers/parser_course_units.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ List<CourseUnit> parseCourseUnitsAndCourseAverage(
codeName, // FIXME: this is not the abbreviation
status: status,
grade: grade,
ects: double.parse(ects),
ects: double.tryParse(ects),
name: name,
curricularYear: int.parse(year),
semesterCode: semester,
Expand Down
25 changes: 16 additions & 9 deletions uni/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ Future<void> main() async {
await dotenv
.load(fileName: 'assets/env/.env', isOptional: true)
.onError((error, stackTrace) {
Logger().e('Error loading .env file: $error', error, stackTrace);
Sentry.captureException(error, stackTrace: stackTrace);
Logger().e(
'Error loading .env file: $error',
error: error,
stackTrace: stackTrace,
);
});

final savedTheme = await AppSharedPreferences.getThemeMode();
Expand Down Expand Up @@ -148,28 +153,29 @@ Future<void> main() async {
create: (_) => ThemeNotifier(savedTheme),
),
],
child: MyApp(route),
child: Application(route),
),
);
},
);
}

/// Manages the state of the app
///
/// Manages the state of the app.
/// This class is necessary to track the app's state for
/// the current execution
class MyApp extends StatefulWidget {
const MyApp(this.initialRoute, {super.key});
/// the current execution.
class Application extends StatefulWidget {
const Application(this.initialRoute, {super.key});

final String initialRoute;

static GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

@override
State<MyApp> createState() => MyAppState();
State<Application> createState() => ApplicationState();
}

/// Manages the app depending on its current state
class MyAppState extends State<MyApp> {
class ApplicationState extends State<Application> {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
Expand All @@ -178,6 +184,7 @@ class MyAppState extends State<MyApp> {
return Consumer2<ThemeNotifier, LocaleNotifier>(
builder: (context, themeNotifier, localeNotifier, _) => MaterialApp(
title: 'uni',
navigatorKey: Application.navigatorKey,
theme: applicationLightTheme,
darkTheme: applicationDarkTheme,
themeMode: themeNotifier.getTheme(),
Expand Down
4 changes: 2 additions & 2 deletions uni/lib/model/entities/course.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class Course {

/// Creates a new instance from a JSON object.
Course.fromJson(Map<String, dynamic> data)
: id = data['cur_id'] as int,
festId = data['fest_id'] as int,
: id = (data['cur_id'] ?? 0) as int,
festId = (data['fest_id'] ?? 0) as int,
name = data['cur_nome'] as String?,
currYear = data['ano_curricular'] as String?,
firstEnrollment = data['fest_a_lect_1_insc'] as int,
Expand Down
6 changes: 0 additions & 6 deletions uni/lib/model/entities/exam.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';
import 'package:uni/model/entities/app_locale.dart';

/// Manages a generic Exam.
Expand Down Expand Up @@ -87,11 +86,6 @@ class Exam {
return '''$id - $subject - ${begin.year} - $month - ${begin.day} - $beginTime-$endTime - $type - $rooms - $weekDay''';
}

/// Prints the data in this exam to the [Logger] with an INFO level.
void printExam() {
Logger().i(toString());
}

@override
bool operator ==(Object other) =>
identical(this, other) || other is Exam && id == other.id;
Expand Down
Loading

0 comments on commit a3f3b4c

Please sign in to comment.