1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 06:59:10 -05:00

Merge branch 'release/1.1.3'

This commit is contained in:
Mikołaj Pich 2021-03-28 20:13:37 +02:00
commit 3c48264539
39 changed files with 352 additions and 121 deletions

View File

@ -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

View File

@ -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"

View File

@ -9,6 +9,6 @@ import javax.inject.Singleton
@Dao
interface RecipientDao : BaseDao<Recipient> {
@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<Recipient>
@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<Recipient>
}

View File

@ -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,

View File

@ -5,7 +5,7 @@ import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
fun List<SdkRecipient>.mapToEntities(userLoginId: Int) = map {
Recipient(
userLoginId = userLoginId,
studentId = userLoginId,
realId = it.id,
realName = it.name,
name = it.shortName,

View File

@ -6,7 +6,7 @@ import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit
fun List<SdkReportingUnit>.mapToEntities(student: Student) = map {
ReportingUnit(
studentId = student.studentId,
studentId = student.id.toInt(),
unitId = it.id,
roles = it.roles,
senderId = it.senderId,

View File

@ -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) =

View File

@ -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<Recipient> {
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<Recipient> {
return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.userLoginId)
return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.studentId)
}
}

View File

@ -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<ReportingUnit> {
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)
}
}
}

View File

@ -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<WidgetConfigureAdapter.ItemViewHolder>() {
class WidgetConfigureAdapter @Inject constructor() :
RecyclerView.Adapter<WidgetConfigureAdapter.ItemViewHolder>() {
var items = emptyList<Pair<Student, Boolean>>()
var items = emptyList<StudentWithSemesters>()
var selectedId = -1L
var onClickListener: (Student) -> Unit = {}
@ -26,17 +31,33 @@ class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter<Widget
@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.student
studentToCompare.studentId == student.studentId
&& studentToCompare.schoolSymbol == student.schoolSymbol
&& studentToCompare.symbol == student.symbol
}.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)
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) }

View File

@ -74,9 +74,8 @@ class AccountAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView.V
studentWithSemesters: StudentWithSemesters
) {
val context = binding.root.context
val student = studentWithSemesters.student
val semesters = studentWithSemesters.semesters
val diary = semesters.maxByOrNull { it.semesterId }
val (student, semesters) = studentWithSemesters
val semester = semesters.maxByOrNull { it.semesterId }
val avatar = context.createNameInitialsDrawable(student.nickOrName, student.avatarColor)
val checkBackgroundColor =
context.getThemeAttrColor(if (isAccountQuickDialogMode) R.attr.colorBackgroundFloating else R.attr.colorSurface)
@ -90,7 +89,7 @@ class AccountAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView.V
}.size > 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)

View File

@ -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) {

View File

@ -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<String>
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
}
}

View File

@ -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<Pair<Student, Boolean>>) {
override fun updateData(data: List<StudentWithSemesters>, selectedStudentId: Long) {
with(configureAdapter) {
selectedId = selectedStudentId
items = data
notifyDataSetChanged()
}

View File

@ -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!!)

View File

@ -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<Pair<Student, Boolean>>)
fun updateData(data: List<StudentWithSemesters>, selectedStudentId: Long)
fun updateLuckyNumberWidget(widgetId: Int)

View File

@ -324,9 +324,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
}
override fun showAccountPicker(studentWithSemesters: List<StudentWithSemesters>) {
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<MainPresenter, ActivityMainBinding>(), 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)
}

View File

@ -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<SplashPresenter, ViewBinding>(), SplashView {
@Inject
lateinit var appInfo: AppInfo
@Inject
override lateinit var presenter: SplashPresenter
@ -40,4 +46,14 @@ class SplashActivity : BaseActivity<SplashPresenter, ViewBinding>(), 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()
}
}

View File

@ -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<SplashView>(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
}
}

View File

@ -9,4 +9,6 @@ interface SplashView : BaseView {
fun openMainView()
fun openExternalUrlAndFinish(url: String)
fun showKitkatView()
}

View File

@ -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<Pair<Student, Boolean>>) {
override fun updateData(data: List<StudentWithSemesters>, selectedStudentId: Long) {
with(configureAdapter) {
selectedId = selectedStudentId
items = data
notifyDataSetChanged()
}

View File

@ -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!!)

View File

@ -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<Pair<Student, Boolean>>)
fun updateData(data: List<StudentWithSemesters>, selectedStudentId: Long)
fun updateTimetableWidget(widgetId: Int)

View File

@ -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
}
}

View File

@ -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

View File

@ -26,7 +26,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:visibility="visible">
android:visibility="gone">
<TextView
android:id="@+id/loginFormHeader"
@ -85,9 +85,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="emailAddress"
android:imeOptions="actionDone"
android:inputType="textEmailAddress"
android:maxLines="1"
android:imeOptions="actionDone"
tools:targetApi="o" />
<requestFocus />
@ -156,7 +156,7 @@
android:orientation="vertical"
android:visibility="invisible"
tools:ignore="UseCompoundDrawables"
tools:visibility="invisible">
tools:visibility="visible">
<ImageView
android:layout_width="100dp"
@ -175,12 +175,10 @@
android:text="@string/error_unknown"
android:textSize="20sp" />
<LinearLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:orientation="horizontal">
android:layout_marginTop="16dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/loginRecoverErrorDetails"
@ -189,14 +187,21 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/all_details" />
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" />
<com.google.android.material.button.MaterialButton
android:id="@+id/loginRecoverErrorRetry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/all_retry" />
</LinearLayout>
android:text="@string/all_retry"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/loginRecoverErrorDetails"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<androidx.core.widget.NestedScrollView
@ -206,7 +211,7 @@
android:fillViewport="true"
android:scrollbars="none"
android:visibility="invisible"
tools:visibility="invisible">
tools:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
@ -253,6 +258,5 @@
android:layout_marginBottom="30dp"
android:text="@android:string/ok" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>

View File

@ -506,6 +506,10 @@
<string name="channel_push">Push upozornění</string>
<string name="channel_upcoming_lessons">Nadcházející lekce</string>
<string name="channel_debug">Ladění</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">Konec podpory</string>
<string name="drop_kitkat_content">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</string>
<string name="drop_kitkat_again">Nezobrazovat znovu</string>
<!--Colors-->
<string name="all_black">Černý</string>
<string name="all_red">Červený</string>

View File

@ -176,7 +176,7 @@
</plurals>
<string name="attendance_excuse_dialog_reason">Abwesenheitsgrund (optional)</string>
<string name="attendance_excuse_dialog_submit">Senden</string>
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
<string name="attendance_excuse_success">Abwesenheitsentschuldigungsanfrage erfolgreich gesendet!</string>
<string name="attendance_excuse_no_selection">Sie müssen mindestens eine Abwesenheit auswählen!</string>
<string name="attendance_excuse_title">Verzeihung</string>
<!--Attendance summary-->
@ -466,6 +466,10 @@
<string name="channel_push">Push-Benachrichtigungen</string>
<string name="channel_upcoming_lessons">Bevorstehende Lektionen</string>
<string name="channel_debug">Debuggen</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">Ende der Unterstützung</string>
<string name="drop_kitkat_content">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</string>
<string name="drop_kitkat_again">Nicht mehr fragen</string>
<!--Colors-->
<string name="all_black">Schwarz</string>
<string name="all_red">Rot</string>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--Activity/Fragment title-->
<string name="login_title">Login</string>
<string name="login_title">Prisijungti</string>
<string name="main_title">Wulkanowy</string>
<string name="grade_title">Laipsnis</string>
<string name="attendance_title">Attendance</string>
@ -506,6 +506,10 @@
<string name="channel_push">Push notifications</string>
<string name="channel_upcoming_lessons">Upcoming lessons</string>
<string name="channel_debug">Debug</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">End of support</string>
<string name="drop_kitkat_content">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</string>
<string name="drop_kitkat_again">Don\'t show again</string>
<!--Colors-->
<string name="all_black">Black</string>
<string name="all_red">Red</string>

View File

@ -49,4 +49,12 @@
<item name="android:navigationBarColor" tools:targetApi="lollipop">?colorSurface</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/black</item>
</style>
<style name="WulkanowyTheme.WidgetAccountSwitcher" parent="Theme.MaterialComponents.Dialog">
<item name="colorPrimary">@color/colorPrimaryLight</item>
<item name="colorSecondary">@color/colorPrimaryLight</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:textColor">?android:textColorPrimary</item>
</style>
</resources>

View File

@ -506,6 +506,10 @@
<string name="channel_push">Powiadomienia push</string>
<string name="channel_upcoming_lessons">Nadchodzące lekcje</string>
<string name="channel_debug">Debugowanie</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">Koniec wsparcia</string>
<string name="drop_kitkat_content">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</string>
<string name="drop_kitkat_again">Nie pokazuj ponownie</string>
<!--Colors-->
<string name="all_black">Czarny</string>
<string name="all_red">Czerwony</string>

View File

@ -192,7 +192,7 @@
</plurals>
<string name="attendance_excuse_dialog_reason">Причина отсутствия (необязательно)</string>
<string name="attendance_excuse_dialog_submit">Послать</string>
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
<string name="attendance_excuse_success">Запрос на освобождение оправдания успешно отправлен!</string>
<string name="attendance_excuse_no_selection">Выберите хотя-бы одно отсутствие</string>
<string name="attendance_excuse_title">Изменить статус</string>
<!--Attendance summary-->
@ -506,6 +506,10 @@
<string name="channel_push">Показывать push-уведомления</string>
<string name="channel_upcoming_lessons">Будущие уроки</string>
<string name="channel_debug">Дебаг</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">Конец поддержки</string>
<string name="drop_kitkat_content">Поддержка заканчивается на вашем устройстве. В Wulkanowy больше не появятся новые возможности. Однако до конца 2021 года мы выпустим критические патчи, чтобы у вас было время перейти на новую модель</string>
<string name="drop_kitkat_again">Не показывать снова</string>
<!--Colors-->
<string name="all_black">Чёрный</string>
<string name="all_red">Красный</string>

View File

@ -506,6 +506,10 @@
<string name="channel_push">Push upozornenia</string>
<string name="channel_upcoming_lessons">Nadchádzajúce lekcie</string>
<string name="channel_debug">Ladenie</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">Koniec podpory</string>
<string name="drop_kitkat_content">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</string>
<string name="drop_kitkat_again">Nezobrazovať znovu</string>
<!--Colors-->
<string name="all_black">Čierny</string>
<string name="all_red">Červený</string>

View File

@ -192,7 +192,7 @@
</plurals>
<string name="attendance_excuse_dialog_reason">Причина відсутності (необов’язково)</string>
<string name="attendance_excuse_dialog_submit">Надіслати</string>
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
<string name="attendance_excuse_success">Запит на виправдання відсутності успішно надіслано!</string>
<string name="attendance_excuse_no_selection">Оберіть хоча б одну відсутність</string>
<string name="attendance_excuse_title">Змінити статус</string>
<!--Attendance summary-->
@ -506,6 +506,10 @@
<string name="channel_push">Показувати push-повідомлення</string>
<string name="channel_upcoming_lessons">Наступні уроки</string>
<string name="channel_debug">Дебаг</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">Кінець підтримки</string>
<string name="drop_kitkat_content">Ми завершуємо підтримку вашого пристрою. Більше нових функцій не з\'явиться у Wulkanowy. Однак ми виробляємо критичні патчі до кінця 2021, тому у вас буде час перейти на новішу модель</string>
<string name="drop_kitkat_again">Не показувати знову</string>
<!--Colors-->
<string name="all_black">Чорний</string>
<string name="all_red">Червоний</string>

View File

@ -541,6 +541,12 @@
<string name="channel_debug">Debug</string>
<!--Drop kitkat alert dialog strings-->
<string name="drop_kitkat_title">End of support</string>
<string name="drop_kitkat_content">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</string>
<string name="drop_kitkat_again">Don\'t show again</string>
<!--Colors-->
<string name="all_black">Black</string>
<string name="all_red">Red</string>
@ -554,6 +560,7 @@
<string name="all_copied">Copied</string>
<string name="all_undo">Undo</string>
<!--Update helper-->
<string name="update_download_started">Download of updates has started…</string>
<string name="update_download_success">An update has just been downloaded.</string>

View File

@ -26,7 +26,7 @@
<item name="android:windowBackground">@drawable/layer_splash_background</item>
</style>
<style name="WulkanowyTheme.WidgetAccountSwitcher" parent="Theme.MaterialComponents.DayNight.Dialog">
<style name="WulkanowyTheme.WidgetAccountSwitcher" parent="Theme.MaterialComponents.Light.Dialog">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorSecondary">@color/colorPrimary</item>
<item name="windowActionBar">false</item>

View File

@ -54,7 +54,7 @@ class RecipientLocalTest {
coEvery { recipientDb.deleteAll(any()) } just Runs
// execute
val res = runBlocking { recipientRepository.getRecipients(student, ReportingUnit(1, 123, "", 4, "", listOf()), 7) }
val res = runBlocking { recipientRepository.getRecipients(student, ReportingUnit(4, 123, "", 4, "", listOf()), 7) }
// verify
assertEquals(3, res.size)
@ -73,7 +73,7 @@ class RecipientLocalTest {
coEvery { recipientDb.deleteAll(any()) } just Runs
// execute
val res = runBlocking { recipientRepository.getRecipients(student, ReportingUnit(1, 123, "", 4, "", listOf()), 7) }
val res = runBlocking { recipientRepository.getRecipients(student, ReportingUnit(4, 123, "", 4, "", listOf()), 7) }
// verify
assertEquals(3, res.size)

View File

@ -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() }
}

View File

@ -1,6 +1,6 @@
buildscript {
ext {
kotlin_version = '1.4.31'
kotlin_version = '1.4.32'
about_libraries = '8.8.4'
hilt_version = "2.33-beta"
}
@ -13,10 +13,10 @@ 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'
classpath 'com.huawei.agconnect:agcp:1.5.1.200'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.1'
classpath "com.github.triplet.gradle:play-publisher:2.8.0"
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.1.1"