diff --git a/app/build.gradle b/app/build.gradle
index 62f4c95c..96bb1176 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -172,10 +172,10 @@ dependencies {
kapt "eu.szkolny.selective-dao:codegen:27f8f3f194"
// Iconics & related
- implementation "com.mikepenz:iconics-core:5.3.0-b01"
- implementation "com.mikepenz:iconics-views:5.3.0-b01"
+ implementation "com.mikepenz:iconics-core:5.3.1"
+ implementation "com.mikepenz:iconics-views:5.3.1"
implementation "com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar"
- implementation "eu.szkolny:szkolny-font:1.3"
+ implementation "eu.szkolny:szkolny-font:77e33acc2a"
// Other dependencies
implementation "cat.ereza:customactivityoncrash:2.3.0"
diff --git a/app/src/main/assets/pl-changelog.html b/app/src/main/assets/pl-changelog.html
index 99883f04..9d71f591 100644
--- a/app/src/main/assets/pl-changelog.html
+++ b/app/src/main/assets/pl-changelog.html
@@ -1,13 +1,6 @@
-
Wersja 4.9, 2021-09-11
+Wersja 4.10, 2021-09-22
- - Vulcan: naprawiono brakujące lekcje w planie. @Antoni-Czaplicki
- - Vulcan: naprawiono wysyłanie wiadomości. @Antoni-Czaplicki
- - Vulcan: naprawiono brak frekwencji.
- - Naprawiono eksportowanie planu lekcji oraz pobieranie załączników. @doteq
- - Mobidziennik: naprawiono możliwość pobierania przyszłego planu lekcji.
- - Mobidziennik: poprawiono brak nowych linii w wysłanej wiadomości.
- - Dodano ekran "Twórcy aplikacji" w Ustawieniach. @Pengwius
- - Zmieniono domyślne tło nagłówka menu. 😋
+ - Dodano wyświetlanie informacji o frekwencji w planie lekcji. @Antoni-Czaplicki
diff --git a/app/src/main/cpp/szkolny-signing.cpp b/app/src/main/cpp/szkolny-signing.cpp
index 9925362d..d3f11d9d 100644
--- a/app/src/main/cpp/szkolny-signing.cpp
+++ b/app/src/main/cpp/szkolny-signing.cpp
@@ -9,7 +9,7 @@
/*secret password - removed for source code publication*/
static toys AES_IV[16] = {
- 0x36, 0x60, 0xb0, 0x4b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ 0xda, 0x2a, 0x5f, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/App.kt b/app/src/main/java/pl/szczodrzynski/edziennik/App.kt
index 71e6c7e6..b3ec1cc3 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/App.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/App.kt
@@ -71,6 +71,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
val permissionManager by lazy { PermissionManager(this) }
val attendanceManager by lazy { AttendanceManager(this) }
val buildManager by lazy { BuildManager(this) }
+ val availabilityManager by lazy { AvailabilityManager(this) }
val db
get() = App.db
@@ -174,8 +175,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
App.config = Config(App.db)
App.profile = Profile(0, 0, 0, "")
debugMode = BuildConfig.DEBUG
- devMode = config.debugMode || debugMode
- enableChucker = config.enableChucker || devMode
+ devMode = config.devMode ?: debugMode
+ enableChucker = config.enableChucker ?: devMode
if (!profileLoadById(config.lastProfileId)) {
db.profileDao().firstId?.let { profileLoadById(it) }
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt
index 2cd4f7b7..b7540b44 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt
@@ -85,6 +85,8 @@ import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushFragment
import pl.szczodrzynski.edziennik.utils.*
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.Utils.dpToPx
+import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager
+import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.NavTarget
import pl.szczodrzynski.navlib.*
@@ -634,45 +636,23 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
return
}
- app.profile.registerName?.let { registerName ->
- var status = app.config.sync.registerAvailability[registerName]
- if (status == null || status.nextCheckAt < currentTimeUnix()) {
- val api = SzkolnyApi(app)
- val result = withContext(Dispatchers.IO) {
- return@withContext api.runCatching({
- val availability = getRegisterAvailability()
- app.config.sync.registerAvailability = availability
- availability[registerName]
- }, onError = {
- if (it.toErrorCode() == ERROR_API_INVALID_SIGNATURE) {
- return@withContext false
- }
- return@withContext it
- })
- }
-
- when (result) {
- false -> {
- Toast.makeText(this@MainActivity, R.string.error_no_api_access, Toast.LENGTH_SHORT).show()
- return@let
- }
- is Throwable -> {
- errorSnackbar.addError(result.toApiError(TAG)).show()
- return
- }
- is RegisterAvailabilityStatus -> {
- status = result
- }
- }
- }
-
- if (status?.available != true || status.minVersionCode > BuildConfig.VERSION_CODE) {
+ val error = withContext(Dispatchers.IO) {
+ app.availabilityManager.check(app.profile)
+ }
+ when (error?.type) {
+ Type.NOT_AVAILABLE -> {
swipeRefreshLayout.isRefreshing = false
loadTarget(DRAWER_ITEM_HOME)
- if (status != null)
- RegisterUnavailableDialog(this, status)
+ RegisterUnavailableDialog(this, error.status!!)
return
}
+ Type.API_ERROR -> {
+ errorSnackbar.addError(error.apiError!!).show()
+ return
+ }
+ Type.NO_API_ACCESS -> {
+ Toast.makeText(this, R.string.error_no_api_access, Toast.LENGTH_SHORT).show()
+ }
}
swipeRefreshLayout.isRefreshing = true
@@ -699,10 +679,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onRegisterAvailabilityEvent(event: RegisterAvailabilityEvent) {
EventBus.getDefault().removeStickyEvent(event)
- app.profile.registerName?.let { registerName ->
- event.data[registerName]?.let {
- RegisterUnavailableDialog(this, it)
- }
+ val error = app.availabilityManager.check(app.profile, cacheOnly = true)
+ if (error != null) {
+ RegisterUnavailableDialog(this, error.status!!)
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt
index 0274912f..e29d93ad 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt
@@ -12,10 +12,7 @@ import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.BuildConfig
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
-import pl.szczodrzynski.edziennik.config.utils.ConfigMigration
-import pl.szczodrzynski.edziennik.config.utils.get
-import pl.szczodrzynski.edziennik.config.utils.set
-import pl.szczodrzynski.edziennik.config.utils.toHashMap
+import pl.szczodrzynski.edziennik.config.utils.*
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
import pl.szczodrzynski.edziennik.data.db.AppDb
import kotlin.coroutines.CoroutineContext
@@ -75,15 +72,15 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
get() { mPrivacyPolicyAccepted = mPrivacyPolicyAccepted ?: values.get("privacyPolicyAccepted", false); return mPrivacyPolicyAccepted ?: false }
set(value) { set("privacyPolicyAccepted", value); mPrivacyPolicyAccepted = value }
- private var mDebugMode: Boolean? = null
- var debugMode: Boolean
- get() { mDebugMode = mDebugMode ?: values.get("debugMode", false); return mDebugMode ?: false }
- set(value) { set("debugMode", value); mDebugMode = value }
+ private var mDevMode: Boolean? = null
+ var devMode: Boolean?
+ get() { mDevMode = mDevMode ?: values.getBooleanOrNull("debugMode"); return mDevMode }
+ set(value) { set("debugMode", value?.toString()); mDevMode = value }
private var mEnableChucker: Boolean? = null
- var enableChucker: Boolean
- get() { mEnableChucker = mEnableChucker ?: values.get("enableChucker", false); return mEnableChucker ?: false }
- set(value) { set("enableChucker", value); mEnableChucker = value }
+ var enableChucker: Boolean?
+ get() { mEnableChucker = mEnableChucker ?: values.getBooleanOrNull("enableChucker"); return mEnableChucker }
+ set(value) { set("enableChucker", value?.toString()); mEnableChucker = value }
private var mDevModePassword: String? = null
var devModePassword: String?
@@ -125,6 +122,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
get() { mApiInvalidCert = mApiInvalidCert ?: values["apiInvalidCert"]; return mApiInvalidCert }
set(value) { set("apiInvalidCert", value); mApiInvalidCert = value }
+ private var mApiAvailabilityCheck: Boolean? = null
+ var apiAvailabilityCheck: Boolean
+ get() { mApiAvailabilityCheck = mApiAvailabilityCheck ?: values.get("apiAvailabilityCheck", true); return mApiAvailabilityCheck ?: true }
+ set(value) { set("apiAvailabilityCheck", value); mApiAvailabilityCheck = value }
+
private var rawEntries: List = db.configDao().getAllNow()
private val profileConfigs: HashMap = hashMapOf()
init {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigExtensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigExtensions.kt
index c98cf832..94bb87e6 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigExtensions.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigExtensions.kt
@@ -59,6 +59,9 @@ fun HashMap.get(key: String, default: String?): String? {
fun HashMap.get(key: String, default: Boolean): Boolean {
return this[key]?.toBoolean() ?: default
}
+fun HashMap.getBooleanOrNull(key: String): Boolean? {
+ return this[key]?.toBooleanStrictOrNull()
+}
fun HashMap.get(key: String, default: Int): Int {
return this[key]?.toIntOrNull() ?: default
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt
index 1095f511..58dc35f7 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt
@@ -67,7 +67,7 @@ class ConfigMigration(app: App, config: Config) {
if (dataVersion < 3) {
update = null
privacyPolicyAccepted = false
- debugMode = false
+ devMode = null
devModePassword = null
appInstalledTime = 0L
appRateSnackbarTime = 0L
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt
index e3692c33..ab27dda9 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt
@@ -18,7 +18,6 @@ import pl.szczodrzynski.edziennik.data.api.events.RegisterAvailabilityEvent
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Profile
@@ -27,6 +26,7 @@ import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
+import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
companion object {
@@ -90,35 +90,21 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
return
}
- profile.registerName?.also { registerName ->
- var status = app.config.sync.registerAvailability[registerName]
- if (status == null || status.nextCheckAt < currentTimeUnix()) {
- val api = SzkolnyApi(app)
- api.runCatching({
- val availability = getRegisterAvailability()
- app.config.sync.registerAvailability = availability
- status = availability[registerName]
- }, onError = {
- val apiError = it.toApiError(TAG)
- if (apiError.errorCode == ERROR_API_INVALID_SIGNATURE) {
- return@also
- }
- taskCallback.onError(apiError)
- return
- })
- }
-
- if (status?.available != true
- || status?.minVersionCode ?: BuildConfig.VERSION_CODE > BuildConfig.VERSION_CODE) {
+ val error = app.availabilityManager.check(profile)
+ when (error?.type) {
+ Type.NOT_AVAILABLE -> {
if (EventBus.getDefault().hasSubscriberForEvent(RegisterAvailabilityEvent::class.java)) {
- EventBus.getDefault().postSticky(
- RegisterAvailabilityEvent(app.config.sync.registerAvailability)
- )
+ EventBus.getDefault().postSticky(RegisterAvailabilityEvent())
}
cancel()
taskCallback.onCompleted()
return
}
+ Type.API_ERROR -> {
+ taskCallback.onError(error.apiError!!)
+ return
+ }
+ else -> return@let
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt
index fe66c4b3..2a3531df 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt
@@ -4,8 +4,4 @@
package pl.szczodrzynski.edziennik.data.api.events
-import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
-
-data class RegisterAvailabilityEvent(
- val data: Map< String, RegisterAvailabilityStatus>
-)
+class RegisterAvailabilityEvent()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt
index 4c07bac8..2df7f141 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt
@@ -46,6 +46,6 @@ object Signing {
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
- return "$param1.MTIzNDU2Nzg5MDkdkClKMQ===.$param2".sha256()
+ return "$param1.MTIzNDU2Nzg5MDY8+Uq3So===.$param2".sha256()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt
index 3ffdc1b8..94be0c34 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt
@@ -64,6 +64,8 @@ abstract class AttendanceDao : BaseDao {
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE attendances.profileId = $profileId AND notified = 0 $ORDER_BY")
+ fun getAllByDateNow(profileId: Int, date: Date) =
+ getRawNow("$QUERY WHERE attendances.profileId = $profileId AND attendanceDate = '${date.stringY_m_d}' $ORDER_BY")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt
index b3586a79..9c2552a6 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt
@@ -140,7 +140,7 @@ open class Profile(
LOGIN_TYPE_MOBIDZIENNIK -> "mobidziennik"
LOGIN_TYPE_PODLASIE -> "podlasie"
LOGIN_TYPE_EDUDZIENNIK -> "edudziennik"
- else -> null
+ else -> "unknown"
}
override fun getImageDrawable(context: Context): Drawable {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyAppFirebase.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyAppFirebase.kt
index 1d563c34..111fef4a 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyAppFirebase.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyAppFirebase.kt
@@ -60,7 +60,7 @@ class SzkolnyAppFirebase(val app: App, val profiles: List, val message:
) ?: return@launch
app.config.sync.registerAvailability = data
if (EventBus.getDefault().hasSubscriberForEvent(RegisterAvailabilityEvent::class.java)) {
- EventBus.getDefault().postSticky(RegisterAvailabilityEvent(data))
+ EventBus.getDefault().postSticky(RegisterAvailabilityEvent())
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt
index b9e733b8..10853812 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt
@@ -42,8 +42,6 @@ class RegisterUnavailableDialog(
init { run {
if (activity.isFinishing)
return@run
- if (status.available && status.minVersionCode <= BuildConfig.VERSION_CODE)
- return@run
onShowListener?.invoke(TAG)
app = activity.applicationContext as App
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt
index 9b43f9be..2df41c36 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt
@@ -8,15 +8,20 @@ import android.content.Intent
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.mikepenz.iconics.IconicsDrawable
+import com.mikepenz.iconics.utils.colorInt
+import com.mikepenz.iconics.utils.sizeDp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
+import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.databinding.DialogLessonDetailsBinding
import pl.szczodrzynski.edziennik.onClick
@@ -24,6 +29,7 @@ import pl.szczodrzynski.edziennik.setText
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventDetailsDialog
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventListAdapter
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
+import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceDetailsDialog
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
import pl.szczodrzynski.edziennik.utils.BetterLink
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
@@ -34,6 +40,7 @@ import kotlin.coroutines.CoroutineContext
class LessonDetailsDialog(
val activity: AppCompatActivity,
val lesson: LessonFull,
+ val attendance: AttendanceFull? = null,
val onShowListener: ((tag: String) -> Unit)? = null,
val onDismissListener: ((tag: String) -> Unit)? = null
) : CoroutineScope {
@@ -52,6 +59,8 @@ class LessonDetailsDialog(
private lateinit var adapter: EventListAdapter
private val manager
get() = app.timetableManager
+ private val attendanceManager
+ get() = app.attendanceManager
init { run {
if (activity.isFinishing)
@@ -170,6 +179,27 @@ class LessonDetailsDialog(
b.teamName = lesson.teamName
}
+ b.attendanceDivider.isVisible = attendance != null
+ b.attendanceLayout.isVisible = attendance != null
+ if (attendance != null) {
+ b.attendanceView.setAttendance(attendance, app.attendanceManager, bigView = true)
+ b.attendanceType.text = attendance.typeName
+ b.attendanceIcon.isVisible = attendance.let {
+ val icon = attendanceManager.getAttendanceIcon(it) ?: return@let false
+ val color = attendanceManager.getAttendanceColor(it)
+ b.attendanceIcon.setImageDrawable(
+ IconicsDrawable(activity, icon).apply {
+ colorInt = color
+ sizeDp = 24
+ }
+ )
+ true
+ }
+ b.attendanceDetails.onClick {
+ AttendanceDetailsDialog(activity, attendance, onShowListener, onDismissListener)
+ }
+ }
+
adapter = EventListAdapter(
activity,
showWeekDay = false,
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabFragment.kt
index 60c30cf9..f7c8952d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabFragment.kt
@@ -41,6 +41,7 @@ class LabFragment : Fragment(), CoroutineScope {
app = activity.application as App
b = TemplateFragmentBinding.inflate(inflater)
b.refreshLayout.setParent(activity.swipeRefreshLayout)
+ b.refreshLayout.isEnabled = false
return b.root
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt
index 4d8205bf..19ae4697 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/debug/LabPageFragment.kt
@@ -16,6 +16,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.config.Config
import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding
import pl.szczodrzynski.edziennik.ui.dialogs.profile.ProfileRemoveDialog
@@ -78,10 +79,10 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}")
}
- b.chucker.isChecked = app.config.enableChucker
-
+ b.chucker.isChecked = App.enableChucker
b.chucker.onChange { _, isChecked ->
app.config.enableChucker = isChecked
+ App.enableChucker = isChecked
MaterialAlertDialogBuilder(activity)
.setTitle("Restart")
.setMessage("Wymagany restart aplikacji")
@@ -94,9 +95,9 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
.show()
}
-
b.disableDebug.onClick {
- app.config.debugMode = false
+ app.config.devMode = false
+ App.devMode = false
MaterialAlertDialogBuilder(activity)
.setTitle("Restart")
.setMessage("Wymagany restart aplikacji")
@@ -115,6 +116,14 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
app.profileSave()
}
+ b.resetCert.onClick {
+ app.config.apiInvalidCert = null
+ }
+
+ b.rebuildConfig.onClick {
+ App.config = Config(App.db)
+ }
+
val profiles = app.db.profileDao().allNow
b.profile.clear()
b.profile += profiles.map { TextInputDropDown.Item(it.id.toLong(), "${it.id} ${it.name} archived ${it.archived}", tag = it) }
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt
index 944c60e8..5d5cbc45 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt
@@ -163,10 +163,9 @@ class HomeFragment : Fragment(), CoroutineScope {
if (app.profile.archived)
items.add(0, HomeArchiveCard(101, app, activity, this, app.profile))
- val status = app.config.sync.registerAvailability[app.profile.registerName]
+ val status = app.availabilityManager.check(app.profile, cacheOnly = true)?.status
val update = app.config.update
- if (update != null && update.versionCode > BuildConfig.VERSION_CODE
- || status != null && (!status.available || status.minVersionCode > BuildConfig.VERSION_CODE)) {
+ if (update != null && update.versionCode > BuildConfig.VERSION_CODE || status?.userMessage != null) {
items.add(0, HomeAvailabilityCard(102, app, activity, this, app.profile))
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt
index fd54748e..613658f4 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt
@@ -50,7 +50,8 @@ class HomeAvailabilityCard(
}
holder.root += b.root
- val status = app.config.sync.registerAvailability[profile.registerName]
+ val error = app.availabilityManager.check(profile, cacheOnly = true)
+ val status = error?.status
val update = app.config.update
if (update == null && status == null)
@@ -58,7 +59,8 @@ class HomeAvailabilityCard(
var onInfoClick = { _: View -> }
- if (status != null && !status.available && status.userMessage != null) {
+ // show "register unavailable" only when disabled
+ if (status?.userMessage != null) {
b.homeAvailabilityTitle.text = HtmlCompat.fromHtml(status.userMessage.title, HtmlCompat.FROM_HTML_MODE_LEGACY)
b.homeAvailabilityText.text = HtmlCompat.fromHtml(status.userMessage.contentShort, HtmlCompat.FROM_HTML_MODE_LEGACY)
b.homeAvailabilityUpdate.isVisible = false
@@ -69,6 +71,7 @@ class HomeAvailabilityCard(
RegisterUnavailableDialog(activity, status)
}
}
+ // show "update available" when available OR version too old for the register
else if (update != null && update.versionCode > BuildConfig.VERSION_CODE) {
b.homeAvailabilityTitle.setText(R.string.home_availability_title)
b.homeAvailabilityText.setText(R.string.home_availability_text, update.versionName)
@@ -78,6 +81,9 @@ class HomeAvailabilityCard(
UpdateAvailableDialog(activity, update)
}
}
+ else {
+ b.root.isVisible = false
+ }
b.homeAvailabilityUpdate.onClick {
if (update == null)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt
index 858b4a01..71a5b804 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginChooserFragment.kt
@@ -26,13 +26,12 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.*
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.*
-import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
-import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
import pl.szczodrzynski.edziennik.databinding.LoginChooserFragmentBinding
import pl.szczodrzynski.edziennik.ui.dialogs.RegisterUnavailableDialog
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackActivity
import pl.szczodrzynski.edziennik.utils.BetterLinkMovementMethod
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
+import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
import pl.szczodrzynski.edziennik.utils.models.Date
import kotlin.coroutines.CoroutineContext
@@ -269,52 +268,23 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
}
private suspend fun checkAvailability(loginType: Int): Boolean {
- when (loginType) {
- LOGIN_TYPE_LIBRUS -> "librus"
- LOGIN_TYPE_VULCAN -> "vulcan"
- LOGIN_TYPE_IDZIENNIK -> "idziennik"
- LOGIN_TYPE_MOBIDZIENNIK -> "mobidziennik"
- LOGIN_TYPE_PODLASIE -> "podlasie"
- LOGIN_TYPE_EDUDZIENNIK -> "edudziennik"
- else -> null
- }?.let { registerName ->
- var status = app.config.sync.registerAvailability[registerName]
- if (status == null || status.nextCheckAt < currentTimeUnix()) {
- val api = SzkolnyApi(app)
- val result = withContext(Dispatchers.IO) {
- return@withContext api.runCatching({
- val availability = getRegisterAvailability()
- app.config.sync.registerAvailability = availability
- availability[registerName]
- }, onError = {
- if (it.toErrorCode() == ERROR_API_INVALID_SIGNATURE) {
- return@withContext false
- }
- return@withContext it
- })
- }
+ val error = withContext(Dispatchers.IO) {
+ app.availabilityManager.check(loginType)
+ } ?: return true
- when (result) {
- false -> {
- Toast.makeText(activity, R.string.error_no_api_access, Toast.LENGTH_SHORT).show()
- return@let
- }
- is Throwable -> {
- activity.errorSnackbar.addError(result.toApiError(TAG)).show()
- return false
- }
- is RegisterAvailabilityStatus -> {
- status = result
- }
- }
+ return when (error.type) {
+ Type.NOT_AVAILABLE -> {
+ RegisterUnavailableDialog(activity, error.status!!)
+ false
}
-
- if (status?.available != true || status.minVersionCode > BuildConfig.VERSION_CODE) {
- if (status != null)
- RegisterUnavailableDialog(activity, status)
- return false
+ Type.API_ERROR -> {
+ activity.errorSnackbar.addError(error.apiError!!).show()
+ false
+ }
+ Type.NO_API_ACCESS -> {
+ Toast.makeText(activity, R.string.error_no_api_access, Toast.LENGTH_SHORT).show()
+ true
}
}
- return true
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt
index 1c9634fc..f14c6d19 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt
@@ -53,7 +53,7 @@ class LoginPrizeFragment : Fragment(), CoroutineScope {
.setTitle(R.string.are_you_sure)
.setMessage(R.string.dev_mode_enable_warning)
.setPositiveButton(R.string.yes) { _, _ ->
- app.config.debugMode = true
+ app.config.devMode = true
App.devMode = true
MaterialAlertDialogBuilder(activity)
.setTitle("Restart")
@@ -67,8 +67,8 @@ class LoginPrizeFragment : Fragment(), CoroutineScope {
.show()
}
.setNegativeButton(R.string.no) { _, _ ->
- app.config.debugMode = false
- App.devMode = false
+ app.config.devMode = App.debugMode
+ App.devMode = App.debugMode
activity.finish()
}
.show()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt
index 00ce872e..5d13ee86 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt
@@ -9,19 +9,24 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
+import android.widget.LinearLayout
import android.widget.TextView
import androidx.asynclayoutinflater.view.AsyncLayoutInflater
-import androidx.core.view.isVisible
-import androidx.core.view.marginTop
-import androidx.core.view.setPadding
-import androidx.core.view.updateLayoutParams
+import androidx.core.view.*
import com.linkedin.android.tachyon.DayView
import com.linkedin.android.tachyon.DayViewConfig
+import com.mikepenz.iconics.IconicsDrawable
+import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
+import com.mikepenz.iconics.utils.colorInt
+import com.mikepenz.iconics.utils.sizeDp
+import eu.szkolny.font.SzkolnyFont
import kotlinx.coroutines.*
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
+import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.databinding.TimetableDayFragmentBinding
@@ -61,6 +66,8 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
private val manager
get() = app.timetableManager
+ private val attendanceManager
+ get() = app.attendanceManager
// find SwipeRefreshLayout in the hierarchy
private val refreshLayout by lazy { view?.findParentById(R.id.refreshLayout) }
@@ -102,14 +109,17 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
val events = withContext(Dispatchers.Default) {
app.db.eventDao().getAllByDateNow(App.profileId, date)
}
- processLessonList(lessons, events)
+ val attendanceList = withContext(Dispatchers.Default) {
+ app.db.attendanceDao().getAllByDateNow(App.profileId, date)
+ }
+ processLessonList(lessons, events, attendanceList)
}
}
return true
}
- private fun processLessonList(lessons: List, events: List) {
+ private fun processLessonList(lessons: List, events: List, attendanceList: List) {
// no lessons - timetable not downloaded yet
if (lessons.isEmpty()) {
inflater.inflate(R.layout.timetable_no_timetable, b.root) { view, _, _ ->
@@ -172,10 +182,10 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
lessons.forEach { it.showAsUnseen = !it.seen }
- buildLessonViews(lessons.filter { it.type != Lesson.TYPE_NO_LESSONS }, events)
+ buildLessonViews(lessons.filter { it.type != Lesson.TYPE_NO_LESSONS }, events, attendanceList)
}
- private fun buildLessonViews(lessons: List, events: List) {
+ private fun buildLessonViews(lessons: List, events: List, attendanceList: List) {
if (!isAdded)
return
@@ -192,6 +202,7 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
for (lesson in lessons) {
+ val attendance = attendanceList.find { it.startTime == lesson.startTime }
val startTime = lesson.displayStartTime ?: continue
val endTime = lesson.displayEndTime ?: continue
@@ -208,11 +219,17 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
val lb = TimetableLessonBinding.bind(eventView)
eventViews += eventView
- eventView.tag = lesson
+ eventView.tag = lesson to attendance
eventView.setOnClickListener {
- if (isAdded && it.tag is LessonFull)
- LessonDetailsDialog(activity, it.tag as LessonFull)
+ if (isAdded && it.tag is Pair<*, *>) {
+ val (lessonObj, attendanceObj) = it.tag as Pair<*, *>
+ LessonDetailsDialog(
+ activity = activity,
+ lesson = lessonObj as LessonFull,
+ attendance = attendanceObj as AttendanceFull?
+ )
+ }
}
val eventList = events.filter { it.time != null && it.time == lesson.displayStartTime }.take(3)
@@ -276,6 +293,18 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
lb.detailsFirst.text = listOfNotEmpty(timeRange, classroomInfo).concat(bullet)
lb.detailsSecond.text = listOfNotEmpty(teacherInfo, teamInfo).concat(bullet)
+ lb.attendanceIcon.isVisible = attendance?.let {
+ val icon = attendanceManager.getAttendanceIcon(it) ?: return@let false
+ val color = attendanceManager.getAttendanceColor(it)
+ lb.attendanceIcon.setImageDrawable(
+ IconicsDrawable(activity, icon).apply {
+ colorInt = color
+ sizeDp = 24
+ }
+ )
+ true
+ } ?: false
+
lb.unread = lesson.type != Lesson.TYPE_NORMAL && lesson.showAsUnseen
if (!lesson.seen) {
manager.markAsSeen(lesson)
@@ -283,6 +312,12 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
//lb.subjectName.typeface = Typeface.create("sans-serif-light", Typeface.BOLD)
lb.annotationVisible = manager.getAnnotation(activity, lesson, lb.annotation)
+ val lessonNumberMargin =
+ if (lb.annotationVisible) (-8).dp
+ else 0
+ lb.lessonNumberText.updateLayoutParams {
+ updateMargins(top = lessonNumberMargin, bottom = lessonNumberMargin)
+ }
// The day view needs the event time ranges in the start minute/end minute format,
// so calculate those here
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt
index cd726797..77af40ed 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt
@@ -4,6 +4,9 @@
package pl.szczodrzynski.edziennik.utils.managers
+import com.mikepenz.iconics.typeface.IIcon
+import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
+import eu.szkolny.font.SzkolnyFont
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -63,6 +66,17 @@ class AttendanceManager(val app: App) : CoroutineScope {
else getAttendanceColor(attendance.baseType)
}
+ fun getAttendanceIcon(attendance: Attendance): IIcon? = when (attendance.baseType) {
+ Attendance.TYPE_PRESENT, Attendance.TYPE_PRESENT_CUSTOM -> CommunityMaterial.Icon.cmd_check
+ Attendance.TYPE_ABSENT -> CommunityMaterial.Icon.cmd_close
+ Attendance.TYPE_ABSENT_EXCUSED -> CommunityMaterial.Icon3.cmd_progress_close
+ Attendance.TYPE_RELEASED -> CommunityMaterial.Icon.cmd_account_arrow_right_outline
+ Attendance.TYPE_BELATED -> CommunityMaterial.Icon.cmd_clock_alert_outline
+ Attendance.TYPE_BELATED_EXCUSED -> CommunityMaterial.Icon.cmd_clock_check_outline
+ Attendance.TYPE_DAY_FREE -> SzkolnyFont.Icon.szf_umbrella_beach_outline
+ else -> null
+ }
+
/* _ _ _____ _____ _ __ _
| | | |_ _| / ____| (_)/ _(_)
| | | | | | | (___ _ __ ___ ___ _| |_ _ ___
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AvailabilityManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AvailabilityManager.kt
new file mode 100644
index 00000000..0c93468e
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AvailabilityManager.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2021-9-18.
+ */
+
+package pl.szczodrzynski.edziennik.utils.managers
+
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.BuildConfig
+import pl.szczodrzynski.edziennik.currentTimeUnix
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
+import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+import pl.szczodrzynski.edziennik.toApiError
+
+class AvailabilityManager(val app: App) {
+ companion object {
+ private const val TAG = "AvailabilityManager"
+ }
+
+ private val api = SzkolnyApi(app)
+
+ data class Error(
+ val type: Type,
+ val status: RegisterAvailabilityStatus?,
+ val apiError: ApiError?
+ ) {
+ companion object {
+ fun notAvailable(status: RegisterAvailabilityStatus) =
+ Error(Type.NOT_AVAILABLE, status, null)
+
+ fun apiError(apiError: ApiError) =
+ Error(Type.API_ERROR, null, apiError)
+
+ fun noApiAccess() =
+ Error(Type.NO_API_ACCESS, null, null)
+ }
+
+ enum class Type {
+ NOT_AVAILABLE,
+ API_ERROR,
+ NO_API_ACCESS,
+ }
+ }
+
+ fun check(profile: Profile, cacheOnly: Boolean = false): Error? {
+ return check(profile.registerName, cacheOnly)
+ }
+
+ fun check(loginType: Int, cacheOnly: Boolean = false): Error? {
+ val registerName = when (loginType) {
+ LOGIN_TYPE_LIBRUS -> "librus"
+ LOGIN_TYPE_VULCAN -> "vulcan"
+ LOGIN_TYPE_IDZIENNIK -> "idziennik"
+ LOGIN_TYPE_MOBIDZIENNIK -> "mobidziennik"
+ LOGIN_TYPE_PODLASIE -> "podlasie"
+ LOGIN_TYPE_EDUDZIENNIK -> "edudziennik"
+ else -> "unknown"
+ }
+ return check(registerName, cacheOnly)
+ }
+
+ fun check(registerName: String, cacheOnly: Boolean = false): Error? {
+ if (!app.config.apiAvailabilityCheck)
+ return null
+ val status = app.config.sync.registerAvailability[registerName]
+ if (status != null && status.nextCheckAt > currentTimeUnix()) {
+ return reportStatus(status)
+ }
+ if (cacheOnly) {
+ return reportStatus(status)
+ }
+
+ return try {
+ val availability = api.getRegisterAvailability()
+ app.config.sync.registerAvailability = availability
+ reportStatus(availability[registerName])
+ } catch (e: Throwable) {
+ reportApiError(e)
+ }
+ }
+
+ private fun reportStatus(status: RegisterAvailabilityStatus?): Error? {
+ if (status == null)
+ return null
+ if (!status.available || status.minVersionCode > BuildConfig.VERSION_CODE)
+ return Error.notAvailable(status)
+ return null
+ }
+
+ private fun reportApiError(throwable: Throwable): Error {
+ val apiError = throwable.toApiError(TAG)
+ if (apiError.errorCode == ERROR_API_INVALID_SIGNATURE) {
+ app.config.sync.registerAvailability = mapOf()
+ return Error.noApiAccess()
+ }
+ return Error.apiError(apiError)
+ }
+}
diff --git a/app/src/main/res/layout/dialog_lesson_details.xml b/app/src/main/res/layout/dialog_lesson_details.xml
index bf9cc40d..a304c641 100644
--- a/app/src/main/res/layout/dialog_lesson_details.xml
+++ b/app/src/main/res/layout/dialog_lesson_details.xml
@@ -134,7 +134,8 @@
android:layout_marginTop="8dp"
android:baselineAligned="false"
android:gravity="center_vertical"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:visibility="gone">
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-->
-
+ tools:text="Cookies:\n\nsynergia.librus.pl\n DZIENNIKSID=L01~1234567890abcdef" />
+ android:layout_height="wrap_content" />
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/timetable_lesson.xml b/app/src/main/res/layout/timetable_lesson.xml
index 3b51a197..4233a58e 100644
--- a/app/src/main/res/layout/timetable_lesson.xml
+++ b/app/src/main/res/layout/timetable_lesson.xml
@@ -48,16 +48,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
- android:paddingHorizontal="8dp"
+ android:baselineAligned="false"
android:orientation="horizontal"
- android:baselineAligned="false">
+ android:paddingHorizontal="8dp"
+ android:paddingVertical="4dp">
+ android:background="@drawable/unread_red_circle"
+ android:visibility="@{unread ? View.VISIBLE : View.GONE}" />
-
-
-
+ tools:text="3" />
@@ -149,7 +138,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="end|bottom"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:paddingBottom="2dp">
Open-Source-Lizenzen
Datenschutzrichtlinie
E-Klassenbuch
- © Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - Juni 2021
+ © Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2021
Klicken Sie hier, um nach Aktualisierungen zu suchen
Aktualisierung
Version
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
index a557681a..84e3c52b 100644
--- a/app/src/main/res/values-en/strings.xml
+++ b/app/src/main/res/values-en/strings.xml
@@ -858,7 +858,7 @@
Open-source licenses
Privacy policy
E-register
- © Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - June 2021
+ © Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2021
Click to check for updates
Update
Version
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b11631b5..fd9a6935 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -921,7 +921,7 @@
Licencje open-source
Polityka prywatności
E-dziennik
- © Kuba Szczodrzyński && Kacper Ziubryniewicz\nwrzesień 2018 - czerwiec 2021
+ © Kuba Szczodrzyński && Kacper Ziubryniewicz\nwrzesień 2018 - 2021
Kliknij, aby sprawdzić aktualizacje
Aktualizacja
Wersja
@@ -1463,4 +1463,5 @@
Rodzaj: %s\nTermin: %s, %s\nNr lekcji: %s\nPrzedmiot: %s\nNauczyciel: %s\nTemat lekcji: %s
\@%s - %s
Najłatwiejszy sposób na korzystanie z e-dziennika.
+ Szczegóły
diff --git a/build.gradle b/build.gradle
index 7e6fb9f9..a8665c89 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,8 +5,8 @@ buildscript {
kotlin_version = '1.5.20'
release = [
- versionName: "4.9",
- versionCode: 4090099
+ versionName: "4.10",
+ versionCode: 4100099
]
setup = [