From 370cfbf22ad862f6106d26b6a5d12eebaaacd024 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2020 09:42:18 +0000 Subject: [PATCH 001/150] Bump core from 1.2.0 to 1.3.0 (#929) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index baa9149b..009963c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -196,7 +196,7 @@ dependencies { testImplementation "io.mockk:mockk:$mockk" testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9' - androidTestImplementation "androidx.test:core:1.2.0" + androidTestImplementation "androidx.test:core:1.3.0" androidTestImplementation "androidx.test:runner:1.2.0" androidTestImplementation "androidx.test.ext:junit:1.1.2" androidTestImplementation "io.mockk:mockk-android:$mockk" From 54fb01cd0d42a1c2b98604209aabe4ebdc85049d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2020 09:42:25 +0000 Subject: [PATCH 002/150] Bump firebase-inappmessaging-display-ktx from 19.1.0 to 19.1.1 (#930) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 009963c4..1bd64b83 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -181,7 +181,7 @@ dependencies { implementation 'me.xdrop:fuzzywuzzy:1.3.1' playImplementation 'com.google.firebase:firebase-analytics:17.5.0' - playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.0' + playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1" playImplementation 'com.google.firebase:firebase-messaging:20.2.4' playImplementation 'com.google.firebase:firebase-crashlytics:17.1.1' From d1ce16d2b1567d738b2e294e3647d73d53a2a0e8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2020 10:03:20 +0000 Subject: [PATCH 003/150] Bump runner from 1.2.0 to 1.3.0 (#932) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1bd64b83..b86108cf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -197,7 +197,7 @@ dependencies { testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9' androidTestImplementation "androidx.test:core:1.3.0" - androidTestImplementation "androidx.test:runner:1.2.0" + androidTestImplementation "androidx.test:runner:1.3.0" androidTestImplementation "androidx.test.ext:junit:1.1.2" androidTestImplementation "io.mockk:mockk-android:$mockk" androidTestImplementation "androidx.room:room-testing:$room" From 57bc2b2533d336353e273b6b9c428b0dcf632664 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2020 10:09:37 +0000 Subject: [PATCH 004/150] Bump firebase-crashlytics from 17.1.1 to 17.2.1 (#931) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index b86108cf..95b0a6e3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -184,7 +184,7 @@ dependencies { playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1" playImplementation 'com.google.firebase:firebase-messaging:20.2.4' - playImplementation 'com.google.firebase:firebase-crashlytics:17.1.1' + playImplementation 'com.google.firebase:firebase-crashlytics:17.2.1' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" From a5de39a3663c3790b986f7120a54028271541433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Mon, 31 Aug 2020 12:55:51 +0200 Subject: [PATCH 005/150] Update UI dependencies (#927) --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 95b0a6e3..8dd3b1f8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -145,9 +145,9 @@ dependencies { implementation "androidx.recyclerview:recyclerview:1.1.0" implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation "androidx.constraintlayout:constraintlayout:1.1.3" + implementation "androidx.constraintlayout:constraintlayout:2.0.1" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" - implementation "com.google.android.material:material:1.1.0" + implementation "com.google.android.material:material:1.2.0" implementation "com.github.wulkanowy:material-chips-input:2.1.1" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" From eb616eedc707d78c0895bcd19bae6301abe200f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 1 Sep 2020 09:31:01 +0200 Subject: [PATCH 006/150] Fix crash in flowWithResourceIn() (#933) --- .../modules/timetable/TimetablePresenter.kt | 1 + .../io/github/wulkanowy/utils/FlowUtils.kt | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) 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 e410eeb9..8581b73c 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 @@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.onEach import timber.log.Timber +import java.lang.NullPointerException import java.time.LocalDate import java.time.LocalDate.now import java.time.LocalDate.of diff --git a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt index 736a4270..31499405 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt @@ -3,6 +3,7 @@ package io.github.wulkanowy.utils import io.github.wulkanowy.data.Resource import io.github.wulkanowy.data.Status import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.filter @@ -69,22 +70,24 @@ inline fun networkBoundResource( fun flowWithResource(block: suspend () -> T) = flow { emit(Resource.loading()) - try { - emit(Resource.success(block())) + emit(try { + Resource.success(block()) } catch (e: Throwable) { - emit(Resource.error(e)) - } + Resource.error(e) + }) } fun flowWithResourceIn(block: suspend () -> Flow>) = flow { emit(Resource.loading()) try { - block().collect { - if (it.status != Status.LOADING) { // LOADING is already emitted - emit(it) + block() + .catch { emit(Resource.error(it)) } + .collect { + if (it.status != Status.LOADING) { // LOADING is already emitted + emit(it) + } } - } } catch (e: Throwable) { emit(Resource.error(e)) } From 9997b1adbbb4e27ac39813c9d65f69495e9f9fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 1 Sep 2020 09:31:36 +0200 Subject: [PATCH 007/150] Add skarzyskokamienna vulcan register (#934) --- app/src/main/res/values/api_hosts.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/res/values/api_hosts.xml b/app/src/main/res/values/api_hosts.xml index f661b88c..64618568 100644 --- a/app/src/main/res/values/api_hosts.xml +++ b/app/src/main/res/values/api_hosts.xml @@ -10,6 +10,7 @@ Rawa Mazowiecka - Platforma vEdukacja Zduńska Wola - e-Urząd Sieradz - Portal oświatowy + Skarżysko-Kamienna - e-Skarżysko Łask - Platforma vEdukacja Powiat łaski - Platforma edukacyjna Powiat Krasnostawski - Platforma oświatowa @@ -36,6 +37,7 @@ https://vulcan.net.pl/ https://vulcan.net.pl/ https://vulcan.net.pl/ + https://vulcan.net.pl/ http://fakelog.tk/?standard @@ -48,6 +50,7 @@ rawamazowiecka zdunskawola sieradz + skarzyskokamienna lask powiatlaski powiatkrasnostawski From 20f931c5cc8725aca38661f4a088012d9e9e54a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 1 Sep 2020 09:33:14 +0200 Subject: [PATCH 008/150] Fix recaptcha loading in password recover (#935) --- .../ui/modules/login/recover/LoginRecoverPresenter.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt index 1d509e1b..e5837705 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt @@ -66,7 +66,12 @@ class LoginRecoverPresenter @Inject constructor( showErrorView(false) showCaptcha(false) } - Status.SUCCESS -> view?.loadReCaptcha(siteKey = it.data!!.first, url = it.data.second) + Status.SUCCESS -> view?.run { + loadReCaptcha(url = it.data!!.first, siteKey = it.data.second) + showProgress(false) + showErrorView(false) + showCaptcha(true) + } Status.ERROR -> { Timber.i("Obtain captcha site key result: An exception occurred") errorHandler.dispatch(it.error!!) From 90be9d1add6ad1f92c90b6125e91b77dd9a49625 Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Tue, 1 Sep 2020 12:57:45 +0200 Subject: [PATCH 009/150] Disable notification sound (#936) --- .../wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt index cd25eea6..41fb6192 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt @@ -26,6 +26,7 @@ class UpcomingLessonsChannel @Inject constructor( lockscreenVisibility = VISIBILITY_PUBLIC setShowBadge(false) enableVibration(false) + setSound(null, null) } ) } From f8b7baef24260e173ec76eafd589115adf085eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 1 Sep 2020 14:58:45 +0200 Subject: [PATCH 010/150] Remove force sync dialog (#938) --- .../ui/modules/settings/SettingsFragment.kt | 9 --------- .../ui/modules/settings/SettingsPresenter.kt | 12 ++++-------- .../wulkanowy/ui/modules/settings/SettingsView.kt | 1 - 3 files changed, 4 insertions(+), 18 deletions(-) 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 a8a15cec..6f4a695d 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 @@ -120,15 +120,6 @@ class SettingsFragment : PreferenceFragmentCompat(), ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) } - override fun showForceSyncDialog() { - AlertDialog.Builder(requireContext()) - .setTitle(R.string.pref_services_dialog_force_sync_title) - .setMessage(R.string.pref_services_dialog_force_sync_summary) - .setPositiveButton(android.R.string.ok) { _, _ -> presenter.onForceSyncDialogSubmit() } - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .show() - } - override fun showFixSyncDialog() { AlertDialog.Builder(requireContext()) .setTitle(R.string.pref_notify_fix_sync_issues) 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 f9e6731f..3d1e063e 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 @@ -55,14 +55,6 @@ class SettingsPresenter @Inject constructor( } fun onSyncNowClicked() { - view?.showForceSyncDialog() - } - - fun onFixSyncIssuesClicked() { - view?.showFixSyncDialog() - } - - fun onForceSyncDialogSubmit() { view?.run { syncManager.startOneTimeSyncWorker().onEach { workInfo -> when (workInfo.state) { @@ -87,4 +79,8 @@ class SettingsPresenter @Inject constructor( }.launch("sync") } } + + fun onFixSyncIssuesClicked() { + view?.showFixSyncDialog() + } } 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 3786ba4b..b647c0b7 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 @@ -18,6 +18,5 @@ interface SettingsView : BaseView { fun setSyncInProgress(inProgress: Boolean) - fun showForceSyncDialog() fun showFixSyncDialog() } From 2ad1d086e01b4284cc2dccdfd3467df22492fbbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 1 Sep 2020 15:39:34 +0200 Subject: [PATCH 011/150] Fix lucky number notification (#937) --- .../github/wulkanowy/data/db/dao/LuckyNumberDao.kt | 2 +- .../luckynumber/LuckyNumberRepository.kt | 12 +++++------- .../wulkanowy/services/sync/works/LuckyNumberWork.kt | 3 +-- 3 files changed, 7 insertions(+), 10 deletions(-) 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 e3fdf01b..57f3005a 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 @@ -12,5 +12,5 @@ import javax.inject.Singleton interface LuckyNumberDao : BaseDao { @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date") - fun load(studentId: Int, date: LocalDate): Flow + fun load(studentId: Int, date: LocalDate): Flow } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt index ef0ced3a..173ce7e4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt @@ -3,7 +3,8 @@ package io.github.wulkanowy.data.repositories.luckynumber import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.utils.networkBoundResource -import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import java.time.LocalDate.now import javax.inject.Inject import javax.inject.Singleton @@ -28,11 +29,8 @@ class LuckyNumberRepository @Inject constructor( } ) - fun getNotNotifiedLuckyNumber(student: Student): Flow { - return local.getLuckyNumber(student, now()) - } + suspend fun getNotNotifiedLuckyNumber(student: Student) = + local.getLuckyNumber(student, now()).map { if (it?.isNotified == false) it else null }.first() - suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) { - local.updateLuckyNumber(luckyNumber) - } + suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) = local.updateLuckyNumber(luckyNumber) } diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt index 9cb765ec..7b9f5ab3 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt @@ -19,7 +19,6 @@ import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.waitForResult -import kotlinx.coroutines.flow.first import javax.inject.Inject import kotlin.random.Random @@ -33,7 +32,7 @@ class LuckyNumberWork @Inject constructor( override suspend fun doWork(student: Student, semester: Semester) { luckyNumberRepository.getLuckyNumber(student, true, preferencesRepository.isNotificationsEnable).waitForResult() - luckyNumberRepository.getNotNotifiedLuckyNumber(student).first()?.let { + luckyNumberRepository.getNotNotifiedLuckyNumber(student)?.let { notify(it) luckyNumberRepository.updateLuckyNumber(it.apply { isNotified = true }) } From 0f65af8958925d5780d9275e784570529a706d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 1 Sep 2020 23:57:56 +0200 Subject: [PATCH 012/150] Fix grade summary empty view (#941) --- .../ui/modules/grade/summary/GradeSummaryAdapter.kt | 2 +- .../ui/modules/grade/summary/GradeSummaryPresenter.kt | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt index 30c4ccc2..ccebe94f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt @@ -21,7 +21,7 @@ class GradeSummaryAdapter @Inject constructor() : RecyclerView.Adapter() - override fun getItemCount() = items.size + 1 + override fun getItemCount() = items.size + if (items.isNotEmpty()) 1 else 0 override fun getItemViewType(position: Int) = when (position) { 0 -> ViewType.HEADER.id 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 9484d8b7..caa3cb84 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 @@ -45,16 +45,17 @@ class GradeSummaryPresenter @Inject constructor( Status.LOADING -> Timber.i("Loading grade summary started") Status.SUCCESS -> { Timber.i("Loading grade summary result: Success") + val items = createGradeSummaryItems(it.data!!) view?.run { - showEmpty(it.data!!.isEmpty()) - showContent(it.data.isNotEmpty()) + showEmpty(items.isEmpty()) + showContent(items.isNotEmpty()) showErrorView(false) - updateData(createGradeSummaryItems(it.data)) + updateData(items) } analytics.logEvent( "load_data", "type" to "grade_summary", - "items" to it.data!!.size + "items" to it.data.size ) } Status.ERROR -> { From 69a11931547358f030330fac4f9a49e4ba74603b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 1 Sep 2020 23:58:18 +0200 Subject: [PATCH 013/150] Fix semester list refresh on no current semester found (#940) --- .../semester/SemesterRepository.kt | 42 ++++++++++++------- .../semester/SemesterRepositoryTest.kt | 23 +++++++++- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt index 28d37ed8..7a76503f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.data.repositories.semester +import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.DispatchersProvider @@ -18,24 +19,33 @@ class SemesterRepository @Inject constructor( ) { suspend fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false) = withContext(dispatchers.backgroundThread) { - local.getSemesters(student).let { semesters -> - semesters.filter { - !forceRefresh && when { - Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> semesters.firstOrNull { it.isCurrent }?.diaryId != 0 - refreshOnNoCurrent -> semesters.any { semester -> semester.isCurrent } - else -> true - } - } - }.ifEmpty { - val new = remote.getSemesters(student) - if (new.isEmpty()) throw IllegalArgumentException("Empty semester list!") - - val old = local.getSemesters(student) - local.deleteSemesters(old.uniqueSubtract(new)) - local.saveSemesters(new.uniqueSubtract(old)) + val semesters = local.getSemesters(student) + if (isShouldFetch(student, semesters, forceRefresh, refreshOnNoCurrent)) { + refreshSemesters(student) local.getSemesters(student) - } + } else semesters + } + + private fun isShouldFetch(student: Student, semesters: List, forceRefresh: Boolean, refreshOnNoCurrent: Boolean): Boolean { + val isNoSemesters = semesters.isEmpty() + + val isRefreshOnModeChangeRequired = if (Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { + semesters.firstOrNull { it.isCurrent }?.diaryId == 0 + } else false + + val isRefreshOnNoCurrentAppropriate = refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent } + + return forceRefresh || isNoSemesters || isRefreshOnModeChangeRequired || isRefreshOnNoCurrentAppropriate + } + + private suspend fun refreshSemesters(student: Student) { + val new = remote.getSemesters(student) + if (new.isEmpty()) throw IllegalArgumentException("Empty semester list!") + + val old = local.getSemesters(student) + local.deleteSemesters(old.uniqueSubtract(new)) + local.saveSemesters(new.uniqueSubtract(old)) } suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false) = withContext(dispatchers.backgroundThread) { diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt index 866c2af4..5a2388ff 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/semester/SemesterRepositoryTest.kt @@ -63,7 +63,15 @@ class SemesterRepositoryTest { createSemesterEntity(0, 2, now().minusMonths(3), now()) ) + val goodSemesters = listOf( + createSemesterEntity(122, 1, now().minusMonths(6), now().minusMonths(3)), + createSemesterEntity(123, 2, now().minusMonths(3), now()) + ) + coEvery { semesterLocal.getSemesters(student) } returns badSemesters + coEvery { semesterRemote.getSemesters(student) } returns goodSemesters + coEvery { semesterLocal.deleteSemesters(any()) } just Runs + coEvery { semesterLocal.saveSemesters(any()) } just Runs val items = runBlocking { semesterRepository.getSemesters(student) } assertEquals(2, items.size) @@ -152,12 +160,23 @@ class SemesterRepositoryTest { @Test fun getSemesters_noCurrent_refreshOnNoCurrent() { - val semesters = listOf( + val semestersWithNoCurrent = listOf( createSemesterEntity(1, 1, now().minusMonths(12), now().minusMonths(6)), createSemesterEntity(1, 2, now().minusMonths(6), now().minusMonths(1)) ) - coEvery { semesterLocal.getSemesters(student) } returns semesters + val newSemesters = listOf( + createSemesterEntity(1, 1, now().minusMonths(12), now().minusMonths(6)), + createSemesterEntity(1, 2, now().minusMonths(6), now().minusMonths(1)), + + createSemesterEntity(2, 1, now().minusMonths(1), now().plusMonths(5)), + createSemesterEntity(2, 2, now().plusMonths(5), now().plusMonths(11)), + ) + + coEvery { semesterLocal.getSemesters(student) } returns semestersWithNoCurrent + coEvery { semesterRemote.getSemesters(student) } returns newSemesters + coEvery { semesterLocal.deleteSemesters(any()) } just Runs + coEvery { semesterLocal.saveSemesters(any()) } just Runs val items = runBlocking { semesterRepository.getSemesters(student, refreshOnNoCurrent = true) } assertEquals(2, items.size) From 40492e6c01ac8212a02dcb5d23555e9f48036f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Wed, 2 Sep 2020 00:14:18 +0200 Subject: [PATCH 014/150] Version 0.20.1 --- .travis.yml | 2 +- README.en.md | 1 - README.md | 1 - app/build.gradle | 2 +- app/src/main/play/release-notes/pl-PL/default.txt | 8 +++++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index c9f9bbe1..e8366be2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.20.0 + - 0.20.1 android: licenses: diff --git a/README.en.md b/README.en.md index 7444ccca..28cce1c3 100644 --- a/README.en.md +++ b/README.en.md @@ -47,7 +47,6 @@ You can also download a [development version](https://wulkanowy.github.io/#downl * [Wulkanowy SDK](https://github.com/wulkanowy/sdk) -* [RxJava 2](https://github.com/ReactiveX/RxJava) * [Dagger 2](https://github.com/google/dagger) * [Room](https://developer.android.com/topic/libraries/architecture/room) * [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) diff --git a/README.md b/README.md index 61b13444..02e1900c 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#downloa ## Zbudowana za pomocą * [Wulkanowy SDK](https://github.com/wulkanowy/SDK) -* [RxJava 2](https://github.com/ReactiveX/RxJava) * [Dagger 2](https://github.com/google/dagger) * [Room](https://developer.android.com/topic/libraries/architecture/room) * [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) diff --git a/app/build.gradle b/app/build.gradle index 8dd3b1f8..eb932978 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.20.0" + implementation "io.github.wulkanowy:sdk:0.20.1" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 5cf0c517..51c3c13a 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,5 +1,7 @@ -Wersja 0.20.0 -- naprawiliśmy obsługę wiadomości -- naprawiliśmy wyświetlanie oznaczenia klasy ucznia w menadżerze kont +Wersja 0.20.1 +- naprawiliśmy powiadomienie o szczęśliwym numerku +- naprawiliśmy przełączanie na nowy rok szkolny +- naprawiliśmy funkcję resetowania hasła +- dodaliśmy dziennik e-Skarżysko Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases From ee168bafe0df36d4d3dc0a952bebc8fcabdd86c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Wed, 2 Sep 2020 00:23:41 +0200 Subject: [PATCH 015/150] Version 0.20.2 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8366be2..688dd000 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.20.1 + - 0.20.2 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index eb932978..b046834a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 64 - versionName "0.20.0" + versionCode 66 + versionName "0.20.2" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.20.1" + implementation "io.github.wulkanowy:sdk:0.20.2" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 51c3c13a..d0e2c823 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,4 +1,4 @@ -Wersja 0.20.1 +Wersja 0.20.2 - naprawiliśmy powiadomienie o szczęśliwym numerku - naprawiliśmy przełączanie na nowy rok szkolny - naprawiliśmy funkcję resetowania hasła From 6ded83d1327ce7a0ddb5b3be0e90f0c4c776b790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Thu, 3 Sep 2020 20:52:24 +0200 Subject: [PATCH 016/150] Fix attendance item description (#943) --- .../ui/modules/attendance/AttendanceAdapter.kt | 3 ++- .../ui/modules/attendance/AttendanceDialog.kt | 3 ++- .../wulkanowy/utils/AttendanceExtension.kt | 16 +++++++++++++++- app/src/main/res/values-pl/strings.xml | 2 ++ app/src/main/res/values/strings.xml | 2 ++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt index a63d5045..8e8a6149 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt @@ -9,6 +9,7 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.repositories.attendance.SentExcuseStatus import io.github.wulkanowy.databinding.ItemAttendanceBinding +import io.github.wulkanowy.utils.description import javax.inject.Inject class AttendanceAdapter @Inject constructor() : @@ -34,7 +35,7 @@ class AttendanceAdapter @Inject constructor() : with(holder.binding) { attendanceItemNumber.text = item.number.toString() attendanceItemSubject.text = item.subject - attendanceItemDescription.text = item.name + attendanceItemDescription.setText(item.description) attendanceItemAlert.visibility = item.run { if (absence && !excused) View.VISIBLE else View.INVISIBLE } attendanceItemNumber.visibility = View.GONE attendanceItemExcuseInfo.visibility = View.GONE diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt index 97b76e81..d5e2fe12 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt @@ -7,6 +7,7 @@ import android.view.ViewGroup import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.databinding.DialogAttendanceBinding +import io.github.wulkanowy.utils.description import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.toFormattedString @@ -43,7 +44,7 @@ class AttendanceDialog : DialogFragment() { with(binding) { attendanceDialogSubject.text = attendance.subject - attendanceDialogDescription.text = attendance.name + attendanceDialogDescription.setText(attendance.description) attendanceDialogDate.text = attendance.date.toFormattedString() attendanceDialogNumber.text = attendance.number.toString() attendanceDialogClose.setOnClickListener { dismiss() } diff --git a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt index c2b1efaa..92e8661f 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt @@ -1,6 +1,9 @@ package io.github.wulkanowy.utils +import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.AttendanceSummary +import io.github.wulkanowy.sdk.scrapper.attendance.AttendanceCategory /** * [UONET+ - Zasady tworzenia podsumowań liczb uczniów obecnych i nieobecnych w tabeli frekwencji] @@ -23,4 +26,15 @@ private fun calculatePercentage(presence: Double, absence: Double): Double { return if ((presence + absence) == 0.0) 0.0 else (presence / (presence + absence)) * 100 } - +inline val Attendance.description + get() = when (AttendanceCategory.valueOf(name)) { + AttendanceCategory.PRESENCE -> R.string.attendance_present + AttendanceCategory.ABSENCE_UNEXCUSED -> R.string.attendance_absence_unexcused + AttendanceCategory.ABSENCE_EXCUSED -> R.string.attendance_absence_excused + AttendanceCategory.UNEXCUSED_LATENESS -> R.string.attendance_unexcused_lateness + AttendanceCategory.EXCUSED_LATENESS -> R.string.attendance_excused_lateness + AttendanceCategory.ABSENCE_FOR_SCHOOL_REASONS -> R.string.attendance_absence_school + AttendanceCategory.EXEMPTION -> R.string.attendance_exemption + AttendanceCategory.DELETED -> R.string.attendance_deleted + else -> R.string.attendance_unknown + } diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index e4d3e902..ebc14542 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -168,6 +168,8 @@ Spóźnienie usprawiedliwione Spóźnienie nieusprawiedliwione Obecność + Usunięty + Nieznany Numer lekcji Brak wpisów diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1eaebf28..963c7047 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -170,6 +170,8 @@ Excused lateness Unexcused lateness Present + Deleted + Unknown Number of lesson No entries From 18b9bf42e115ebf24885e6a4e4cb2e73c7e562ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Thu, 3 Sep 2020 20:54:28 +0200 Subject: [PATCH 017/150] Fix crash in flowWithResourceIn() (#944) --- app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt index aec52425..ba8bfd85 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import timber.log.Timber @@ -63,7 +64,7 @@ open class BasePresenter( fun Flow.launch(individualJobTag: String = "load"): Job { jobs[individualJobTag]?.cancel() - val job = launchIn(this@BasePresenter) + val job = catch { errorHandler.dispatch(it) }.launchIn(this@BasePresenter) jobs[individualJobTag] = job Timber.d("Job $individualJobTag launched in ${this@BasePresenter.javaClass.simpleName}: $job") return job From debb21f5f9945502ddf470c09aecd96ec05f8594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Thu, 3 Sep 2020 21:10:39 +0200 Subject: [PATCH 018/150] Add full stacktrace to errors list in sync now (#945) --- .../java/io/github/wulkanowy/services/sync/SyncWorker.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index 2ba0435b..13326ca0 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -50,13 +50,16 @@ class SyncWorker @WorkerInject constructor( } catch (e: Throwable) { Timber.w("${work::class.java.simpleName} result: An exception ${e.message} occurred") if (e is FeatureDisabledException || e is FeatureNotAvailableException) null - else e + else { + Timber.e(e) + e + } } } val result = when { exceptions.isNotEmpty() && inputData.getBoolean("one_time", false) -> { Result.failure(Data.Builder() - .putString("error", exceptions.toString()) + .putString("error", exceptions.map { it.stackTraceToString() }.toString()) .build() ) } From 9a7c04fe7b590f1661b0c25387d6b4a5f9f7f71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Fri, 4 Sep 2020 23:42:01 +0200 Subject: [PATCH 019/150] Version 0.20.3 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 7 ++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 688dd000..1c1038b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.20.2 + - 0.20.3 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index b046834a..2d608f97 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 66 - versionName "0.20.2" + versionCode 67 + versionName "0.20.3" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.20.2" + implementation "io.github.wulkanowy:sdk:0.20.3" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 d0e2c823..47df9980 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,7 +1,4 @@ -Wersja 0.20.2 -- naprawiliśmy powiadomienie o szczęśliwym numerku -- naprawiliśmy przełączanie na nowy rok szkolny -- naprawiliśmy funkcję resetowania hasła -- dodaliśmy dziennik e-Skarżysko +Wersja 0.20.3 +- naprawiliśmy opisy wpisów frekwencyjnych, które teraz będą już w całości po polsku Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases From c30f105be558acac6a783e40116f22fc65aefd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Mon, 7 Sep 2020 09:35:26 +0200 Subject: [PATCH 020/150] Fix crash on unknown attendance category type (#949) --- app/build.gradle | 2 +- .../main/java/io/github/wulkanowy/utils/AttendanceExtension.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2d608f97..cb7995d4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.20.3" + implementation "io.github.wulkanowy:sdk:0faa503" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' diff --git a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt index 92e8661f..f10b00a0 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt @@ -27,7 +27,7 @@ private fun calculatePercentage(presence: Double, absence: Double): Double { } inline val Attendance.description - get() = when (AttendanceCategory.valueOf(name)) { + get() = when (AttendanceCategory.getCategoryByName(name)) { AttendanceCategory.PRESENCE -> R.string.attendance_present AttendanceCategory.ABSENCE_UNEXCUSED -> R.string.attendance_absence_unexcused AttendanceCategory.ABSENCE_EXCUSED -> R.string.attendance_absence_excused From 6363c90e37452508d011be4f8e573664d17b311e Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Mon, 7 Sep 2020 20:28:32 +0200 Subject: [PATCH 021/150] Disable sound of upcoming lessons notification (fix) (#950) --- .../main/java/io/github/wulkanowy/services/sync/SyncManager.kt | 1 + .../wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 1d005ae8..47a94927 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 @@ -44,6 +44,7 @@ class SyncManager @Inject constructor( if (SDK_INT >= O) { channels.forEach { it.create() } + notificationManager.deleteNotificationChannel("lesson_channel") notificationManager.deleteNotificationChannel("new_entries_channel") } diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt index 41fb6192..63b3a4f9 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt @@ -17,7 +17,7 @@ class UpcomingLessonsChannel @Inject constructor( ) : Channel { companion object { - const val CHANNEL_ID = "lesson_channel" + const val CHANNEL_ID = "upcoming_lesson_channel" } override fun create() { From ec761f63294d977b46455a09c68d65236903436f Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Tue, 8 Sep 2020 20:13:17 +0200 Subject: [PATCH 022/150] Fix bug in grade statistics (#951) --- .../ui/modules/grade/statistics/GradeStatisticsPresenter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 112f4c58..73cee9e9 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 @@ -164,8 +164,8 @@ class GradeStatisticsPresenter @Inject constructor( Status.SUCCESS -> { Timber.i("Loading grade stats result: Success") view?.run { - showEmpty(it.data!!.isEmpty()) - showContent(it.data.isNotEmpty()) + showEmpty(it.data!!.isEmpty() || it.data.first().partial.isEmpty()) + showContent(it.data.isNotEmpty() && it.data.first().partial.isNotEmpty()) showErrorView(false) updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) From 6e56d3ff061d14308f8011723d56f3b56b4ca07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Wed, 9 Sep 2020 13:28:44 +0200 Subject: [PATCH 023/150] Ignore empty semesters on refresh (#955) --- .../wulkanowy/data/repositories/semester/SemesterRepository.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt index 7a76503f..2748f1df 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt @@ -8,6 +8,7 @@ import io.github.wulkanowy.utils.getCurrentOrLast import io.github.wulkanowy.utils.isCurrent import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.withContext +import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -41,7 +42,7 @@ class SemesterRepository @Inject constructor( private suspend fun refreshSemesters(student: Student) { val new = remote.getSemesters(student) - if (new.isEmpty()) throw IllegalArgumentException("Empty semester list!") + if (new.isEmpty()) return Timber.i("Empty semester list!") val old = local.getSemesters(student) local.deleteSemesters(old.uniqueSubtract(new)) From adde5541e2f4d42972c7e04eb3efa370ddc761f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Fri, 11 Sep 2020 13:02:16 +0200 Subject: [PATCH 024/150] Move timetable notifications scheduling to background thread (#954) --- .../TimetableNotificationSchedulerHelper.kt | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt index 8f8782a2..5c4b916b 100644 --- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt +++ b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt @@ -26,7 +26,9 @@ import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companio import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.STUDENT_ID import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.STUDENT_NAME import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.utils.DispatchersProvider import io.github.wulkanowy.utils.toTimestamp +import kotlinx.coroutines.withContext import timber.log.Timber import java.time.LocalDateTime import java.time.LocalDateTime.now @@ -35,7 +37,8 @@ import javax.inject.Inject class TimetableNotificationSchedulerHelper @Inject constructor( @ApplicationContext private val context: Context, private val alarmManager: AlarmManager, - private val preferencesRepository: PreferencesRepository + private val preferencesRepository: PreferencesRepository, + private val dispatchersProvider: DispatchersProvider, ) { private fun getRequestCode(time: LocalDateTime, studentId: Int) = (time.toTimestamp() * studentId).toInt() @@ -44,13 +47,15 @@ class TimetableNotificationSchedulerHelper @Inject constructor( return day.getOrNull(index - 1)?.end ?: lesson.start.minusMinutes(30) } - fun cancelScheduled(lessons: List, studentId: Int = 1) { - lessons.sortedBy { it.start }.forEachIndexed { index, lesson -> - val upcomingTime = getUpcomingLessonTime(index, lessons, lesson) - cancelScheduledTo(upcomingTime..lesson.start, getRequestCode(upcomingTime, studentId)) - cancelScheduledTo(lesson.start..lesson.end, getRequestCode(lesson.start, studentId)) + suspend fun cancelScheduled(lessons: List, studentId: Int = 1) { + withContext(dispatchersProvider.backgroundThread) { + lessons.sortedBy { it.start }.forEachIndexed { index, lesson -> + val upcomingTime = getUpcomingLessonTime(index, lessons, lesson) + cancelScheduledTo(upcomingTime..lesson.start, getRequestCode(upcomingTime, studentId)) + cancelScheduledTo(lesson.start..lesson.end, getRequestCode(lesson.start, studentId)) - Timber.d("TimetableNotification canceled: type 1 & 2, subject: ${lesson.subject}, start: ${lesson.start}, student: $studentId") + Timber.d("TimetableNotification canceled: type 1 & 2, subject: ${lesson.subject}, start: ${lesson.start}, student: $studentId") + } } } @@ -61,28 +66,30 @@ class TimetableNotificationSchedulerHelper @Inject constructor( fun cancelNotification() = NotificationManagerCompat.from(context).cancel(MainView.Section.TIMETABLE.id) - fun scheduleNotifications(lessons: List, student: Student) { + suspend fun scheduleNotifications(lessons: List, student: Student) { if (!preferencesRepository.isUpcomingLessonsNotificationsEnable) return cancelScheduled(lessons, student.studentId) - lessons.groupBy { it.date } - .map { it.value.sortedBy { lesson -> lesson.start } } - .map { it.filter { lesson -> !lesson.canceled && lesson.isStudentPlan } } - .map { day -> - day.forEachIndexed { index, lesson -> - val intent = createIntent(student, lesson, day.getOrNull(index + 1)) + withContext(dispatchersProvider.backgroundThread) { + lessons.groupBy { it.date } + .map { it.value.sortedBy { lesson -> lesson.start } } + .map { it.filter { lesson -> !lesson.canceled && lesson.isStudentPlan } } + .map { day -> + day.forEachIndexed { index, lesson -> + val intent = createIntent(student, lesson, day.getOrNull(index + 1)) - if (lesson.start > now()) { - scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_UPCOMING, getUpcomingLessonTime(index, day, lesson)) - } + if (lesson.start > now()) { + scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_UPCOMING, getUpcomingLessonTime(index, day, lesson)) + } - if (lesson.end > now()) { - scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_CURRENT, lesson.start) - if (day.lastIndex == index) { - scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION, lesson.end) + if (lesson.end > now()) { + scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_CURRENT, lesson.start) + if (day.lastIndex == index) { + scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION, lesson.end) + } } } } - } + } } private fun createIntent(student: Student, lesson: Timetable, nextLesson: Timetable?): Intent { From cd51fac621c9cee5a87018ec43fae54708a1ef62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 13 Sep 2020 13:46:45 +0200 Subject: [PATCH 025/150] Add eduportal.koszalin.pl register (#959) --- app/build.gradle | 2 +- app/src/main/res/values/api_hosts.xml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cb7995d4..c4c6efa8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0faa503" + implementation "io.github.wulkanowy:sdk:7c0e838" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' diff --git a/app/src/main/res/values/api_hosts.xml b/app/src/main/res/values/api_hosts.xml index 64618568..29434602 100644 --- a/app/src/main/res/values/api_hosts.xml +++ b/app/src/main/res/values/api_hosts.xml @@ -7,6 +7,7 @@ Lubelski Portal Oświatowy EduNet Miasta Tarnowa ResMan Rzeszów + Platforma Edukacyjna Koszalina Rawa Mazowiecka - Platforma vEdukacja Zduńska Wola - e-Urząd Sieradz - Portal oświatowy @@ -27,6 +28,7 @@ https://edu.lublin.eu https://umt.tarnow.pl https://resman.pl + https://eduportal.koszalin.pl https://vulcan.net.pl/ https://vulcan.net.pl/ https://vulcan.net.pl/ @@ -47,6 +49,7 @@ lublin tarnow rzeszow + koszalin rawamazowiecka zdunskawola sieradz From 7cfe58d311f0f75d17c9fb8d9f5f86a0dc2bb50e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2020 14:02:31 +0000 Subject: [PATCH 026/150] Bump material from 1.2.0 to 1.2.1 (#963) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index c4c6efa8..e4d84e0c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -147,7 +147,7 @@ dependencies { implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.constraintlayout:constraintlayout:2.0.1" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" - implementation "com.google.android.material:material:1.2.0" + implementation "com.google.android.material:material:1.2.1" implementation "com.github.wulkanowy:material-chips-input:2.1.1" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" From 53561668fc704dfed91a9ac42f53fe82821e4ac7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2020 14:03:09 +0000 Subject: [PATCH 027/150] Bump hilt_version from 2.28.3-alpha to 2.29.1-alpha (#962) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9f239fdd..7ccadff3 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { kotlin_version = '1.4.0' about_libraries = '8.3.0' - hilt_version = "2.28.3-alpha" + hilt_version = "2.29.1-alpha" } repositories { mavenCentral() From acf5c8e9ba6708baec1dde1d979c5c1345af44ed Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2020 14:04:41 +0000 Subject: [PATCH 028/150] Bump firebase-crashlytics-gradle from 2.2.1 to 2.3.0 (#964) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7ccadff3..d40c71dc 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { classpath 'com.android.tools.build:gradle:4.0.1' classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.3' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' classpath "com.github.triplet.gradle:play-publisher:2.7.5" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0" classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0" From 792b1235982ce87b3334b19812f77b9df1f38d5a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2020 14:07:30 +0000 Subject: [PATCH 029/150] Bump coil from 1.0.0-rc1 to 1.0.0-rc2 (#961) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index e4d84e0c..eb1cab5e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -176,7 +176,7 @@ dependencies { implementation "fr.bipi.treessence:treessence:0.3.2" implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation 'com.wdullaer:materialdatetimepicker:4.2.3' - implementation "io.coil-kt:coil:1.0.0-rc1" + implementation "io.coil-kt:coil:1.0.0-rc2" implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' From 47150364d862fff62feac2008844e7630a7403fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 13 Sep 2020 16:27:53 +0200 Subject: [PATCH 030/150] Fix lifecycle of timer tasks in timetable lessons (#958) Co-authored-by: Faierbel --- .../java/io/github/wulkanowy/data/Resource.kt | 2 +- .../ui/modules/timetable/TimetableAdapter.kt | 18 +++++++++--------- .../ui/modules/timetable/TimetableFragment.kt | 1 + .../io/github/wulkanowy/utils/FlowUtils.kt | 2 +- build.gradle | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/Resource.kt b/app/src/main/java/io/github/wulkanowy/data/Resource.kt index ae22832a..406440c8 100644 --- a/app/src/main/java/io/github/wulkanowy/data/Resource.kt +++ b/app/src/main/java/io/github/wulkanowy/data/Resource.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.data -data class Resource(val status: Status, val data: T?, val error: Throwable?) { +data class Resource(val status: Status, val data: T?, val error: Throwable?) { companion object { fun success(data: T?): Resource { return Resource(Status.SUCCESS, data, null) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt index d87f0620..58be38ce 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt @@ -6,6 +6,7 @@ import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.TextView +import androidx.core.view.ViewCompat import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Timetable @@ -44,8 +45,8 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter() - private fun resetTimers() { - Timber.d("Timetable timers reset") + fun resetTimers() { + Timber.d("Timetable timers (${timers.size}) reset") with(timers) { forEach { (_, timer) -> timer.cancel() } clear() @@ -69,11 +70,6 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter(R.layout.fragme } override fun onDestroyView() { + timetableAdapter.resetTimers() presenter.onDetachView() super.onDestroyView() } diff --git a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt index 31499405..23b86dd3 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt @@ -89,7 +89,7 @@ fun flowWithResourceIn(block: suspend () -> Flow>) = flow { } } } catch (e: Throwable) { - emit(Resource.error(e)) + emit(Resource.error(e)) } } diff --git a/build.gradle b/build.gradle index d40c71dc..4205cce5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - kotlin_version = '1.4.0' + kotlin_version = '1.4.10' about_libraries = '8.3.0' hilt_version = "2.29.1-alpha" } From 5d8fb376abcae8211409ecfdcd354ee4a56f7256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 13 Sep 2020 18:37:34 +0200 Subject: [PATCH 031/150] Expand exam sync date range to next month (#960) --- .../data/repositories/exam/ExamRepository.kt | 8 ++-- .../wulkanowy/services/sync/works/ExamWork.kt | 4 +- .../github/wulkanowy/utils/TimeExtension.kt | 9 ++++- .../wulkanowy/utils/TimeExtensionTest.kt | 38 +++++++++++++++++++ 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt index e7f115ac..3f4591a2 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt @@ -2,9 +2,9 @@ package io.github.wulkanowy.data.repositories.exam import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.monday +import io.github.wulkanowy.utils.endExamsDay import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.sunday +import io.github.wulkanowy.utils.startExamsDay import io.github.wulkanowy.utils.uniqueSubtract import java.time.LocalDate import javax.inject.Inject @@ -18,8 +18,8 @@ class ExamRepository @Inject constructor( fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getExams(semester, start.monday, end.sunday) }, - fetch = { remote.getExams(student, semester, start.monday, end.sunday) }, + query = { local.getExams(semester, start.startExamsDay, start.endExamsDay) }, + fetch = { remote.getExams(student, semester, start.startExamsDay, start.endExamsDay) }, saveFetchResult = { old, new -> local.deleteExams(old uniqueSubtract new) local.saveExams(new uniqueSubtract old) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt index f7d8db0a..899d45cb 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt @@ -3,8 +3,6 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.repositories.exam.ExamRepository -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.waitForResult import java.time.LocalDate.now import javax.inject.Inject @@ -12,6 +10,6 @@ import javax.inject.Inject class ExamWork @Inject constructor(private val examRepository: ExamRepository) : Work { override suspend fun doWork(student: Student, semester: Semester) { - examRepository.getExams(student, semester, now().monday, now().sunday, true).waitForResult() + examRepository.getExams(student, semester, now(), now(), true).waitForResult() } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt index d1aba160..9bd30e87 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt @@ -13,8 +13,7 @@ import java.time.Month import java.time.ZoneId import java.time.ZoneOffset import java.time.format.DateTimeFormatter.ofPattern -import java.time.format.TextStyle.FULL_STANDALONE -import java.time.format.TextStyle.* +import java.time.format.TextStyle.FULL import java.time.temporal.TemporalAdjusters.firstInMonth import java.time.temporal.TemporalAdjusters.next import java.time.temporal.TemporalAdjusters.previous @@ -78,6 +77,12 @@ inline val LocalDate.nextOrSameSchoolDay: LocalDate } } +inline val LocalDate.startExamsDay: LocalDate + get() = nextOrSameSchoolDay.monday + +inline val LocalDate.endExamsDay: LocalDate + get() = nextOrSameSchoolDay.monday.plusWeeks(4).minusDays(1) + inline val LocalDate.previousOrSameSchoolDay: LocalDate get() { return when (dayOfWeek) { diff --git a/app/src/test/java/io/github/wulkanowy/utils/TimeExtensionTest.kt b/app/src/test/java/io/github/wulkanowy/utils/TimeExtensionTest.kt index 9709ded3..d604dfef 100644 --- a/app/src/test/java/io/github/wulkanowy/utils/TimeExtensionTest.kt +++ b/app/src/test/java/io/github/wulkanowy/utils/TimeExtensionTest.kt @@ -171,4 +171,42 @@ class TimeExtensionTest { assertEquals(of(2019, 5, 1), of(2019, 5, 1).getLastSchoolDayIfHoliday(2018)) assertEquals(of(2018, 5, 1), of(2019, 5, 1).getLastSchoolDayIfHoliday(2017)) } + + @Test + fun getExamsCutOffDates() { + with(of(2020, 9, 13)) { + assertEquals(of(2020, 9, 14), startExamsDay) + assertEquals(of(2020, 10, 11), endExamsDay) + } + + with(of(2020, 9, 14)) { + assertEquals(of(2020, 9, 14), startExamsDay) + assertEquals(of(2020, 10, 11), endExamsDay) + } + + with(of(2020, 9, 15)) { + assertEquals(of(2020, 9, 14), startExamsDay) + assertEquals(of(2020, 10, 11), endExamsDay) + } + + with(of(2020, 9, 16)) { + assertEquals(of(2020, 9, 14), startExamsDay) + assertEquals(of(2020, 10, 11), endExamsDay) + } + + with(of(2020, 9, 17)) { + assertEquals(of(2020, 9, 14), startExamsDay) + assertEquals(of(2020, 10, 11), endExamsDay) + } + + with(of(2020, 9, 18)) { + assertEquals(of(2020, 9, 14), startExamsDay) + assertEquals(of(2020, 10, 11), endExamsDay) + } + + with(of(2020, 9, 19)) { + assertEquals(of(2020, 9, 21), startExamsDay) + assertEquals(of(2020, 10, 18), endExamsDay) + } + } } From cd92f37435f8122db016072a9fc6a99790d343d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 13 Sep 2020 19:00:32 +0200 Subject: [PATCH 032/150] Version 0.20.4 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 7 +++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c1038b8..eadf43fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.20.3 + - 0.20.4 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index eb1cab5e..d9936480 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 67 - versionName "0.20.3" + versionCode 68 + versionName "0.20.4" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:7c0e838" + implementation "io.github.wulkanowy:sdk:0.20.4" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 47df9980..6ca04c57 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,4 +1,7 @@ -Wersja 0.20.3 -- naprawiliśmy opisy wpisów frekwencyjnych, które teraz będą już w całości po polsku +Wersja 0.20.4 +- dodaliśmy obsługę koszalińskiego dziennika +- poprawiliśmy synchronizację sprawdzianów +- wyłączyliśmy dźwięk powiadomienia przy włączonej opcji pokazywania nadchodzących lekcji w powiadomieniu +- poprawiliśmy problemy ze stabilnością we frekwencji i planie lekcji Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases From 73be4168078678233d71619d8905bc9ddfe22c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 19 Sep 2020 00:57:55 +0200 Subject: [PATCH 033/150] Fix crash in flowWithResourceIn() (#967) --- app/build.gradle | 2 +- .../github/wulkanowy/data/db/dao/MessagesDao.kt | 2 +- .../github/wulkanowy/data/db/entities/Message.kt | 12 ++++++------ .../data/repositories/message/MessageLocal.kt | 3 +-- .../data/repositories/message/MessageRemote.kt | 4 ++-- .../repositories/message/MessageRepository.kt | 4 +++- .../message/preview/MessagePreviewPresenter.kt | 4 +++- .../java/io/github/wulkanowy/utils/FlowUtils.kt | 16 ++++++---------- .../java/io/github/wulkanowy/TestEnityCreator.kt | 4 ++-- 9 files changed, 25 insertions(+), 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d9936480..9107f810 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.20.4" + implementation "io.github.wulkanowy:sdk:b652036" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 79050de0..729ba6a6 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 @@ -12,7 +12,7 @@ interface MessagesDao : BaseDao { @Transaction @Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId") - fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow + fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow @Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC") fun loadAll(studentId: Int, folder: Int): Flow> diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt index 914dc381..1f10a164 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt @@ -36,12 +36,6 @@ data class Message( var unread: Boolean, - @ColumnInfo(name = "unread_by") - val unreadBy: Int, - - @ColumnInfo(name = "read_by") - val readBy: Int, - val removed: Boolean, @ColumnInfo(name = "has_attachments") @@ -54,5 +48,11 @@ data class Message( @ColumnInfo(name = "is_notified") var isNotified: Boolean = true + @ColumnInfo(name = "unread_by") + var unreadBy: Int = 0 + + @ColumnInfo(name = "read_by") + var readBy: Int = 0 + var content: String = "" } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt index 730bd005..f1c8eaf0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt @@ -6,7 +6,6 @@ import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.MessageAttachment import io.github.wulkanowy.data.db.entities.MessageWithAttachment import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED import kotlinx.coroutines.flow.Flow import javax.inject.Inject import javax.inject.Singleton @@ -29,7 +28,7 @@ class MessageLocal @Inject constructor( messagesDb.deleteAll(messages) } - fun getMessageWithAttachment(student: Student, message: Message): Flow { + fun getMessageWithAttachment(student: Student, message: Message): Flow { return messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) } 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 fdf0c675..044a13a2 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 @@ -30,12 +30,12 @@ class MessageRemote @Inject constructor(private val sdk: Sdk) { date = it.date ?: now(), folderId = it.folderId, unread = it.unread ?: false, - unreadBy = it.unreadBy ?: 0, - readBy = it.readBy ?: 0, removed = it.removed, hasAttachments = it.hasAttachments ).apply { content = it.content.orEmpty() + unreadBy = it.unreadBy ?: 0 + readBy = it.readBy ?: 0 } } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt index f653f268..bb932699 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt @@ -34,12 +34,14 @@ class MessageRepository @Inject constructor( fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource( shouldFetch = { + checkNotNull(it, { "This message no longer exist!" }) Timber.d("Message content in db empty: ${it.message.content.isEmpty()}") it.message.unread || it.message.content.isEmpty() }, query = { local.getMessageWithAttachment(student, message) }, - fetch = { remote.getMessagesContentDetails(student, it.message, markAsRead) }, + fetch = { remote.getMessagesContentDetails(student, it!!.message, markAsRead) }, saveFetchResult = { old, (downloadedMessage, attachments) -> + checkNotNull(old, { "Fetched message no longer exist!" }) local.updateMessages(listOf(old.message.copy(unread = !markAsRead).apply { id = old.message.id content = content.ifBlank { downloadedMessage } 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 d261d1ee..7a633a2d 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 @@ -64,7 +64,8 @@ class MessagePreviewPresenter @Inject constructor( when (it.status) { Status.LOADING -> Timber.i("Loading message ${message.messageId} preview started") Status.SUCCESS -> { - Timber.i("Loading message ${it.data!!.message.messageId} preview result: Success ") + Timber.i("Loading message ${message.messageId} preview result: Success ") + checkNotNull(it.data, { "Can't find message in local db! Probably no longer exist in this folder" }) this@MessagePreviewPresenter.message = it.data.message this@MessagePreviewPresenter.attachments = it.data.attachments view?.apply { @@ -194,6 +195,7 @@ class MessagePreviewPresenter @Inject constructor( view?.run { lastError = error setErrorDetails(message) + showContent(false) showErrorView(true) setErrorRetryCallback { retryCallback() } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt index 23b86dd3..724458c0 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt @@ -80,17 +80,13 @@ fun flowWithResource(block: suspend () -> T) = flow { fun flowWithResourceIn(block: suspend () -> Flow>) = flow { emit(Resource.loading()) - try { - block() - .catch { emit(Resource.error(it)) } - .collect { - if (it.status != Status.LOADING) { // LOADING is already emitted - emit(it) - } + block() + .catch { emit(Resource.error(it)) } + .collect { + if (it.status != Status.LOADING) { // LOADING is already emitted + emit(it) } - } catch (e: Throwable) { - emit(Resource.error(e)) - } + } } fun Flow>.afterLoading(callback: () -> Unit) = onEach { diff --git a/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt b/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt index 35a20030..d15dc953 100644 --- a/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt +++ b/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt @@ -90,10 +90,10 @@ fun getMessageEntity( date = now(), folderId = 1, unread = unread, - unreadBy = 1, - readBy = 1, removed = false, hasAttachments = false ).apply { this.content = content + unreadBy = 1 + readBy = 1 } From d6ebc343d5b039c909ed32e729d9091ec51da008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 19 Sep 2020 01:25:34 +0200 Subject: [PATCH 034/150] Version 0.20.5 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 8 +++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index eadf43fc..5dbd9e36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.20.4 + - 0.20.5 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 9107f810..11a82fbd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 68 - versionName "0.20.4" + versionCode 69 + versionName "0.20.5" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -126,7 +126,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:b652036" + implementation "io.github.wulkanowy:sdk:0.20.5" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 6ca04c57..62a71f43 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,7 +1,5 @@ -Wersja 0.20.4 -- dodaliśmy obsługę koszalińskiego dziennika -- poprawiliśmy synchronizację sprawdzianów -- wyłączyliśmy dźwięk powiadomienia przy włączonej opcji pokazywania nadchodzących lekcji w powiadomieniu -- poprawiliśmy problemy ze stabilnością we frekwencji i planie lekcji +Wersja 0.20.5 +- naprawiliśmy logowanie do koszalińskiego dziennika +- naprawiliśmy resetowanie hasła na gdańskim dzienniku Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases From b0b3ccfd530e2b450804c194365b4e4fe225c754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 20 Sep 2020 21:54:59 +0200 Subject: [PATCH 035/150] Upgrade gradle wrapper to 6.6.1 (#968) --- .travis.yml | 4 ++-- app/jacoco.gradle | 4 ++-- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58695 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 ++ gradlew.bat | 22 ++++------------------ 11 files changed, 16 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5dbd9e36..45818739 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,8 +48,8 @@ before_script: script: - ./gradlew dependencies --stacktrace --daemon - fossa --no-ansi || true - - ./gradlew -Pcoverage testPlayDebugUnitTest --stacktrace --daemon - - ./gradlew -Pcoverage createFdroidDebugCoverageReport --stacktrace --daemon + - ./gradlew -Pcoverage testFdroidDebugUnitTest --stacktrace --daemon + - ./gradlew -Pcoverage connectedFdroidDebugAndroidTest --stacktrace --daemon - ./gradlew -Pcoverage jacocoTestReport --stacktrace --daemon - | if [ $TRAVIS_TAG ]; then diff --git a/app/jacoco.gradle b/app/jacoco.gradle index e9abfb61..a5cf84e6 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -35,13 +35,13 @@ task jacocoTestReport(type: JacocoReport) { dir: "$buildDir/intermediates/classes/debug", excludes: excludes ) + fileTree( - dir: "$buildDir/tmp/kotlin-classes/playDebug", + dir: "$buildDir/tmp/kotlin-classes/fdroidDebug", excludes: excludes )) sourceDirectories.setFrom(files([ "src/main/java", - "src/play/java" + "src/fdroid/java" ])) executionData.setFrom(fileTree( dir: project.projectDir, diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 42169ca5..7e287767 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -19,7 +19,7 @@ Hausaufgaben Wählen Sie ein Konto - Semester %d, %d/%d + Semester %1$d, %2$d/%3$d Melden Sie sich mit dem Studenten- oder Elternkonto an Geben Sie das Symbol diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index ebc14542..bc94b227 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -19,7 +19,7 @@ Zadania domowe Wybierz konto - Semestr %d, %d/%d + Semestr %1$d, %2$d/%3$d Zaloguj się za pomocą konta ucznia lub rodzica Podaj symbol diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 15c58317..7052fbc9 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -19,7 +19,7 @@ Домашние задания Выберите аккаунт - %d семестр, %d/%d + %1$d семестр, %2$d/%3$d Авторизируйтесь при помощи аккаунта ученика или родителя Впишите \"symbol\" diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 423c4e12..15fe203d 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -19,7 +19,7 @@ Домашні завдання Оберіть аккаунт - %d семестр, %d/%d + %1$d семестр, %2$d/%3$d Авторизуйтеся за допомогою аккаунта учня або батька Впишіть \"symbol\" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 963c7047..7df2b68a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,7 +21,7 @@ - Semester %d, %d/%d + Semester %1$d, %2$d/%3$d diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f3d88b1c2faf2fc91d853cd5d4242b5547257070..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 12842 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6623300b..33682bbb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7d..4f906e0c 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 9109989e..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 2a74b11cce0a0388d1dd2d5e589a0fa5a23969bb Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Fri, 25 Sep 2020 15:37:19 +0200 Subject: [PATCH 036/150] Add app shortcuts (#939) Co-authored-by: Faierbel --- .../wulkanowy/ui/modules/main/MainActivity.kt | 42 +++++++++++++++++- .../drawable-hdpi/ic_shortcut_attendance.png | Bin 0 -> 1536 bytes .../res/drawable-hdpi/ic_shortcut_exam.png | Bin 0 -> 1602 bytes .../res/drawable-hdpi/ic_shortcut_grade.png | Bin 0 -> 1812 bytes .../res/drawable-hdpi/ic_shortcut_message.png | Bin 0 -> 1775 bytes .../drawable-hdpi/ic_shortcut_timetable.png | Bin 0 -> 1625 bytes .../drawable-mdpi/ic_shortcut_attendance.png | Bin 0 -> 902 bytes .../res/drawable-mdpi/ic_shortcut_exam.png | Bin 0 -> 913 bytes .../res/drawable-mdpi/ic_shortcut_grade.png | Bin 0 -> 1034 bytes .../res/drawable-mdpi/ic_shortcut_message.png | Bin 0 -> 1048 bytes .../drawable-mdpi/ic_shortcut_timetable.png | Bin 0 -> 937 bytes .../drawable-xhdpi/ic_shortcut_attendance.png | Bin 0 -> 1907 bytes .../res/drawable-xhdpi/ic_shortcut_exam.png | Bin 0 -> 1940 bytes .../res/drawable-xhdpi/ic_shortcut_grade.png | Bin 0 -> 2231 bytes .../drawable-xhdpi/ic_shortcut_message.png | Bin 0 -> 2387 bytes .../drawable-xhdpi/ic_shortcut_timetable.png | Bin 0 -> 1971 bytes .../ic_shortcut_attendance.png | Bin 0 -> 3393 bytes .../res/drawable-xxhdpi/ic_shortcut_exam.png | Bin 0 -> 3417 bytes .../res/drawable-xxhdpi/ic_shortcut_grade.png | Bin 0 -> 3917 bytes .../drawable-xxhdpi/ic_shortcut_message.png | Bin 0 -> 4279 bytes .../drawable-xxhdpi/ic_shortcut_timetable.png | Bin 0 -> 3457 bytes .../ic_shortcut_attendance.png | Bin 0 -> 4892 bytes .../res/drawable-xxxhdpi/ic_shortcut_exam.png | Bin 0 -> 5027 bytes .../drawable-xxxhdpi/ic_shortcut_grade.png | Bin 0 -> 5529 bytes .../drawable-xxxhdpi/ic_shortcut_message.png | Bin 0 -> 5994 bytes .../ic_shortcut_timetable.png | Bin 0 -> 5087 bytes 26 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_shortcut_attendance.png create mode 100644 app/src/main/res/drawable-hdpi/ic_shortcut_exam.png create mode 100644 app/src/main/res/drawable-hdpi/ic_shortcut_grade.png create mode 100644 app/src/main/res/drawable-hdpi/ic_shortcut_message.png create mode 100644 app/src/main/res/drawable-hdpi/ic_shortcut_timetable.png create mode 100644 app/src/main/res/drawable-mdpi/ic_shortcut_attendance.png create mode 100644 app/src/main/res/drawable-mdpi/ic_shortcut_exam.png create mode 100644 app/src/main/res/drawable-mdpi/ic_shortcut_grade.png create mode 100644 app/src/main/res/drawable-mdpi/ic_shortcut_message.png create mode 100644 app/src/main/res/drawable-mdpi/ic_shortcut_timetable.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_shortcut_attendance.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_shortcut_exam.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_shortcut_grade.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_shortcut_message.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_shortcut_timetable.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_shortcut_attendance.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_shortcut_exam.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_shortcut_grade.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_shortcut_message.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_shortcut_timetable.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_shortcut_attendance.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_shortcut_exam.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_shortcut_grade.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_shortcut_message.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_shortcut_timetable.png 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 03560889..95b4aa77 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 @@ -1,14 +1,21 @@ package io.github.wulkanowy.ui.modules.main +import android.annotation.SuppressLint import android.content.Context import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK +import android.content.pm.ShortcutInfo +import android.content.pm.ShortcutManager +import android.graphics.drawable.Icon +import android.os.Build import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.LOLLIPOP import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.annotation.RequiresApi +import androidx.core.content.getSystemService import androidx.core.view.ViewCompat import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment @@ -31,6 +38,7 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor @@ -48,6 +56,9 @@ class MainActivity : BaseActivity(), MainVie @Inject lateinit var analytics: FirebaseAnalyticsHelper + @Inject + lateinit var appInfo: AppInfo + private val overlayProvider by lazy { ElevationOverlayProvider(this) } private val navController = FragNavController(supportFragmentManager, R.id.mainFragmentContainer) @@ -59,7 +70,7 @@ class MainActivity : BaseActivity(), MainVie return Intent(context, MainActivity::class.java) .apply { if (clear) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK - startMenu?.let { putExtra(EXTRA_START_MENU, it) } + startMenu?.let { putExtra(EXTRA_START_MENU, it.id) } } } } @@ -83,18 +94,45 @@ class MainActivity : BaseActivity(), MainVie MainView.Section.LUCKY_NUMBER.id to LuckyNumberFragment.newInstance() ) + @SuppressLint("NewApi") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(ActivityMainBinding.inflate(layoutInflater).apply { binding = this }.root) setSupportActionBar(binding.mainToolbar) messageContainer = binding.mainFragmentContainer - presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_START_MENU) as? MainView.Section) + presenter.onAttachView(this, MainView.Section.values().singleOrNull { it.id == intent.getIntExtra(EXTRA_START_MENU, -1) }) with(navController) { initialize(startMenuIndex, savedInstanceState) pushFragment(moreMenuFragments[startMenuMoreIndex]) } + if (appInfo.systemVersion >= Build.VERSION_CODES.N_MR1) initShortcuts() + } + + @RequiresApi(Build.VERSION_CODES.N_MR1) + fun initShortcuts() { + val shortcutsList = mutableListOf() + + listOf( + Triple(getString(R.string.grade_title), R.drawable.ic_shortcut_grade, MainView.Section.GRADE), + Triple(getString(R.string.attendance_title), R.drawable.ic_shortcut_attendance, MainView.Section.ATTENDANCE), + Triple(getString(R.string.exam_title), R.drawable.ic_shortcut_exam, MainView.Section.EXAM), + Triple(getString(R.string.timetable_title), R.drawable.ic_shortcut_timetable, MainView.Section.TIMETABLE), + Triple(getString(R.string.message_title), R.drawable.ic_shortcut_message, MainView.Section.MESSAGE) + ).forEach { (title, icon, enum) -> + shortcutsList.add(ShortcutInfo.Builder(applicationContext, title) + .setShortLabel(title) + .setLongLabel(title) + .setIcon(Icon.createWithResource(applicationContext, icon)) + .setIntents(arrayOf( + Intent(applicationContext, MainActivity::class.java).setAction(Intent.ACTION_VIEW), + Intent(applicationContext, MainActivity::class.java).putExtra(EXTRA_START_MENU, enum.id) + .setAction(Intent.ACTION_VIEW).addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK))) + .build()) + } + + getSystemService()?.dynamicShortcuts = shortcutsList } override fun onCreateOptionsMenu(menu: Menu?): Boolean { diff --git a/app/src/main/res/drawable-hdpi/ic_shortcut_attendance.png b/app/src/main/res/drawable-hdpi/ic_shortcut_attendance.png new file mode 100644 index 0000000000000000000000000000000000000000..0b5feff2dfcbc56abf45eb59dab87786b7944275 GIT binary patch literal 1536 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84mJh`hS0a0-5D5Ik9)c}hE&A8o#USq;wp1| z|NgtILSAb+mzq9YARc|B)_VOEG5t7>Bh8D#`L?Mo)2L4pUi9K@v-wIPB~Rzfx4cv!}vt>$JH0*Y3XE_dV@?_3d}3d^UORw*LJ4?C&%0 z%|Fks?_V%ko$*r59?lF0JF!g<8|sqR7_)yl+7VQ_pu44lk)e2{y80qZ#yhP7dlZiF zcrSmSv*c<%#{!<@e4&B}hV{%791bn9WU3Q7VA}jy{t!oyX0*A(cHhrSn*^GfD)=2{ zd!;fxiBx$oTjJsmxzoGE7wpNOc!Du?(n%4a&VGd>4eP&Y7z_9+O#glAMB3$vUA1JCd{M?i@F(ROCV;#d`2CGFYLRgHRG0riw_^-ES z&4q?dE3ddZmYC$Yz6zYzBH_L4^85CQvJw-FV@`{`;tp=Cny#9l#mBSf%+I?DyO@6Hi;+KGRlE?PtHS7$% z5}@^TuDOMLQSc+K6Z57Xf4t}3)@+WSKW&PmSqs=xX5G*GG3jX9MWtB=Ia%?C zl<3X<`}c)}6jSa^A-A6V$d5k^|JjuD)yM97GW)tVGh_OsIrUL9muoHHN#;(R?s>ak zw)szv%dYx|Oi$EPqD(CAzvTAN+rYd-ENCY0a*h`l-{^$p-D7Ft&@S6*BN$axwPEk> z+yBg!9D=SqJk{G!DmEoGCxl_4*vuu%f*iOXKi*+)#3U%Fpyc$sQ}~9Zg@mR8lb)L8 z{{>q_uQQ%9_~yAN9$lPL;^E*PE^ef}Wr1b$XYp9Z zk0GnH-BgsHUs!pjsjGqE&5PI0r}x!v`_pc095Hj=w*S-azrFF^wmxQOAv6EnKc!49 zEEhtpF6(EX<4Jzcz_Itj-g8I27#tF{5n;iBZ{Q2G0@@a!l zv4m5NOyi_idTQ#Wdh0G~G$gqkULSESsw0?9BYReOi$MNW;Q;S^{itv6wuX94pD2I( zXjPR${bw)j?Rkl*X~)h5>5B`yga=RiT2{)Pbmo(VM}YA5RkZ;wi)Xxf@tT!`!Q8_9 zE`zJciV&X9OBYA@&WJU-E-t`x?z+wDO_SH@D;%G?ZT4#3En*H#Wf#=%p3%15wB~BV z<~}{O)O;<4+ooNN_g=iXCE{3jz3z{NhFEc`3bUW}yh{zMjH|R5ZWe32P5OV|FN*(j z+~JyAChIQ*%V`K*yt*WM!H?CM^E5dMt-1n^=5D(6BA8d8HZ$Uy6tit)Y(DS1$)V31 zoK&7qm|ePavBHsemp0$1I=JRe(;o3NDRFzByxRX{mH1olHD39@|FApf-acNq`GR!& zd0ES*=l*kdUU{IkSizj{{Jf)=o}OO#<;s>qiKEww7p>)8+s>zW@0Qf6M|G{m z{BjTGzrH>(I_lHuS3j$Lqt6Egxyi?EXngfpf0EOL$NJkuUowZh6H{S)sazqa7xw1j z7e&9;eev?lVGUCfb5>o<|E6K%R+uu&tLWb16+Ad)dr}V-&B9v*r~RI(PS>euh8}Op?2vB4z7;9GE6J(z4%x(>q5gE&CY#d z@2;D^6zBdSSX6g?{jva-rSW--I8MD>{N;6FNTp@^#%jkS94|!d^dp2^iVGk3Id+sV z&ET_&S$$3aQ=;99M`@bkCk^iF@Jlb5CpCe8YdvFs)1k6Yv6ibC7#J8lUHx3vIVCg! E09nbx1poj5 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_shortcut_exam.png b/app/src/main/res/drawable-hdpi/ic_shortcut_exam.png new file mode 100644 index 0000000000000000000000000000000000000000..e5af0d086652352adeb55f94422f0dbad97f8b7c GIT binary patch literal 1602 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84mJh`hS0a0-5D6zI6Yk)Ln`9l&bgl-;wo}{ z|MPcF4NixfpN4yUado({yO?{Sgb*{oie182c>y1eh&q>e5nlzvg%4dXh;u%5pRE@5 zpV7hDr$%v)2k*1M{T_5e8J%w4o0(U z4=eo=Jn+e2>OO|KJB2y0rfxo(%U&MRqdutBAsV8GjZQ{$DKO=y7bu1I( zD~I!$EP^*CZ($65Hm8QY>YS2C=7DQ-CvRaCZTZpJXnSkl&MmCRb2YdATEv>6ssA+b zxMMl@1MU@@IAyqRPf%S~ek0%brci)t&5x@$_-4LZmCSccuWMboZ}4ZA+fl8mx{Oa- zf1FCm+4}Fw%BbMw>th(Fdqqt+v1!A*Bb~F}TzPsrs%ni=(Qx)L54F^j}Zm?pwTcxo(IK*Ls}>bA{tSZ7JdG=L_=poJRjeSF%b=6F=`Pj@VnSzhd%pYH=PPwn`}Gy3Ca@Q1XXU<{98v#iN#*&>90}uPZEXweBAJ)& z|EQ2KkzKT9$1#T`DwDHT%*ucDT!y*#yUD_5DqqF73KZBXKXuqU*R|o3)1SNt8OxLz z8E0%+T60u*!kM(~Q7&1}WpJy(>~o^ z)vm+x#6tYwpTd;ynKPQx+}sUo-%1IX{QH!}A$X0KXTkFhtH~~v{|pV;HKWBY9+h1e zefyCPLrB3K=`(+}6*?R~{B-Iu6@{%%Vdnj6jD{D_u6e!h@}1_EfP<5+yEZx8dG%aj zD@!=z$^*hLw=CCP`=e*Yp4JX#0ftQPNbYY^&lfaUa^$D^GOpa?8GC$IW;W}hk4#Ov zslDDzD^6;tHq@wfvji|{T&UXQVexSRhn&cJqx+JpXM8uBUpz-zo(4a520au>8UTz3m}z8bIM=AiKFP}yCn=4~vizglPh zznATCgp=a~UzoPINY5STcOm>*hWV@aci)}X63Jc}@VaGY(L0Nvb;iodGvuV0q`k@~ zc$Kf1@$N<7;+K4Pr>y?C~weUR*5xY25wrQI8D<^r+S?i{6z6(cK7rBLP+%UDgDURtx`V=7tyM}+P X`g79CRJ3M+>IMc+S3j3^P6R)D literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_shortcut_grade.png b/app/src/main/res/drawable-hdpi/ic_shortcut_grade.png new file mode 100644 index 0000000000000000000000000000000000000000..095a8228c4467a76872236c47ca5d286cb1d2b58 GIT binary patch literal 1812 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84mJh`hS0a0-5D6zZhN{ohE&A8opU=s#8u|_ z{>{5Nwk*Bkax1{&i>t$(yOuFJP7?$a40*-=Gahs~Ak?u>Lu!HI(@6~r^o2OK&xrWT zoN>`mU?yYpcUlATuHIX;9oOxVm_`nSCE+cw`R%w6q=16!Qr8$bJQTfBOWgNOLBWBWQ(gbbJ7 zUG-{B{ADSpIq%s&G_JB!{cUOHcH*Avu7CY0zxSkhsc87UbYpO5G+8-gN|Rk1!o9m8BXMHqk4BD>hkS}oK3s>^? zlw*^ajx4%p&eZaU^6ibW%)2&bT-=qS^|e;?;7OxOAs&`% z`fuKg>t8D@WL?3fx?G?o+p~yAV{!4LPz_6Ah1Q0S;JHsE0-7$(x7=`MV@_DvQEkCv zGPd2y4pa9`J-v^8xmttnf*!#es@4;^^0%KnH)9LSltTHs;4DSq+vQ5frxedDb53s2 z*-+%IlPf_U>!BAS2Ii zSH>>pOIy~5w(6v9+m__#&d#zTXxfz*8hP?oEx&DT-?b?&(O&fW{VY=>R+Xk$&vQ#_ z#5X&p<=*RACTq=eQgUaNsPgsoyQ>*y-`eUu-RaK(%YSyIr+#$)&-0ovp)$?UJlKKL z%l`2J^*pu>tE{t6Pcu6d{lT=q+G+F#|@xQvBnB8fA%DFTw ziq+EAM73)6_AcxCGjZMW-#QU?S}Gc!_vE&AHgF0}S@1=K{SNy~4#&&i-m>uo^28Q= zT9WL*bnZ?wJ8x`I&T?Vz%Q-(+Fu62bPCRz2xHXw+fyL5#kELmw8n!KK?q=$fcHqs; z&A7K$y7A@Z?pOUm%uEIXiEoxJYKSngvUlj%Fz2p#e?w9Eu7~&HdcJ)1o#8AwO~UEG zpBR68|E5P%_Axu?U3e=xp?$93RiV>+CiV&*+jn-~+!}{jWg>Ix-^A48x4x)TluZD{%zxb zS34@nRVMOb&po>uiSOs<&i=4SgxRTOW1-$ub`FCc$Ha`Tpv@H<6C0v_MxK{ZNaRWT zyY<+&vS|C$>?w~s?4%otoR$6w&6aqV5wTzHZ1p#VfZ*g^(P3Sa=55Kfi-_;v$XpwjZCrCYLVf5xqeBG0YW z4^NsVWqjFVg`ei%4&AfdF1(Ti}>)GO8zWs3;tLR$hv_+eqPgw1_ z!}-bKXC-Ax$GSvcb|h*FwJ%=$@9k z*hHAN2VgxZ5vraL86 z+rATr7{LBZjQ(YtikNe#7b)CO1==?FG$rgJ){AuHzu{S$BN^tt7f^}xCZ@+zL zV)S_QquYYnB>jKg72Wv016wj*O)V7LmE~Y`Jl^Qkt*?w)j~85-WqK@c>8}ML>jJb) zES~ZObe^oRYFd8lnql;&d%b@7?jMYTRPsLkXt!8fvZ|iv#=$<}6qy|#q;-9c;Mk$GJ9hVsq_|Mk-80@ixO(9n jd&=i&H4bJC|CmjbP0l+XkKoH@ITr z|7J7J%mqI)n0#9^ET;r)*gKm!fX~)3M8!@^z{x3#VPTNU5~d(-nF&=Zjx=8Is`2n} zXjKSta^i4d=+t_8h53lgqm8_(UmThPE>AF#Z#7Z5VSP2{&6UD8cTb+Py0M{nOZmO( z&$GX$Jv)0&r!m@xQ($_(C8PL+)^;Du1@}Wr>v$p-2?%vCZ*AH5opD9vn|Lwrmn{gN_O!Kaqq7uO0QybDN&XtL>5XF{bV|8jDu(GVn3ac-s=lcj5)p zhU@+>DH7sg8py_s^EYi6saK1s=EpfhjP37BW3yzeWt;gG{vN}wZUAlh3xsG!;xJ+gKm2TRl&ikS+_HNgXb@w$CEIieeb4mmze^W_x=rmLhYM5utI7$3Ncc15>hDEEY+8MoDYmN8I^Ze2j z&FU6dP&4n;+i%S;gboM=BnjR~xjw;W{q~z#hM8O%6YXqHEEe5#dC%^o799g`Zy!e2 zkgpMPPs041J*Su7@qf84$7>Ul(WavQ_Gh0`=c~ z+`{|kU&``!sA-lxU@GZ*_4fAUYkjf`aqD{|9`4c+JA8Sv`o-E`TMFjt@UQc%7c@B7 zyl7R`B*viGKHO1J57y4RAi3$->}&m{<&Pa}_fFwsn)4}emvZO{76-x5zs}#To>`P2 zuq2~o^@{(;co(O;%h|JCE?vo{qAl#|c=6882lJx#WljBPEG>C(uj-}ha@jgB`x9Ip zY)o6Z6lk&Zd3O(vGmRElH_9bt+(EnXcBgway>+R6Y=HY;JhK zniXvPw@^+b@alO+kNlE;<|zjbwzV5xx!1Q&+1=pAHM5^H+XbdvyPEiIo~_2pwXB+Y za_qMh`5zfc|C#d7S3m&~`# zt_WGPU3>$VwQJ+{O_x5*c(pdVH*(_9#}bvFSZveJJ=n|4-cwM|rtxrDAlmDo-`t0uA zWxZ9i*GVtDQTfC(u1Jqo!V)ok>gMG%;n7_C*(a{{Fqi^l0tVdq)nhO}lTG96LGc$F7x|H(ume zU9!GX*+ygQM4R&2TZ`3Cg{?EGliN`#?C(EE;MCfMi$D8T=%X)Afp(21sZUH4oIEz`-*);qZ<*<NPx(x#?9%oypRMGn1|!VPt(-e4_9BDo(}ar7wGQJ#4$@ zUgq7*^hMz_ukpRWchgpXowj;+=6s<`@3QCrPwd$H&9i0Z??(oV=W4&sVK7`7etwVN z5!*cp3yS;q7jTvJ?U#sqBDdhwJ4cxb)hy>#j!fD-zq;eHmg)1=uWj~SR8FWn<}PE+ zHs_J&+Mjis-9^OqGd@}TC3)g=-SeL6tvkX6SqgSdk7QBUd3_;^g6INu-(ON8Ld_o} zrkv~T_bgnnk|B?Qb+1G7i?7SSl-**RA~NN?H^ar1cXTqAFscR#eUI94^}>_7hyz^# zkLtf)7HL{=r++p_lUGmRyXS>2m8$2G^w|`(7@rw;^XnKoS=l)3J{NI=o8_(F^+n$- v?atl~jnVijGxHhu(v4+rN*E&pe)CJnPcMtC;BaSPU|{fc^>bP0l+XkKvNuDO literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_shortcut_timetable.png b/app/src/main/res/drawable-hdpi/ic_shortcut_timetable.png new file mode 100644 index 0000000000000000000000000000000000000000..2808559a54b2c9a5f5b3ce003753ac7dd5aae0c0 GIT binary patch literal 1625 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_shortcut_grade.png b/app/src/main/res/drawable-mdpi/ic_shortcut_grade.png new file mode 100644 index 0000000000000000000000000000000000000000..e35135071cbf8dd97a30c7fdc83d8d6964ff9bbc GIT binary patch literal 1034 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F4ZLo%H2&f4oQ;wW<9 z{%vb%K_(87g!4yt-`@E|h)ZanY1ZSw?DU1b(-w(L;BIu;aK(+=dhJ0sJ3YmKfC({0 zo6DDfVE0gM?1;Mic1Gll(){a|D z#&(J1!#oWP2j*%CZ$8MNq44f23sdypmtW>rsc+D0*t6=MK9h~pkrr`xiR5g?2L43f z-)~&!zph|9aXg8?dyxL)8vYtKQqlLif`Q!hBD=ZyL$CPx>d$>u`3emT6*m=1 zEHz0H*J6CIwYP7F+NMW;xS*zAnX`YGV zJizS`dU@H|nVT5;9(`PWy!BB2MUhXvRmJuDQ;w}>Eb;Mm{QpLWW!EmRGj+03Ouv10 zcQTkSF)r)PnDuZq>w=?6oGCe>YzIm##JeRQU1e}uDZ)}+{&J9hV>a9E*7M zpMfLNtzo7c(+NG@?Sc*sQ#qEp<)$&7cviQsB}Msy4gS@ z+x3;`e(}EkhZ%)}=gP{Lep%1noSPPZwbU|}(;@2$8)vBQ@}0FaxzDCDU)gh^fMce1 zYDV>KuiiNIY4eZBLTw{I6>hLP)ykb#H&BT`u)wzpj z1Pb4+m%X^PX#d~u|2Ju2jYAHM$fE7i^EN|<@AuwB6og+ITKq&Uvm zemB1QWz1=riapG0U;pw6mizgJ@5i^9S1r5u)xIce`mpa+f6_-Y1GAo{dQ%66u8wNf uSpS)SeP=!m^>wQfzHaPcTw2TjLHrtjw7+q%Mlk~e1B0ilpUXO@geCy77}r_= literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_shortcut_message.png b/app/src/main/res/drawable-mdpi/ic_shortcut_message.png new file mode 100644 index 0000000000000000000000000000000000000000..392c45d2482df45902ce93adb278865ef7278105 GIT binary patch literal 1048 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FH_O(8JX-m&o~>rZS!Z%`LivGeH~ZAtwO&i4VzuA#Pun9t#mhh5ZC?M zPA`3rT(H=I5~E5tt*h({cHZf%eY~k>#s1W+S9KA!3mNXXC>@mW)_f3gqf_VU@u^d$ z&n>aa)y$V?oc_6(<<7>?JyMpebIMzGWG_Cf#iaMVnI&dpV1%Y5E03kq7nYaYEGG)= z)--rKc3pd9$*5eYxXbIM9%lgW`QN>~T}QeYUhjO?yeRzD+z2s;bm^osyg_^Bou4}8 zT+z+U$Oe<={@!nvz0NGJ(_@-2GzN?u=iE1;erMk@hcXl0z!r7m%x!!G< z`pwx)@yI`?rS*(2Zn+8Bav5tMO-ek{of4`io@EofYVU@!U)%>u=d^EYy}8Y~eZ%_w z@*8EXog^QKpR4`VVqRPOT7;a&f~kO?7pVdbLqCC>!#bDG2ThpG#_FZ1MM70SYv#>3kfX(#>oUXpuz6W| za&@%y7o%Buxm)GVby!6$TXrVsKl6c~0*rUJMcFXu>Whng$g7a}oSfV+Wof8E+ppl| z8`s%&ZKlKrx}y>2{_!Wia%Y+P?hx7^Xi$xqpBFEl zvAb5fsPN*Q&9|aVVsALg50rfiCB(@|Z;=5XcV4{y%9_fuTrbL01Ai4}h}H7$*c|9W3@`Prh5U+leY z9beR!b{<-PuDHbhm8nbHXZ7qGjoZ!&*X^u%r(g3S-)x&n;*#j@xDKVecfKkp-HltH zrqXol)x6wBb{STIi?&Ipod0C)z8|yt+}3vv-kQ6wKbf%J;Je$m8CUmjcKNp8HvgjE ztK^Gz9u9b=!20KE1B0WB{`4htKKz>fH1F&(?oG1}N+;$#VXR})|NPw{f8zcs1_lNO MPgg&ebxsLQ00JlO`~Uy| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_shortcut_timetable.png b/app/src/main/res/drawable-mdpi/ic_shortcut_timetable.png new file mode 100644 index 0000000000000000000000000000000000000000..7d61306a41b585969825c6309b8b5e23680c3cea GIT binary patch literal 937 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F>zS{ z|M`zDjSJs~{A19X^h3urYboDUEm219mpszUItD=zUMgx)ZV?Fy%{x;UiiU0v%UbGT zsqXl;Z^o&x8A9?_;>-J9A1Ob#UTWgSy7xb8-`%}i{avqR%72Zg{}$^r+}U)@=Wv9G z(;3bN#vNA^6SlD&aNJ@(^JL9jt?BjOtr~0@ujszc6RvP@IjYjfp=f4wpnc8b8ox#Q zr9zBXa(~a$KElm#eR7?}lJXRRy=TI-=9j$9WVHBMbI+j1l=05BzY`YynO1OjdDzyd z&?({l4ToM$_0H9gpX8bMuei>}FkI_|1)> z|1l5mBU{G&;yLy&({^hg&~USRlM|z2#l%y5?zrpv+p{`YChX>wY!gnenDM^#byVQ) zU=@d{8_(+9G`W<2DrL{}MK|A^TB;>(=5!#f@3Xbw`P=e;eS_pn-Oa;SR%m^7TBzJo zVi&DfU1WOu+Fur)MZX`Wl7###)` z8Jf{6D}w*>G;9oIns%AN;XqVh@p`jtMwOetqpi=s(YcWEVgvKC&Nu(+F6owPpWhjN ziJh@!9(#KBf&0Jzs)(k$tL=^}cA8gw{`)>gkL0>ZUCa{>I9A?u)hYeYd?GO5Dh!GTL+gZSH>7X<_yX^A++h@+)rj#$ha7(qMfQwi1!5_1zg2zpGpFWl_Pc%4>F4R{x$56ZA4b z|Lk>%-$n=cN`jiM-IF)@kZ-n4C2>`BcU?!&-8)|ugYL%3r>Z=<^=e=KMsXR&jxTYB zTNV6nzgu5weSOvMWp5mIuiI@i!F%5V;gx&Sc>7bb^miRr*tEXtPR_j+fnt%*;mk}H yf^SV@%5T5VU*)$^!}6)?ozw1YD`!_V*vIMIb8w%&XbS@a1B0ilpUXO@geCyjim&7V literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_shortcut_attendance.png b/app/src/main/res/drawable-xhdpi/ic_shortcut_attendance.png new file mode 100644 index 0000000000000000000000000000000000000000..302b9e0ee885ba3c5885e709bea958844f0baaf2 GIT binary patch literal 1907 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^Tstvp>ELn`9l&h_mPaTPiK zf4zC5%Z?ut1^BBR^tErtZWdJO5-^!){IMbK14E3$9R}ftXC{0oyxLuGp}R`qj)y_u zq4a>0e!ltziIyHoPZW+FnB=kPv(MRY>o#w;y?oU)^zP=%SFf+D3jJFbx_)2WUbP>~ zLwEyLF8zJzA>))g95xL63%0W@Q&(r*9wpdu?BE``1KA02?2F8UiUrR${1j|xSEyom zRxQGEwsWOsDakbR^b-k16zh{9nE)=4X+dS^=#be{qV|_{Ao}4 zbe5GcTWUYE2G z_o~$Mw~Nl?W-oB>aMpdG(J(!ywnf#lpYe*b=J|+8%T<>dFcgZsWxpu?wy|W#{C3@E z!i#SHS=Etc#crT`g#Ap7jLUnmkB-+)CG7KbIj*+k&&^q9L>&DXk2uX?D>(6#T}0ux zkH*u)@TV4x2C=JilhUrX-Y*ON*!1+C+M>V0y~oyXJH3@pp>NS%g1hMP8NubI~}cC-epty{mgi+AUo%?qde&be}tt0AJ} zJwr{>Vkd2nW8W7}na>w>zmYK{MdC2R!^uOQ+tOd#<2smbAmB6TgmbnYVaOf5*L(yCY8XDu_ABruCfSx?Wbj zL)L4jVgH2~2Dg-a_5M1aOV4guUt+s(?zetEdLb!`E*4yU)bqsedY0SIEk>*dm&M6d z*fQQ(dDU;*jQ$MKgb6Ex7&`n~dyhTO%zAZ~Icw{0y;{@VjCXGD5?%ZJJa53W^FnK) zT0gE1pPo{3i@781klSP5T!wXL`&W6GH(1X$Z~p(+e7_lQ(Tc|SUdOrp!3?Vw$fap) zWj_*FBI0tKcb~7d_frM~dG6U~tF|{?V&o{~Jm7xomWjs<)&h(7LlM6JofF?A+HVFa!u( z*|pwV*Vu8Rz;4Ex#r)TFQbidVe&|g3blb02mpx$h)q`vP{FrMumBpb%DaT}5#iS)) z8=Uss*~FGO{foC0^A&a7;wN6r1-3gEz6fH!8qIzt`?H(I(@DO|O@yD6u7RH#YX*Y_=leO?tWFLkSi!G%Y>u@#CT=q6Yr|%3Fa39SI>Y;A95);b ztH?0^s`>PP;QGh&yT#A4q&zp;zi5iXhv{E7O}(RiG-3LeDIxW~S7UxN@TIppo!hf) z))%JwKx=z;Yw@kO8J<11`yIe)sjy`R|BEB@uf1aAWRYLvEZ*=oLH6X7EA6WRri!~`F@>}#1TYTlwl zVS2L`X}Ne^Z#8sqDSexn5fxkW;?cISQ=GAP3^l}ymiufs6q~c|&V#$6?FJh@P5sAa zECM;Z5QlL`qzH$vy>+9fkzIumOBj-?p@XTG5s0C zxy7gUoA}?o6Z~#Maj~_-7TM4Ht+tD9_d9xEH{-L@64JXvzSTdOySC-?t^I4hoGe|* z;qo{k?*6}a#*4e=F{aK;clg3_z*)eS;j=AQQ(F0)ZEK3UYvOltYJEy>->AdCAVo{A ifjwXoo0r}{dkLo>eU zBo(n=2(tQ|#~|Nmxg#}wUD|YpMVj0@?x_5-%a_>6SkQXI`#>DqwpG{ig(_L@q&#TS zecGyWf2CKp%z;?NK9k1B3~_;>oUTRl7$mkXwOQ;Dr(<}GVMkvvgG>AtwoCW^`I^u4 z?{s^dEqwF}UqVm^|BRn19rsKF6;mq>?kg=4b`JWt#3!vmVJ$<9;y#uFmvmO16L!ho zl_BAFQ4BuUvXsxfDSf!TRP@eTPN6?Ze{1cW-KGQ=qE3ES@{kMw#{+<*Vl2+b612n&jHax)@L+MafO#w?@0FE zso8nKg@J3+_Q@{xnU~aVS$FX+*t(kY&x~a*slVGA_#eMpbd2qR)wvy=x~Wmy)-;RT zS5NDlpH;b$>u}BKJd-`fZ%@SQFkC9+i*Si|^$MPlup;jLgrf4#X-irkXx2Y|dt3IC zTDB?c(jLX8p9^Fk2dIlNgm>Kcotq-c#$b@^{WD5rl?TH=$#vx$lAeSsFl=a8EUkQQ zhBD(0r$33G81{NFFxYHdT2s1l+HMVo^Q9~emzX=g9s0u0lkoQ8;fS57+-shm?)|di zr_U^7;~%e&@!Hr_i~YB$Sz-LXwtMFu9j=6+4(VNg%6?s6d-%ap?~2T?S#ziMPx<@) z@$nhAHoHr+oPVF;aq9bFE+MW3Pd8r6(XwZrtAFCa4T-pWJB@=J)r9_3KIK~0FME0V z)YRUV$_K4XJEB+5%`>WBwmKxgw_n=aI0{+EbvH+VXbn?O9lq}8$s{7xD(hKu60&&GM>2+w62HcK|J@XJA&TH$x8b) z6&WU^Ufs3cTi3vGoj^51%#{V7`6k|Fc$a&-?b+w&yEf;Z-2UtL#)rSY_U+knuIbCY!BsdAXROWPVC3r+;z8fzhQ#Yfoa9fb zm->EToa6R%&g_&Ne&1}t-dvwIb5`Hv*<1HcCM@^b|ARP+T~_w?*rPuIw^>-^o7{ z=KQ$4v8sXppvQ*3FQM-i>W8ww{;+&W=#E)4dbYN#{&>7eiRE$M%41hfeqqU(rSB)Y zDJRgN%6ZyWpNlamU$ipf8Q7H_fB#|JxkK>MzUB2G9d||<+ zkcHjRQ76?)3U4pSdEys&=U9eC?7oA$z4;V3f3p3XYUKEK?b?)Q8k28kUY~8m@bArv zAA(nnUA*{>`n?!M>bhnXt=f5G#}XNb+evGyj%gk1ao}#)c5o+0wR`8cvZNP#lsm&1 z^veQQFXwUInZa%_f3tjjm8Z=!&S$}ekL=WQ-@36qT;a6SsUqL|+mqsLVg^#8Sr)76 zJpY?tW8TFbX8Xcs`NTU6dn8u0x0^?v**&{$z6pDQWNO_dn}Xu=#qD$E-ep}RJEQtl zOz0geeYSfRGuAI$|32&9`xDvGoa$Ta17H4q9R#kGHhgVkyg2JZ!=^LA3RNr#QZD=l zYWj6nUzA<0s}(=_|MR>ipRjG>pI0$F@mb0gz<45(*)sjVJe%tNKJ)t<-!m{UFnGH9 KxvXO5T>Ln`9l&OM!f#ZBh; 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 Nc)I$ztaD0e0syj8YmWc` literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_shortcut_timetable.png b/app/src/main/res/drawable-xhdpi/ic_shortcut_timetable.png new file mode 100644 index 0000000000000000000000000000000000000000..9a40fe61c794ef5e83f61d43a7e653221e844e7b GIT binary patch literal 1971 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^Tst2|vCLn`9l&OP5R;wo}{ z|N84Xoc2iFlp|rxCe)d3iJh(Ixng+-mP4gUVVM$&3SKMy<7F_-n)6PL-tmEwF_New_k0_ z{t#VQWxjLpVDF51_gELnGTdX|;4|^zJmwv&&$3^<+?mzi`*)c~ zUXtNT<_xL1mF5lo2W9ST5)R+&%y6-VH6~Bs?*y}+D-1jOHcxNZ%aaqBdtc)d$Bv^1 zSfe|*13#_w%9c4`d))F8LmzX6Z>Xxs$x60_8)A=olq!RgdKe3|r!p)2+GIH)?YH^O z1iPnKUf-V)5NzF0c>L#tnf^^LY=uRG!q`6NDp?sS965g~g^lA9*MZVG>ltJ&Mlv#Q zI)B4S=4xo47{lYMuLO*%V}HoTc1cgGp5DR7b0us4D!p(^hV4N&*%#%9YR}@VJoEc) z)!#i{u~V1|R$rZ*@GZ^a=U+qq+h2cihKh!;9VnGqfAxLv(uiYE=WK7ivEIpDl_BQ% zPrd`{S|U*{M*Ft6{xDg&uai;a%8$)u{yd6;4NW`e=Jnc6wC>_Pur_4R(a?SDF_HhB zOmePgZDe~E!BAv-b&6?K`mPzlS57eealNKr`1MS&ol=$gt0Y|`hUBStqEDGw?)`4$?)pM8ZRnBBM8|(XExrLOdEPWE5@RoVy!B`;sygXPvawj8$&n>4tf^AwN4fSoWW!Fgje9FO~^Wa6> z1mkA`4C@~MN&LiM>(9Vov$?gRcHy+$3JmXGaWE`p7g&4h%eSwIUmqTh*jH)1W~q1Y zmkl?aq=JKgyng0uV^=Nq-==QO<~Oz6v6Ybm2X;KZbEPzYdHGqXFY&ut!o${GiToLG z^S@nfSEp_D7RL|oWO+G0I-0xgV#>G|k!><%e&acyT9 z33iFsUmu>kjf?GpML1)ItRgo%!;gz%Nz-*2G#R4QpRuwSq;hYx5o!3Zv!d2rr>~#$ zWUvE+!s%6IcGG7)Z;Cm7llj3Sw%OY|->`g0cpYXEx9>`9PVl~~x4TQt^R`S~S}OLX z-gEvWRJz1H(3fTr+*fA8U_Z&{@Iq;HI^y_?C#Oh8}M3Ny}IS zHb~EU^2;+sLbXBYK+No!_8j3_{JYzlJ8xYP^N`=h7Z7p9CUE7~hKA;uK6*!NnAh&F zvlVOpeS2H$y(Qkf4Og7bTxhnAea$d)qlznoP_&@rjUMk!Lg!2vPM+NnvTd>TcCMmV zO^3EGzHBvNV&=|`Y^@DGnL8C$GE4f$UoZR@Cb3@kLLTcJR@?2ZGsKzojoUx5zF-vO zdm6lB+N5fRiR+eT>=S?WbIGBd3pB(x&wAYOaCPTSyD9xurWe@@q@F&FQ5Dwj&PZ{7 za(d^iyBB6ZKbLs)+gmTK86h5O>z7wgz4X%|`Q)vwFZNdm+G>ZXY>i*^XJ+k!hwIt5 z*ad!4SYubhak{OoXTNBKi2sxt4mbIis#)i5o}Tk&;=FMA%jZKjryq8alI7)YmHFj! z^*!q`xh(ZndE1OuSFX6rVj%qerpJn=oSO#w%y^$Q8+}~9w5oyspvQ*3AED<0{H`9f z`lFdCxz26U#%Tqn{~{)|C)}Bo)-%_~|G=`y(o+*sxtlIZZ(8%RD@|$fbjROJ780Dd zp7Wph**ih*`sW#3(U#AW!mk96Lks4t3X_?P9Ln*)M zc^}?2IeX;PoUiMQ3CPaYo?-3vq%7*~GM)x|>r?eEUs)zzYQD2Lh+*gaMaSl3>6z$h zvR~K~p>3b6YN&jHX+dhixx@DYm+Y10oV{K3B3DA5_|`vD62tXwF`k+B=J@%S$H51!2{mo2KQ67MKWcozJ8)uU^bh9BGx*6`ZehF|{Iw`beb zf{_2>)9%&lg)&~WGWc%3Kha^!s%(eIXPg4Ij0T*G+!N{?riH%mxhxj8?&SaAaz{1o s*+(~dF=z&BGEQL#+U9WT=zn%|sf&HlPZ<&!7#J8lUHx3vIVCg!00GvCg#Z8m literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_shortcut_attendance.png b/app/src/main/res/drawable-xxhdpi/ic_shortcut_attendance.png new file mode 100644 index 0000000000000000000000000000000000000000..9b4ef2daf0472bcce13162e5aae899b279f46345 GIT binary patch literal 3393 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 TU!lyvz`)??>gTe~DWM4fb~kd8 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_attendance.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_attendance.png new file mode 100644 index 0000000000000000000000000000000000000000..7b9a68a708fc52785e7896b46ca261115317cc5b GIT binary patch literal 4892 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 YUYluI^;A%Rfq{X+)78&qol`;+07ldkTmS$7 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_exam.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_exam.png new file mode 100644 index 0000000000000000000000000000000000000000..519c50abcbfa93d9f6ade9896a366d86e3a96997 GIT binary patch literal 5027 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_grade.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_grade.png new file mode 100644 index 0000000000000000000000000000000000000000..13c793d5eab438cebce711486cec63316f13b9bd GIT binary patch literal 5529 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_message.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_message.png new file mode 100644 index 0000000000000000000000000000000000000000..eaffa2dde91cb1975be6c8dfc982e1870a29b5f9 GIT binary patch literal 5994 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_timetable.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_timetable.png new file mode 100644 index 0000000000000000000000000000000000000000..03522e9a59f85db3e8a42e43eb2b10283eaeee0e GIT binary patch literal 5087 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 b{~64W3t1Yxp5V;Dz`)??>gTe~DWM4fTA*>r literal 0 HcmV?d00001 From e08abc1fc25fcd47f50566ad0762cd1b64150d1f Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Fri, 25 Sep 2020 15:45:07 +0200 Subject: [PATCH 037/150] Show subjects without grades in "Grades" (#947) --- .../data/repositories/preferences/PreferencesRepository.kt | 3 +++ .../ui/modules/grade/details/GradeDetailsPresenter.kt | 2 +- app/src/main/res/values-pl/strings.xml | 1 + app/src/main/res/values/preferences_defaults.xml | 1 + app/src/main/res/values/preferences_keys.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/scheme_preferences.xml | 6 ++++++ 7 files changed, 14 insertions(+), 1 deletion(-) 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 1d5e57f8..a6c83fc9 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 @@ -80,6 +80,9 @@ class PreferencesRepository @Inject constructor( val showTimetableTimers: Boolean get() = getBoolean(R.string.pref_key_timetable_show_timers, R.bool.pref_default_timetable_show_timers) + val showSubjectsWithoutGrades: Boolean + get() = getBoolean(R.string.pref_key_subjects_without_grades, R.bool.pref_default_subjects_without_grades) + private fun getString(id: Int, default: Int) = getString(context.getString(id), default) private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default) 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 a3651793..3dfa0206 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 @@ -186,7 +186,7 @@ class GradeDetailsPresenter @Inject constructor( private fun createGradeItems(items: List): List { return items - .filter { it.grades.isNotEmpty() } + .let { if (!preferencesRepository.showSubjectsWithoutGrades) it.filter { it.grades.isNotEmpty() } else it.filter { true }} .sortedBy { it.subject } .map { (subject, average, points, _, grades) -> val subItems = grades diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index bc94b227..48629058 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -359,6 +359,7 @@ Oznaczaj bieżącą lekcję na planie Pokazuj listę wykresów w ocenach klasy Pokazuj lekcje całej klasy + Pokazuj przedmioty bez ocen w Oceny Schemat kolorów ocen Język aplikacji Powiadomienia diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml index a82b14eb..5c6eb7d6 100644 --- a/app/src/main/res/values/preferences_defaults.xml +++ b/app/src/main/res/values/preferences_defaults.xml @@ -20,4 +20,5 @@ true no false + false diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml index 6cb877ec..1a0311b3 100644 --- a/app/src/main/res/values/preferences_keys.xml +++ b/app/src/main/res/values/preferences_keys.xml @@ -22,4 +22,5 @@ fill_message_content show_whole_class_plan timetable_show_timers + subjects_without_grades diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7df2b68a..d461299d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -385,6 +385,7 @@ Mark current lesson in timetable Show chart list in class grades Show whole class lessons + Show subjects without grades in Grades Grades color scheme App language diff --git a/app/src/main/res/xml/scheme_preferences.xml b/app/src/main/res/xml/scheme_preferences.xml index 4cdb989c..bbb2aaeb 100644 --- a/app/src/main/res/xml/scheme_preferences.xml +++ b/app/src/main/res/xml/scheme_preferences.xml @@ -40,6 +40,12 @@ app:key="@string/pref_key_grade_statistics_list" app:singleLineTitle="false" app:title="@string/pref_view_grade_statistics_list" /> + Date: Fri, 25 Sep 2020 15:46:08 +0200 Subject: [PATCH 038/150] Different notification for notes and praises (#952) --- .../wulkanowy/services/sync/works/NoteWork.kt | 27 +++++++++++-- app/src/main/res/values-pl/strings.xml | 38 +++++++++++++++++++ app/src/main/res/values/strings.xml | 28 ++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt index 84b80679..b0889696 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt @@ -14,6 +14,9 @@ import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.repositories.note.NoteRepository import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory +import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory.NEUTRAL +import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory.POSITIVE import io.github.wulkanowy.services.sync.channels.NewNotesChannel import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView @@ -41,8 +44,20 @@ class NoteWork @Inject constructor( private fun notify(notes: List) { notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewNotesChannel.CHANNEL_ID) - .setContentTitle(context.resources.getQuantityString(R.plurals.note_new_items, notes.size, notes.size)) - .setContentText(context.resources.getQuantityString(R.plurals.note_notify_new_items, notes.size, notes.size)) + .setContentTitle( + when (NoteCategory.getByValue(notes.first().categoryType)) { + POSITIVE -> context.resources.getQuantityString(R.plurals.praise_new_items, notes.size, notes.size) + NEUTRAL -> context.resources.getQuantityString(R.plurals.neutral_note_new_items, notes.size, notes.size) + else -> context.resources.getQuantityString(R.plurals.note_new_items, notes.size, notes.size) + } + ) + .setContentText( + when (NoteCategory.getByValue(notes.first().categoryType)) { + POSITIVE -> context.resources.getQuantityString(R.plurals.praise_notify_new_items, notes.size, notes.size) + NEUTRAL -> context.resources.getQuantityString(R.plurals.neutral_note_notify_new_items, notes.size, notes.size) + else -> context.resources.getQuantityString(R.plurals.note_notify_new_items, notes.size, notes.size) + } + ) .setSmallIcon(R.drawable.ic_stat_note) .setAutoCancel(true) .setDefaults(DEFAULT_ALL) @@ -52,7 +67,13 @@ class NoteWork @Inject constructor( PendingIntent.getActivity(context, MainView.Section.NOTE.id, MainActivity.getStartIntent(context, MainView.Section.NOTE, true), FLAG_UPDATE_CURRENT)) .setStyle(NotificationCompat.InboxStyle().run { - setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size)) + setSummaryText( + when (NoteCategory.getByValue(notes.first().categoryType)) { + POSITIVE -> context.resources.getQuantityString(R.plurals.praise_number_item, notes.size, notes.size) + NEUTRAL -> context.resources.getQuantityString(R.plurals.neutral_note_number_item, notes.size, notes.size) + else -> context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size) + } + ) notes.forEach { addLine("${it.teacher}: ${it.category}") } this }) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 48629058..28204419 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -252,6 +252,44 @@ Masz %1$d nowych uwag Masz %1$d nowych uwag + + + %d pochwała + %d pochwały + %d pochwał + %d pochwał + + + Nowa pochwała + Nowe pochwały + Nowe pochwały + Nowe pochwały + + + Masz %1$d nową pochwałę + Masz %1$d nowe pochwały + Masz %1$d nowych pochwał + Masz %1$d nowych pochwał + + + + %d neutralna uwaga + %d neutralne uwagi + %d neutralnych uwag + %d neutralnych uwag + + + Nowa neutralna uwaga + Nowe neutralne uwagi + Nowe neutralne uwagi + Nowe neutralne uwagi + + + Masz %1$d nową neutralną uwagę + Masz %1$d nowe neutralne uwagi + Masz %1$d nowych neutralnych uwag + Masz %1$d nowych neutralnych uwag + Brak zadań domowych Wykonane diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d461299d..b917ad5d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -249,6 +249,34 @@ You received %1$d notes + + + %d praise + %d praises + + + New praise + New praises + + + You received %1$d praise + You received %1$d praises + + + + + %d neutral note + %d neutral notes + + + New neutral note + New neutral notes + + + You received %1$d neutral note + You received %1$d neutral notes + + No info about homework From c6a99f10002ea8e030940da5d2249d2105f9db77 Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Sun, 27 Sep 2020 14:49:19 +0200 Subject: [PATCH 039/150] Add remembering the full screen mode in homework (#956) Co-authored-by: Faierbel --- .../preferences/PreferencesRepository.kt | 4 ++++ .../homework/details/HomeworkDetailsAdapter.kt | 4 ++++ .../homework/details/HomeworkDetailsDialog.kt | 17 +++++++++++++++-- .../details/HomeworkDetailsPresenter.kt | 10 +++++++++- .../main/res/values/preferences_defaults.xml | 1 + app/src/main/res/values/preferences_keys.xml | 1 + 6 files changed, 34 insertions(+), 3 deletions(-) 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 a6c83fc9..c76bcf1e 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 @@ -80,6 +80,10 @@ class PreferencesRepository @Inject constructor( val showTimetableTimers: Boolean get() = getBoolean(R.string.pref_key_timetable_show_timers, R.bool.pref_default_timetable_show_timers) + var isHomeworkFullscreen: Boolean + get() = getBoolean(R.string.pref_key_homework_fullscreen, R.bool.pref_default_homework_fullscreen) + set(value) = sharedPref.edit().putBoolean("homework_fullscreen", value).apply() + val showSubjectsWithoutGrades: Boolean get() = getBoolean(R.string.pref_key_subjects_without_grades, R.bool.pref_default_subjects_without_grades) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt index 5d6ee162..cd9a7e85 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt @@ -29,6 +29,8 @@ class HomeworkDetailsAdapter @Inject constructor() : attachments = value?.attachments.orEmpty() } + var isHomeworkFullscreen = false + var onAttachmentClickListener: (url: String) -> Unit = {} var onFullScreenClickListener = {} @@ -67,6 +69,8 @@ class HomeworkDetailsAdapter @Inject constructor() : homeworkDialogSubject.text = homework?.subject homeworkDialogTeacher.text = homework?.teacher homeworkDialogContent.text = homework?.content + homeworkDialogFullScreen.visibility = if (isHomeworkFullscreen) GONE else VISIBLE + homeworkDialogFullScreenExit.visibility = if (isHomeworkFullscreen) VISIBLE else GONE homeworkDialogFullScreen.setOnClickListener { homeworkDialogFullScreen.visibility = GONE homeworkDialogFullScreenExit.visibility = VISIBLE diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt index 78abfffd..aecaa394 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt @@ -62,12 +62,25 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew homeworkDialogClose.setOnClickListener { dismiss() } } + if (presenter.isHomeworkFullscreen) { + dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT) + } else { + dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT) + } + with(binding.homeworkDialogRecycler) { layoutManager = LinearLayoutManager(context) adapter = detailsAdapter.apply { onAttachmentClickListener = { context.openInternetBrowser(it, ::showMessage) } - onFullScreenClickListener = { dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT) } - onFullScreenExitClickListener = { dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT) } + onFullScreenClickListener = { + dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT) + presenter.isHomeworkFullscreen = true + } + onFullScreenExitClickListener = { + dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT) + presenter.isHomeworkFullscreen = false + } + isHomeworkFullscreen = presenter.isHomeworkFullscreen homework = this@HomeworkDetailsDialog.homework } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt index a53d38e8..e485dd74 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt @@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.modules.homework.details import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.data.repositories.homework.HomeworkRepository +import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler @@ -16,9 +17,16 @@ class HomeworkDetailsPresenter @Inject constructor( errorHandler: ErrorHandler, studentRepository: StudentRepository, private val homeworkRepository: HomeworkRepository, - private val analytics: FirebaseAnalyticsHelper + private val analytics: FirebaseAnalyticsHelper, + private val preferencesRepository: PreferencesRepository ) : BasePresenter(errorHandler, studentRepository) { + var isHomeworkFullscreen + get() = preferencesRepository.isHomeworkFullscreen + set(value) { + preferencesRepository.isHomeworkFullscreen = value + } + override fun onAttachView(view: HomeworkDetailsView) { super.onAttachView(view) view.initView() diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml index 5c6eb7d6..bb987271 100644 --- a/app/src/main/res/values/preferences_defaults.xml +++ b/app/src/main/res/values/preferences_defaults.xml @@ -20,5 +20,6 @@ true no false + false false diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml index 1a0311b3..d948dc47 100644 --- a/app/src/main/res/values/preferences_keys.xml +++ b/app/src/main/res/values/preferences_keys.xml @@ -22,5 +22,6 @@ fill_message_content show_whole_class_plan timetable_show_timers + homework_fullscreen subjects_without_grades From d32ebd66de8b0969410437ecf637193c61d4e98c Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Sun, 27 Sep 2020 16:28:39 +0200 Subject: [PATCH 040/150] Add subjects sorting in grades (#946) --- .../preferences/PreferencesRepository.kt | 4 ++++ .../ui/modules/grade/GradeSortingMode.kt | 10 ++++++++++ .../grade/details/GradeDetailsPresenter.kt | 17 +++++++++++++++-- .../main/res/values-pl/preferences_values.xml | 4 ++++ app/src/main/res/values-pl/strings.xml | 1 + .../main/res/values/preferences_defaults.xml | 1 + app/src/main/res/values/preferences_keys.xml | 1 + app/src/main/res/values/preferences_values.xml | 9 +++++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/scheme_preferences.xml | 8 ++++++++ 10 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSortingMode.kt 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 c76bcf1e..fa12622c 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 @@ -5,6 +5,7 @@ import android.content.SharedPreferences import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R import io.github.wulkanowy.ui.modules.grade.GradeAverageMode +import io.github.wulkanowy.ui.modules.grade.GradeSortingMode import javax.inject.Inject import javax.inject.Singleton @@ -77,6 +78,9 @@ class PreferencesRepository @Inject constructor( val showWholeClassPlan: String get() = getString(R.string.pref_key_timetable_show_whole_class, R.string.pref_default_timetable_show_whole_class) + val gradeSortingMode: GradeSortingMode + get() = GradeSortingMode.getByValue(getString(R.string.pref_key_grade_sorting_mode, R.string.pref_default_grade_sorting_mode)) + val showTimetableTimers: Boolean get() = getBoolean(R.string.pref_key_timetable_show_timers, R.bool.pref_default_timetable_show_timers) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSortingMode.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSortingMode.kt new file mode 100644 index 00000000..1e6b26e8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSortingMode.kt @@ -0,0 +1,10 @@ +package io.github.wulkanowy.ui.modules.grade + +enum class GradeSortingMode(val value: String) { + ALPHABETIC("alphabetic"), + DATE("date"); + + companion object { + fun getByValue(value: String) = values().firstOrNull { it.value == value } ?: ALPHABETIC + } +} \ No newline at end of file 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 3dfa0206..97b7b71c 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,5 +1,6 @@ package io.github.wulkanowy.ui.modules.grade.details +import android.annotation.SuppressLint import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.repositories.grade.GradeRepository @@ -10,6 +11,8 @@ import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage +import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.ALPHABETIC +import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.DATE import io.github.wulkanowy.utils.FirebaseAnalyticsHelper import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.flowWithResource @@ -184,10 +187,20 @@ class GradeDetailsPresenter @Inject constructor( } } + @SuppressLint("DefaultLocale") private fun createGradeItems(items: List): List { return items - .let { if (!preferencesRepository.showSubjectsWithoutGrades) it.filter { it.grades.isNotEmpty() } else it.filter { true }} - .sortedBy { it.subject } + .let { gradesWithAverages -> + if (!preferencesRepository.showSubjectsWithoutGrades) { + gradesWithAverages.filter { it.grades.isNotEmpty() } + } else gradesWithAverages + } + .let { + when (preferencesRepository.gradeSortingMode) { + DATE -> it.sortedByDescending { gradeDetailsWithAverage -> gradeDetailsWithAverage.grades.firstOrNull()?.date } + ALPHABETIC -> it.sortedBy { gradeDetailsWithAverage -> gradeDetailsWithAverage.subject.toLowerCase() } + } + } .map { (subject, average, points, _, grades) -> val subItems = grades .sortedByDescending { it.date } diff --git a/app/src/main/res/values-pl/preferences_values.xml b/app/src/main/res/values-pl/preferences_values.xml index 1d81fb58..c57d2be5 100644 --- a/app/src/main/res/values-pl/preferences_values.xml +++ b/app/src/main/res/values-pl/preferences_values.xml @@ -29,6 +29,10 @@ 0,5 0,75 + + Alfabetycznie + Według daty + Dzienniczek+ Wulkanowy diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 28204419..33017452 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -399,6 +399,7 @@ Pokazuj lekcje całej klasy Pokazuj przedmioty bez ocen w Oceny Schemat kolorów ocen + Sortowanie przedmiotów w "Oceny" Język aplikacji Powiadomienia Pokazuj powiadomienia diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml index bb987271..d42cfc32 100644 --- a/app/src/main/res/values/preferences_defaults.xml +++ b/app/src/main/res/values/preferences_defaults.xml @@ -19,6 +19,7 @@ 0.33 true no + alphabetic false false false diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml index d948dc47..e9f9054e 100644 --- a/app/src/main/res/values/preferences_keys.xml +++ b/app/src/main/res/values/preferences_keys.xml @@ -20,6 +20,7 @@ grade_modifier_plus grade_modifier_minus fill_message_content + grade_sorting_mode show_whole_class_plan timetable_show_timers homework_fullscreen diff --git a/app/src/main/res/values/preferences_values.xml b/app/src/main/res/values/preferences_values.xml index 5824658c..06a9d8c4 100644 --- a/app/src/main/res/values/preferences_values.xml +++ b/app/src/main/res/values/preferences_values.xml @@ -75,6 +75,15 @@ 0.75 + + Alphabetic + By date + + + alphabetic + date + + Dzienniczek+ Wulkanowy diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b917ad5d..073e7738 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -415,6 +415,7 @@ Show whole class lessons Show subjects without grades in Grades Grades color scheme + Subjects sorting in "Grades" App language Notifications diff --git a/app/src/main/res/xml/scheme_preferences.xml b/app/src/main/res/xml/scheme_preferences.xml index bbb2aaeb..99cb3366 100644 --- a/app/src/main/res/xml/scheme_preferences.xml +++ b/app/src/main/res/xml/scheme_preferences.xml @@ -62,6 +62,14 @@ app:key="@string/pref_key_grade_color_scheme" app:title="@string/pref_view_grade_color_scheme" app:useSimpleSummaryProvider="true" /> + Date: Sun, 27 Sep 2020 16:33:36 +0200 Subject: [PATCH 041/150] Show groups next to subjects in timetable (#953) --- .../preferences/PreferencesRepository.kt | 3 +++ .../ui/modules/timetable/TimetableAdapter.kt | 5 ++++ .../ui/modules/timetable/TimetableFragment.kt | 3 ++- .../modules/timetable/TimetablePresenter.kt | 1 + .../ui/modules/timetable/TimetableView.kt | 2 +- app/src/main/res/layout/item_timetable.xml | 23 +++++++++++++++---- app/src/main/res/values-pl/strings.xml | 1 + .../main/res/values/preferences_defaults.xml | 1 + app/src/main/res/values/preferences_keys.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/scheme_preferences.xml | 6 +++++ 11 files changed, 41 insertions(+), 6 deletions(-) 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 fa12622c..da31751a 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 @@ -75,6 +75,9 @@ class PreferencesRepository @Inject constructor( val fillMessageContent: Boolean get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content) + val showGroupsInPlan: Boolean + get() = getBoolean(R.string.pref_key_timetable_show_groups, R.bool.pref_default_timetable_show_groups) + val showWholeClassPlan: String get() = getString(R.string.pref_key_timetable_show_whole_class, R.string.pref_default_timetable_show_whole_class) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt index 58be38ce..f049f828 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt @@ -41,6 +41,8 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter() @@ -99,6 +101,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter(R.layout.fragme else false } - override fun updateData(data: List, showWholeClassPlanType: String, showTimetableTimers: Boolean) { + override fun updateData(data: List, showWholeClassPlanType: String, showGroupsInPlanType: Boolean, showTimetableTimers: Boolean) { with(timetableAdapter) { items = data.toMutableList() showTimers = showTimetableTimers showWholeClassPlan = showWholeClassPlanType + showGroupsInPlan = showGroupsInPlanType notifyDataSetChanged() } } 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 8581b73c..f924650a 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 @@ -143,6 +143,7 @@ class TimetablePresenter @Inject constructor( view?.apply { updateData( showWholeClassPlanType = prefRepository.showWholeClassPlan, + showGroupsInPlanType = prefRepository.showGroupsInPlan, showTimetableTimers = prefRepository.showTimetableTimers, data = it.data!! .filter { item -> if (prefRepository.showWholeClassPlan == "no") item.isStudentPlan else true } 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 fe34f1ee..24412017 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 @@ -12,7 +12,7 @@ interface TimetableView : BaseView { fun initView() - fun updateData(data: List, showWholeClassPlanType: String, showTimetableTimers: Boolean) + fun updateData(data: List, showWholeClassPlanType: String, showGroupsInPlanType: Boolean, showTimetableTimers: Boolean) fun updateNavigationDay(date: String) diff --git a/app/src/main/res/layout/item_timetable.xml b/app/src/main/res/layout/item_timetable.xml index 4e278261..ccef6e72 100644 --- a/app/src/main/res/layout/item_timetable.xml +++ b/app/src/main/res/layout/item_timetable.xml @@ -74,7 +74,22 @@ app:layout_constraintBottom_toBottomOf="@+id/timetableItemNumber" app:layout_constraintStart_toEndOf="@+id/timetableItemTimeStart" tools:text="22" - tools:visibility="gone" /> + tools:visibility="visible" /> + + + tools:visibility="visible" /> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 33017452..0923951a 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -395,6 +395,7 @@ Motyw aplikacji Rozwiń oceny Oznaczaj bieżącą lekcję na planie + Pokazuj grupę obok przedmiotu na planie Pokazuj listę wykresów w ocenach klasy Pokazuj lekcje całej klasy Pokazuj przedmioty bez ocen w Oceny diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml index d42cfc32..fb82e0ed 100644 --- a/app/src/main/res/values/preferences_defaults.xml +++ b/app/src/main/res/values/preferences_defaults.xml @@ -18,6 +18,7 @@ 0.33 0.33 true + false no alphabetic false diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml index e9f9054e..0cfa485e 100644 --- a/app/src/main/res/values/preferences_keys.xml +++ b/app/src/main/res/values/preferences_keys.xml @@ -22,6 +22,7 @@ fill_message_content grade_sorting_mode show_whole_class_plan + show_groups_in_plan timetable_show_timers homework_fullscreen subjects_without_grades diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 073e7738..bf4727be 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -411,6 +411,7 @@ Application theme Expand grades Mark current lesson in timetable + Show groups next to subjects in timetable Show chart list in class grades Show whole class lessons Show subjects without grades in Grades diff --git a/app/src/main/res/xml/scheme_preferences.xml b/app/src/main/res/xml/scheme_preferences.xml index 99cb3366..3f24c787 100644 --- a/app/src/main/res/xml/scheme_preferences.xml +++ b/app/src/main/res/xml/scheme_preferences.xml @@ -40,6 +40,12 @@ app:key="@string/pref_key_grade_statistics_list" app:singleLineTitle="false" app:title="@string/pref_view_grade_statistics_list" /> + Date: Sun, 27 Sep 2020 20:59:27 +0200 Subject: [PATCH 042/150] Migrate from gson to moshi (#969) --- app/build.gradle | 7 +++-- .../io/github/wulkanowy/data/db/Converters.kt | 30 ++++++++++++------- .../wulkanowy/data/pojos/Contributor.kt | 8 ++++- .../appcreator/AppCreatorRepository.kt | 11 +++---- .../main/res/layout/fragment_contributor.xml | 10 ++++--- app/src/main/res/layout/item_contributor.xml | 3 +- 6 files changed, 46 insertions(+), 23 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 11a82fbd..c0a4e9f3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,6 +119,7 @@ ext { room = "2.2.5" chucker = "3.2.0" mockk = "1.10.0" + moshi = "1.9.3" } configurations.all { @@ -126,7 +127,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.20.5" + implementation "io.github.wulkanowy:sdk:9364c2e" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' @@ -170,7 +171,9 @@ dependencies { implementation "com.ncapdevi:frag-nav:3.3.0" implementation "com.github.YarikSOffice:lingver:1.2.2" - implementation "com.google.code.gson:gson:2.8.6" + implementation "com.squareup.moshi:moshi:$moshi" + implementation "com.squareup.moshi:moshi-adapters:$moshi" + kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi" implementation "com.jakewharton.timber:timber:4.7.1" implementation "at.favre.lib:slf4j-timber:1.0.1" implementation "fr.bipi.treessence:treessence:0.3.2" diff --git a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt index b21c4834..834a9636 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt @@ -1,8 +1,8 @@ package io.github.wulkanowy.data.db import androidx.room.TypeConverter -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types import java.time.Instant import java.time.LocalDate import java.time.LocalDateTime @@ -12,6 +12,16 @@ import java.util.Date class Converters { + private val moshi by lazy { Moshi.Builder().build() } + + private val integerListAdapter by lazy { + moshi.adapter>(Types.newParameterizedType(List::class.java, Integer::class.java)) + } + + private val stringMapAdapter by lazy { + moshi.adapter>(Types.newParameterizedType(MutableMap::class.java, String::class.java, String::class.java)) + } + @TypeConverter fun timestampToDate(value: Long?): LocalDate? = value?.run { Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate() @@ -39,22 +49,22 @@ class Converters { fun intToMonth(value: Int?) = value?.let { Month.of(it) } @TypeConverter - fun intListToGson(list: List): String { - return Gson().toJson(list) + fun intListToJson(list: List): String { + return integerListAdapter.toJson(list) } @TypeConverter - fun gsonToIntList(value: String): List { - return Gson().fromJson(value, object : TypeToken>() {}.type) + fun jsonToIntList(value: String): List { + return integerListAdapter.fromJson(value).orEmpty() } @TypeConverter - fun stringPairListToGson(list: List>): String { - return Gson().toJson(list) + fun stringPairListToJson(list: List>): String { + return stringMapAdapter.toJson(list.toMap()) } @TypeConverter - fun gsonToStringPairList(value: String): List> { - return Gson().fromJson(value, object : TypeToken>>() {}.type) + fun jsonToStringPairList(value: String): List> { + return stringMapAdapter.fromJson(value).orEmpty().toList() } } diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt index e792bde4..d2338c28 100644 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt +++ b/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt @@ -1,3 +1,9 @@ package io.github.wulkanowy.data.pojos -class Contributor(val displayName: String, val githubUsername: String) +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +class Contributor( + val displayName: String, + val githubUsername: String +) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt index d1956557..ff538969 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt @@ -1,7 +1,8 @@ package io.github.wulkanowy.data.repositories.appcreator import android.content.res.AssetManager -import com.google.gson.Gson +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types import io.github.wulkanowy.data.pojos.Contributor import io.github.wulkanowy.utils.DispatchersProvider import kotlinx.coroutines.withContext @@ -15,9 +16,9 @@ class AppCreatorRepository @Inject constructor( ) { suspend fun getAppCreators() = withContext(dispatchers.backgroundThread) { - Gson().fromJson( - assets.open("contributors.json").bufferedReader().use { it.readText() }, - Array::class.java - ).toList() + val moshi = Moshi.Builder().build() + val type = Types.newParameterizedType(List::class.java, Contributor::class.java) + val adapter = moshi.adapter>(type) + adapter.fromJson(assets.open("contributors.json").bufferedReader().use { it.readText() }) } } diff --git a/app/src/main/res/layout/fragment_contributor.xml b/app/src/main/res/layout/fragment_contributor.xml index 399ab599..d913c5a4 100644 --- a/app/src/main/res/layout/fragment_contributor.xml +++ b/app/src/main/res/layout/fragment_contributor.xml @@ -1,5 +1,6 @@ @@ -20,17 +21,18 @@ android:id="@+id/creatorRecycler" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1" /> + android:layout_weight="1" + tools:listitem="@layout/item_contributor" /> diff --git a/app/src/main/res/layout/item_contributor.xml b/app/src/main/res/layout/item_contributor.xml index 36eb64ec..9b126343 100644 --- a/app/src/main/res/layout/item_contributor.xml +++ b/app/src/main/res/layout/item_contributor.xml @@ -15,7 +15,8 @@ android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" - android:contentDescription="@string/contributor_avatar_description" /> + android:contentDescription="@string/contributor_avatar_description" + tools:src="@tools:sample/avatars" /> Date: Sun, 27 Sep 2020 22:11:55 +0200 Subject: [PATCH 043/150] Version 0.21.0 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 11 ++++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 45818739..c2361d66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.20.5 + - 0.21.0 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index c0a4e9f3..0dd31527 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 69 - versionName "0.20.5" + versionCode 70 + versionName "0.21.0" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -127,7 +127,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:9364c2e" + implementation "io.github.wulkanowy:sdk:0.21.0" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 62a71f43..09f44931 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,5 +1,10 @@ -Wersja 0.20.5 -- naprawiliśmy logowanie do koszalińskiego dziennika -- naprawiliśmy resetowanie hasła na gdańskim dzienniku +Wersja 0.21.0 +- naprawiliśmy logowanie do tarnowskiego dziennika +- naprawiliśmy wyświetlanie podsumowania punktów klasy +- dodaliśmy skróty aplikacji +- dodaliśmy opcję pokazywania nazwy grupy w planie lekcji na liście +- dodaliśmy opcję pokazywania w ocenach przedmiotów bez ocen +- dodaliśmy dodatkowe opcje sortowania ocen +- dodaliśmy rozróżnianie powiadomień dla pochwał i uwag Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases From e5661098d9f9b293580cb41840520e134b36bdb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 29 Sep 2020 11:42:54 +0200 Subject: [PATCH 044/150] Fix string pair list type converter (#970) --- app/build.gradle | 2 +- .../io/github/wulkanowy/data/db/Converters.kt | 11 +-- .../data/db/adapters/PairAdapterFactory.kt | 68 +++++++++++++++++++ .../wulkanowy/data/db/ConvertersTest.kt | 25 +++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt create mode 100644 app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt diff --git a/app/build.gradle b/app/build.gradle index 0dd31527..440b665a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,7 +127,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.21.0" + implementation "io.github.wulkanowy:sdk:84c0703" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' diff --git a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt index 834a9636..def0b371 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt @@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db import androidx.room.TypeConverter import com.squareup.moshi.Moshi import com.squareup.moshi.Types +import io.github.wulkanowy.data.db.adapters.PairAdapterFactory import java.time.Instant import java.time.LocalDate import java.time.LocalDateTime @@ -12,14 +13,14 @@ import java.util.Date class Converters { - private val moshi by lazy { Moshi.Builder().build() } + private val moshi by lazy { Moshi.Builder().add(PairAdapterFactory).build() } private val integerListAdapter by lazy { moshi.adapter>(Types.newParameterizedType(List::class.java, Integer::class.java)) } - private val stringMapAdapter by lazy { - moshi.adapter>(Types.newParameterizedType(MutableMap::class.java, String::class.java, String::class.java)) + private val stringListPairAdapter by lazy { + moshi.adapter>>(Types.newParameterizedType(List::class.java, Pair::class.java, String::class.java, String::class.java)) } @TypeConverter @@ -60,11 +61,11 @@ class Converters { @TypeConverter fun stringPairListToJson(list: List>): String { - return stringMapAdapter.toJson(list.toMap()) + return stringListPairAdapter.toJson(list) } @TypeConverter fun jsonToStringPairList(value: String): List> { - return stringMapAdapter.fromJson(value).orEmpty().toList() + return stringListPairAdapter.fromJson(value).orEmpty() } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt b/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt new file mode 100644 index 00000000..60ae37c9 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt @@ -0,0 +1,68 @@ +package io.github.wulkanowy.data.db.adapters + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type + +object PairAdapterFactory : JsonAdapter.Factory { + + override fun create(type: Type, annotations: MutableSet, moshi: Moshi): JsonAdapter<*>? { + if (type !is ParameterizedType || List::class.java != type.rawType) return null + if (type.actualTypeArguments[0] != Pair::class.java) return null + + val listType = Types.newParameterizedType(List::class.java, Map::class.java, String::class.java) + val listAdapter = moshi.adapter>>(listType) + + val mapType = Types.newParameterizedType(MutableMap::class.java, String::class.java, String::class.java) + val mapAdapter = moshi.adapter>(mapType) + + return PairAdapter(listAdapter, mapAdapter) + } + + private class PairAdapter( + private val listAdapter: JsonAdapter>>, + private val mapAdapter: JsonAdapter>, + ) : JsonAdapter>>() { + + override fun toJson(writer: JsonWriter, value: List>?) { + writer.beginArray() + value?.forEach { + writer.beginObject() + writer.name("first").value(it.first) + writer.name("second").value(it.second) + writer.endObject() + } + writer.endArray() + } + + override fun fromJson(reader: JsonReader): List>? { + return if (reader.peek() == JsonReader.Token.BEGIN_OBJECT) deserializeMoshiMap(reader) + else deserializeGsonPair(reader) + } + + // for compatibility with 0.21.0 + private fun deserializeMoshiMap(reader: JsonReader): List>? { + val map = mapAdapter.fromJson(reader) ?: return null + + return map.entries.map { + it.key to it.value + } + } + + private fun deserializeGsonPair(reader: JsonReader): List>? { + val list = listAdapter.fromJson(reader) ?: return null + + require(list.size == 2 || list.isEmpty()) { + "pair with more or less than two elements: $list" + } + + return list.map { + it["first"].orEmpty() to it["second"].orEmpty() + } + } + } +} diff --git a/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt b/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt new file mode 100644 index 00000000..50741b7a --- /dev/null +++ b/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt @@ -0,0 +1,25 @@ +package io.github.wulkanowy.data.db + +import org.junit.Assert.assertEquals +import org.junit.Test + +class ConvertersTest { + + @Test + fun stringPairListToJson() { + assertEquals(Converters().stringPairListToJson(listOf("aaa" to "bbb", "ccc" to "ddd")), "[{\"first\":\"aaa\",\"second\":\"bbb\"},{\"first\":\"ccc\",\"second\":\"ddd\"}]") + assertEquals(Converters().stringPairListToJson(listOf()), "[]") + } + + @Test + fun jsonToStringPairList() { + assertEquals(Converters().jsonToStringPairList("[{\"first\":\"aaa\",\"second\":\"bbb\"},{\"first\":\"ccc\",\"second\":\"ddd\"}]"), listOf("aaa" to "bbb", "ccc" to "ddd")) + assertEquals(Converters().jsonToStringPairList("[]"), listOf>()) + } + + @Test + fun jsonToStringPairList_0210() { + assertEquals(Converters().jsonToStringPairList("{\"aaa\":\"bbb\",\"ccc\":\"ddd\"}"), listOf("aaa" to "bbb", "ccc" to "ddd")) + assertEquals(Converters().jsonToStringPairList("{}"), listOf>()) + } +} From d95a33787b39a1215efdf9f6a91cba9edb23df30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 29 Sep 2020 11:43:49 +0200 Subject: [PATCH 045/150] Version 0.21.1 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c2361d66..a36c34cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.21.0 + - 0.21.1 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 440b665a..cee711d2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 70 - versionName "0.21.0" + versionCode 71 + versionName "0.21.1" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -127,7 +127,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:84c0703" + implementation "io.github.wulkanowy:sdk:0.21.1" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 09f44931..271eac7f 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,4 +1,4 @@ -Wersja 0.21.0 +Wersja 0.21.1 - naprawiliśmy logowanie do tarnowskiego dziennika - naprawiliśmy wyświetlanie podsumowania punktów klasy - dodaliśmy skróty aplikacji From 1f0f6b3e512bd37513855d5bb35d855af29f4a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 29 Sep 2020 21:02:49 +0200 Subject: [PATCH 046/150] Fix string pair list type converter (#971) --- app/build.gradle | 2 +- .../wulkanowy/data/db/adapters/PairAdapterFactory.kt | 8 ++++---- .../java/io/github/wulkanowy/data/db/ConvertersTest.kt | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cee711d2..927f2e50 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,7 +127,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.21.1" + implementation "io.github.wulkanowy:sdk:7577fc9" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' diff --git a/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt b/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt index 60ae37c9..4a9b168d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/adapters/PairAdapterFactory.kt @@ -56,11 +56,11 @@ object PairAdapterFactory : JsonAdapter.Factory { private fun deserializeGsonPair(reader: JsonReader): List>? { val list = listAdapter.fromJson(reader) ?: return null - require(list.size == 2 || list.isEmpty()) { - "pair with more or less than two elements: $list" - } - return list.map { + require(it.size == 2) { + "pair with more or less than two elements: $list" + } + it["first"].orEmpty() to it["second"].orEmpty() } } diff --git a/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt b/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt index 50741b7a..3b0d7c84 100644 --- a/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/db/ConvertersTest.kt @@ -7,19 +7,24 @@ class ConvertersTest { @Test fun stringPairListToJson() { + assertEquals(Converters().stringPairListToJson(listOf("aaa" to "bbb", "ccc" to "ddd", "eee" to "fff")), "[{\"first\":\"aaa\",\"second\":\"bbb\"},{\"first\":\"ccc\",\"second\":\"ddd\"},{\"first\":\"eee\",\"second\":\"fff\"}]") assertEquals(Converters().stringPairListToJson(listOf("aaa" to "bbb", "ccc" to "ddd")), "[{\"first\":\"aaa\",\"second\":\"bbb\"},{\"first\":\"ccc\",\"second\":\"ddd\"}]") + assertEquals(Converters().stringPairListToJson(listOf("aaa" to "bbb")), "[{\"first\":\"aaa\",\"second\":\"bbb\"}]") assertEquals(Converters().stringPairListToJson(listOf()), "[]") } @Test fun jsonToStringPairList() { + assertEquals(Converters().jsonToStringPairList("[{\"first\":\"aaa\",\"second\":\"bbb\"},{\"first\":\"ccc\",\"second\":\"ddd\"},{\"first\":\"eee\",\"second\":\"fff\"}]"), listOf("aaa" to "bbb", "ccc" to "ddd", "eee" to "fff")) assertEquals(Converters().jsonToStringPairList("[{\"first\":\"aaa\",\"second\":\"bbb\"},{\"first\":\"ccc\",\"second\":\"ddd\"}]"), listOf("aaa" to "bbb", "ccc" to "ddd")) + assertEquals(Converters().jsonToStringPairList("[{\"first\":\"aaa\",\"second\":\"bbb\"}]"), listOf("aaa" to "bbb")) assertEquals(Converters().jsonToStringPairList("[]"), listOf>()) } @Test fun jsonToStringPairList_0210() { assertEquals(Converters().jsonToStringPairList("{\"aaa\":\"bbb\",\"ccc\":\"ddd\"}"), listOf("aaa" to "bbb", "ccc" to "ddd")) + assertEquals(Converters().jsonToStringPairList("{\"aaa\":\"bbb\"}"), listOf("aaa" to "bbb")) assertEquals(Converters().jsonToStringPairList("{}"), listOf>()) } } From 8a1a712d6d46b551b3093ca170ff80ee53663970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Tue, 29 Sep 2020 21:10:05 +0200 Subject: [PATCH 047/150] Version 0.21.2 --- .travis.yml | 2 +- app/build.gradle | 6 +++--- app/src/main/play/release-notes/pl-PL/default.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index a36c34cf..24280c5f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.21.1 + - 0.21.2 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 927f2e50..56609466 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 29 - versionCode 71 - versionName "0.21.1" + versionCode 72 + versionName "0.21.2" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -127,7 +127,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:7577fc9" + implementation "io.github.wulkanowy:sdk:0.21.2" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 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 271eac7f..7553e2cb 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,4 +1,4 @@ -Wersja 0.21.1 +Wersja 0.21.2 - naprawiliśmy logowanie do tarnowskiego dziennika - naprawiliśmy wyświetlanie podsumowania punktów klasy - dodaliśmy skróty aplikacji From 7298d0d75a33aad1e6dbf76f402a550cc66b09d9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 19:33:22 +0000 Subject: [PATCH 048/150] Bump google-services from 4.3.3 to 4.3.4 (#978) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4205cce5..ec7f96ff 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ buildscript { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.android.tools.build:gradle:4.0.1' classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" - classpath 'com.google.gms:google-services:4.3.3' + classpath 'com.google.gms:google-services:4.3.4' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' classpath "com.github.triplet.gradle:play-publisher:2.7.5" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0" From f21216286da6d5ecafe4e38d6ad126c6ae9d58f8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 19:34:13 +0000 Subject: [PATCH 049/150] Bump mockk from 1.10.0 to 1.10.2 (#977) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 56609466..3fe8de51 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -118,7 +118,7 @@ ext { work_manager = "2.4.0" room = "2.2.5" chucker = "3.2.0" - mockk = "1.10.0" + mockk = "1.10.2" moshi = "1.9.3" } From 613fa44c27f6f2386d5e4169c319c333a126d0a7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 19:34:53 +0000 Subject: [PATCH 050/150] Bump about_libraries from 8.3.0 to 8.3.1 (#975) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ec7f96ff..c5cfaf99 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.4.10' - about_libraries = '8.3.0' + about_libraries = '8.3.1' hilt_version = "2.29.1-alpha" } repositories { From 43ed8c8fce7a7899b83dfd6a2047f8ff9eb64af0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 19:52:02 +0000 Subject: [PATCH 051/150] Bump firebase-messaging from 20.2.4 to 20.3.0 (#973) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3fe8de51..9c507052 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -186,7 +186,7 @@ dependencies { playImplementation 'com.google.firebase:firebase-analytics:17.5.0' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1" - playImplementation 'com.google.firebase:firebase-messaging:20.2.4' + playImplementation 'com.google.firebase:firebase-messaging:20.3.0' playImplementation 'com.google.firebase:firebase-crashlytics:17.2.1' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' From c479b31670934470f52bb6428756f112f347d095 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 20:01:45 +0000 Subject: [PATCH 052/150] Bump coil from 1.0.0-rc2 to 1.0.0-rc3 (#976) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9c507052..b0c1bf6c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -179,7 +179,7 @@ dependencies { implementation "fr.bipi.treessence:treessence:0.3.2" implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation 'com.wdullaer:materialdatetimepicker:4.2.3' - implementation "io.coil-kt:coil:1.0.0-rc2" + implementation "io.coil-kt:coil:1.0.0-rc3" implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' From 112c1eb793942111f4536346cba28ade30b72a54 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 20:13:01 +0000 Subject: [PATCH 053/150] Bump moshi from 1.9.3 to 1.10.0 (#972) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index b0c1bf6c..60588069 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,7 +119,7 @@ ext { room = "2.2.5" chucker = "3.2.0" mockk = "1.10.2" - moshi = "1.9.3" + moshi = "1.10.0" } configurations.all { From 047e70ad46cf36ed91bd8cc63fcb96a9ef3dce33 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2020 20:13:18 +0000 Subject: [PATCH 054/150] Bump firebase-crashlytics from 17.2.1 to 17.2.2 (#974) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 60588069..9dffc380 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -187,7 +187,7 @@ dependencies { playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1" playImplementation 'com.google.firebase:firebase-messaging:20.3.0' - playImplementation 'com.google.firebase:firebase-crashlytics:17.2.1' + playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" From b91973aec374c9fbbf7b149aa261ae8035cf7d78 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2020 15:38:29 +0000 Subject: [PATCH 055/150] Bump chucker from 3.2.0 to 3.3.0 (#979) --- app/build.gradle | 2 +- .../main/java/io/github/wulkanowy/data/RepositoryModule.kt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9dffc380..6bcb9765 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -117,7 +117,7 @@ play { ext { work_manager = "2.4.0" room = "2.2.5" - chucker = "3.2.0" + chucker = "3.3.0" mockk = "1.10.2" moshi = "1.10.0" } diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt index 3370d0ac..6486cab9 100644 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt @@ -33,7 +33,11 @@ internal class RepositoryModule { setSimpleHttpLogger { Timber.d(it) } // for debug only - addInterceptor(ChuckerInterceptor(context, chuckerCollector), true) + addInterceptor(ChuckerInterceptor( + context = context, + collector = chuckerCollector, + alwaysReadResponseBody = true + ), true) } } From 40fc6ec2e07941931b2e72f02a0b44da09c7345a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 3 Oct 2020 01:08:57 +0200 Subject: [PATCH 056/150] Upgrade android sdk to 30 (#966) --- .travis.yml | 24 +++++++++------- app/build.gradle | 6 ++-- .../wulkanowy/ui/modules/main/MainActivity.kt | 4 +-- .../message/preview/MessagePreviewFragment.kt | 2 +- .../message/send/SendMessageActivity.kt | 6 ++-- .../io/github/wulkanowy/utils/LoggerUtils.kt | 28 +++++++++---------- 6 files changed, 38 insertions(+), 32 deletions(-) diff --git a/.travis.yml b/.travis.yml index 24280c5f..dc9df619 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,8 @@ jdk: oraclejdk8 env: global: - - ANDROID_API_LEVEL=29 - - ANDROID_BUILD_TOOLS_VERSION=29.0.3 + - ANDROID_API_LEVEL=30 + - ANDROID_BUILD_TOOLS_VERSION=30.0.2 cache: directories: @@ -28,22 +28,26 @@ android: - build-tools-$ANDROID_BUILD_TOOLS_VERSION # The SDK version used to compile your project - android-$ANDROID_API_LEVEL - # Additional components + # Additional components - extra-google-google_play_services - extra-google-m2repository - extra-android-m2repository - addon-google_apis-google-$ANDROID_API_LEVEL - # Android emulator + # Android emulator - android-22 - sys-img-armeabi-v7a-android-22 +before_install: + - yes | sdkmanager "platforms;android-30" + - yes | sdkmanager "build-tools;30.0.2" + before_script: - # Launch emulator before the execution - - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a - - emulator -avd test -no-audio -no-window & - - android-wait-for-emulator - - adb shell input keyevent 82 & - - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash" + # Launch emulator before the execution + - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a + - emulator -avd test -no-audio -no-window & + - android-wait-for-emulator + - adb shell input keyevent 82 & + - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash" script: - ./gradlew dependencies --stacktrace --daemon diff --git a/app/build.gradle b/app/build.gradle index 6bcb9765..1cd3b990 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,14 +10,14 @@ apply from: 'sonarqube.gradle' apply from: 'hooks.gradle' android { - compileSdkVersion 29 - buildToolsVersion '29.0.3' + compileSdkVersion 30 + buildToolsVersion '30.0.2' defaultConfig { applicationId "io.github.wulkanowy" testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 72 versionName "0.21.2" multiDexEnabled true 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 95b4aa77..53ac1631 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 @@ -181,8 +181,8 @@ class MainActivity : BaseActivity(), MainVie analytics.setCurrentScreen(this, name) } - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return if (item?.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected() + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return if (item.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected() else 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 740f4927..b35731ca 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 @@ -174,7 +174,7 @@ class MessagePreviewFragment : @RequiresApi(Build.VERSION_CODES.LOLLIPOP) override fun printDocument(html: String, jobName: String) { - val webView = WebView(activity) + val webView = WebView(requireContext()) webView.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt index 2267279c..59944d41 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.message.send +import android.annotation.SuppressLint import android.content.Context import android.content.Intent import android.graphics.Rect @@ -74,6 +75,7 @@ class SendMessageActivity : BaseActivity Date: Sat, 3 Oct 2020 13:01:11 +0200 Subject: [PATCH 057/150] New Crowdin updates (#948) --- .../main/res/values-de/preferences_values.xml | 4 + app/src/main/res/values-de/strings.xml | 31 ++++++++ .../main/res/values-ru/preferences_values.xml | 8 +- app/src/main/res/values-ru/strings.xml | 73 +++++++++++++++---- .../main/res/values-uk/preferences_values.xml | 4 + app/src/main/res/values-uk/strings.xml | 43 +++++++++++ 6 files changed, 146 insertions(+), 17 deletions(-) diff --git a/app/src/main/res/values-de/preferences_values.xml b/app/src/main/res/values-de/preferences_values.xml index 11935b49..177a12a9 100644 --- a/app/src/main/res/values-de/preferences_values.xml +++ b/app/src/main/res/values-de/preferences_values.xml @@ -29,6 +29,10 @@ 0,5 0,75 + + Alphabetic + By date + Dzienniczek+ Wulkanowy diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7e287767..c33c273a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -154,6 +154,8 @@ Entschuldigte Verspätung Unentschuldigte Verspätung Anwesend + Deleted + Unknown Lektion Nummer Keine Einträgen @@ -222,6 +224,32 @@ Du hast %1$d Eintrag bekommen Du hast %1$d Eintragen bekommen + + + %d praise + %d praises + + + New praise + New praises + + + You received %1$d praise + You received %1$d praises + + + + %d neutral note + %d neutral notes + + + New neutral note + New neutral notes + + + You received %1$d neutral note + You received %1$d neutral notes + Keine Informationen über Hausaufgaben Gemacht @@ -327,9 +355,12 @@ Thema der Anwendung Noten erweitern Aktuelle Lektion im Stundenplan markieren + Show groups next to subjects in timetable Liste der Diagramme in Klassenbewertungen anzeigen Unterricht der ganzen Klasse anzeigen + Show subjects without grades in Grades Farbschema der Noten + Subjects sorting in \"Grades\" App Sprache Benachrichtigungen Benachrichtigungen anzeigen diff --git a/app/src/main/res/values-ru/preferences_values.xml b/app/src/main/res/values-ru/preferences_values.xml index a41abf35..b8c7e4f6 100644 --- a/app/src/main/res/values-ru/preferences_values.xml +++ b/app/src/main/res/values-ru/preferences_values.xml @@ -29,6 +29,10 @@ 0,5 0,75 + + Alphabetic + By date + Dzienniczek+ Wulkanowy @@ -36,8 +40,8 @@ Средняя оценка со 2 семестра - Average of grades from both semesters - Average of grades from the whole year + Средняя оценка с двух семестров + Средняя оценок со всего года Не показывать diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 7052fbc9..a4870b84 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -108,16 +108,16 @@ Новые оценки - New predicted grade + Новая ожидаемая оценка New predicted grades New predicted grades - New predicted grades + Новые ожидаемые оценки - New final grade + Новая итоговая оценка New final grades New final grades - New final grades + Новые итоговые оценки Вы получили %1$d оценку @@ -126,16 +126,16 @@ Вы получили %1$d оценок - You received %1$d predicted grade - You received %1$d predicted grades + Вы получили %1$d ожидаемую оценку + Вы получили %1$d ожидаемые оценки You received %1$d predicted grades You received %1$d predicted grades - You received %1$d final grade + Вы получили %1$d финальную оценку You received %1$d final grades You received %1$d final grades - You received %1$d final grades + Вы получили %1$d финальные оценки Урок @@ -168,6 +168,8 @@ Опоздание по уважительным причинам Опоздание по неуважительным причинам Присутствие + Удалено + Неизвестно Урок № Данные не найдены @@ -204,8 +206,8 @@ Перенести в корзину Удалить навсегда Сообщение успешно удалено - Share - Print + Поделиться + Печать Тема Текст Сообщение успешно отправлено @@ -250,6 +252,44 @@ Вы получили %1$d предупреждений Вы получили %1$d предупреждений + + + %d praise + %d praises + %d praises + %d praises + + + New praise + New praises + New praises + New praises + + + You received %1$d praise + You received %1$d praises + You received %1$d praises + You received %1$d praises + + + + %d neutral note + %d neutral notes + %d neutral notes + %d neutral notes + + + New neutral note + New neutral notes + New neutral notes + New neutral notes + + + You received %1$d neutral note + You received %1$d neutral notes + You received %1$d neutral notes + You received %1$d neutral notes + Нет домашних заданий сделанный @@ -291,10 +331,10 @@ Выйти Вы точно хотите выйти из данного аккаунта? Выйти - Student account - Parent account - Mobile API mode - Hybrid mode + Профиль ученика + Профиль родителя + Режим Mobile API + Гибридный режим Версия приложения Разработчики @@ -353,11 +393,14 @@ Принудительно высчитать среднюю оценку через приложение Показывать присутствия в посещаемости Тема приложения - Больше оценок + Разворачивать оценки Отмечать текущий урок в расписании + Show groups next to subjects in timetable Показывать диаграммы в оценках класса Показать уроки всего класса + Show subjects without grades in Grades Схема цветов оценок + Subjects sorting in \"Grades\" Язык приложения Уведомления Показывать уведомления diff --git a/app/src/main/res/values-uk/preferences_values.xml b/app/src/main/res/values-uk/preferences_values.xml index 9942621a..7e7d3cbf 100644 --- a/app/src/main/res/values-uk/preferences_values.xml +++ b/app/src/main/res/values-uk/preferences_values.xml @@ -29,6 +29,10 @@ 0,5 0,75 + + Alphabetic + By date + Dzienniczek+ Wulkanowy diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 15fe203d..ed10d24d 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -168,6 +168,8 @@ Спізнення з поважних причин Спізнення з не поважних причин Присутність + Deleted + Unknown Номер уроку Брак записів @@ -250,6 +252,44 @@ %1$d нових зауважень %1$d нових зауважень + + + %d praise + %d praises + %d praises + %d praises + + + New praise + New praises + New praises + New praises + + + You received %1$d praise + You received %1$d praises + You received %1$d praises + You received %1$d praises + + + + %d neutral note + %d neutral notes + %d neutral notes + %d neutral notes + + + New neutral note + New neutral notes + New neutral notes + New neutral notes + + + You received %1$d neutral note + You received %1$d neutral notes + You received %1$d neutral notes + You received %1$d neutral notes + Брак домашніх завдань Позначити як зроблене @@ -355,9 +395,12 @@ Тема додатку Більше оцінок Позначити поточний урок у розкладі + Show groups next to subjects in timetable Показувати діаграми в оцінках класу Показати уроки всього класу + Show subjects without grades in Grades Схема кольорів оцінок + Subjects sorting in \"Grades\" Мова додатку Повідомлення Показувати повідомлення From da6d8a74fdb57446317fdf843ab6d87ce66b5636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Tue, 6 Oct 2020 23:34:27 +0200 Subject: [PATCH 058/150] New Crowdin updates (#981) --- app/src/main/res/values-pl/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 0923951a..44e981cb 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -400,7 +400,7 @@ Pokazuj lekcje całej klasy Pokazuj przedmioty bez ocen w Oceny Schemat kolorów ocen - Sortowanie przedmiotów w "Oceny" + Sortowanie przedmiotów w \"Oceny\" Język aplikacji Powiadomienia Pokazuj powiadomienia From ca6dfbf2d048d21b9720adb8ffd6a2b9e7b2ed98 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2020 21:43:50 +0000 Subject: [PATCH 059/150] Bump core-ktx from 1.3.1 to 1.3.2 (#983) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1cd3b990..2d758dbc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -134,7 +134,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' - implementation "androidx.core:core-ktx:1.3.1" + implementation "androidx.core:core-ktx:1.3.2" implementation "androidx.activity:activity-ktx:1.1.0" implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0" From 518387e7bbba258389229cd0365465517e7283f2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2020 21:43:56 +0000 Subject: [PATCH 060/150] Bump gradle from 4.0.1 to 4.0.2 (#982) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c5cfaf99..dc45aea2 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.0.2' classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.4' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' From d6f3c572930e6a442f1d2b8a80287bc0c38ad82c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2020 21:45:38 +0000 Subject: [PATCH 061/150] Bump moshi from 1.10.0 to 1.11.0 (#984) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 2d758dbc..a83aa0eb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,7 +119,7 @@ ext { room = "2.2.5" chucker = "3.3.0" mockk = "1.10.2" - moshi = "1.10.0" + moshi = "1.11.0" } configurations.all { From 2bd0c75055aa743d241d8df5b2680a5efc464973 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2020 21:56:46 +0000 Subject: [PATCH 062/150] Bump about_libraries from 8.3.1 to 8.4.2 (#985) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dc45aea2..37a3c899 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.4.10' - about_libraries = '8.3.1' + about_libraries = '8.4.2' hilt_version = "2.29.1-alpha" } repositories { From 26a69092cc47d3766475f38404290ff1d01d38e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Wed, 7 Oct 2020 11:19:34 +0200 Subject: [PATCH 063/150] Add AppGallery badge (#986) --- README.en.md | 9 ++++++--- README.md | 9 ++++++--- appgallery_badge.png | Bin 0 -> 56482 bytes 3 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 appgallery_badge.png diff --git a/README.en.md b/README.en.md index 28cce1c3..4c5e53da 100644 --- a/README.en.md +++ b/README.en.md @@ -32,14 +32,17 @@ Unofficial android VULCAN UONET+ register client for both students and their par ## Download -You can download the current beta version from the Google Play or the F-Droid store +You can download the current beta version from the Google Play, F-Droid or Huawei AppGallery store [Get it on Google Play](https://play.google.com/store/apps/details?id=io.github.wulkanowy) + alt="Get it on Google Play" + height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy) [Get it on F-Droid](https://f-droid.org/packages/io.github.wulkanowy/) +[Explore it on AppGallery](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=) You can also download a [development version](https://wulkanowy.github.io/#download) that includes new features being prepared for the next release diff --git a/README.md b/README.md index 02e1900c..9e29cdb6 100644 --- a/README.md +++ b/README.md @@ -32,14 +32,17 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica ## Pobierz -Aktualną wersję beta możesz pobrać ze sklepu Google Play lub F-Droid +Aktualną wersję beta możesz pobrać ze sklepu Google Play, F-Droid lub Huawei AppGallery [Pobierz z Google Play](https://play.google.com/store/apps/details?id=io.github.wulkanowy) + alt="Pobierz z Google Play" + height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy) [Pobierz z F-Droid](https://f-droid.org/packages/io.github.wulkanowy/) +[Odkrywaj w AppGallery](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=) Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#download), która zawiera nowe funkcje przygotowywane do następnego wydania diff --git a/appgallery_badge.png b/appgallery_badge.png new file mode 100644 index 0000000000000000000000000000000000000000..ce8860758169eb6c425b9dbd8ca9e05a7d9381ea GIT binary patch literal 56482 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Ü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 literal 0 HcmV?d00001 From 721b4ac7973ab63bbeaf39ef9930b70aa4eb7c82 Mon Sep 17 00:00:00 2001 From: Mateusz Idziejczak Date: Fri, 9 Oct 2020 21:24:58 +0200 Subject: [PATCH 064/150] Add support for night mode in account switcher dialog (#988) --- app/src/main/res/values/styles.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 8f30e345..58ad1640 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -23,7 +23,7 @@ @drawable/layer_splash_background - -