From 57681b35ea0be4e8b7df011050410445dce126ae Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Mar 2021 22:58:17 +0000 Subject: [PATCH 01/23] Bump mockk from 1.10.6 to 1.11.0 (#1229) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index b8b6f016..3e56ea24 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -145,7 +145,7 @@ ext { work_hilt = "1.0.0-beta01" room = "2.3.0-beta03" chucker = "3.4.0" - mockk = "1.10.6" + mockk = "1.11.0" moshi = "1.11.0" } From 87e7e00705c25c0d9807207bfc7c9c5e9fd21f74 Mon Sep 17 00:00:00 2001 From: MRmlik12 <44818681+MRmlik12@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:57:12 +0100 Subject: [PATCH 02/23] Remove firebase inappmessage dependency (#1235) --- app/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3e56ea24..6b36d629 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -208,8 +208,6 @@ dependencies { playImplementation platform('com.google.firebase:firebase-bom:26.7.0') playImplementation 'com.google.firebase:firebase-analytics-ktx' - playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx' - playImplementation "com.google.firebase:firebase-inappmessaging-ktx" playImplementation 'com.google.firebase:firebase-messaging:' playImplementation 'com.google.firebase:firebase-crashlytics:' playImplementation 'com.google.android.play:core-ktx:1.8.1' From c9dc9a323fc6518ea7168f17fe36494f52db086e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:02:28 +0000 Subject: [PATCH 03/23] Bump gradle from 4.1.2 to 4.1.3 (#1234) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8a10f65b..77374fe8 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.android.tools.build:gradle:4.1.2' + classpath 'com.android.tools.build:gradle:4.1.3' classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.5' classpath 'com.huawei.agconnect:agcp:1.5.0.300' From 5bee155f1ed7b2e898bb1a6a3668b86358b095e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 20 Mar 2021 13:10:53 +0100 Subject: [PATCH 04/23] Remove listenablefuture from dependencies (#1237) --- app/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 6b36d629..c31ced27 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -211,7 +211,6 @@ dependencies { playImplementation 'com.google.firebase:firebase-messaging:' playImplementation 'com.google.firebase:firebase-crashlytics:' playImplementation 'com.google.android.play:core-ktx:1.8.1' - playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' hmsImplementation 'com.huawei.hms:hianalytics:5.2.0.300' hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.5.0.300' From 15603357499961ae70dcf2753bd46362a4bc501a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 20 Mar 2021 13:27:47 +0100 Subject: [PATCH 05/23] Fix very rare crash in login recovery (#1231) --- .../login/recover/LoginRecoverFragment.kt | 22 +++++++++++---- .../res/layout/fragment_login_recover.xml | 28 +++++++++++-------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt index f0c9652f..2e2f9f5c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt @@ -9,6 +9,7 @@ import android.view.View.VISIBLE import android.webkit.JavascriptInterface import android.webkit.WebView import android.webkit.WebViewClient +import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -42,10 +43,12 @@ class LoginRecoverFragment : private lateinit var hostSymbols: Array override val recoverHostValue: String - get() = hostValues.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())).orEmpty() + get() = hostValues.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())) + .orEmpty() override val formHostSymbol: String - get() = hostSymbols.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())).orEmpty() + get() = hostSymbols.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())) + .orEmpty() override val recoverNameValue: String get() = bindingLocal.loginRecoverName.text.toString().trim() @@ -82,7 +85,9 @@ class LoginRecoverFragment : with(bindingLocal.loginRecoverHost) { setText(hostKeys.getOrNull(0).orEmpty()) - setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) + setAdapter( + LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys) + ) setOnClickListener { if (bindingLocal.loginRecoverFormContainer.visibility == GONE) dismissDropDown() } } } @@ -127,6 +132,7 @@ class LoginRecoverFragment : override fun showErrorView(show: Boolean) { bindingLocal.loginRecoverError.visibility = if (show) VISIBLE else GONE + bindingLocal.loginRecoverErrorDetails.isVisible = true } override fun setErrorDetails(message: String) { @@ -166,7 +172,7 @@ class LoginRecoverFragment : with(bindingLocal.loginRecoverWebView) { settings.javaScriptEnabled = true webViewClient = object : WebViewClient() { - private var recoverWebViewSuccess: Boolean = true + private var recoverWebViewSuccess = true override fun onPageFinished(view: WebView?, url: String?) { if (recoverWebViewSuccess) { @@ -175,10 +181,16 @@ class LoginRecoverFragment : } else { showProgress(false) showErrorView(true) + bindingLocal.loginRecoverErrorDetails.isVisible = false } } - override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) { + override fun onReceivedError( + view: WebView, + errorCode: Int, + description: String, + failingUrl: String + ) { recoverWebViewSuccess = false } } diff --git a/app/src/main/res/layout/fragment_login_recover.xml b/app/src/main/res/layout/fragment_login_recover.xml index 629ed54d..4277155b 100644 --- a/app/src/main/res/layout/fragment_login_recover.xml +++ b/app/src/main/res/layout/fragment_login_recover.xml @@ -26,7 +26,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="16dp" - android:visibility="visible"> + android:visibility="gone"> @@ -156,7 +156,7 @@ android:orientation="vertical" android:visibility="invisible" tools:ignore="UseCompoundDrawables" - tools:visibility="invisible"> + tools:visibility="visible"> - + android:layout_marginTop="16dp"> + android:text="@string/all_details" + app:layout_constraintEnd_toStartOf="@id/loginRecoverErrorRetry" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + android:text="@string/all_retry" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/loginRecoverErrorDetails" + app:layout_constraintTop_toTopOf="parent" /> + + tools:visibility="gone"> - From efafd2094a0d913cd40bef53cc78434a94bcf3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 20 Mar 2021 14:01:17 +0100 Subject: [PATCH 06/23] Add dialog with info about dropping support for android 4 (#1221) --- .../repositories/PreferencesRepository.kt | 5 +++ .../ui/modules/splash/SplashActivity.kt | 16 +++++++++ .../ui/modules/splash/SplashPresenter.kt | 35 ++++++++++++++++--- .../wulkanowy/ui/modules/splash/SplashView.kt | 2 ++ app/src/main/res/values/strings.xml | 7 ++++ .../ui/modules/splash/SplashPresenterTest.kt | 17 ++++++++- 6 files changed, 76 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt index 11adbd0f..5bd1f3c1 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt @@ -2,6 +2,7 @@ package io.github.wulkanowy.data.repositories import android.content.Context import android.content.SharedPreferences +import androidx.core.content.edit import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R import io.github.wulkanowy.ui.modules.grade.GradeAverageMode @@ -145,6 +146,10 @@ class PreferencesRepository @Inject constructor( R.bool.pref_default_subjects_without_grades ) + var isKitkatDialogDisabled: Boolean + get() = sharedPref.getBoolean("kitkat_dialog_disabled", false) + set(value) = sharedPref.edit { putBoolean("kitkat_dialog_disabled", value) } + private fun getString(id: Int, default: Int) = getString(context.getString(id), default) private fun getString(id: String, default: Int) = diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt index 80138175..2b96a9a0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt @@ -3,17 +3,23 @@ package io.github.wulkanowy.ui.modules.splash import android.os.Bundle import android.widget.Toast import android.widget.Toast.LENGTH_LONG +import androidx.appcompat.app.AlertDialog import androidx.viewbinding.ViewBinding import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.main.MainActivity +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.openInternetBrowser import javax.inject.Inject @AndroidEntryPoint class SplashActivity : BaseActivity(), SplashView { + @Inject + lateinit var appInfo: AppInfo + @Inject override lateinit var presenter: SplashPresenter @@ -40,4 +46,14 @@ class SplashActivity : BaseActivity(), SplashView override fun showError(text: String, error: Throwable) { Toast.makeText(this, text, LENGTH_LONG).show() } + + override fun showKitkatView() { + AlertDialog.Builder(this) + .setTitle(R.string.drop_kitkat_title) + .setMessage(R.string.drop_kitkat_content) + .setPositiveButton(android.R.string.ok, null) + .setNeutralButton(R.string.drop_kitkat_again) { _, _ -> presenter.onNeutralButtonSelected() } + .setOnDismissListener { presenter.onKitkatViewDismissed() } + .show() + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt index 79588917..4590d91a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt @@ -1,9 +1,12 @@ package io.github.wulkanowy.ui.modules.splash +import android.os.Build import io.github.wulkanowy.data.Status +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.flowWithResource import kotlinx.coroutines.flow.onEach import timber.log.Timber @@ -11,25 +14,47 @@ import javax.inject.Inject class SplashPresenter @Inject constructor( errorHandler: ErrorHandler, - studentRepository: StudentRepository + studentRepository: StudentRepository, + private val preferencesRepository: PreferencesRepository, + private val appInfo: AppInfo ) : BasePresenter(errorHandler, studentRepository) { + private var externalUrl: String? = null + fun onAttachView(view: SplashView, externalUrl: String?) { super.onAttachView(view) + this.externalUrl = externalUrl + if (appInfo.systemVersion < Build.VERSION_CODES.LOLLIPOP && !preferencesRepository.isKitkatDialogDisabled) { + view.showKitkatView() + } else { + loadCorrectDataOrUser() + } + } + + private fun loadCorrectDataOrUser() { if (!externalUrl.isNullOrBlank()) { - return view.openExternalUrlAndFinish(externalUrl) + view?.openExternalUrlAndFinish(externalUrl!!) + return } flowWithResource { studentRepository.isCurrentStudentSet() }.onEach { when (it.status) { Status.LOADING -> Timber.d("Is current user set check started") - Status.SUCCESS -> with(view) { - if (it.data!!) openMainView() - else openLoginView() + Status.SUCCESS -> { + if (it.data!!) view?.openMainView() + else view?.openLoginView() } Status.ERROR -> errorHandler.dispatch(it.error!!) } }.launch() } + + fun onKitkatViewDismissed() { + loadCorrectDataOrUser() + } + + fun onNeutralButtonSelected() { + preferencesRepository.isKitkatDialogDisabled = true + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt index a5aa1409..c9c5fe9a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt @@ -9,4 +9,6 @@ interface SplashView : BaseView { fun openMainView() fun openExternalUrlAndFinish(url: String) + + fun showKitkatView() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db5ed7b4..c4109d2b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -541,6 +541,12 @@ Debug + + End of support + We are ending support for your device. No more new features will appear for it in Wulkanowy. However, we will be releasing critical patches until the end of 2021 so you have time to switch to a newer model + Don\'t show again + + Black Red @@ -554,6 +560,7 @@ Copied Undo + Download of updates has started… An update has just been downloaded. diff --git a/app/src/test/java/io/github/wulkanowy/ui/modules/splash/SplashPresenterTest.kt b/app/src/test/java/io/github/wulkanowy/ui/modules/splash/SplashPresenterTest.kt index 71d17b3b..48c2aa9c 100644 --- a/app/src/test/java/io/github/wulkanowy/ui/modules/splash/SplashPresenterTest.kt +++ b/app/src/test/java/io/github/wulkanowy/ui/modules/splash/SplashPresenterTest.kt @@ -1,10 +1,13 @@ package io.github.wulkanowy.ui.modules.splash import io.github.wulkanowy.MainCoroutineRule +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.AppInfo import io.mockk.MockKAnnotations import io.mockk.coEvery +import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.verify import org.junit.Before @@ -22,6 +25,12 @@ class SplashPresenterTest { @MockK lateinit var studentRepository: StudentRepository + @MockK + lateinit var preferencesRepository: PreferencesRepository + + @MockK + lateinit var appInfo: AppInfo + @MockK(relaxed = true) lateinit var errorHandler: ErrorHandler @@ -30,19 +39,25 @@ class SplashPresenterTest { @Before fun setUp() { MockKAnnotations.init(this) - presenter = SplashPresenter(errorHandler, studentRepository) + presenter = SplashPresenter(errorHandler, studentRepository, preferencesRepository, appInfo) } @Test fun testOpenLoginView() { + every { appInfo.systemVersion } returns 30 + every { preferencesRepository.isKitkatDialogDisabled } returns true coEvery { studentRepository.isCurrentStudentSet() } returns false + presenter.onAttachView(splashView, null) verify { splashView.openLoginView() } } @Test fun testMainMainView() { + every { appInfo.systemVersion } returns 30 + every { preferencesRepository.isKitkatDialogDisabled } returns true coEvery { studentRepository.isCurrentStudentSet() } returns true + presenter.onAttachView(splashView, null) verify { splashView.openMainView() } } From e03b0dfa0150505da6c67c9bc4917ed292719e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sun, 21 Mar 2021 12:04:55 +0100 Subject: [PATCH 07/23] Fix missing avatars in widgets (#1238) --- .../ui/base/WidgetConfigureAdapter.kt | 29 ++++-- .../TimetableWidgetProvider.kt | 93 ++++++++++++++++--- 2 files changed, 101 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt index 8e6130fb..99440f83 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt @@ -1,18 +1,20 @@ package io.github.wulkanowy.ui.base import android.annotation.SuppressLint -import android.graphics.PorterDuff import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.databinding.ItemAccountBinding +import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.nickOrName import javax.inject.Inject -class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter() { +class WidgetConfigureAdapter @Inject constructor() : + RecyclerView.Adapter() { var items = emptyList>() @@ -27,16 +29,31 @@ class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter 1 with(holder.binding) { accountItemName.text = "${student.nickOrName} ${student.className}" accountItemSchool.text = student.schoolName + accountItemImage.setImageDrawable(avatar) - with(accountItemImage) { - val colorImage = if (isCurrent) context.getThemeAttrColor(R.attr.colorPrimary) - else context.getThemeAttrColor(R.attr.colorOnSurface, 153) + with(accountItemAccountType) { + setText(if (student.isParent) R.string.account_type_parent else R.string.account_type_student) + isVisible = isDuplicatedStudent + } - setColorFilter(colorImage, PorterDuff.Mode.SRC_IN) + with(accountItemCheck) { + isVisible = isCurrent + borderColor = checkBackgroundColor + circleColor = checkBackgroundColor } root.setOnClickListener { onClickListener(student) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt index 1d63f094..071a2d17 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt @@ -13,6 +13,8 @@ import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.res.Configuration +import android.graphics.Bitmap +import android.graphics.Canvas import android.widget.RemoteViews import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -25,6 +27,8 @@ import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.createNameInitialsDrawable +import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nickOrName @@ -72,7 +76,8 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { fun getThemeWidgetKey(appWidgetId: Int) = "timetable_widget_theme_$appWidgetId" - fun getCurrentThemeWidgetKey(appWidgetId: Int) = "timetable_widget_current_theme_$appWidgetId" + fun getCurrentThemeWidgetKey(appWidgetId: Int) = + "timetable_widget_current_theme_$appWidgetId" } override fun onReceive(context: Context, intent: Intent) { @@ -88,21 +93,29 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { private suspend fun onUpdate(context: Context, intent: Intent) { if (intent.getStringExtra(EXTRA_BUTTON_TYPE) === null) { intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId -> - val student = getStudent(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId) + val student = + getStudent(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId) updateWidget(context, appWidgetId, now().nextOrSameSchoolDay, student) } } else { val buttonType = intent.getStringExtra(EXTRA_BUTTON_TYPE) val toggledWidgetId = intent.getIntExtra(EXTRA_TOGGLED_WIDGET_ID, 0) - val student = getStudent(sharedPref.getLong(getStudentWidgetKey(toggledWidgetId), 0), toggledWidgetId) - val savedDate = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(toggledWidgetId), 0)) + val student = getStudent( + sharedPref.getLong(getStudentWidgetKey(toggledWidgetId), 0), + toggledWidgetId + ) + val savedDate = + LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(toggledWidgetId), 0)) val date = when (buttonType) { BUTTON_RESET -> now().nextOrSameSchoolDay BUTTON_NEXT -> savedDate.nextSchoolDay BUTTON_PREV -> savedDate.previousSchoolDay else -> now().nextOrSameSchoolDay } - if (!buttonType.isNullOrBlank()) analytics.logEvent("changed_timetable_widget_day", "button" to buttonType) + if (!buttonType.isNullOrBlank()) analytics.logEvent( + "changed_timetable_widget_day", + "button" to buttonType + ) updateWidget(context, toggledWidgetId, date, student) } } @@ -121,9 +134,15 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { } @SuppressLint("DefaultLocale") - private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate, student: Student?) { + private fun updateWidget( + context: Context, + appWidgetId: Int, + date: LocalDate, + student: Student? + ) { val savedConfigureTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0) - val isSystemDarkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + val isSystemDarkMode = + context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES var currentTheme = 0L var layoutId = R.layout.widget_timetable @@ -134,21 +153,28 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { val nextNavIntent = createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT) val prevNavIntent = createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV) - val resetNavIntent = createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET) + val resetNavIntent = + createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET) val adapterIntent = Intent(context, TimetableWidgetService::class.java) .apply { putExtra(EXTRA_APPWIDGET_ID, appWidgetId) //make Intent unique action = appWidgetId.toString() } - val accountIntent = PendingIntent.getActivity(context, -Int.MAX_VALUE + appWidgetId, + val accountIntent = PendingIntent.getActivity( + context, -Int.MAX_VALUE + appWidgetId, Intent(context, TimetableWidgetConfigureActivity::class.java).apply { addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK) putExtra(EXTRA_APPWIDGET_ID, appWidgetId) putExtra(EXTRA_FROM_PROVIDER, true) - }, FLAG_UPDATE_CURRENT) - val appIntent = PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id, - MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT) + }, FLAG_UPDATE_CURRENT + ) + val appIntent = PendingIntent.getActivity( + context, + MainView.Section.TIMETABLE.id, + MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), + FLAG_UPDATE_CURRENT + ) val remoteView = RemoteViews(context.packageName, layoutId).apply { setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) @@ -160,6 +186,11 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { R.id.timetableWidgetName, student?.nickOrName ?: context.getString(R.string.all_no_data) ) + + student?.let { + setImageViewBitmap(R.id.timetableWidgetAccount, context.createAvatarBitmap(it)) + } + setRemoteAdapter(R.id.timetableWidgetList, adapterIntent) setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent) setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent) @@ -181,13 +212,20 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { } } - private fun createNavIntent(context: Context, code: Int, appWidgetId: Int, buttonType: String): PendingIntent { - return PendingIntent.getBroadcast(context, code, + private fun createNavIntent( + context: Context, + code: Int, + appWidgetId: Int, + buttonType: String + ): PendingIntent { + return PendingIntent.getBroadcast( + context, code, Intent(context, TimetableWidgetProvider::class.java).apply { action = ACTION_APPWIDGET_UPDATE putExtra(EXTRA_BUTTON_TYPE, buttonType) putExtra(EXTRA_TOGGLED_WIDGET_ID, appWidgetId) - }, FLAG_UPDATE_CURRENT) + }, FLAG_UPDATE_CURRENT + ) } private suspend fun getStudent(studentId: Long, appWidgetId: Int) = try { @@ -208,4 +246,29 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { } null } + + private fun Context.createAvatarBitmap(student: Student): Bitmap { + val avatarColor = if (student.avatarColor == -2937041L) { + getCompatColor(R.color.colorPrimaryLight).toLong() + } else { + student.avatarColor + } + val avatarDrawable = createNameInitialsDrawable(student.nickOrName, avatarColor, 0.5f) + + val avatarBitmap = + if (avatarDrawable.intrinsicWidth <= 0 || avatarDrawable.intrinsicHeight <= 0) { + Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + } else { + Bitmap.createBitmap( + avatarDrawable.intrinsicWidth, + avatarDrawable.intrinsicHeight, + Bitmap.Config.ARGB_8888 + ) + } + + val canvas = Canvas(avatarBitmap) + avatarDrawable.setBounds(0, 0, canvas.width, canvas.height) + avatarDrawable.draw(canvas) + return avatarBitmap + } } From 8733e7782f5d87e8ae8525cb51644d04ac3a68ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sun, 21 Mar 2021 22:37:34 +0100 Subject: [PATCH 08/23] Fix colorPrimary and class name in widget account manager (#1241) --- .../ui/base/WidgetConfigureAdapter.kt | 14 +++++++++----- .../ui/modules/account/AccountAdapter.kt | 7 +++---- .../LuckyNumberWidgetConfigureActivity.kt | 9 ++++++--- .../LuckyNumberWidgetConfigurePresenter.kt | 9 +++++---- .../LuckyNumberWidgetConfigureView.kt | 4 ++-- .../TimetableWidgetConfigureActivity.kt | 18 +++++++++++++----- .../TimetableWidgetConfigurePresenter.kt | 15 ++++++++++----- .../TimetableWidgetConfigureView.kt | 4 ++-- app/src/main/res/values-night/styles.xml | 8 ++++++++ app/src/main/res/values/styles.xml | 2 +- 10 files changed, 59 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt index 99440f83..a43aaffb 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt @@ -7,6 +7,7 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ItemAccountBinding import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.getThemeAttrColor @@ -16,7 +17,9 @@ import javax.inject.Inject class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter() { - var items = emptyList>() + var items = emptyList() + + var selectedId = -1L var onClickListener: (Student) -> Unit = {} @@ -28,12 +31,13 @@ class WidgetConfigureAdapter @Inject constructor() : @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val (student, isCurrent) = items[position] + val (student, semesters) = items[position] + val semester = semesters.maxByOrNull { it.semesterId } val context = holder.binding.root.context val checkBackgroundColor = context.getThemeAttrColor(R.attr.colorSurface) val avatar = context.createNameInitialsDrawable(student.nickOrName, student.avatarColor) val isDuplicatedStudent = items.filter { - val studentToCompare = it.first + val studentToCompare = it.student studentToCompare.studentId == student.studentId && studentToCompare.schoolSymbol == student.schoolSymbol @@ -41,7 +45,7 @@ class WidgetConfigureAdapter @Inject constructor() : }.size > 1 with(holder.binding) { - accountItemName.text = "${student.nickOrName} ${student.className}" + accountItemName.text = "${student.nickOrName} ${semester?.diaryName.orEmpty()}" accountItemSchool.text = student.schoolName accountItemImage.setImageDrawable(avatar) @@ -51,7 +55,7 @@ class WidgetConfigureAdapter @Inject constructor() : } with(accountItemCheck) { - isVisible = isCurrent + isVisible = student.id == selectedId borderColor = checkBackgroundColor circleColor = checkBackgroundColor } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt index 227f0661..523fbbd7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt @@ -74,9 +74,8 @@ class AccountAdapter @Inject constructor() : RecyclerView.Adapter 1 && isAccountQuickDialogMode with(binding) { - accountItemName.text = "${student.nickOrName} ${diary?.diaryName.orEmpty()}" + accountItemName.text = "${student.nickOrName} ${semester?.diaryName.orEmpty()}" accountItemSchool.text = studentWithSemesters.student.schoolName accountItemImage.setImageDrawable(avatar) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt index 692615d9..024beff8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt @@ -11,7 +11,7 @@ import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.WidgetConfigureAdapter @@ -38,7 +38,9 @@ class LuckyNumberWidgetConfigureActivity : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setResult(RESULT_CANCELED) - setContentView(ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root) + setContentView( + ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root + ) intent.extras.let { presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID)) @@ -70,8 +72,9 @@ class LuckyNumberWidgetConfigureActivity : .show() } - override fun updateData(data: List>) { + override fun updateData(data: List, selectedStudentId: Long) { with(configureAdapter) { + selectedId = selectedStudentId items = data notifyDataSetChanged() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt index f4041e9e..5b6af69a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt @@ -51,16 +51,17 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor( when (it.status) { Status.LOADING -> Timber.d("Lucky number widget configure students data load") Status.SUCCESS -> { - val widgetId = appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } + val selectedStudentId = appWidgetId?.let { id -> + sharedPref.getLong(getStudentWidgetKey(id), 0) + } ?: -1 + when { it.data!!.isEmpty() -> view?.openLoginView() it.data.size == 1 -> { selectedStudent = it.data.single().student view?.showThemeDialog() } - else -> view?.updateData(it.data.map { entity -> - entity.student to (entity.student.id == widgetId) - }) + else -> view?.updateData(it.data, selectedStudentId) } } Status.ERROR -> errorHandler.dispatch(it.error!!) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt index c8c348ed..b4556f7e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget -import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView interface LuckyNumberWidgetConfigureView : BaseView { @@ -9,7 +9,7 @@ interface LuckyNumberWidgetConfigureView : BaseView { fun showThemeDialog() - fun updateData(data: List>) + fun updateData(data: List, selectedStudentId: Long) fun updateLuckyNumberWidget(widgetId: Int) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt index 23d1f27a..a27dba88 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt @@ -12,7 +12,7 @@ import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.WidgetConfigureAdapter @@ -37,13 +37,19 @@ class TimetableWidgetConfigureActivity : private var dialog: AlertDialog? = null - override public fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setResult(RESULT_CANCELED) - setContentView(ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root) + setContentView( + ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root + ) intent.extras.let { - presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID), it?.getBoolean(EXTRA_FROM_PROVIDER)) + presenter.onAttachView( + this, + it?.getInt(EXTRA_APPWIDGET_ID), + it?.getBoolean(EXTRA_FROM_PROVIDER) + ) } } @@ -61,6 +67,7 @@ class TimetableWidgetConfigureActivity : getString(R.string.widget_timetable_theme_light), getString(R.string.widget_timetable_theme_dark) ) + if (appInfo.systemVersion >= Build.VERSION_CODES.Q) items += getString(R.string.widget_timetable_theme_system) dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher) @@ -72,8 +79,9 @@ class TimetableWidgetConfigureActivity : .show() } - override fun updateData(data: List>) { + override fun updateData(data: List, selectedStudentId: Long) { with(configureAdapter) { + selectedId = selectedStudentId items = data notifyDataSetChanged() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt index 67805fe0..2a40c8e4 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt @@ -25,7 +25,11 @@ class TimetableWidgetConfigurePresenter @Inject constructor( private var selectedStudent: Student? = null - fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) { + fun onAttachView( + view: TimetableWidgetConfigureView, + appWidgetId: Int?, + isFromProvider: Boolean? + ) { super.onAttachView(view) this.appWidgetId = appWidgetId this.isFromProvider = isFromProvider ?: false @@ -56,16 +60,17 @@ class TimetableWidgetConfigurePresenter @Inject constructor( when (it.status) { Status.LOADING -> Timber.d("Timetable widget configure students data load") Status.SUCCESS -> { - val widgetId = appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } + val selectedStudentId = appWidgetId?.let { id -> + sharedPref.getLong(getStudentWidgetKey(id), 0) + } ?: -1 + when { it.data!!.isEmpty() -> view?.openLoginView() it.data.size == 1 && !isFromProvider -> { selectedStudent = it.data.single().student view?.showThemeDialog() } - else -> view?.updateData(it.data.map { entity -> - entity.student to (entity.student.id == widgetId) - }) + else -> view?.updateData(it.data, selectedStudentId) } } Status.ERROR -> errorHandler.dispatch(it.error!!) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt index 056225ab..accdc28d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt @@ -1,13 +1,13 @@ package io.github.wulkanowy.ui.modules.timetablewidget -import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView interface TimetableWidgetConfigureView : BaseView { fun initView() - fun updateData(data: List>) + fun updateData(data: List, selectedStudentId: Long) fun updateTimetableWidget(widgetId: Int) diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index b218fbc8..68a9fa2f 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -49,4 +49,12 @@ ?colorSurface @android:color/black + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index fc7ffb77..297a4f28 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -26,7 +26,7 @@ @drawable/layer_splash_background -