Skip to content

Commit

Permalink
Merge branch 'develop' into enhancement/academic-path-api
Browse files Browse the repository at this point in the history
  • Loading branch information
DGoiana authored Jul 13, 2024
2 parents b0a8403 + a8d82b5 commit aed0bfc
Show file tree
Hide file tree
Showing 30 changed files with 1,056 additions and 386 deletions.
11 changes: 7 additions & 4 deletions uni/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ dart run build_runner watch

## Translation files

Intl package allows the internationalization of the app, currently supporting Portuguese ('pt_PT') and English ('en_EN). This package creates `.arb` files (one for each language), mapping a key to the correspondent translated string.
In order to access those translations through getters, you must add the translations you want to the `.arb` files and run:
Intl package allows the internationalization of the app, currently supporting Portuguese ('pt_PT') and English ('en_EN'), by generating `.dart` files (one for each language), mapping a key to the correspondent translated string as you can see at ```generated/intl``` files.
To generate these files, you must add the translations you want in the `.arb` files of the ```I10n``` folder and run:
```
dart pub global activate intl_utils 2.1.0
```
```
dart pub global run intl_utils:generate
```
This will generate `.dart` files with the getters you need to access the translations.
You must include `'package:uni/generated/l10n.dart'` and, depending on the locale of the application, `S.of(context).{key_of_translation}` will get you the translated string.

To use the translation import `'package:uni/generated/l10n.dart'` and use `S.of(context).{key_of_translation}`.

## Project structure

Expand Down
14 changes: 12 additions & 2 deletions uni/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
<application
android:label="uni"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:launchMode="singleInstance"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
Expand All @@ -24,6 +25,15 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="pt.up.fe.ni.uni"
android:host="auth" />
</intent-filter>

</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
Expand Down
2 changes: 1 addition & 1 deletion uni/app_version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.9.0-beta.19+282
1.9.0-beta.20+283
4 changes: 4 additions & 0 deletions uni/assets/env/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Plausbile
PLAUSIBLE_URL=https://plausible.example.com
PLAUSIBLE_DOMAIN=your.plausible.domain

# AAI - Federated Authentication
REALM=https://open-id.up.pt/realms/sigarra
CLIENT_ID=mobile-app-uni
18 changes: 18 additions & 0 deletions uni/assets/images/AAI.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions uni/ios/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ Runner/GeneratedPluginRegistrant.*
!default.mode2v3
!default.pbxuser
!default.perspectivev3

Podfile.lock
113 changes: 113 additions & 0 deletions uni/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
PODS:
- add_2_calendar (0.0.1):
- Flutter
- app_links (0.0.1):
- Flutter
- battery_plus (1.0.0):
- Flutter
- connectivity_plus (0.0.1):
- Flutter
- ReachabilitySwift
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
- open_file_plus (1.0.0):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- ReachabilitySwift (5.0.0)
- Sentry/HybridSDK (8.20.0):
- SentryPrivate (= 8.20.0)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- Sentry/HybridSDK (= 8.20.0)
- SentryPrivate (8.20.0)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
- url_launcher_ios (0.0.1):
- Flutter
- workmanager (0.0.1):
- Flutter

DEPENDENCIES:
- add_2_calendar (from `.symlinks/plugins/add_2_calendar/ios`)
- app_links (from `.symlinks/plugins/app_links/ios`)
- battery_plus (from `.symlinks/plugins/battery_plus/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- open_file_plus (from `.symlinks/plugins/open_file_plus/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- workmanager (from `.symlinks/plugins/workmanager/ios`)

SPEC REPOS:
trunk:
- ReachabilitySwift
- Sentry
- SentryPrivate

EXTERNAL SOURCES:
add_2_calendar:
:path: ".symlinks/plugins/add_2_calendar/ios"
app_links:
:path: ".symlinks/plugins/app_links/ios"
battery_plus:
:path: ".symlinks/plugins/battery_plus/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
Flutter:
:path: Flutter
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
open_file_plus:
:path: ".symlinks/plugins/open_file_plus/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
sentry_flutter:
:path: ".symlinks/plugins/sentry_flutter/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
workmanager:
:path: ".symlinks/plugins/workmanager/ios"

SPEC CHECKSUMS:
add_2_calendar: 5eee66d5a3b99cd5e1487a7e03abd4e3ac4aff11
app_links: e70ca16b4b0f88253b3b3660200d4a10b4ea9795
battery_plus: 3b68b6e7710fe49c022999753d22760e6dbbc471
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
open_file_plus: 05737718530c14cf02868e3b7754d7fe4df76d8b
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
Sentry: a8d7b373b9f9868442b02a0c425192f693103cbf
sentry_flutter: 03e7660857a8cdb236e71456a7e8447b65c8a788
SentryPrivate: 006b24af16828441f70e2ab6adf241bd0a8ad130
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6

PODFILE CHECKSUM: b8542614aec8767bc1398a33de5c54e3592a72c6

COCOAPODS: 1.14.3
2 changes: 1 addition & 1 deletion uni/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "";
TargetAttributes = {
378A17102ACF02E100B89C1C = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
11 changes: 11 additions & 0 deletions uni/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UIKit
import Flutter
import workmanager
import flutter_local_notifications
import app_links

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
Expand All @@ -10,6 +11,8 @@ import flutter_local_notifications
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)

// Notifications
WorkmanagerPlugin.registerTask(withIdentifier:"pt.up.fe.ni.uni.notificationworker")
UIApplication.shared.setMinimumBackgroundFetchInterval(TimeInterval(60*15))
//in case we have a notification with actions
Expand All @@ -20,6 +23,14 @@ import flutter_local_notifications
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

// Custom url schemes & retrieve the link from parameters
if let url = AppLinks.shared.getLink(launchOptions: launchOptions) {
// We have a link, propagate it to your Flutter app
AppLinks.shared.handleLink(url: url)
return true // Returning true will stop the propagation to other packages
}

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
13 changes: 13 additions & 0 deletions uni/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>pt.up.fe.ni.uni</string>
<key>CFBundleURLSchemes</key>
<array>
<string>pt.up.fe.ni.uni</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationQueriesSchemes</key>
Expand Down
35 changes: 28 additions & 7 deletions uni/lib/controller/background_workers/notifications.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,38 @@ class NotificationManager {
PreferencesController.prefs = await SharedPreferences.getInstance();
final userInfo = await PreferencesController.getPersistentUserInfo();
final faculties = PreferencesController.getUserFaculties();
final refreshToken = await PreferencesController.getSessionRefreshToken();

if (userInfo == null || faculties.isEmpty) {
if (faculties.isEmpty) {
return;
}
if (userInfo == null && refreshToken == null) {
return; // Session not persistent
}

final session = await NetworkRouter.login(
userInfo.item1,
userInfo.item2,
faculties,
persistentSession: false,
);
Session? session;
if (userInfo != null) {
session = await NetworkRouter.login(
userInfo.item1,
userInfo.item2,
faculties,
persistentSession: false,
);
}

if (refreshToken != null) {
final token = await NetworkRouter.getAccessToken(refreshToken);
final studentNumber = await PreferencesController.getUserNumber();
if (token == null || studentNumber == null) {
return;
}
session = await NetworkRouter.loginWithToken(
token,
studentNumber,
faculties,
persistentSession: false,
);
}

if (session == null) {
return;
Expand Down
2 changes: 2 additions & 0 deletions uni/lib/controller/cleanup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Future<void> cleanupStoredData(BuildContext context) async {
AppBusStopDatabase().deleteBusStops(),
AppCourseUnitsDatabase().deleteCourseUnits(),
NetworkRouter.killSigarraAuthentication(faculties),
PreferencesController.removePersistentUserInfo(),
PreferencesController.removeSessionRefreshToken(),
]);

final toCleanDirectory = await getApplicationDocumentsDirectory();
Expand Down
32 changes: 30 additions & 2 deletions uni/lib/controller/local_storage/preferences_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class PreferencesController {
static const String _userNumber = 'user_number';
static const String _userPw = 'user_password';
static const String _userFaculties = 'user_faculties';
static const String _refreshToken = 'refresh_token';
static const String _termsAndConditions = 'terms_and_conditions';
static const String _areTermsAndConditionsAcceptedKey = 'is_t&c_accepted';
static const String _tuitionNotificationsToggleKey =
Expand Down Expand Up @@ -81,6 +82,20 @@ class PreferencesController {
); // Could be multiple faculties;
}

/// Saves the user's session refresh token, student number and faculties.
static Future<void> saveSessionRefreshToken(
String refreshToken,
String userNumber,
List<String> faculties,
) async {
await _secureStorage.write(key: _userNumber, value: userNumber);
await _secureStorage.write(key: _refreshToken, value: refreshToken);
await prefs.setStringList(
_userFaculties,
faculties,
);
}

/// Sets whether or not the Terms and Conditions have been accepted.
static Future<void> setTermsAndConditionsAcceptance({
required bool areAccepted,
Expand Down Expand Up @@ -157,8 +172,16 @@ class PreferencesController {

/// Deletes the user's student number and password.
static Future<void> removePersistentUserInfo() async {
await prefs.remove(_userNumber);
await prefs.remove(_userPw);
await _secureStorage.delete(key: _userNumber);
await _secureStorage.delete(key: _userPw);
await prefs.remove(_userFaculties);
}

/// Deletes the user's session refresh token.
static Future<void> removeSessionRefreshToken() async {
await _secureStorage.delete(key: _userNumber);
await _secureStorage.delete(key: _refreshToken);
await prefs.remove(_userFaculties);
}

/// Returns a tuple containing the user's student number and password.
Expand All @@ -177,6 +200,11 @@ class PreferencesController {
return Tuple2(userNum, userPass);
}

/// Returns the user's session refresh token.
static Future<String?> getSessionRefreshToken() {
return _secureStorage.read(key: _refreshToken);
}

/// Returns the user's faculties
static List<String> getUserFaculties() {
final storedFaculties = prefs.getStringList(_userFaculties);
Expand Down
Loading

0 comments on commit aed0bfc

Please sign in to comment.