diff --git a/.gitignore b/.gitignore
index 921bd0a9a..cd5ff7146 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,4 +119,3 @@ Thumbs.db
app/src/release/agconnect-services.json
app/src/release/agconnect-credentials.json
.idea/deploymentTargetDropDown.xml
-.idea/kotlinc.xml
diff --git a/LICENSE b/LICENSE
index a1fc37058..c97032f74 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2023 Wulkanowy
+ Copyright 2022 Wulkanowy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/app/build.gradle b/app/build.gradle
index de0c2a3ce..a61d0a1d4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -16,15 +16,15 @@ apply from: 'hooks.gradle'
android {
namespace 'io.github.wulkanowy'
- compileSdkVersion 33
+ compileSdkVersion 32
defaultConfig {
applicationId "io.github.wulkanowy"
testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 21
- targetSdkVersion 33
- versionCode 124
- versionName "2.0.2"
+ targetSdkVersion 32
+ versionCode 117
+ versionName "1.8.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "app_name", "Wulkanowy"
@@ -162,7 +162,7 @@ play {
track = 'production'
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
userFraction = 0.10d
- updatePriority = 2
+ updatePriority = 5
enabled.set(false)
}
@@ -177,36 +177,36 @@ huaweiPublish {
}
ext {
- work_manager = "2.8.1"
+ work_manager = "2.7.1"
android_hilt = "1.0.0"
- room = "2.5.1"
+ room = "2.4.3"
chucker = "3.5.2"
- mockk = "1.13.5"
+ mockk = "1.13.2"
coroutines = "1.6.4"
}
dependencies {
- implementation 'io.github.wulkanowy:sdk:2.0.1'
+ implementation "io.github.wulkanowy:sdk:1.8.2"
- coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
- implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0"
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
- implementation "androidx.core:core-ktx:1.10.0"
- implementation 'androidx.core:core-splashscreen:1.0.1'
- implementation "androidx.activity:activity-ktx:1.7.1"
- implementation "androidx.appcompat:appcompat:1.6.1"
- implementation "androidx.fragment:fragment-ktx:1.5.7"
- implementation "androidx.annotation:annotation:1.6.0"
+ implementation "androidx.core:core-ktx:1.8.0"
+ implementation 'androidx.core:core-splashscreen:1.0.0'
+ implementation "androidx.activity:activity-ktx:1.5.1"
+ implementation "androidx.appcompat:appcompat:1.5.1"
+ implementation "androidx.fragment:fragment-ktx:1.5.4"
+ implementation "androidx.annotation:annotation:1.5.0"
implementation "androidx.preference:preference-ktx:1.2.0"
- implementation "androidx.recyclerview:recyclerview:1.3.0"
+ implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation "androidx.viewpager2:viewpager2:1.1.0-beta01"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
- implementation "com.google.android.material:material:1.8.0"
+ implementation "com.google.android.material:material:1.7.0"
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
implementation 'com.github.lopspower:CircularImageView:4.3.0'
@@ -214,7 +214,7 @@ dependencies {
implementation "androidx.work:work-runtime-ktx:$work_manager"
playImplementation "androidx.work:work-gcm:$work_manager"
- implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1"
+ implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room"
@@ -229,30 +229,28 @@ dependencies {
implementation "com.github.YarikSOffice:lingver:1.3.0"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
- implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"
- implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"
+ implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
+ implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
implementation "com.jakewharton.timber:timber:5.0.1"
implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation 'com.github.bastienpaulfr:Treessence:1.0.5'
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
- implementation "io.coil-kt:coil:2.3.0"
- implementation "io.github.wulkanowy:AppKillerManager:3.0.1"
+ implementation "io.coil-kt:coil:2.2.2"
+ implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
- implementation 'com.fredporciuncula:flow-preferences:1.9.1'
- implementation 'org.apache.commons:commons-text:1.10.0'
+ implementation 'com.fredporciuncula:flow-preferences:1.8.0'
- playImplementation platform('com.google.firebase:firebase-bom:31.5.0')
+ playImplementation platform('com.google.firebase:firebase-bom:31.0.3')
playImplementation 'com.google.firebase:firebase-analytics-ktx'
playImplementation 'com.google.firebase:firebase-messaging:'
playImplementation 'com.google.firebase:firebase-crashlytics:'
- playImplementation 'com.google.firebase:firebase-config-ktx'
playImplementation 'com.google.android.play:core:1.10.3'
playImplementation 'com.google.android.play:core-ktx:1.8.1'
- playImplementation 'com.google.android.gms:play-services-ads:22.0.0'
+ playImplementation 'com.google.android.gms:play-services-ads:21.3.0'
- hmsImplementation 'com.huawei.hms:hianalytics:6.9.1.200'
- hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.0.300'
+ hmsImplementation 'com.huawei.hms:hianalytics:6.8.0.300'
+ hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.300'
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
@@ -265,17 +263,17 @@ dependencies {
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
- testImplementation 'org.robolectric:robolectric:4.10'
- testImplementation "androidx.test:runner:1.5.2"
- testImplementation "androidx.test.ext:junit:1.1.5"
+ testImplementation 'org.robolectric:robolectric:4.9'
+ testImplementation "androidx.test:runner:1.5.1"
+ testImplementation "androidx.test.ext:junit:1.1.4"
testImplementation "androidx.test:core:1.5.0"
testImplementation "androidx.room:room-testing:$room"
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
- androidTestImplementation "androidx.test:core:1.5.0"
- androidTestImplementation "androidx.test:runner:1.5.2"
- androidTestImplementation "androidx.test.ext:junit:1.1.5"
+ androidTestImplementation "androidx.test:core:1.4.0"
+ androidTestImplementation "androidx.test:runner:1.4.0"
+ androidTestImplementation "androidx.test.ext:junit:1.1.3"
androidTestImplementation "io.mockk:mockk-android:$mockk"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/55.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/55.json
deleted file mode 100644
index 60c2efbe0..000000000
--- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/55.json
+++ /dev/null
@@ -1,2435 +0,0 @@
-{
- "formatVersion": 1,
- "database": {
- "version": 55,
- "identityHash": "cba22eea6d26cf4d6b9a388ba3329a12",
- "entities": [
- {
- "tableName": "Students",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "scrapperBaseUrl",
- "columnName": "scrapper_base_url",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mobileBaseUrl",
- "columnName": "mobile_base_url",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "loginType",
- "columnName": "login_type",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "loginMode",
- "columnName": "login_mode",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "certificateKey",
- "columnName": "certificate_key",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "privateKey",
- "columnName": "private_key",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "isParent",
- "columnName": "is_parent",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "email",
- "columnName": "email",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "password",
- "columnName": "password",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "symbol",
- "columnName": "symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "userLoginId",
- "columnName": "user_login_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "userName",
- "columnName": "user_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentName",
- "columnName": "student_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolSymbol",
- "columnName": "school_id",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolShortName",
- "columnName": "school_short",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolName",
- "columnName": "school_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "className",
- "columnName": "class_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "classId",
- "columnName": "class_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isCurrent",
- "columnName": "is_current",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "registrationDate",
- "columnName": "registration_date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "nick",
- "columnName": "nick",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "avatarColor",
- "columnName": "avatar_color",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [
- {
- "name": "index_Students_email_symbol_student_id_school_id_class_id",
- "unique": true,
- "columnNames": [
- "email",
- "symbol",
- "student_id",
- "school_id",
- "class_id"
- ],
- "orders": [],
- "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)"
- }
- ],
- "foreignKeys": []
- },
- {
- "tableName": "Semesters",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "kindergartenDiaryId",
- "columnName": "kindergarten_diary_id",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- },
- {
- "fieldPath": "diaryName",
- "columnName": "diary_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolYear",
- "columnName": "school_year",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "semesterName",
- "columnName": "semester_name",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "start",
- "columnName": "start",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "end",
- "columnName": "end",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "classId",
- "columnName": "class_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "unitId",
- "columnName": "unit_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "current",
- "columnName": "is_current",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [
- {
- "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id",
- "unique": true,
- "columnNames": [
- "student_id",
- "diary_id",
- "kindergarten_diary_id",
- "semester_id"
- ],
- "orders": [],
- "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)"
- }
- ],
- "foreignKeys": []
- },
- {
- "tableName": "Exams",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "entryDate",
- "columnName": "entry_date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "group",
- "columnName": "group",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "type",
- "columnName": "type",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "description",
- "columnName": "description",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacher",
- "columnName": "teacher",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacherSymbol",
- "columnName": "teacher_symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Timetable",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "number",
- "columnName": "number",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "start",
- "columnName": "start",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "end",
- "columnName": "end",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "subjectOld",
- "columnName": "subjectOld",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "group",
- "columnName": "group",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "room",
- "columnName": "room",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "roomOld",
- "columnName": "roomOld",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacher",
- "columnName": "teacher",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacherOld",
- "columnName": "teacherOld",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "info",
- "columnName": "info",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "isStudentPlan",
- "columnName": "student_plan",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "changes",
- "columnName": "changes",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "canceled",
- "columnName": "canceled",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Attendance",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "timeId",
- "columnName": "time_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "number",
- "columnName": "number",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "presence",
- "columnName": "presence",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "absence",
- "columnName": "absence",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "exemption",
- "columnName": "exemption",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "lateness",
- "columnName": "lateness",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "excused",
- "columnName": "excused",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "deleted",
- "columnName": "deleted",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "excusable",
- "columnName": "excusable",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "excuseStatus",
- "columnName": "excuse_status",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "AttendanceSummary",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subjectId",
- "columnName": "subject_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "month",
- "columnName": "month",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "presence",
- "columnName": "presence",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "absence",
- "columnName": "absence",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "absenceExcused",
- "columnName": "absence_excused",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "absenceForSchoolReasons",
- "columnName": "absence_for_school_reasons",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "lateness",
- "columnName": "lateness",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "latenessExcused",
- "columnName": "lateness_excused",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "exemption",
- "columnName": "exemption",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Grades",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "entry",
- "columnName": "entry",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "value",
- "columnName": "value",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "modifier",
- "columnName": "modifier",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "comment",
- "columnName": "comment",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "color",
- "columnName": "color",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "gradeSymbol",
- "columnName": "grade_symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "description",
- "columnName": "description",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "weight",
- "columnName": "weight",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "weightValue",
- "columnName": "weightValue",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "teacher",
- "columnName": "teacher",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isRead",
- "columnName": "is_read",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "GradesSummary",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "position",
- "columnName": "position",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "predictedGrade",
- "columnName": "predicted_grade",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "finalGrade",
- "columnName": "final_grade",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "proposedPoints",
- "columnName": "proposed_points",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "finalPoints",
- "columnName": "final_points",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "pointsSum",
- "columnName": "points_sum",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "average",
- "columnName": "average",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPredictedGradeNotified",
- "columnName": "is_predicted_grade_notified",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isFinalGradeNotified",
- "columnName": "is_final_grade_notified",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "predictedGradeLastChange",
- "columnName": "predicted_grade_last_change",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "finalGradeLastChange",
- "columnName": "final_grade_last_change",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "GradePartialStatistics",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "classAverage",
- "columnName": "class_average",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentAverage",
- "columnName": "student_average",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "classAmounts",
- "columnName": "class_amounts",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentAmounts",
- "columnName": "student_amounts",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "GradesPointsStatistics",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "others",
- "columnName": "others",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "student",
- "columnName": "student",
- "affinity": "REAL",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "GradeSemesterStatistics",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "amounts",
- "columnName": "amounts",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentGrade",
- "columnName": "student_grade",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Messages",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)",
- "fields": [
- {
- "fieldPath": "email",
- "columnName": "email",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "messageGlobalKey",
- "columnName": "message_global_key",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "mailboxKey",
- "columnName": "mailbox_key",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "messageId",
- "columnName": "message_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "correspondents",
- "columnName": "correspondents",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "folderId",
- "columnName": "folder_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "unread",
- "columnName": "unread",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "readBy",
- "columnName": "read_by",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "unreadBy",
- "columnName": "unread_by",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "hasAttachments",
- "columnName": "has_attachments",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "sender",
- "columnName": "sender",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "recipients",
- "columnName": "recipients",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "MessageAttachments",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))",
- "fields": [
- {
- "fieldPath": "messageGlobalKey",
- "columnName": "message_global_key",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "url",
- "columnName": "url",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "filename",
- "columnName": "filename",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "message_global_key",
- "url",
- "filename"
- ],
- "autoGenerate": false
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Notes",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "teacher",
- "columnName": "teacher",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacherSymbol",
- "columnName": "teacher_symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "category",
- "columnName": "category",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "categoryType",
- "columnName": "category_type",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isPointsShow",
- "columnName": "is_points_show",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "points",
- "columnName": "points",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isRead",
- "columnName": "is_read",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Homework",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "semesterId",
- "columnName": "semester_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "entryDate",
- "columnName": "entry_date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacher",
- "columnName": "teacher",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacherSymbol",
- "columnName": "teacher_symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "attachments",
- "columnName": "attachments",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isDone",
- "columnName": "is_done",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isAddedByUser",
- "columnName": "is_added_by_user",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Subjects",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "realId",
- "columnName": "real_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "LuckyNumbers",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "luckyNumber",
- "columnName": "lucky_number",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "CompletedLesson",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "number",
- "columnName": "number",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "topic",
- "columnName": "topic",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacher",
- "columnName": "teacher",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "teacherSymbol",
- "columnName": "teacher_symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "substitution",
- "columnName": "substitution",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "absence",
- "columnName": "absence",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "resources",
- "columnName": "resources",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Mailboxes",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))",
- "fields": [
- {
- "fieldPath": "globalKey",
- "columnName": "globalKey",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "email",
- "columnName": "email",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "symbol",
- "columnName": "symbol",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolId",
- "columnName": "schoolId",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "fullName",
- "columnName": "fullName",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "userName",
- "columnName": "userName",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentName",
- "columnName": "studentName",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolNameShort",
- "columnName": "schoolNameShort",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "type",
- "columnName": "type",
- "affinity": "TEXT",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "globalKey"
- ],
- "autoGenerate": false
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Recipients",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "mailboxGlobalKey",
- "columnName": "mailboxGlobalKey",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "studentMailboxGlobalKey",
- "columnName": "studentMailboxGlobalKey",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "fullName",
- "columnName": "fullName",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "userName",
- "columnName": "userName",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "schoolShortName",
- "columnName": "schoolShortName",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "type",
- "columnName": "type",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "MobileDevices",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "userLoginId",
- "columnName": "user_login_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "deviceId",
- "columnName": "device_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Teachers",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "classId",
- "columnName": "class_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "shortName",
- "columnName": "short_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "School",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "classId",
- "columnName": "class_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "name",
- "columnName": "name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "address",
- "columnName": "address",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "contact",
- "columnName": "contact",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "headmaster",
- "columnName": "headmaster",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "pedagogue",
- "columnName": "pedagogue",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Conferences",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "title",
- "columnName": "title",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "agenda",
- "columnName": "agenda",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "presentOnConference",
- "columnName": "present_on_conference",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "conferenceId",
- "columnName": "conference_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "TimetableAdditional",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "start",
- "columnName": "start",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "end",
- "columnName": "end",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "repeatId",
- "columnName": "repeat_id",
- "affinity": "BLOB",
- "notNull": false,
- "defaultValue": "NULL"
- },
- {
- "fieldPath": "isAddedByUser",
- "columnName": "is_added_by_user",
- "affinity": "INTEGER",
- "notNull": true,
- "defaultValue": "0"
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "StudentInfo",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "fullName",
- "columnName": "full_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "firstName",
- "columnName": "first_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "secondName",
- "columnName": "second_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "surname",
- "columnName": "surname",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "birthDate",
- "columnName": "birth_date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "birthPlace",
- "columnName": "birth_place",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "gender",
- "columnName": "gender",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "hasPolishCitizenship",
- "columnName": "has_polish_citizenship",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "familyName",
- "columnName": "family_name",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "parentsNames",
- "columnName": "parents_names",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "address",
- "columnName": "address",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "registeredAddress",
- "columnName": "registered_address",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "correspondenceAddress",
- "columnName": "correspondence_address",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "phoneNumber",
- "columnName": "phone_number",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "cellPhoneNumber",
- "columnName": "cell_phone_number",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "email",
- "columnName": "email",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "firstGuardian.fullName",
- "columnName": "first_guardian_full_name",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "firstGuardian.kinship",
- "columnName": "first_guardian_kinship",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "firstGuardian.address",
- "columnName": "first_guardian_address",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "firstGuardian.phones",
- "columnName": "first_guardian_phones",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "firstGuardian.email",
- "columnName": "first_guardian_email",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "secondGuardian.fullName",
- "columnName": "second_guardian_full_name",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "secondGuardian.kinship",
- "columnName": "second_guardian_kinship",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "secondGuardian.address",
- "columnName": "second_guardian_address",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "secondGuardian.phones",
- "columnName": "second_guardian_phones",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "secondGuardian.email",
- "columnName": "second_guardian_email",
- "affinity": "TEXT",
- "notNull": false
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "TimetableHeaders",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "diaryId",
- "columnName": "diary_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "SchoolAnnouncements",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
- "fields": [
- {
- "fieldPath": "userLoginId",
- "columnName": "user_login_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "subject",
- "columnName": "subject",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "isNotified",
- "columnName": "is_notified",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "Notifications",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
- "fields": [
- {
- "fieldPath": "studentId",
- "columnName": "student_id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "title",
- "columnName": "title",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "type",
- "columnName": "type",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "destination",
- "columnName": "destination",
- "affinity": "TEXT",
- "notNull": true,
- "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'"
- },
- {
- "fieldPath": "date",
- "columnName": "date",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "data",
- "columnName": "data",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": true
- },
- "indices": [],
- "foreignKeys": []
- },
- {
- "tableName": "AdminMessages",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `type` TEXT NOT NULL, `is_dismissible` INTEGER NOT NULL, PRIMARY KEY(`id`))",
- "fields": [
- {
- "fieldPath": "id",
- "columnName": "id",
- "affinity": "INTEGER",
- "notNull": true
- },
- {
- "fieldPath": "title",
- "columnName": "title",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "content",
- "columnName": "content",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "versionMin",
- "columnName": "version_name",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "versionMax",
- "columnName": "version_max",
- "affinity": "INTEGER",
- "notNull": false
- },
- {
- "fieldPath": "targetRegisterHost",
- "columnName": "target_register_host",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "targetFlavor",
- "columnName": "target_flavor",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "destinationUrl",
- "columnName": "destination_url",
- "affinity": "TEXT",
- "notNull": false
- },
- {
- "fieldPath": "priority",
- "columnName": "priority",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "type",
- "columnName": "type",
- "affinity": "TEXT",
- "notNull": true
- },
- {
- "fieldPath": "isDismissible",
- "columnName": "is_dismissible",
- "affinity": "INTEGER",
- "notNull": true
- }
- ],
- "primaryKey": {
- "columnNames": [
- "id"
- ],
- "autoGenerate": false
- },
- "indices": [],
- "foreignKeys": []
- }
- ],
- "views": [],
- "setupQueries": [
- "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'cba22eea6d26cf4d6b9a388ba3329a12')"
- ]
- }
-}
\ No newline at end of file
diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml
index 9c21d49d9..7dbec2cb9 100644
--- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,6 +1,5 @@
-
+
-
-
+
\ No newline at end of file
diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 000000000..7dbec2cb9
--- /dev/null
+++ b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 000000000..81e723ecc
Binary files /dev/null and b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 000000000..394b57076
Binary files /dev/null and b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 000000000..365b4d663
Binary files /dev/null and b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 000000000..463c089b3
Binary files /dev/null and b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 000000000..53d6f5bbd
Binary files /dev/null and b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt
deleted file mode 100644
index 88f2598f8..000000000
--- a/app/src/fdroid/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.github.wulkanowy.utils
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt
deleted file mode 100644
index 88f2598f8..000000000
--- a/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.github.wulkanowy.utils
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 174c9a1fc..7835db902 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,8 +8,7 @@
-
-
+
@@ -37,14 +36,13 @@
+ tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
): List
@Delete
@@ -20,9 +20,6 @@ abstract class StudentDao {
@Update(entity = Student::class)
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
- @Update(entity = Student::class)
- abstract suspend fun update(studentName: StudentName)
-
@Query("SELECT * FROM Students WHERE is_current = 1")
abstract suspend fun loadCurrent(): Student?
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt
index 2292c3e62..50299e607 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt
@@ -22,7 +22,6 @@ data class Exam(
val subject: String,
- @Deprecated("not available anymore")
val group: String,
val type: String,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
index 6f0c84ad7..93f042999 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
@@ -2,14 +2,16 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
+import androidx.room.PrimaryKey
import java.io.Serializable
-@Entity(
- tableName = "MessageAttachments",
- primaryKeys = ["message_global_key", "url", "filename"],
-)
+@Entity(tableName = "MessageAttachments")
data class MessageAttachment(
+ @PrimaryKey
+ @ColumnInfo(name = "real_id")
+ val realId: Int,
+
@ColumnInfo(name = "message_global_key")
val messageGlobalKey: String,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt
deleted file mode 100644
index 46f754b5e..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.wulkanowy.data.db.entities
-
-import androidx.room.ColumnInfo
-import androidx.room.Entity
-import androidx.room.PrimaryKey
-import java.io.Serializable
-
-@Entity
-data class StudentName(
-
- @ColumnInfo(name = "student_name")
- val studentName: String
-
-) : Serializable {
-
- @PrimaryKey
- var id: Long = 0
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt
deleted file mode 100644
index 424be171b..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.github.wulkanowy.data.db.migrations
-
-import androidx.room.DeleteColumn
-import androidx.room.migration.AutoMigrationSpec
-import androidx.sqlite.db.SupportSQLiteDatabase
-
-@DeleteColumn(
- tableName = "MessageAttachments",
- columnName = "real_id",
-)
-class Migration55 : AutoMigrationSpec {
-
- override fun onPostMigrate(db: SupportSQLiteDatabase) {
- db.execSQL("DELETE FROM Messages")
- db.execSQL("DELETE FROM MessageAttachments")
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
index add6439d4..17a9e5cdb 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
@@ -10,9 +10,9 @@ fun List.mapToEntities(semester: Semester) = map {
diaryId = semester.diaryId,
agenda = it.agenda,
conferenceId = it.id,
- date = it.date.toInstant(),
+ date = it.dateZoned.toInstant(),
presentOnConference = it.presentOnConference,
- subject = it.topic,
- title = it.place,
+ subject = it.subject,
+ title = it.title
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
index 173dfebf9..bdb5efbba 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
@@ -11,7 +11,7 @@ fun List.mapToEntities(semester: Semester) = map {
date = it.date,
entryDate = it.entryDate,
subject = it.subject,
- group = "",
+ group = it.group,
type = it.type,
description = it.description,
teacher = it.teacher,
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
index a26d76651..120eb183a 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
@@ -2,7 +2,6 @@ package io.github.wulkanowy.data.mappers
import io.github.wulkanowy.data.db.entities.*
import io.github.wulkanowy.sdk.pojo.MailboxType
-import timber.log.Timber
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
@@ -17,16 +16,13 @@ fun List.mapToEntities(
mailboxKey = mailbox?.globalKey ?: allMailboxes.find { box ->
box.fullName == it.mailbox
}?.globalKey.let { mailboxKey ->
- if (mailboxKey == null) {
- Timber.e("Can't find ${it.mailbox} in $allMailboxes")
- "unknown"
- } else mailboxKey
+ requireNotNull(mailboxKey) { "Can't find ${it.mailbox} in $allMailboxes" }
},
email = student.email,
messageId = it.id,
correspondents = it.correspondents,
subject = it.subject.trim(),
- date = it.date.toInstant(),
+ date = it.dateZoned.toInstant(),
folderId = it.folderId,
unread = it.unread,
unreadBy = it.unreadBy,
@@ -40,6 +36,7 @@ fun List.mapToEntities(
fun List.mapToEntities(messageGlobalKey: String) = map {
MessageAttachment(
messageGlobalKey = messageGlobalKey,
+ realId = it.url.hashCode(),
url = it.url,
filename = it.filename
)
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt
index 1f4178fae..1a1c501f6 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt
@@ -9,7 +9,7 @@ import io.github.wulkanowy.sdk.pojo.Token as SdkToken
fun List.mapToEntities(student: Student) = map {
MobileDevice(
userLoginId = student.userLoginId,
- date = it.createDate.toInstant(),
+ date = it.createDateZoned.toInstant(),
deviceId = it.id,
name = it.name
)
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RegisterUserMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RegisterUserMapper.kt
deleted file mode 100644
index bcf26a5e1..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/RegisterUserMapper.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-package io.github.wulkanowy.data.mappers
-
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.data.pojos.*
-import java.time.Instant
-import io.github.wulkanowy.sdk.pojo.RegisterStudent as SdkRegisterStudent
-import io.github.wulkanowy.sdk.pojo.RegisterUser as SdkRegisterUser
-
-fun SdkRegisterUser.mapToPojo(password: String?) = RegisterUser(
- email = email,
- login = login,
- password = password,
- scrapperBaseUrl = scrapperBaseUrl,
- loginMode = loginMode,
- loginType = loginType,
- symbols = symbols.map { registerSymbol ->
- RegisterSymbol(
- symbol = registerSymbol.symbol,
- error = registerSymbol.error,
- hebeBaseUrl = registerSymbol.hebeBaseUrl,
- keyId = registerSymbol.keyId,
- privatePem = registerSymbol.privatePem,
- userName = registerSymbol.userName,
- schools = registerSymbol.schools.map {
- RegisterUnit(
- userLoginId = it.userLoginId,
- schoolId = it.schoolId,
- schoolName = it.schoolName,
- schoolShortName = it.schoolShortName,
- parentIds = it.parentIds,
- studentIds = it.studentIds,
- employeeIds = it.employeeIds,
- error = it.error,
- students = it.subjects
- .filterIsInstance()
- .map { registerSubject ->
- RegisterStudent(
- studentId = registerSubject.studentId,
- studentName = registerSubject.studentName,
- studentSecondName = registerSubject.studentSecondName,
- studentSurname = registerSubject.studentSurname,
- className = registerSubject.className,
- classId = registerSubject.classId,
- isParent = registerSubject.isParent,
- semesters = registerSubject.semesters
- .mapToEntities(registerSubject.studentId),
- )
- },
- )
- }
- )
- },
-)
-
-fun RegisterStudent.mapToStudentWithSemesters(
- user: RegisterUser,
- symbol: RegisterSymbol,
- unit: RegisterUnit,
- colors: List,
-): StudentWithSemesters = StudentWithSemesters(
- semesters = semesters,
- student = Student(
- email = user.login, // for compatibility
- userName = symbol.userName,
- userLoginId = unit.userLoginId,
- isParent = isParent,
- className = className,
- classId = classId,
- studentId = studentId,
- symbol = symbol.symbol,
- loginType = user.loginType?.name.orEmpty(),
- schoolName = unit.schoolName,
- schoolShortName = unit.schoolShortName,
- schoolSymbol = unit.schoolId,
- studentName = "$studentName $studentSurname",
- loginMode = user.loginMode.name,
- scrapperBaseUrl = user.scrapperBaseUrl.orEmpty(),
- mobileBaseUrl = symbol.hebeBaseUrl.orEmpty(),
- certificateKey = symbol.keyId.orEmpty(),
- privateKey = symbol.privatePem.orEmpty(),
- password = user.password.orEmpty(),
- isCurrent = false,
- registrationDate = Instant.now(),
- ).apply {
- avatarColor = colors.random()
- },
-)
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt
new file mode 100644
index 000000000..a2110d7f5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt
@@ -0,0 +1,37 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
+import java.time.Instant
+import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
+
+fun List.mapToEntities(password: String = "", colors: List) = map {
+ StudentWithSemesters(
+ student = Student(
+ email = it.email,
+ password = password,
+ isParent = it.isParent,
+ symbol = it.symbol,
+ studentId = it.studentId,
+ userLoginId = it.userLoginId,
+ userName = it.userName,
+ studentName = it.studentName + " " + it.studentSurname,
+ schoolSymbol = it.schoolSymbol,
+ schoolShortName = it.schoolShortName,
+ schoolName = it.schoolName,
+ className = it.className,
+ classId = it.classId,
+ scrapperBaseUrl = it.scrapperBaseUrl,
+ loginType = it.loginType.name,
+ isCurrent = false,
+ registrationDate = Instant.now(),
+ mobileBaseUrl = it.mobileBaseUrl,
+ privateKey = it.privateKey,
+ certificateKey = it.certificateKey,
+ loginMode = it.loginMode.name,
+ ).apply {
+ avatarColor = colors.random()
+ },
+ semesters = it.semesters.mapToEntities(it.studentId)
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt
index ee525e108..e55aa3cf7 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt
@@ -5,10 +5,10 @@ import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.db.entities.TimetableAdditional
import io.github.wulkanowy.data.db.entities.TimetableHeader
import io.github.wulkanowy.data.pojos.TimetableFull
-import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetableFull
+import io.github.wulkanowy.sdk.pojo.TimetableFull as SdkTimetableFull
import io.github.wulkanowy.sdk.pojo.TimetableDayHeader as SdkTimetableHeader
-import io.github.wulkanowy.sdk.pojo.Lesson as SdkLesson
-import io.github.wulkanowy.sdk.pojo.LessonAdditional as SdkTimetableAdditional
+import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetable
+import io.github.wulkanowy.sdk.pojo.TimetableAdditional as SdkTimetableAdditional
fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull(
lessons = lessons.mapToEntities(semester),
@@ -16,13 +16,13 @@ fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull(
headers = headers.mapToEntities(semester)
)
-fun List.mapToEntities(semester: Semester) = map {
+fun List.mapToEntities(semester: Semester) = map {
Timetable(
studentId = semester.studentId,
diaryId = semester.diaryId,
number = it.number,
- start = it.start.toInstant(),
- end = it.end.toInstant(),
+ start = it.startZoned.toInstant(),
+ end = it.endZoned.toInstant(),
date = it.date,
subject = it.subject,
subjectOld = it.subjectOld,
@@ -45,8 +45,8 @@ fun List.mapToEntities(semester: Semester) = map {
diaryId = semester.diaryId,
subject = it.subject,
date = it.date,
- start = it.start.toInstant(),
- end = it.end.toInstant(),
+ start = it.startZoned.toInstant(),
+ end = it.endZoned.toInstant(),
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/RegisterUser.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/RegisterUser.kt
deleted file mode 100644
index 98bf1402b..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/pojos/RegisterUser.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.wulkanowy.data.pojos
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.sdk.scrapper.Scrapper
-
-data class RegisterUser(
- val email: String,
- val password: String?,
- val login: String, // may be the same as email
- val scrapperBaseUrl: String?,
- val loginType: Scrapper.LoginType?,
- val loginMode: Sdk.Mode,
- val symbols: List,
-) : java.io.Serializable
-
-data class RegisterSymbol(
- val symbol: String,
- val error: Throwable?,
- val hebeBaseUrl: String?,
- val keyId: String?,
- val privatePem: String?,
- val userName: String,
- val schools: List,
-) : java.io.Serializable
-
-data class RegisterUnit(
- val userLoginId: Int,
- val schoolId: String,
- val schoolName: String,
- val schoolShortName: String,
- val parentIds: List,
- val studentIds: List,
- val employeeIds: List,
- val error: Throwable?,
- val students: List,
-) : java.io.Serializable
-
-data class RegisterStudent(
- val studentId: Int,
- val studentName: String,
- val studentSecondName: String,
- val studentSurname: String,
- val className: String,
- val classId: Int,
- val isParent: Boolean,
- val semesters: List,
-) : java.io.Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt
index bec2797db..cbaa12bd3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt
@@ -19,6 +19,7 @@ class AppCreatorRepository @Inject constructor(
) {
@OptIn(ExperimentalSerializationApi::class)
+ @Suppress("BlockingMethodInNonBlockingContext")
suspend fun getAppCreators() = withContext(dispatchers.io) {
val inputStream = context.assets.open("contributors.json").buffered()
json.decodeFromStream>(inputStream)
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
index 3afb99077..fd5d8bd16 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
@@ -59,7 +59,7 @@ class AttendanceRepository @Inject constructor(
}
sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .getAttendance(start.monday, end.sunday)
+ .getAttendance(start.monday, end.sunday, semester.semesterId)
.mapToEntities(semester, lessons)
},
saveFetchResult = { old, new ->
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
index 013c0951d..faa80b93e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
@@ -52,7 +52,7 @@ class ExamRepository @Inject constructor(
fetch = {
sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .getExams(start.startExamsDay, start.endExamsDay)
+ .getExams(start.startExamsDay, start.endExamsDay, semester.semesterId)
.mapToEntities(semester)
},
saveFetchResult = { old, new ->
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
index 53d9beadd..f95b8dbec 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
@@ -103,10 +103,7 @@ class MessageRepository @Inject constructor(
messagesDb.loadMessageWithAttachment(message.messageGlobalKey)
},
fetch = {
- sdk.init(student).getMessageDetails(
- messageKey = it!!.message.messageGlobalKey,
- markAsRead = message.unread && markAsRead,
- )
+ sdk.init(student).getMessageDetails(it!!.message.messageGlobalKey, markAsRead)
},
saveFetchResult = { old, new ->
checkNotNull(old) { "Fetched message no longer exist!" }
@@ -181,7 +178,7 @@ class MessageRepository @Inject constructor(
).first()
}
- suspend fun deleteMessage(student: Student, mailbox: Mailbox?, message: Message) {
+ suspend fun deleteMessage(student: Student, mailbox: Mailbox, message: Message) {
deleteMessages(student, mailbox, listOf(message))
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
index 4101803f3..e5d7bc5cb 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
@@ -42,7 +42,7 @@ class NoteRepository @Inject constructor(
fetch = {
sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .getNotes()
+ .getNotes(semester.semesterId)
.mapToEntities(semester)
},
saveFetchResult = { old, new ->
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
index 348a4054b..afc262868 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
@@ -2,17 +2,14 @@ package io.github.wulkanowy.data.repositories
import android.content.Context
import android.content.SharedPreferences
-import androidx.annotation.StringRes
import androidx.core.content.edit
import com.fredporciuncula.flow.preferences.FlowSharedPreferences
import com.fredporciuncula.flow.preferences.Preference
-import com.fredporciuncula.flow.preferences.Serializer
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.R
import io.github.wulkanowy.data.enums.*
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
-import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.decodeFromString
@@ -31,35 +28,29 @@ class PreferencesRepository @Inject constructor(
private val json: Json,
) {
+ val startMenuIndex: Int
+ get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt()
+
val isShowPresent: Boolean
get() = getBoolean(
R.string.pref_key_attendance_present,
R.bool.pref_default_attendance_present
)
- private val gradeAverageModePref: Preference
- get() = getObjectFlow(
- R.string.pref_key_grade_average_mode,
- R.string.pref_default_grade_average_mode,
- object : Serializer {
- override fun serialize(value: GradeAverageMode) = value.value
- override fun deserialize(serialized: String) =
- GradeAverageMode.getByValue(serialized)
- },
+ val gradeAverageMode: GradeAverageMode
+ get() = GradeAverageMode.getByValue(
+ getString(
+ R.string.pref_key_grade_average_mode,
+ R.string.pref_default_grade_average_mode
+ )
)
- val gradeAverageModeFlow: Flow
- get() = gradeAverageModePref.asFlow()
-
- private val gradeAverageForceCalcPref: Preference
- get() = flowSharedPref.getBoolean(
- context.getString(R.string.pref_key_grade_average_force_calc),
- context.resources.getBoolean(R.bool.pref_default_grade_average_force_calc)
+ val gradeAverageForceCalc: Boolean
+ get() = getBoolean(
+ R.string.pref_key_grade_average_force_calc,
+ R.bool.pref_default_grade_average_force_calc
)
- val gradeAverageForceCalcFlow: Flow
- get() = gradeAverageForceCalcPref.asFlow()
-
val gradeExpandMode: GradeExpandMode
get() = GradeExpandMode.getByValue(
getString(
@@ -149,24 +140,12 @@ class PreferencesRepository @Inject constructor(
R.string.pref_default_grade_modifier_plus
).toDouble()
- val gradePlusModifierFlow: Flow
- get() = getStringFlow(
- R.string.pref_key_grade_modifier_plus,
- R.string.pref_default_grade_modifier_plus
- ).asFlow().map { it.toDouble() }
-
val gradeMinusModifier: Double
get() = getString(
R.string.pref_key_grade_modifier_minus,
R.string.pref_default_grade_modifier_minus
).toDouble()
- val gradeMinusModifierFlow: Flow
- get() = getStringFlow(
- R.string.pref_key_grade_modifier_minus,
- R.string.pref_default_grade_modifier_minus
- ).asFlow().map { it.toDouble() }
-
val fillMessageContent: Boolean
get() = getBoolean(
R.string.pref_key_fill_message_content,
@@ -201,17 +180,24 @@ class PreferencesRepository @Inject constructor(
R.bool.pref_default_timetable_show_timers
)
+ var isHomeworkFullscreen: Boolean
+ get() = getBoolean(
+ R.string.pref_key_homework_fullscreen,
+ R.bool.pref_default_homework_fullscreen
+ )
+ set(value) = sharedPref.edit().putBoolean("homework_fullscreen", value).apply()
+
val showSubjectsWithoutGrades: Boolean
get() = getBoolean(
R.string.pref_key_subjects_without_grades,
R.bool.pref_default_subjects_without_grades
)
- val isOptionalArithmeticAverageFlow: Flow
- get() = flowSharedPref.getBoolean(
- context.getString(R.string.pref_key_optional_arithmetic_average),
- context.resources.getBoolean(R.bool.pref_default_optional_arithmetic_average)
- ).asFlow()
+ val isOptionalArithmeticAverage: Boolean
+ get() = getBoolean(
+ R.string.pref_key_optional_arithmetic_average,
+ R.bool.pref_default_optional_arithmetic_average
+ )
var lasSyncDate: Instant?
get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date)
@@ -329,20 +315,6 @@ class PreferencesRepository @Inject constructor(
putBoolean(context.getString(R.string.pref_key_ads_enabled), value)
}
- var appMenuItemOrder: List
- get() {
- val value = sharedPref.getString(PREF_KEY_APP_MENU_ITEM_ORDER, null)
- ?: return AppMenuItem.defaultAppMenuItemList
-
- return json.decodeFromString(value)
- }
- set(value) = sharedPref.edit {
- putString(
- PREF_KEY_APP_MENU_ITEM_ORDER,
- json.encodeToString(value)
- )
- }
-
var installationId: String
get() = sharedPref.getString(PREF_KEY_INSTALLATION_ID, null).orEmpty()
private set(value) = sharedPref.edit { putString(PREF_KEY_INSTALLATION_ID, value) }
@@ -358,21 +330,6 @@ class PreferencesRepository @Inject constructor(
private fun getLong(id: String, default: Int) =
sharedPref.getLong(id, context.resources.getString(default).toLong())
- private fun getStringFlow(id: Int, default: Int) =
- flowSharedPref.getString(context.getString(id), context.getString(default))
-
- private fun getObjectFlow(
- @StringRes id: Int,
- @StringRes default: Int,
- serializer: Serializer
- ): Preference = flowSharedPref.getObject(
- key = context.getString(id),
- serializer = serializer,
- defaultValue = serializer.deserialize(
- flowSharedPref.getString(context.getString(default)).get()
- )
- )
-
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
private fun getString(id: String, default: Int) =
@@ -384,7 +341,6 @@ class PreferencesRepository @Inject constructor(
sharedPref.getBoolean(id, context.resources.getBoolean(default))
private companion object {
- private const val PREF_KEY_APP_MENU_ITEM_ORDER = "app_menu_item_order"
private const val PREF_KEY_INSTALLATION_ID = "installation_id"
private const val PREF_KEY_DASHBOARD_ITEMS_POSITION = "dashboard_items_position"
private const val PREF_KEY_IN_APP_REVIEW_COUNT = "in_app_review_count"
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
index 92bb37081..96f019223 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
@@ -40,7 +40,7 @@ class SemesterRepository @Inject constructor(
val isNoSemesters = semesters.isEmpty()
val isRefreshOnModeChangeRequired = when {
- Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE -> {
+ Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> {
semesters.firstOrNull { it.isCurrent }?.let {
0 == it.diaryId && 0 == it.kindergartenDiaryId
} == true
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
index a6bb72433..f006b7d28 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
@@ -6,17 +6,14 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao
-import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.db.entities.StudentName
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
-import io.github.wulkanowy.data.mappers.mapToPojo
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.DispatchersProvider
-import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.security.decrypt
import io.github.wulkanowy.utils.security.encrypt
import kotlinx.coroutines.withContext
@@ -30,51 +27,45 @@ class StudentRepository @Inject constructor(
private val studentDb: StudentDao,
private val semesterDb: SemesterDao,
private val sdk: Sdk,
+ private val appInfo: AppInfo,
private val appDatabase: AppDatabase
) {
+ suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty()
+
suspend fun isCurrentStudentSet() = studentDb.loadCurrent()?.isCurrent ?: false
suspend fun getStudentsApi(
pin: String,
symbol: String,
token: String
- ): RegisterUser = sdk
- .getStudentsFromHebe(token, pin, symbol, "")
- .mapToPojo(null)
+ ): List =
+ sdk.getStudentsFromMobileApi(token, pin, symbol, "")
+ .mapToEntities(colors = appInfo.defaultColorsForAvatar)
suspend fun getStudentsScrapper(
email: String,
password: String,
scrapperBaseUrl: String,
symbol: String
- ): RegisterUser = sdk
- .getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, symbol)
- .mapToPojo(password)
-
- suspend fun getUserSubjectsFromScrapper(
- email: String,
- password: String,
- scrapperBaseUrl: String,
- symbol: String
- ): RegisterUser = sdk
- .getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, symbol)
- .mapToPojo(password)
+ ): List =
+ sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
+ .mapToEntities(password, appInfo.defaultColorsForAvatar)
suspend fun getStudentsHybrid(
email: String,
password: String,
scrapperBaseUrl: String,
symbol: String
- ): RegisterUser = sdk
- .getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol)
- .mapToPojo(password)
+ ): List =
+ sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol)
+ .mapToEntities(password, appInfo.defaultColorsForAvatar)
suspend fun getSavedStudents(decryptPass: Boolean = true) =
studentDb.loadStudentsWithSemesters()
.map {
it.apply {
- if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
+ if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
student.password = withContext(dispatchers.io) {
decrypt(student.password)
}
@@ -84,7 +75,7 @@ class StudentRepository @Inject constructor(
suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true) =
studentDb.loadStudentWithSemestersById(id)?.apply {
- if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
+ if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
student.password = withContext(dispatchers.io) {
decrypt(student.password)
}
@@ -94,7 +85,7 @@ class StudentRepository @Inject constructor(
suspend fun getStudentById(id: Long, decryptPass: Boolean = true): Student {
val student = studentDb.loadById(id) ?: throw NoCurrentStudentException()
- if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
+ if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
student.password = withContext(dispatchers.io) {
decrypt(student.password)
}
@@ -105,7 +96,7 @@ class StudentRepository @Inject constructor(
suspend fun getCurrentStudent(decryptPass: Boolean = true): Student {
val student = studentDb.loadCurrent() ?: throw NoCurrentStudentException()
- if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
+ if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
student.password = withContext(dispatchers.io) {
decrypt(student.password)
}
@@ -118,7 +109,7 @@ class StudentRepository @Inject constructor(
val students = studentsWithSemesters.map { it.student }
.map {
it.apply {
- if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.HEBE) {
+ if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) {
password = withContext(dispatchers.io) {
encrypt(password, context)
}
@@ -149,21 +140,4 @@ class StudentRepository @Inject constructor(
suspend fun isOneUniqueStudent() = getSavedStudents(false)
.distinctBy { it.student.studentName }.size == 1
-
- suspend fun authorizePermission(student: Student, semester: Semester, pesel: String) =
- sdk.init(student)
- .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .authorizePermission(pesel)
-
- suspend fun refreshStudentName(student: Student, semester: Semester) {
- val newCurrentApiStudent = sdk.init(student)
- .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .getCurrentStudent() ?: return
-
- val studentName = StudentName(
- studentName = "${newCurrentApiStudent.studentName} ${newCurrentApiStudent.studentSurname}"
- ).apply { id = student.id }
-
- studentDb.update(studentName)
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
index 4e3b40f96..acd71e1f4 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
@@ -40,7 +40,7 @@ class TeacherRepository @Inject constructor(
fetch = {
sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .getTeachers()
+ .getTeachers(semester.semesterId)
.mapToEntities(semester)
},
saveFetchResult = { old, new ->
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
index 136fb8d5b..3145c2a23 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
@@ -13,7 +13,6 @@ import io.github.wulkanowy.utils.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.sync.Mutex
-import java.time.Instant
import java.time.LocalDate
import javax.inject.Inject
import javax.inject.Singleton
@@ -66,7 +65,7 @@ class TimetableRepository @Inject constructor(
fetch = {
val timetableFull = sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
- .getTimetable(start.monday, end.sunday)
+ .getTimetableFull(start.monday, end.sunday)
timetableFull.mapToEntities(semester)
},
@@ -165,11 +164,6 @@ class TimetableRepository @Inject constructor(
timetableHeaderDb.insertAll(new uniqueSubtract old)
}
- fun getLastRefreshTimestamp(semester: Semester, start: LocalDate, end: LocalDate): Instant {
- val refreshKey = getRefreshKey(cacheKey, semester, start, end)
- return refreshHelper.getLastRefreshTimestamp(refreshKey)
- }
-
suspend fun saveAdditionalList(additionalList: List) =
timetableAdditionalDb.insertAll(additionalList)
diff --git a/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt
index 669514aae..a696d9b2f 100644
--- a/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt
+++ b/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt
@@ -17,11 +17,8 @@ class GetMailboxByStudentUseCase @Inject constructor(
private fun List.filterByStudent(student: Student): Mailbox? {
val normalizedStudentName = student.studentName.normalizeStudentName()
- return singleOrNull {
+ return find {
it.studentName.normalizeStudentName() == normalizedStudentName
- } ?: singleOrNull {
- it.studentName.normalizeStudentName() == normalizedStudentName
- && it.schoolNameShort == student.schoolShortName
} ?: singleOrNull {
it.studentName.getFirstAndLastPart() == normalizedStudentName.getFirstAndLastPart()
} ?: singleOrNull {
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
index e0a136f98..c1bed4dd3 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
@@ -4,12 +4,18 @@ import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.O
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.asFlow
-import androidx.work.*
import androidx.work.BackoffPolicy.EXPONENTIAL
+import androidx.work.Constraints
+import androidx.work.Data
import androidx.work.ExistingPeriodicWorkPolicy.KEEP
-import androidx.work.ExistingPeriodicWorkPolicy.UPDATE
+import androidx.work.ExistingPeriodicWorkPolicy.REPLACE
+import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType.CONNECTED
import androidx.work.NetworkType.UNMETERED
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkInfo
+import androidx.work.WorkManager
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
import io.github.wulkanowy.data.repositories.PreferencesRepository
@@ -54,7 +60,7 @@ class SyncManager @Inject constructor(
val serviceInterval = preferencesRepository.servicesInterval
workManager.enqueueUniquePeriodicWork(
- SyncWorker::class.java.simpleName, if (restart) UPDATE else KEEP,
+ SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
PeriodicWorkRequestBuilder(serviceInterval, MINUTES)
.setInitialDelay(10, MINUTES)
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
diff --git a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt b/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt
index d48556fa6..45cd2b04e 100644
--- a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt
@@ -4,6 +4,7 @@ import android.content.Intent
import android.widget.RemoteViewsService
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.data.db.SharedPrefProvider
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.repositories.TimetableRepository
@@ -23,13 +24,14 @@ class TimetableWidgetService : RemoteViewsService() {
@Inject
lateinit var semesterRepo: SemesterRepository
+ @Inject
+ lateinit var prefRepository: PreferencesRepository
+
@Inject
lateinit var sharedPref: SharedPrefProvider
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
Timber.d("TimetableWidgetFactory created")
- return TimetableWidgetFactory(
- timetableRepo, studentRepo, semesterRepo, sharedPref, applicationContext, intent
- )
+ return TimetableWidgetFactory(timetableRepo, studentRepo, semesterRepo, prefRepository, sharedPref, applicationContext, intent)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
index f622209a7..075557a5c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
@@ -4,13 +4,12 @@ import android.app.ActivityManager
import android.os.Bundle
import android.view.View
import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
import io.github.wulkanowy.R
-import io.github.wulkanowy.ui.modules.auth.AuthDialog
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.utils.FragmentLifecycleLogger
import io.github.wulkanowy.utils.getThemeAttrColor
@@ -31,8 +30,6 @@ abstract class BaseActivity, VB : ViewBinding> :
protected var messageContainer: View? = null
- protected var messageAnchor: View? = null
-
abstract var presenter: T
override fun onCreate(savedInstanceState: Bundle?) {
@@ -51,7 +48,6 @@ abstract class BaseActivity, VB : ViewBinding> :
if (messageContainer != null) {
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
.setAction(R.string.all_details) { showErrorDetailsDialog(error) }
- .apply { messageAnchor?.let { anchorView = it } }
.show()
} else showMessage(text)
}
@@ -61,15 +57,12 @@ abstract class BaseActivity, VB : ViewBinding> :
}
override fun showMessage(text: String) {
- if (messageContainer != null) {
- Snackbar.make(messageContainer!!, text, LENGTH_LONG)
- .apply { messageAnchor?.let { anchorView = it } }
- .show()
- } else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
+ if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
+ else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
}
override fun showExpiredDialog() {
- MaterialAlertDialogBuilder(this)
+ AlertDialog.Builder(this)
.setTitle(R.string.main_session_expired)
.setMessage(R.string.main_session_relogin)
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() }
@@ -77,15 +70,10 @@ abstract class BaseActivity, VB : ViewBinding> :
.show()
}
- override fun showAuthDialog() {
- AuthDialog.newInstance().show(supportFragmentManager, "auth_dialog")
- }
-
override fun showChangePasswordSnackbar(redirectUrl: String) {
messageContainer?.let {
Snackbar.make(it, R.string.error_password_change_required, LENGTH_LONG)
.setAction(R.string.all_change) { openInternetBrowser(redirectUrl) }
- .apply { messageAnchor?.let { anchorView = it } }
.show()
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
index 84540b1ca..25a53395d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
@@ -1,14 +1,8 @@
package io.github.wulkanowy.ui.base
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import androidx.viewbinding.ViewBinding
-import com.google.android.material.elevation.SurfaceColors
-import io.github.wulkanowy.ui.modules.auth.AuthDialog
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.lifecycleAwareVariable
import javax.inject.Inject
@@ -40,25 +34,10 @@ abstract class BaseDialogFragment : DialogFragment(), BaseView
(activity as? BaseActivity<*, *>)?.showChangePasswordSnackbar(redirectUrl)
}
- override fun showAuthDialog() {
- AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
- }
-
override fun showErrorDetailsDialog(error: Throwable) {
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- view.setBackgroundColor(SurfaceColors.SURFACE_3.getColor(requireContext()))
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ) = binding.root
-
override fun onResume() {
super.onResume()
analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt
index b25346a7e..dbc5af3a9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt
@@ -7,7 +7,6 @@ import androidx.viewbinding.ViewBinding
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
import io.github.wulkanowy.R
-import io.github.wulkanowy.ui.modules.auth.AuthDialog
import io.github.wulkanowy.utils.lifecycleAwareVariable
abstract class BaseFragment(@LayoutRes layoutId: Int) : Fragment(layoutId),
@@ -43,10 +42,6 @@ abstract class BaseFragment(@LayoutRes layoutId: Int) : Fragme
(activity as? BaseActivity<*, *>)?.showExpiredDialog()
}
- override fun showAuthDialog() {
- AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
- }
-
override fun openClearLoginView() {
(activity as? BaseActivity<*, *>)?.openClearLoginView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt
index 2d913103b..15c069f54 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt
@@ -1,15 +1,10 @@
package io.github.wulkanowy.ui.base
import io.github.wulkanowy.data.repositories.StudentRepository
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.launch
import timber.log.Timber
open class BasePresenter(
@@ -31,7 +26,6 @@ open class BasePresenter(
onSessionExpired = view::showExpiredDialog
onNoCurrentStudent = view::openClearLoginView
onPasswordChangeRequired = view::showChangePasswordSnackbar
- onAuthorizationRequired = view::showAuthDialog
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt
index b31737e2b..d3165ea44 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt
@@ -8,8 +8,6 @@ interface BaseView {
fun showExpiredDialog()
- fun showAuthDialog()
-
fun openClearLoginView()
fun showErrorDetailsDialog(error: Throwable)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
index 679d904a3..e979fa8af 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
@@ -4,13 +4,13 @@ import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.os.Bundle
-import android.view.View
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import androidx.appcompat.app.AlertDialog
import androidx.core.content.getSystemService
import androidx.core.os.bundleOf
import androidx.core.view.isGone
+import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -20,7 +20,7 @@ import io.github.wulkanowy.utils.*
import javax.inject.Inject
@AndroidEntryPoint
-class ErrorDialog : BaseDialogFragment() {
+class ErrorDialog : DialogFragment() {
@Inject
lateinit var appInfo: AppInfo
@@ -28,8 +28,6 @@ class ErrorDialog : BaseDialogFragment() {
@Inject
lateinit var preferencesRepository: PreferencesRepository
- private lateinit var error: Throwable
-
companion object {
private const val ARGUMENT_KEY = "error"
@@ -38,31 +36,32 @@ class ErrorDialog : BaseDialogFragment() {
}
}
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- error = requireArguments().serializable(ARGUMENT_KEY)
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val error = requireArguments().getSerializable(ARGUMENT_KEY) as Throwable
+
+ val binding = DialogErrorBinding.inflate(layoutInflater)
+ binding.bindErrorDetails(error)
+
+ return getAlertDialog(binding, error).apply {
+ enableReportButtonIfErrorIsReportable(error)
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ private fun getAlertDialog(binding: DialogErrorBinding, error: Throwable): AlertDialog {
return MaterialAlertDialogBuilder(requireContext()).apply {
val errorStacktrace = error.stackTraceToString()
setTitle(R.string.all_details)
- setView(DialogErrorBinding.inflate(layoutInflater).apply { binding = this }.root)
+ setView(binding.root)
setNeutralButton(R.string.about_feedback) { _, _ ->
openConfirmDialog { openEmailClient(errorStacktrace) }
}
setNegativeButton(android.R.string.cancel) { _, _ -> }
setPositiveButton(android.R.string.copy) { _, _ -> copyErrorToClipboard(errorStacktrace) }
- }.create().apply {
- setOnShowListener {
- getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = error.isShouldBeReported()
- }
- }
+ }.create()
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- with(binding) {
+ private fun DialogErrorBinding.bindErrorDetails(error: Throwable) {
+ return with(this) {
errorDialogHumanizedMessage.text = resources.getErrorString(error)
errorDialogErrorMessage.text = error.localizedMessage
errorDialogErrorMessage.isGone = error.localizedMessage.isNullOrBlank()
@@ -71,6 +70,12 @@ class ErrorDialog : BaseDialogFragment() {
}
}
+ private fun AlertDialog.enableReportButtonIfErrorIsReportable(error: Throwable) {
+ setOnShowListener {
+ getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = error.isShouldBeReported()
+ }
+ }
+
private fun copyErrorToClipboard(errorStacktrace: String) {
val clip = ClipData.newPlainText("Error details", errorStacktrace)
requireActivity().getSystemService()?.setPrimaryClip(clip)
@@ -78,7 +83,7 @@ class ErrorDialog : BaseDialogFragment() {
}
private fun openConfirmDialog(callback: () -> Unit) {
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(R.string.dialog_error_check_update)
.setMessage(R.string.dialog_error_check_update_message)
.setNeutralButton(R.string.about_feedback) { _, _ -> callback() }
@@ -108,4 +113,8 @@ class ErrorDialog : BaseDialogFragment() {
}
)
}
+
+ private fun showMessage(text: String) {
+ Toast.makeText(requireContext(), text, LENGTH_LONG).show()
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt
index 0a41a47b3..afe200e9a 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt
@@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.base
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
-import io.github.wulkanowy.sdk.scrapper.exception.AuthorizationRequiredException
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
import io.github.wulkanowy.utils.getErrorString
@@ -21,8 +20,6 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
var onPasswordChangeRequired: (String) -> Unit = {}
- var onAuthorizationRequired: () -> Unit = {}
-
fun dispatch(error: Throwable) {
Timber.e(error, "An exception occurred while the Wulkanowy was running")
proceed(error)
@@ -34,7 +31,6 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl)
is ScramblerException, is BadCredentialsException -> onSessionExpired()
is NoCurrentStudentException -> onNoCurrentStudent()
- is AuthorizationRequiredException -> onAuthorizationRequired()
}
}
@@ -43,6 +39,5 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
onSessionExpired = {}
onNoCurrentStudent = {}
onPasswordChangeRequired = {}
- onAuthorizationRequired = {}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
index f42f315ce..2d83bbbf9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
@@ -1,19 +1,17 @@
package io.github.wulkanowy.ui.base
-import android.content.pm.PackageInfo
-import android.content.pm.PackageManager
import android.content.pm.PackageManager.GET_ACTIVITIES
-import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
-import com.google.android.material.color.DynamicColors
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
import io.github.wulkanowy.R
import io.github.wulkanowy.data.enums.AppTheme
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.ui.modules.login.LoginActivity
-import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity
import io.github.wulkanowy.ui.modules.main.MainActivity
-import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureActivity
+import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
import javax.inject.Inject
import javax.inject.Singleton
@@ -27,40 +25,31 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
when (activity) {
is MainActivity -> activity.setTheme(R.style.WulkanowyTheme_Black)
is LoginActivity -> activity.setTheme(R.style.WulkanowyTheme_Login_Black)
+ is SendMessageActivity -> activity.setTheme(R.style.WulkanowyTheme_MessageSend_Black)
}
}
- } else if (activity is TimetableWidgetConfigureActivity || activity is LuckyNumberWidgetConfigureActivity) {
- DynamicColors.applyToActivityIfAvailable(activity)
}
}
fun applyDefaultTheme() {
AppCompatDelegate.setDefaultNightMode(
when (preferencesRepository.appTheme) {
- AppTheme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
- AppTheme.DARK, AppTheme.BLACK -> AppCompatDelegate.MODE_NIGHT_YES
- AppTheme.SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
+ AppTheme.LIGHT -> MODE_NIGHT_NO
+ AppTheme.DARK, AppTheme.BLACK -> MODE_NIGHT_YES
+ AppTheme.SYSTEM -> MODE_NIGHT_FOLLOW_SYSTEM
}
)
}
- private fun isThemeApplicable(activity: AppCompatActivity): Boolean =
- getPackageInfo(activity)
+ private fun isThemeApplicable(activity: AppCompatActivity) =
+ activity.packageManager
+ .getPackageInfo(activity.packageName, GET_ACTIVITIES)
.activities
.singleOrNull { it.name == activity::class.java.canonicalName }
?.theme
.let {
it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar
|| it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black
+ || it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black
}
-
- @Suppress("DEPRECATION")
- private fun getPackageInfo(activity: AppCompatActivity): PackageInfo {
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- activity.packageManager.getPackageInfo(
- activity.packageName,
- PackageManager.PackageInfoFlags.of(GET_ACTIVITIES.toLong())
- )
- } else activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES)
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt
index f0969fac4..561419a05 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt
@@ -9,14 +9,11 @@ import io.github.wulkanowy.ui.modules.exam.ExamFragment
import io.github.wulkanowy.ui.modules.grade.GradeFragment
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
-import io.github.wulkanowy.ui.modules.luckynumber.history.LuckyNumberHistoryFragment
import io.github.wulkanowy.ui.modules.message.MessageFragment
-import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment
import io.github.wulkanowy.ui.modules.more.MoreFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment
-import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
+import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
-import io.github.wulkanowy.ui.modules.settings.SettingsFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
import kotlinx.serialization.Serializable
import java.time.LocalDate
@@ -42,13 +39,10 @@ sealed class Destination {
NOTE(Note),
CONFERENCE(Conference),
SCHOOL_ANNOUNCEMENT(SchoolAnnouncement),
- SCHOOL_AND_TEACHERS(SchoolAndTeachers),
- LUCKY_NUMBER(LuckyNumber),
- LUCKY_NUMBER_HISTORY(LuckyNumberHistory),
+ SCHOOL(School),
+ LUCKY_NUMBER(More),
MORE(More),
- MESSAGE(Message),
- MOBILE_DEVICE(MobileDevice),
- SETTINGS(Settings);
+ MESSAGE(Message);
}
@Serializable
@@ -109,9 +103,9 @@ sealed class Destination {
}
@Serializable
- object SchoolAndTeachers : Destination() {
- override val destinationType get() = Type.SCHOOL_AND_TEACHERS
- override val destinationFragment get() = SchoolAndTeachersFragment.newInstance()
+ object School : Destination() {
+ override val destinationType get() = Type.SCHOOL
+ override val destinationFragment get() = SchoolFragment.newInstance()
}
@Serializable
@@ -120,12 +114,6 @@ sealed class Destination {
override val destinationFragment get() = LuckyNumberFragment.newInstance()
}
- @Serializable
- object LuckyNumberHistory : Destination() {
- override val destinationType get() = Type.LUCKY_NUMBER_HISTORY
- override val destinationFragment get() = LuckyNumberHistoryFragment.newInstance()
- }
-
@Serializable
object More : Destination() {
override val destinationType get() = Type.MORE
@@ -137,16 +125,4 @@ sealed class Destination {
override val destinationType get() = Type.MESSAGE
override val destinationFragment get() = MessageFragment.newInstance()
}
-
- @Serializable
- object MobileDevice : Destination() {
- override val destinationType get() = Type.MOBILE_DEVICE
- override val destinationFragment get() = MobileDeviceFragment.newInstance()
- }
-
- @Serializable
- object Settings : Destination() {
- override val destinationType get() = Type.SETTINGS
- override val destinationFragment get() = SettingsFragment.newInstance()
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt
index f115372a5..051c93c95 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt
@@ -34,7 +34,6 @@ class AccountFragment : BaseFragment(R.layout.fragment_a
override val titleStringId = R.string.account_title
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt
index d6bc6154b..c3137ec58 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt
@@ -6,10 +6,8 @@ import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AlertDialog
-import androidx.core.os.bundleOf
import androidx.core.view.get
import androidx.core.view.isVisible
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Student
@@ -23,7 +21,6 @@ import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoFragment
import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView
import io.github.wulkanowy.utils.createNameInitialsDrawable
import io.github.wulkanowy.utils.nickOrName
-import io.github.wulkanowy.utils.serializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -40,12 +37,12 @@ class AccountDetailsFragment :
private const val ARGUMENT_KEY = "Data"
- fun newInstance(student: Student) = AccountDetailsFragment().apply {
- arguments = bundleOf(ARGUMENT_KEY to student)
- }
+ fun newInstance(student: Student) =
+ AccountDetailsFragment().apply {
+ arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, student) }
+ }
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -54,7 +51,7 @@ class AccountDetailsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentAccountDetailsBinding.bind(view)
- presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY))
+ presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student)
}
override fun initView() {
@@ -115,7 +112,7 @@ class AccountDetailsFragment :
override fun showLogoutConfirmDialog() {
context?.let {
- MaterialAlertDialogBuilder(it)
+ AlertDialog.Builder(it)
.setTitle(R.string.account_logout_student)
.setMessage(R.string.account_confirm)
.setPositiveButton(R.string.account_logout) { _, _ -> presenter.onLogoutConfirm() }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt
index 4229579c0..21a7a492d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt
@@ -1,16 +1,14 @@
package io.github.wulkanowy.ui.modules.account.accountedit
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
+import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.databinding.DialogAccountEditBinding
import io.github.wulkanowy.ui.base.BaseDialogFragment
-import io.github.wulkanowy.utils.serializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -26,21 +24,28 @@ class AccountEditDialog : BaseDialogFragment(), Accoun
private const val ARGUMENT_KEY = "student_with_semesters"
- fun newInstance(student: Student) = AccountEditDialog().apply {
- arguments = bundleOf(ARGUMENT_KEY to student)
- }
+ fun newInstance(student: Student) =
+ AccountEditDialog().apply {
+ arguments = Bundle().apply {
+ putSerializable(ARGUMENT_KEY, student)
+ }
+ }
}
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogAccountEditBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setStyle(STYLE_NO_TITLE, 0)
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View = DialogAccountEditBinding.inflate(inflater).apply { binding = this }.root
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY))
+ presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student)
}
override fun initView() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt
index 2d2dccec4..4279102e1 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt
@@ -1,11 +1,10 @@
package io.github.wulkanowy.ui.modules.account.accountquick
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
+import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.DialogAccountQuickBinding
@@ -14,7 +13,6 @@ import io.github.wulkanowy.ui.modules.account.AccountAdapter
import io.github.wulkanowy.ui.modules.account.AccountFragment
import io.github.wulkanowy.ui.modules.account.AccountItem
import io.github.wulkanowy.ui.modules.main.MainActivity
-import io.github.wulkanowy.utils.serializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -32,23 +30,27 @@ class AccountQuickDialog : BaseDialogFragment(), Acco
fun newInstance(studentsWithSemesters: List) =
AccountQuickDialog().apply {
- arguments = bundleOf(STUDENTS_ARGUMENT_KEY to studentsWithSemesters.toTypedArray())
+ arguments = Bundle().apply {
+ putSerializable(STUDENTS_ARGUMENT_KEY, studentsWithSemesters.toTypedArray())
+ }
}
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(
- DialogAccountQuickBinding.inflate(layoutInflater)
- .apply { binding = this }.root
- )
- .create()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setStyle(STYLE_NO_TITLE, 0)
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogAccountQuickBinding.inflate(inflater).apply { binding = this }.root
+
+ @Suppress("UNCHECKED_CAST")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- val studentsWithSemesters = requireArguments()
- .serializable>(STUDENTS_ARGUMENT_KEY).toList()
+ val studentsWithSemesters =
+ (requireArguments()[STUDENTS_ARGUMENT_KEY] as Array).toList()
presenter.onAttachView(this, studentsWithSemesters)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt
index c0026bee5..9b5c63e4c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt
@@ -1,20 +1,19 @@
package io.github.wulkanowy.ui.modules.attendance
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.databinding.DialogAttendanceBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
import io.github.wulkanowy.utils.descriptionRes
-import io.github.wulkanowy.utils.serializable
+import io.github.wulkanowy.utils.lifecycleAwareVariable
import io.github.wulkanowy.utils.toFormattedString
-@AndroidEntryPoint
-class AttendanceDialog : BaseDialogFragment() {
+class AttendanceDialog : DialogFragment() {
+
+ private var binding: DialogAttendanceBinding by lifecycleAwareVariable()
private lateinit var attendance: Attendance
@@ -23,20 +22,23 @@ class AttendanceDialog : BaseDialogFragment() {
private const val ARGUMENT_KEY = "Item"
fun newInstance(exam: Attendance) = AttendanceDialog().apply {
- arguments = bundleOf(ARGUMENT_KEY to exam)
+ arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- attendance = requireArguments().serializable(ARGUMENT_KEY)
+ setStyle(STYLE_NO_TITLE, 0)
+ arguments?.run {
+ attendance = getSerializable(ARGUMENT_KEY) as Attendance
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogAttendanceBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
- }
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogAttendanceBinding.inflate(inflater).apply { binding = this }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
index a73c2606e..6354b5e04 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
@@ -4,10 +4,10 @@ import android.content.DialogInterface.BUTTON_POSITIVE
import android.os.Bundle
import android.view.*
import android.view.View.*
+import androidx.appcompat.app.AlertDialog
import androidx.appcompat.view.ActionMode
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Attendance
@@ -84,7 +84,6 @@ class AttendanceFragment : BaseFragment(R.layout.frag
}
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -124,7 +123,7 @@ class AttendanceFragment : BaseFragment(R.layout.frag
attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() }
- attendanceNavContainer.elevation = requireContext().dpToPx(3f)
+ attendanceNavContainer.elevation = requireContext().dpToPx(8f)
}
}
@@ -228,7 +227,7 @@ class AttendanceFragment : BaseFragment(R.layout.frag
override fun showExcuseDialog() {
val dialogBinding = DialogExcuseBinding.inflate(LayoutInflater.from(context))
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(R.string.attendance_excuse_title)
.setView(dialogBinding.root)
.setNegativeButton(android.R.string.cancel) { _, _ -> }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt
deleted file mode 100644
index fa29df473..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.github.wulkanowy.ui.modules.auth
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.core.text.parseAsHtml
-import androidx.core.view.isVisible
-import androidx.core.widget.doOnTextChanged
-import dagger.hilt.android.AndroidEntryPoint
-import io.github.wulkanowy.R
-import io.github.wulkanowy.databinding.DialogAuthBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class AuthDialog : BaseDialogFragment(), AuthView {
-
- @Inject
- lateinit var presenter: AuthPresenter
-
- companion object {
- fun newInstance() = AuthDialog()
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setStyle(STYLE_NO_TITLE, R.style.FullScreenDialogStyle)
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- return DialogAuthBinding.inflate(inflater).apply { binding = this }.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- presenter.onAttachView(this)
-
- binding.authInput.doOnTextChanged { text, _, _, _ ->
- presenter.onPeselChange(text?.toString())
- }
-
- binding.authButton.setOnClickListener { presenter.authorize() }
- binding.authSuccessButton.setOnClickListener {
- activity?.recreate()
- dismiss()
- }
- binding.authButtonSkip.setOnClickListener { dismiss() }
- }
-
- override fun enableAuthButton(isEnabled: Boolean) {
- binding.authButton.isEnabled = isEnabled
- }
-
- override fun showProgress(show: Boolean) {
- binding.authProgress.isVisible = show
- }
-
- override fun showPeselError(show: Boolean) {
- binding.authInputLayout.error = getString(R.string.auth_api_error).takeIf { show }
- }
-
- override fun showInvalidPeselError(show: Boolean) {
- binding.authInputLayout.error = getString(R.string.auth_invalid_error).takeIf { show }
- }
-
- override fun showSuccess(show: Boolean) {
- binding.authSuccess.isVisible = show
- }
-
- override fun showContent(show: Boolean) {
- binding.authForm.isVisible = show
- }
-
- override fun showDescriptionWithName(name: String) {
- binding.authDescription.text = getString(R.string.auth_description, name).parseAsHtml()
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthPresenter.kt
deleted file mode 100644
index 8f579712b..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthPresenter.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-package io.github.wulkanowy.ui.modules.auth
-
-import io.github.wulkanowy.data.repositories.SemesterRepository
-import io.github.wulkanowy.data.repositories.StudentRepository
-import io.github.wulkanowy.ui.base.BasePresenter
-import io.github.wulkanowy.ui.base.ErrorHandler
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-class AuthPresenter @Inject constructor(
- private val semesterRepository: SemesterRepository,
- errorHandler: ErrorHandler,
- studentRepository: StudentRepository
-) : BasePresenter(errorHandler, studentRepository) {
-
- private var pesel: String = ""
-
- override fun onAttachView(view: AuthView) {
- super.onAttachView(view)
- view.enableAuthButton(pesel.length == 11)
- view.showSuccess(false)
- view.showProgress(false)
-
- loadName()
- }
-
- private fun loadName() {
- presenterScope.launch {
- runCatching { studentRepository.getCurrentStudent(false) }
- .onSuccess { view?.showDescriptionWithName(it.studentName) }
- .onFailure { errorHandler.dispatch(it) }
- }
- }
-
- fun onPeselChange(newPesel: String?) {
- pesel = newPesel.orEmpty()
-
- view?.enableAuthButton(pesel.length == 11)
- view?.showPeselError(false)
- view?.showInvalidPeselError(false)
- }
-
- fun authorize() {
- presenterScope.launch {
- view?.showProgress(true)
- view?.showContent(false)
-
- if (!isValidPESEL(pesel)) {
- view?.showInvalidPeselError(true)
- view?.showProgress(false)
- view?.showContent(true)
- return@launch
- }
-
- runCatching {
- val student = studentRepository.getCurrentStudent()
- val semester = semesterRepository.getCurrentSemester(student)
-
- val isSuccess = studentRepository.authorizePermission(student, semester, pesel)
- if (isSuccess) {
- studentRepository.refreshStudentName(student, semester)
- }
- isSuccess
- }
- .onFailure { errorHandler.dispatch(it) }
- .onSuccess {
- if (it) {
- view?.showSuccess(true)
- view?.showContent(false)
- view?.showPeselError(false)
- } else {
- view?.showSuccess(false)
- view?.showContent(true)
- view?.showPeselError(true)
- }
- }
-
- view?.showProgress(false)
- }
- }
-
- private fun isValidPESEL(peselString: String): Boolean {
- if (peselString.length != 11) {
- return false
- }
-
- val weights = intArrayOf(1, 3, 7, 9, 1, 3, 7, 9, 1, 3)
- var sum = 0
-
- for (i in 0 until 10) {
- sum += weights[i] * Character.getNumericValue(peselString[i])
- }
-
- sum %= 10
- sum = 10 - sum
- sum %= 10
-
- return sum == Character.getNumericValue(peselString[10])
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthView.kt
deleted file mode 100644
index d7e1917c2..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthView.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.github.wulkanowy.ui.modules.auth
-
-import io.github.wulkanowy.ui.base.BaseView
-
-interface AuthView : BaseView {
-
- fun enableAuthButton(isEnabled: Boolean)
-
- fun showProgress(show: Boolean)
-
- fun showPeselError(show: Boolean)
-
- fun showInvalidPeselError(show: Boolean)
-
- fun showSuccess(show: Boolean)
-
- fun showContent(show: Boolean)
-
- fun showDescriptionWithName(name: String)
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt
index c532377e1..477b762b9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt
@@ -1,20 +1,19 @@
package io.github.wulkanowy.ui.modules.conference
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
+import android.view.ViewGroup
import androidx.core.view.isVisible
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.databinding.DialogConferenceBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
-import io.github.wulkanowy.utils.serializable
+import io.github.wulkanowy.utils.lifecycleAwareVariable
import io.github.wulkanowy.utils.toFormattedString
-@AndroidEntryPoint
-class ConferenceDialog : BaseDialogFragment() {
+class ConferenceDialog : DialogFragment() {
+
+ private var binding: DialogConferenceBinding by lifecycleAwareVariable()
private lateinit var conference: Conference
@@ -23,20 +22,23 @@ class ConferenceDialog : BaseDialogFragment() {
private const val ARGUMENT_KEY = "item"
fun newInstance(conference: Conference) = ConferenceDialog().apply {
- arguments = bundleOf(ARGUMENT_KEY to conference)
+ arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, conference) }
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- conference = requireArguments().serializable(ARGUMENT_KEY)
+ setStyle(STYLE_NO_TITLE, 0)
+ arguments?.let {
+ conference = it.getSerializable(ARGUMENT_KEY) as Conference
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogConferenceBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
- }
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogConferenceBinding.inflate(inflater).also { binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -55,4 +57,4 @@ class ConferenceDialog : BaseDialogFragment() {
conferenceDialogAgendaTitle.isVisible = conference.agenda.isNotBlank()
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt
index 0cd3150c7..b9642b1c7 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt
@@ -16,7 +16,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class ConferenceFragment : BaseFragment(R.layout.fragment_conference),
- ConferenceView, MainView.TitledView, MainView.MainChildView {
+ ConferenceView, MainView.TitledView {
@Inject
lateinit var presenter: ConferencePresenter
@@ -109,14 +109,6 @@ class ConferenceFragment : BaseFragment(R.layout.frag
(activity as? MainActivity)?.showDialogFragment(ConferenceDialog.newInstance(conference))
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onFragmentReselected()
- }
-
- override fun resetView() {
- binding.conferenceRecycler.smoothScrollToPosition(0)
- }
-
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt
index 1178c7200..f53648930 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt
@@ -96,11 +96,4 @@ class ConferencePresenter @Inject constructor(
.onResourceError(errorHandler::dispatch)
.launch()
}
-
- fun onFragmentReselected() {
- Timber.i("Conference is reselected")
- if (view?.isViewEmpty == false) {
- view?.resetView()
- }
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt
index 3299a1f08..4f73394df 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt
@@ -28,6 +28,4 @@ interface ConferenceView : BaseView {
fun showContent(show: Boolean)
fun openConferenceDialog(conference: Conference)
-
- fun resetView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt
index ce17c7632..de0b4a6c9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt
@@ -11,7 +11,6 @@ import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.databinding.FragmentDashboardBinding
@@ -62,7 +61,6 @@ class DashboardFragment : BaseFragment(R.layout.fragme
fun newInstance() = DashboardFragment()
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -149,7 +147,7 @@ class DashboardFragment : BaseFragment(R.layout.fragme
val values = requireContext().resources.getStringArray(R.array.dashboard_tile_values)
val selectedItemsState = values.map { value -> selectedItems.any { it.name == value } }
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(R.string.pref_dashboard_appearance_tiles_title)
.setMultiChoiceItems(entries, selectedItemsState.toBooleanArray()) { _, _, _ -> }
.setPositiveButton(android.R.string.ok) { dialog, _ ->
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt
index ac2c896dc..22b0d267e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt
@@ -606,7 +606,7 @@ class DashboardPresenter @Inject constructor(
}
is Resource.Error -> {
Timber.i("Loading dashboard admin message result: An exception occurred")
- Timber.e(it.error)
+ errorHandler.dispatch(it.error)
updateData(
dashboardItem = DashboardItem.AdminMessages(
adminMessage = null,
@@ -748,7 +748,7 @@ class DashboardPresenter @Inject constructor(
itemsLoadedList.find { it.type == DashboardItem.Type.ACCOUNT }?.error != null
val isGeneralError =
filteredItems.none { it.error == null } && filteredItems.isNotEmpty() || isAccountItemError
- val firstError = itemsLoadedList.firstNotNullOfOrNull { it.error }
+ val firstError = itemsLoadedList.mapNotNull { it.error }.firstOrNull()
val filteredOriginalLoadedList =
dashboardItemLoadedList.filterNot { it.type == DashboardItem.Type.ACCOUNT }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardGradesAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardGradesAdapter.kt
index d821de537..d00df9d41 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardGradesAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardGradesAdapter.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.dashboard.adapters
-import android.content.res.ColorStateList
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
@@ -9,7 +8,6 @@ import io.github.wulkanowy.data.enums.GradeColorTheme
import io.github.wulkanowy.databinding.SubitemDashboardGradesBinding
import io.github.wulkanowy.databinding.SubitemDashboardSmallGradeBinding
import io.github.wulkanowy.utils.getBackgroundColor
-import io.github.wulkanowy.utils.getCompatColor
class DashboardGradesAdapter : RecyclerView.Adapter() {
@@ -39,9 +37,7 @@ class DashboardGradesAdapter : RecyclerView.Adapter(R.layout.fragme
fun newInstance() = LogViewerFragment()
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt
index d452d74a5..41adc008a 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt
@@ -1,22 +1,21 @@
package io.github.wulkanowy.ui.modules.exam
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.databinding.DialogExamBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
+import io.github.wulkanowy.utils.lifecycleAwareVariable
import io.github.wulkanowy.utils.openCalendarEventAdd
-import io.github.wulkanowy.utils.serializable
import io.github.wulkanowy.utils.toFormattedString
import java.time.LocalTime
-@AndroidEntryPoint
-class ExamDialog : BaseDialogFragment() {
+class ExamDialog : DialogFragment() {
+
+ private var binding: DialogExamBinding by lifecycleAwareVariable()
private lateinit var exam: Exam
@@ -25,20 +24,23 @@ class ExamDialog : BaseDialogFragment() {
private const val ARGUMENT_KEY = "Item"
fun newInstance(exam: Exam) = ExamDialog().apply {
- arguments = bundleOf(ARGUMENT_KEY to exam)
+ arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- exam = requireArguments().serializable(ARGUMENT_KEY)
+ setStyle(STYLE_NO_TITLE, 0)
+ arguments?.run {
+ exam = getSerializable(ARGUMENT_KEY) as Exam
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogExamBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
- }
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogExamBinding.inflate(inflater).apply { binding = this }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt
index 0123e2340..ddd0e4a19 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt
@@ -2,7 +2,9 @@ package io.github.wulkanowy.ui.modules.exam
import android.os.Bundle
import android.view.View
-import android.view.View.*
+import android.view.View.GONE
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -18,7 +20,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class ExamFragment : BaseFragment(R.layout.fragment_exam), ExamView,
- MainView.TitledView, MainView.MainChildView {
+ MainView.TitledView {
@Inject
lateinit var presenter: ExamPresenter
@@ -62,7 +64,7 @@ class ExamFragment : BaseFragment(R.layout.fragment_exam),
examPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
examNextButton.setOnClickListener { presenter.onNextWeek() }
- examNavContainer.elevation = requireContext().dpToPx(3f)
+ examNavContainer.elevation = requireContext().dpToPx(8f)
}
}
@@ -124,14 +126,6 @@ class ExamFragment : BaseFragment(R.layout.fragment_exam),
(activity as? MainActivity)?.showDialogFragment(ExamDialog.newInstance(exam))
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onViewReselected()
- }
-
- override fun resetView() {
- binding.examRecycler.smoothScrollToPosition(0)
- }
-
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt
index 858140728..99b0bcb87 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt
@@ -175,17 +175,4 @@ class ExamPresenter @Inject constructor(
)
}
}
-
- fun onViewReselected() {
- Timber.i("Exam view is reselected")
-
- baseDate = now().nextOrSameSchoolDay
-
- if (currentDate != baseDate) {
- reloadView(baseDate)
- loadData()
- } else if (view?.isViewEmpty == false) {
- view?.resetView()
- }
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt
index 677fac40e..45b9e788c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt
@@ -34,6 +34,4 @@ interface ExamView : BaseView {
fun showPreButton(show: Boolean)
fun showExamDialog(exam: Exam)
-
- fun resetView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt
index 2d63aae4d..b6733d4f2 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt
@@ -12,92 +12,70 @@ import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.*
import io.github.wulkanowy.utils.calcAverage
import io.github.wulkanowy.utils.changeModifier
-import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flatMapLatest
import javax.inject.Inject
-@OptIn(ExperimentalCoroutinesApi::class)
+@OptIn(FlowPreview::class)
class GradeAverageProvider @Inject constructor(
private val semesterRepository: SemesterRepository,
private val gradeRepository: GradeRepository,
private val preferencesRepository: PreferencesRepository
) {
- private data class AverageCalcParams(
- val gradeAverageMode: GradeAverageMode,
- val forceAverageCalc: Boolean,
- val isOptionalArithmeticAverage: Boolean,
- val plusModifier: Double,
- val minusModifier: Double,
- )
+ private val plusModifier get() = preferencesRepository.gradePlusModifier
- fun getGradesDetailsWithAverage(
- student: Student,
- semesterId: Int,
- forceRefresh: Boolean
- ): Flow>> = combine(
- flow = preferencesRepository.gradeAverageModeFlow,
- flow2 = preferencesRepository.gradeAverageForceCalcFlow,
- flow3 = preferencesRepository.isOptionalArithmeticAverageFlow,
- flow4 = preferencesRepository.gradePlusModifierFlow,
- flow5 = preferencesRepository.gradeMinusModifierFlow,
- ) { gradeAverageMode, forceAverageCalc, isOptionalArithmeticAverage, plusModifier, minusModifier ->
- AverageCalcParams(
- gradeAverageMode = gradeAverageMode,
- forceAverageCalc = forceAverageCalc,
- isOptionalArithmeticAverage = isOptionalArithmeticAverage,
- plusModifier = plusModifier,
- minusModifier = minusModifier,
- )
- }.flatMapLatest { params ->
+ private val minusModifier get() = preferencesRepository.gradeMinusModifier
+
+ private val isOptionalArithmeticAverage get() = preferencesRepository.isOptionalArithmeticAverage
+
+ fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean) =
flatResourceFlow {
val semesters = semesterRepository.getSemesters(student)
- when (params.gradeAverageMode) {
+
+ when (preferencesRepository.gradeAverageMode) {
ONE_SEMESTER -> getGradeSubjects(
student = student,
semester = semesters.single { it.semesterId == semesterId },
- forceRefresh = forceRefresh,
- params = params,
+ forceRefresh = forceRefresh
)
BOTH_SEMESTERS -> calculateCombinedAverage(
student = student,
semesters = semesters,
semesterId = semesterId,
forceRefresh = forceRefresh,
- config = params,
+ averageMode = BOTH_SEMESTERS
)
ALL_YEAR -> calculateCombinedAverage(
student = student,
semesters = semesters,
semesterId = semesterId,
forceRefresh = forceRefresh,
- config = params,
+ averageMode = ALL_YEAR
)
}
- }
- }.distinctUntilChanged()
+ }.distinctUntilChanged()
private fun calculateCombinedAverage(
student: Student,
semesters: List,
semesterId: Int,
forceRefresh: Boolean,
- config: AverageCalcParams,
+ averageMode: GradeAverageMode
): Flow>> {
+ val isGradeAverageForceCalc = preferencesRepository.gradeAverageForceCalc
val selectedSemester = semesters.single { it.semesterId == semesterId }
val firstSemester =
semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
val selectedSemesterGradeSubjects =
- getGradeSubjects(student, selectedSemester, forceRefresh, config)
+ getGradeSubjects(student, selectedSemester, forceRefresh)
if (selectedSemester == firstSemester) return selectedSemesterGradeSubjects
- val firstSemesterGradeSubjects =
- getGradeSubjects(student, firstSemester, forceRefresh, config)
+ val firstSemesterGradeSubjects = getGradeSubjects(student, firstSemester, forceRefresh)
return selectedSemesterGradeSubjects.combine(firstSemesterGradeSubjects) { secondSemesterGradeSubject, firstSemesterGradeSubject ->
if (firstSemesterGradeSubject.errorOrNull != null) {
@@ -113,21 +91,21 @@ class GradeAverageProvider @Inject constructor(
val firstSemesterSubject = firstSemesterGradeSubject.dataOrNull.orEmpty()
.singleOrNull { it.subject == secondSemesterSubject.subject }
- val updatedAverage = if (config.gradeAverageMode == ALL_YEAR) {
+ val updatedAverage = if (averageMode == ALL_YEAR) {
calculateAllYearAverage(
student = student,
isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester,
+ isGradeAverageForceCalc = isGradeAverageForceCalc,
secondSemesterSubject = secondSemesterSubject,
- firstSemesterSubject = firstSemesterSubject,
- config = config,
+ firstSemesterSubject = firstSemesterSubject
)
} else {
calculateBothSemestersAverage(
student = student,
isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester,
+ isGradeAverageForceCalc = isGradeAverageForceCalc,
secondSemesterSubject = secondSemesterSubject,
- firstSemesterSubject = firstSemesterSubject,
- config = config
+ firstSemesterSubject = firstSemesterSubject
)
}
secondSemesterSubject.copy(average = updatedAverage)
@@ -139,17 +117,17 @@ class GradeAverageProvider @Inject constructor(
private fun calculateAllYearAverage(
student: Student,
isAnyVulcanAverage: Boolean,
+ isGradeAverageForceCalc: Boolean,
secondSemesterSubject: GradeSubject,
- firstSemesterSubject: GradeSubject?,
- config: AverageCalcParams,
- ) = if (!isAnyVulcanAverage || config.forceAverageCalc) {
- val updatedSecondSemesterGrades = secondSemesterSubject.grades
- .updateModifiers(student, config)
- val updatedFirstSemesterGrades = firstSemesterSubject?.grades
- ?.updateModifiers(student, config).orEmpty()
+ firstSemesterSubject: GradeSubject?
+ ) = if (!isAnyVulcanAverage || isGradeAverageForceCalc) {
+ val updatedSecondSemesterGrades =
+ secondSemesterSubject.grades.updateModifiers(student)
+ val updatedFirstSemesterGrades =
+ firstSemesterSubject?.grades?.updateModifiers(student).orEmpty()
(updatedSecondSemesterGrades + updatedFirstSemesterGrades).calcAverage(
- config.isOptionalArithmeticAverage
+ isOptionalArithmeticAverage
)
} else {
secondSemesterSubject.average
@@ -158,35 +136,32 @@ class GradeAverageProvider @Inject constructor(
private fun calculateBothSemestersAverage(
student: Student,
isAnyVulcanAverage: Boolean,
+ isGradeAverageForceCalc: Boolean,
secondSemesterSubject: GradeSubject,
- firstSemesterSubject: GradeSubject?,
- config: AverageCalcParams,
- ): Double {
- return if (!isAnyVulcanAverage || config.forceAverageCalc) {
- val divider = if (secondSemesterSubject.grades.any { it.weightValue > .0 }) 2 else 1
- val secondSemesterAverage = secondSemesterSubject.grades
- .updateModifiers(student, config)
- .calcAverage(config.isOptionalArithmeticAverage)
- val firstSemesterAverage = firstSemesterSubject?.grades
- ?.updateModifiers(student, config)
- ?.calcAverage(config.isOptionalArithmeticAverage) ?: secondSemesterAverage
+ firstSemesterSubject: GradeSubject?
+ ): Double = if (!isAnyVulcanAverage || isGradeAverageForceCalc) {
+ val divider = if (secondSemesterSubject.grades.any { it.weightValue > .0 }) 2 else 1
- (secondSemesterAverage + firstSemesterAverage) / divider
- } else {
- val divider = if (secondSemesterSubject.average > 0) 2 else 1
+ val secondSemesterAverage = secondSemesterSubject.grades.updateModifiers(student)
+ .calcAverage(isOptionalArithmeticAverage)
+ val firstSemesterAverage = firstSemesterSubject?.grades?.updateModifiers(student)
+ ?.calcAverage(isOptionalArithmeticAverage) ?: secondSemesterAverage
- secondSemesterSubject.average.plus(
- (firstSemesterSubject?.average ?: secondSemesterSubject.average)
- ) / divider
- }
+ (secondSemesterAverage + firstSemesterAverage) / divider
+ } else {
+ val divider = if (secondSemesterSubject.average > 0) 2 else 1
+
+ (secondSemesterSubject.average + (firstSemesterSubject?.average
+ ?: secondSemesterSubject.average)) / divider
}
private fun getGradeSubjects(
student: Student,
semester: Semester,
- forceRefresh: Boolean,
- params: AverageCalcParams,
+ forceRefresh: Boolean
): Flow>> {
+ val isGradeAverageForceCalc = preferencesRepository.gradeAverageForceCalc
+
return gradeRepository.getGrades(student, semester, forceRefresh = forceRefresh)
.mapResourceData { res ->
val (details, summaries) = res
@@ -197,15 +172,13 @@ class GradeAverageProvider @Inject constructor(
student = student,
semester = semester,
grades = allGrades.toList(),
- calcAverage = isAnyAverage,
- params = params,
+ calcAverage = isAnyAverage
).map { summary ->
val grades = allGrades[summary.subject].orEmpty()
GradeSubject(
subject = summary.subject,
- average = if (!isAnyAverage || params.forceAverageCalc) {
- grades.updateModifiers(student, params)
- .calcAverage(params.isOptionalArithmeticAverage)
+ average = if (!isAnyAverage || isGradeAverageForceCalc) {
+ grades.updateModifiers(student).calcAverage(isOptionalArithmeticAverage)
} else summary.average,
points = summary.pointsSum,
summary = summary,
@@ -222,8 +195,7 @@ class GradeAverageProvider @Inject constructor(
student: Student,
semester: Semester,
grades: List>>,
- calcAverage: Boolean,
- params: AverageCalcParams,
+ calcAverage: Boolean
): List {
if (isNotEmpty() && size > grades.size) return this
@@ -239,16 +211,15 @@ class GradeAverageProvider @Inject constructor(
proposedPoints = "",
finalPoints = "",
pointsSum = "",
- average = if (calcAverage) details.updateModifiers(student, params)
- .calcAverage(params.isOptionalArithmeticAverage) else .0
+ average = if (calcAverage) details.updateModifiers(student)
+ .calcAverage(isOptionalArithmeticAverage) else .0
)
}
}
- private fun List.updateModifiers(
- student: Student,
- params: AverageCalcParams,
- ): List = if (student.loginMode == Sdk.Mode.SCRAPPER.name) {
- map { it.changeModifier(params.plusModifier, params.minusModifier) }
- } else this
+ private fun List.updateModifiers(student: Student): List {
+ return if (student.loginMode == Sdk.Mode.SCRAPPER.name) {
+ map { it.changeModifier(plusModifier, minusModifier) }
+ } else this
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt
index 7ce07eb68..0a8561eec 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt
@@ -8,7 +8,6 @@ import android.view.View
import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import androidx.appcompat.app.AlertDialog
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -52,7 +51,6 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade
override val currentPageIndex get() = binding.gradeViewPager.currentItem
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -142,7 +140,7 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade
val choices = semesters.map { getString(R.string.grade_semester, it.semesterName) }
.toTypedArray()
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setSingleChoiceItems(choices, selectedIndex) { dialog, which ->
presenter.onSemesterSelected(which)
dialog.dismiss()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt
index 15b5db031..e5c3bb63e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt
@@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.modules.grade.details
import android.annotation.SuppressLint
-import android.content.res.ColorStateList
import android.content.res.Resources
import android.view.LayoutInflater
import android.view.View
@@ -18,10 +17,9 @@ import io.github.wulkanowy.databinding.HeaderGradeDetailsBinding
import io.github.wulkanowy.databinding.ItemGradeDetailsBinding
import io.github.wulkanowy.ui.base.BaseExpandableAdapter
import io.github.wulkanowy.utils.getBackgroundColor
-import io.github.wulkanowy.utils.getCompatColor
import io.github.wulkanowy.utils.toFormattedString
import timber.log.Timber
-import java.util.*
+import java.util.BitSet
import javax.inject.Inject
class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter() {
@@ -205,9 +203,7 @@ class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter grade.description
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt
index 39f72f8bc..34594111f 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt
@@ -1,23 +1,21 @@
package io.github.wulkanowy.ui.modules.grade.details
-import android.app.Dialog
-import android.content.res.ColorStateList
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
-import androidx.core.content.ContextCompat
-import androidx.core.os.bundleOf
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.enums.GradeColorTheme
import io.github.wulkanowy.databinding.DialogGradeBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
import io.github.wulkanowy.utils.*
-@AndroidEntryPoint
-class GradeDetailsDialog : BaseDialogFragment() {
+
+class GradeDetailsDialog : DialogFragment() {
+
+ private var binding: DialogGradeBinding by lifecycleAwareVariable()
private lateinit var grade: Grade
@@ -29,25 +27,29 @@ class GradeDetailsDialog : BaseDialogFragment() {
private const val COLOR_THEME_KEY = "Theme"
- fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = GradeDetailsDialog().apply {
- arguments = bundleOf(
- ARGUMENT_KEY to grade,
- COLOR_THEME_KEY to colorTheme
- )
- }
+ fun newInstance(grade: Grade, colorTheme: GradeColorTheme) =
+ GradeDetailsDialog().apply {
+ arguments = Bundle().apply {
+ putSerializable(ARGUMENT_KEY, grade)
+ putSerializable(COLOR_THEME_KEY, colorTheme)
+ }
+ }
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- grade = requireArguments().serializable(ARGUMENT_KEY)
- gradeColorTheme = requireArguments().serializable(COLOR_THEME_KEY)
+ setStyle(STYLE_NO_TITLE, 0)
+ arguments?.run {
+ grade = getSerializable(ARGUMENT_KEY) as Grade
+ gradeColorTheme = getSerializable(COLOR_THEME_KEY) as GradeColorTheme
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogGradeBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
- }
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogGradeBinding.inflate(inflater).apply { binding = this }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -55,9 +57,10 @@ class GradeDetailsDialog : BaseDialogFragment() {
with(binding) {
gradeDialogSubject.text = grade.subject
- gradeDialogWeightValue.text = grade.weight
- gradeDialogWeightLayout.backgroundTintList =
- ColorStateList.valueOf(requireContext().getCompatColor(grade.getGradeColor()))
+ gradeDialogColorAndWeightValue.run {
+ text = context.getString(R.string.grade_weight_value, grade.weight)
+ setBackgroundResource(grade.getGradeColor())
+ }
gradeDialogDateValue.text = grade.date.toFormattedString()
gradeDialogColorValue.text = getString(grade.colorStringId)
@@ -71,12 +74,7 @@ class GradeDetailsDialog : BaseDialogFragment() {
gradeDialogValue.run {
text = grade.entry
- backgroundTintList = ColorStateList.valueOf(
- ContextCompat.getColor(
- requireContext(),
- grade.getBackgroundColor(gradeColorTheme)
- )
- )
+ setBackgroundResource(grade.getBackgroundColor(gradeColorTheme))
}
gradeDialogTeacherValue.text = grade.teacher.ifBlank { getString(R.string.all_no_data) }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt
index 23d767a6f..81f3226ad 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt
@@ -5,7 +5,9 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
-import android.view.View.*
+import android.view.View.GONE
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -40,7 +42,6 @@ class GradeDetailsFragment :
override val isViewEmpty
get() = gradeDetailsAdapter.itemCount == 0
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt
index 3fce8d57e..fd0ac5471 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt
@@ -116,9 +116,7 @@ class GradeStatisticsAdapter @Inject constructor() :
}
)
- binding.gradeStatisticsTypeSwitch.addOnButtonCheckedListener { _, checkedId, isChecked ->
- if (!isChecked) return@addOnButtonCheckedListener
-
+ binding.gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
currentDataType = when (checkedId) {
R.id.gradeStatisticsTypePartial -> GradeStatisticsItem.DataType.PARTIAL
R.id.gradeStatisticsTypeSemester -> GradeStatisticsItem.DataType.SEMESTER
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt
index edc384c5e..2af59c011 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt
@@ -15,7 +15,6 @@ import io.github.wulkanowy.ui.modules.grade.GradeFragment
import io.github.wulkanowy.ui.modules.grade.GradeView
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor
-import io.github.wulkanowy.utils.serializable
import io.github.wulkanowy.utils.setOnItemSelectedListener
import javax.inject.Inject
@@ -49,8 +48,8 @@ class GradeStatisticsFragment :
messageContainer = binding.gradeStatisticsRecycler
presenter.onAttachView(
view = this,
- type = savedInstanceState?.serializable(SAVED_CHART_TYPE),
- subjectName = savedInstanceState?.serializable(SAVED_SUBJECT_NAME),
+ type = savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType,
+ subjectName = savedInstanceState?.getSerializable(SAVED_SUBJECT_NAME) as? String,
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt
index abd0b13c4..3810902ff 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt
@@ -7,7 +7,6 @@ import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.GradeSummary
@@ -119,7 +118,7 @@ class GradeSummaryFragment :
}
override fun showCalculatedAverageHelpDialog() {
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(R.string.grade_summary_calculated_average_help_dialog_title)
.setMessage(R.string.grade_summary_calculated_average_help_dialog_message)
.setPositiveButton(R.string.all_close) { _, _ -> }
@@ -127,7 +126,7 @@ class GradeSummaryFragment :
}
override fun showFinalAverageHelpDialog() {
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(R.string.grade_summary_final_average_help_dialog_title)
.setMessage(R.string.grade_summary_final_average_help_dialog_message)
.setPositiveButton(R.string.all_close) { _, _ -> }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt
index 0381acf35..d4eaade2c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt
@@ -21,7 +21,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class HomeworkFragment : BaseFragment(R.layout.fragment_homework),
- HomeworkView, MainView.TitledView, MainView.MainChildView {
+ HomeworkView, MainView.TitledView {
@Inject
lateinit var presenter: HomeworkPresenter
@@ -67,7 +67,7 @@ class HomeworkFragment : BaseFragment(R.layout.fragment
openAddHomeworkButton.setOnClickListener { presenter.onHomeworkAddButtonClicked() }
- homeworkNavContainer.elevation = requireContext().dpToPx(3f)
+ homeworkNavContainer.elevation = requireContext().dpToPx(8f)
}
}
@@ -133,14 +133,6 @@ class HomeworkFragment : BaseFragment(R.layout.fragment
(activity as? MainActivity)?.showDialogFragment(HomeworkAddDialog())
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onViewReselected()
- }
-
- override fun resetView() {
- binding.homeworkRecycler.smoothScrollToPosition(0)
- }
-
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt
index 6b263e26d..2ac552b41 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt
@@ -177,21 +177,8 @@ class HomeworkPresenter @Inject constructor(
showNextButton(!currentDate.plusDays(7).isHolidays)
updateNavigationWeek(
"${currentDate.monday.toFormattedString("dd.MM")} - " +
- currentDate.sunday.toFormattedString("dd.MM")
+ currentDate.sunday.toFormattedString("dd.MM")
)
}
}
-
- fun onViewReselected() {
- Timber.i("Homework view is reselected")
-
- baseDate = LocalDate.now().nextOrSameSchoolDay
-
- if (currentDate != baseDate) {
- reloadView(baseDate)
- loadData()
- } else if (view?.isViewEmpty == false) {
- view?.resetView()
- }
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt
index 56ba6c89e..7c05ab865 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt
@@ -36,6 +36,4 @@ interface HomeworkView : BaseView {
fun showHomeworkDialog(homework: Homework)
fun showAddHomeworkDialog()
-
- fun resetView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt
index c51370ea7..c2aff2b13 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt
@@ -1,10 +1,10 @@
package io.github.wulkanowy.ui.modules.homework.add
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.databinding.DialogHomeworkAddBinding
@@ -21,15 +21,20 @@ class HomeworkAddDialog : BaseDialogFragment(), Homewo
@Inject
lateinit var presenter: HomeworkAddPresenter
- //todo: move it to presenter
+ // todo: move it to presenter
private var date: LocalDate? = null
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogHomeworkAddBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setStyle(STYLE_NO_TITLE, 0)
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogHomeworkAddBinding.inflate(inflater).apply { binding = this }.root
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter.onAttachView(this)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt
index 1ad2a0e32..e03707a5c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt
@@ -31,8 +31,14 @@ class HomeworkDetailsAdapter @Inject constructor() :
attachments = value?.attachments.orEmpty()
}
+ var isHomeworkFullscreen = false
+
var onAttachmentClickListener: (url: String) -> Unit = {}
+ var onFullScreenClickListener = {}
+
+ var onFullScreenExitClickListener = {}
+
var onDeleteClickListener: (homework: Homework) -> Unit = {}
override fun getItemCount() = 1 + if (attachments.isNotEmpty()) attachments.size + 1 else 0
@@ -76,6 +82,18 @@ class HomeworkDetailsAdapter @Inject constructor() :
homeworkDialogTeacher.text = homework?.teacher.ifNullOrBlank { noDataString }
homeworkDialogContent.text = homework?.content.ifNullOrBlank { noDataString }
homeworkDialogDelete.visibility = if (homework?.isAddedByUser == true) VISIBLE else GONE
+ homeworkDialogFullScreen.visibility = if (isHomeworkFullscreen) GONE else VISIBLE
+ homeworkDialogFullScreenExit.visibility = if (isHomeworkFullscreen) VISIBLE else GONE
+ homeworkDialogFullScreen.setOnClickListener {
+ homeworkDialogFullScreen.visibility = GONE
+ homeworkDialogFullScreenExit.visibility = VISIBLE
+ onFullScreenClickListener()
+ }
+ homeworkDialogFullScreenExit.setOnClickListener {
+ homeworkDialogFullScreen.visibility = VISIBLE
+ homeworkDialogFullScreenExit.visibility = GONE
+ onFullScreenExitClickListener()
+ }
homeworkDialogDelete.setOnClickListener {
onDeleteClickListener(homework!!)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt
index 1f9bc881b..f9d463510 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt
@@ -1,19 +1,19 @@
package io.github.wulkanowy.ui.modules.homework.details
import android.annotation.SuppressLint
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
+import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.databinding.DialogHomeworkBinding
import io.github.wulkanowy.ui.base.BaseDialogFragment
import io.github.wulkanowy.utils.openInternetBrowser
-import io.github.wulkanowy.utils.serializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -35,20 +35,23 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew
private const val ARGUMENT_KEY = "Item"
fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply {
- arguments = bundleOf(ARGUMENT_KEY to homework)
+ arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) }
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- homework = requireArguments().serializable(ARGUMENT_KEY)
+ setStyle(STYLE_NO_TITLE, 0)
+ arguments?.run {
+ homework = getSerializable(ARGUMENT_KEY) as Homework
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogHomeworkBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
- }
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogHomeworkBinding.inflate(inflater).apply { binding = this }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -64,11 +67,26 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew
homeworkDialogClose.setOnClickListener { dismiss() }
}
+ if (presenter.isHomeworkFullscreen) {
+ dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT)
+ } else {
+ dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT)
+ }
+
with(binding.homeworkDialogRecycler) {
layoutManager = LinearLayoutManager(context)
adapter = detailsAdapter.apply {
onAttachmentClickListener = { context.openInternetBrowser(it, ::showMessage) }
+ onFullScreenClickListener = {
+ dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT)
+ presenter.isHomeworkFullscreen = true
+ }
+ onFullScreenExitClickListener = {
+ dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT)
+ presenter.isHomeworkFullscreen = false
+ }
onDeleteClickListener = { homework -> presenter.deleteHomework(homework) }
+ isHomeworkFullscreen = presenter.isHomeworkFullscreen
homework = this@HomeworkDetailsDialog.homework
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt
index 84933f06b..e76df6bd0 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt
@@ -5,6 +5,7 @@ import io.github.wulkanowy.data.logResourceStatus
import io.github.wulkanowy.data.onResourceError
import io.github.wulkanowy.data.onResourceSuccess
import io.github.wulkanowy.data.repositories.HomeworkRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.resourceFlow
import io.github.wulkanowy.ui.base.BasePresenter
@@ -18,8 +19,15 @@ class HomeworkDetailsPresenter @Inject constructor(
studentRepository: StudentRepository,
private val homeworkRepository: HomeworkRepository,
private val analytics: AnalyticsHelper,
+ private val preferencesRepository: PreferencesRepository
) : BasePresenter(errorHandler, studentRepository) {
+ var isHomeworkFullscreen
+ get() = preferencesRepository.isHomeworkFullscreen
+ set(value) {
+ preferencesRepository.isHomeworkFullscreen = value
+ }
+
override fun onAttachView(view: HomeworkDetailsView) {
super.onAttachView(view)
view.initView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt
index c17c92efd..aac60b56d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt
@@ -2,17 +2,13 @@ package io.github.wulkanowy.ui.modules.login
import android.content.Context
import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Bundle
import android.view.MenuItem
-import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE
import androidx.fragment.app.commit
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.ActivityLoginBinding
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
@@ -20,9 +16,6 @@ import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
-import io.github.wulkanowy.ui.modules.main.MainActivity
-import io.github.wulkanowy.ui.modules.notifications.NotificationsFragment
-import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.UpdateHelper
import javax.inject.Inject
@@ -35,9 +28,6 @@ class LoginActivity : BaseActivity(), Logi
@Inject
lateinit var updateHelper: UpdateHelper
- @Inject
- lateinit var appInfo: AppInfo
-
companion object {
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
}
@@ -65,7 +55,7 @@ class LoginActivity : BaseActivity(), Logi
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) onBackPressedDispatcher.onBackPressed()
+ if (item.itemId == android.R.id.home) onBackPressed()
return true
}
@@ -77,24 +67,8 @@ class LoginActivity : BaseActivity(), Logi
openFragment(LoginSymbolFragment.newInstance(loginData))
}
- fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
- openFragment(LoginStudentSelectFragment.newInstance(loginData, registerUser))
- }
-
- fun navigateToNotifications() {
- val isNotificationsPermissionRequired = appInfo.systemVersion >= TIRAMISU
- val isPermissionGranted = ContextCompat.checkSelfPermission(
- this, "android.permission.POST_NOTIFICATIONS"
- ) == PackageManager.PERMISSION_GRANTED
-
- if (isNotificationsPermissionRequired && !isPermissionGranted) {
- openFragment(NotificationsFragment.newInstance(), clearBackStack = true)
- } else navigateToFinish()
- }
-
- fun navigateToFinish() {
- startActivity(MainActivity.getStartIntent(this))
- finish()
+ fun navigateToStudentSelect(studentsWithSemesters: List) {
+ openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters))
}
fun onAdvancedLoginClick() {
@@ -106,8 +80,6 @@ class LoginActivity : BaseActivity(), Logi
}
private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) {
- supportFragmentManager.popBackStack(fragment::class.java.name, POP_BACK_STACK_INCLUSIVE)
-
supportFragmentManager.commit {
replace(R.id.loginContainer, fragment)
setReorderingAllowed(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt
index ae6c22492..5d4743589 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt
@@ -6,5 +6,4 @@ data class LoginData(
val login: String,
val password: String,
val baseUrl: String,
- val symbol: String?,
) : Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt
index 4f709438a..37ab71dce 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt
@@ -4,15 +4,13 @@ import android.content.Context
import android.database.sqlite.SQLiteConstraintException
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.R
-import io.github.wulkanowy.sdk.hebe.exception.InvalidPinException
-import io.github.wulkanowy.sdk.hebe.exception.InvalidTokenException
-import io.github.wulkanowy.sdk.hebe.exception.TokenDeadException
-import io.github.wulkanowy.sdk.hebe.exception.UnknownTokenException
+import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException
+import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException
+import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException
+import io.github.wulkanowy.sdk.mobile.exception.TokenDeadException
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
import io.github.wulkanowy.ui.base.ErrorHandler
import javax.inject.Inject
-import io.github.wulkanowy.sdk.hebe.exception.InvalidSymbolException as InvalidHebeSymbolException
-import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException as InvalidScrapperSymbolException
class LoginErrorHandler @Inject constructor(
@ApplicationContext context: Context,
@@ -34,11 +32,9 @@ class LoginErrorHandler @Inject constructor(
is BadCredentialsException -> onBadCredentials(error.message)
is SQLiteConstraintException -> onStudentDuplicate(resources.getString(R.string.login_duplicate_student))
is TokenDeadException -> onInvalidToken(resources.getString(R.string.login_expired_token))
- is UnknownTokenException,
is InvalidTokenException -> onInvalidToken(resources.getString(R.string.login_invalid_token))
is InvalidPinException -> onInvalidPin(resources.getString(R.string.login_invalid_pin))
- is InvalidScrapperSymbolException,
- is InvalidHebeSymbolException -> onInvalidSymbol(resources.getString(R.string.login_invalid_symbol))
+ is InvalidSymbolException -> onInvalidSymbol(resources.getString(R.string.login_invalid_symbol))
else -> super.proceed(error)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt
index ead2d71af..37dcb38b3 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt
@@ -8,7 +8,7 @@ import android.widget.ArrayAdapter
import androidx.core.widget.doOnTextChanged
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.base.BaseFragment
@@ -34,9 +34,9 @@ class LoginAdvancedFragment :
override val formLoginType: String
get() = when (binding.loginTypeSwitch.checkedRadioButtonId) {
- R.id.loginTypeApi -> Sdk.Mode.HEBE.name
- R.id.loginTypeScrapper -> Sdk.Mode.SCRAPPER.name
- else -> Sdk.Mode.HYBRID.name
+ R.id.loginTypeApi -> "API"
+ R.id.loginTypeScrapper -> "SCRAPPER"
+ else -> "HYBRID"
}
override val formUsernameValue: String
@@ -99,7 +99,7 @@ class LoginAdvancedFragment :
loginTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
presenter.onLoginModeSelected(
when (checkedId) {
- R.id.loginTypeApi -> Sdk.Mode.HEBE
+ R.id.loginTypeApi -> Sdk.Mode.API
R.id.loginTypeScrapper -> Sdk.Mode.SCRAPPER
else -> Sdk.Mode.HYBRID
}
@@ -327,8 +327,8 @@ class LoginAdvancedFragment :
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
}
- override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
- (activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
+ override fun navigateToStudentSelect(studentsWithSemesters: List) {
+ (activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
}
override fun onResume() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt
index ab56bd786..1b42c6c52 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt
@@ -1,13 +1,12 @@
package io.github.wulkanowy.ui.modules.login.advanced
import io.github.wulkanowy.data.Resource
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.logResourceStatus
import io.github.wulkanowy.data.onResourceNotLoading
-import io.github.wulkanowy.data.pojos.RegisterUser
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.resourceFlow
import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
@@ -92,16 +91,14 @@ class LoginAdvancedPresenter @Inject constructor(
fun onLoginModeSelected(type: Sdk.Mode) {
view?.run {
when (type) {
- Sdk.Mode.HEBE -> {
+ Sdk.Mode.API -> {
showOnlyMobileApiModeInputs()
showMobileApiWarningMessage()
}
-
Sdk.Mode.SCRAPPER -> {
showOnlyScrapperModeInputs()
showScraperWarningMessage()
}
-
Sdk.Mode.HYBRID -> {
showOnlyHybridModeInputs()
showHybridWarningMessage()
@@ -142,29 +139,23 @@ class LoginAdvancedPresenter @Inject constructor(
showProgress(true)
showContent(false)
}
-
is Resource.Success -> {
analytics.logEvent(
"registration_form",
- "success" to true,
- "scrapperBaseUrl" to view?.formHostValue.orEmpty(),
- "error" to "No error"
- )
- val loginData = LoginData(
- login = view?.formUsernameValue.orEmpty().trim(),
- password = view?.formPassValue.orEmpty().trim(),
- baseUrl = view?.formHostValue.orEmpty().trim(),
- symbol = view?.formSymbolValue.orEmpty().trim().getNormalizedSymbol(),
- )
- when (it.data.symbols.size) {
- 0 -> view?.navigateToSymbol(loginData)
- else -> view?.navigateToStudentSelect(
- loginData = loginData,
- registerUser = it.data,
- )
- }
+ "success" to true,
+ "students" to it.data.size,
+ "error" to "No error"
+ )
+ val loginData = LoginData(
+ login = view?.formUsernameValue.orEmpty().trim(),
+ password = view?.formPassValue.orEmpty().trim(),
+ baseUrl = view?.formHostValue.orEmpty().trim()
+ )
+ when (it.data.size) {
+ 0 -> view?.navigateToSymbol(loginData)
+ else -> view?.navigateToStudentSelect(it.data)
+ }
}
-
is Resource.Error -> {
analytics.logEvent(
"registration_form",
@@ -182,7 +173,7 @@ class LoginAdvancedPresenter @Inject constructor(
}.launch("login")
}
- private suspend fun getStudentsAppropriatesToLoginType(): RegisterUser {
+ private suspend fun getStudentsAppropriatesToLoginType(): List {
val email = view?.formUsernameValue.orEmpty()
val password = view?.formPassValue.orEmpty()
val endpoint = view?.formHostValue.orEmpty()
@@ -192,11 +183,10 @@ class LoginAdvancedPresenter @Inject constructor(
val token = view?.formTokenValue.orEmpty()
return when (Sdk.Mode.valueOf(view?.formLoginType.orEmpty())) {
- Sdk.Mode.HEBE -> studentRepository.getStudentsApi(pin, symbol, token)
+ Sdk.Mode.API -> studentRepository.getStudentsApi(pin, symbol, token)
Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper(
email, password, endpoint, symbol
)
-
Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid(
email, password, endpoint, symbol
)
@@ -215,8 +205,8 @@ class LoginAdvancedPresenter @Inject constructor(
var isCorrect = true
- when (Sdk.Mode.valueOf(view?.formLoginType.orEmpty())) {
- Sdk.Mode.HEBE -> {
+ when (Sdk.Mode.valueOf(view?.formLoginType ?: "")) {
+ Sdk.Mode.API -> {
if (pin.isEmpty()) {
view?.setErrorPinRequired()
isCorrect = false
@@ -232,17 +222,17 @@ class LoginAdvancedPresenter @Inject constructor(
isCorrect = false
}
}
-
Sdk.Mode.HYBRID, Sdk.Mode.SCRAPPER -> {
if (login.isEmpty()) {
view?.setErrorUsernameRequired()
isCorrect = false
} else {
- if ("@" in login && "login" in host) {
+ if ("@" in login && "standard" !in host) {
view?.setErrorLoginRequired()
isCorrect = false
}
- if ("@" !in login && "email" in host) {
+
+ if ("@" !in login && "standard" in host) {
view?.setErrorEmailRequired()
isCorrect = false
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt
index 34062d938..f9b84f1ab 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt
@@ -1,6 +1,6 @@
package io.github.wulkanowy.ui.modules.login.advanced
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.login.LoginData
@@ -72,7 +72,7 @@ interface LoginAdvancedView : BaseView {
fun navigateToSymbol(loginData: LoginData)
- fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
+ fun navigateToStudentSelect(studentsWithSemesters: List)
fun setErrorPinRequired()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt
index 43ba3fe1d..463e192de 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt
@@ -9,13 +9,18 @@ import androidx.core.view.isVisible
import androidx.core.widget.doOnTextChanged
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.databinding.FragmentLoginFormBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.LoginData
-import io.github.wulkanowy.utils.*
+import io.github.wulkanowy.utils.AppInfo
+import io.github.wulkanowy.utils.hideSoftInput
+import io.github.wulkanowy.utils.openEmailClient
+import io.github.wulkanowy.utils.openInternetBrowser
+import io.github.wulkanowy.utils.setOnEditorDoneSignIn
+import io.github.wulkanowy.utils.showSoftInput
import javax.inject.Inject
@AndroidEntryPoint
@@ -144,14 +149,12 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
override fun setErrorPassRequired(focus: Boolean) {
with(binding.loginFormPassLayout) {
error = getString(R.string.error_field_required)
- setEndIconTintList(requireContext().getAttrColorStateList(R.attr.colorError))
}
}
override fun setErrorPassInvalid(focus: Boolean) {
with(binding.loginFormPassLayout) {
error = getString(R.string.login_invalid_password)
- setEndIconTintList(requireContext().getAttrColorStateList(R.attr.colorError))
}
}
@@ -159,7 +162,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
with(binding) {
loginFormUsernameLayout.error = " "
loginFormPassLayout.error = " "
- loginFormPassLayout.setEndIconTintList(requireContext().getAttrColorStateList(R.attr.colorError))
loginFormHostLayout.error = " "
loginFormErrorBox.text = message ?: getString(R.string.login_incorrect_password_default)
loginFormErrorBox.isVisible = true
@@ -179,7 +181,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
override fun clearPassError() {
binding.loginFormPassLayout.error = null
- binding.loginFormPassLayout.setEndIconTintList(null)
binding.loginFormErrorBox.isVisible = false
}
@@ -204,10 +205,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
binding.loginFormContainer.visibility = if (show) VISIBLE else GONE
}
- override fun showOtherOptionsButton(show: Boolean) {
- binding.loginFormAdvancedButton.isVisible = show
- }
-
@SuppressLint("SetTextI18n")
override fun showVersion() {
binding.loginFormVersion.text = "v${appInfo.versionName}"
@@ -229,8 +226,8 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
}
- override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
- (activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
+ override fun navigateToStudentSelect(studentsWithSemesters: List) {
+ (activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
}
override fun openAdvancedLogin() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt
index ed70eb128..0acb0ea6d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt
@@ -7,7 +7,6 @@ import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
-import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.ifNullOrBlank
import timber.log.Timber
import java.net.URL
@@ -16,7 +15,6 @@ import javax.inject.Inject
class LoginFormPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler,
- private val appInfo: AppInfo,
private val analytics: AnalyticsHelper
) : BasePresenter(loginErrorHandler, studentRepository) {
@@ -27,7 +25,6 @@ class LoginFormPresenter @Inject constructor(
view.run {
initView()
showContact(false)
- showOtherOptionsButton(appInfo.isDebug)
showVersion()
loginErrorHandler.onBadCredentials = {
@@ -96,7 +93,7 @@ class LoginFormPresenter @Inject constructor(
if (!validateCredentials(email, password, host)) return
resourceFlow {
- studentRepository.getUserSubjectsFromScrapper(
+ studentRepository.getStudentsScrapper(
email = email,
password = password,
scrapperBaseUrl = host,
@@ -112,14 +109,14 @@ class LoginFormPresenter @Inject constructor(
}
}
.onResourceSuccess {
- val loginData = LoginData(email, password, host, symbol)
- when (it.symbols.size) {
- 0 -> view?.navigateToSymbol(loginData)
- else -> view?.navigateToStudentSelect(loginData, it)
+ when (it.size) {
+ 0 -> view?.navigateToSymbol(LoginData(email, password, host))
+ else -> view?.navigateToStudentSelect(it)
}
analytics.logEvent(
"registration_form",
"success" to true,
+ "students" to it.size,
"scrapperBaseUrl" to host,
"error" to "No error"
)
@@ -137,6 +134,7 @@ class LoginFormPresenter @Inject constructor(
analytics.logEvent(
"registration_form",
"success" to false,
+ "students" to -1,
"scrapperBaseUrl" to host,
"error" to it.message.ifNullOrBlank { "No message" }
)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt
index e5c680d6f..8003975db 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt
@@ -1,6 +1,6 @@
package io.github.wulkanowy.ui.modules.login.form
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.login.LoginData
@@ -56,13 +56,11 @@ interface LoginFormView : BaseView {
fun showContent(show: Boolean)
- fun showOtherOptionsButton(show: Boolean)
-
fun showVersion()
fun navigateToSymbol(loginData: LoginData)
- fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
+ fun navigateToStudentSelect(studentsWithSemesters: List)
fun openPrivacyPolicyPage()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt
index b9afba986..786bbfce8 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt
@@ -98,7 +98,7 @@ class LoginRecoverFragment :
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() }
- loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressedDispatcher.onBackPressed() }
+ loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressed() }
}
with(bindingLocal.loginRecoverHost) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt
index e6d131829..c046c2ff5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt
@@ -2,182 +2,65 @@ package io.github.wulkanowy.ui.modules.login.studentselect
import android.annotation.SuppressLint
import android.view.LayoutInflater
+import android.view.View
import android.view.ViewGroup
-import androidx.core.view.isVisible
-import androidx.recyclerview.widget.DiffUtil.ItemCallback
-import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
-import io.github.wulkanowy.R
-import io.github.wulkanowy.databinding.*
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
+import io.github.wulkanowy.databinding.ItemLoginStudentSelectBinding
import javax.inject.Inject
-@SuppressLint("SetTextI18n")
class LoginStudentSelectAdapter @Inject constructor() :
- ListAdapter(Differ) {
+ RecyclerView.Adapter() {
- override fun getItemViewType(position: Int): Int = getItem(position).type.ordinal
+ private val checkedList = mutableMapOf()
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- val inflater = LayoutInflater.from(parent.context)
- return when (LoginStudentSelectItemType.values()[viewType]) {
- LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER -> EmptySymbolsHeaderViewHolder(
- ItemLoginStudentSelectEmptySymbolHeaderBinding.inflate(inflater, parent, false),
- )
- LoginStudentSelectItemType.SYMBOL_HEADER -> SymbolsHeaderViewHolder(
- ItemLoginStudentSelectHeaderSymbolBinding.inflate(inflater, parent, false)
- )
- LoginStudentSelectItemType.SCHOOL_HEADER -> SchoolHeaderViewHolder(
- ItemLoginStudentSelectHeaderSchoolBinding.inflate(inflater, parent, false)
- )
- LoginStudentSelectItemType.STUDENT -> StudentViewHolder(
- ItemLoginStudentSelectStudentBinding.inflate(inflater, parent, false)
- )
- LoginStudentSelectItemType.HELP -> HelpViewHolder(
- ItemLoginStudentSelectHelpBinding.inflate(inflater, parent, false)
- )
+ var items = emptyList>()
+ set(value) {
+ field = value
+ checkedList.clear()
}
- }
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- when (holder) {
- is EmptySymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.EmptySymbolsHeader)
- is SymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SymbolHeader)
- is SchoolHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SchoolHeader)
- is StudentViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Student)
- is HelpViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Help)
- }
- }
+ var onClickListener: (StudentWithSemesters, alreadySaved: Boolean) -> Unit = { _, _ -> }
- private class EmptySymbolsHeaderViewHolder(
- private val binding: ItemLoginStudentSelectEmptySymbolHeaderBinding,
- ) : RecyclerView.ViewHolder(binding.root) {
+ override fun getItemCount() = items.size
- fun bind(item: LoginStudentSelectItem.EmptySymbolsHeader) {
- with(binding) {
- loginStudentSelectEmptySymbolChevron.rotation = if (item.isExpanded) 270f else 90f
- root.setOnClickListener { item.onClick() }
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
+ ItemLoginStudentSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ )
+
+ @SuppressLint("SetTextI18n")
+ override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
+ val (studentAndSemesters, alreadySaved) = items[position]
+ val student = studentAndSemesters.student
+ val semesters = studentAndSemesters.semesters
+ val diary = semesters.maxByOrNull { it.semesterId }
+
+ with(holder.binding) {
+ loginItemName.text = "${student.studentName} ${diary?.diaryName.orEmpty()}"
+ loginItemSchool.text = student.schoolName
+ loginItemName.isEnabled = !alreadySaved
+ loginItemSchool.isEnabled = !alreadySaved
+ loginItemSignedIn.visibility = if (alreadySaved) View.VISIBLE else View.GONE
+
+ with(loginItemCheck) {
+ isEnabled = !alreadySaved
+ keyListener = null
+ isChecked = checkedList[position] ?: false
}
- }
- }
- private class SymbolsHeaderViewHolder(
- private val binding: ItemLoginStudentSelectHeaderSymbolBinding,
- ) : RecyclerView.ViewHolder(binding.root) {
-
- fun bind(item: LoginStudentSelectItem.SymbolHeader) {
- with(binding) {
- loginStudentSelectHeaderSymbolValue.text = buildString {
- append(root.context.getString(R.string.mobile_device_symbol))
- append(": ")
- append(item.humanReadableName ?: item.symbol.symbol)
- if (!item.humanReadableName.isNullOrBlank()) {
- append(" (${item.symbol.symbol})")
- }
- }
- loginStudentSelectHeaderSymbolUsername.text = item.symbol.userName
- loginStudentSelectHeaderSymbolUsername.isVisible = item.symbol.userName.isNotBlank()
- loginStudentSelectHeaderSymbolError.text = item.symbol.error?.message
- loginStudentSelectHeaderSymbolError.isVisible = item.symbol.error != null
- loginStudentSelectHeaderSymbolError.maxLines = when {
- item.isErrorExpanded -> Int.MAX_VALUE
- else -> 2
- }
-
- if (item.symbol.error != null) {
- root.setOnClickListener { item.onClick(item.symbol) }
- } else root.setOnClickListener(null)
- }
- }
- }
-
- private class SchoolHeaderViewHolder(
- private val binding: ItemLoginStudentSelectHeaderSchoolBinding,
- ) : RecyclerView.ViewHolder(binding.root) {
-
- fun bind(item: LoginStudentSelectItem.SchoolHeader) {
- with(binding) {
- loginStudentSelectHeaderSchoolName.text = buildString {
- append(item.unit.schoolName.trim())
- append(" (")
- append(item.unit.schoolShortName)
- append(")")
- }
- loginStudentSelectHeaderSchoolDetails.isVisible = item.unit.students.isEmpty()
- loginStudentSelectHeaderSchoolError.text = item.unit.error?.message
- loginStudentSelectHeaderSchoolError.isVisible = item.unit.error != null
- loginStudentSelectHeaderSchoolError.maxLines = when {
- item.isErrorExpanded -> Int.MAX_VALUE
- else -> 2
- }
-
- if (item.unit.error != null) {
- root.setOnClickListener { item.onClick(item.unit) }
- } else root.setOnClickListener(null)
- }
- }
- }
-
- private class StudentViewHolder(
- private val binding: ItemLoginStudentSelectStudentBinding,
- ) : RecyclerView.ViewHolder(binding.root) {
-
- fun bind(item: LoginStudentSelectItem.Student) {
- val student = item.student
- val semesters = student.semesters
- val diary = semesters.maxByOrNull { it.semesterId }
-
- with(binding) {
- loginItemName.text = "${student.studentName} ${student.studentSurname}"
- loginItemName.isEnabled = item.isEnabled
- loginItemSignedIn.text = if (!item.isEnabled) {
- root.context.getString(R.string.login_signed_in)
- } else diary?.diaryName
+ root.setOnClickListener {
+ onClickListener(studentAndSemesters, alreadySaved)
with(loginItemCheck) {
- keyListener = null
- isEnabled = item.isEnabled
- isChecked = item.isSelected || !item.isEnabled
- }
-
- root.isEnabled = item.isEnabled
- root.setOnClickListener {
- item.onClick(item)
+ if (isEnabled) {
+ isChecked = !isChecked
+ checkedList[position] = isChecked
+ }
}
}
}
}
- private class HelpViewHolder(
- private val binding: ItemLoginStudentSelectHelpBinding,
- ) : RecyclerView.ViewHolder(binding.root) {
-
- fun bind(item: LoginStudentSelectItem.Help) {
- with(binding) {
- loginStudentSelectHelpSymbol.isVisible = item.isSymbolButtonVisible
- loginStudentSelectHelpSymbol.setOnClickListener { item.onEnterSymbolClick() }
- loginStudentSelectHelpMail.setOnClickListener { item.onContactUsClick() }
- loginStudentSelectHelpDiscord.setOnClickListener { item.onDiscordClick() }
- }
- }
- }
-
- private object Differ : ItemCallback() {
-
- override fun areItemsTheSame(
- oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem
- ): Boolean = when {
- oldItem is LoginStudentSelectItem.EmptySymbolsHeader && newItem is LoginStudentSelectItem.EmptySymbolsHeader -> true
- oldItem is LoginStudentSelectItem.SymbolHeader && newItem is LoginStudentSelectItem.SymbolHeader -> {
- oldItem.symbol == newItem.symbol
- }
- oldItem is LoginStudentSelectItem.Student && newItem is LoginStudentSelectItem.Student -> {
- oldItem.student == newItem.student
- }
- else -> oldItem == newItem
- }
-
- override fun areContentsTheSame(
- oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem
- ): Boolean = oldItem == newItem
- }
+ class ItemViewHolder(val binding: ItemLoginStudentSelectBinding) :
+ RecyclerView.ViewHolder(binding.root)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt
index c33d12faa..c42a4e9d1 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt
@@ -2,20 +2,21 @@ package io.github.wulkanowy.ui.modules.login.studentselect
import android.os.Bundle
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import androidx.core.os.bundleOf
-import androidx.core.view.isVisible
+import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
-import io.github.wulkanowy.ui.modules.login.LoginData
+import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser
-import io.github.wulkanowy.utils.serializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -35,73 +36,75 @@ class LoginStudentSelectFragment :
@Inject
lateinit var preferencesRepository: PreferencesRepository
- private lateinit var symbolsNames: Array
- private lateinit var symbolsValues: Array
-
- override val symbols: Map by lazy {
- symbolsValues.zip(symbolsNames).toMap()
- }
-
companion object {
- private const val ARG_LOGIN = "LOGIN"
- private const val ARG_STUDENTS = "STUDENTS"
+ const val ARG_STUDENTS = "STUDENTS"
- fun newInstance(loginData: LoginData, registerUser: RegisterUser) =
+ fun newInstance(studentsWithSemesters: List) =
LoginStudentSelectFragment().apply {
- arguments = bundleOf(
- ARG_LOGIN to loginData,
- ARG_STUDENTS to registerUser,
- )
+ arguments = bundleOf(ARG_STUDENTS to studentsWithSemesters)
}
}
+ @Suppress("UNCHECKED_CAST")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentLoginStudentSelectBinding.bind(view)
-
- symbolsNames = resources.getStringArray(R.array.symbols)
- symbolsValues = resources.getStringArray(R.array.symbols_values)
-
presenter.onAttachView(
view = this,
- loginData = requireArguments().serializable(ARG_LOGIN),
- registerUser = requireArguments().serializable(ARG_STUDENTS),
+ students = requireArguments().getSerializable(ARG_STUDENTS) as List,
)
}
override fun initView() {
(requireActivity() as LoginActivity).showActionBar(true)
+ loginAdapter.onClickListener = presenter::onItemSelected
+
with(binding) {
loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() }
- loginStudentSelectRecycler.adapter = loginAdapter
+ loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() }
+ loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() }
+
+ with(loginStudentSelectRecycler) {
+ layoutManager = LinearLayoutManager(context)
+ adapter = loginAdapter
+ }
}
}
- override fun updateData(data: List) {
- loginAdapter.submitList(data)
+ override fun updateData(data: List>) {
+ with(loginAdapter) {
+ items = data
+ notifyDataSetChanged()
+ }
}
- override fun navigateToSymbol(loginData: LoginData) {
- (requireActivity() as LoginActivity).navigateToSymbolFragment(loginData)
- }
-
- override fun navigateToNext() {
- (requireActivity() as LoginActivity).navigateToNotifications()
+ override fun openMainView() {
+ startActivity(MainActivity.getStartIntent(requireContext()))
+ requireActivity().finish()
}
override fun showProgress(show: Boolean) {
- binding.loginStudentSelectProgress.isVisible = show
+ binding.loginStudentSelectProgress.visibility = if (show) VISIBLE else GONE
}
override fun showContent(show: Boolean) {
- binding.loginStudentSelectContent.isVisible = show
+ binding.loginStudentSelectContent.visibility = if (show) VISIBLE else GONE
}
override fun enableSignIn(enable: Boolean) {
binding.loginStudentSelectSignIn.isEnabled = enable
}
+ override fun showContact(show: Boolean) {
+ binding.loginStudentSelectContact.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun onDestroyView() {
+ presenter.onDetachView()
+ super.onDestroyView()
+ }
+
override fun openDiscordInvite() {
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
}
@@ -122,9 +125,4 @@ class LoginStudentSelectFragment :
)
)
}
-
- override fun onDestroyView() {
- presenter.onDetachView()
- super.onDestroyView()
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt
deleted file mode 100644
index 1edc8e7b4..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package io.github.wulkanowy.ui.modules.login.studentselect
-
-import io.github.wulkanowy.data.pojos.RegisterStudent
-import io.github.wulkanowy.data.pojos.RegisterSymbol
-import io.github.wulkanowy.data.pojos.RegisterUnit
-
-sealed class LoginStudentSelectItem(val type: LoginStudentSelectItemType) {
-
- data class EmptySymbolsHeader(
- val isExpanded: Boolean,
- val onClick: () -> Unit,
- ) : LoginStudentSelectItem(LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER)
-
- data class SymbolHeader(
- val symbol: RegisterSymbol,
- val humanReadableName: String?,
- val isErrorExpanded: Boolean,
- val onClick: (RegisterSymbol) -> Unit,
- ) : LoginStudentSelectItem(LoginStudentSelectItemType.SYMBOL_HEADER)
-
- data class SchoolHeader(
- val unit: RegisterUnit,
- val isErrorExpanded: Boolean,
- val onClick: (RegisterUnit) -> Unit,
- ) : LoginStudentSelectItem(LoginStudentSelectItemType.SCHOOL_HEADER)
-
- data class Student(
- val symbol: RegisterSymbol,
- val unit: RegisterUnit,
- val student: RegisterStudent,
- val isEnabled: Boolean,
- val isSelected: Boolean,
- val onClick: (Student) -> Unit,
- ) : LoginStudentSelectItem(LoginStudentSelectItemType.STUDENT)
-
- data class Help(
- val onEnterSymbolClick: () -> Unit,
- val onContactUsClick: () -> Unit,
- val onDiscordClick: () -> Unit,
- val isSymbolButtonVisible: Boolean,
- ) : LoginStudentSelectItem(LoginStudentSelectItemType.HELP)
-}
-
-enum class LoginStudentSelectItemType {
- EMPTY_SYMBOLS_HEADER,
- SYMBOL_HEADER,
- SCHOOL_HEADER,
- STUDENT,
- HELP,
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt
index 7e1fe3b21..3455b3cf1 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt
@@ -1,24 +1,15 @@
package io.github.wulkanowy.ui.modules.login.studentselect
import io.github.wulkanowy.data.Resource
-import io.github.wulkanowy.data.dataOrNull
+import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.logResourceStatus
-import io.github.wulkanowy.data.mappers.mapToStudentWithSemesters
-import io.github.wulkanowy.data.pojos.RegisterStudent
-import io.github.wulkanowy.data.pojos.RegisterSymbol
-import io.github.wulkanowy.data.pojos.RegisterUnit
-import io.github.wulkanowy.data.pojos.RegisterUser
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.resourceFlow
-import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
-import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException
import io.github.wulkanowy.services.sync.SyncManager
import io.github.wulkanowy.ui.base.BasePresenter
-import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
-import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.ifNullOrBlank
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
@@ -28,30 +19,18 @@ class LoginStudentSelectPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler,
private val syncManager: SyncManager,
- private val analytics: AnalyticsHelper,
- private val appInfo: AppInfo,
+ private val analytics: AnalyticsHelper
) : BasePresenter(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null
- private lateinit var registerUser: RegisterUser
- private lateinit var loginData: LoginData
+ private val selectedStudents = mutableListOf()
- private lateinit var students: List
- private var isEmptySymbolsExpanded = false
- private var expandedSymbolError: RegisterSymbol? = null
- private var expandedSchoolError: RegisterUnit? = null
-
- private val selectedStudents = mutableListOf()
-
- fun onAttachView(
- view: LoginStudentSelectView,
- loginData: LoginData,
- registerUser: RegisterUser,
- ) {
+ fun onAttachView(view: LoginStudentSelectView, students: List) {
super.onAttachView(view)
with(view) {
initView()
+ showContact(false)
enableSignIn(false)
loginErrorHandler.onStudentDuplicate = {
showMessage(it)
@@ -59,171 +38,50 @@ class LoginStudentSelectPresenter @Inject constructor(
}
}
- this.loginData = loginData
- this.registerUser = registerUser
- loadData()
+ if (students.size == 1) registerStudents(students)
+ loadData(students)
}
- private fun loadData() {
- resetSelectedState()
-
- resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
- students = it.dataOrNull.orEmpty()
- when (it) {
- is Resource.Loading -> Timber.d("Login student select students load started")
- is Resource.Success -> refreshItems()
- is Resource.Error -> {
- errorHandler.dispatch(it.error)
- lastError = it.error
- refreshItems()
- }
- }
- }.launch()
- }
-
- private fun createItems(): List = buildList {
- val notEmptySymbols = registerUser.symbols.filter { it.schools.isNotEmpty() }
- val emptySymbols = registerUser.symbols.filter { it.schools.isEmpty() }
-
- if (emptySymbols.isNotEmpty() && notEmptySymbols.isNotEmpty() && emptySymbols.any { it.symbol == loginData.symbol }) {
- add(createEmptySymbolItem(emptySymbols.first { it.symbol == loginData.symbol }))
- }
-
- addAll(createNotEmptySymbolItems(notEmptySymbols, students))
- addAll(createEmptySymbolItems(emptySymbols, notEmptySymbols.isNotEmpty()))
-
- val helpItem = LoginStudentSelectItem.Help(
- onEnterSymbolClick = ::onEnterSymbol,
- onContactUsClick = ::onEmailClick,
- onDiscordClick = ::onDiscordClick,
- isSymbolButtonVisible = "login" !in loginData.baseUrl,
- )
- add(helpItem)
- }
-
- private fun createNotEmptySymbolItems(
- notEmptySymbols: List,
- students: List,
- ) = buildList {
- notEmptySymbols.forEach { registerSymbol ->
- val symbolHeader = LoginStudentSelectItem.SymbolHeader(
- symbol = registerSymbol,
- humanReadableName = view?.symbols?.get(registerSymbol.symbol),
- isErrorExpanded = expandedSymbolError == registerSymbol,
- onClick = ::onSymbolItemClick,
- )
- add(symbolHeader)
-
- registerSymbol.schools.forEach { registerUnit ->
- val schoolHeader = LoginStudentSelectItem.SchoolHeader(
- unit = registerUnit,
- isErrorExpanded = expandedSchoolError == registerUnit,
- onClick = ::onUnitItemClick,
- )
- add(schoolHeader)
-
- registerUnit.students.forEach {
- add(createStudentItem(it, registerSymbol, registerUnit, students))
- }
- }
- }
- }
-
- private fun createStudentItem(
- student: RegisterStudent,
- symbol: RegisterSymbol,
- school: RegisterUnit,
- students: List,
- ) = LoginStudentSelectItem.Student(
- symbol = symbol,
- unit = school,
- student = student,
- onClick = ::onItemSelected,
- isEnabled = students.none {
- it.student.email == registerUser.login
- && it.student.symbol == symbol.symbol
- && it.student.studentId == student.studentId
- && it.student.schoolSymbol == school.schoolId
- && it.student.classId == student.classId
- },
- isSelected = selectedStudents
- .filter { it.symbol.symbol == symbol.symbol }
- .filter { it.unit.schoolId == school.schoolId }
- .filter { it.student.studentId == student.studentId }
- .filter { it.student.classId == student.classId }
- .size == 1,
- )
-
- private fun createEmptySymbolItems(
- emptySymbols: List,
- isNotEmptySymbolsExist: Boolean,
- ) = buildList {
- val filteredEmptySymbols = emptySymbols.filter {
- it.error !is InvalidSymbolException
- }.ifEmpty { emptySymbols.takeIf { !isNotEmptySymbolsExist }.orEmpty() }
-
- if (filteredEmptySymbols.isNotEmpty() && isNotEmptySymbolsExist) {
- val emptyHeader = LoginStudentSelectItem.EmptySymbolsHeader(
- isExpanded = isEmptySymbolsExpanded,
- onClick = ::onEmptySymbolsToggle,
- )
- add(emptyHeader)
- if (isEmptySymbolsExpanded) {
- filteredEmptySymbols.forEach {
- add(createEmptySymbolItem(it))
- }
- }
- }
-
- if (filteredEmptySymbols.isNotEmpty() && !isNotEmptySymbolsExist) {
- filteredEmptySymbols.forEach {
- add(createEmptySymbolItem(it))
- }
- }
- }
-
- private fun createEmptySymbolItem(registerSymbol: RegisterSymbol) =
- LoginStudentSelectItem.SymbolHeader(
- symbol = registerSymbol,
- humanReadableName = view?.symbols?.get(registerSymbol.symbol),
- isErrorExpanded = expandedSymbolError == registerSymbol,
- onClick = ::onSymbolItemClick,
- )
-
fun onSignIn() {
registerStudents(selectedStudents)
}
- private fun onEmptySymbolsToggle() {
- isEmptySymbolsExpanded = !isEmptySymbolsExpanded
-
- refreshItems()
- }
-
- private fun onItemSelected(item: LoginStudentSelectItem.Student) {
- if (!item.isEnabled) return
+ fun onItemSelected(studentWithSemester: StudentWithSemesters, alreadySaved: Boolean) {
+ if (alreadySaved) return
selectedStudents
- .removeAll {
- it.student.studentId == item.student.studentId &&
- it.student.classId == item.student.classId &&
- it.unit.schoolId == item.unit.schoolId &&
- it.symbol.symbol == item.symbol.symbol
- }
- .let { if (!it) selectedStudents.add(item) }
+ .removeAll { it == studentWithSemester }
+ .let { if (!it) selectedStudents.add(studentWithSemester) }
view?.enableSignIn(selectedStudents.isNotEmpty())
- refreshItems()
}
- private fun onSymbolItemClick(symbol: RegisterSymbol) {
- expandedSymbolError = if (symbol != expandedSymbolError) symbol else null
- refreshItems()
+ private fun compareStudents(a: Student, b: Student): Boolean {
+ return a.email == b.email
+ && a.symbol == b.symbol
+ && a.studentId == b.studentId
+ && a.schoolSymbol == b.schoolSymbol
+ && a.classId == b.classId
}
- private fun onUnitItemClick(unit: RegisterUnit) {
- expandedSchoolError = if (unit != expandedSchoolError) unit else null
- refreshItems()
+ private fun loadData(studentsWithSemesters: List) {
+ resetSelectedState()
+
+ resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
+ when (it) {
+ is Resource.Loading -> Timber.d("Login student select students load started")
+ is Resource.Success -> view?.updateData(studentsWithSemesters.map { studentWithSemesters ->
+ studentWithSemesters to it.data.any { item ->
+ compareStudents(studentWithSemesters.student, item.student)
+ }
+ })
+ is Resource.Error -> {
+ errorHandler.dispatch(it.error)
+ lastError = it.error
+ view?.updateData(studentsWithSemesters.map { student -> student to false })
+ }
+ }
+ }.launch()
}
private fun resetSelectedState() {
@@ -231,20 +89,7 @@ class LoginStudentSelectPresenter @Inject constructor(
view?.enableSignIn(false)
}
- private fun refreshItems() {
- view?.updateData(createItems())
- }
-
- private fun registerStudents(students: List) {
- val studentsWithSemesters = students
- .filterIsInstance().map { item ->
- item.student.mapToStudentWithSemesters(
- user = registerUser,
- symbol = item.symbol,
- unit = item.unit,
- colors = appInfo.defaultColorsForAvatar,
- )
- }
+ private fun registerStudents(studentsWithSemesters: List) {
resourceFlow { studentRepository.saveStudents(studentsWithSemesters) }
.logResourceStatus("registration")
.onEach {
@@ -255,13 +100,14 @@ class LoginStudentSelectPresenter @Inject constructor(
}
is Resource.Success -> {
syncManager.startOneTimeSyncWorker(quiet = true)
- view?.navigateToNext()
+ view?.openMainView()
logRegisterEvent(studentsWithSemesters)
}
is Resource.Error -> {
view?.apply {
showProgress(false)
showContent(true)
+ showContact(true)
}
lastError = it.error
loginErrorHandler.dispatch(it.error)
@@ -271,37 +117,12 @@ class LoginStudentSelectPresenter @Inject constructor(
}.launch("register")
}
- private fun onEnterSymbol() {
- view?.navigateToSymbol(loginData)
- }
-
- private fun onDiscordClick() {
+ fun onDiscordClick() {
view?.openDiscordInvite()
}
- private fun onEmailClick() {
- view?.openEmail(lastError?.message.ifNullOrBlank {
- loginData.baseUrl + "/" + loginData.symbol + "\n" + registerUser.symbols.filterNot {
- (it.error is AccountPermissionException || it.error is InvalidSymbolException) && it.symbol != loginData.symbol
- }.joinToString(";\n") { symbol ->
- buildString {
- append(" -")
- append(symbol.symbol)
- append("(${symbol.error?.message?.let { it.take(46) + "..." } ?: symbol.schools.size})")
- if (symbol.schools.isNotEmpty()) {
- append(": ")
- }
- append(symbol.schools.joinToString(", ") { unit ->
- buildString {
- append(unit.schoolShortName)
- append("(${unit.error?.message?.let { it.take(46) + "..." } ?: unit.students.size})")
- }
- })
- }
- } + "\nPozostałe: " + registerUser.symbols.filter {
- it.error is AccountPermissionException || it.error is InvalidSymbolException
- }.joinToString(", ") { it.symbol }
- })
+ fun onEmailClick() {
+ view?.openEmail(lastError?.message.ifNullOrBlank { "empty" })
}
private fun logRegisterEvent(
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt
index 39f312bf3..f2acd76c5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt
@@ -1,19 +1,15 @@
package io.github.wulkanowy.ui.modules.login.studentselect
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
-import io.github.wulkanowy.ui.modules.login.LoginData
interface LoginStudentSelectView : BaseView {
- val symbols: Map
-
fun initView()
- fun updateData(data: List)
+ fun updateData(data: List>)
- fun navigateToSymbol(loginData: LoginData)
-
- fun navigateToNext()
+ fun openMainView()
fun showProgress(show: Boolean)
@@ -21,6 +17,8 @@ interface LoginStudentSelectView : BaseView {
fun enableSignIn(enable: Boolean)
+ fun showContact(show: Boolean)
+
fun openDiscordInvite()
fun openEmail(lastError: String)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt
index 692aaeb76..36c40d156 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt
@@ -12,13 +12,17 @@ import androidx.core.text.parseAsHtml
import androidx.core.widget.doOnTextChanged
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.LoginData
-import io.github.wulkanowy.utils.*
+import io.github.wulkanowy.utils.AppInfo
+import io.github.wulkanowy.utils.hideSoftInput
+import io.github.wulkanowy.utils.openEmailClient
+import io.github.wulkanowy.utils.openInternetBrowser
+import io.github.wulkanowy.utils.showSoftInput
import javax.inject.Inject
@AndroidEntryPoint
@@ -42,8 +46,6 @@ class LoginSymbolFragment :
}
}
- override val symbolValue: String? get() = binding.loginSymbolName.text?.toString()
-
override val symbolNameError: CharSequence?
get() = binding.loginSymbolNameLayout.error
@@ -52,7 +54,7 @@ class LoginSymbolFragment :
binding = FragmentLoginSymbolBinding.bind(view)
presenter.onAttachView(
view = this,
- loginData = requireArguments().serializable(SAVED_LOGIN_DATA),
+ loginData = requireArguments().getSerializable(SAVED_LOGIN_DATA) as LoginData,
)
}
@@ -60,7 +62,7 @@ class LoginSymbolFragment :
(requireActivity() as LoginActivity).showActionBar(true)
with(binding) {
- loginSymbolSignIn.setOnClickListener { presenter.attemptLogin() }
+ loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
loginSymbolFaq.setOnClickListener { presenter.onFaqClick() }
loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() }
@@ -93,21 +95,10 @@ class LoginSymbolFragment :
}
}
- override fun setErrorSymbolInvalid() {
- with(binding.loginSymbolNameLayout) {
- requestFocus()
- error = getString(R.string.login_invalid_symbol)
- }
- }
-
override fun setErrorSymbolRequire() {
- setErrorSymbol(getString(R.string.error_field_required))
- }
-
- override fun setErrorSymbol(message: String) {
- with(binding.loginSymbolNameLayout) {
+ binding.loginSymbolNameLayout.apply {
requestFocus()
- error = message
+ error = getString(R.string.error_field_required)
}
}
@@ -138,8 +129,8 @@ class LoginSymbolFragment :
binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE
}
- override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
- (activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
+ override fun navigateToStudentSelect(studentsWithSemesters: List) {
+ (activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
}
override fun onSaveInstanceState(outState: Bundle) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt
index 03ea95fa6..691cd4481 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt
@@ -1,13 +1,9 @@
package io.github.wulkanowy.ui.modules.login.symbol
import io.github.wulkanowy.data.Resource
-import io.github.wulkanowy.data.dataOrNull
import io.github.wulkanowy.data.onResourceNotLoading
-import io.github.wulkanowy.data.pojos.RegisterUser
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.resourceFlow
-import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
-import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
@@ -27,14 +23,9 @@ class LoginSymbolPresenter @Inject constructor(
lateinit var loginData: LoginData
- private var registerUser: RegisterUser? = null
-
fun onAttachView(view: LoginSymbolView, loginData: LoginData) {
super.onAttachView(view)
this.loginData = loginData
- loginErrorHandler.onBadCredentials = {
- view.setErrorSymbol(it.orEmpty())
- }
with(view) {
initView()
showContact(false)
@@ -48,25 +39,21 @@ class LoginSymbolPresenter @Inject constructor(
view?.apply { if (symbolNameError != null) clearSymbolError() }
}
- fun attemptLogin() {
- if (view?.symbolValue.isNullOrBlank()) {
+ fun attemptLogin(symbol: String) {
+ if (symbol.isBlank()) {
view?.setErrorSymbolRequire()
return
}
- loginData = loginData.copy(
- symbol = view?.symbolValue?.getNormalizedSymbol(),
- )
resourceFlow {
- studentRepository.getUserSubjectsFromScrapper(
+ studentRepository.getStudentsScrapper(
email = loginData.login,
password = loginData.password,
scrapperBaseUrl = loginData.baseUrl,
- symbol = loginData.symbol.orEmpty(),
+ symbol = symbol,
)
- }.onEach { user ->
- registerUser = user.dataOrNull
- when (user) {
+ }.onEach {
+ when (it) {
is Resource.Loading -> view?.run {
Timber.i("Login with symbol started")
hideSoftKeyboard()
@@ -74,7 +61,7 @@ class LoginSymbolPresenter @Inject constructor(
showContent(false)
}
is Resource.Success -> {
- when (user.data.symbols.size) {
+ when (it.data.size) {
0 -> {
Timber.i("Login with symbol result: Empty student list")
view?.run {
@@ -83,26 +70,16 @@ class LoginSymbolPresenter @Inject constructor(
}
}
else -> {
- val enteredSymbolDetails = user.data.symbols
- .firstOrNull()
- ?.takeIf { it.symbol == loginData.symbol }
-
- if (enteredSymbolDetails?.error is InvalidSymbolException) {
- view?.run {
- setErrorSymbolInvalid()
- showContact(true)
- }
- } else {
- Timber.i("Login with symbol result: Success")
- view?.navigateToStudentSelect(loginData, requireNotNull(user.data))
- }
+ Timber.i("Login with symbol result: Success")
+ view?.navigateToStudentSelect(requireNotNull(it.data))
}
}
analytics.logEvent(
"registration_symbol",
"success" to true,
+ "students" to it.data.size,
"scrapperBaseUrl" to loginData.baseUrl,
- "symbol" to view?.symbolValue,
+ "symbol" to symbol,
"error" to "No error"
)
}
@@ -113,11 +90,11 @@ class LoginSymbolPresenter @Inject constructor(
"success" to false,
"students" to -1,
"scrapperBaseUrl" to loginData.baseUrl,
- "symbol" to view?.symbolValue,
- "error" to user.error.message.ifNullOrBlank { "No message" }
+ "symbol" to symbol,
+ "error" to it.error.message.ifNullOrBlank { "No message" }
)
- loginErrorHandler.dispatch(user.error)
- lastError = user.error
+ loginErrorHandler.dispatch(it.error)
+ lastError = it.error
view?.showContact(true)
}
}
@@ -134,12 +111,6 @@ class LoginSymbolPresenter @Inject constructor(
}
fun onEmailClick() {
- view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank {
- registerUser?.symbols?.flatMap { symbol ->
- symbol.schools.map { it.error?.message } + symbol.error?.message
- }?.filterNotNull()?.distinct()?.joinToString(";") {
- it.take(46) + "..."
- } ?: "blank"
- })
+ view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank { "empty" })
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt
index 6585c00f4..527895b77 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt
@@ -1,13 +1,10 @@
package io.github.wulkanowy.ui.modules.login.symbol
-import io.github.wulkanowy.data.pojos.RegisterUser
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
-import io.github.wulkanowy.ui.modules.login.LoginData
interface LoginSymbolView : BaseView {
- val symbolValue: String?
-
val symbolNameError: CharSequence?
fun initView()
@@ -16,12 +13,8 @@ interface LoginSymbolView : BaseView {
fun setErrorSymbolIncorrect()
- fun setErrorSymbolInvalid()
-
fun setErrorSymbolRequire()
- fun setErrorSymbol(message: String)
-
fun clearSymbolError()
fun clearAndFocusSymbol()
@@ -34,7 +27,7 @@ interface LoginSymbolView : BaseView {
fun showContent(show: Boolean)
- fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
+ fun navigateToStudentSelect(studentsWithSemesters: List)
fun showContact(show: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt
index a6c75c1d9..0a73fe15d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt
@@ -18,7 +18,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class LuckyNumberFragment :
BaseFragment(R.layout.fragment_lucky_number), LuckyNumberView,
- MainView.TitledView, MainView.MainChildView {
+ MainView.TitledView {
@Inject
lateinit var presenter: LuckyNumberPresenter
@@ -86,14 +86,6 @@ class LuckyNumberFragment :
(activity as? MainActivity)?.pushView(LuckyNumberHistoryFragment.newInstance())
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onViewReselected()
- }
-
- override fun popView() {
- (activity as? MainActivity)?.popView()
- }
-
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt
index 2039624b1..6f5c8e740 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt
@@ -99,9 +99,4 @@ class LuckyNumberPresenter @Inject constructor(
fun onDetailsClick() {
view?.showErrorDetailsDialog(lastError)
}
-
- fun onViewReselected() {
- Timber.i("Luckynumber view is reselected")
- view?.popView()
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt
index 3d34ebc8f..0c05a1566 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt
@@ -26,6 +26,4 @@ interface LuckyNumberView : BaseView {
fun showContent(show: Boolean)
fun openLuckyNumberHistory()
-
- fun popView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt
index a78ce5dd2..53f06cacd 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt
@@ -61,7 +61,7 @@ class LuckyNumberHistoryFragment :
luckyNumberHistoryPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
luckyNumberHistoryNextButton.setOnClickListener { presenter.onNextWeek() }
- luckyNumberHistoryNavContainer.elevation = requireContext().dpToPx(3f)
+ luckyNumberHistoryNavContainer.elevation = requireContext().dpToPx(8f)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt
index a2d23e543..024beff85 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt
@@ -1,12 +1,16 @@
package io.github.wulkanowy.ui.modules.luckynumberwidget
-import android.appwidget.AppWidgetManager.*
+import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE
+import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
+import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS
import android.content.Intent
+import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
+import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding
import io.github.wulkanowy.ui.base.BaseActivity
@@ -37,6 +41,7 @@ class LuckyNumberWidgetConfigureActivity :
setContentView(
ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root
)
+
intent.extras.let {
presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID))
}
@@ -51,6 +56,22 @@ class LuckyNumberWidgetConfigureActivity :
configureAdapter.onClickListener = presenter::onItemSelect
}
+ override fun showThemeDialog() {
+ var items = arrayOf(
+ getString(R.string.widget_timetable_theme_light),
+ getString(R.string.widget_timetable_theme_dark)
+ )
+ if (appInfo.systemVersion >= Build.VERSION_CODES.Q) items += (getString(R.string.widget_timetable_theme_system))
+
+ dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher)
+ .setTitle(R.string.widget_timetable_theme_title)
+ .setOnDismissListener { presenter.onDismissThemeView() }
+ .setSingleChoiceItems(items, -1) { _, which ->
+ presenter.onThemeSelect(which)
+ }
+ .show()
+ }
+
override fun updateData(data: List, selectedStudentId: Long) {
with(configureAdapter) {
selectedId = selectedStudentId
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt
index 7e53dad06..cac648da8 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt
@@ -8,6 +8,7 @@ import io.github.wulkanowy.data.resourceFlow
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey
+import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getThemeWidgetKey
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import javax.inject.Inject
@@ -31,9 +32,20 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
fun onItemSelect(student: Student) {
selectedStudent = student
+ view?.showThemeDialog()
+ }
+
+ fun onThemeSelect(index: Int) {
+ appWidgetId?.let {
+ sharedPref.putLong(getThemeWidgetKey(it), index.toLong())
+ }
registerStudent(selectedStudent)
}
+ fun onDismissThemeView() {
+ view?.finishView()
+ }
+
private fun loadData() {
resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
when (it) {
@@ -44,7 +56,10 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
} ?: -1
when {
it.data.isEmpty() -> view?.openLoginView()
- it.data.size == 1 -> onItemSelect(it.data.single().student)
+ it.data.size == 1 -> {
+ selectedStudent = it.data.single().student
+ view?.showThemeDialog()
+ }
else -> view?.updateData(it.data, selectedStudentId)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt
index df13b993d..b4556f7ef 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt
@@ -7,6 +7,8 @@ interface LuckyNumberWidgetConfigureView : BaseView {
fun initView()
+ fun showThemeDialog()
+
fun updateData(data: List, selectedStudentId: Long)
fun updateLuckyNumberWidget(widgetId: Int)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt
index bafb2d7e5..e03e3e90e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt
@@ -2,12 +2,14 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
-import android.util.TypedValue.COMPLEX_UNIT_SP
-import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.widget.RemoteViews
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -15,6 +17,7 @@ import io.github.wulkanowy.data.Resource
import io.github.wulkanowy.data.dataOrNull
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.entities.LuckyNumber
+import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.toFirstResult
@@ -38,12 +41,16 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
lateinit var sharedPref: SharedPrefProvider
companion object {
- private const val LUCKY_NUMBER_WIDGET_MAX_SIZE = 196
- private const val LUCKY_NUMBER_PENDING_INTENT_ID = 300
- private const val LUCKY_NUMBER_HISTORY_PENDING_INTENT_ID = 301
+ const val LUCKY_NUMBER_PENDING_INTENT_ID = 200
fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId"
+
+ fun getThemeWidgetKey(appWidgetId: Int) = "lucky_number_widget_theme_$appWidgetId"
+
+ fun getHeightWidgetKey(appWidgetId: Int) = "lucky_number_widget_height_$appWidgetId"
+
+ fun getWidthWidgetKey(appWidgetId: Int) = "lucky_number_widget_width_$appWidgetId"
}
override fun onUpdate(
@@ -52,86 +59,107 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
appWidgetIds: IntArray?
) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
+ appWidgetIds?.forEach { appWidgetId ->
+ val luckyNumber =
+ getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)
+ val appIntent = PendingIntent.getActivity(
+ context,
+ LUCKY_NUMBER_PENDING_INTENT_ID,
+ SplashActivity.getStartIntent(context, Destination.LuckyNumber),
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
+ )
- val appIntent = PendingIntent.getActivity(
- context,
- LUCKY_NUMBER_PENDING_INTENT_ID,
- SplashActivity.getStartIntent(context, Destination.LuckyNumber),
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
- )
+ if (luckyNumber is Resource.Error) {
+ Timber.e("Error loading lucky number for widget", luckyNumber.error)
+ }
- val historyIntent = PendingIntent.getActivity(
- context,
- LUCKY_NUMBER_HISTORY_PENDING_INTENT_ID,
- SplashActivity.getStartIntent(context, Destination.LuckyNumberHistory),
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
- )
+ val remoteView =
+ RemoteViews(context.packageName, getCorrectLayoutId(appWidgetId, context))
+ .apply {
+ setTextViewText(
+ R.id.luckyNumberWidgetNumber,
+ luckyNumber.dataOrNull?.luckyNumber?.toString() ?: "#"
+ )
+ setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent)
+ }
- appWidgetIds?.forEach { widgetId ->
- val studentId = sharedPref.getLong(getStudentWidgetKey(widgetId), 0)
- val luckyNumberResource = getLuckyNumber(studentId, widgetId)
- val luckyNumber = luckyNumberResource.dataOrNull?.luckyNumber?.toString()
- val remoteView = RemoteViews(context.packageName, R.layout.widget_luckynumber)
- .apply {
- setTextViewText(R.id.luckyNumberWidgetValue, luckyNumber ?: "-")
- setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent)
- setOnClickPendingIntent(R.id.luckyNumberWidgetHistoryButton, historyIntent)
- }
-
- resizeWidget(context, appWidgetManager.getAppWidgetOptions(widgetId), remoteView)
- appWidgetManager.updateAppWidget(widgetId, remoteView)
- }
- }
-
- override fun onAppWidgetOptionsChanged(
- context: Context?,
- appWidgetManager: AppWidgetManager?,
- appWidgetId: Int,
- newOptions: Bundle?
- ) {
- super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
-
- if (context == null || newOptions == null || appWidgetManager == null) {
- return
- }
-
- val remoteView = RemoteViews(context.packageName, R.layout.widget_luckynumber)
- resizeWidget(context, newOptions, remoteView)
- appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteView)
- }
-
- private fun resizeWidget(context: Context, options: Bundle, remoteViews: RemoteViews) {
- val (width, height) = options.getWidgetSize(context)
- val size = minOf(width, height, LUCKY_NUMBER_WIDGET_MAX_SIZE).toFloat()
- resizeWidgetContents(size, remoteViews)
- Timber.v("LuckyNumberWidget resized: ${width}x${height} ($size)")
- }
-
- private fun resizeWidgetContents(size: Float, remoteViews: RemoteViews) {
- var historyButtonVisibility = View.VISIBLE
- var luckyNumberTextSize = 72f
-
- if (size < 150) {
- luckyNumberTextSize = 44f
- historyButtonVisibility = View.GONE
- }
- if (size < 75) {
- luckyNumberTextSize = 26f
- }
-
- remoteViews.apply {
- setTextViewTextSize(R.id.luckyNumberWidgetValue, COMPLEX_UNIT_SP, luckyNumberTextSize)
- setViewVisibility(R.id.luckyNumberWidgetHistoryButton, historyButtonVisibility)
+ setStyles(remoteView, appWidgetId)
+ appWidgetManager.updateAppWidget(appWidgetId, remoteView)
}
}
override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
super.onDeleted(context, appWidgetIds)
appWidgetIds?.forEach { appWidgetId ->
- sharedPref.delete(getStudentWidgetKey(appWidgetId))
+ with(sharedPref) {
+ delete(getHeightWidgetKey(appWidgetId))
+ delete(getStudentWidgetKey(appWidgetId))
+ delete(getThemeWidgetKey(appWidgetId))
+ delete(getWidthWidgetKey(appWidgetId))
+ }
}
}
+ override fun onAppWidgetOptionsChanged(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetId: Int,
+ newOptions: Bundle?
+ ) {
+ super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
+
+ val remoteView = RemoteViews(context.packageName, getCorrectLayoutId(appWidgetId, context))
+
+ setStyles(remoteView, appWidgetId, newOptions)
+ appWidgetManager.updateAppWidget(appWidgetId, remoteView)
+ }
+
+ private fun setStyles(views: RemoteViews, appWidgetId: Int, options: Bundle? = null) {
+ val width = options?.getInt(OPTION_APPWIDGET_MIN_WIDTH) ?: sharedPref.getLong(
+ getWidthWidgetKey(appWidgetId), 74
+ ).toInt()
+ val height = options?.getInt(OPTION_APPWIDGET_MAX_HEIGHT) ?: sharedPref.getLong(
+ getHeightWidgetKey(appWidgetId), 74
+ ).toInt()
+
+ with(sharedPref) {
+ putLong(getWidthWidgetKey(appWidgetId), width.toLong())
+ putLong(getHeightWidgetKey(appWidgetId), height.toLong())
+ }
+
+ val rows = getCellsForSize(height)
+ val cols = getCellsForSize(width)
+
+ Timber.d("New lucky number widget measurement: %dx%d", width, height)
+ Timber.d("Widget size: $cols x $rows")
+
+ when {
+ 1 == cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = false)
+ 1 == cols && 1 < rows -> views.setVisibility(imageTop = true, imageLeft = false)
+ 1 < cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = true)
+ 1 == cols && 1 == rows -> views.setVisibility(imageTop = true, imageLeft = false)
+ 2 == cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = true)
+ else -> views.setVisibility(imageTop = false, imageLeft = false, title = true)
+ }
+ }
+
+ private fun RemoteViews.setVisibility(
+ imageTop: Boolean,
+ imageLeft: Boolean,
+ title: Boolean = false
+ ) {
+ setViewVisibility(R.id.luckyNumberWidgetImageTop, if (imageTop) VISIBLE else GONE)
+ setViewVisibility(R.id.luckyNumberWidgetImageLeft, if (imageLeft) VISIBLE else GONE)
+ setViewVisibility(R.id.luckyNumberWidgetTitle, if (title) VISIBLE else GONE)
+ setViewVisibility(R.id.luckyNumberWidgetNumber, VISIBLE)
+ }
+
+ private fun getCellsForSize(size: Int): Int {
+ var n = 2
+ while (74 * n - 30 < size) ++n
+ return n - 1
+ }
+
private fun getLuckyNumber(studentId: Long, appWidgetId: Int) = runBlocking {
try {
val students = studentRepository.getSavedStudents()
@@ -153,24 +181,22 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
Resource.Success(null)
}
} catch (e: Exception) {
- Timber.e(e, "An error has occurred in lucky number provider")
+ if (e.cause !is NoCurrentStudentException) {
+ Timber.e(e, "An error has occurred in lucky number provider")
+ }
Resource.Error(e)
}
}
- private fun Bundle.getWidgetSize(context: Context): Pair {
- val minWidth = getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
- val maxWidth = getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
- val minHeight = getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
- val maxHeight = getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
+ private fun getCorrectLayoutId(appWidgetId: Int, context: Context): Int {
+ val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
+ val isSystemDarkMode =
+ context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
- val orientation = context.resources.configuration.orientation
- val isPortrait = orientation == Configuration.ORIENTATION_PORTRAIT
-
- return if (isPortrait) {
- minWidth to maxHeight
+ return if (savedTheme == 1L || (savedTheme == 2L && isSystemDarkMode)) {
+ R.layout.widget_luckynumber_dark
} else {
- maxWidth to minHeight
+ R.layout.widget_luckynumber
}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
index 091080a55..5cd6fa103 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
@@ -2,14 +2,12 @@ package io.github.wulkanowy.ui.modules.main
import android.content.Context
import android.content.Intent
-import android.os.Build
+import android.os.Build.VERSION_CODES.P
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
-import android.view.ViewGroup.MarginLayoutParams
-import androidx.activity.OnBackPressedCallback
-import androidx.activity.addCallback
-import androidx.core.view.*
+import androidx.core.view.ViewCompat
+import androidx.core.view.isVisible
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.preference.Preference
@@ -27,7 +25,6 @@ import io.github.wulkanowy.databinding.DialogAdsConsentBinding
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog
-import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
import io.github.wulkanowy.utils.*
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@@ -53,8 +50,6 @@ class MainActivity : BaseActivity(), MainVie
@Inject
lateinit var appInfo: AppInfo
- private var onBackCallback: OnBackPressedCallback? = null
-
private var accountMenu: MenuItem? = null
private val overlayProvider by lazy { ElevationOverlayProvider(this) }
@@ -90,20 +85,9 @@ class MainActivity : BaseActivity(), MainVie
super.onCreate(savedInstanceState)
setContentView(ActivityMainBinding.inflate(layoutInflater).apply { binding = this }.root)
setSupportActionBar(binding.mainToolbar)
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- WindowCompat.setDecorFitsSystemWindows(window, false)
- binding.mainAppBar.isLifted = true
- }
- initializeFragmentContainer()
-
this.savedInstanceState = savedInstanceState
messageContainer = binding.mainMessageContainer
- messageAnchor = binding.mainMessageContainer
updateHelper.messageContainer = binding.mainFragmentContainer
- onBackCallback = onBackPressedDispatcher.addCallback(this, enabled = false) {
- presenter.onBackPressed()
- }
val destination = intent.getStringExtra(EXTRA_START_DESTINATION)
?.takeIf { savedInstanceState == null }
@@ -133,20 +117,13 @@ class MainActivity : BaseActivity(), MainVie
return true
}
- override fun initView(
- startMenuIndex: Int,
- rootAppMenuItems: List,
- rootUpdatedDestinations: List
- ) {
+ override fun initView(startMenuIndex: Int, rootDestinations: List) {
initializeToolbar()
- initializeBottomNavigation(startMenuIndex, rootAppMenuItems)
- initializeNavController(startMenuIndex, rootUpdatedDestinations)
+ initializeBottomNavigation(startMenuIndex)
+ initializeNavController(startMenuIndex, rootDestinations)
}
- private fun initializeNavController(
- startMenuIndex: Int,
- rootUpdatedDestinations: List
- ) {
+ private fun initializeNavController(startMenuIndex: Int, rootDestinations: List) {
with(navController) {
setOnViewChangeListener { destinationView ->
presenter.onViewChange(destinationView)
@@ -156,7 +133,7 @@ class MainActivity : BaseActivity(), MainVie
)
}
fragmentHideStrategy = HIDE
- rootFragments = rootUpdatedDestinations.map { it.destinationFragment }
+ rootFragments = rootDestinations.map { it.destinationFragment }
initialize(startMenuIndex, savedInstanceState)
}
@@ -172,16 +149,17 @@ class MainActivity : BaseActivity(), MainVie
}
}
- private fun initializeBottomNavigation(
- startMenuIndex: Int,
- rootAppMenuItems: List
- ) {
+ private fun initializeBottomNavigation(startMenuIndex: Int) {
with(binding.mainBottomNav) {
with(menu) {
- rootAppMenuItems.forEachIndexed { index, item ->
- add(Menu.NONE, index, Menu.NONE, item.title)
- .setIcon(item.icon)
- }
+ add(Menu.NONE, 0, Menu.NONE, R.string.dashboard_title)
+ .setIcon(R.drawable.ic_main_dashboard)
+ add(Menu.NONE, 1, Menu.NONE, R.string.grade_title)
+ .setIcon(R.drawable.ic_main_grade)
+ add(Menu.NONE, 2, Menu.NONE, R.string.attendance_title)
+ .setIcon(R.drawable.ic_main_attendance)
+ add(Menu.NONE, 3, Menu.NONE, R.string.timetable_title)
+ .setIcon(R.drawable.ic_main_timetable)
add(Menu.NONE, 4, Menu.NONE, R.string.more_title)
.setIcon(R.drawable.ic_main_more)
}
@@ -195,17 +173,6 @@ class MainActivity : BaseActivity(), MainVie
}
}
- private fun initializeFragmentContainer() {
- ViewCompat.setOnApplyWindowInsetsListener(binding.mainFragmentContainer) { view, insets ->
- val bottomInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
-
- view.updateLayoutParams {
- bottomMargin = if (binding.mainBottomNav.isVisible) 0 else bottomInsets.bottom
- }
- WindowInsetsCompat.CONSUMED
- }
- }
-
override fun onPreferenceStartFragment(
caller: PreferenceFragmentCompat,
pref: Preference
@@ -250,9 +217,20 @@ class MainActivity : BaseActivity(), MainVie
showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters))
}
+ override fun showActionBarElevation(show: Boolean) {
+ ViewCompat.setElevation(binding.mainToolbar, if (show) dpToPx(4f) else 0f)
+ }
+
override fun showBottomNavigation(show: Boolean) {
binding.mainBottomNav.isVisible = show
- binding.mainFragmentContainer.requestApplyInsets()
+
+ if (appInfo.systemVersion >= P) {
+ window.navigationBarColor = if (show) {
+ getThemeAttrColor(android.R.attr.navigationBarColor)
+ } else {
+ getThemeAttrColor(R.attr.colorSurface)
+ }
+ }
}
override fun openMoreDestination(destination: Destination) {
@@ -288,7 +266,6 @@ class MainActivity : BaseActivity(), MainVie
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.pushFragment(fragment)
- onBackCallback?.isEnabled = !isRootView
}
override fun popView(depth: Int) {
@@ -296,7 +273,10 @@ class MainActivity : BaseActivity(), MainVie
analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.safelyPopFragments(depth)
- onBackCallback?.isEnabled = !isRootView
+ }
+
+ override fun onBackPressed() {
+ presenter.onBackPressed { super.onBackPressed() }
}
override fun showStudentAvatar(student: Student) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt
index ae05ecf22..9c32d8583 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt
@@ -14,6 +14,9 @@ import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.account.AccountView
import io.github.wulkanowy.ui.modules.account.accountdetails.AccountDetailsView
+import io.github.wulkanowy.ui.modules.grade.GradeView
+import io.github.wulkanowy.ui.modules.message.MessageView
+import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersView
import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView
import io.github.wulkanowy.utils.AdsHelper
import io.github.wulkanowy.utils.AnalyticsHelper
@@ -39,16 +42,17 @@ class MainPresenter @Inject constructor(
private var studentsWitSemesters: List? = null
- private val rootAppMenuItems = preferencesRepository.appMenuItemOrder
- .sortedBy { it.order }
- .take(4)
-
- private val rootDestinationTypeList = rootAppMenuItems.map { it.destinationType }
- .plus(Destination.Type.MORE)
+ private val rootDestinationTypeList = listOf(
+ Destination.Type.DASHBOARD,
+ Destination.Type.GRADE,
+ Destination.Type.ATTENDANCE,
+ Destination.Type.TIMETABLE,
+ Destination.Type.MORE
+ )
private val Destination?.startMenuIndex
get() = when {
- this == null -> 0
+ this == null -> preferencesRepository.startMenuIndex
destinationType in rootDestinationTypeList -> {
rootDestinationTypeList.indexOf(destinationType)
}
@@ -65,7 +69,7 @@ class MainPresenter @Inject constructor(
if (it == initDestination?.destinationType) initDestination else it.defaultDestination
}
- view.initView(startMenuIndex, rootAppMenuItems, destinations)
+ view.initView(startMenuIndex, destinations)
if (initDestination != null && startMenuIndex == 4) {
view.openMoreDestination(initDestination)
}
@@ -97,6 +101,7 @@ class MainPresenter @Inject constructor(
fun onViewChange(destinationView: BaseView) {
view?.apply {
showBottomNavigation(shouldShowBottomNavigation(destinationView))
+ showActionBarElevation(shouldShowActionBarElevation(destinationView))
currentViewTitle?.let { setViewTitle(it) }
currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) }
currentStackSize?.let {
@@ -106,6 +111,13 @@ class MainPresenter @Inject constructor(
}
}
+ private fun shouldShowActionBarElevation(destination: BaseView) = when (destination) {
+ is GradeView,
+ is MessageView,
+ is SchoolAndTeachersView -> false
+ else -> true
+ }
+
private fun shouldShowBottomNavigation(destination: BaseView) = when (destination) {
is AccountView,
is StudentInfoView,
@@ -127,9 +139,12 @@ class MainPresenter @Inject constructor(
return true
}
- fun onBackPressed() {
+ fun onBackPressed(default: () -> Unit) {
Timber.i("Back pressed in main view")
- view?.popView()
+ view?.run {
+ if (isRootView) default()
+ else popView()
+ }
}
fun onTabSelected(index: Int, wasSelected: Boolean): Boolean {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt
index 62436f3bf..3d018e3d6 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt
@@ -4,7 +4,6 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.Destination
-import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
interface MainView : BaseView {
@@ -16,11 +15,7 @@ interface MainView : BaseView {
val currentStackSize: Int?
- fun initView(
- startMenuIndex: Int,
- rootAppMenuItems: List,
- rootUpdatedDestinations: List
- )
+ fun initView(startMenuIndex: Int, rootDestinations: List)
fun switchMenuView(position: Int)
@@ -28,6 +23,8 @@ interface MainView : BaseView {
fun showAccountPicker(studentWithSemesters: List)
+ fun showActionBarElevation(show: Boolean)
+
fun showBottomNavigation(show: Boolean)
fun notifyMenuViewReselected()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt
index 4317fb7fa..4607793c9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt
@@ -15,7 +15,6 @@ import io.github.wulkanowy.data.enums.MessageFolder.*
import io.github.wulkanowy.databinding.FragmentMessageBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
-import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
@@ -25,7 +24,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class MessageFragment : BaseFragment(R.layout.fragment_message),
- MessageView, MainView.TitledView, MainView.MainChildView {
+ MessageView, MainView.TitledView {
@Inject
lateinit var presenter: MessagePresenter
@@ -124,12 +123,8 @@ class MessageFragment : BaseFragment(R.layout.fragment_m
presenter.onChildViewShowNewMessage(show)
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onFragmentReselected()
- }
-
- override fun onFragmentChanged() {
- if (::presenter.isInitialized) presenter.onFragmentChanged()
+ fun onFragmentChanged() {
+ presenter.onFragmentChanged()
}
override fun notifyChildLoadData(index: Int, forceRefresh: Boolean) {
@@ -144,19 +139,10 @@ class MessageFragment : BaseFragment(R.layout.fragment_m
}
}
- override fun notifyChildParentReselected(index: Int) {
- (pagerAdapter.getFragmentInstance(index) as? MessageTabFragment)
- ?.onParentReselected()
- }
-
override fun openSendMessage() {
context?.let { it.startActivity(SendMessageActivity.getStartIntent(it)) }
}
- override fun popView() {
- (activity as? MainActivity)?.popView()
- }
-
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt
index cf6bad19e..68bdc4b7c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt
@@ -39,14 +39,6 @@ class MessagePresenter @Inject constructor(
view?.notifyChildrenFinishActionMode()
}
- fun onFragmentReselected() {
- Timber.i("Message view is reselected")
- view?.run {
- popView()
- notifyChildParentReselected(currentPageIndex)
- }
- }
-
fun onChildViewLoaded() {
view?.apply {
showContent(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt
index def4a2751..e0cc5098c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt
@@ -20,9 +20,5 @@ interface MessageView : BaseView {
fun notifyChildrenFinishActionMode()
- fun notifyChildParentReselected(index: Int)
-
fun openSendMessage()
-
- fun popView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt
index 8bd84f2bf..222412ef1 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt
@@ -1,16 +1,15 @@
package io.github.wulkanowy.ui.modules.message.mailboxchooser
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.fragment.app.setFragmentResult
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.databinding.DialogMailboxChooserBinding
import io.github.wulkanowy.ui.base.BaseDialogFragment
-import io.github.wulkanowy.utils.parcelableArray
import javax.inject.Inject
@AndroidEntryPoint
@@ -37,23 +36,24 @@ class MailboxChooserDialog : BaseDialogFragment(),
}
}
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(
- DialogMailboxChooserBinding.inflate(layoutInflater).apply { binding = this }.root
- )
- .create()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setStyle(STYLE_NO_TITLE, 0)
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogMailboxChooserBinding.inflate(inflater).apply { binding = this }.root
@Suppress("UNCHECKED_CAST")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
presenter.onAttachView(
view = this,
requireMailbox = requireArguments().getBoolean(REQUIRED_KEY, false),
- mailboxes = requireArguments().parcelableArray(MAILBOX_KEY).orEmpty().toList(),
+ mailboxes = requireArguments().getParcelableArray(MAILBOX_KEY).orEmpty()
+ .toList() as List,
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
index 6c54d9fcb..2a5523f4d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
@@ -13,7 +13,6 @@ import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.core.content.getSystemService
-import androidx.core.os.bundleOf
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
@@ -24,7 +23,6 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
-import io.github.wulkanowy.utils.serializable
import io.github.wulkanowy.utils.shareText
import javax.inject.Inject
@@ -68,12 +66,13 @@ class MessagePreviewFragment :
companion object {
const val MESSAGE_ID_KEY = "message_id"
- fun newInstance(message: Message) = MessagePreviewFragment().apply {
- arguments = bundleOf(MESSAGE_ID_KEY to message)
+ fun newInstance(message: Message): MessagePreviewFragment {
+ return MessagePreviewFragment().apply {
+ arguments = Bundle().apply { putSerializable(MESSAGE_ID_KEY, message) }
+ }
}
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -84,8 +83,8 @@ class MessagePreviewFragment :
binding = FragmentMessagePreviewBinding.bind(view)
messageContainer = binding.messagePreviewContainer
presenter.onAttachView(
- view = this,
- message = (savedInstanceState ?: arguments)?.serializable(MESSAGE_ID_KEY),
+ this,
+ (savedInstanceState ?: arguments)?.getSerializable(MESSAGE_ID_KEY) as? Message
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
index 56f23b6fa..fd75f6f3a 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
@@ -186,7 +186,7 @@ class MessagePreviewPresenter @Inject constructor(
runCatching {
val student = studentRepository.getCurrentStudent(decryptPass = true)
val mailbox = messageRepository.getMailboxByStudent(student)
- messageRepository.deleteMessage(student, mailbox, message!!)
+ messageRepository.deleteMessage(student, mailbox!!, message!!)
}
.onFailure {
retryCallback = { onMessageDelete() }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt
index 0ba82f1a0..b5f687bd4 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt
@@ -1,10 +1,10 @@
package io.github.wulkanowy.ui.modules.message.send
import android.annotation.SuppressLint
+import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.graphics.Rect
-import android.os.Build
import android.os.Bundle
import android.text.Spanned
import android.view.Menu
@@ -12,14 +12,11 @@ import android.view.MenuItem
import android.view.TouchDelegate
import android.view.View.GONE
import android.view.View.VISIBLE
-import android.view.ViewGroup
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import androidx.core.text.parseAsHtml
import androidx.core.text.toHtml
-import androidx.core.view.*
import androidx.core.widget.doOnTextChanged
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Mailbox
@@ -27,11 +24,10 @@ import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.databinding.ActivitySendMessageBinding
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog
-import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY
import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.MAILBOX_KEY
+import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.hideSoftInput
-import io.github.wulkanowy.utils.nullableSerializable
import io.github.wulkanowy.utils.showSoftInput
import javax.inject.Inject
@@ -102,13 +98,6 @@ class SendMessageActivity : BaseActivity= Build.VERSION_CODES.R) {
- WindowCompat.setDecorFitsSystemWindows(window, false)
- binding.sendAppBar.isLifted = true
- }
- initializeMessageContainer()
-
messageContainer = binding.sendMessageContainer
formRecipientsData = binding.sendMessageTo.addedChipItems as List
@@ -119,12 +108,12 @@ class SendMessageActivity : BaseActivity
- presenter.onMailboxSelected(bundle.nullableSerializable(MAILBOX_KEY))
+ presenter.onMailboxSelected(bundle.getSerializable(MAILBOX_KEY) as? Mailbox)
}
}
@@ -140,22 +129,6 @@ class SendMessageActivity : BaseActivity
- val navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
- val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())
-
- view.updateLayoutParams {
- bottomMargin = if (imeInsets.bottom > navigationBarInsets.bottom) {
- imeInsets.bottom
- } else {
- navigationBarInsets.bottom
- }
- }
- WindowInsetsCompat.CONSUMED
- }
- }
-
private fun onMessageSubjectChange(text: CharSequence?) {
formSubjectValue = text.toString()
presenter.onMessageContentChange()
@@ -278,7 +251,7 @@ class SendMessageActivity : BaseActivity presenter.restoreMessageParts() }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt
index 9792c7085..6df6153c5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.message.tab
-import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.graphics.Typeface
import android.view.LayoutInflater
@@ -69,23 +68,21 @@ class MessageTabAdapter @Inject constructor() :
}
}
- @SuppressLint("PrivateResource")
private fun bindHeaderViewHolder(holder: HeaderViewHolder, position: Int) {
val item = items[position] as MessageTabDataItem.FilterHeader
- val context = holder.binding.root.context
with(holder.binding) {
- chipMailbox.text =
- item.selectedMailbox ?: context.getString(R.string.message_chip_all_mailboxes)
+ chipMailbox.text = item.selectedMailbox
+ ?: root.context.getString(R.string.message_chip_all_mailboxes)
chipMailbox.chipBackgroundColor = ColorStateList.valueOf(
if (item.selectedMailbox == null) {
- context.getCompatColor(R.color.m3_elevated_chip_background_color)
- } else context.getThemeAttrColor(R.attr.colorPrimary, 64)
+ root.context.getCompatColor(R.color.mtrl_choice_chip_background_color)
+ } else root.context.getThemeAttrColor(android.R.attr.colorPrimary, 64)
)
chipMailbox.setTextColor(
if (item.selectedMailbox == null) {
- context.getThemeAttrColor(R.attr.colorOnSurfaceVariant)
- } else context.getThemeAttrColor(R.attr.colorPrimary)
+ root.context.getThemeAttrColor(android.R.attr.textColorPrimary)
+ } else root.context.getThemeAttrColor(android.R.attr.colorPrimary)
)
chipMailbox.setOnClickListener { onMailboxClickListener() }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt
index 592cbd604..5d608ad3b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt
@@ -9,7 +9,6 @@ import android.view.View.*
import android.widget.CompoundButton
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.SearchView
-import androidx.core.os.bundleOf
import androidx.core.view.updatePadding
import androidx.fragment.app.setFragmentResultListener
import androidx.recyclerview.widget.LinearLayoutManager
@@ -28,7 +27,6 @@ import io.github.wulkanowy.ui.widgets.DividerItemDecoration
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.hideSoftInput
-import io.github.wulkanowy.utils.nullableSerializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -45,8 +43,12 @@ class MessageTabFragment : BaseFragment(R.layout.frag
const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id"
- fun newInstance(folder: MessageFolder) = MessageTabFragment().apply {
- arguments = bundleOf(MESSAGE_TAB_FOLDER_ID to folder.name)
+ fun newInstance(folder: MessageFolder): MessageTabFragment {
+ return MessageTabFragment().apply {
+ arguments = Bundle().apply {
+ putString(MESSAGE_TAB_FOLDER_ID, folder.name)
+ }
+ }
}
}
@@ -84,7 +86,6 @@ class MessageTabFragment : BaseFragment(R.layout.frag
}
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -129,12 +130,11 @@ class MessageTabFragment : BaseFragment(R.layout.frag
setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle ->
presenter.onMailboxSelected(
- mailbox = bundle.nullableSerializable(MailboxChooserDialog.MAILBOX_KEY),
+ mailbox = bundle.getSerializable(MailboxChooserDialog.MAILBOX_KEY) as? Mailbox,
)
}
}
- @Suppress("DEPRECATION")
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.action_menu_message_tab, menu)
@@ -235,10 +235,6 @@ class MessageTabFragment : BaseFragment(R.layout.frag
presenter.onParentFinishActionMode()
}
- fun onParentReselected() {
- presenter.onParentReselected()
- }
-
private fun onChipChecked(chip: CompoundButton, isChecked: Boolean) {
when (chip.id) {
R.id.chip_unread -> presenter.onUnreadFilterSelected(isChecked)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt
index ec92e9c20..ea142db2b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt
@@ -83,14 +83,6 @@ class MessageTabPresenter @Inject constructor(
view?.showActionMode(false)
}
- fun onParentReselected() {
- view?.run {
- if (!isViewEmpty) {
- resetListPosition()
- }
- }
- }
-
fun onDestroyActionMode() {
isActionMode = false
messagesToDelete.clear()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt
index 1afe773cf..f8e367c57 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt
@@ -22,7 +22,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class MobileDeviceFragment :
BaseFragment(R.layout.fragment_mobile_device), MobileDeviceView,
- MainView.TitledView, MainView.MainChildView {
+ MainView.TitledView {
@Inject
lateinit var presenter: MobileDevicePresenter
@@ -135,14 +135,6 @@ class MobileDeviceFragment :
(activity as? MainActivity)?.showDialogFragment(MobileDeviceTokenDialog.newInstance())
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onFragmentReselected()
- }
-
- override fun resetView() {
- binding.mobileDevicesRecycler.smoothScrollToPosition(0)
- }
-
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt
index 56785dbf4..36a720e53 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt
@@ -129,10 +129,4 @@ class MobileDevicePresenter @Inject constructor(
.onResourceError(errorHandler::dispatch)
.launch("unregister")
}
-
- fun onFragmentReselected() {
- if (view?.isViewEmpty == false) {
- view?.resetView()
- }
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt
index 973cb1234..b94646a7b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt
@@ -32,6 +32,4 @@ interface MobileDeviceView : BaseView {
fun setErrorDetails(message: String)
fun showTokenDialog()
-
- fun resetView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt
index 2cc2a2aa7..eb420a6ae 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt
@@ -1,17 +1,17 @@
package io.github.wulkanowy.ui.modules.mobiledevice.token
-import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Base64
+import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
+import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.getSystemService
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.pojos.MobileDeviceToken
@@ -31,14 +31,17 @@ class MobileDeviceTokenDialog : BaseDialogFragment(),
fun newInstance() = MobileDeviceTokenDialog()
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(
- DialogMobileDeviceBinding.inflate(layoutInflater).apply { binding = this }.root
- )
- .create()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setStyle(STYLE_NO_TITLE, 0)
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogMobileDeviceBinding.inflate(inflater).apply { binding = this }.root
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter.onAttachView(this)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt
index 697eab330..70587b0cf 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt
@@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.more
+import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
@@ -8,9 +9,9 @@ import javax.inject.Inject
class MoreAdapter @Inject constructor() : RecyclerView.Adapter() {
- var items = emptyList()
+ var items = emptyList>()
- var onClickListener: (moreItem: MoreItem) -> Unit = {}
+ var onClickListener: (name: String) -> Unit = {}
override fun getItemCount() = items.size
@@ -19,14 +20,13 @@ class MoreAdapter @Inject constructor() : RecyclerView.Adapter(R.layout.fragment_more),
override val titleStringId: Int
get() = R.string.more_title
+ override val messagesRes: Pair?
+ get() = context?.run { getString(R.string.message_title) to getCompatDrawable(R.drawable.ic_more_messages) }
+
+ override val homeworkRes: Pair?
+ get() = context?.run { getString(R.string.homework_title) to getCompatDrawable(R.drawable.ic_more_homework) }
+
+ override val noteRes: Pair?
+ get() = context?.run { getString(R.string.note_title) to getCompatDrawable(R.drawable.ic_more_note) }
+
+ override val conferencesRes: Pair?
+ get() = context?.run { getString(R.string.conferences_title) to getCompatDrawable(R.drawable.ic_more_conferences) }
+
+ override val schoolAnnouncementRes: Pair?
+ get() = context?.run { getString(R.string.school_announcement_title) to getCompatDrawable(R.drawable.ic_all_about) }
+
+ override val schoolAndTeachersRes: Pair?
+ get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) }
+
+ override val mobileDevicesRes: Pair?
+ get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) }
+
+ override val settingsRes: Pair?
+ get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) }
+
+ override val examRes: Pair?
+ get() = context?.run { getString(R.string.exam_title) to getCompatDrawable(R.drawable.ic_main_exam) }
+
+ override val luckyNumberRes: Pair?
+ get() = context?.run { getString(R.string.lucky_number_title) to getCompatDrawable(R.drawable.ic_more_lucky_number) }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentMoreBinding.bind(view)
@@ -54,19 +94,55 @@ class MoreFragment : BaseFragment(R.layout.fragment_more),
?.onFragmentChanged()
}
- override fun updateData(data: List) {
+ override fun updateData(data: List>) {
with(moreAdapter) {
items = data
notifyDataSetChanged()
}
}
- override fun popView(depth: Int) {
- (activity as? MainActivity)?.popView(depth)
+ override fun openMessagesView() {
+ (activity as? MainActivity)?.pushView(MessageFragment.newInstance())
}
- override fun openView(destination: Destination) {
- (activity as? MainActivity)?.pushView(destination.destinationFragment)
+ override fun openHomeworkView() {
+ (activity as? MainActivity)?.pushView(HomeworkFragment.newInstance())
+ }
+
+ override fun openNoteView() {
+ (activity as? MainActivity)?.pushView(NoteFragment.newInstance())
+ }
+
+ override fun openSchoolAnnouncementView() {
+ (activity as? MainActivity)?.pushView(SchoolAnnouncementFragment.newInstance())
+ }
+
+ override fun openConferencesView() {
+ (activity as? MainActivity)?.pushView(ConferenceFragment.newInstance())
+ }
+
+ override fun openSchoolAndTeachersView() {
+ (activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance())
+ }
+
+ override fun openMobileDevicesView() {
+ (activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance())
+ }
+
+ override fun openSettingsView() {
+ (activity as? MainActivity)?.pushView(SettingsFragment.newInstance())
+ }
+
+ override fun openExamView() {
+ (activity as? MainActivity)?.pushView(ExamFragment.newInstance())
+ }
+
+ override fun openLuckyNumberView() {
+ (activity as? MainActivity)?.pushView(LuckyNumberFragment.newInstance())
+ }
+
+ override fun popView(depth: Int) {
+ (activity as? MainActivity)?.popView(depth)
}
override fun onDestroyView() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt
deleted file mode 100644
index d544f041c..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package io.github.wulkanowy.ui.modules.more
-
-import io.github.wulkanowy.ui.modules.Destination
-
-data class MoreItem(
-
- val icon: Int,
-
- val title: Int,
-
- val destination: Destination
-)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt
index 0ebaf4c7b..92551d6e9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt
@@ -1,24 +1,16 @@
package io.github.wulkanowy.ui.modules.more
-import io.github.wulkanowy.R
-import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.ui.modules.Destination
import timber.log.Timber
import javax.inject.Inject
class MorePresenter @Inject constructor(
errorHandler: ErrorHandler,
- studentRepository: StudentRepository,
- preferencesRepository: PreferencesRepository
+ studentRepository: StudentRepository
) : BasePresenter(errorHandler, studentRepository) {
- private val moreAppMenuItem = preferencesRepository.appMenuItemOrder
- .sortedBy { it.order }
- .drop(4)
-
override fun onAttachView(view: MoreView) {
super.onAttachView(view)
view.initView()
@@ -26,10 +18,22 @@ class MorePresenter @Inject constructor(
loadData()
}
- fun onItemSelected(moreItem: MoreItem) {
- Timber.i("Select more item \"${moreItem.destination.destinationType}\"")
-
- view?.openView(moreItem.destination)
+ fun onItemSelected(title: String) {
+ Timber.i("Select more item \"${title}\"")
+ view?.run {
+ when (title) {
+ messagesRes?.first -> openMessagesView()
+ examRes?.first -> openExamView()
+ homeworkRes?.first -> openHomeworkView()
+ noteRes?.first -> openNoteView()
+ conferencesRes?.first -> openConferencesView()
+ schoolAnnouncementRes?.first -> openSchoolAnnouncementView()
+ schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
+ mobileDevicesRes?.first -> openMobileDevicesView()
+ settingsRes?.first -> openSettingsView()
+ luckyNumberRes?.first -> openLuckyNumberView()
+ }
+ }
}
fun onViewReselected() {
@@ -39,21 +43,19 @@ class MorePresenter @Inject constructor(
private fun loadData() {
Timber.i("Load items for more view")
- val moreItems = moreAppMenuItem.map {
- MoreItem(
- icon = it.icon,
- title = it.title,
- destination = it.destinationType.defaultDestination
- )
+ view?.run {
+ updateData(listOfNotNull(
+ messagesRes,
+ examRes,
+ homeworkRes,
+ noteRes,
+ luckyNumberRes,
+ conferencesRes,
+ schoolAnnouncementRes,
+ schoolAndTeachersRes,
+ mobileDevicesRes,
+ settingsRes
+ ))
}
- .plus(
- MoreItem(
- icon = R.drawable.ic_more_settings,
- title = R.string.settings_title,
- destination = Destination.Settings
- )
- )
-
- view?.updateData(moreItems)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt
index fbca97edc..cb895de28 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt
@@ -1,15 +1,53 @@
package io.github.wulkanowy.ui.modules.more
+import android.graphics.drawable.Drawable
import io.github.wulkanowy.ui.base.BaseView
-import io.github.wulkanowy.ui.modules.Destination
interface MoreView : BaseView {
+ val messagesRes: Pair?
+
+ val homeworkRes: Pair?
+
+ val noteRes: Pair?
+
+ val conferencesRes: Pair?
+
+ val schoolAnnouncementRes: Pair?
+
+ val schoolAndTeachersRes: Pair?
+
+ val mobileDevicesRes: Pair?
+
+ val settingsRes: Pair?
+
+ val examRes: Pair?
+
+ val luckyNumberRes: Pair?
+
fun initView()
- fun updateData(data: List)
+ fun updateData(data: List>)
+
+ fun openSettingsView()
fun popView(depth: Int)
- fun openView(destination: Destination)
+ fun openMessagesView()
+
+ fun openHomeworkView()
+
+ fun openNoteView()
+
+ fun openSchoolAnnouncementView()
+
+ fun openConferencesView()
+
+ fun openSchoolAndTeachersView()
+
+ fun openMobileDevicesView()
+
+ fun openExamView()
+
+ fun openLuckyNumberView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt
index 0592e9243..5811456b6 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt
@@ -1,24 +1,23 @@
package io.github.wulkanowy.ui.modules.note
import android.annotation.SuppressLint
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import androidx.core.content.ContextCompat
-import androidx.core.os.bundleOf
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.databinding.DialogNoteBinding
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory
-import io.github.wulkanowy.ui.base.BaseDialogFragment
import io.github.wulkanowy.utils.getThemeAttrColor
-import io.github.wulkanowy.utils.serializable
+import io.github.wulkanowy.utils.lifecycleAwareVariable
import io.github.wulkanowy.utils.toFormattedString
-@AndroidEntryPoint
-class NoteDialog : BaseDialogFragment() {
+class NoteDialog : DialogFragment() {
+
+ private var binding: DialogNoteBinding by lifecycleAwareVariable()
private lateinit var note: Note
@@ -26,21 +25,24 @@ class NoteDialog : BaseDialogFragment() {
private const val ARGUMENT_KEY = "Item"
- fun newInstance(note: Note) = NoteDialog().apply {
- arguments = bundleOf(ARGUMENT_KEY to note)
+ fun newInstance(exam: Note) = NoteDialog().apply {
+ arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- note = requireArguments().serializable(ARGUMENT_KEY)
+ setStyle(STYLE_NO_TITLE, 0)
+ arguments?.run {
+ note = getSerializable(ARGUMENT_KEY) as Note
+ }
}
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return MaterialAlertDialogBuilder(requireContext(), theme)
- .setView(DialogNoteBinding.inflate(layoutInflater).apply { binding = this }.root)
- .create()
- }
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = DialogNoteBinding.inflate(inflater).apply { binding = this }.root
@SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt
index cb54b3840..dd6223448 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt
@@ -18,7 +18,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class NoteFragment : BaseFragment(R.layout.fragment_note), NoteView,
- MainView.TitledView, MainView.MainChildView {
+ MainView.TitledView {
@Inject
lateinit var presenter: NotePresenter
@@ -112,14 +112,6 @@ class NoteFragment : BaseFragment(R.layout.fragment_note),
binding.noteSwipe.isRefreshing = show
}
- override fun onFragmentReselected() {
- if (::presenter.isInitialized) presenter.onFragmentReselected()
- }
-
- override fun resetView() {
- binding.noteRecycler.smoothScrollToPosition(0)
- }
-
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt
index 62ad347fa..440565e11 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt
@@ -121,10 +121,4 @@ class NotePresenter @Inject constructor(
}
.launch("update_note")
}
-
- fun onFragmentReselected() {
- if (view?.isViewEmpty == false) {
- view?.resetView()
- }
- }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt
index b813b3159..9fc0be94c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt
@@ -30,6 +30,4 @@ interface NoteView : BaseView {
fun showRefresh(show: Boolean)
fun showNoteDialog(note: Note)
-
- fun resetView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt
deleted file mode 100644
index 0763d4fa8..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package io.github.wulkanowy.ui.modules.notifications
-
-import android.os.Bundle
-import android.view.View
-import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
-import io.github.wulkanowy.R
-import io.github.wulkanowy.databinding.FragmentNotificationsBinding
-import io.github.wulkanowy.ui.base.BaseFragment
-import io.github.wulkanowy.ui.modules.login.LoginActivity
-import io.github.wulkanowy.utils.openNotificationSettings
-
-@AndroidEntryPoint
-class NotificationsFragment :
- BaseFragment(R.layout.fragment_notifications) {
-
- private val permission = "android.permission.POST_NOTIFICATIONS"
-
- private val requestPermissionLauncher = registerForActivityResult(RequestPermission()) {
- if (it) {
- navigateToFinish()
- } else showSettingsDialog()
- }
-
- companion object {
- fun newInstance() = NotificationsFragment()
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- binding = FragmentNotificationsBinding.bind(view)
- initView()
- }
-
- private fun initView() {
- with(binding) {
- notificationsSkip.setOnClickListener { navigateToFinish() }
- notificationsEnable.setOnClickListener { requestPermission() }
- }
- }
-
- private fun showSettingsDialog() {
- MaterialAlertDialogBuilder(requireContext())
- .setTitle(R.string.notifications_header_title)
- .setMessage(R.string.notifications_header_description)
- .setNegativeButton(R.string.notifications_skip) { dialog, _ ->
- dialog.dismiss()
- navigateToFinish()
- }
- .setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ ->
- requireActivity().openNotificationSettings()
- }
- .show()
- }
-
- private fun requestPermission() {
- requestPermissionLauncher.launch(permission)
- }
-
- private fun navigateToFinish() {
- (requireActivity() as LoginActivity).navigateToFinish()
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt
index 46999599b..62f6251ec 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt
@@ -2,10 +2,10 @@ package io.github.wulkanowy.ui.modules.schoolannouncement
import android.view.LayoutInflater
import android.view.ViewGroup
+import androidx.core.text.parseAsHtml
import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
import io.github.wulkanowy.databinding.ItemSchoolAnnouncementBinding
-import io.github.wulkanowy.utils.parseUonetHtml
import io.github.wulkanowy.utils.toFormattedString
import javax.inject.Inject
@@ -28,7 +28,7 @@ class SchoolAnnouncementAdapter @Inject constructor() :
with(holder.binding) {
schoolAnnouncementItemDate.text = item.date.toFormattedString()
schoolAnnouncementItemType.text = item.subject
- schoolAnnouncementItemContent.text = item.content.parseUonetHtml()
+ schoolAnnouncementItemContent.text = item.content.parseAsHtml()
root.setOnClickListener { onItemClickListener(item) }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt
index c1c584414..7dcd51cea 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt
@@ -1,20 +1,19 @@
package io.github.wulkanowy.ui.modules.schoolannouncement
-import android.app.Dialog
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
-import androidx.core.os.bundleOf
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import android.view.ViewGroup
+import androidx.core.text.parseAsHtml
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
import io.github.wulkanowy.databinding.DialogSchoolAnnouncementBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
-import io.github.wulkanowy.utils.parseUonetHtml
-import io.github.wulkanowy.utils.serializable
+import io.github.wulkanowy.utils.lifecycleAwareVariable
import io.github.wulkanowy.utils.toFormattedString
-@AndroidEntryPoint
-class SchoolAnnouncementDialog : BaseDialogFragment() {
+class SchoolAnnouncementDialog : DialogFragment() {
+
+ private var binding: DialogSchoolAnnouncementBinding by lifecycleAwareVariable()
private lateinit var announcement: SchoolAnnouncement
@@ -22,24 +21,24 @@ class SchoolAnnouncementDialog : BaseDialogFragment) -> Unit = {}
-) : ItemTouchHelper.Callback() {
-
- override fun isLongPressDragEnabled() = true
-
- override fun isItemViewSwipeEnabled() = false
-
- override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
- //Not implemented
- }
-
- override fun getMovementFlags(
- recyclerView: RecyclerView,
- viewHolder: RecyclerView.ViewHolder
- ) = makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0)
-
- override fun onMove(
- recyclerView: RecyclerView,
- viewHolder: RecyclerView.ViewHolder,
- target: RecyclerView.ViewHolder
- ): Boolean {
- val list = menuOrderAdapter.items.toMutableList()
-
- Collections.swap(list, viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
-
- menuOrderAdapter.submitList(list)
- return true
- }
-
- override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
- super.clearView(recyclerView, viewHolder)
-
- onUserInteractionEndListener(menuOrderAdapter.items.toList())
- }
-}
-
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderAdapter.kt
deleted file mode 100644
index 6bdd2fe0c..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderAdapter.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package io.github.wulkanowy.ui.modules.settings.appearance.menuorder
-
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.recyclerview.widget.DiffUtil
-import androidx.recyclerview.widget.RecyclerView
-import io.github.wulkanowy.databinding.ItemMenuOrderBinding
-import javax.inject.Inject
-
-class MenuOrderAdapter @Inject constructor() :
- RecyclerView.Adapter() {
-
- val items = mutableListOf()
-
- fun submitList(newItems: List) {
- val diffResult = DiffUtil.calculateDiff(DiffCallback(newItems, items.toMutableList()))
-
- with(items) {
- clear()
- addAll(newItems)
- }
-
- diffResult.dispatchUpdatesTo(this)
- }
-
- override fun getItemCount() = items.size
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
- ItemMenuOrderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- )
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val item = items[position].appMenuItem
-
- with(holder.binding) {
- menuOrderItemTitle.setText(item.title)
- menuOrderItemIcon.setImageResource(item.icon)
- }
- }
-
- class ViewHolder(val binding: ItemMenuOrderBinding) : RecyclerView.ViewHolder(binding.root)
-
- private class DiffCallback(
- private val oldList: List,
- private val newList: List
- ) : DiffUtil.Callback() {
-
- override fun getNewListSize() = newList.size
-
- override fun getOldListSize() = oldList.size
-
- override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
- oldList[oldItemPosition] == newList[newItemPosition]
-
- override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
- oldList[oldItemPosition].appMenuItem.destinationType == newList[newItemPosition].appMenuItem.destinationType
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderDividerItemDecoration.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderDividerItemDecoration.kt
deleted file mode 100644
index 21a7f5e80..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderDividerItemDecoration.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package io.github.wulkanowy.ui.modules.settings.appearance.menuorder
-
-import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Rect
-import android.graphics.drawable.ShapeDrawable
-import android.view.View
-import androidx.core.graphics.drawable.DrawableCompat
-import androidx.core.view.forEach
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.RecyclerView
-import io.github.wulkanowy.R
-import io.github.wulkanowy.utils.getThemeAttrColor
-
-class MenuOrderDividerItemDecoration(private val context: Context) :
- DividerItemDecoration(context, VERTICAL) {
-
- private val dividerDrawable = ShapeDrawable()
- .apply {
- DrawableCompat.setTint(this, context.getThemeAttrColor(R.attr.colorDivider))
- }
-
- override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
- canvas.save()
- val dividerLeft = parent.paddingLeft
- val dividerRight = parent.width - parent.paddingRight
-
- parent.forEach {
- if (parent.getChildAdapterPosition(it) == 3) {
- val params = it.layoutParams as RecyclerView.LayoutParams
- val dividerTop = it.bottom + params.bottomMargin
- val dividerBottom = dividerTop + dividerDrawable.intrinsicHeight
-
- dividerDrawable.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom + 30)
- dividerDrawable.draw(canvas)
- }
- }
-
- canvas.restore()
- }
-
- override fun getItemOffsets(
- outRect: Rect, view: View, parent: RecyclerView,
- state: RecyclerView.State
- ) {
- if (parent.getChildAdapterPosition(view) == 3) {
- outRect.bottom = dividerDrawable.intrinsicHeight + 30
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderFragment.kt
deleted file mode 100644
index e08fc5dd3..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderFragment.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-package io.github.wulkanowy.ui.modules.settings.appearance.menuorder
-
-import android.os.Bundle
-import android.view.Menu
-import android.view.MenuInflater
-import android.view.MenuItem
-import android.view.View
-import androidx.activity.addCallback
-import androidx.core.view.MenuProvider
-import androidx.recyclerview.widget.ItemTouchHelper
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.SimpleItemAnimator
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
-import io.github.wulkanowy.R
-import io.github.wulkanowy.databinding.FragmentMenuOrderBinding
-import io.github.wulkanowy.ui.base.BaseFragment
-import io.github.wulkanowy.ui.modules.main.MainActivity
-import io.github.wulkanowy.ui.modules.main.MainView
-import io.github.wulkanowy.ui.widgets.DividerItemDecoration
-import javax.inject.Inject
-
-
-@AndroidEntryPoint
-class MenuOrderFragment : BaseFragment(R.layout.fragment_menu_order),
- MenuOrderView, MainView.TitledView {
-
- @Inject
- lateinit var presenter: MenuOrderPresenter
-
- @Inject
- lateinit var menuOrderAdapter: MenuOrderAdapter
-
- override val titleStringId = R.string.menu_order_title
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- binding = FragmentMenuOrderBinding.bind(view)
- presenter.onAttachView(this)
- }
-
- override fun initView() {
- val itemTouchHelper = ItemTouchHelper(
- MenuItemMoveCallback(menuOrderAdapter, presenter::onDragAndDropEnd)
- )
-
- itemTouchHelper.attachToRecyclerView(binding.menuOrderRecycler)
-
- with(binding.menuOrderRecycler) {
- layoutManager = LinearLayoutManager(context)
- adapter = menuOrderAdapter
- addItemDecoration(MenuOrderDividerItemDecoration(context))
- addItemDecoration(DividerItemDecoration(context))
- (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
- }
-
- requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
- presenter.onBackSelected()
- }
-
- initializeToolbar()
- }
-
- private fun initializeToolbar() {
- requireActivity().addMenuProvider(object : MenuProvider {
- override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
- }
-
- override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
- if (menuItem.itemId == android.R.id.home) {
- presenter.onBackSelected()
- return true
- }
- return false
- }
-
- }, viewLifecycleOwner)
- }
-
- override fun updateData(data: List) {
- menuOrderAdapter.submitList(data)
- }
-
- override fun restartApp() {
- startActivity(MainActivity.getStartIntent(requireContext()))
- requireActivity().finishAffinity()
- }
-
- override fun popView() {
- (activity as? MainActivity?)?.popView()
- }
-
- override fun showRestartConfirmationDialog() {
- MaterialAlertDialogBuilder(requireContext())
- .setTitle(R.string.menu_order_confirm_title)
- .setMessage(R.string.menu_order_confirm_content)
- .setPositiveButton(R.string.menu_order_confirm_restart) { _, _ -> presenter.onConfirmRestart() }
- .setNegativeButton(R.string.all_cancel) { _, _ -> presenter.onCancelRestart() }
- .show()
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderItem.kt
deleted file mode 100644
index b82bc1bd2..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderItem.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.github.wulkanowy.ui.modules.settings.appearance.menuorder
-
-data class MenuOrderItem(
- val appMenuItem: AppMenuItem,
- val order: Int
-)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderPresenter.kt
deleted file mode 100644
index 1c90cc5e6..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderPresenter.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package io.github.wulkanowy.ui.modules.settings.appearance.menuorder
-
-import io.github.wulkanowy.data.repositories.PreferencesRepository
-import io.github.wulkanowy.data.repositories.StudentRepository
-import io.github.wulkanowy.ui.base.BasePresenter
-import io.github.wulkanowy.ui.base.ErrorHandler
-import timber.log.Timber
-import javax.inject.Inject
-
-class MenuOrderPresenter @Inject constructor(
- studentRepository: StudentRepository,
- errorHandler: ErrorHandler,
- private val preferencesRepository: PreferencesRepository
-) : BasePresenter(errorHandler, studentRepository) {
-
- private var updatedMenuOrderItems = emptyList()
-
- override fun onAttachView(view: MenuOrderView) {
- super.onAttachView(view)
- view.initView()
- Timber.i("Menu order view was initialized")
- loadData()
- }
-
- private fun loadData() {
- val savedMenuItemList = (preferencesRepository.appMenuItemOrder)
- .sortedBy { it.order }
- .map { MenuOrderItem(it, it.order) }
-
- view?.updateData(savedMenuItemList)
- }
-
- fun onDragAndDropEnd(list: List) {
- val updatedList = list.mapIndexed { index, menuOrderItem ->
- menuOrderItem.copy(order = index)
- }
-
- updatedMenuOrderItems = updatedList
- view?.updateData(updatedList)
- }
-
- fun onBackSelected() {
- if (updatedMenuOrderItems.isNotEmpty()) {
- view?.showRestartConfirmationDialog()
- } else {
- view?.popView()
- }
- }
-
- fun onConfirmRestart() {
- updatedMenuOrderItems.forEach {
- it.appMenuItem.apply {
- order = it.order
- }
- }
-
- preferencesRepository.appMenuItemOrder = updatedMenuOrderItems.map { it.appMenuItem }
- view?.restartApp()
- }
-
- fun onCancelRestart() {
- view?.popView()
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderView.kt
deleted file mode 100644
index 264e68ccb..000000000
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderView.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.github.wulkanowy.ui.modules.settings.appearance.menuorder
-
-import io.github.wulkanowy.ui.base.BaseView
-
-interface MenuOrderView : BaseView {
-
- fun initView()
-
- fun updateData(data: List)
-
- fun restartApp()
-
- fun showRestartConfirmationDialog()
-
- fun popView()
-}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt
index 35c1faa45..364ad2137 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt
@@ -1,31 +1,32 @@
package io.github.wulkanowy.ui.modules.settings.notifications
+import android.annotation.SuppressLint
import android.content.Intent
import android.content.SharedPreferences
-import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Build
import android.os.Bundle
+import android.provider.Settings
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationManagerCompat
-import androidx.core.content.ContextCompat
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import androidx.recyclerview.widget.RecyclerView
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.thelittlefireman.appkillermanager.AppKillerManager
import com.thelittlefireman.appkillermanager.exceptions.NoActionFoundException
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.base.ErrorDialog
-import io.github.wulkanowy.ui.modules.auth.AuthDialog
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.openInternetBrowser
-import io.github.wulkanowy.utils.openNotificationSettings
+import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
@@ -41,14 +42,7 @@ class NotificationsFragment : PreferenceFragmentCompat(),
override val titleStringId get() = R.string.pref_settings_notifications_title
- private val notificationsPermission = "android.permission.POST_NOTIFICATIONS"
-
override val isNotificationPermissionGranted: Boolean
- get() = ContextCompat.checkSelfPermission(
- requireContext(), notificationsPermission
- ) == PackageManager.PERMISSION_GRANTED
-
- override val isNotificationPiggybackPermissionGranted: Boolean
get() {
val packageNameList =
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
@@ -57,13 +51,6 @@ class NotificationsFragment : PreferenceFragmentCompat(),
return appPackageName in packageNameList
}
- private val requestPermissionLauncher =
- registerForActivityResult(ActivityResultContracts.RequestPermission()) {
- if (it) {
- presenter.onNotificationsPermissionResult()
- } else openNotificationsPermissionDialog()
- }
-
private val notificationSettingsPiggybackContract =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
presenter.onNotificationPiggybackPermissionResult()
@@ -149,12 +136,8 @@ class NotificationsFragment : PreferenceFragmentCompat(),
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
}
- override fun showAuthDialog() {
- AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
- }
-
override fun showFixSyncDialog() {
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(R.string.pref_notify_fix_sync_issues)
.setMessage(R.string.pref_notify_fix_sync_issues_message)
.setNegativeButton(android.R.string.cancel) { _, _ -> }
@@ -173,30 +156,26 @@ class NotificationsFragment : PreferenceFragmentCompat(),
.show()
}
+ @SuppressLint("InlinedApi")
override fun openSystemSettings() {
- requireActivity().openNotificationSettings()
- }
-
- override fun requestNotificationPermissions() {
- requestPermissionLauncher.launch(notificationsPermission)
- }
-
- override fun openNotificationsPermissionDialog() {
- MaterialAlertDialogBuilder(requireContext())
- .setTitle(R.string.notifications_header_title)
- .setMessage(R.string.notifications_header_description)
- .setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ ->
- requireActivity().openNotificationSettings()
+ val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) {
+ Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
+ putExtra("android.provider.extra.APP_PACKAGE", requireActivity().packageName)
}
- .setNegativeButton(android.R.string.cancel) { _, _ ->
- setNotificationPreferencesChecked(false)
+ } else {
+ Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
+ data = Uri.fromParts("package", requireActivity().packageName, null)
}
- .setOnDismissListener { setNotificationPreferencesChecked(false) }
- .show()
+ }
+ try {
+ requireActivity().startActivity(intent)
+ } catch (e: Exception) {
+ Timber.e(e)
+ }
}
- override fun openNotificationPiggyBackPermissionDialog() {
- MaterialAlertDialogBuilder(requireContext())
+ override fun openNotificationPermissionDialog() {
+ AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.pref_notification_piggyback_popup_title))
.setMessage(getString(R.string.pref_notification_piggyback_popup_description))
.setPositiveButton(getString(R.string.pref_notification_go_to_settings)) { _, _ ->
@@ -210,7 +189,7 @@ class NotificationsFragment : PreferenceFragmentCompat(),
}
override fun openNotificationExactAlarmSettings() {
- MaterialAlertDialogBuilder(requireContext())
+ AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.pref_notification_exact_alarm_popup_title))
.setMessage(getString(R.string.pref_notification_exact_alarm_popup_descriptions))
.setPositiveButton(getString(R.string.pref_notification_go_to_settings)) { _, _ ->
@@ -223,11 +202,6 @@ class NotificationsFragment : PreferenceFragmentCompat(),
.show()
}
- override fun setNotificationPreferencesChecked(isChecked: Boolean) {
- findPreference(getString(R.string.pref_key_notifications_enable))?.isChecked =
- isChecked
- }
-
override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
findPreference(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
isChecked
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt
index 232b03480..4cbdac945 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt
@@ -26,13 +26,12 @@ class NotificationsPresenter @Inject constructor(
with(view) {
enableNotification(
- notificationKey = preferencesRepository.notificationsEnableKey,
- enable = preferencesRepository.isServiceEnabled
+ preferencesRepository.notificationsEnableKey,
+ preferencesRepository.isServiceEnabled
)
initView(appInfo.isDebug)
}
- checkNotificationsPermissionState()
checkNotificationPiggybackState()
Timber.i("Settings notifications view was initialized")
@@ -50,17 +49,12 @@ class NotificationsPresenter @Inject constructor(
view?.openNotificationExactAlarmSettings()
}
}
- notificationsEnableKey -> {
- if (isNotificationsEnable && view?.isNotificationPermissionGranted == false) {
- view?.requestNotificationPermissions()
- }
- }
isDebugNotificationEnableKey -> {
chuckerCollector.showNotification = isDebugNotificationEnable
}
isNotificationPiggybackEnabledKey -> {
- if (isNotificationPiggybackEnabled && view?.isNotificationPiggybackPermissionGranted == false) {
- view?.openNotificationPiggyBackPermissionDialog()
+ if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) {
+ view?.openNotificationPermissionDialog()
}
}
}
@@ -76,15 +70,9 @@ class NotificationsPresenter @Inject constructor(
view?.openSystemSettings()
}
- fun onNotificationsPermissionResult() {
- view?.run {
- setNotificationPreferencesChecked(isNotificationPermissionGranted)
- }
- }
-
fun onNotificationPiggybackPermissionResult() {
view?.run {
- setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted)
+ setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
}
}
@@ -92,18 +80,10 @@ class NotificationsPresenter @Inject constructor(
view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms())
}
- private fun checkNotificationsPermissionState() {
- if (preferencesRepository.isNotificationsEnable) {
- view?.run {
- setNotificationPreferencesChecked(isNotificationPermissionGranted)
- }
- }
- }
-
private fun checkNotificationPiggybackState() {
if (preferencesRepository.isNotificationPiggybackEnabled) {
view?.run {
- setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted)
+ setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt
index a391681cb..2bf8e31f4 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt
@@ -6,8 +6,6 @@ interface NotificationsView : BaseView {
val isNotificationPermissionGranted: Boolean
- val isNotificationPiggybackPermissionGranted: Boolean
-
fun initView(showDebugNotificationSwitch: Boolean)
fun showFixSyncDialog()
@@ -16,16 +14,10 @@ interface NotificationsView : BaseView {
fun enableNotification(notificationKey: String, enable: Boolean)
- fun requestNotificationPermissions()
-
- fun openNotificationsPermissionDialog()
-
- fun openNotificationPiggyBackPermissionDialog()
+ fun openNotificationPermissionDialog()
fun openNotificationExactAlarmSettings()
- fun setNotificationPreferencesChecked(isChecked: Boolean)
-
fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt
index df2e1348a..8477e3222 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt
@@ -5,12 +5,10 @@ import android.os.Bundle
import android.view.View
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
-import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.base.ErrorDialog
-import io.github.wulkanowy.ui.modules.auth.AuthDialog
import io.github.wulkanowy.ui.modules.main.MainView
import javax.inject.Inject
@@ -77,11 +75,7 @@ class SyncFragment : PreferenceFragmentCompat(),
}
override fun showMessage(text: String) {
- Snackbar.make(requireView(), text, Snackbar.LENGTH_LONG)
- .apply {
- anchorView = requireActivity().findViewById(R.id.main_bottom_nav)
- show()
- }
+ (activity as? BaseActivity<*, *>)?.showMessage(text)
}
override fun showExpiredDialog() {
@@ -100,10 +94,6 @@ class SyncFragment : PreferenceFragmentCompat(),
ErrorDialog.newInstance(error).show(childFragmentManager, "error_details")
}
- override fun showAuthDialog() {
- AuthDialog.newInstance().show(childFragmentManager, "auth_dialog")
- }
-
override fun onResume() {
super.onResume()
preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt
index 598046a2d..361a59440 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt
@@ -8,7 +8,6 @@ import android.view.MenuInflater
import android.view.View
import android.widget.Toast
import androidx.core.content.getSystemService
-import androidx.core.os.bundleOf
import androidx.core.view.get
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
@@ -25,8 +24,6 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.capitalise
import io.github.wulkanowy.utils.getThemeAttrColor
-import io.github.wulkanowy.utils.nullableSerializable
-import io.github.wulkanowy.utils.serializable
import javax.inject.Inject
@AndroidEntryPoint
@@ -41,9 +38,7 @@ class StudentInfoFragment :
lateinit var studentInfoAdapter: StudentInfoAdapter
override val titleStringId: Int
- get() = when (
- requireArguments().nullableSerializable(INFO_TYPE_ARGUMENT_KEY)
- ) {
+ get() = when (requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as? StudentInfoView.Type) {
StudentInfoView.Type.PERSONAL -> R.string.account_personal_data
StudentInfoView.Type.CONTACT -> R.string.account_contact
StudentInfoView.Type.ADDRESS -> R.string.account_address
@@ -63,14 +58,13 @@ class StudentInfoFragment :
fun newInstance(type: StudentInfoView.Type, studentWithSemesters: StudentWithSemesters) =
StudentInfoFragment().apply {
- arguments = bundleOf(
- INFO_TYPE_ARGUMENT_KEY to type,
- STUDENT_ARGUMENT_KEY to studentWithSemesters
- )
+ arguments = Bundle().apply {
+ putSerializable(INFO_TYPE_ARGUMENT_KEY, type)
+ putSerializable(STUDENT_ARGUMENT_KEY, studentWithSemesters)
+ }
}
}
- @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
@@ -80,9 +74,9 @@ class StudentInfoFragment :
super.onViewCreated(view, savedInstanceState)
binding = FragmentStudentInfoBinding.bind(view)
presenter.onAttachView(
- view = this,
- type = requireArguments().serializable(INFO_TYPE_ARGUMENT_KEY),
- studentWithSemesters = requireArguments().serializable(STUDENT_ARGUMENT_KEY),
+ this,
+ requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as StudentInfoView.Type,
+ requireArguments().getSerializable(STUDENT_ARGUMENT_KEY) as StudentWithSemesters
)
}
@@ -159,6 +153,7 @@ class StudentInfoFragment :
)
}
+ @OptIn(ExperimentalStdlibApi::class)
override fun showFamilyTypeData(studentInfo: StudentInfo) {
val items = buildList {
add(studentInfo.firstGuardian?.let {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt
index d917e7d51..2f0d697fc 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt
@@ -160,7 +160,7 @@ class TimetableAdapter @Inject constructor() :
timetableSmallItemDescription.setTextColor(
root.context.getThemeAttrColor(
- if (lesson.canceled) R.attr.colorTimetableCanceled
+ if (lesson.canceled) R.attr.colorPrimary
else R.attr.colorTimetableChange
)
)
@@ -185,7 +185,7 @@ class TimetableAdapter @Inject constructor() :
timetableItemDescription.setTextColor(
root.context.getThemeAttrColor(
- if (lesson.canceled) R.attr.colorTimetableCanceled
+ if (lesson.canceled) R.attr.colorPrimary
else R.attr.colorTimetableChange
)
)
@@ -228,8 +228,8 @@ class TimetableAdapter @Inject constructor() :
}
private fun updateNumberAndSubjectCanceledColor(numberView: TextView, subjectView: TextView) {
- numberView.setTextColor(numberView.context.getThemeAttrColor(R.attr.colorTimetableCanceled))
- subjectView.setTextColor(subjectView.context.getThemeAttrColor(R.attr.colorTimetableCanceled))
+ numberView.setTextColor(numberView.context.getThemeAttrColor(R.attr.colorPrimary))
+ subjectView.setTextColor(subjectView.context.getThemeAttrColor(R.attr.colorPrimary))
}
private fun updateNumberColor(numberView: TextView, lesson: Timetable) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt
index e8a853479..c9243b12e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt
@@ -1,24 +1,26 @@
package io.github.wulkanowy.ui.modules.timetable
import android.annotation.SuppressLint
-import android.app.Dialog
import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
-import androidx.core.os.bundleOf
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.databinding.DialogTimetableBinding
-import io.github.wulkanowy.ui.base.BaseDialogFragment
-import io.github.wulkanowy.utils.*
+import io.github.wulkanowy.utils.capitalise
+import io.github.wulkanowy.utils.getThemeAttrColor
+import io.github.wulkanowy.utils.lifecycleAwareVariable
+import io.github.wulkanowy.utils.toFormattedString
import java.time.Instant
-@AndroidEntryPoint
-class TimetableDialog : BaseDialogFragment