diff --git a/.travis.yml b/.travis.yml
index 8bda02d6..bf6f72f7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ cache:
branches:
only:
- develop
- - 0.12.0
+ - 0.13.0
android:
licenses:
diff --git a/app/build.gradle b/app/build.gradle
index 090a643d..177f15b7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,8 +17,8 @@ android {
testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 16
targetSdkVersion 29
- versionCode 47
- versionName "0.12.0"
+ versionCode 48
+ versionName "0.13.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
@@ -110,8 +110,8 @@ play {
}
ext {
- work_manager = "2.3.0-alpha03"
- room = "2.2.1"
+ work_manager = "2.3.0-beta01"
+ room = "2.2.2"
dagger = "2.25.2"
chucker = "2.0.4"
mockk = "1.9.2"
@@ -119,28 +119,27 @@ ext {
configurations.all {
resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3"
- resolutionStrategy.force "com.google.android.material:material:1.1.0-alpha07"
}
dependencies {
- implementation "io.github.wulkanowy:api:0.12.0"
+ implementation "io.github.wulkanowy:api:0.13.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
- implementation "androidx.core:core-ktx:1.2.0-beta01"
- implementation "androidx.activity:activity-ktx:1.1.0-rc01"
+ implementation "androidx.core:core-ktx:1.2.0-rc01"
+ implementation "androidx.activity:activity-ktx:1.1.0-rc03"
implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.appcompat:appcompat-resources:1.1.0"
- implementation "androidx.fragment:fragment-ktx:1.2.0-rc01"
+ implementation "androidx.fragment:fragment-ktx:1.2.0-rc03"
implementation "androidx.annotation:annotation:1.1.0"
implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.preference:preference-ktx:1.1.0"
- implementation "androidx.recyclerview:recyclerview:1.1.0-rc01"
+ implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03"
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
- implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-rc01"
- implementation "com.google.android.material:material:1.1.0-alpha07"
+ implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
+ implementation "com.google.android.material:material:1.1.0-beta02"
implementation "com.github.wulkanowy:material-chips-input:2.0.1"
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
@@ -157,17 +156,18 @@ dependencies {
implementation "com.google.dagger:dagger-android-support:$dagger"
kapt "com.google.dagger:dagger-compiler:$dagger"
kapt "com.google.dagger:dagger-android-processor:$dagger"
- implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0"
- kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.0"
+ implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2"
+ kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.2"
implementation "eu.davidea:flexible-adapter:5.1.0"
implementation "eu.davidea:flexible-adapter-ui:1.0.0"
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
implementation "com.ncapdevi:frag-nav:3.3.0"
+ implementation "com.github.YarikSOffice:lingver:1.1.0"
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
- implementation "io.reactivex.rxjava2:rxjava:2.2.13"
+ implementation "io.reactivex.rxjava2:rxjava:2.2.15"
implementation "com.google.code.gson:gson:2.8.6"
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
@@ -175,6 +175,7 @@ dependencies {
implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation "com.squareup.okhttp3:logging-interceptor:3.12.6"
implementation "com.mikepenz:aboutlibraries:7.0.4"
+ implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
playImplementation "com.google.firebase:firebase-core:17.2.1"
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
@@ -187,7 +188,7 @@ dependencies {
testImplementation "junit:junit:4.12"
testImplementation "io.mockk:mockk:$mockk"
testImplementation "org.threeten:threetenbp:1.4.0"
- testImplementation "org.mockito:mockito-inline:3.1.0"
+ testImplementation "org.mockito:mockito-inline:3.2.0"
androidTestImplementation "androidx.test:core:1.2.0"
androidTestImplementation "androidx.test:runner:1.2.0"
@@ -195,7 +196,7 @@ dependencies {
androidTestImplementation "io.mockk:mockk-android:$mockk"
androidTestImplementation "androidx.room:room-testing:$room"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
- androidTestImplementation "org.mockito:mockito-android:3.1.0"
+ androidTestImplementation "org.mockito:mockito-android:3.2.0"
}
apply plugin: 'com.google.gms.google-services'
diff --git a/app/src/debug/res/values-pl/strings.xml b/app/src/debug/res/values-pl/strings.xml
deleted file mode 100644
index c90641dd..00000000
--- a/app/src/debug/res/values-pl/strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
- Wulkanowy DEV
-
diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
index 72969059..eee70891 100644
--- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
+++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
@@ -6,10 +6,13 @@ import android.util.Log.VERBOSE
import androidx.multidex.MultiDex
import androidx.work.Configuration
import com.jakewharton.threetenabp.AndroidThreeTen
+import com.yariksoffice.lingver.Lingver
import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.utils.Log
+import io.github.wulkanowy.data.db.SharedPrefProvider
+import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
import io.github.wulkanowy.di.DaggerAppComponent
import io.github.wulkanowy.services.sync.SyncWorkerFactory
import io.github.wulkanowy.ui.base.ThemeManager
@@ -32,6 +35,9 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
@Inject
lateinit var themeManager: ThemeManager
+ @Inject
+ lateinit var sharedPrefProvider: SharedPrefProvider
+
@Inject
lateinit var appInfo: AppInfo
@@ -44,7 +50,9 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
super.onCreate()
AndroidThreeTen.init(this)
RxJavaPlugins.setErrorHandler(::onError)
+ Lingver.init(this)
themeManager.applyDefaultTheme()
+ migrateSharedPreferences()
initLogging()
initCrashlytics(this, appInfo)
@@ -60,6 +68,13 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
}
+ private fun migrateSharedPreferences() {
+ if (sharedPrefProvider.getLong(APP_VERSION_CODE_KEY, -1) < 48) { // #596
+ sharedPrefProvider.delete(getString(R.string.pref_key_grade_modifier_plus))
+ sharedPrefProvider.delete(getString(R.string.pref_key_grade_modifier_minus))
+ }
+ }
+
private fun onError(error: Throwable) {
//RxJava's too deep stack traces may cause SOE on older android devices
val cause = error.cause
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
index a6d0a067..6a953395 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
@@ -8,6 +8,10 @@ import javax.inject.Singleton
@Singleton
class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
+ companion object {
+ const val APP_VERSION_CODE_KEY = "app_version_code"
+ }
+
fun putLong(key: String, value: Long, sync: Boolean = false) {
sharedPref.edit(sync) { putLong(key, value) }
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt
index d3c4f146..3eb57473 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Attendance
import io.reactivex.Maybe
@@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface AttendanceDao {
-
- @Insert
- fun insertAll(exams: List): List
-
- @Delete
- fun deleteAll(exams: List)
+interface AttendanceDao : BaseDao {
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt
index a7413de5..fd58533f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt
@@ -1,20 +1,12 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.reactivex.Maybe
@Dao
-interface AttendanceSummaryDao {
-
- @Insert
- fun insertAll(exams: List): List
-
- @Delete
- fun deleteAll(exams: List)
+interface AttendanceSummaryDao : BaseDao {
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
new file mode 100644
index 00000000..32dbadb8
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Update
+
+interface BaseDao {
+
+ @Insert
+ fun insertAll(items: List): List
+
+ @Update
+ fun updateAll(items: List)
+
+ @Delete
+ fun deleteAll(items: List)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
index 6816ceaa..e13e569b 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.reactivex.Maybe
@@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface CompletedLessonsDao {
-
- @Insert
- fun insertAll(exams: List)
-
- @Delete
- fun deleteAll(exams: List)
+interface CompletedLessonsDao : BaseDao {
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
index 06cd5613..ca6b32df 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Exam
import io.reactivex.Maybe
@@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface ExamDao {
-
- @Insert
- fun insertAll(exams: List): List
-
- @Delete
- fun deleteAll(exams: List)
+interface ExamDao : BaseDao {
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt
index 0bd210b0..c74d1937 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt
@@ -1,26 +1,14 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
-import androidx.room.Update
import io.github.wulkanowy.data.db.entities.Grade
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
-interface GradeDao {
-
- @Insert
- fun insertAll(grades: List)
-
- @Update
- fun updateAll(grade: List)
-
- @Delete
- fun deleteAll(grades: List)
+interface GradeDao : BaseDao {
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
fun loadAll(semesterId: Int, studentId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt
index 99a1269b..37609286 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface GradePointsStatisticsDao {
-
- @Insert
- fun insertAll(gradesStatistics: List)
-
- @Delete
- fun deleteAll(gradesStatistics: List)
+interface GradePointsStatisticsDao : BaseDao {
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Maybe
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
index 338c369f..6faa35d0 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeStatistics
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface GradeStatisticsDao {
-
- @Insert
- fun insertAll(gradesStatistics: List)
-
- @Delete
- fun deleteAll(gradesStatistics: List)
+interface GradeStatisticsDao : BaseDao {
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt
index 3f2e87bd..1165ef07 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface GradeSummaryDao {
-
- @Insert
- fun insertAll(gradesSummary: List)
-
- @Delete
- fun deleteAll(gradesSummary: List)
+interface GradeSummaryDao : BaseDao {
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
fun loadAll(semesterId: Int, studentId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt
index 253bdb11..1947a0df 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Homework
import io.reactivex.Maybe
@@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface HomeworkDao {
-
- @Insert
- fun insertAll(homework: List)
-
- @Delete
- fun deleteAll(homework: List)
+interface HomeworkDao : BaseDao {
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt
index afd7905c..f16c28d9 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt
@@ -1,10 +1,7 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
-import androidx.room.Update
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.reactivex.Maybe
import org.threeten.bp.LocalDate
@@ -12,18 +9,8 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface LuckyNumberDao {
-
- @Insert
- fun insert(luckyNumber: LuckyNumber)
-
- @Update
- fun update(luckyNumber: LuckyNumber)
-
- @Delete
- fun delete(luckyNumber: LuckyNumber)
+interface LuckyNumberDao : BaseDao {
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
fun load(studentId: Int, date: LocalDate): Maybe
-
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
index 4f72c6c9..6d14ad01 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
@@ -1,24 +1,12 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
-import androidx.room.Update
import io.github.wulkanowy.data.db.entities.Message
import io.reactivex.Maybe
@Dao
-interface MessagesDao {
-
- @Insert
- fun insertAll(messages: List)
-
- @Delete
- fun deleteAll(messages: List)
-
- @Update
- fun updateAll(messages: List)
+interface MessagesDao : BaseDao {
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
fun loadAll(studentId: Int, folder: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
index d6b97f6a..b05b2d9c 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
@@ -1,20 +1,12 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.MobileDevice
import io.reactivex.Maybe
@Dao
-interface MobileDeviceDao {
-
- @Insert
- fun insertAll(devices: List)
-
- @Delete
- fun deleteAll(devices: List)
+interface MobileDeviceDao : BaseDao {
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
fun loadAll(studentId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt
index 867e06a2..ea2fc6eb 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt
@@ -1,28 +1,15 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
-import androidx.room.Update
import io.github.wulkanowy.data.db.entities.Note
import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
-interface NoteDao {
-
- @Insert
- fun insertAll(notes: List)
-
- @Update
- fun updateAll(notes: List)
-
- @Delete
- fun deleteAll(notes: List)
+interface NoteDao : BaseDao {
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
fun loadAll(studentId: Int): Maybe>
-
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
index 7c5fd6ca..afb941b1 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Recipient
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface RecipientDao {
-
- @Insert
- fun insertAll(messages: List)
-
- @Delete
- fun deleteAll(messages: List)
+interface RecipientDao : BaseDao {
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
fun load(studentId: Int, role: Int, unitId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
index 1898390a..6ddfd494 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface ReportingUnitDao {
-
- @Insert
- fun insertAll(reportingUnits: List)
-
- @Delete
- fun deleteAll(reportingUnits: List)
+interface ReportingUnitDao : BaseDao {
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
fun load(studentId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt
index c2b2e0bc..e9bd6755 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.School
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface SchoolDao {
-
- @Insert
- fun insert(school: School)
-
- @Delete
- fun delete(school: School)
+interface SchoolDao : BaseDao {
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
fun load(studentId: Int, classId: Int): Maybe
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt
index 01841fb6..654b80f3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Semester
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface SemesterDao {
-
- @Insert
- fun insertAll(semester: List)
-
- @Delete
- fun deleteAll(semester: List)
+interface SemesterDao : BaseDao {
@Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
fun loadAll(studentId: Int, classId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt
index 725a371a..525a7129 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt
@@ -1,20 +1,12 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Subject
import io.reactivex.Maybe
@Dao
-interface SubjectDao {
-
- @Insert
- fun insertAll(subjects: List): List
-
- @Delete
- fun deleteAll(subjects: List)
+interface SubjectDao : BaseDao {
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
fun loadAll(diaryId: Int, studentId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt
index e7794248..5ea237a8 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Teacher
import io.reactivex.Maybe
@@ -10,13 +8,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface TeacherDao {
-
- @Insert
- fun insertAll(teachers: List)
-
- @Delete
- fun deleteAll(teachers: List)
+interface TeacherDao : BaseDao {
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
fun loadAll(studentId: Int, classId: Int): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt
index abe21361..6b62cc82 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt
@@ -1,8 +1,6 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
-import androidx.room.Delete
-import androidx.room.Insert
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Timetable
import io.reactivex.Maybe
@@ -11,13 +9,7 @@ import javax.inject.Singleton
@Singleton
@Dao
-interface TimetableDao {
-
- @Insert
- fun insertAll(exams: List): List
-
- @Delete
- fun deleteAll(exams: List)
+interface TimetableDao : BaseDao {
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt
index 115c8965..b461ca22 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt
@@ -12,15 +12,15 @@ import javax.inject.Singleton
class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) {
fun saveLuckyNumber(luckyNumber: LuckyNumber) {
- luckyNumberDb.insert(luckyNumber)
+ luckyNumberDb.insertAll(listOf(luckyNumber))
}
fun updateLuckyNumber(luckyNumber: LuckyNumber) {
- luckyNumberDb.update(luckyNumber)
+ luckyNumberDb.updateAll(listOf(luckyNumber))
}
fun deleteLuckyNumber(luckyNumber: LuckyNumber) {
- luckyNumberDb.delete(luckyNumber)
+ luckyNumberDb.deleteAll(listOf(luckyNumber))
}
fun getLuckyNumber(semester: Semester, date: LocalDate): Maybe {
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt
index b2bff1e7..90c510ef 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt
@@ -11,7 +11,6 @@ import io.reactivex.Single
import org.threeten.bp.LocalDateTime.now
import javax.inject.Inject
import javax.inject.Singleton
-import io.github.wulkanowy.api.messages.Message as ApiMessage
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient
@Singleton
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt
index 8f0efa5b..473ffa7f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt
@@ -3,7 +3,6 @@ package io.github.wulkanowy.data.repositories.mobiledevice
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
import io.github.wulkanowy.data.db.entities.MobileDevice
import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
import io.reactivex.Maybe
import javax.inject.Inject
import javax.inject.Singleton
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
index e1caf920..07a3654a 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
@@ -33,6 +33,10 @@ class PreferencesRepository @Inject constructor(
val gradeColorTheme: String
get() = getString(R.string.pref_key_grade_color_scheme, R.string.pref_default_grade_color_scheme)
+ val appLanguageKey = context.getString(R.string.pref_key_app_language)
+ val appLanguage
+ get() = getString(appLanguageKey, R.string.pref_default_app_language)
+
val serviceEnableKey = context.getString(R.string.pref_key_services_enable)
val isServiceEnabled: Boolean
get() = getBoolean(serviceEnableKey, R.bool.pref_default_services_enable)
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt
index 6b8328ec..9b1d4ac2 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt
@@ -15,7 +15,7 @@ class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao)
return recipientDb.load(student.studentId, role, unit.realId).filter { !it.isEmpty() }
}
- fun saveRecipients(recipients: List) {
+ fun saveRecipients(recipients: List): List {
return recipientDb.insertAll(recipients)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt
index b4281cbf..6f9eec3f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt
@@ -18,7 +18,7 @@ class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: Report
return reportingUnitDb.loadOne(student.studentId, unitId)
}
- fun saveReportingUnits(reportingUnits: List) {
+ fun saveReportingUnits(reportingUnits: List): List {
return reportingUnitDb.insertAll(reportingUnits)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt
index 1692e39b..d8727287 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt
@@ -9,11 +9,11 @@ import javax.inject.Inject
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
fun saveSchool(school: School) {
- schoolDb.insert(school)
+ schoolDb.insertAll(listOf(school))
}
fun deleteSchool(school: School) {
- schoolDb.delete(school)
+ schoolDb.deleteAll(listOf(school))
}
fun getSchool(semester: Semester): Maybe {
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt
index e6d74421..f27199f2 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt
@@ -24,7 +24,7 @@ class StudentLocal @Inject constructor(
fun getStudents(decryptPass: Boolean): Maybe> {
return studentDb.loadAll()
.map { list -> list.map { it.apply { if (decryptPass) password = decrypt(password) } } }
- .filter { !it.isEmpty() }
+ .filter { it.isNotEmpty() }
}
fun getCurrentStudent(decryptPass: Boolean): Maybe {
diff --git a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
index 42e50fa4..4f568385 100644
--- a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
@@ -2,6 +2,7 @@ package io.github.wulkanowy.di
import android.appwidget.AppWidgetManager
import android.content.Context
+import com.yariksoffice.lingver.Lingver
import dagger.Module
import dagger.Provides
import eu.davidea.flexibleadapter.FlexibleAdapter
@@ -32,4 +33,8 @@ internal class AppModule {
@Singleton
@Provides
fun provideAppInfo() = AppInfo()
+
+ @Singleton
+ @Provides
+ fun provideLingver() = Lingver.getInstance()
}
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 98fc3522..6b046977 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
@@ -11,6 +11,7 @@ import androidx.work.NetworkType.UNMETERED
import androidx.work.PeriodicWorkRequestBuilder
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.preferences.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.DebugChannel
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
@@ -32,10 +33,6 @@ class SyncManager @Inject constructor(
appInfo: AppInfo
) {
- companion object {
- private const val APP_VERSION_CODE_KEY = "app_version_code"
- }
-
init {
if (now().isHolidays) stopSyncWorker()
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 f0e51e31..ab67d8ac 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
@@ -22,7 +22,8 @@ import io.github.wulkanowy.utils.FragmentLifecycleLogger
import io.github.wulkanowy.utils.getThemeAttrColor
import javax.inject.Inject
-abstract class BaseActivity> : AppCompatActivity(), BaseView, HasAndroidInjector {
+abstract class BaseActivity> : AppCompatActivity(), BaseView,
+ HasAndroidInjector {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector
@@ -53,13 +54,15 @@ abstract class BaseActivity> : AppCompatActivity
override fun showError(text: String, error: Throwable) {
if (messageContainer != null) {
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
- .setAction(R.string.all_details) {
- ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
- }
+ .setAction(R.string.all_details) { showErrorDetailsDialog(error) }
.show()
} else showMessage(text)
}
+ override fun showErrorDetailsDialog(error: Throwable) {
+ ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
+ }
+
override fun showMessage(text: String) {
if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
else Toast.makeText(this, text, Toast.LENGTH_LONG).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
new file mode 100644
index 00000000..fdc46371
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
@@ -0,0 +1,27 @@
+package io.github.wulkanowy.ui.base
+
+import android.widget.Toast
+import dagger.android.support.DaggerAppCompatDialogFragment
+
+abstract class BaseDialogFragment : DaggerAppCompatDialogFragment(), BaseView {
+
+ override fun showError(text: String, error: Throwable) {
+ showMessage(text)
+ }
+
+ override fun showMessage(text: String) {
+ Toast.makeText(context, text, Toast.LENGTH_LONG).show()
+ }
+
+ override fun showExpiredDialog() {
+ (activity as? BaseActivity<*>)?.showExpiredDialog()
+ }
+
+ override fun openClearLoginView() {
+ (activity as? BaseActivity<*>)?.openClearLoginView()
+ }
+
+ override fun showErrorDetailsDialog(error: Throwable) {
+ ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
+ }
+}
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 4b2ad053..2f5878d0 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
@@ -13,15 +13,17 @@ abstract class BaseFragment : DaggerFragment(), BaseView {
override fun showError(text: String, error: Throwable) {
if (messageContainer != null) {
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
- .setAction(R.string.all_details) {
- if (isAdded) ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
- }
+ .setAction(R.string.all_details) { if (isAdded) showErrorDetailsDialog(error) }
.show()
} else {
(activity as? BaseActivity<*>)?.showError(text, error)
}
}
+ override fun showErrorDetailsDialog(error: Throwable) {
+ ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
+ }
+
override fun showMessage(text: String) {
if (messageContainer != null) {
Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
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 7681263b..0f4df92c 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
@@ -9,4 +9,6 @@ interface BaseView {
fun showExpiredDialog()
fun openClearLoginView()
+
+ fun showErrorDetailsDialog(error: Throwable)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt
index 46dc5cfe..22276bdf 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt
@@ -47,6 +47,11 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback))
}
+ override val faqRes: Triple?
+ get() = context?.run {
+ Triple(getString(R.string.about_faq), getString(R.string.about_faq_summary), getCompatDrawable(R.drawable.ic_about_faq))
+ }
+
override val discordRes: Triple?
get() = context?.run {
Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord))
@@ -130,6 +135,10 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
}
}
+ override fun openFaqPage() {
+ context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania", ::showMessage)
+ }
+
override fun openLicenses() {
(activity as? MainActivity)?.pushView(LicenseFragment.newInstance())
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt
index 5303d361..8087c955 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt
@@ -28,10 +28,15 @@ class AboutPresenter @Inject constructor(
view?.run {
when (item.title) {
feedbackRes?.first -> {
- Timber.i("Opening email client ")
+ Timber.i("Opening email client")
openEmailClient()
analytics.logEvent("about_open", "name" to "feedback")
}
+ faqRes?.first -> {
+ Timber.i("Opening faq page")
+ openFaqPage()
+ analytics.logEvent("about_open", "name" to "faq")
+ }
discordRes?.first -> {
Timber.i("Opening discord")
openDiscordInvite()
@@ -61,6 +66,7 @@ class AboutPresenter @Inject constructor(
updateData(AboutScrollableHeader(), listOfNotNull(
versionRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
feedbackRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
+ faqRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
discordRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
homepageRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
licensesRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt
index 318a75e4..34850bae 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt
@@ -9,6 +9,8 @@ interface AboutView : BaseView {
val feedbackRes: Triple?
+ val faqRes: Triple?
+
val discordRes: Triple?
val homepageRes: Triple?
@@ -25,6 +27,8 @@ interface AboutView : BaseView {
fun openEmailClient()
+ fun openFaqPage()
+
fun openHomepage()
fun openLicenses()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt
index f23a1eb5..cfff31c9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt
@@ -7,18 +7,17 @@ import android.view.ViewGroup
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import androidx.appcompat.app.AlertDialog
-import dagger.android.support.DaggerAppCompatDialogFragment
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.R
-import io.github.wulkanowy.ui.base.BaseActivity
+import io.github.wulkanowy.ui.base.BaseDialogFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.dialog_account.*
import javax.inject.Inject
-class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
+class AccountDialog : BaseDialogFragment(), AccountView {
@Inject
lateinit var presenter: AccountPresenter
@@ -77,14 +76,6 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
}
}
- override fun showExpiredDialog() {
- (activity as? BaseActivity<*>)?.showExpiredDialog()
- }
-
- override fun openClearLoginView() {
- (activity as? BaseActivity<*>)?.openClearLoginView()
- }
-
override fun showConfirmDialog() {
context?.let {
AlertDialog.Builder(it)
@@ -105,4 +96,3 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
super.onDestroy()
}
}
-
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 fb6309f7..bc7c1cac 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
@@ -6,7 +6,11 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
+import android.view.View.GONE
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
import android.view.ViewGroup
+import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
@@ -17,9 +21,11 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
+import io.github.wulkanowy.utils.SchooldaysRangeLimiter
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_attendance.*
+import org.threeten.bp.LocalDate
import javax.inject.Inject
class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView,
@@ -70,7 +76,11 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
}
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ attendanceErrorRetry.setOnClickListener { presenter.onRetry() }
+ attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+
attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() }
+ attendanceNavDate.setOnClickListener { presenter.onPickDate() }
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
@@ -110,11 +120,19 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
}
override fun showEmpty(show: Boolean) {
- attendanceEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ attendanceEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ attendanceError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ attendanceErrorMessage.text = message
}
override fun showProgress(show: Boolean) {
- attendanceProgress.visibility = if (show) View.VISIBLE else View.GONE
+ attendanceProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -122,7 +140,7 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
}
override fun showContent(show: Boolean) {
- attendanceRecycler.visibility = if (show) View.VISIBLE else View.GONE
+ attendanceRecycler.visibility = if (show) VISIBLE else GONE
}
override fun hideRefresh() {
@@ -130,17 +148,32 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
}
override fun showPreButton(show: Boolean) {
- attendancePreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ attendancePreviousButton.visibility = if (show) VISIBLE else INVISIBLE
}
override fun showNextButton(show: Boolean) {
- attendanceNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ attendanceNextButton.visibility = if (show) VISIBLE else INVISIBLE
}
override fun showAttendanceDialog(lesson: Attendance) {
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
}
+ override fun showDatePickerDialog(currentDate: LocalDate) {
+ val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
+ presenter.onDateSet(year, month + 1, dayOfMonth)
+ }
+ val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
+ currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
+
+ with(datePickerDialog) {
+ setDateRangeLimiter(SchooldaysRangeLimiter())
+ version = DatePickerDialog.Version.VERSION_2
+ scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
+ show(this@AttendanceFragment.parentFragmentManager, null)
+ }
+ }
+
override fun openSummaryView() {
(activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance())
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
index b8114208..1490ee6e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
@@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.attendance
+import android.annotation.SuppressLint
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
@@ -37,10 +38,13 @@ class AttendancePresenter @Inject constructor(
lateinit var currentDate: LocalDate
private set
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: AttendanceView, date: Long?) {
super.onAttachView(view)
view.initView()
Timber.i("Attendance view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
if (currentDate.isHolidays) setBaseDateOnHolidays()
reloadView()
@@ -56,11 +60,32 @@ class AttendancePresenter @Inject constructor(
reloadView()
}
+ fun onPickDate() {
+ view?.showDatePickerDialog(currentDate)
+ }
+
+ fun onDateSet(year: Int, month: Int, day: Int) {
+ loadData(LocalDate.of(year, month, day))
+ reloadView()
+ }
+
fun onSwipeRefresh() {
Timber.i("Force refreshing the attendance")
loadData(currentDate, true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(currentDate, true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onViewReselected() {
Timber.i("Attendance view is reselected")
view?.also { view ->
@@ -130,18 +155,29 @@ class AttendancePresenter @Inject constructor(
view?.apply {
updateData(it)
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
}
analytics.logEvent("load_attendance", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading attendance result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
}
)
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun reloadView() {
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
view?.apply {
@@ -149,11 +185,13 @@ class AttendancePresenter @Inject constructor(
enableSwipe(false)
showContent(false)
showEmpty(false)
+ showErrorView(false)
clearData()
reloadNavigation()
}
}
+ @SuppressLint("DefaultLocale")
private fun reloadNavigation() {
view?.apply {
showPreButton(!currentDate.minusDays(1).isHolidays)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
index 04fe94a4..a6d0d4ba 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
@@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.attendance
import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.ui.base.BaseView
+import org.threeten.bp.LocalDate
interface AttendanceView : BaseView {
@@ -23,6 +24,10 @@ interface AttendanceView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
@@ -35,6 +40,8 @@ interface AttendanceView : BaseView {
fun showAttendanceDialog(lesson: Attendance)
+ fun showDatePickerDialog(currentDate: LocalDate)
+
fun openSummaryView()
fun popView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt
index 4fe490d5..fc360184 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt
@@ -57,6 +57,8 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
}
attendanceSummarySwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ attendanceSummaryErrorRetry.setOnClickListener { presenter.onRetry() }
+ attendanceSummaryErrorDetails.setOnClickListener { presenter.onDetailsClick() }
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
@@ -93,6 +95,14 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
attendanceSummaryEmpty.visibility = if (show) VISIBLE else GONE
}
+ override fun showErrorView(show: Boolean) {
+ attendanceSummaryError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ attendanceSummaryErrorMessage.text = message
+ }
+
override fun showProgress(show: Boolean) {
attendanceSummaryProgress.visibility = if (show) VISIBLE else GONE
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt
index 40339299..3ce85d81 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt
@@ -33,10 +33,13 @@ class AttendanceSummaryPresenter @Inject constructor(
var currentSubjectId = -1
private set
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: AttendanceSummaryView, subjectId: Int?) {
super.onAttachView(view)
view.initView()
Timber.i("Attendance summary view was initialized with subject id ${subjectId ?: -1}")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData(subjectId ?: -1)
loadSubjects()
}
@@ -46,12 +49,26 @@ class AttendanceSummaryPresenter @Inject constructor(
loadData(currentSubjectId, true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(currentSubjectId, true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onSubjectSelected(name: String?) {
Timber.i("Select attendance summary subject $name")
view?.run {
showContent(false)
showProgress(true)
enableSwipe(false)
+ showEmpty(false)
+ showErrorView(false)
clearView()
}
(subjects.singleOrNull { it.name == name }?.realId ?: -1).let {
@@ -88,13 +105,23 @@ class AttendanceSummaryPresenter @Inject constructor(
analytics.logEvent("load_attendance_summary", "items" to it.first.size, "force_refresh" to forceRefresh, "item_id" to subjectId)
}) {
Timber.i("Loading attendance summary result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
}
)
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun loadSubjects() {
Timber.i("Loading attendance summary subjects started")
disposable.add(studentRepository.getCurrentStudent()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt
index 50f03e20..b86f6590 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt
@@ -18,6 +18,10 @@ interface AttendanceSummaryView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun updateDataSet(data: List, header: AttendanceSummaryScrollableHeader)
fun updateSubjects(data: ArrayList)
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 c762fa15..b880f465 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
@@ -61,6 +61,9 @@ class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.
}
examSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ examErrorRetry.setOnClickListener { presenter.onRetry() }
+ examErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+
examPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
examNextButton.setOnClickListener { presenter.onNextWeek() }
@@ -95,6 +98,14 @@ class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.
examEmpty.visibility = if (show) VISIBLE else GONE
}
+ override fun showErrorView(show: Boolean) {
+ examError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ examErrorMessage.text = message
+ }
+
override fun showProgress(show: Boolean) {
examProgress.visibility = if (show) VISIBLE else GONE
}
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 93109922..35cf5b94 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
@@ -36,10 +36,13 @@ class ExamPresenter @Inject constructor(
lateinit var currentDate: LocalDate
private set
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: ExamView, date: Long?) {
super.onAttachView(view)
view.initView()
Timber.i("Exam view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
if (currentDate.isHolidays) setBaseDateOnHolidays()
reloadView()
@@ -60,6 +63,18 @@ class ExamPresenter @Inject constructor(
loadData(currentDate, true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(currentDate, true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onExamItemSelected(item: AbstractFlexibleItem<*>?) {
if (item is ExamItem) {
Timber.i("Select exam item ${item.exam.id}")
@@ -116,17 +131,28 @@ class ExamPresenter @Inject constructor(
view?.apply {
updateData(it)
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
}
analytics.logEvent("load_exam", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading exam result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
})
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun createExamItems(items: Map>): List {
return items.flatMap {
ExamHeader(it.key).let { header ->
@@ -142,6 +168,7 @@ class ExamPresenter @Inject constructor(
enableSwipe(false)
showContent(false)
showEmpty(false)
+ showErrorView(false)
clearData()
reloadNavigation()
}
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 888cb05e..5f4a7430 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
@@ -21,6 +21,10 @@ interface ExamView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
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 68ae57ec..884b9f8c 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
@@ -13,6 +13,7 @@ import androidx.appcompat.app.AlertDialog
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
+import io.github.wulkanowy.ui.base.ErrorDialog
import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment
import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
@@ -83,7 +84,8 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
setElevationCompat(context.dpToPx(4f))
}
- gradeSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ gradeErrorRetry.setOnClickListener { presenter.onRetry() }
+ gradeErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -104,22 +106,18 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
gradeProgress.visibility = if (show) VISIBLE else INVISIBLE
}
- override fun showEmpty(show: Boolean) {
- gradeEmpty.visibility = if (show) VISIBLE else INVISIBLE
+ override fun showErrorView(show: Boolean) {
+ gradeError.visibility = if (show) VISIBLE else INVISIBLE
}
- override fun showRefresh(show: Boolean) {
- gradeSwipe.isRefreshing = show
+ override fun setErrorDetails(message: String) {
+ gradeErrorMessage.text = message
}
override fun showSemesterSwitch(show: Boolean) {
semesterSwitchMenu?.isVisible = show
}
- override fun enableSwipe(enable: Boolean) {
- gradeSwipe.isEnabled = enable
- }
-
override fun showSemesterDialog(selectedIndex: Int) {
val choices = arrayOf(
getString(R.string.grade_semester, 1),
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt
index 2ee69480..d8c20238 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt
@@ -25,14 +25,14 @@ class GradePresenter @Inject constructor(
private val loadedSemesterId = mutableMapOf()
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: GradeView, savedIndex: Int?) {
super.onAttachView(view)
selectedIndex = savedIndex ?: 0
- view.run {
- initView()
- enableSwipe(false)
- }
+ view.initView()
Timber.i("Grade view was initialized with $selectedIndex index")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
@@ -71,7 +71,7 @@ class GradePresenter @Inject constructor(
view?.apply {
showContent(true)
showProgress(false)
- showEmpty(false)
+ showErrorView(false)
loadedSemesterId[currentPageIndex] = semesterId
}
}
@@ -80,10 +80,18 @@ class GradePresenter @Inject constructor(
if (semesters.isNotEmpty()) loadChild(index)
}
- fun onSwipeRefresh() {
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
loadData()
}
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
private fun loadData() {
Timber.i("Loading grade data started")
disposable.add(studentRepository.getCurrentStudent()
@@ -96,25 +104,28 @@ class GradePresenter @Inject constructor(
}
.subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread)
- .doFinally { view?.showRefresh(false) }
+ .doFinally { view?.showProgress(false) }
.subscribe({
view?.run {
Timber.i("Loading grade result: Attempt load index $currentPageIndex")
loadChild(currentPageIndex)
- enableSwipe(false)
+ showErrorView(false)
showSemesterSwitch(true)
}
}) {
Timber.i("Loading grade result: An exception occurred")
errorHandler.dispatch(it)
- view?.run {
- showProgress(false)
- showEmpty(true)
- enableSwipe(true)
- }
})
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ lastError = error
+ view?.run {
+ showErrorView(true)
+ setErrorDetails(message)
+ }
+ }
+
private fun loadChild(index: Int, forceRefresh: Boolean = false) {
semesters.first { it.semesterName == selectedIndex }.semesterId.also {
if (forceRefresh || loadedSemesterId[index] != it) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt
index a37e6d67..bbdbc32e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt
@@ -12,16 +12,14 @@ interface GradeView : BaseView {
fun showProgress(show: Boolean)
- fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
- fun showRefresh(show: Boolean)
+ fun setErrorDetails(message: String)
fun showSemesterSwitch(show: Boolean)
fun showSemesterDialog(selectedIndex: Int)
- fun enableSwipe(enable: Boolean)
-
fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean)
fun notifyChildParentReselected(index: Int)
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 8993760d..b3dd3587 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
@@ -18,6 +18,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.ui.base.BaseFragment
+import io.github.wulkanowy.ui.base.ErrorDialog
import io.github.wulkanowy.ui.modules.grade.GradeFragment
import io.github.wulkanowy.ui.modules.grade.GradeView
import io.github.wulkanowy.ui.modules.main.MainActivity
@@ -90,6 +91,8 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
)
}
gradeDetailsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ gradeDetailsErrorRetry.setOnClickListener { presenter.onRetry() }
+ gradeDetailsErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -141,6 +144,14 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
gradeDetailsEmpty.visibility = if (show) VISIBLE else INVISIBLE
}
+ override fun showErrorView(show: Boolean) {
+ gradeDetailsError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ gradeDetailsErrorMessage.text = message
+ }
+
override fun showRefresh(show: Boolean) {
gradeDetailsSwipe.isRefreshing = show
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt
index 96b55686..647047c6 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.grade.details
-import android.widget.Toast
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.repositories.grade.GradeRepository
@@ -31,9 +30,12 @@ class GradeDetailsPresenter @Inject constructor(
private var currentSemesterId = 0
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: GradeDetailsView) {
super.onAttachView(view)
view.initView()
+ errorHandler.showErrorMessage = ::showErrorViewOnError
}
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
@@ -90,6 +92,18 @@ class GradeDetailsPresenter @Inject constructor(
view?.notifyParentRefresh()
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ view?.notifyParentRefresh()
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onParentViewReselected() {
view?.run {
if (!isViewEmpty) {
@@ -140,21 +154,32 @@ class GradeDetailsPresenter @Inject constructor(
}
.subscribe({
Timber.i("Loading grade details result: Success")
- newGradesAmount = it.sumBy { gradeDetailsHeader -> gradeDetailsHeader.newGrades }
+ newGradesAmount = it.sumBy { gradeDetailsHeader -> gradeDetailsHeader.newGrades }
updateMarkAsDoneButton()
view?.run {
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
updateData(it)
}
analytics.logEvent("load_grade_details", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading grade details result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
})
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun createGradeItems(items: Map>, averages: Map): List {
val isGradeExpandable = preferencesRepository.isGradeExpandable
val gradeColorTheme = preferencesRepository.gradeColorTheme
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt
index fb806351..dad4ac6e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt
@@ -38,6 +38,10 @@ interface GradeDetailsView : BaseView {
fun showProgress(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun enableSwipe(enable: Boolean)
fun showRefresh(show: Boolean)
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 94b5f474..5bcf167e 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
@@ -111,9 +111,11 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
setOnItemSelectedListener { presenter.onSubjectSelected(it?.text?.toString()) }
}
- gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
-
gradeStatisticsSubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
+
+ gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ gradeStatisticsErrorRetry.setOnClickListener { presenter.onRetry() }
+ gradeStatisticsErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun updateSubjects(data: ArrayList) {
@@ -228,6 +230,14 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
gradeStatisticsEmpty.visibility = if (show) View.VISIBLE else View.INVISIBLE
}
+ override fun showErrorView(show: Boolean) {
+ gradeStatisticsError.visibility = if (show) View.VISIBLE else View.GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ gradeStatisticsErrorMessage.text = message
+ }
+
override fun showProgress(show: Boolean) {
gradeStatisticsProgress.visibility = if (show) View.VISIBLE else View.GONE
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt
index 1e053701..9795c130 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt
@@ -30,6 +30,8 @@ class GradeStatisticsPresenter @Inject constructor(
private var currentSubjectName: String = "Wszystkie"
+ private lateinit var lastError: Throwable
+
var currentType: ViewType = ViewType.PARTIAL
private set
@@ -37,6 +39,7 @@ class GradeStatisticsPresenter @Inject constructor(
super.onAttachView(view)
currentType = type ?: ViewType.PARTIAL
view.initView()
+ errorHandler.showErrorMessage = ::showErrorViewOnError
}
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
@@ -51,6 +54,7 @@ class GradeStatisticsPresenter @Inject constructor(
enableSwipe(false)
showRefresh(false)
showBarContent(false)
+ showErrorView(false)
showEmpty(false)
clearView()
}
@@ -62,6 +66,18 @@ class GradeStatisticsPresenter @Inject constructor(
view?.notifyParentRefresh()
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ view?.notifyParentRefresh()
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onSubjectSelected(name: String?) {
Timber.i("Select grade stats subject $name")
view?.run {
@@ -70,6 +86,7 @@ class GradeStatisticsPresenter @Inject constructor(
showProgress(true)
enableSwipe(false)
showEmpty(false)
+ showErrorView(false)
clearView()
}
(subjects.singleOrNull { it.name == name }?.name)?.let {
@@ -86,6 +103,7 @@ class GradeStatisticsPresenter @Inject constructor(
showProgress(true)
enableSwipe(false)
showEmpty(false)
+ showErrorView(false)
clearView()
}
loadDataByType(currentSemesterId, currentSubjectName, type)
@@ -146,12 +164,12 @@ class GradeStatisticsPresenter @Inject constructor(
showEmpty(it.isEmpty())
showBarContent(false)
showPieContent(it.isNotEmpty())
+ showErrorView(false)
updatePieData(it, preferencesRepository.gradeColorTheme)
}
analytics.logEvent("load_grade_statistics", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.e("Loading grade stats result: An exception occurred")
- view?.run { showEmpty(isPieViewEmpty) }
errorHandler.dispatch(it)
})
}
@@ -177,12 +195,12 @@ class GradeStatisticsPresenter @Inject constructor(
showEmpty(false)
showPieContent(false)
showBarContent(true)
+ showErrorView(false)
updateBarData(it)
}
analytics.logEvent("load_grade_points_statistics", "force_refresh" to forceRefresh)
}, {
Timber.e("Loading grade points stats result: An exception occurred")
- view?.run { showEmpty(isBarViewEmpty) }
errorHandler.dispatch(it)
}, {
Timber.d("Loading grade points stats result: No point stats found")
@@ -193,4 +211,15 @@ class GradeStatisticsPresenter @Inject constructor(
})
)
}
+
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isBarViewEmpty || isPieViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt
index d6e66fac..a214744c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt
@@ -32,6 +32,10 @@ interface GradeStatisticsView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
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 7699a641..05fde522 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
@@ -56,6 +56,8 @@ class GradeSummaryFragment : BaseFragment(), GradeSummaryView, GradeView.GradeCh
adapter = gradeSummaryAdapter
}
gradeSummarySwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ gradeSummaryErrorRetry.setOnClickListener { presenter.onRetry() }
+ gradeSummaryErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun updateData(data: List, header: GradeSummaryScrollableHeader) {
@@ -82,6 +84,14 @@ class GradeSummaryFragment : BaseFragment(), GradeSummaryView, GradeView.GradeCh
gradeSummaryEmpty.visibility = if (show) VISIBLE else INVISIBLE
}
+ override fun showErrorView(show: Boolean) {
+ gradeSummaryError.visibility = if (show) VISIBLE else INVISIBLE
+ }
+
+ override fun setErrorDetails(message: String) {
+ gradeSummaryErrorMessage.text = message
+ }
+
override fun showProgress(show: Boolean) {
gradeSummaryProgress.visibility = if (show) VISIBLE else GONE
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt
index 3f8fd0ed..1aaa9d09 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt
@@ -25,9 +25,12 @@ class GradeSummaryPresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter(errorHandler, studentRepository, schedulers) {
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: GradeSummaryView) {
super.onAttachView(view)
view.initView()
+ errorHandler.showErrorMessage = ::showErrorViewOnError
}
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
@@ -56,21 +59,44 @@ class GradeSummaryPresenter @Inject constructor(
view?.run {
showEmpty(gradeSummaryItems.isEmpty())
showContent(gradeSummaryItems.isNotEmpty())
+ showErrorView(false)
updateData(gradeSummaryItems, gradeSummaryHeader)
}
analytics.logEvent("load_grade_summary", "items" to gradeSummaryItems.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading grade summary result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
})
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
fun onSwipeRefresh() {
Timber.i("Force refreshing the grade summary")
view?.notifyParentRefresh()
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ view?.notifyParentRefresh()
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onParentViewReselected() {
view?.run {
if (!isViewEmpty) resetView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt
index 9e9c6e58..cf318487 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt
@@ -26,6 +26,10 @@ interface GradeSummaryView : BaseView {
fun showContent(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showEmpty(show: Boolean)
fun notifyParentDataLoaded(semesterId: Int)
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 8195dd20..3f8f1359 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
@@ -3,6 +3,8 @@ package io.github.wulkanowy.ui.modules.homework
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.view.ViewGroup
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
@@ -34,6 +36,8 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
override val titleStringId get() = R.string.homework_title
+ override val isViewEmpty get() = homeworkAdapter.isEmpty
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_homework, container, false)
}
@@ -41,7 +45,7 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
messageContainer = homeworkRecycler
- presenter.onAttachView(this, savedInstanceState?.getLong(HomeworkFragment.SAVED_DATE_KEY))
+ presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY))
}
override fun initView() {
@@ -56,6 +60,9 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
}
homeworkSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ homeworkErrorRetry.setOnClickListener { presenter.onRetry() }
+ homeworkErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+
homeworkPreviousButton.setOnClickListener { presenter.onPreviousDay() }
homeworkNextButton.setOnClickListener { presenter.onNextDay() }
@@ -74,18 +81,24 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
homeworkNavDate.text = date
}
- override fun isViewEmpty() = homeworkAdapter.isEmpty
-
override fun hideRefresh() {
homeworkSwipe.isRefreshing = false
}
override fun showEmpty(show: Boolean) {
- homeworkEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ homeworkEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ homeworkError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ homeworkErrorMessage.text = message
}
override fun showProgress(show: Boolean) {
- homeworkProgress.visibility = if (show) View.VISIBLE else View.GONE
+ homeworkProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -93,15 +106,15 @@ class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
}
override fun showContent(show: Boolean) {
- homeworkRecycler.visibility = if (show) View.VISIBLE else View.GONE
+ homeworkRecycler.visibility = if (show) VISIBLE else GONE
}
override fun showPreButton(show: Boolean) {
- homeworkPreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ homeworkPreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE
}
override fun showNextButton(show: Boolean) {
- homeworkNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ homeworkNextButton.visibility = if (show) VISIBLE else View.INVISIBLE
}
override fun showTimetableDialog(homework: Homework) {
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 6829031c..7e1da314 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
@@ -35,10 +35,13 @@ class HomeworkPresenter @Inject constructor(
lateinit var currentDate: LocalDate
private set
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: HomeworkView, date: Long?) {
super.onAttachView(view)
view.initView()
Timber.i("Homework view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
if (currentDate.isHolidays) setBaseDateOnHolidays()
reloadView()
@@ -59,6 +62,18 @@ class HomeworkPresenter @Inject constructor(
loadData(currentDate, true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(currentDate, true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onHomeworkItemSelected(item: AbstractFlexibleItem<*>?) {
if (item is HomeworkItem) {
Timber.i("Select homework item ${item.homework.id}")
@@ -105,17 +120,29 @@ class HomeworkPresenter @Inject constructor(
view?.apply {
updateData(it)
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
}
analytics.logEvent("load_homework", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading homework result: An exception occurred")
- view?.run { showEmpty(isViewEmpty()) }
+
errorHandler.dispatch(it)
})
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun createHomeworkItem(items: Map>): List {
return items.flatMap {
HomeworkHeader(it.key).let { header ->
@@ -131,6 +158,7 @@ class HomeworkPresenter @Inject constructor(
enableSwipe(false)
showContent(false)
showEmpty(false)
+ showErrorView(false)
clearData()
reloadNavigation()
}
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 977a5b73..1d241df4 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
@@ -5,6 +5,8 @@ import io.github.wulkanowy.ui.base.BaseView
interface HomeworkView : BaseView {
+ val isViewEmpty: Boolean
+
fun initView()
fun updateData(data: List)
@@ -13,12 +15,14 @@ interface HomeworkView : BaseView {
fun updateNavigationWeek(date: String)
- fun isViewEmpty(): Boolean
-
fun hideRefresh()
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
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 1288e299..a3e70489 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
@@ -16,7 +16,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.hideSoftInput
-import io.github.wulkanowy.utils.openEmail
+import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.showSoftInput
import kotlinx.android.synthetic.main.fragment_login_form.*
@@ -62,7 +62,7 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
loginFormSignIn.setOnClickListener { presenter.onSignInClick() }
loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() }
- loginFormContactDiscord.setOnClickListener { presenter.onDiscordClick() }
+ loginFormFaq.setOnClickListener { presenter.onFaqClick() }
loginFormContactEmail.setOnClickListener { presenter.onEmailClick() }
loginFormPass.setOnEditorActionListener { _, id, _ ->
@@ -161,12 +161,12 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
presenter.onDetachView()
}
- override fun openDiscordInvite() {
- context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
+ override fun openFaqPage() {
+ context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania/dlaczego-nie-moge-sie-zalogowac", ::showMessage)
}
override fun openEmail() {
- context?.openEmail(
+ context?.openEmailClient(
requireContext().getString(R.string.login_email_intent_title),
"wulkanowyinc@gmail.com",
requireContext().getString(R.string.login_email_subject),
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 bdab1dad..10c0a663 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
@@ -91,8 +91,8 @@ class LoginFormPresenter @Inject constructor(
}))
}
- fun onDiscordClick() {
- view?.openDiscordInvite()
+ fun onFaqClick() {
+ view?.openFaqPage()
}
fun onEmailClick() {
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 7eec9477..91e8d86e 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
@@ -45,7 +45,7 @@ interface LoginFormView : BaseView {
fun showContact(show: Boolean)
- fun openDiscordInvite()
+ fun openFaqPage()
fun openEmail()
}
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 dba0c951..8478f7cc 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
@@ -14,7 +14,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.utils.AppInfo
-import io.github.wulkanowy.utils.openEmail
+import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_login_student_select.*
@@ -102,7 +102,7 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView {
}
override fun openEmail() {
- context?.openEmail(
+ context?.openEmailClient(
requireContext().getString(R.string.login_email_intent_title),
"wulkanowyinc@gmail.com",
requireContext().getString(R.string.login_email_subject),
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 724e3fbb..5e9ce3ba 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
@@ -16,7 +16,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.hideSoftInput
-import io.github.wulkanowy.utils.openEmail
+import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser
import io.github.wulkanowy.utils.showSoftInput
import kotlinx.android.synthetic.main.fragment_login_symbol.*
@@ -50,7 +50,7 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView {
override fun initView() {
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
- loginSymbolContactDiscord.setOnClickListener { presenter.onDiscordClick() }
+ loginSymbolFaq.setOnClickListener { presenter.onFaqClick() }
loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() }
loginSymbolName.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() }
@@ -126,12 +126,12 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView {
presenter.onDetachView()
}
- override fun openDiscordInvite() {
- context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
+ override fun openFaqPage() {
+ context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania/co-to-jest-symbol", ::showMessage)
}
override fun openEmail() {
- context?.openEmail(
+ context?.openEmailClient(
requireContext().getString(R.string.login_email_intent_title),
"wulkanowyinc@gmail.com",
requireContext().getString(R.string.login_email_subject),
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 8e4dd3b0..49aabc92 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
@@ -89,8 +89,8 @@ class LoginSymbolPresenter @Inject constructor(
}
}
- fun onDiscordClick() {
- view?.openDiscordInvite()
+ fun onFaqClick() {
+ view?.openFaqPage()
}
fun onEmailClick() {
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 9b5340cf..1afc1532 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
@@ -29,7 +29,7 @@ interface LoginSymbolView : BaseView {
fun showContact(show: Boolean)
- fun openDiscordInvite()
+ fun openFaqPage()
fun openEmail()
}
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 00204a87..12bf1a13 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
@@ -3,6 +3,8 @@ package io.github.wulkanowy.ui.modules.luckynumber
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.view.ViewGroup
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.LuckyNumber
@@ -23,17 +25,22 @@ class LuckyNumberFragment : BaseFragment(), LuckyNumberView, MainView.TitledView
override val titleStringId: Int
get() = R.string.lucky_number_title
+ override val isViewEmpty get() = luckyNumberText.text.isBlank()
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_lucky_number, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
+ messageContainer = luckyNumberSwipe
presenter.onAttachView(this)
}
override fun initView() {
luckyNumberSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ luckyNumberErrorRetry.setOnClickListener { presenter.onRetry() }
+ luckyNumberErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun updateData(data: LuckyNumber) {
@@ -45,11 +52,19 @@ class LuckyNumberFragment : BaseFragment(), LuckyNumberView, MainView.TitledView
}
override fun showEmpty(show: Boolean) {
- luckyNumberEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ luckyNumberEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ luckyNumberError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ luckyNumberErrorMessage.text = message
}
override fun showProgress(show: Boolean) {
- luckyNumberProgress.visibility = if (show) View.VISIBLE else View.GONE
+ luckyNumberProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -57,11 +72,7 @@ class LuckyNumberFragment : BaseFragment(), LuckyNumberView, MainView.TitledView
}
override fun showContent(show: Boolean) {
- luckyNumberContent.visibility = if (show) View.VISIBLE else View.GONE
- }
-
- override fun isViewEmpty(): Boolean {
- return luckyNumberText.text.isBlank()
+ luckyNumberContent.visibility = if (show) VISIBLE else GONE
}
override fun 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 ee7260e6..63ced4b8 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
@@ -19,6 +19,8 @@ class LuckyNumberPresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter(errorHandler, studentRepository, schedulers) {
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: LuckyNumberView) {
super.onAttachView(view)
view.run {
@@ -27,6 +29,7 @@ class LuckyNumberPresenter @Inject constructor(
enableSwipe(false)
}
Timber.i("Lucky number view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
@@ -52,25 +55,49 @@ class LuckyNumberPresenter @Inject constructor(
updateData(it)
showContent(true)
showEmpty(false)
+ showErrorView(false)
}
analytics.logEvent("load_lucky_number", "lucky_number" to it.luckyNumber, "force_refresh" to forceRefresh)
}, {
Timber.i("Loading lucky number result: An exception occurred")
- view?.run { showEmpty(isViewEmpty()) }
errorHandler.dispatch(it)
}, {
Timber.i("Loading lucky number result: No lucky number found")
view?.run {
showContent(false)
showEmpty(true)
+ showEmpty(false)
}
})
)
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
fun onSwipeRefresh() {
Timber.i("Force refreshing the lucky number")
loadData(true)
}
+
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
}
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 9ead2b1f..a680c83e 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
@@ -5,6 +5,8 @@ import io.github.wulkanowy.ui.base.BaseView
interface LuckyNumberView : BaseView {
+ val isViewEmpty: Boolean
+
fun initView()
fun updateData(data: LuckyNumber)
@@ -13,11 +15,13 @@ interface LuckyNumberView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
fun showContent(show: Boolean)
-
- fun isViewEmpty(): Boolean
}
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 3c8f18a0..6e4716bf 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
@@ -58,7 +58,10 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
.subscribe({
when {
it.isEmpty() -> view?.openLoginView()
- it.size == 1 -> registerStudent(it.single().student)
+ it.size == 1 -> {
+ selectedStudent = it.single().student
+ view?.showThemeDialog()
+ }
else -> view?.updateData(it)
}
}, { errorHandler.dispatch(it) }))
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 4c7f7759..991c1d10 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
@@ -100,7 +100,7 @@ class MainActivity : BaseActivity(), MainView {
override fun initView() {
with(mainToolbar) {
if (SDK_INT >= LOLLIPOP) stateListAnimator = null
- setBackgroundColor(overlayProvider.get().getSurfaceColorWithOverlayIfNeeded(dpToPx(4f)))
+ setBackgroundColor(overlayProvider.get().compositeOverlayWithThemeSurfaceColorIfNeeded(dpToPx(4f)))
}
with(mainBottomNav) {
@@ -113,7 +113,7 @@ class MainActivity : BaseActivity(), MainView {
))
accentColor = getThemeAttrColor(R.attr.colorPrimary)
inactiveColor = ColorUtils.setAlphaComponent(getThemeAttrColor(R.attr.colorOnSurface), 153)
- defaultBackgroundColor = overlayProvider.get().getSurfaceColorWithOverlayIfNeeded(dpToPx(8f))
+ defaultBackgroundColor = overlayProvider.get().compositeOverlayWithThemeSurfaceColorIfNeeded(dpToPx(8f))
titleState = ALWAYS_SHOW
currentItem = startMenuIndex
isBehaviorTranslationEnabled = false
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 4f881e8f..22231e42 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
@@ -65,6 +65,10 @@ class MessagePreviewFragment : BaseFragment(), MessagePreviewView, MainView.Titl
presenter.onAttachView(this, (savedInstanceState ?: arguments)?.getLong(MESSAGE_ID_KEY) ?: 0L)
}
+ override fun initView() {
+ messagePreviewErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+ }
+
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.action_menu_message_preview, menu)
menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply)
@@ -126,8 +130,16 @@ class MessagePreviewFragment : BaseFragment(), MessagePreviewView, MainView.Titl
menuDeleteButton?.setTitle(R.string.message_move_to_bin)
}
- override fun showMessageError() {
- messagePreviewError.visibility = VISIBLE
+ override fun showErrorView(show: Boolean) {
+ messagePreviewError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ messagePreviewErrorMessage.text = message
+ }
+
+ override fun setErrorRetryCallback(callback: () -> Unit) {
+ messagePreviewErrorRetry.setOnClickListener { callback() }
}
override fun openMessageReply(message: 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 a230c0b3..c32bd611 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
@@ -23,11 +23,29 @@ class MessagePreviewPresenter @Inject constructor(
private var message: Message? = null
+ private lateinit var lastError: Throwable
+
+ private var retryCallback: () -> Unit = {}
+
fun onAttachView(view: MessagePreviewView, id: Long) {
super.onAttachView(view)
+ view.initView()
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData(id)
}
+ private fun onMessageLoadRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(messageId)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
private fun loadData(id: Long) {
Timber.i("Loading message $id preview started")
messageId = id
@@ -55,7 +73,7 @@ class MessagePreviewPresenter @Inject constructor(
analytics.logEvent("load_message_preview", "length" to message.content?.length)
}) {
Timber.i("Loading message $id preview result: An exception occurred ")
- view?.showMessageError()
+ retryCallback = { onMessageLoadRetry() }
errorHandler.dispatch(it)
})
}
@@ -85,6 +103,7 @@ class MessagePreviewPresenter @Inject constructor(
showContent(false)
showProgress(true)
showOptions(false)
+ showErrorView(false)
}
}
.doFinally {
@@ -97,15 +116,24 @@ class MessagePreviewPresenter @Inject constructor(
popView()
}
}, { error ->
- view?.showMessageError()
+ retryCallback = { onMessageDelete() }
errorHandler.dispatch(error)
}, {
- view?.showMessageError()
+ view?.showErrorView(true)
})
)
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ setErrorRetryCallback { retryCallback() }
+ }
+ }
+
fun onMessageDelete(): Boolean {
deleteMessage()
return true
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
index 373dee11..d5776627 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
@@ -9,6 +9,8 @@ interface MessagePreviewView : BaseView {
val deleteMessageSuccessString: String
+ fun initView()
+
fun setSubject(subject: String)
fun setRecipient(recipient: String)
@@ -23,19 +25,23 @@ interface MessagePreviewView : BaseView {
fun showContent(show: Boolean)
+ fun notifyParentMessageDeleted(message: Message)
+
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
+ fun setErrorRetryCallback(callback: () -> Unit)
+
fun showOptions(show: Boolean)
fun setDeletedOptionsLabels()
fun setNotDeletedOptionsLabels()
- fun showMessageError()
-
fun openMessageReply(message: Message?)
fun openMessageForward(message: Message?)
fun popView()
-
- fun notifyParentMessageDeleted(message: Message)
}
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 326cd6a7..d6065983 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
@@ -72,6 +72,8 @@ class MessageTabFragment : BaseFragment(), MessageTabView {
)
}
messageTabSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ messageTabErrorRetry.setOnClickListener { presenter.onRetry() }
+ messageTabErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun updateData(data: List) {
@@ -102,6 +104,14 @@ class MessageTabFragment : BaseFragment(), MessageTabView {
messageTabEmpty.visibility = if (show) VISIBLE else INVISIBLE
}
+ override fun showErrorView(show: Boolean) {
+ messageTabError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ messageTabErrorMessage.text = message
+ }
+
override fun showRefresh(show: Boolean) {
messageTabSwipe.isRefreshing = show
}
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 af576293..1123e7e4 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
@@ -23,9 +23,12 @@ class MessageTabPresenter @Inject constructor(
lateinit var folder: MessageFolder
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: MessageTabView, folder: MessageFolder) {
super.onAttachView(view)
view.initView()
+ errorHandler.showErrorMessage = ::showErrorViewOnError
this.folder = folder
}
@@ -34,6 +37,18 @@ class MessageTabPresenter @Inject constructor(
onParentViewLoadData(true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onDeleteMessage() {
loadData(false)
}
@@ -78,17 +93,28 @@ class MessageTabPresenter @Inject constructor(
view?.run {
showEmpty(it.isEmpty())
showContent(it.isNotEmpty())
+ showErrorView(false)
updateData(it)
}
analytics.logEvent("load_messages", "items" to it.size, "folder" to folder.name)
}) {
Timber.i("Loading $folder message result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
})
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun updateMessage(message: Message) {
Timber.i("Attempt to update message ${message.id}")
disposable.add(messageRepository.updateMessage(message)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt
index 967863de..e5705c73 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt
@@ -26,6 +26,10 @@ interface MessageTabView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showRefresh(show: Boolean)
fun openMessage(messageId: Long)
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 1d9104a8..d47574f6 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
@@ -61,6 +61,8 @@ class MobileDeviceFragment : BaseFragment(), MobileDeviceView, MainView.TitledVi
onDeviceUnregisterListener = presenter::onUnregisterDevice
}
mobileDevicesSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ mobileDevicesErrorRetry.setOnClickListener { presenter.onRetry() }
+ mobileDevicesErrorDetails.setOnClickListener { presenter.onDetailsClick() }
mobileDeviceAddButton.setOnClickListener { presenter.onRegisterDevice() }
}
@@ -105,6 +107,14 @@ class MobileDeviceFragment : BaseFragment(), MobileDeviceView, MainView.TitledVi
mobileDevicesEmpty.visibility = if (show) VISIBLE else GONE
}
+ override fun showErrorView(show: Boolean) {
+ mobileDevicesError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ mobileDevicesErrorMessage.text = message
+ }
+
override fun enableSwipe(enable: Boolean) {
mobileDevicesSwipe.isEnabled = enable
}
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 71359a52..e95d2ce0 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
@@ -20,10 +20,13 @@ class MobileDevicePresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter(errorHandler, studentRepository, schedulers) {
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: MobileDeviceView) {
super.onAttachView(view)
view.initView()
Timber.i("Mobile device view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
@@ -31,6 +34,18 @@ class MobileDevicePresenter @Inject constructor(
loadData(true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
private fun loadData(forceRefresh: Boolean = false) {
Timber.i("Loading mobile devices data started")
disposable.add(studentRepository.getCurrentStudent()
@@ -51,6 +66,7 @@ class MobileDevicePresenter @Inject constructor(
updateData(it)
showContent(it.isNotEmpty())
showEmpty(it.isEmpty())
+ showErrorView(false)
}
analytics.logEvent("load_devices", "items" to it.size, "force_refresh" to forceRefresh)
}) {
@@ -59,6 +75,17 @@ class MobileDevicePresenter @Inject constructor(
})
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
fun onRegisterDevice() {
view?.showTokenDialog()
}
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 58804e24..869b59bb 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
@@ -25,6 +25,10 @@ interface MobileDeviceView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showUndo(position: Int, device: MobileDevice)
fun showTokenDialog()
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 a1812ece..8b81156b 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
@@ -12,15 +12,13 @@ import android.view.View.VISIBLE
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.getSystemService
-import dagger.android.support.DaggerDialogFragment
import io.github.wulkanowy.R
import io.github.wulkanowy.data.pojos.MobileDeviceToken
-import io.github.wulkanowy.data.repositories.mobiledevice.MobileDeviceRemote
-import io.github.wulkanowy.ui.base.BaseActivity
+import io.github.wulkanowy.ui.base.BaseDialogFragment
import kotlinx.android.synthetic.main.dialog_mobile_device.*
import javax.inject.Inject
-class MobileDeviceTokenDialog : DaggerDialogFragment(), MobileDeviceTokenVIew {
+class MobileDeviceTokenDialog : BaseDialogFragment(), MobileDeviceTokenVIew {
@Inject
lateinit var presenter: MobileDeviceTokenPresenter
@@ -66,6 +64,12 @@ class MobileDeviceTokenDialog : DaggerDialogFragment(), MobileDeviceTokenVIew {
})
}
+ private fun clickCopy(text: String) {
+ val clip = ClipData.newPlainText("wulkanowy", text)
+ activity?.getSystemService()?.setPrimaryClip(clip)
+ Toast.makeText(context, R.string.all_copied, Toast.LENGTH_LONG).show()
+ }
+
override fun hideLoading() {
mobileDeviceDialogProgress.visibility = GONE
}
@@ -78,30 +82,8 @@ class MobileDeviceTokenDialog : DaggerDialogFragment(), MobileDeviceTokenVIew {
dismiss()
}
- override fun showError(text: String, error: Throwable) {
- showMessage(text)
- }
-
- override fun showMessage(text: String) {
- Toast.makeText(context, text, Toast.LENGTH_LONG).show()
- }
-
- override fun showExpiredDialog() {
- (activity as? BaseActivity<*>)?.showExpiredDialog()
- }
-
- override fun openClearLoginView() {
- (activity as? BaseActivity<*>)?.openClearLoginView()
- }
-
override fun onDestroyView() {
presenter.onDetachView()
super.onDestroyView()
}
-
- fun clickCopy(text: String) {
- val clip = ClipData.newPlainText("wulkanowy", text)
- activity?.getSystemService()?.setPrimaryClip(clip)
- Toast.makeText(context, R.string.all_copied, Toast.LENGTH_LONG).show()
- }
}
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 6117ae24..e5335e45 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
@@ -60,6 +60,8 @@ class NoteFragment : BaseFragment(), NoteView, MainView.TitledView {
)
}
noteSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ noteErrorRetry.setOnClickListener { presenter.onRetry() }
+ noteErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun showNoteDialog(note: Note) {
@@ -82,6 +84,14 @@ class NoteFragment : BaseFragment(), NoteView, MainView.TitledView {
noteEmpty.visibility = if (show) VISIBLE else GONE
}
+ override fun showErrorView(show: Boolean) {
+ noteError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ noteErrorMessage.text = message
+ }
+
override fun showProgress(show: Boolean) {
noteProgress.visibility = if (show) VISIBLE else GONE
}
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 df98ab88..7acf37a4 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
@@ -21,10 +21,13 @@ class NotePresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter(errorHandler, studentRepository, schedulers) {
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: NoteView) {
super.onAttachView(view)
view.initView()
Timber.i("Note view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
@@ -33,6 +36,18 @@ class NotePresenter @Inject constructor(
loadData(true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
private fun loadData(forceRefresh: Boolean = false) {
Timber.i("Loading note data started")
disposable.add(studentRepository.getCurrentStudent()
@@ -53,17 +68,28 @@ class NotePresenter @Inject constructor(
view?.apply {
updateData(it)
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
}
analytics.logEvent("load_note", "items" to it.size, "force_refresh" to forceRefresh)
}, {
Timber.i("Loading note result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
})
)
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
fun onNoteItemSelected(item: AbstractFlexibleItem<*>?) {
if (item is NoteItem) {
Timber.i("Select note item ${item.note.id}")
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 9a2c12eb..a9c9f4f2 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
@@ -18,6 +18,10 @@ interface NoteView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt
index 92f74ca8..5a7c4cad 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt
@@ -3,6 +3,8 @@ package io.github.wulkanowy.ui.modules.schoolandteachers.school
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.view.ViewGroup
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.School
@@ -10,8 +12,8 @@ import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
-import io.github.wulkanowy.utils.dialPhone
-import io.github.wulkanowy.utils.openMapLocation
+import io.github.wulkanowy.utils.openDialer
+import io.github.wulkanowy.utils.openNavigation
import kotlinx.android.synthetic.main.fragment_school.*
import javax.inject.Inject
@@ -22,6 +24,8 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn
override val titleStringId get() = R.string.school_title
+ override val isViewEmpty get() = schoolName.text.isBlank()
+
companion object {
fun newInstance() = SchoolFragment()
}
@@ -37,6 +41,8 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn
override fun initView() {
schoolSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ schoolErrorRetry.setOnClickListener { presenter.onRetry() }
+ schoolErrorDetails.setOnClickListener { presenter.onDetailsClick() }
schoolAddressButton.setOnClickListener { presenter.onAddressSelected() }
schoolTelephoneButton.setOnClickListener { presenter.onTelephoneSelected() }
@@ -45,19 +51,27 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn
override fun updateData(data: School) {
schoolName.text = data.name
schoolAddress.text = data.address.ifBlank { "-" }
- schoolAddressButton.visibility = if (data.address.isNotBlank()) View.VISIBLE else View.GONE
+ schoolAddressButton.visibility = if (data.address.isNotBlank()) VISIBLE else GONE
schoolTelephone.text = data.contact.ifBlank { "-" }
- schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) View.VISIBLE else View.GONE
+ schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) VISIBLE else GONE
schoolHeadmaster.text = data.headmaster
schoolPedagogue.text = data.pedagogue
}
override fun showEmpty(show: Boolean) {
- schoolEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ schoolEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ schoolError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ schoolErrorMessage.text = message
}
override fun showProgress(show: Boolean) {
- schoolProgress.visibility = if (show) View.VISIBLE else View.GONE
+ schoolProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -65,7 +79,7 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn
}
override fun showContent(show: Boolean) {
- schoolContent.visibility = if (show) View.VISIBLE else View.GONE
+ schoolContent.visibility = if (show) VISIBLE else GONE
}
override fun hideRefresh() {
@@ -86,10 +100,10 @@ class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAn
}
override fun openMapsLocation(location: String) {
- context?.openMapLocation(location)
+ context?.openNavigation(location)
}
override fun dialPhone(phone: String) {
- context?.dialPhone(phone)
+ context?.openDialer(phone)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt
index 2b0a37b1..d3299d90 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt
@@ -23,10 +23,13 @@ class SchoolPresenter @Inject constructor(
private var contact: String? = null
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: SchoolView) {
super.onAttachView(view)
view.initView()
Timber.i("School view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
@@ -34,12 +37,24 @@ class SchoolPresenter @Inject constructor(
loadData(true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onParentViewLoadData(forceRefresh: Boolean) {
loadData(forceRefresh)
}
fun onAddressSelected() {
- address?.let{ view?.openMapsLocation(it) }
+ address?.let { view?.openMapsLocation(it) }
}
fun onTelephoneSelected() {
@@ -68,6 +83,7 @@ class SchoolPresenter @Inject constructor(
updateData(it)
showContent(true)
showEmpty(false)
+ showErrorView(false)
}
analytics.logEvent("load_school", "force_refresh" to forceRefresh)
}, {
@@ -76,9 +92,22 @@ class SchoolPresenter @Inject constructor(
}, {
Timber.i("Loading school result: No school info found")
view?.run {
- showContent(false)
- showEmpty(true)
+ showContent(!isViewEmpty)
+ showEmpty(isViewEmpty)
+ showErrorView(false)
}
}))
}
+
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ showContent(false)
+ } else showError(message, error)
+ }
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt
index 39e7b805..c42c2f91 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt
@@ -6,12 +6,18 @@ import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildVi
interface SchoolView : BaseView, SchoolAndTeachersChildView {
+ val isViewEmpty: Boolean
+
fun initView()
fun updateData(data: School)
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt
index 842e50fe..b6bb9c10 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt
@@ -3,6 +3,8 @@ package io.github.wulkanowy.ui.modules.schoolandteachers.teacher
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.view.ViewGroup
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
@@ -16,7 +18,8 @@ import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragmen
import kotlinx.android.synthetic.main.fragment_teacher.*
import javax.inject.Inject
-class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView, SchoolAndTeachersChildView {
+class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView,
+ SchoolAndTeachersChildView {
@Inject
lateinit var presenter: TeacherPresenter
@@ -55,6 +58,8 @@ class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView, School
)
}
teacherSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ teacherErrorRetry.setOnClickListener { presenter.onRetry() }
+ teacherErrorDetails.setOnClickListener { presenter.onDetailsClick() }
}
override fun updateData(data: List) {
@@ -70,11 +75,19 @@ class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView, School
}
override fun showEmpty(show: Boolean) {
- teacherEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ teacherEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ teacherError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ teacherErrorMessage.text = message
}
override fun showProgress(show: Boolean) {
- teacherProgress.visibility = if (show) View.VISIBLE else View.GONE
+ teacherProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -82,7 +95,7 @@ class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView, School
}
override fun showContent(show: Boolean) {
- teacherRecycler.visibility = if (show) View.VISIBLE else View.GONE
+ teacherRecycler.visibility = if (show) VISIBLE else GONE
}
override fun hideRefresh() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt
index aabcff28..6aa4871d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt
@@ -19,10 +19,13 @@ class TeacherPresenter @Inject constructor(
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter(errorHandler, studentRepository, schedulers) {
+ private lateinit var lastError: Throwable
+
override fun onAttachView(view: TeacherView) {
super.onAttachView(view)
view.initView()
Timber.i("Teacher view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData()
}
@@ -30,6 +33,18 @@ class TeacherPresenter @Inject constructor(
loadData(true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onParentViewLoadData(forceRefresh: Boolean) {
loadData(forceRefresh)
}
@@ -56,6 +71,7 @@ class TeacherPresenter @Inject constructor(
updateData(it)
showContent(it.isNotEmpty())
showEmpty(it.isEmpty())
+ showErrorView(false)
}
analytics.logEvent("load_teachers", "items" to it.size, "force_refresh" to forceRefresh)
}) {
@@ -63,4 +79,15 @@ class TeacherPresenter @Inject constructor(
errorHandler.dispatch(it)
})
}
+
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt
index 2cc1139c..b16be8ff 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt
@@ -27,4 +27,8 @@ interface TeacherView : BaseView, SchoolAndTeachersChildView {
fun showContent(show: Boolean)
fun showEmpty(show: Boolean)
+
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt
index cb172b98..03a89d27 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt
@@ -5,14 +5,17 @@ import android.content.SharedPreferences
import android.os.Bundle
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
+import com.yariksoffice.lingver.Lingver
import dagger.android.support.AndroidSupportInjection
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.main.MainView
import io.github.wulkanowy.utils.AppInfo
import javax.inject.Inject
-class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener,
+class SettingsFragment : PreferenceFragmentCompat(),
+ SharedPreferences.OnSharedPreferenceChangeListener,
MainView.TitledView, SettingsView {
@Inject
@@ -21,6 +24,9 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
@Inject
lateinit var appInfo: AppInfo
+ @Inject
+ lateinit var lingver: Lingver
+
companion object {
fun newInstance() = SettingsFragment()
}
@@ -50,6 +56,10 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
activity?.recreate()
}
+ override fun updateLanguage(langCode: String) {
+ lingver.setLocale(requireContext(), langCode)
+ }
+
override fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) {
findPreference(serviceEnablesKey)?.apply {
summary = if (isHolidays) getString(R.string.pref_services_suspended) else ""
@@ -73,6 +83,10 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
(activity as? BaseActivity<*>)?.openClearLoginView()
}
+ override fun showErrorDetailsDialog(error: Throwable) {
+ ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
+ }
+
override fun onResume() {
super.onResume()
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt
index 88d38e0d..89ba0ee5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt
@@ -6,6 +6,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.services.sync.SyncManager
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
+import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.isHolidays
@@ -20,7 +21,8 @@ class SettingsPresenter @Inject constructor(
private val preferencesRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper,
private val syncManager: SyncManager,
- private val chuckCollector: ChuckCollector
+ private val chuckCollector: ChuckCollector,
+ private val appInfo: AppInfo
) : BasePresenter(errorHandler, studentRepository, schedulers) {
override fun onAttachView(view: SettingsView) {
@@ -38,6 +40,10 @@ class SettingsPresenter @Inject constructor(
servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startSyncWorker(true)
isDebugNotificationEnableKey -> chuckCollector.showNotification(isDebugNotificationEnable)
appThemeKey -> view?.recreateView()
+ appLanguageKey -> view?.run {
+ updateLanguage(if (appLanguage == "system") appInfo.systemLanguage else appLanguage)
+ recreateView()
+ }
else -> Unit
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt
index 1c4bf3b0..e50eb47b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt
@@ -6,5 +6,7 @@ interface SettingsView : BaseView {
fun recreateView()
+ fun updateLanguage(langCode: String)
+
fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt
index a64dee8d..ef6057df 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt
@@ -6,7 +6,10 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.view.ViewGroup
+import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
@@ -17,9 +20,11 @@ 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.timetable.completed.CompletedLessonsFragment
+import io.github.wulkanowy.utils.SchooldaysRangeLimiter
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_timetable.*
+import org.threeten.bp.LocalDate
import javax.inject.Inject
class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
@@ -71,7 +76,11 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
}
timetableSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ timetableErrorRetry.setOnClickListener { presenter.onRetry() }
+ timetableErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+
timetablePreviousButton.setOnClickListener { presenter.onPreviousDay() }
+ timetableNavDate.setOnClickListener { presenter.onPickDate() }
timetableNextButton.setOnClickListener { presenter.onNextDay() }
timetableNavContainer.setElevationCompat(requireContext().dpToPx(8f))
@@ -115,11 +124,19 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
}
override fun showEmpty(show: Boolean) {
- timetableEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ timetableEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ timetableError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ timetableErrorMessage.text = message
}
override fun showProgress(show: Boolean) {
- timetableProgress.visibility = if (show) View.VISIBLE else View.GONE
+ timetableProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -127,21 +144,36 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
}
override fun showContent(show: Boolean) {
- timetableRecycler.visibility = if (show) View.VISIBLE else View.GONE
+ timetableRecycler.visibility = if (show) VISIBLE else GONE
}
override fun showPreButton(show: Boolean) {
- timetablePreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ timetablePreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE
}
override fun showNextButton(show: Boolean) {
- timetableNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ timetableNextButton.visibility = if (show) VISIBLE else View.INVISIBLE
}
override fun showTimetableDialog(lesson: Timetable) {
(activity as? MainActivity)?.showDialogFragment(TimetableDialog.newInstance(lesson))
}
+ override fun showDatePickerDialog(currentDate: LocalDate) {
+ val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
+ presenter.onDateSet(year, month + 1, dayOfMonth)
+ }
+ val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
+ currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
+
+ with(datePickerDialog) {
+ setDateRangeLimiter(SchooldaysRangeLimiter())
+ version = DatePickerDialog.Version.VERSION_2
+ scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
+ show(this@TimetableFragment.parentFragmentManager, null)
+ }
+ }
+
override fun openCompletedLessonsView() {
(activity as? MainActivity)?.pushView(CompletedLessonsFragment.newInstance())
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt
index cea5bf2f..4c30ecb7 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt
@@ -17,6 +17,7 @@ import io.github.wulkanowy.utils.previousSchoolDay
import io.github.wulkanowy.utils.toFormattedString
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDate.now
+import org.threeten.bp.LocalDate.of
import org.threeten.bp.LocalDate.ofEpochDay
import timber.log.Timber
import java.util.concurrent.TimeUnit.MILLISECONDS
@@ -36,10 +37,13 @@ class TimetablePresenter @Inject constructor(
lateinit var currentDate: LocalDate
private set
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: TimetableView, date: Long?) {
super.onAttachView(view)
view.initView()
Timber.i("Timetable was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
if (currentDate.isHolidays) setBaseDateOnHolidays()
reloadView()
@@ -55,11 +59,32 @@ class TimetablePresenter @Inject constructor(
reloadView()
}
+ fun onPickDate() {
+ view?.showDatePickerDialog(currentDate)
+ }
+
+ fun onDateSet(year: Int, month: Int, day: Int) {
+ loadData(of(year, month, day))
+ reloadView()
+ }
+
fun onSwipeRefresh() {
Timber.i("Force refreshing the timetable")
loadData(currentDate, true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(currentDate, true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onViewReselected() {
Timber.i("Timetable view is reselected")
view?.also { view ->
@@ -125,17 +150,28 @@ class TimetablePresenter @Inject constructor(
view?.apply {
updateData(it)
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
}
analytics.logEvent("load_timetable", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading timetable result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it)
})
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun reloadView() {
Timber.i("Reload timetable view with the date ${currentDate.toFormattedString()}")
view?.apply {
@@ -143,6 +179,7 @@ class TimetablePresenter @Inject constructor(
enableSwipe(false)
showContent(false)
showEmpty(false)
+ showErrorView(false)
clearData()
reloadNavigation()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt
index 84f28974..f730a271 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt
@@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.timetable
import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.ui.base.BaseView
+import org.threeten.bp.LocalDate
interface TimetableView : BaseView {
@@ -23,6 +24,10 @@ interface TimetableView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean)
@@ -35,6 +40,8 @@ interface TimetableView : BaseView {
fun showTimetableDialog(lesson: Timetable)
+ fun showDatePickerDialog(currentDate: LocalDate)
+
fun popView()
fun openCompletedLessonsView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt
index c7b5c6ca..60c16b2d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt
@@ -3,7 +3,11 @@ package io.github.wulkanowy.ui.modules.timetable.completed
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.GONE
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
import android.view.ViewGroup
+import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
@@ -12,10 +16,12 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson
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.utils.SchooldaysRangeLimiter
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getCompatDrawable
import io.github.wulkanowy.utils.setOnItemClickListener
import kotlinx.android.synthetic.main.fragment_timetable_completed.*
+import org.threeten.bp.LocalDate
import javax.inject.Inject
class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.TitledView {
@@ -55,7 +61,11 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
}
completedLessonsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
+ completedLessonErrorRetry.setOnClickListener { presenter.onRetry() }
+ completedLessonErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+
completedLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() }
+ completedLessonsNavDate.setOnClickListener { presenter.onPickDate() }
completedLessonsNextButton.setOnClickListener { presenter.onNextDay() }
completedLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f))
@@ -78,7 +88,15 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
}
override fun showEmpty(show: Boolean) {
- completedLessonsEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ completedLessonsEmpty.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ completedLessonError.visibility = if (show) VISIBLE else GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ completedLessonErrorMessage.text = message
}
override fun showFeatureDisabled() {
@@ -87,7 +105,7 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
}
override fun showProgress(show: Boolean) {
- completedLessonsProgress.visibility = if (show) View.VISIBLE else View.GONE
+ completedLessonsProgress.visibility = if (show) VISIBLE else GONE
}
override fun enableSwipe(enable: Boolean) {
@@ -95,21 +113,36 @@ class CompletedLessonsFragment : BaseFragment(), CompletedLessonsView, MainView.
}
override fun showContent(show: Boolean) {
- completedLessonsRecycler.visibility = if (show) View.VISIBLE else View.GONE
+ completedLessonsRecycler.visibility = if (show) VISIBLE else GONE
}
override fun showPreButton(show: Boolean) {
- completedLessonsPreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ completedLessonsPreviousButton.visibility = if (show) VISIBLE else INVISIBLE
}
override fun showNextButton(show: Boolean) {
- completedLessonsNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
+ completedLessonsNextButton.visibility = if (show) VISIBLE else INVISIBLE
}
override fun showCompletedLessonDialog(completedLesson: CompletedLesson) {
(activity as? MainActivity)?.showDialogFragment(CompletedLessonDialog.newInstance(completedLesson))
}
+ override fun showDatePickerDialog(currentDate: LocalDate) {
+ val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
+ presenter.onDateSet(year, month + 1, dayOfMonth)
+ }
+ val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
+ currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
+
+ with(datePickerDialog) {
+ setDateRangeLimiter(SchooldaysRangeLimiter())
+ version = DatePickerDialog.Version.VERSION_2
+ scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
+ show(this@CompletedLessonsFragment.parentFragmentManager, null)
+ }
+ }
+
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/timetable/completed/CompletedLessonsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt
index b936c657..e2b56950 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt
@@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.timetable.completed
+import android.annotation.SuppressLint
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
@@ -34,17 +35,20 @@ class CompletedLessonsPresenter @Inject constructor(
lateinit var currentDate: LocalDate
private set
+ private lateinit var lastError: Throwable
+
fun onAttachView(view: CompletedLessonsView, date: Long?) {
super.onAttachView(view)
Timber.i("Completed lessons is attached")
view.initView()
- loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
- if (currentDate.isHolidays) setBaseDateOnHolidays()
- reloadView()
+ completedLessonsErrorHandler.showErrorMessage = ::showErrorViewOnError
completedLessonsErrorHandler.onFeatureDisabled = {
this.view?.showFeatureDisabled()
Timber.i("Completed lessons feature disabled by school")
}
+ loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
+ if (currentDate.isHolidays) setBaseDateOnHolidays()
+ reloadView()
}
fun onPreviousDay() {
@@ -57,11 +61,32 @@ class CompletedLessonsPresenter @Inject constructor(
reloadView()
}
+ fun onPickDate() {
+ view?.showDatePickerDialog(currentDate)
+ }
+
+ fun onDateSet(year: Int, month: Int, day: Int) {
+ loadData(LocalDate.of(year, month, day))
+ reloadView()
+ }
+
fun onSwipeRefresh() {
Timber.i("Force refreshing the completed lessons")
loadData(currentDate, true)
}
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(currentDate, true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
fun onCompletedLessonsItemSelected(item: AbstractFlexibleItem<*>?) {
if (item is CompletedLessonItem) {
Timber.i("Select completed lessons item ${item.completedLesson.id}")
@@ -108,17 +133,28 @@ class CompletedLessonsPresenter @Inject constructor(
view?.apply {
updateData(it)
showEmpty(it.isEmpty())
+ showErrorView(false)
showContent(it.isNotEmpty())
}
analytics.logEvent("load_completed_lessons", "items" to it.size, "force_refresh" to forceRefresh)
}) {
Timber.i("Loading completed lessons result: An exception occurred")
- view?.run { showEmpty(isViewEmpty) }
completedLessonsErrorHandler.dispatch(it)
})
}
}
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
private fun reloadView() {
Timber.i("Reload completed lessons view with the date ${currentDate.toFormattedString()}")
view?.apply {
@@ -126,11 +162,13 @@ class CompletedLessonsPresenter @Inject constructor(
enableSwipe(false)
showContent(false)
showEmpty(false)
+ showErrorView(false)
clearData()
reloadNavigation()
}
}
+ @SuppressLint("DefaultLocale")
private fun reloadNavigation() {
view?.apply {
showPreButton(!currentDate.minusDays(1).isHolidays)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt
index a8bef66f..a6a327e2 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt
@@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.timetable.completed
import io.github.wulkanowy.data.db.entities.CompletedLesson
import io.github.wulkanowy.ui.base.BaseView
+import org.threeten.bp.LocalDate
interface CompletedLessonsView : BaseView {
@@ -19,6 +20,10 @@ interface CompletedLessonsView : BaseView {
fun showEmpty(show: Boolean)
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
fun showFeatureDisabled()
fun showProgress(show: Boolean)
@@ -32,4 +37,6 @@ interface CompletedLessonsView : BaseView {
fun showNextButton(show: Boolean)
fun showCompletedLessonDialog(completedLesson: CompletedLesson)
+
+ fun showDatePickerDialog(currentDate: LocalDate)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt
index cad26f2e..a04922e5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt
@@ -33,7 +33,7 @@ class MaterialLinearLayout : LinearLayout {
if (SDK_INT >= LOLLIPOP) {
setElevation(elevation)
} else {
- setBackgroundColor(ElevationOverlayProvider(context).getSurfaceColorWithOverlayIfNeeded(elevation))
+ setBackgroundColor(ElevationOverlayProvider(context).compositeOverlayWithThemeSurfaceColorIfNeeded(elevation))
}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt
index 3bcaae7d..e19d0111 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt
@@ -19,7 +19,7 @@ open class MaterialTabLayout : TabLayout {
if (SDK_INT >= LOLLIPOP) {
setElevation(elevation)
} else {
- setBackgroundColor(ElevationOverlayProvider(context).getSurfaceColorWithOverlayIfNeeded(elevation))
+ setBackgroundColor(ElevationOverlayProvider(context).compositeOverlayWithThemeSurfaceColorIfNeeded(elevation))
}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt
index 3fa83a04..a444da6f 100644
--- a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt
+++ b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt
@@ -1,5 +1,6 @@
package io.github.wulkanowy.utils
+import android.content.res.Resources
import android.os.Build.MANUFACTURER
import android.os.Build.MODEL
import android.os.Build.VERSION.SDK_INT
@@ -25,4 +26,8 @@ open class AppInfo {
open val systemManufacturer: String get() = MANUFACTURER
open val systemModel: String get() = MODEL
+
+ @Suppress("DEPRECATION")
+ open val systemLanguage: String
+ get() = Resources.getSystem().configuration.locale.language
}
diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt
index 5110b067..a265378e 100644
--- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt
+++ b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt
@@ -32,7 +32,7 @@ fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -
}
}
-fun Context.openEmail(chooserTitle: String, email: String, subject: String?, body: String?) {
+fun Context.openEmailClient(chooserTitle: String, email: String, subject: String?, body: String?) {
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", email, null))
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
if (subject != null) emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
@@ -40,7 +40,7 @@ fun Context.openEmail(chooserTitle: String, email: String, subject: String?, bod
startActivity(Intent.createChooser(emailIntent, chooserTitle))
}
-fun Context.openMapLocation(location: String) {
+fun Context.openNavigation(location: String) {
val intentUri = Uri.parse("geo:0,0?q=${Uri.encode(location)}")
val intent = Intent(Intent.ACTION_VIEW, intentUri)
if (intent.resolveActivity(packageManager) != null) {
@@ -48,7 +48,7 @@ fun Context.openMapLocation(location: String) {
}
}
-fun Context.dialPhone(phone: String) {
+fun Context.openDialer(phone: String) {
val intentUri = Uri.parse("tel:$phone")
val intent = Intent(Intent.ACTION_DIAL, intentUri)
startActivity(intent)
diff --git a/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt
index c863b030..22dbc22f 100644
--- a/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt
+++ b/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt
@@ -67,8 +67,8 @@ inline val Grade.colorStringId: Int
fun Grade.changeModifier(plusModifier: Double, minusModifier: Double): Grade {
return when {
- modifier != .0 && plusModifier != .0 && modifier > 0 -> copy(modifier = plusModifier)
- modifier != .0 && minusModifier != .0 && modifier < 0 -> copy(modifier = -minusModifier)
+ modifier > 0 -> copy(modifier = plusModifier)
+ modifier < 0 -> copy(modifier = -minusModifier)
else -> this
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/utils/SchooldaysRangeLimiter.kt b/app/src/main/java/io/github/wulkanowy/utils/SchooldaysRangeLimiter.kt
new file mode 100644
index 00000000..922aafbd
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/utils/SchooldaysRangeLimiter.kt
@@ -0,0 +1,51 @@
+package io.github.wulkanowy.utils
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.wdullaer.materialdatetimepicker.date.DateRangeLimiter
+import org.threeten.bp.DayOfWeek
+import org.threeten.bp.LocalDate
+import java.util.Calendar
+
+@Suppress("UNUSED_PARAMETER")
+class SchooldaysRangeLimiter : DateRangeLimiter {
+
+ private val now = LocalDate.now()
+
+ override fun setToNearestDate(day: Calendar): Calendar = day
+
+ override fun isOutOfRange(year: Int, month: Int, day: Int): Boolean {
+ val date = LocalDate.of(year, month + 1, day)
+ val dayOfWeek = date.dayOfWeek
+ return dayOfWeek == DayOfWeek.SUNDAY || dayOfWeek == DayOfWeek.SATURDAY || date.isHolidays
+ }
+
+ override fun getStartDate(): Calendar {
+ val startYear = if (now.monthValue <= 6) now.year - 1 else now.year
+ val startOfSchoolYear = now.withYear(startYear).firstSchoolDay
+
+ val calendar = Calendar.getInstance()
+ calendar.set(startOfSchoolYear.year, startOfSchoolYear.monthValue - 1, startOfSchoolYear.dayOfMonth)
+ return calendar
+ }
+
+ override fun getEndDate(): Calendar {
+ val endYear = if (now.monthValue > 6) now.year + 1 else now.year
+ val endOfSchoolYear = now.withYear(endYear).lastSchoolDay
+
+ val calendar = Calendar.getInstance()
+ calendar.set(endOfSchoolYear.year, endOfSchoolYear.monthValue - 1, endOfSchoolYear.dayOfMonth)
+ return calendar
+ }
+
+ override fun writeToParcel(parcel: Parcel, flags: Int) {}
+
+ override fun describeContents() = 0
+
+ companion object CREATOR : Parcelable.Creator {
+
+ override fun createFromParcel(parcel: Parcel): SchooldaysRangeLimiter = SchooldaysRangeLimiter()
+
+ override fun newArray(size: Int): Array = arrayOfNulls(size)
+ }
+}
diff --git a/app/src/main/play/listings/pl-PL/full-description.txt b/app/src/main/play/listings/pl-PL/full-description.txt
index d33cb56f..641b7706 100644
--- a/app/src/main/play/listings/pl-PL/full-description.txt
+++ b/app/src/main/play/listings/pl-PL/full-description.txt
@@ -1,4 +1,4 @@
-Aplikacja jest we wczesnej fazie rozwoju, ciągle pracujemy nad kolejnymi funkcjami.
+Aplikacja jest przeznaczona dla użytkowników dziennika VULCAN UONET+.
Wyróżnione cechy i funkcje:
- obliczanie średniej ważonej,
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png
new file mode 100644
index 00000000..56768bf5
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png
new file mode 100644
index 00000000..83d9353a
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png
new file mode 100644
index 00000000..f83a7af8
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png
new file mode 100644
index 00000000..90d5fef4
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png
new file mode 100644
index 00000000..eadbf2db
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png
new file mode 100644
index 00000000..2a11a3db
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png
new file mode 100644
index 00000000..d9b2f1c7
Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/account-switcher.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/account-switcher.png
deleted file mode 100644
index 8a52d8de..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/account-switcher.png and /dev/null differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/attendance-dialog.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/attendance-dialog.png
deleted file mode 100644
index c6508574..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/attendance-dialog.png and /dev/null differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/attendance-statistics.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/attendance-statistics.png
deleted file mode 100644
index 376fc3c3..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/attendance-statistics.png and /dev/null differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/grades.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/grades.png
deleted file mode 100644
index 6b4089b0..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/grades.png and /dev/null differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/more.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/more.png
deleted file mode 100644
index c3dc523f..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/more.png and /dev/null differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/timetable-dialog.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/timetable-dialog.png
deleted file mode 100644
index 511433d4..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/timetable-dialog.png and /dev/null differ
diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/timetable-widget.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/timetable-widget.png
deleted file mode 100644
index 1d502470..00000000
Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/timetable-widget.png and /dev/null differ
diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt
index 68608c38..fe3993f6 100644
--- a/app/src/main/play/release-notes/pl-PL/default.txt
+++ b/app/src/main/play/release-notes/pl-PL/default.txt
@@ -1,9 +1,9 @@
-Wersja 0.12.0
+Wersja 0.13.0
-- wsparcie dla dziennika Lubelskiego Portalu Oświatowego
-- naprawa problemów z wyświetlaniem ocen punktowych
-- automatyczne przełączanie motywu na androidzie 10
-- wyświetlanie pomocy przy problemach z logowaniem
-- wyświetlanie informacji o szkole
+- naprawiony plan lekcji po ostatniej aktualizacji VULCANa (19.11)
+- naprawiona opcja wyboru motywu dla widżetu ze szczęśliwym numerkiem
+- nowa opcja zmiany języka i język rosyjski
+- możliwość łatwego nawigowania między dniami w planie lekcji przez kalendarz
+- opcja ustawienia modyfikatora oceny na wartość 0,0
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
diff --git a/app/src/main/res/drawable/ic_about_faq.xml b/app/src/main/res/drawable/ic_about_faq.xml
new file mode 100644
index 00000000..d6ab255b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_about_faq.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_error.xml b/app/src/main/res/drawable/ic_error.xml
new file mode 100644
index 00000000..bb4cb302
--- /dev/null
+++ b/app/src/main/res/drawable/ic_error.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/fragment_attendance.xml b/app/src/main/res/layout/fragment_attendance.xml
index 4877103e..daf7e67f 100644
--- a/app/src/main/res/layout/fragment_attendance.xml
+++ b/app/src/main/res/layout/fragment_attendance.xml
@@ -2,7 +2,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ tools:context=".ui.modules.attendance.AttendanceFragment">
+ android:layout_height="match_parent"
+ tools:listitem="@layout/item_attendance" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:srcCompat="@drawable/ic_chevron_left" />
+ app:srcCompat="@drawable/ic_chevron_right" />
diff --git a/app/src/main/res/layout/fragment_attendance_summary.xml b/app/src/main/res/layout/fragment_attendance_summary.xml
index 35bc0960..da0ce7f2 100644
--- a/app/src/main/res/layout/fragment_attendance_summary.xml
+++ b/app/src/main/res/layout/fragment_attendance_summary.xml
@@ -82,4 +82,55 @@
android:text="@string/attendance_no_items"
android:textSize="20sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_exam.xml b/app/src/main/res/layout/fragment_exam.xml
index adfbee32..1e1b0c99 100644
--- a/app/src/main/res/layout/fragment_exam.xml
+++ b/app/src/main/res/layout/fragment_exam.xml
@@ -2,7 +2,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ tools:context=".ui.modules.exam.ExamFragment">
+ android:layout_height="match_parent"
+ tools:listitem="@layout/header_exam" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:srcCompat="@drawable/ic_chevron_left" />
+ app:srcCompat="@drawable/ic_chevron_right" />
diff --git a/app/src/main/res/layout/fragment_grade.xml b/app/src/main/res/layout/fragment_grade.xml
index d134ec17..0bc864b2 100644
--- a/app/src/main/res/layout/fragment_grade.xml
+++ b/app/src/main/res/layout/fragment_grade.xml
@@ -13,23 +13,17 @@
android:visibility="invisible"
app:tabMode="scrollable"
app:tabSelectedTextColor="?colorPrimary"
- app:tabTextColor="@color/mtrl_on_surface_emphasis_medium"
+ app:tabTextColor="@color/material_on_surface_emphasis_medium"
tools:ignore="UnusedAttribute"
tools:visibility="visible" />
-
-
-
-
+ android:layout_marginTop="48dp"
+ android:visibility="invisible"
+ tools:visibility="visible" />
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_grade_details.xml b/app/src/main/res/layout/fragment_grade_details.xml
index 125d43a9..a1faefe7 100644
--- a/app/src/main/res/layout/fragment_grade_details.xml
+++ b/app/src/main/res/layout/fragment_grade_details.xml
@@ -13,7 +13,8 @@
+ android:layout_height="match_parent"
+ tools:listitem="@layout/item_grade_details" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_grade_statistics.xml b/app/src/main/res/layout/fragment_grade_statistics.xml
index 6e88f8a8..10c8bb19 100644
--- a/app/src/main/res/layout/fragment_grade_statistics.xml
+++ b/app/src/main/res/layout/fragment_grade_statistics.xml
@@ -47,39 +47,45 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
+ android:layout_gravity="center">
-
+ android:orientation="horizontal"
+ android:paddingStart="16dp"
+ android:paddingTop="5dp"
+ android:paddingEnd="16dp"
+ android:visibility="invisible"
+ tools:visibility="visible">
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_grade_summary.xml b/app/src/main/res/layout/fragment_grade_summary.xml
index 2d9e7dc6..3f21e61c 100644
--- a/app/src/main/res/layout/fragment_grade_summary.xml
+++ b/app/src/main/res/layout/fragment_grade_summary.xml
@@ -13,7 +13,8 @@
+ android:layout_height="match_parent"
+ tools:listitem="@layout/item_grade_summary" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_homework.xml b/app/src/main/res/layout/fragment_homework.xml
index 799d3f42..0fcde9c0 100644
--- a/app/src/main/res/layout/fragment_homework.xml
+++ b/app/src/main/res/layout/fragment_homework.xml
@@ -2,7 +2,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ tools:context=".ui.modules.homework.HomeworkFragment">
+ android:layout_height="match_parent"
+ tools:listitem="@layout/item_homework" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:srcCompat="@drawable/ic_chevron_left" />
+ app:srcCompat="@drawable/ic_chevron_right" />
diff --git a/app/src/main/res/layout/fragment_login_form.xml b/app/src/main/res/layout/fragment_login_form.xml
index 29943515..9f7f01e0 100644
--- a/app/src/main/res/layout/fragment_login_form.xml
+++ b/app/src/main/res/layout/fragment_login_form.xml
@@ -2,7 +2,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ tools:context=".ui.modules.login.form.LoginFormFragment">
+ android:text="@string/about_faq"
+ app:icon="@drawable/ic_about_faq" />
+ android:layout_height="match_parent"
+ tools:context=".ui.modules.login.symbol.LoginSymbolFragment">
+ android:layout_marginRight="16dp"
+ android:orientation="horizontal">
+
+ android:layout_marginLeft="8dp"
+ android:layout_weight="1"
+ android:text="@string/about_faq"
+ app:icon="@drawable/ic_about_faq" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_message.xml b/app/src/main/res/layout/fragment_message.xml
index d396276f..b4cc0c2f 100644
--- a/app/src/main/res/layout/fragment_message.xml
+++ b/app/src/main/res/layout/fragment_message.xml
@@ -16,7 +16,7 @@
app:tabMaxWidth="0dp"
app:tabMode="fixed"
app:tabSelectedTextColor="?colorPrimary"
- app:tabTextColor="@color/mtrl_on_surface_emphasis_medium"
+ app:tabTextColor="@color/material_on_surface_emphasis_medium"
tools:ignore="UnusedAttribute"
tools:visibility="visible" />
@@ -35,8 +35,8 @@
android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
- android:tint="?colorOnSecondary"
android:text="@string/send_message_title"
+ android:tint="?colorOnSecondary"
app:icon="@drawable/ic_menu_message_write" />
+
+ tools:ignore="UseCompoundDrawables"
+ tools:visibility="invisible">
+
+
+
+
+
+
+
+ android:layout_height="match_parent"
+ tools:listitem="@layout/item_message" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_mobile_device.xml b/app/src/main/res/layout/fragment_mobile_device.xml
index b78dc067..cf11c283 100644
--- a/app/src/main/res/layout/fragment_mobile_device.xml
+++ b/app/src/main/res/layout/fragment_mobile_device.xml
@@ -14,6 +14,18 @@
android:indeterminate="true"
tools:visibility="invisible" />
+
+
+
+
+
-
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical"
+ android:visibility="invisible"
+ tools:ignore="UseCompoundDrawables"
+ tools:visibility="invisible">
-
+
+
+
+
-
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:gravity="center"
+ android:orientation="horizontal">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_school.xml b/app/src/main/res/layout/fragment_school.xml
index 2570251b..a7e9a213 100644
--- a/app/src/main/res/layout/fragment_school.xml
+++ b/app/src/main/res/layout/fragment_school.xml
@@ -229,7 +229,58 @@
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
- android:text="@string/teacher_no_items"
+ android:text="@string/school_no_info"
android:textSize="20sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_schoolandteachers.xml b/app/src/main/res/layout/fragment_schoolandteachers.xml
index 2b3f2203..6414abb9 100644
--- a/app/src/main/res/layout/fragment_schoolandteachers.xml
+++ b/app/src/main/res/layout/fragment_schoolandteachers.xml
@@ -16,7 +16,7 @@
app:tabMaxWidth="0dp"
app:tabMode="fixed"
app:tabSelectedTextColor="?colorPrimary"
- app:tabTextColor="@color/mtrl_on_surface_emphasis_medium"
+ app:tabTextColor="@color/material_on_surface_emphasis_medium"
tools:ignore="UnusedAttribute"
tools:visibility="visible" />
diff --git a/app/src/main/res/layout/fragment_teacher.xml b/app/src/main/res/layout/fragment_teacher.xml
index 01cf8726..484bf065 100644
--- a/app/src/main/res/layout/fragment_teacher.xml
+++ b/app/src/main/res/layout/fragment_teacher.xml
@@ -49,4 +49,55 @@
android:text="@string/teacher_no_items"
android:textSize="20sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_timetable.xml b/app/src/main/res/layout/fragment_timetable.xml
index db5c6fc2..98ccabbf 100644
--- a/app/src/main/res/layout/fragment_timetable.xml
+++ b/app/src/main/res/layout/fragment_timetable.xml
@@ -2,7 +2,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ tools:context=".ui.modules.timetable.TimetableFragment">
+ android:layout_height="match_parent"
+ tools:listitem="@layout/item_timetable" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:srcCompat="@drawable/ic_chevron_left" />
+ app:srcCompat="@drawable/ic_chevron_right" />
diff --git a/app/src/main/res/layout/fragment_timetable_completed.xml b/app/src/main/res/layout/fragment_timetable_completed.xml
index 7c093a4a..11067044 100644
--- a/app/src/main/res/layout/fragment_timetable_completed.xml
+++ b/app/src/main/res/layout/fragment_timetable_completed.xml
@@ -57,6 +57,57 @@
android:text="@string/completed_lessons_no_items"
android:textSize="20sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_homework.xml b/app/src/main/res/layout/item_homework.xml
index 5d03ed58..68169039 100644
--- a/app/src/main/res/layout/item_homework.xml
+++ b/app/src/main/res/layout/item_homework.xml
@@ -32,7 +32,7 @@
android:layout_toRightOf="@id/homeworkItemSubject"
android:gravity="end"
android:textSize="13sp"
- tools:text="@tools:sample/lorem" />
+ tools:text="@tools:sample/full_names" />
+ tools:text="@tools:sample/lorem" />
diff --git a/app/src/main/res/menu/action_menu_attendance.xml b/app/src/main/res/menu/action_menu_attendance.xml
index 86c2fed7..bb20c8ec 100644
--- a/app/src/main/res/menu/action_menu_attendance.xml
+++ b/app/src/main/res/menu/action_menu_attendance.xml
@@ -6,6 +6,6 @@
android:icon="@drawable/ic_menu_attendance_summary"
android:orderInCategory="1"
android:title="@string/attendance_summary_button"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/menu/action_menu_grade.xml b/app/src/main/res/menu/action_menu_grade.xml
index 4438309d..6357cbb5 100644
--- a/app/src/main/res/menu/action_menu_grade.xml
+++ b/app/src/main/res/menu/action_menu_grade.xml
@@ -6,6 +6,6 @@
android:icon="@drawable/ic_menu_grade_semester"
android:orderInCategory="1"
android:title="@string/grade_switch_semester"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/menu/action_menu_grade_details.xml b/app/src/main/res/menu/action_menu_grade_details.xml
index fbd28eec..62516cbd 100644
--- a/app/src/main/res/menu/action_menu_grade_details.xml
+++ b/app/src/main/res/menu/action_menu_grade_details.xml
@@ -6,6 +6,6 @@
android:enabled="false"
android:orderInCategory="100"
android:title="@string/grade_menu_read"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="never" />
diff --git a/app/src/main/res/menu/action_menu_main.xml b/app/src/main/res/menu/action_menu_main.xml
index 78b4ee4a..72bea25a 100644
--- a/app/src/main/res/menu/action_menu_main.xml
+++ b/app/src/main/res/menu/action_menu_main.xml
@@ -6,6 +6,6 @@
android:icon="@drawable/ic_all_account"
android:orderInCategory="2"
android:title="@string/main_account_picker"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="always" />
diff --git a/app/src/main/res/menu/action_menu_message_preview.xml b/app/src/main/res/menu/action_menu_message_preview.xml
index f7979780..dfc12e23 100644
--- a/app/src/main/res/menu/action_menu_message_preview.xml
+++ b/app/src/main/res/menu/action_menu_message_preview.xml
@@ -6,20 +6,20 @@
android:icon="@drawable/ic_menu_message_reply"
android:orderInCategory="1"
android:title="@string/message_reply"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/menu/action_menu_send_message.xml b/app/src/main/res/menu/action_menu_send_message.xml
index 491f74f9..4b43764a 100644
--- a/app/src/main/res/menu/action_menu_send_message.xml
+++ b/app/src/main/res/menu/action_menu_send_message.xml
@@ -6,6 +6,6 @@
android:icon="@drawable/ic_menu_message_send"
android:orderInCategory="1"
android:title="@string/send_message_title"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/menu/action_menu_timetable.xml b/app/src/main/res/menu/action_menu_timetable.xml
index cfbdb626..c3d0222c 100644
--- a/app/src/main/res/menu/action_menu_timetable.xml
+++ b/app/src/main/res/menu/action_menu_timetable.xml
@@ -6,6 +6,6 @@
android:icon="@drawable/ic_menu_timetable_lessons_completed"
android:orderInCategory="1"
android:title="@string/completed_lessons_button"
- app:iconTint="@color/mtrl_on_surface_emphasis_medium"
+ app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml
index 3e4a2466..49264538 100644
--- a/app/src/main/res/values-night/styles.xml
+++ b/app/src/main/res/values-night/styles.xml
@@ -10,6 +10,7 @@
- ?android:textColorPrimary
- @android:color/black
- false
+ - true
+
+
diff --git a/app/src/main/res/xml/scheme_preferences.xml b/app/src/main/res/xml/scheme_preferences.xml
index 28229f41..d9e6c533 100644
--- a/app/src/main/res/xml/scheme_preferences.xml
+++ b/app/src/main/res/xml/scheme_preferences.xml
@@ -37,6 +37,14 @@
app:key="@string/pref_key_grade_color_scheme"
app:title="@string/pref_view_grade_color_scheme"
app:useSimpleSummaryProvider="true" />
+
+ app:title="@string/pref_view_grade_average_force_calc" />