diff --git a/README.md b/README.md index bcb0937b1..bbc36ab65 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica * powiadomienia np. o nowej ocenie * obsługa wielu kont wraz z możliwością zmiany nazwy ucznia * ciemny i czarny (AMOLED) motyw -* tryb offilne +* tryb offline * brak reklam ## Pobierz diff --git a/app/build.gradle b/app/build.gradle index b8b6f0162..80496ff1e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,8 +20,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 30 - versionCode 88 - versionName "1.1.2" + versionCode 89 + versionName "1.1.3" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -137,20 +137,20 @@ play { serviceAccountCredentials = file('key.p12') defaultToAppBundles = false track = 'production' - updatePriority = 5 + updatePriority = 3 } ext { work_manager = "2.5.0" work_hilt = "1.0.0-beta01" - room = "2.3.0-beta03" + room = "2.3.0-rc01" chucker = "3.4.0" - mockk = "1.10.6" + mockk = "1.11.0" moshi = "1.11.0" } dependencies { - implementation "io.github.wulkanowy:sdk:1.1.2" + implementation "io.github.wulkanowy:sdk:1.1.3" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' @@ -158,11 +158,11 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3' implementation "androidx.core:core-ktx:1.3.2" - implementation "androidx.activity:activity-ktx:1.2.1" + implementation "androidx.activity:activity-ktx:1.2.2" implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat-resources:1.2.0" - implementation "androidx.fragment:fragment-ktx:1.3.1" - implementation "androidx.annotation:annotation:1.1.0" + implementation "androidx.fragment:fragment-ktx:1.3.2" + implementation "androidx.annotation:annotation:1.2.0" implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.preference:preference-ktx:1.1.1" @@ -179,7 +179,7 @@ dependencies { implementation "androidx.work:work-runtime-ktx:$work_manager" playImplementation "androidx.work:work-gcm:$work_manager" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.0" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-ktx:$room" @@ -208,15 +208,12 @@ 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' - 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' + hmsImplementation 'com.huawei.hms:hianalytics:5.2.0.301' + hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.5.1.200' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt index 943f3f0cc..c2787ac3b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt @@ -9,6 +9,6 @@ import javax.inject.Singleton @Dao interface RecipientDao : BaseDao { - @Query("SELECT * FROM Recipients WHERE student_id = :userLoginId AND unit_id = :unitId AND role = :role") - suspend fun loadAll(userLoginId: Int, unitId: Int, role: Int): List + @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND unit_id = :unitId AND role = :role") + suspend fun loadAll(studentId: Int, unitId: Int, role: Int): List } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt index b1f1f3530..3021da72d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt @@ -9,7 +9,7 @@ import java.io.Serializable data class Recipient( @ColumnInfo(name = "student_id") - val userLoginId: Int, + val studentId: Int, @ColumnInfo(name = "real_id") val realId: String, diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt index 9996f6800..80bddaab1 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt @@ -5,7 +5,7 @@ import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient fun List.mapToEntities(userLoginId: Int) = map { Recipient( - userLoginId = userLoginId, + studentId = userLoginId, realId = it.id, realName = it.name, name = it.shortName, diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt index 71ea7099d..6a21d59fc 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt @@ -6,7 +6,7 @@ import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit fun List.mapToEntities(student: Student) = map { ReportingUnit( - studentId = student.studentId, + studentId = student.id.toInt(), unitId = it.id, roles = it.roles, senderId = it.senderId, 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 11adbd0f7..5bd1f3c12 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/data/repositories/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt index 24ab5f0c9..975a30a20 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt @@ -19,22 +19,22 @@ class RecipientRepository @Inject constructor( ) { suspend fun refreshRecipients(student: Student, unit: ReportingUnit, role: Int) { - val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.senderId) - val old = recipientDb.loadAll(unit.senderId, unit.unitId, role) + val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.studentId) + val old = recipientDb.loadAll(unit.studentId, unit.unitId, role) recipientDb.deleteAll(old uniqueSubtract new) recipientDb.insertAll(new uniqueSubtract old) } suspend fun getRecipients(student: Student, unit: ReportingUnit, role: Int): List { - return recipientDb.loadAll(unit.senderId, unit.unitId, role).ifEmpty { + return recipientDb.loadAll(unit.studentId, unit.unitId, role).ifEmpty { refreshRecipients(student, unit, role) - recipientDb.loadAll(unit.senderId, unit.unitId, role) + recipientDb.loadAll(unit.studentId, unit.unitId, role) } } suspend fun getMessageRecipients(student: Student, message: Message): List { - return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.userLoginId) + return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.studentId) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt index 792e66b5e..b9caf978b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt @@ -18,25 +18,25 @@ class ReportingUnitRepository @Inject constructor( suspend fun refreshReportingUnits(student: Student) { val new = sdk.init(student).getReportingUnits().mapToEntities(student) - val old = reportingUnitDb.load(student.studentId) + val old = reportingUnitDb.load(student.id.toInt()) reportingUnitDb.deleteAll(old.uniqueSubtract(new)) reportingUnitDb.insertAll(new.uniqueSubtract(old)) } suspend fun getReportingUnits(student: Student): List { - return reportingUnitDb.load(student.studentId).ifEmpty { + return reportingUnitDb.load(student.id.toInt()).ifEmpty { refreshReportingUnits(student) - reportingUnitDb.load(student.studentId) + reportingUnitDb.load(student.id.toInt()) } } suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? { - return reportingUnitDb.loadOne(student.studentId, unitId) ?: run { + return reportingUnitDb.loadOne(student.id.toInt(), unitId) ?: run { refreshReportingUnits(student) - return reportingUnitDb.loadOne(student.studentId, unitId) + return reportingUnitDb.loadOne(student.id.toInt(), unitId) } } } 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 8e6130fbf..a43aaffb7 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,20 +1,25 @@ 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.data.db.entities.StudentWithSemesters 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>() + var items = emptyList() + + var selectedId = -1L var onClickListener: (Student) -> Unit = {} @@ -26,17 +31,33 @@ class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter 1 with(holder.binding) { - accountItemName.text = "${student.nickOrName} ${student.className}" + accountItemName.text = "${student.nickOrName} ${semester?.diaryName.orEmpty()}" 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 = student.id == selectedId + borderColor = checkBackgroundColor + circleColor = checkBackgroundColor } root.setOnClickListener { onClickListener(student) } 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 227f06613..523fbbd79 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/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt index 70b468990..99dcf1bb3 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt @@ -162,7 +162,7 @@ class LoginFormPresenter @Inject constructor( view?.setErrorEmailRequired() isCorrect = false } - if ("@" in login && "login" !in host && "email" !in host) { + if ("@" in login && "||" !in login && "login" !in host && "email" !in host) { val emailHost = login.substringAfter("@") val emailDomain = URL(host).host if (emailHost != emailDomain) { 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 f0c9652fb..2e2f9f5ce 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/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt index 692615d98..024beff85 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt @@ -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 f4041e9e4..5b6af69ac 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 c8c348ed3..b4556f7ef 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt @@ -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/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 5fda72106..37c6c6e75 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 @@ -324,9 +324,7 @@ class MainActivity : BaseActivity(), MainVie } override fun showAccountPicker(studentWithSemesters: List) { - if (supportFragmentManager.isStateSaved) return - - navController.showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters)) + showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters)) } override fun showActionBarElevation(show: Boolean) { @@ -342,9 +340,18 @@ class MainActivity : BaseActivity(), MainVie (navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentChanged() } + @Suppress("DEPRECATION") fun showDialogFragment(dialog: DialogFragment) { if (supportFragmentManager.isStateSaved) return + //Deprecated method is used here to avoid fragnav bug + if (navController.currentDialogFrag?.fragmentManager == null) { + FragNavController::class.java.getDeclaredField("mCurrentDialogFrag").apply { + isAccessible = true + set(navController, null) + } + } + navController.showDialogFragment(dialog) } 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 80138175d..2b96a9a0c 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 795889171..4590d91a5 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 a5aa14091..c9c5fe9a4 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/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt index 23d1f27ab..a27dba882 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 67805fe0b..2a40c8e4a 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 056225ab5..accdc28dc 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/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt index 1d63f0943..071a2d178 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 + } } 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 8ab595f93..8b264d441 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,6 +1,11 @@ -Wersja 1.1.2 +Wersja 1.1.3 -- naprawiliśmy wyświetlanie planu lekcji i lekcji dodatkowych -- naprawiliśmy kilka rzadkich problemów ze stabilnością +Oprócz tego naprawiliśmy: +- rzadkie problemy ze stabilnością przy logowaniu i w innych miejscach +- brakujące awatary przy zmianie konta z poziomu widżetu +- wysyłanie wiadomości gdy w aplikacji jest zalogowany jednocześnie uczeń i rodzic + +Ta wersja jest ostatnią, która będzie działać na starszych urządzeniach z Androidem 4. +Od tej pory do końca roku bedziemy dla nich udostępniać wyłącznie krytyczne poprawki błędów Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases diff --git a/app/src/main/res/layout/fragment_login_recover.xml b/app/src/main/res/layout/fragment_login_recover.xml index 629ed54de..4277155bc 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"> - diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 8c8ad7291..a2118955a 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -506,6 +506,10 @@ Push upozornění Nadcházející lekce Ladění + + Konec podpory + Ukončujeme podporu pro vaše zařízení. V Wulkanovým už pro něj nebudou žádné nové funkce. Kritické opravy však budeme vydávat až do konce roku 2021, abyste měli čas přejít na novější model + Nezobrazovat znovu Černý Červený diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 391fdd21f..2880996a8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -176,7 +176,7 @@ Abwesenheitsgrund (optional) Senden - Absence excuse request sent successfully! + Abwesenheitsentschuldigungsanfrage erfolgreich gesendet! Sie müssen mindestens eine Abwesenheit auswählen! Verzeihung @@ -466,6 +466,10 @@ Push-Benachrichtigungen Bevorstehende Lektionen Debuggen + + Ende der Unterstützung + Wir beenden die Unterstützung für dein Gerät. Es werden keine neuen Funktionen mehr in Wulkanowy erscheinen. Allerdings werden wir bis Ende 2021 kritische Patches veröffentlichen, so dass du Zeit hast, zu einem neueren Modell zu wechseln + Nicht mehr fragen Schwarz Rot diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 569df4bc8..424cc2523 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -1,7 +1,7 @@ - Login + Prisijungti Wulkanowy Laipsnis Attendance @@ -506,6 +506,10 @@ Push notifications Upcoming lessons 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 diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index b218fbc87..68a9fa2fe 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-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 0d4395838..fb538fadb 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -506,6 +506,10 @@ Powiadomienia push Nadchodzące lekcje Debugowanie + + Koniec wsparcia + Kończymy wsparcie dla Twojego urządzenia. Nie pojawią się już dla niego żadne nowe funkcje w Wulkanowym. Będziemy jednak wypuszczać krytyczne poprawki do końca 2021 roku, abyś miał czas na przeniesienie się na nowszy model + Nie pokazuj ponownie Czarny Czerwony diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index b614ac9e9..665d9dc46 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -192,7 +192,7 @@ Причина отсутствия (необязательно) Послать - Absence excuse request sent successfully! + Запрос на освобождение оправдания успешно отправлен! Выберите хотя-бы одно отсутствие Изменить статус @@ -506,6 +506,10 @@ Показывать push-уведомления Будущие уроки Дебаг + + Конец поддержки + Поддержка заканчивается на вашем устройстве. В Wulkanowy больше не появятся новые возможности. Однако до конца 2021 года мы выпустим критические патчи, чтобы у вас было время перейти на новую модель + Не показывать снова Чёрный Красный diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 601bd880e..8a5b8d242 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -506,6 +506,10 @@ Push upozornenia Nadchádzajúce lekcie Ladenie + + Koniec podpory + Ukončujeme podporu pre vaše zariadenie. V Wulkanovým už pre neho nebudú žiadne nové funkcie. Kritické opravy však budeme vydávať až do konca roka 2021, aby ste mali čas prejsť na novší model + Nezobrazovať znovu Čierny Červený diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 61a6bb3f2..2e0b89da6 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -46,7 +46,7 @@ Минув термін дії токену Недійсна адреса електронної пошти Використовуйте призначений логін замість електронної пошти - Використовуйте призначений логін або електронну адресу в @% 1 $ s + Використовуйте призначений логін або електронну адресу в @%1$s Неправильний симбвол Студента не знайдено Перевірте символ та обраний варіант реєстру UONET+ Обов\'язкове поле @@ -192,7 +192,7 @@ Причина відсутності (необов’язково) Надіслати - Absence excuse request sent successfully! + Запит на виправдання відсутності успішно надіслано! Оберіть хоча б одну відсутність Змінити статус @@ -506,6 +506,10 @@ Показувати push-повідомлення Наступні уроки Дебаг + + Кінець підтримки + Ми завершуємо підтримку вашого пристрою. Більше нових функцій не з\'явиться у Wulkanowy. Однак ми виробляємо критичні патчі до кінця 2021, тому у вас буде час перейти на новішу модель + Не показувати знову Чорний Червоний diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db5ed7b49..c4109d2b8 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/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index fc7ffb77f..297a4f288 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 -