mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-20 00:58:02 +02:00
Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
31b569b02e | |||
8bf77817d2 | |||
27b61adf1d | |||
a0244841ad | |||
12c0c6f2ec | |||
aaa3b8626e | |||
48c9e2dfe3 | |||
81d4801d27 | |||
5f8016061d | |||
5007587192 | |||
dfd1083e41 | |||
678baf46e5 | |||
4077fe448d | |||
f085e17ef7 | |||
7fd2cad46b | |||
93dc2ac9ab | |||
ac53e267fc | |||
86eb1a0f42 | |||
710d82da27 | |||
0123f50810 | |||
6d3eb65445 | |||
a9a0630226 | |||
ec7577f999 | |||
05c7c0012c | |||
d65c6db954 | |||
771dc437e6 | |||
3d5d3847cc |
3
.github/workflows/build-release-aab-play.yml
vendored
3
.github/workflows/build-release-aab-play.yml
vendored
@ -113,10 +113,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
||||||
packageName: pl.szczodrzynski.edziennik
|
packageName: pl.szczodrzynski.edziennik
|
||||||
releaseFile: ${{ needs.sign.outputs.signedReleaseFile }}
|
releaseFiles: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||||
releaseName: ${{ steps.changelog.outputs.appVersionName }}
|
releaseName: ${{ steps.changelog.outputs.appVersionName }}
|
||||||
track: ${{ secrets.PLAY_RELEASE_TRACK }}
|
track: ${{ secrets.PLAY_RELEASE_TRACK }}
|
||||||
whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }}
|
whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }}
|
||||||
|
status: completed
|
||||||
|
|
||||||
- name: Upload workflow artifact
|
- name: Upload workflow artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
<h3>Wersja 4.13, 2022-10-26</h3>
|
<h3>Wersja 4.13.5, 2023-03-22</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Poprawione powiadomienia na Androidzie 13. @santoni0</li>
|
<li>Naprawiono pobieranie załączników na Androidzie 13 i nowszym.</li>
|
||||||
<li>Opcja kolorowania bloków w planie lekcji.</li>
|
|
||||||
<li><b>USOS</b> - pierwsza wersja obsługi systemu. Osobne rodzaje wydarzeń (oraz wygląd niektórych części aplikacji) lepiej dostosowany do nauki na studiach.</li>
|
|
||||||
<li>Możliwość dostosowania wyświetlania planu lekcji.</li>
|
|
||||||
<li>Opcja ustawienia nowych wydarzeń domyślnie jako udostępnione.</li>
|
|
||||||
<li>Poprawione udostępnianie notatek dotyczących danej lekcji</li>
|
|
||||||
<li>Bardziej czytelna legenda rodzaju udostępnionego wydarzenia.</li>
|
|
||||||
<li>Poprawione opcje filtrowania powiadomień i wyboru przycisków menu bocznego.</li>
|
|
||||||
<li>Ulepszony system pobierania aktualizacji aplikacji.</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
Dzięki za korzystanie ze Szkolnego!<br>
|
Dzięki za korzystanie ze Szkolnego!<br>
|
||||||
<i>© [Kuba Szczodrzyński](@kuba2k2) 2022</i>
|
<i>© [Kuba Szczodrzyński](@kuba2k2) 2023</i>
|
||||||
|
@ -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] = {
|
||||||
0xce, 0x63, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
0x92, 0xc2, 0xe7, 0x13, 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);
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Signing.getCert(this)
|
Signing.getCert(this)
|
||||||
|
Utils.initializeStorageDir(this)
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
@ -422,6 +423,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()
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class Config(db: AppDb) : BaseConfig(db) {
|
|||||||
var update by config<Update?>(null)
|
var update by config<Update?>(null)
|
||||||
var updatesChannel by config<String>("release")
|
var updatesChannel by config<String>("release")
|
||||||
|
|
||||||
var devMode by config<Boolean?>(null)
|
var devMode by config<Boolean?>("debugMode", null)
|
||||||
var devModePassword by config<String?>(null)
|
var devModePassword by config<String?>(null)
|
||||||
var enableChucker by config<Boolean?>(null)
|
var enableChucker by config<Boolean?>(null)
|
||||||
|
|
||||||
|
@ -115,9 +115,9 @@ class ConfigDelegate<T>(
|
|||||||
is Boolean -> value
|
is Boolean -> value
|
||||||
// enums, maps & collections
|
// enums, maps & collections
|
||||||
is Enum<*> -> value.toInt()
|
is Enum<*> -> value.toInt()
|
||||||
is Collection<*> -> JsonArray(value.map {
|
is Collection<*> -> value.map {
|
||||||
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
|
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
|
||||||
})
|
}.toJsonElement()
|
||||||
is Map<*, *> -> gson.toJson(value.mapValues { (_, it) ->
|
is Map<*, *> -> gson.toJson(value.mapValues { (_, it) ->
|
||||||
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
|
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
|
||||||
})
|
})
|
||||||
|
@ -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) }
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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;")
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ class LibrusApiNotices(override val data: DataLibrus,
|
|||||||
val id = note.getLong("Id") ?: return@forEach
|
val id = note.getLong("Id") ?: return@forEach
|
||||||
val text = note.getString("Text") ?: ""
|
val text = note.getString("Text") ?: ""
|
||||||
val categoryId = note.getJsonObject("Category")?.getLong("Id") ?: -1
|
val categoryId = note.getJsonObject("Category")?.getLong("Id") ?: -1
|
||||||
val teacherId = note.getJsonObject("AddedBy")?.getLong("Id") ?: -1
|
val teacherId = note.getJsonObject("Teacher")?.getLong("Id") ?: -1
|
||||||
val addedDate = note.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach
|
val addedDate = note.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach
|
||||||
|
|
||||||
val type = when (note.getInt("Positive")) {
|
val type = when (note.getInt("Positive")) {
|
||||||
|
@ -125,7 +125,7 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
|
|||||||
val receiverId = teacher?.id ?: -1
|
val receiverId = teacher?.id ?: -1
|
||||||
teacher?.loginId = receiverLoginId
|
teacher?.loginId = receiverLoginId
|
||||||
|
|
||||||
val readDateText = message.select("readed").text()
|
val readDateText = receiver.select("readed").text()
|
||||||
val readDate = when (readDateText.isNotNullNorEmpty()) {
|
val readDate = when (readDateText.isNotNullNorEmpty()) {
|
||||||
true -> Date.fromIso(readDateText)
|
true -> Date.fromIso(readDateText)
|
||||||
else -> 0
|
else -> 0
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.MTIzNDU2Nzg5MDHSZrnOj0===.$param2".sha256()
|
return "$param1.MTIzNDU2Nzg5MD3uL2uE3E===.$param2".sha256()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>>
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package pl.szczodrzynski.edziennik.ext
|
package pl.szczodrzynski.edziennik.ext
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -48,6 +49,11 @@ fun JsonObject.putEnum(key: String, value: Enum<*>) = addProperty(key, value.toI
|
|||||||
fun String.toJsonObject(): JsonObject? = try { JsonParser.parseString(this).asJsonObject } catch (ignore: Exception) { null }
|
fun String.toJsonObject(): JsonObject? = try { JsonParser.parseString(this).asJsonObject } catch (ignore: Exception) { null }
|
||||||
fun String.toJsonArray(): JsonArray? = try { JsonParser.parseString(this).asJsonArray } catch (ignore: Exception) { null }
|
fun String.toJsonArray(): JsonArray? = try { JsonParser.parseString(this).asJsonArray } catch (ignore: Exception) { null }
|
||||||
|
|
||||||
|
fun Any?.toJsonElement(): JsonElement = when (this) {
|
||||||
|
is Collection<*> -> JsonArray(this)
|
||||||
|
else -> Gson().toJsonTree(this)
|
||||||
|
}
|
||||||
|
|
||||||
operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value)
|
operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value)
|
||||||
operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value)
|
operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value)
|
||||||
operator fun JsonObject.set(key: String, value: String?) = this.addProperty(key, value)
|
operator fun JsonObject.set(key: String, value: String?) = this.addProperty(key, value)
|
||||||
@ -67,6 +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())
|
||||||
|
null -> add(key, null)
|
||||||
|
else -> add(key, value.toJsonElement())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,6 +106,8 @@ fun JsonArray(properties: Collection<Any?>): JsonArray {
|
|||||||
is Char -> add(property as Char?)
|
is Char -> add(property as Char?)
|
||||||
is Number -> add(property as Number?)
|
is Number -> add(property as Number?)
|
||||||
is Boolean -> add(property as Boolean?)
|
is Boolean -> add(property as Boolean?)
|
||||||
|
is Enum<*> -> add(property.toInt())
|
||||||
|
else -> add(property.toJsonElement())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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(
|
||||||
|
@ -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 ?: "?"
|
||||||
|
@ -109,12 +109,10 @@ class GenerateBlockTimetableDialog(
|
|||||||
.show()
|
.show()
|
||||||
|
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.onClick {
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.onClick {
|
||||||
app.permissionManager.requestStoragePermission(activity, permissionMessage = R.string.permissions_generate_timetable) {
|
when (b.weekSelectionRadioGroup.checkedRadioButtonId) {
|
||||||
when (b.weekSelectionRadioGroup.checkedRadioButtonId) {
|
R.id.withChangesCurrentWeekRadio -> generateBlockTimetable(weekCurrentStart, weekCurrentEnd)
|
||||||
R.id.withChangesCurrentWeekRadio -> generateBlockTimetable(weekCurrentStart, weekCurrentEnd)
|
R.id.withChangesNextWeekRadio -> generateBlockTimetable(weekNextStart, weekNextEnd)
|
||||||
R.id.withChangesNextWeekRadio -> generateBlockTimetable(weekNextStart, weekNextEnd)
|
R.id.forSelectedWeekRadio -> selectDate()
|
||||||
R.id.forSelectedWeekRadio -> selectDate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package pl.szczodrzynski.edziennik.ui.views
|
package pl.szczodrzynski.edziennik.ui.views
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@ -50,6 +51,10 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
val attachmentSizes = arguments.getLongArray("attachmentSizes")
|
val attachmentSizes = arguments.getLongArray("attachmentSizes")
|
||||||
|
|
||||||
val adapter = AttachmentAdapter(context, onAttachmentClick = { item ->
|
val adapter = AttachmentAdapter(context, onAttachmentClick = { item ->
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
downloadAttachment(item)
|
||||||
|
return@AttachmentAdapter
|
||||||
|
}
|
||||||
app.permissionManager.requestStoragePermission(activity, R.string.permissions_attachment) {
|
app.permissionManager.requestStoragePermission(activity, R.string.permissions_attachment) {
|
||||||
downloadAttachment(item)
|
downloadAttachment(item)
|
||||||
}
|
}
|
||||||
@ -57,6 +62,10 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
val popupMenu = PopupMenu(chip.context, chip)
|
val popupMenu = PopupMenu(chip.context, chip)
|
||||||
popupMenu.menu.add(0, 1, 0, R.string.messages_attachment_download_again)
|
popupMenu.menu.add(0, 1, 0, R.string.messages_attachment_download_again)
|
||||||
popupMenu.setOnMenuItemClickListener {
|
popupMenu.setOnMenuItemClickListener {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
downloadAttachment(item)
|
||||||
|
return@setOnMenuItemClickListener true
|
||||||
|
}
|
||||||
app.permissionManager.requestStoragePermission(activity, R.string.permissions_attachment) {
|
app.permissionManager.requestStoragePermission(activity, R.string.permissions_attachment) {
|
||||||
downloadAttachment(item, forceDownload = true)
|
downloadAttachment(item, forceDownload = true)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -774,14 +774,21 @@ public class Utils {
|
|||||||
|
|
||||||
private static File storageDir = null;
|
private static File storageDir = null;
|
||||||
public static File getStorageDir() {
|
public static File getStorageDir() {
|
||||||
if (storageDir != null)
|
|
||||||
return storageDir;
|
|
||||||
storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
|
||||||
storageDir = new File(storageDir, "Szkolny.eu");
|
|
||||||
storageDir.mkdirs();
|
|
||||||
return storageDir;
|
return storageDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void initializeStorageDir(Context context) {
|
||||||
|
if (storageDir != null)
|
||||||
|
return;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
storageDir = context.getExternalFilesDir(null);
|
||||||
|
} else {
|
||||||
|
storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||||
|
storageDir = new File(storageDir, "Szkolny.eu");
|
||||||
|
}
|
||||||
|
storageDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeStringToFile(File file, String data) throws IOException {
|
public static void writeStringToFile(File file, String data) throws IOException {
|
||||||
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file));
|
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file));
|
||||||
outputStreamWriter.write(data);
|
outputStreamWriter.write(data);
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
@ -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}"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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,
|
||||||
|
@ -847,7 +847,7 @@
|
|||||||
<string name="settings_about_licenses_text">Open-Source-Lizenzen</string>
|
<string name="settings_about_licenses_text">Open-Source-Lizenzen</string>
|
||||||
<string name="settings_about_privacy_policy_text">Datenschutzrichtlinie</string>
|
<string name="settings_about_privacy_policy_text">Datenschutzrichtlinie</string>
|
||||||
<string name="settings_card_register_title">E-Klassenbuch</string>
|
<string name="settings_card_register_title">E-Klassenbuch</string>
|
||||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński, September 2018 - 2022</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński, September 2018 - 2023</string>
|
||||||
<string name="settings_about_update_subtext">Klicken Sie hier, um nach Aktualisierungen zu suchen</string>
|
<string name="settings_about_update_subtext">Klicken Sie hier, um nach Aktualisierungen zu suchen</string>
|
||||||
<string name="settings_about_update_text">Aktualisierung</string>
|
<string name="settings_about_update_text">Aktualisierung</string>
|
||||||
<string name="settings_about_version_text">Version</string>
|
<string name="settings_about_version_text">Version</string>
|
||||||
|
@ -849,7 +849,7 @@
|
|||||||
<string name="settings_about_licenses_text">Open-source licenses</string>
|
<string name="settings_about_licenses_text">Open-source licenses</string>
|
||||||
<string name="settings_about_privacy_policy_text">Privacy policy</string>
|
<string name="settings_about_privacy_policy_text">Privacy policy</string>
|
||||||
<string name="settings_card_register_title">E-register</string>
|
<string name="settings_card_register_title">E-register</string>
|
||||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński, September 2018 – 2022</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński, September 2018 – 2023</string>
|
||||||
<string name="settings_about_update_subtext">Click to check for updates</string>
|
<string name="settings_about_update_subtext">Click to check for updates</string>
|
||||||
<string name="settings_about_update_text">Update</string>
|
<string name="settings_about_update_text">Update</string>
|
||||||
<string name="settings_about_version_text">Version</string>
|
<string name="settings_about_version_text">Version</string>
|
||||||
@ -1353,7 +1353,6 @@
|
|||||||
<string name="home_archive_close_no_target_text">Child %s does not have a profile on this account in the current school year. Probably this profile has been deleted or the student no longer attends this class.\n\nTo go to the current profile, select a student from the list or log in to their account with the Add student button.</string>
|
<string name="home_archive_close_no_target_text">Child %s does not have a profile on this account in the current school year. Probably this profile has been deleted or the student no longer attends this class.\n\nTo go to the current profile, select a student from the list or log in to their account with the Add student button.</string>
|
||||||
<string name="build_invalid_no_remote_repo">A reference to a remote repository was not found. Make sure you are using the official repository fork and verify your Gradle configuration.</string>
|
<string name="build_invalid_no_remote_repo">A reference to a remote repository was not found. Make sure you are using the official repository fork and verify your Gradle configuration.</string>
|
||||||
<string name="login_mode_mobidziennik_web_guide">"Enter the data you use to log in to the MobiDziennik website. As the server address, you can enter the address of the website where you have MobiDziennik. "</string>
|
<string name="login_mode_mobidziennik_web_guide">"Enter the data you use to log in to the MobiDziennik website. As the server address, you can enter the address of the website where you have MobiDziennik. "</string>
|
||||||
<string name="permissions_generate_timetable">In order to be able to save the generated timetable, you must grant access rights to the device\'s memory.\n\nClick OK to grant permissions.</string>
|
|
||||||
<string name="login_summary_account_child">(Child)</string>
|
<string name="login_summary_account_child">(Child)</string>
|
||||||
<string name="login_summary_account_parent">(Parent)</string>
|
<string name="login_summary_account_parent">(Parent)</string>
|
||||||
<string name="menu_teachers">Teachers</string>
|
<string name="menu_teachers">Teachers</string>
|
||||||
@ -1433,4 +1432,5 @@
|
|||||||
<string name="dialog_lesson_attendance_details">Details</string>
|
<string name="dialog_lesson_attendance_details">Details</string>
|
||||||
<string name="menu_agenda_config">Agenda settings</string>
|
<string name="menu_agenda_config">Agenda settings</string>
|
||||||
<string name="registration_config_note_sharing_title">Share notes</string>
|
<string name="registration_config_note_sharing_title">Share notes</string>
|
||||||
|
<string name="home_timetable_all_lessons">All lessons:</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -916,7 +916,7 @@
|
|||||||
<string name="settings_about_licenses_text">Licencje open-source</string>
|
<string name="settings_about_licenses_text">Licencje open-source</string>
|
||||||
<string name="settings_about_privacy_policy_text">Polityka prywatności</string>
|
<string name="settings_about_privacy_policy_text">Polityka prywatności</string>
|
||||||
<string name="settings_card_register_title">E-dziennik</string>
|
<string name="settings_card_register_title">E-dziennik</string>
|
||||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński, wrzesień 2018 - 2022</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński, wrzesień 2018 - 2023</string>
|
||||||
<string name="settings_about_update_subtext">Kliknij, aby sprawdzić aktualizacje</string>
|
<string name="settings_about_update_subtext">Kliknij, aby sprawdzić aktualizacje</string>
|
||||||
<string name="settings_about_update_text">Aktualizacja</string>
|
<string name="settings_about_update_text">Aktualizacja</string>
|
||||||
<string name="settings_about_version_text">Wersja</string>
|
<string name="settings_about_version_text">Wersja</string>
|
||||||
@ -1416,7 +1416,6 @@
|
|||||||
<string name="build_dialog_open_repo">Sprawdź kod</string>
|
<string name="build_dialog_open_repo">Sprawdź kod</string>
|
||||||
<string name="error_no_api_access">Brak dostępu do API</string>
|
<string name="error_no_api_access">Brak dostępu do API</string>
|
||||||
<string name="build_date">Data kompilacji</string>
|
<string name="build_date">Data kompilacji</string>
|
||||||
<string name="permissions_generate_timetable">Aby móc zapisać wygenerowany plan lekcji musisz przyznać uprawnienia dostępu do pamięci urządzenia.\n\nKliknij OK, aby przyznać uprawnienia.</string>
|
|
||||||
<string name="privacy_policy_dialog_html"><![CDATA[Korzystając z aplikacji potwierdzasz <a href="https://szkolny.eu/privacy-policy">przeczytanie Polityki prywatności</a> i akceptujesz jej postanowienia.<br /><br />Autorzy aplikacji nie biorą odpowiedzialności za korzystanie z aplikacji Szkolny.eu.]]></string>
|
<string name="privacy_policy_dialog_html"><![CDATA[Korzystając z aplikacji potwierdzasz <a href="https://szkolny.eu/privacy-policy">przeczytanie Polityki prywatności</a> i akceptujesz jej postanowienia.<br /><br />Autorzy aplikacji nie biorą odpowiedzialności za korzystanie z aplikacji Szkolny.eu.]]></string>
|
||||||
<string name="login_chooser_version_format">Szkolny.eu v%s\n%s</string>
|
<string name="login_chooser_version_format">Szkolny.eu v%s\n%s</string>
|
||||||
<string name="menu_agenda_config">Ustawienia terminarza</string>
|
<string name="menu_agenda_config">Ustawienia terminarza</string>
|
||||||
@ -1551,4 +1550,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>
|
||||||
|
@ -5,8 +5,8 @@ buildscript {
|
|||||||
kotlin_version = '1.6.10'
|
kotlin_version = '1.6.10'
|
||||||
|
|
||||||
release = [
|
release = [
|
||||||
versionName: "4.13",
|
versionName: "4.13.5",
|
||||||
versionCode: 4130099
|
versionCode: 4130599
|
||||||
]
|
]
|
||||||
|
|
||||||
setup = [
|
setup = [
|
||||||
|
Reference in New Issue
Block a user