Compare commits

...

18 Commits

Author SHA1 Message Date
a0244841ad [4.13.4] Update build.gradle, signing and changelog. 2022-12-26 14:45:29 +01:00
12c0c6f2ec [UI] Always show event subject dropdown for university school. 2022-12-26 14:43:42 +01:00
aaa3b8626e [UI] Update event types for university school. 2022-12-26 14:01:25 +01:00
48c9e2dfe3 [4.13.3] Update build.gradle, signing and changelog. 2022-12-06 10:35:23 +01:00
81d4801d27 [UI] Add snowfall to CounterActivity. Enable in February as well. 2022-12-06 10:34:12 +01:00
5f8016061d [API/Vulcan] Fix wrong serializing of null in JSON causing API error. 2022-12-06 10:22:47 +01:00
5007587192 [UI/Agenda] Allow prioritizing event subject over event type. 2022-11-30 11:29:43 +01:00
dfd1083e41 [UI/Timetable] Show lesson replacing notes in all places. 2022-11-30 10:41:43 +01:00
678baf46e5 [4.13.2] Update build.gradle, signing and changelog. 2022-11-28 20:30:11 +01:00
4077fe448d [4.13.2-rc.4] Update build.gradle, signing and changelog. 2022-11-25 16:52:16 +01:00
f085e17ef7 [API/Vulcan] Once again fix ignoring 404 response on Addressbook. 2022-11-25 16:51:35 +01:00
7fd2cad46b [4.13.2-rc.3] Update build.gradle, signing and changelog. 2022-11-25 16:13:58 +01:00
93dc2ac9ab [API/Vulcan] Fix ignoring 404 response on Addressbook. 2022-11-25 16:11:50 +01:00
ac53e267fc [4.13.2-rc.2] Update build.gradle, signing and changelog. 2022-11-25 14:55:49 +01:00
86eb1a0f42 [API/Vulcan] Actually ignore 404 response on Addressbook. 2022-11-25 14:54:05 +01:00
710d82da27 [4.13.2-rc.1] Update build.gradle, signing and changelog. 2022-11-25 14:40:39 +01:00
0123f50810 [API/Vulcan] Ignore 404 response on Addressbook. 2022-11-25 14:20:22 +01:00
6d3eb65445 [API/Mobidziennik] Do not clear email field if not set. 2022-11-15 22:20:00 +01:00
44 changed files with 251 additions and 126 deletions

View File

@ -156,6 +156,7 @@ dependencies {
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2" implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
implementation "androidx.recyclerview:recyclerview:1.2.1" implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation "androidx.room:room-runtime:2.4.3" implementation "androidx.room:room-runtime:2.4.3"
implementation "androidx.room:room-ktx:2.4.3"
implementation "androidx.work:work-runtime-ktx:2.7.1" implementation "androidx.work:work-runtime-ktx:2.7.1"
kapt "androidx.room:room-compiler:2.4.3" kapt "androidx.room:room-compiler:2.4.3"

View File

@ -1,9 +1,11 @@
<h3>Wersja 4.13.1, 2022-11-03</h3> <h3>Wersja 4.13.4, 2022-12-26</h3>
<ul> <ul>
<li>Edycja kart na stronie głównej znowu działa.</li> <li>USOS: zaktualizowano rodzaje wydarzeń. Wybór przedmiotu jest teraz zawsze widoczny.</li>
<li>Poprawiono pobieranie nauczyciela w zakładce Uwagi. @BxOxSxS</li> <li>Opcja wyświetlania nazwy przedmiotu w miejscu rodzaju wydarzenia.</li>
<li>Poprawiono oznaczanie daty przeczytania wiadomości wysłanych. @BxOxSxS</li> <li>Notatki zastępujące treść lekcji są teraz wyświetlane wszędzie.</li>
<li>Dodano tłumaczenie karty planu lekcji. @MedzikUser</li> <li>Na ekranie odliczania czasu lekcji również pada śnieg.</li>
<li>Poprawiono synchronizację w Mobidzienniku bez ustawionego adresu e-mail.</li>
<li>Poprawiono błąd synchronizacji w Vulcanie.</li>
</ul> </ul>
<br> <br>
<br> <br>

View File

@ -9,7 +9,7 @@
/*secret password - removed for source code publication*/ /*secret password - removed for source code publication*/
static toys AES_IV[16] = { static toys AES_IV[16] = {
0xe8, 0x2b, 0x2c, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 0x4b, 0x43, 0x7e, 0xa2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat); unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);

View File

@ -422,6 +422,12 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
try { try {
App.data = AppData.get(profile.loginStoreType) App.data = AppData.get(profile.loginStoreType)
d("App", "Loaded AppData: ${App.data}") d("App", "Loaded AppData: ${App.data}")
// apply newly-added config overrides, if not changed by the user yet
for ((key, value) in App.data.configOverrides) {
val config = App.profile.config
if (!config.has(key))
config.set(key, value)
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e("App", "Cannot load AppData", e) Log.e("App", "Cannot load AppData", e)
Toast.makeText(this, R.string.app_cannot_load_data, Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.app_cannot_load_data, Toast.LENGTH_LONG).show()

View File

@ -322,7 +322,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
// IT'S WINTER MY DUDES // IT'S WINTER MY DUDES
val today = Date.getToday() val today = Date.getToday()
if ((today.month % 11 == 1) && app.config.ui.snowfall) { if ((today.month / 3 % 4 == 0) && app.config.ui.snowfall) {
b.rootFrame.addView(layoutInflater.inflate(R.layout.snowfall, b.rootFrame, false)) b.rootFrame.addView(layoutInflater.inflate(R.layout.snowfall, b.rootFrame, false))
} else if (app.config.ui.eggfall && BigNightUtil().isDataWielkanocyNearDzisiaj()) { } else if (app.config.ui.eggfall && BigNightUtil().isDataWielkanocyNearDzisiaj()) {
val eggfall = layoutInflater.inflate( val eggfall = layoutInflater.inflate(

View File

@ -59,10 +59,11 @@ data class AppData(
val lessonHeight: Int, val lessonHeight: Int,
val enableMarkAsReadAnnouncements: Boolean, val enableMarkAsReadAnnouncements: Boolean,
val enableNoticePoints: Boolean, val enableNoticePoints: Boolean,
val eventManualShowSubjectDropdown: Boolean,
) )
data class EventType( data class EventType(
val id: Int, val id: Long,
val color: String, val color: String,
val name: String, val name: String,
) )

View File

@ -43,4 +43,6 @@ abstract class BaseConfig(
db.configDao().add(ConfigEntry(profileId ?: -1, key, value)) db.configDao().add(ConfigEntry(profileId ?: -1, key, value))
} }
} }
fun has(key: String) = values.containsKey(key)
} }

View File

@ -15,7 +15,7 @@ class ProfileConfig(
entries: List<ConfigEntry>?, entries: List<ConfigEntry>?,
) : BaseConfig(db, profileId, entries) { ) : BaseConfig(db, profileId, entries) {
companion object { companion object {
const val DATA_VERSION = 4 const val DATA_VERSION = 5
} }
val grades by lazy { ProfileConfigGrades(this) } val grades by lazy { ProfileConfigGrades(this) }

View File

@ -15,6 +15,7 @@ class ProfileConfigUI(base: ProfileConfig) {
var agendaGroupByType by base.config<Boolean>(false) var agendaGroupByType by base.config<Boolean>(false)
var agendaLessonChanges by base.config<Boolean>(true) var agendaLessonChanges by base.config<Boolean>(true)
var agendaTeacherAbsence by base.config<Boolean>(true) var agendaTeacherAbsence by base.config<Boolean>(true)
var agendaSubjectImportant by base.config<Boolean>(false)
var agendaElearningMark by base.config<Boolean>(false) var agendaElearningMark by base.config<Boolean>(false)
var agendaElearningGroup by base.config<Boolean>(true) var agendaElearningGroup by base.config<Boolean>(true)

View File

@ -16,6 +16,8 @@ import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_AL
class ProfileConfigMigration(config: ProfileConfig) { class ProfileConfigMigration(config: ProfileConfig) {
init { config.apply { init { config.apply {
val profile = db.profileDao().getByIdNow(profileId ?: -1)
if (dataVersion < 2) { if (dataVersion < 2) {
sync.notificationFilter = sync.notificationFilter + NotificationType.TEACHER_ABSENCE sync.notificationFilter = sync.notificationFilter + NotificationType.TEACHER_ABSENCE
@ -37,11 +39,23 @@ class ProfileConfigMigration(config: ProfileConfig) {
// switch to new event types (USOS) // switch to new event types (USOS)
dataVersion = 4 dataVersion = 4
val profile = db.profileDao().getByIdNow(profileId ?: -1)
if (profile?.loginStoreType?.schoolType == SchoolType.UNIVERSITY) { if (profile?.loginStoreType?.schoolType == SchoolType.UNIVERSITY) {
db.eventTypeDao().clear(profileId ?: -1) db.eventTypeDao().clear(profileId ?: -1)
db.eventTypeDao().addDefaultTypes(profile) db.eventTypeDao().addDefaultTypes(profile)
} }
} }
if (dataVersion < 5) {
// update USOS event types and the appropriate events (2022-12-25)
dataVersion = 5
if (profile?.loginStoreType?.schoolType == SchoolType.UNIVERSITY) {
db.eventTypeDao().getAllWithDefaults(profile)
// wejściówka (4) -> kartkówka (3)
db.eventDao().getRawNow("UPDATE events SET eventType = 3 WHERE profileId = $profileId AND eventType = 4;")
// zadanie (6) -> zadanie domowe (-1)
db.eventDao().getRawNow("UPDATE events SET eventType = -1 WHERE profileId = $profileId AND eventType = 6;")
}
}
}} }}
} }

View File

@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBID
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.DAY
import pl.szczodrzynski.edziennik.ext.get import pl.szczodrzynski.edziennik.ext.get
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
class MobidziennikWebAccountEmail(override val data: DataMobidziennik, class MobidziennikWebAccountEmail(override val data: DataMobidziennik,
override val lastSync: Long?, override val lastSync: Long?,
@ -24,7 +25,8 @@ class MobidziennikWebAccountEmail(override val data: DataMobidziennik,
MobidziennikLuckyNumberExtractor(data, text) MobidziennikLuckyNumberExtractor(data, text)
val email = Regexes.MOBIDZIENNIK_ACCOUNT_EMAIL.find(text)?.let { it[1] } val email = Regexes.MOBIDZIENNIK_ACCOUNT_EMAIL.find(text)?.let { it[1] }
data.loginEmail = email if (email.isNotNullNorBlank())
data.loginEmail = email
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL, if (email == null) 3* DAY else 7* DAY) data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL, if (email == null) 3* DAY else 7* DAY)
onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL) onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL)

View File

@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.ext.JsonObject import pl.szczodrzynski.edziennik.ext.JsonObject
import pl.szczodrzynski.edziennik.ext.getJsonObject import pl.szczodrzynski.edziennik.ext.getJsonObject
import pl.szczodrzynski.edziennik.ext.getString import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
@ -77,7 +78,9 @@ class MobidziennikLoginApi2(val data: DataMobidziennik, val onSuccess: () -> Uni
} }
} }
data.loginEmail = json.getString("email") val email = json.getString("email")
if (email.isNotNullNorBlank())
data.loginEmail = email
data.globalId = json.getString("id_global") data.globalId = json.getString("id_global")
data.loginId = json.getString("login") data.loginId = json.getString("login")
onSuccess() onSuccess()

View File

@ -26,6 +26,7 @@ import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.HttpURLConnection.HTTP_NOT_FOUND
import java.net.URLEncoder import java.net.URLEncoder
import java.time.Instant import java.time.Instant
import java.time.LocalDateTime import java.time.LocalDateTime
@ -183,6 +184,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
payload: JsonElement? = null, payload: JsonElement? = null,
baseUrl: Boolean = false, baseUrl: Boolean = false,
firebaseToken: String? = null, firebaseToken: String? = null,
allow404: Boolean = false,
crossinline onSuccess: (json: T, response: Response?) -> Unit crossinline onSuccess: (json: T, response: Response?) -> Unit
) { ) {
val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint" val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint"
@ -295,6 +297,19 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
} }
override fun onFailure(response: Response?, throwable: Throwable?) { override fun onFailure(response: Response?, throwable: Throwable?) {
if (allow404 && response?.code() == HTTP_NOT_FOUND) {
try {
onSuccess(null as T, response)
} catch (e: Exception) {
data.error(
ApiError(tag, EXCEPTION_VULCAN_HEBE_REQUEST)
.withResponse(response)
.withThrowable(e)
)
}
return
}
data.error( data.error(
ApiError(tag, ERROR_REQUEST_FAILURE) ApiError(tag, ERROR_REQUEST_FAILURE)
.withResponse(response) .withResponse(response)
@ -338,6 +353,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
query: Map<String, String> = mapOf(), query: Map<String, String> = mapOf(),
baseUrl: Boolean = false, baseUrl: Boolean = false,
firebaseToken: String? = null, firebaseToken: String? = null,
allow404: Boolean = false,
crossinline onSuccess: (json: T, response: Response?) -> Unit crossinline onSuccess: (json: T, response: Response?) -> Unit
) { ) {
val queryPath = query.map { val queryPath = query.map {
@ -348,6 +364,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
if (query.isNotEmpty()) "$endpoint?$queryPath" else endpoint, if (query.isNotEmpty()) "$endpoint?$queryPath" else endpoint,
baseUrl = baseUrl, baseUrl = baseUrl,
firebaseToken = firebaseToken, firebaseToken = firebaseToken,
allow404 = allow404,
onSuccess = onSuccess onSuccess = onSuccess
) )
} }
@ -382,6 +399,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
messageBox: String? = null, messageBox: String? = null,
params: Map<String, String> = mapOf(), params: Map<String, String> = mapOf(),
includeFilterType: Boolean = true, includeFilterType: Boolean = true,
allow404: Boolean = false,
onSuccess: (data: List<JsonObject>, response: Response?) -> Unit onSuccess: (data: List<JsonObject>, response: Response?) -> Unit
) { ) {
val url = if (includeFilterType && filterType != null) val url = if (includeFilterType && filterType != null)
@ -427,8 +445,8 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
) )
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
apiGet(tag, url, query) { json: JsonArray, response -> apiGet(tag, url, query, allow404 = allow404) { json: JsonArray?, response ->
onSuccess(json.map { it.asJsonObject }, response) onSuccess(json?.map { it.asJsonObject } ?: listOf(), response)
} }
} }
} }

View File

@ -19,6 +19,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_PARENTS_
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_STUDENT import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_STUDENT
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_TEACHER import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_TEACHER
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import java.net.HttpURLConnection.HTTP_NOT_FOUND
class VulcanHebeAddressbook( class VulcanHebeAddressbook(
override val data: DataVulcan, override val data: DataVulcan,
@ -41,8 +42,15 @@ class VulcanHebeAddressbook(
VULCAN_HEBE_ENDPOINT_ADDRESSBOOK, VULCAN_HEBE_ENDPOINT_ADDRESSBOOK,
HebeFilterType.BY_PERSON, HebeFilterType.BY_PERSON,
lastSync = lastSync, lastSync = lastSync,
includeFilterType = false includeFilterType = false,
) { list, _ -> allow404 = true,
) { list, response ->
if (response?.code() == HTTP_NOT_FOUND) {
data.setSyncNext(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK, 2 * DAY)
onSuccess(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK)
return@apiGetList
}
list.forEach { person -> list.forEach { person ->
val id = person.getString("Id") ?: return@forEach val id = person.getString("Id") ?: return@forEach

View File

@ -46,6 +46,6 @@ object Signing {
/*fun provideKey(param1: String, param2: Long): ByteArray {*/ /*fun provideKey(param1: String, param2: Long): ByteArray {*/
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray { fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
return "$param1.MTIzNDU2Nzg5MDsJslqno5===.$param2".sha256() return "$param1.MTIzNDU2Nzg5MD4BikzMWC===.$param2".sha256()
} }
} }

View File

@ -25,6 +25,9 @@ abstract class EventTypeDao {
@Query("DELETE FROM eventTypes WHERE profileId = :profileId") @Query("DELETE FROM eventTypes WHERE profileId = :profileId")
abstract fun clear(profileId: Int) abstract fun clear(profileId: Int)
@Query("DELETE FROM eventTypes WHERE profileId = :profileId AND eventTypeSource = :source")
abstract fun clearBySource(profileId: Int, source: Int)
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId AND eventType = :typeId") @Query("SELECT * FROM eventTypes WHERE profileId = :profileId AND eventType = :typeId")
abstract fun getByIdNow(profileId: Int, typeId: Long): EventType? abstract fun getByIdNow(profileId: Int, typeId: Long): EventType?
@ -43,7 +46,7 @@ abstract class EventTypeDao {
val typeList = data.eventTypes.map { val typeList = data.eventTypes.map {
EventType( EventType(
profileId = profile.id, profileId = profile.id,
id = it.id.toLong(), id = it.id,
name = it.name, name = it.name,
color = Color.parseColor(it.color), color = Color.parseColor(it.color),
order = order++, order = order++,
@ -53,4 +56,21 @@ abstract class EventTypeDao {
addAll(typeList) addAll(typeList)
return typeList return typeList
} }
fun getAllWithDefaults(profile: Profile): List<EventType> {
val eventTypes = getAllNow(profile.id)
val defaultIdsExpected = AppData.get(profile.loginStoreType).eventTypes
.map { it.id }
val defaultIdsFound = eventTypes.filter { it.source == SOURCE_DEFAULT }
.sortedBy { it.order }
.map { it.id }
if (defaultIdsExpected == defaultIdsFound)
return eventTypes
clearBySource(profile.id, SOURCE_DEFAULT)
addDefaultTypes(profile)
return eventTypes
}
} }

View File

@ -28,6 +28,9 @@ interface ProfileDao {
@Query("SELECT * FROM profiles WHERE profileId = :profileId") @Query("SELECT * FROM profiles WHERE profileId = :profileId")
fun getByIdNow(profileId: Int): Profile? fun getByIdNow(profileId: Int): Profile?
@Query("SELECT * FROM profiles WHERE profileId = :profileId")
suspend fun getByIdSuspend(profileId: Int): Profile?
@get:Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId") @get:Query("SELECT * FROM profiles WHERE profileId >= 0 ORDER BY profileId")
val all: LiveData<List<Profile>> val all: LiveData<List<Profile>>

View File

@ -5,31 +5,6 @@ package pl.szczodrzynski.edziennik.data.db.entity
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_CLASS_EVENT
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_DEFAULT
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_ELEARNING
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_ESSAY
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_EXAM
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_EXCURSION
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_HOMEWORK
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_INFORMATION
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_PROJECT
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_PT_MEETING
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_READING
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_SHORT_QUIZ
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_CLASS_EVENT
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_DEFAULT
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_ELEARNING
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_ESSAY
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_EXAM
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_EXCURSION
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_HOMEWORK
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_INFORMATION
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_PROJECT
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_PT_MEETING
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_READING
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_SHORT_QUIZ
@Entity( @Entity(
tableName = "eventTypes", tableName = "eventTypes",
@ -55,35 +30,5 @@ class EventType(
const val SOURCE_REGISTER = 1 const val SOURCE_REGISTER = 1
const val SOURCE_CUSTOM = 2 const val SOURCE_CUSTOM = 2
const val SOURCE_SHARED = 3 const val SOURCE_SHARED = 3
fun getTypeColorMap() = mapOf(
TYPE_ELEARNING to COLOR_ELEARNING,
TYPE_HOMEWORK to COLOR_HOMEWORK,
TYPE_DEFAULT to COLOR_DEFAULT,
TYPE_EXAM to COLOR_EXAM,
TYPE_SHORT_QUIZ to COLOR_SHORT_QUIZ,
TYPE_ESSAY to COLOR_ESSAY,
TYPE_PROJECT to COLOR_PROJECT,
TYPE_PT_MEETING to COLOR_PT_MEETING,
TYPE_EXCURSION to COLOR_EXCURSION,
TYPE_READING to COLOR_READING,
TYPE_CLASS_EVENT to COLOR_CLASS_EVENT,
TYPE_INFORMATION to COLOR_INFORMATION
)
fun getTypeNameMap() = mapOf(
TYPE_ELEARNING to R.string.event_type_elearning,
TYPE_HOMEWORK to R.string.event_type_homework,
TYPE_DEFAULT to R.string.event_other,
TYPE_EXAM to R.string.event_exam,
TYPE_SHORT_QUIZ to R.string.event_short_quiz,
TYPE_ESSAY to R.string.event_essay,
TYPE_PROJECT to R.string.event_project,
TYPE_PT_MEETING to R.string.event_pt_meeting,
TYPE_EXCURSION to R.string.event_excursion,
TYPE_READING to R.string.event_reading,
TYPE_CLASS_EVENT to R.string.event_class_event,
TYPE_INFORMATION to R.string.event_information
)
} }
} }

View File

@ -6,6 +6,8 @@ package pl.szczodrzynski.edziennik.data.db.enums
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.ext.getString
import pl.szczodrzynski.edziennik.ext.isNotNullNorBlank
enum class LoginMethod( enum class LoginMethod(
val loginType: LoginType, val loginType: LoginType,
@ -26,7 +28,7 @@ enum class LoginMethod(
MOBIDZIENNIK_API2( MOBIDZIENNIK_API2(
loginType = LoginType.MOBIDZIENNIK, loginType = LoginType.MOBIDZIENNIK,
id = 1300, id = 1300,
isPossible = { profile, _ -> profile?.studentData?.has("email") ?: false }, isPossible = { profile, _ -> profile?.studentData?.getString("email").isNotNullNorBlank() },
), ),
LIBRUS_PORTAL( LIBRUS_PORTAL(
loginType = LoginType.LIBRUS, loginType = LoginType.LIBRUS,
@ -57,7 +59,7 @@ enum class LoginMethod(
VULCAN_WEB_MAIN( VULCAN_WEB_MAIN(
loginType = LoginType.VULCAN, loginType = LoginType.VULCAN,
id = 4100, id = 4100,
isPossible = { _, loginStore -> loginStore.hasLoginData("webHost") }, isPossible = { _, loginStore -> loginStore.getLoginData("webHost", null).isNotNullNorBlank() },
), ),
VULCAN_HEBE( VULCAN_HEBE(
loginType = LoginType.VULCAN, loginType = LoginType.VULCAN,

View File

@ -73,7 +73,8 @@ fun JsonObject(vararg properties: Pair<String, Any?>): JsonObject {
is Number -> addProperty(key, value) is Number -> addProperty(key, value)
is Boolean -> addProperty(key, value) is Boolean -> addProperty(key, value)
is Enum<*> -> addProperty(key, value.toInt()) is Enum<*> -> addProperty(key, value.toInt())
else -> add(key, property.toJsonElement()) null -> add(key, null)
else -> add(key, value.toJsonElement())
} }
} }
} }

View File

@ -8,6 +8,7 @@ import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Rect import android.graphics.Rect
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.* import android.widget.*
import androidx.annotation.StringRes import androidx.annotation.StringRes
@ -161,3 +162,12 @@ val SwipeRefreshLayout.onScrollListener: RecyclerView.OnScrollListener
} }
} }
fun View.removeFromParent() {
(parent as? ViewGroup)?.removeView(this)
}
fun View.appendView(child: View) {
val parent = parent as? ViewGroup ?: return
val index = parent.indexOfChild(this)
parent.addView(child, index + 1)
}

View File

@ -142,13 +142,7 @@ class AgendaFragment : Fragment(), CoroutineScope {
private suspend fun checkEventTypes() { private suspend fun checkEventTypes() {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val eventTypes = app.db.eventTypeDao().getAllNow(app.profileId).map { app.db.eventTypeDao().getAllWithDefaults(app.profile)
it.id
}
val defaultEventTypes = EventType.getTypeColorMap().keys
if (!eventTypes.containsAll(defaultEventTypes)) {
app.db.eventTypeDao().addDefaultTypes(app.profile)
}
} }
} }

View File

@ -11,6 +11,7 @@ import android.widget.TextView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.github.tibolte.agendacalendarview.render.EventRenderer import com.github.tibolte.agendacalendarview.render.EventRenderer
import com.mikepenz.iconics.view.IconicsTextView import com.mikepenz.iconics.view.IconicsTextView
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding
import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventCompactBinding import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventCompactBinding
@ -53,16 +54,24 @@ class AgendaEventRenderer(
else else
event.time!!.stringHM event.time!!.stringHM
val agendaSubjectImportant = App.profile.config.ui.agendaSubjectImportant
val eventSubtitle = listOfNotNull( val eventSubtitle = listOfNotNull(
timeText, timeText,
event.subjectLongName, event.subjectLongName.takeIf { !agendaSubjectImportant },
event.typeName.takeIf { agendaSubjectImportant },
event.teacherName, event.teacherName,
event.teamName event.teamName
).join(", ") ).join(", ")
card.foreground.setTintColor(event.eventColor) card.foreground.setTintColor(event.eventColor)
card.background.setTintColor(event.eventColor) card.background.setTintColor(event.eventColor)
manager.setEventTopic(title, event, doneIconColor = textColor) manager.setEventTopic(
title = title,
event = event,
doneIconColor = textColor,
showType = !agendaSubjectImportant,
showSubject = agendaSubjectImportant,
)
title.setTextColor(textColor) title.setTextColor(textColor)
subtitle?.text = eventSubtitle subtitle?.text = eventSubtitle
subtitle?.setTextColor(textColor) subtitle?.setTextColor(textColor)

View File

@ -23,6 +23,7 @@ import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.config.Config import pl.szczodrzynski.edziennik.config.Config
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor
import pl.szczodrzynski.edziennik.data.db.entity.EventType.Companion.SOURCE_DEFAULT
import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding
import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.ui.base.lazypager.LazyFragment import pl.szczodrzynski.edziennik.ui.base.lazypager.LazyFragment
@ -65,6 +66,7 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
b.clearEndpointTimers.isVisible = false b.clearEndpointTimers.isVisible = false
b.rodo.isVisible = false b.rodo.isVisible = false
b.removeHomework.isVisible = false b.removeHomework.isVisible = false
b.resetEventTypes.isVisible = false
b.unarchive.isVisible = false b.unarchive.isVisible = false
b.profile.isVisible = false b.profile.isVisible = false
} }
@ -100,6 +102,11 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}") app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}")
} }
b.resetEventTypes.onClick {
app.db.eventTypeDao().clearBySource(App.profileId, SOURCE_DEFAULT)
app.db.eventTypeDao().getAllWithDefaults(App.profile)
}
b.chucker.isChecked = App.enableChucker b.chucker.isChecked = App.enableChucker
b.chucker.onChange { _, isChecked -> b.chucker.onChange { _, isChecked ->
app.config.enableChucker = isChecked app.config.enableChucker = isChecked

View File

@ -113,9 +113,20 @@ class EventDetailsDialog(
b.typeColor.background?.setTintColor(event.eventColor) b.typeColor.background?.setTintColor(event.eventColor)
b.details = mutableListOf( val agendaSubjectImportant = event.subjectLongName != null
&& App.config[event.profileId].ui.agendaSubjectImportant
b.name = if (agendaSubjectImportant)
event.subjectLongName
else
event.typeName
b.details = listOfNotNull(
if (agendaSubjectImportant)
event.typeName
else
event.subjectLongName, event.subjectLongName,
event.teamName?.asColoredSpannable(colorSecondary) event.teamName?.asColoredSpannable(colorSecondary)
).concat(bullet) ).concat(bullet)
b.addedBy.setText( b.addedBy.setText(

View File

@ -24,6 +24,7 @@ class EventListAdapter(
val showDate: Boolean = false, val showDate: Boolean = false,
val showColor: Boolean = true, val showColor: Boolean = true,
val showType: Boolean = true, val showType: Boolean = true,
val showTypeColor: Boolean = showType,
val showTime: Boolean = true, val showTime: Boolean = true,
val showSubject: Boolean = true, val showSubject: Boolean = true,
val markAsSeen: Boolean = true, val markAsSeen: Boolean = true,

View File

@ -19,7 +19,9 @@ import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.config.AppData
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
@ -35,9 +37,11 @@ import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.LessonFull import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
import pl.szczodrzynski.edziennik.ext.JsonObject import pl.szczodrzynski.edziennik.ext.JsonObject
import pl.szczodrzynski.edziennik.ext.appendView
import pl.szczodrzynski.edziennik.ext.getStudentData import pl.szczodrzynski.edziennik.ext.getStudentData
import pl.szczodrzynski.edziennik.ext.onChange import pl.szczodrzynski.edziennik.ext.onChange
import pl.szczodrzynski.edziennik.ext.onClick import pl.szczodrzynski.edziennik.ext.onClick
import pl.szczodrzynski.edziennik.ext.removeFromParent
import pl.szczodrzynski.edziennik.ext.setText import pl.szczodrzynski.edziennik.ext.setText
import pl.szczodrzynski.edziennik.ext.setTintColor import pl.szczodrzynski.edziennik.ext.setTintColor
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
@ -117,6 +121,15 @@ class EventManualDialog(
} }
override suspend fun onShow() { override suspend fun onShow() {
val data = withContext(Dispatchers.IO) {
val profile = app.db.profileDao().getByIdSuspend(profileId) ?: return@withContext null
AppData.get(profile.loginStoreType)
}
if (data?.uiConfig?.eventManualShowSubjectDropdown == true) {
b.subjectDropdownLayout.removeFromParent()
b.timeDropdownLayout.appendView(b.subjectDropdownLayout)
}
b.showMore.onClick { // TODO iconics is broken b.showMore.onClick { // TODO iconics is broken
it.apply { it.apply {
refreshDrawableState() refreshDrawableState()

View File

@ -113,7 +113,7 @@ class EventViewHolder(
b.attachmentIcon.isVisible = item.hasAttachments b.attachmentIcon.isVisible = item.hasAttachments
b.typeColor.background?.setTintColor(item.eventColor) b.typeColor.background?.setTintColor(item.eventColor)
b.typeColor.isVisible = adapter.showType && adapter.showColor b.typeColor.isVisible = adapter.showTypeColor
b.editButton.isVisible = !adapter.simpleMode b.editButton.isVisible = !adapter.simpleMode
&& item.addedManually && item.addedManually

View File

@ -4,8 +4,10 @@
package pl.szczodrzynski.edziennik.ui.home package pl.szczodrzynski.edziennik.ui.home
import android.graphics.BitmapFactory
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.jetradarmobile.snowfall.SnowfallView
import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
@ -20,6 +22,7 @@ import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
import pl.szczodrzynski.edziennik.ext.timeLeft import pl.szczodrzynski.edziennik.ext.timeLeft
import pl.szczodrzynski.edziennik.ext.timeTill import pl.szczodrzynski.edziennik.ext.timeTill
import pl.szczodrzynski.edziennik.ui.dialogs.BellSyncTimeChooseDialog import pl.szczodrzynski.edziennik.ui.dialogs.BellSyncTimeChooseDialog
import pl.szczodrzynski.edziennik.utils.BigNightUtil
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -61,6 +64,7 @@ class CounterActivity : AppCompatActivity(), CoroutineScope {
it.type != Lesson.TYPE_SHIFTED_SOURCE it.type != Lesson.TYPE_SHIFTED_SOURCE
}) })
} }
lessonList.onEach { it.filterNotes() }
} }
b.bellSync.setImageDrawable( b.bellSync.setImageDrawable(
@ -81,6 +85,27 @@ class CounterActivity : AppCompatActivity(), CoroutineScope {
counterJob = startCoroutineTimer(repeatMillis = 500) { counterJob = startCoroutineTimer(repeatMillis = 500) {
update() update()
} }
// IT'S WINTER MY DUDES
val today = Date.getToday()
if ((today.month / 3 % 4 == 0) && app.config.ui.snowfall) {
b.rootFrame.addView(layoutInflater.inflate(R.layout.snowfall, b.rootFrame, false))
} else if (app.config.ui.eggfall && BigNightUtil().isDataWielkanocyNearDzisiaj()) {
val eggfall = layoutInflater.inflate(
R.layout.eggfall,
b.rootFrame,
false
) as SnowfallView
eggfall.setSnowflakeBitmaps(listOf(
BitmapFactory.decodeResource(resources, R.drawable.egg1),
BitmapFactory.decodeResource(resources, R.drawable.egg2),
BitmapFactory.decodeResource(resources, R.drawable.egg3),
BitmapFactory.decodeResource(resources, R.drawable.egg4),
BitmapFactory.decodeResource(resources, R.drawable.egg5),
BitmapFactory.decodeResource(resources, R.drawable.egg6)
))
b.rootFrame.addView(eggfall)
}
}} }}
private fun update() { private fun update() {
@ -101,13 +126,15 @@ class CounterActivity : AppCompatActivity(), CoroutineScope {
when { when {
actual != null -> { actual != null -> {
b.lessonName.text = actual.displaySubjectName b.lessonName.text = actual.getNoteSubstituteText(showNotes = true)
?: actual.displaySubjectName
val left = actual.displayEndTime!! - now val left = actual.displayEndTime!! - now
b.timeLeft.text = timeLeft(left.toInt(), "\n", countInSeconds) b.timeLeft.text = timeLeft(left.toInt(), "\n", countInSeconds)
} }
next != null -> { next != null -> {
b.lessonName.text = next.displaySubjectName b.lessonName.text = next.getNoteSubstituteText(showNotes = true)
?: next.displaySubjectName
val till = next.displayStartTime!! - now val till = next.displayStartTime!! - now
b.timeLeft.text = timeTill(till.toInt(), "\n", countInSeconds) b.timeLeft.text = timeTill(till.toInt(), "\n", countInSeconds)

View File

@ -63,9 +63,10 @@ class HomeEventsCard(
simpleMode = true, simpleMode = true,
showWeekDay = true, showWeekDay = true,
showDate = true, showDate = true,
showType = true, showType = !profile.config.ui.agendaSubjectImportant,
showTypeColor = true,
showTime = false, showTime = false,
showSubject = false, showSubject = profile.config.ui.agendaSubjectImportant,
markAsSeen = false, markAsSeen = false,
onEventClick = { onEventClick = {
EventDetailsDialog( EventDetailsDialog(

View File

@ -232,6 +232,7 @@ class HomeTimetableCard(
} }
lessons = lessons.filter { it.type != Lesson.TYPE_NO_LESSONS } lessons = lessons.filter { it.type != Lesson.TYPE_NO_LESSONS }
lessons.onEach { it.filterNotes() }
b.timetableLayout.visibility = View.VISIBLE b.timetableLayout.visibility = View.VISIBLE
b.noTimetableLayout.visibility = View.GONE b.noTimetableLayout.visibility = View.GONE
@ -344,6 +345,7 @@ class HomeTimetableCard(
private val LessonFull?.subjectSpannable: CharSequence private val LessonFull?.subjectSpannable: CharSequence
get() = if (this == null) "?" else when { get() = if (this == null) "?" else when {
hasReplacingNotes() -> getNoteSubstituteText(showNotes = true) ?: "?"
isCancelled -> displaySubjectName?.asStrikethroughSpannable() ?: "?" isCancelled -> displaySubjectName?.asStrikethroughSpannable() ?: "?"
isChange -> displaySubjectName?.asItalicSpannable() ?: "?" isChange -> displaySubjectName?.asItalicSpannable() ?: "?"
else -> displaySubjectName ?: "?" else -> displaySubjectName ?: "?"

View File

@ -33,13 +33,8 @@ class EventTypeDropdown : TextInputDropDown {
suspend fun loadItems() { suspend fun loadItems() {
val types = withContext(Dispatchers.Default) { val types = withContext(Dispatchers.Default) {
val list = mutableListOf<Item>() val list = mutableListOf<Item>()
val types = db.eventTypeDao().getAllNow(profileId)
var types = db.eventTypeDao().getAllNow(profileId) .sortedBy { it.order }
if (types.none { it.id in -1L..10L }) {
val profile = db.profileDao().getByIdNow(profileId) ?: return@withContext listOf()
types = db.eventTypeDao().addDefaultTypes(profile)
}
list += types.map { list += types.map {
Item(it.id, it.name, tag = it, icon = IconicsDrawable(context).apply { Item(it.id, it.name, tag = it, icon = IconicsDrawable(context).apply {

View File

@ -337,8 +337,11 @@ class WidgetTimetableProvider : AppWidgetProvider() {
scrollPos = pos + 1 scrollPos = pos + 1
} }
// remove notes from other profiles
lesson.filterNotes()
// set the subject and classroom name // set the subject and classroom name
model.subjectName = lesson.displaySubjectName model.subjectName = lesson.getNoteSubstituteText(showNotes = true)
?: lesson.displaySubjectName
model.classroomName = lesson.displayClassroom model.classroomName = lesson.displayClassroom
// set the bell sync to calculate progress in ListProvider // set the bell sync to calculate progress in ListProvider

View File

@ -48,6 +48,7 @@ class EventManager(val app: App) : CoroutineScope {
title: TextView, title: TextView,
event: EventFull, event: EventFull,
showType: Boolean = true, showType: Boolean = true,
showSubject: Boolean = false,
showNotes: Boolean = true, showNotes: Boolean = true,
doneIconColor: Int? = null doneIconColor: Int? = null
) { ) {
@ -60,6 +61,7 @@ class EventManager(val app: App) : CoroutineScope {
if (event.hasNotes() && hasReplacingNotes && showNotes) "{cmd-swap-horizontal} " else null, if (event.hasNotes() && hasReplacingNotes && showNotes) "{cmd-swap-horizontal} " else null,
if (event.hasNotes() && !hasReplacingNotes && showNotes) "{cmd-playlist-edit} " else null, if (event.hasNotes() && !hasReplacingNotes && showNotes) "{cmd-playlist-edit} " else null,
if (showType) "${event.typeName ?: "wydarzenie"} - " else null, if (showType) "${event.typeName ?: "wydarzenie"} - " else null,
if (showSubject) event.subjectLongName?.plus(" - ") else null,
topicSpan, topicSpan,
).concat() ).concat()

View File

@ -171,7 +171,7 @@ class NoteManager(private val app: App) {
activity = activity, activity = activity,
simpleMode = true, simpleMode = true,
showDate = true, showDate = true,
showColor = false, showTypeColor = false,
showTime = false, showTime = false,
markAsSeen = false, markAsSeen = false,
showNotes = false, showNotes = false,

View File

@ -19,7 +19,7 @@ public class ItemWidgetTimetableModel {
public Time endTime; public Time endTime;
public boolean lessonPassed; public boolean lessonPassed;
public boolean lessonCurrent; public boolean lessonCurrent;
public String subjectName = ""; public CharSequence subjectName = "";
public String classroomName = ""; public String classroomName = "";
public boolean lessonChange = false; public boolean lessonChange = false;
public boolean lessonChangeNoClassroom = false; public boolean lessonChangeNoClassroom = false;

View File

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootFrame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -50,4 +53,4 @@
android:textSize="48sp" android:textSize="48sp"
tools:text="Zostało 2341 sekund" /> tools:text="Zostało 2341 sekund" />
</LinearLayout> </LinearLayout>
</layout> </FrameLayout>

View File

@ -50,6 +50,14 @@
android:minHeight="32dp" android:minHeight="32dp"
android:text="@string/agenda_config_teacher_absence" /> android:text="@string/agenda_config_teacher_absence" />
<com.google.android.material.checkbox.MaterialCheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checked="@={config.ui.agendaSubjectImportant}"
android:minHeight="32dp"
android:text="@string/agenda_config_subject_important" />
<com.google.android.material.checkbox.MaterialCheckBox <com.google.android.material.checkbox.MaterialCheckBox
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -17,6 +17,7 @@
type="pl.szczodrzynski.edziennik.data.db.full.EventFull" /> type="pl.szczodrzynski.edziennik.data.db.full.EventFull" />
<variable name="eventShared" type="boolean" /> <variable name="eventShared" type="boolean" />
<variable name="eventOwn" type="boolean" /> <variable name="eventOwn" type="boolean" />
<variable name="name" type="java.lang.CharSequence" />
<variable name="details" type="java.lang.CharSequence" /> <variable name="details" type="java.lang.CharSequence" />
<variable name="monthName" type="String" /> <variable name="monthName" type="String" />
</data> </data>
@ -55,7 +56,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{event.typeName}" android:text="@{name}"
android:textIsSelectable="true" android:textIsSelectable="true"
android:textAppearance="@style/NavView.TextView.Title" android:textAppearance="@style/NavView.TextView.Title"
android:visibility="@{event.typeName == null ? View.GONE : View.VISIBLE}" android:visibility="@{event.typeName == null ? View.GONE : View.VISIBLE}"

View File

@ -13,6 +13,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:id="@+id/mainLayout"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -34,6 +35,7 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/timeDropdownLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense" style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -163,6 +165,7 @@
tools:visibility="visible"> tools:visibility="visible">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/subjectDropdownLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -100,6 +100,13 @@
android:text="Remove all homework body (null)" android:text="Remove all homework body (null)"
android:textAllCaps="false" /> android:textAllCaps="false" />
<Button
android:id="@+id/resetEventTypes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reset event types"
android:textAllCaps="false" />
<TextView <TextView
android:id="@+id/cookies" android:id="@+id/cookies"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -12,7 +12,8 @@
"uiConfig": { "uiConfig": {
"lessonHeight": 60, "lessonHeight": 60,
"enableMarkAsReadAnnouncements": true, "enableMarkAsReadAnnouncements": true,
"enableNoticePoints": false "enableNoticePoints": false,
"eventManualShowSubjectDropdown": false
}, },
"eventTypes": [ "eventTypes": [
{ {
@ -83,43 +84,40 @@
}, },
"university": { "university": {
"configOverrides": { "configOverrides": {
"agendaSubjectImportant": true,
"shareByDefault": true, "shareByDefault": true,
"timetableColorSubjectName": true, "timetableColorSubjectName": true,
"timetableTrimHourRange": true "timetableTrimHourRange": true
}, },
"uiConfig": { "uiConfig": {
"lessonHeight": 45 "lessonHeight": 45,
"eventManualShowSubjectDropdown": true
}, },
"eventTypes": [ "eventTypes": [
{ {
"id": 1, "id": 3,
"color": "#f44336", "color": "#76ff03",
"name": "egzamin" "name": "kartkówka"
}, },
{ {
"id": 2, "id": 2,
"color": "#e91e63", "color": "#e91e63",
"name": "kolokwium" "name": "kolokwium"
}, },
{
"id": 3,
"color": "#76ff03",
"name": "kartkówka"
},
{
"id": 4,
"color": "#ffeb3b",
"name": "wejściówka"
},
{ {
"id": 5, "id": 5,
"color": "#90caf9", "color": "#90caf9",
"name": "zaliczenie" "name": "zaliczenie"
}, },
{ {
"id": 6, "id": 1,
"color": "#4050b5", "color": "#f44336",
"name": "zadanie" "name": "egzamin"
},
{
"id": 11,
"color": "#3d5afe",
"name": "poprawka"
}, },
{ {
"id": 7, "id": 7,

View File

@ -1551,4 +1551,5 @@
<string name="settings_register_share_by_default_subtext">Ustaw tworzone wydarzenia domyślnie jako udostępnione</string> <string name="settings_register_share_by_default_subtext">Ustaw tworzone wydarzenia domyślnie jako udostępnione</string>
<string name="settings_registration_section">Rejestracja</string> <string name="settings_registration_section">Rejestracja</string>
<string name="home_timetable_all_lessons">Wszystkie lekcje:</string> <string name="home_timetable_all_lessons">Wszystkie lekcje:</string>
<string name="agenda_config_subject_important">Wyświetl nazwę przedmiotu zamiast rodzaju</string>
</resources> </resources>

View File

@ -5,8 +5,8 @@ buildscript {
kotlin_version = '1.6.10' kotlin_version = '1.6.10'
release = [ release = [
versionName: "4.13.1", versionName: "4.13.4",
versionCode: 4130199 versionCode: 4130499
] ]
setup = [ setup = [