diff --git a/.env.example b/.env.example
index 982c4bd..21d2e5c 100644
--- a/.env.example
+++ b/.env.example
@@ -1,3 +1,6 @@
-COURSES_URL=
-GRADS_URL=
-GRADE_OPTIMIZER_URL=
+API_COURSES=
+API_SUBJECTS=
+API_GENETIC_ALGORITHM=
+API_SUPPORT_URL=
+API_FINAL_SCORE_URL=
+API_NOTIFICATIONS=
diff --git a/.github/workflows/build_IOS.yml b/.github/workflows/build_IOS.yml
index bbdbf77..72f6d31 100644
--- a/.github/workflows/build_IOS.yml
+++ b/.github/workflows/build_IOS.yml
@@ -28,7 +28,6 @@
# run: |
# echo "GRADS_URL=${{ vars.API_COURSES }}" >> .env # The courses API
# echo "COURSES_URL=${{ vars.API_SUBJECTS }}" >> .env # The subjects API
- # echo "GRADE_OPTIMIZER_URL=${{ vars.API_GRADE_OPTMIZER }}" >> .env # The grade optimizer API
# - name: Setup Fastlane
# uses: ruby/setup-ruby@v1
diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml
index 732a13a..7dc359c 100644
--- a/.github/workflows/build_android.yml
+++ b/.github/workflows/build_android.yml
@@ -6,20 +6,16 @@ on:
- homolog
- prod
- workflow_call:
-
jobs:
build_android:
environment: ${{ github.ref_name }}
runs-on: ubuntu-latest
permissions:
id-token: write
- contents: write
+ contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- with:
- repository: ${{ inputs.repository }}
- name: Get Version
run: |
@@ -29,27 +25,38 @@ jobs:
echo "app_build_name=$app_build_name" >> $GITHUB_ENV
- name: Setup Java Version
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v4
with:
- java-version: "12.x"
+ java-version: "17"
+ distribution: 'temurin'
- name: Setup Flutter Version
- uses: subosito/flutter-action@v1
+ uses: subosito/flutter-action@v2
with:
flutter-version: "3.24.3"
- name: Get flutter dependencies
run: flutter pub get
- - name: Setup Fastlane
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: "2.6"
- bundler-cache: true
- working-directory: android
-
- - name: Set envs
+ - name: Set AWS Account ID
run: |
+ if [[ "${{ github.ref_name }}" == "dev" ]]; then
+ echo "AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID_DEV }}" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "homolog" ]]; then
+ echo "AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID_HOML }}" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "prod" ]]; then
+ echo "AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID_PROD }}" >> $GITHUB_ENV
+ else
+ echo "Invalid branch name!" && exit 1
+ fi
+ echo "STACK_NAME=DevMediasStack${{github.ref_name}}" >> $GITHUB_ENV
+
+ - name: Setup AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ aws-region: ${{ vars.AWS_REGION }}
+ role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/GithubActionsRole
+ role-session-name: github-action
- name: Configure Keystore
run: |
@@ -65,33 +72,51 @@ jobs:
ANDROID_KEYSTORE_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_STORE_PASSWORD }}
working-directory: android
+ # Busca o endpoint do APIGW no SSM (configurado no back).
+ - name: Fetch config from SSM
+ run: |
+ STAGE=$(echo "${{ github.ref_name }}" | tr '[:upper:]' '[:lower:]')
+
+ API_BASE=$(aws ssm get-parameter \
+ --name "/devmedias/$STAGE/api/url" \
+ --query "Parameter.Value" --output text)
+
+ API_BASE="${API_BASE%/}/"
+ echo "API_BASE=$API_BASE" >> $GITHUB_ENV
+
- name: Create .env file
run: |
- echo "API_COURSES=${{vars.API_COURSES}}" >> .env # The courses API
- echo "API_SUBJECTS=${{vars.API_SUBJECTS}}" >> .env # The subjects API
- echo "API_GRADE_OPTMIZER=${{vars.API_GRADE_OPTMIZER}}" >> .env # The grade optimizer API
- echo "API_SUPPORT_URL=${{vars.API_SUPPORT_URL}}" >> .env # The support API
- echo "API_FINAL_SCORE_URL=${{vars.API_FINAL_SCORE_URL}}" >> .env # The final score API
+ {
+ echo "API_COURSES=${API_BASE}get-all-cursos"
+ echo "API_SUBJECTS=${API_BASE}get-all-disciplinas"
+ echo "API_GENETIC_ALGORITHM=${API_BASE}genetic-algorithm"
+ echo "API_SUPPORT_URL=${API_BASE}public/contact-us"
+ echo "API_FINAL_SCORE_URL=${API_BASE}calculate-mean"
+ echo "API_NOTIFICATIONS="
+ } >> .env
- name: Build Android
run: |
- flutter build appbundle --release --build-name=$app_build_name --build-number=$app_build_number
+ flutter build appbundle --release \
+ --build-name=$app_build_name \
+ --build-number=$app_build_number
- name: Upload to artifacts
uses: actions/upload-artifact@v4
with:
name: app-release.aab
path: build/app/outputs/bundle/release/
+ retention-days: 1
deploy_to_play_store:
needs: build_android
environment: ${{ github.ref_name }}
runs-on: ubuntu-latest
+ permissions:
+ contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- with:
- repository: ${{ inputs.repository }}
- name: Download artifact
uses: actions/download-artifact@v4
@@ -102,12 +127,12 @@ jobs:
- name: Setup Fastlane
uses: ruby/setup-ruby@v1
with:
- ruby-version: "2.6"
+ ruby-version: "3.2"
bundler-cache: true
working-directory: android
- name: Exec fastlane
- run: bundle exec fastlane ${{github.ref_name}}
+ run: bundle exec fastlane ${{ github.ref_name }}
env:
PLAY_STORE_CONFIG_JSON: ${{ secrets.PLAY_STORE_CONFIG_JSON }}
working-directory: android
diff --git a/.gitignore b/.gitignore
index d40954c..9be5be1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,9 @@
# Miscellaneous
*.class
*.log
+# Lock files (do not ignore Dart/Flutter lockfile — commit pubspec.lock)
*.lock
+!pubspec.lock
*.pyc
*.swp
.DS_Store
@@ -35,6 +37,11 @@ migrate_working_dir/
.pub/
/build/
+# Platform build outputs (Gradle, CMake, etc.)
+/android/build/
+/android/app/build/
+/ios/build/
+
# Symbolication related
app.*.symbols
diff --git a/android/.gitignore b/android/.gitignore
index 6f56801..e67dffd 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -1,5 +1,7 @@
gradle-wrapper.jar
/.gradle
+/build/
+app/build/
/captures/
/gradlew
/gradlew.bat
diff --git a/android/Gemfile.lock b/android/Gemfile.lock
index 29f7dcf..da7f77e 100644
--- a/android/Gemfile.lock
+++ b/android/Gemfile.lock
@@ -215,4 +215,4 @@ DEPENDENCIES
fastlane
BUNDLED WITH
- 1.17.2
\ No newline at end of file
+ 1.17.2
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 8f4efc8..d53381e 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -43,12 +43,12 @@ android {
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = '1.8'
+ jvmTarget = '17'
}
sourceSets {
@@ -57,7 +57,7 @@ android {
defaultConfig {
applicationId "com.dev_medias_front_rn_v2"
- minSdkVersion 21
+ minSdkVersion flutter.minSdkVersion
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
diff --git a/android/app/src/main/kotlin/com/example/dev_medias_front_flutter/MainActivity.kt b/android/app/src/main/kotlin/com/dev_medias_front_rn_v2/MainActivity.kt
similarity index 100%
rename from android/app/src/main/kotlin/com/example/dev_medias_front_flutter/MainActivity.kt
rename to android/app/src/main/kotlin/com/dev_medias_front_rn_v2/MainActivity.kt
diff --git a/android/build.gradle b/android/build.gradle
index bc157bd..690d416 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -5,14 +5,15 @@ allprojects {
}
}
-rootProject.buildDir = '../build'
+rootProject.layout.buildDirectory.value(rootProject.layout.buildDirectory.dir("../../build").get())
+
subprojects {
- project.buildDir = "${rootProject.buildDir}/${project.name}"
+ project.layout.buildDirectory.value(rootProject.layout.buildDirectory.dir(project.name).get())
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
- delete rootProject.buildDir
+ delete rootProject.layout.buildDirectory
}
diff --git a/android/fastlane/Appfile b/android/fastlane/Appfile
index 3ee7e12..a507123 100644
--- a/android/fastlane/Appfile
+++ b/android/fastlane/Appfile
@@ -1 +1 @@
-package_name("com.dev_medias_front_rn")
\ No newline at end of file
+package_name("com.dev_medias_front_rn_v2")
\ No newline at end of file
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index e1ca574..afa1e8e 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
index 1d6d19b..bd247b0 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -19,8 +19,8 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
- id "com.android.application" version "7.3.0" apply false
- id "org.jetbrains.kotlin.android" version "1.7.10" apply false
+ id "com.android.application" version "8.7.0" apply false
+ id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}
include ":app"
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 310f180..3d62243 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 12.0
+ 13.0
diff --git a/ios/Podfile b/ios/Podfile
index d97f17e..e51a31d 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '12.0'
+# platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 2d4708e..5702378 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -21,10 +21,10 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
SPEC CHECKSUMS:
- Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
- path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
- shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
+ Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
+ path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
+ shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
-PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
+PODFILE CHECKSUM: 4f1c12611da7338d21589c0b2ecd6bd20b109694
COCOAPODS: 1.16.2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 3703d84..08dcd71 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -454,7 +454,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -585,7 +585,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -636,7 +636,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 8e3ca5d..e3773d4 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
diff --git a/lib/app/controller/add_page_controller.dart b/lib/app/controller/add_page_controller.dart
index 22eeec4..d0d6386 100644
--- a/lib/app/controller/add_page_controller.dart
+++ b/lib/app/controller/add_page_controller.dart
@@ -20,7 +20,8 @@ abstract class AddPageControllerBase with Store {
@action
Future loadCourses() async {
setCoursesLoaded(false);
- final result = await coursesController.fetchCourses();
+ await coursesController.refreshAllSubjects();
+ final result = Map.from(coursesController.allCourses!);
result.removeWhere(
(key, value) => userController.currentCourses.contains(value.code));
availableCourses = ObservableMap.of(result);
diff --git a/lib/app/controller/common/courses_controller.dart b/lib/app/controller/common/courses_controller.dart
index 17a85f9..f58f8d2 100644
--- a/lib/app/controller/common/courses_controller.dart
+++ b/lib/app/controller/common/courses_controller.dart
@@ -57,7 +57,21 @@ abstract class CoursesControllerBase with Store {
setLoadedCourses(true);
return response;
} catch (e) {
- throw Exception('Erro de rede: $e');
+ setLoadedCourses(allCourses != null && allCourses!.isNotEmpty);
+ rethrow;
+ }
+ }
+
+ /// GET de todas as disciplinas + atualização do catálogo e lista da home.
+ @action
+ Future refreshAllSubjects() async {
+ try {
+ final courses = await fetchCourses();
+ setAllCourses(courses);
+ await userController.pruneCurrentCoursesWithCatalog();
+ return true;
+ } catch (_) {
+ return false;
}
}
}
diff --git a/lib/app/controller/common/courses_controller.g.dart b/lib/app/controller/common/courses_controller.g.dart
index a060a7e..23e4750 100644
--- a/lib/app/controller/common/courses_controller.g.dart
+++ b/lib/app/controller/common/courses_controller.g.dart
@@ -64,6 +64,15 @@ mixin _$CoursesController on CoursesControllerBase, Store {
return _$fetchCoursesAsyncAction.run(() => super.fetchCourses());
}
+ late final _$refreshAllSubjectsAsyncAction =
+ AsyncAction('CoursesControllerBase.refreshAllSubjects', context: context);
+
+ @override
+ Future refreshAllSubjects() {
+ return _$refreshAllSubjectsAsyncAction
+ .run(() => super.refreshAllSubjects());
+ }
+
late final _$CoursesControllerBaseActionController =
ActionController(name: 'CoursesControllerBase', context: context);
@@ -89,6 +98,17 @@ mixin _$CoursesController on CoursesControllerBase, Store {
}
}
+ @override
+ void deleteAllCurrentCourses() {
+ final _$actionInfo = _$CoursesControllerBaseActionController.startAction(
+ name: 'CoursesControllerBase.deleteAllCurrentCourses');
+ try {
+ return super.deleteAllCurrentCourses();
+ } finally {
+ _$CoursesControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
@override
String toString() {
return '''
diff --git a/lib/app/controller/common/notifications_controller.dart b/lib/app/controller/common/notifications_controller.dart
new file mode 100644
index 0000000..3dc27fd
--- /dev/null
+++ b/lib/app/controller/common/notifications_controller.dart
@@ -0,0 +1,26 @@
+import 'package:dev_medias_front_flutter/app/model/notice.dart';
+import 'package:dev_medias_front_flutter/app/service/notification_service.dart';
+import 'package:mobx/mobx.dart';
+
+part 'notifications_controller.g.dart';
+
+class NotificationsController = NotificationsControllerBase
+ with _$NotificationsController;
+
+abstract class NotificationsControllerBase with Store {
+ NotificationsControllerBase();
+
+ final NotificationService _service = NotificationService();
+
+ @observable
+ ObservableList notices = ObservableList();
+
+ @action
+ Future fetchNotifications() async {
+ final list = await _service.getNotifications();
+ notices = ObservableList.of(list);
+ }
+}
+
+final NotificationsController notificationsController =
+ NotificationsController();
diff --git a/lib/app/controller/common/notifications_controller.g.dart b/lib/app/controller/common/notifications_controller.g.dart
new file mode 100644
index 0000000..bf434e9
--- /dev/null
+++ b/lib/app/controller/common/notifications_controller.g.dart
@@ -0,0 +1,44 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'notifications_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers
+
+mixin _$NotificationsController on NotificationsControllerBase, Store {
+ late final _$noticesAtom =
+ Atom(name: 'NotificationsControllerBase.notices', context: context);
+
+ @override
+ ObservableList get notices {
+ _$noticesAtom.reportRead();
+ return super.notices;
+ }
+
+ @override
+ set notices(ObservableList value) {
+ _$noticesAtom.reportWrite(value, super.notices, () {
+ super.notices = value;
+ });
+ }
+
+ late final _$fetchNotificationsAsyncAction = AsyncAction(
+ 'NotificationsControllerBase.fetchNotifications',
+ context: context);
+
+ @override
+ Future fetchNotifications() {
+ return _$fetchNotificationsAsyncAction
+ .run(() => super.fetchNotifications());
+ }
+
+ @override
+ String toString() {
+ return '''
+notices: ${notices}
+ ''';
+ }
+}
diff --git a/lib/app/controller/common/support_controller.dart b/lib/app/controller/common/support_controller.dart
index 7fbad83..6b9cbd2 100644
--- a/lib/app/controller/common/support_controller.dart
+++ b/lib/app/controller/common/support_controller.dart
@@ -23,17 +23,17 @@ abstract class _SupportControllerBase with Store {
TextEditingController get getMessageController => messageController;
@action
- Future