mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-29 21:45:31 +02:00
Compare commits
16 Commits
v4.11-rc.2
...
v4.11.2
Author | SHA1 | Date | |
---|---|---|---|
98a89b1ca1 | |||
6d1e18cce2 | |||
8fe0f88be4 | |||
aeed735521 | |||
e314fafaff | |||
2ab0dd7546 | |||
aa06868a4e | |||
2b104e6463 | |||
afb1863827 | |||
d8228748e4 | |||
b0608c47c4 | |||
dda0d88f19 | |||
a1b5560977 | |||
86f5811bda | |||
3f11e75985 | |||
c39b5442c9 |
@ -1,23 +1,8 @@
|
|||||||
<h3>Wersja 4.11-rc.2, 2021-10-30</h3>
|
<h3>Wersja 4.11.2, 2022-02-05</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Nowości w module Wiadomości:</li>
|
<li>Mobidziennik: naprawiono brak nadawców w liście wiadomości.</li>
|
||||||
<li>→ <b>Formatowanie tekstu</b> przy wysyłaniu wiadomości oraz dodawaniu wydarzeń.</li>
|
|
||||||
<li>→ Zapisywanie <b>wersji roboczych</b> wiadomości, do późniejszej edycji i wysłania.</li>
|
|
||||||
<li>→ Możliwość <b>wyszukiwania zadań domowych</b>, podobnie jak wiadomości.</li>
|
|
||||||
<li>→ Dodawanie gwiazdki do wiadomości, w celu "przypięcia" na górę listy.</li>
|
|
||||||
<br>
|
|
||||||
<li>Opcja <b>dodawania notatek</b> do wydarzeń, ocen, lekcji, itp.</li>
|
|
||||||
<li>Możliwość udostępniania notatek w klasie, jako "ogłoszenia" widoczne na ekranie głównym.</li>
|
|
||||||
<br>
|
|
||||||
<li>Dodano <b>listę nauczycieli</b> w menu Więcej. @Antoni-Czaplicki</li>
|
|
||||||
<li>Logowanie: skaner kodów QR, uproszczone pole adresu w Mobidzienniku.</li>
|
|
||||||
<li>Naprawiono filtrowanie powiadomień.</li>
|
|
||||||
<li>Mobidziennik: dodano wyświetlanie lekcji z planów "pozalekcyjnych".</li>
|
|
||||||
<li>Mobidziennik: dodano pobieranie pełnej treści "informacji" w kalendarzu.</li>
|
|
||||||
<li>Mobidziennik: poprawiono wyświetlanie załączników oraz ich wielkości.</li>
|
|
||||||
<li>Dodano tajne funkcje. @Antoni-Czaplicki</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), [Kacper Ziubryniewicz](@kapi2289) 2021</i>
|
<i>© [Kuba Szczodrzyński](@kuba2k2), [Kacper Ziubryniewicz](@kapi2289) 2022</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] = {
|
||||||
0x15, 0x02, 0x8d, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
0x66, 0xae, 0x85, 0x2a, 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);
|
||||||
|
|
||||||
|
@ -182,10 +182,6 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
data.startProgress(R.string.edziennik_progress_endpoint_pt_meetings)
|
data.startProgress(R.string.edziennik_progress_endpoint_pt_meetings)
|
||||||
LibrusApiPtMeetings(data, lastSync, onSuccess)
|
LibrusApiPtMeetings(data, lastSync, onSuccess)
|
||||||
}
|
}
|
||||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_day_types)
|
|
||||||
LibrusApiTeacherFreeDayTypes(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS -> {
|
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_days)
|
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_days)
|
||||||
LibrusApiTeacherFreeDays(data, lastSync, onSuccess)
|
LibrusApiTeacherFreeDays(data, lastSync, onSuccess)
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-19
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsenceType
|
|
||||||
import pl.szczodrzynski.edziennik.ext.*
|
|
||||||
|
|
||||||
class LibrusApiTeacherFreeDayTypes(override val data: DataLibrus,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : LibrusApi(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiTeacherFreeDayTypes"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "TeacherFreeDays/Types") { json ->
|
|
||||||
val teacherAbsenceTypes = json.getJsonArray("Types")?.asJsonObjectList()
|
|
||||||
|
|
||||||
teacherAbsenceTypes?.forEach { teacherAbsenceType ->
|
|
||||||
val id = teacherAbsenceType.getLong("Id") ?: return@forEach
|
|
||||||
val name = teacherAbsenceType.getString("Name") ?: return@forEach
|
|
||||||
|
|
||||||
val teacherAbsenceTypeObject = TeacherAbsenceType(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
name
|
|
||||||
)
|
|
||||||
|
|
||||||
data.teacherAbsenceTypes.put(id, teacherAbsenceTypeObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES, 7 * DAY)
|
|
||||||
onSuccess(ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -36,8 +36,6 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
|
|||||||
val id = teacherAbsence.getLong("Id") ?: return@forEach
|
val id = teacherAbsence.getLong("Id") ?: return@forEach
|
||||||
val teacherId = teacherAbsence.getJsonObject("Teacher")?.getLong("Id")
|
val teacherId = teacherAbsence.getJsonObject("Teacher")?.getLong("Id")
|
||||||
?: return@forEach
|
?: return@forEach
|
||||||
val type = teacherAbsence.getJsonObject("Type").getLong("Id") ?: return@forEach
|
|
||||||
val name = data.teacherAbsenceTypes.singleOrNull { it.id == type }?.name
|
|
||||||
val dateFrom = Date.fromY_m_d(teacherAbsence.getString("DateFrom"))
|
val dateFrom = Date.fromY_m_d(teacherAbsence.getString("DateFrom"))
|
||||||
val dateTo = Date.fromY_m_d(teacherAbsence.getString("DateTo"))
|
val dateTo = Date.fromY_m_d(teacherAbsence.getString("DateTo"))
|
||||||
val timeFrom = teacherAbsence.getString("TimeFrom")?.let { Time.fromH_m_s(it) }
|
val timeFrom = teacherAbsence.getString("TimeFrom")?.let { Time.fromH_m_s(it) }
|
||||||
@ -46,8 +44,8 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
|
|||||||
val teacherAbsenceObject = TeacherAbsence(
|
val teacherAbsenceObject = TeacherAbsence(
|
||||||
profileId = profileId,
|
profileId = profileId,
|
||||||
id = id,
|
id = id,
|
||||||
type = type,
|
type = -1L,
|
||||||
name = name,
|
name = null,
|
||||||
dateFrom = dateFrom,
|
dateFrom = dateFrom,
|
||||||
dateTo = dateTo,
|
dateTo = dateTo,
|
||||||
timeFrom = timeFrom,
|
timeFrom = timeFrom,
|
||||||
|
@ -7,10 +7,12 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik
|
|||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_MOBIDZIENNIK_WEB
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_MOBIDZIENNIK_WEB
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
import pl.szczodrzynski.edziennik.data.api.models.Data
|
||||||
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.currentTimeUnix
|
import pl.szczodrzynski.edziennik.ext.currentTimeUnix
|
||||||
|
import pl.szczodrzynski.edziennik.ext.get
|
||||||
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
|
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
|
||||||
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
|
||||||
@ -35,6 +37,31 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
|
|||||||
|
|
||||||
override fun generateUserCode() = "$loginServerName:$loginUsername:$studentId"
|
override fun generateUserCode() = "$loginServerName:$loginUsername:$studentId"
|
||||||
|
|
||||||
|
fun parseDateTime(dateStr: String): Pair<Date, Time> {
|
||||||
|
// pt, 4 lut, 09:11
|
||||||
|
val dateParts = dateStr.split(',', ' ').filter { it.isNotEmpty() }
|
||||||
|
// [pt], [4], [lut], [09:11]
|
||||||
|
val date = Date.getToday()
|
||||||
|
date.day = dateParts[1].toIntOrNull() ?: 1
|
||||||
|
date.month = when (dateParts[2]) {
|
||||||
|
"sty" -> 1
|
||||||
|
"lut" -> 2
|
||||||
|
"mar" -> 3
|
||||||
|
"kwi" -> 4
|
||||||
|
"maj" -> 5
|
||||||
|
"cze" -> 6
|
||||||
|
"lip" -> 7
|
||||||
|
"sie" -> 8
|
||||||
|
"wrz" -> 9
|
||||||
|
"paź" -> 10
|
||||||
|
"lis" -> 11
|
||||||
|
"gru" -> 12
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
|
val time = Time.fromH_m(dateParts[3])
|
||||||
|
return date to time
|
||||||
|
}
|
||||||
|
|
||||||
val teachersMap = LongSparseArray<String>()
|
val teachersMap = LongSparseArray<String>()
|
||||||
val subjectsMap = LongSparseArray<String>()
|
val subjectsMap = LongSparseArray<String>()
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
|||||||
|
|
||||||
val doc = Jsoup.parse(text)
|
val doc = Jsoup.parse(text)
|
||||||
|
|
||||||
|
val today = Date.getToday()
|
||||||
|
var currentYear = today.year
|
||||||
|
var currentMonth = today.month
|
||||||
|
|
||||||
val list = doc.getElementsByClass("spis").first()?.getElementsByClass("podswietl")
|
val list = doc.getElementsByClass("spis").first()?.getElementsByClass("podswietl")
|
||||||
list?.forEach { item ->
|
list?.forEach { item ->
|
||||||
val id = item.attr("rel").toLongOrNull() ?: return@forEach
|
val id = item.attr("rel").toLongOrNull() ?: return@forEach
|
||||||
@ -47,15 +51,20 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
|||||||
}
|
}
|
||||||
val subject = subjectEl?.ownText() ?: ""
|
val subject = subjectEl?.ownText() ?: ""
|
||||||
|
|
||||||
val addedDateEl = item.select("td:eq(1) small").first()
|
val addedDateEl = item.select("td:eq(4)").first()
|
||||||
val addedDate = Date.fromIsoHm(addedDateEl?.text())
|
val (date, time) = data.parseDateTime(addedDateEl?.text()?.trim() ?: "")
|
||||||
|
if (date.month > currentMonth) {
|
||||||
|
currentYear--
|
||||||
|
}
|
||||||
|
currentMonth = date.month
|
||||||
|
date.year = currentYear
|
||||||
|
|
||||||
val senderEl = item.select("td:eq(2)").first()
|
val senderEl = item.select("td:eq(3)").first()
|
||||||
val senderName = senderEl?.ownText().fixName()
|
val senderName = senderEl?.ownText().fixName()
|
||||||
val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id
|
val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id
|
||||||
data.messageRecipientIgnoreList.add(MessageRecipient(profileId, -1, id))
|
data.messageRecipientIgnoreList.add(MessageRecipient(profileId, -1, id))
|
||||||
|
|
||||||
val isRead = item.select("td:eq(3) span").first()?.hasClass("wiadomosc_przeczytana") == true
|
val isRead = item.select("td:eq(5) span").first()?.hasClass("wiadomosc_przeczytana") == true
|
||||||
|
|
||||||
val message = Message(
|
val message = Message(
|
||||||
profileId = profileId,
|
profileId = profileId,
|
||||||
@ -64,7 +73,7 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
|||||||
subject = subject,
|
subject = subject,
|
||||||
body = null,
|
body = null,
|
||||||
senderId = senderId,
|
senderId = senderId,
|
||||||
addedDate = addedDate
|
addedDate = date.combineWith(time)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (hasAttachments)
|
if (hasAttachments)
|
||||||
|
@ -40,23 +40,29 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
|
|||||||
|
|
||||||
val doc = Jsoup.parse(text)
|
val doc = Jsoup.parse(text)
|
||||||
|
|
||||||
|
val today = Date.getToday()
|
||||||
|
var currentYear = today.year
|
||||||
|
var currentMonth = today.month
|
||||||
|
|
||||||
val list = doc.getElementsByClass("spis").first()?.getElementsByClass("podswietl")
|
val list = doc.getElementsByClass("spis").first()?.getElementsByClass("podswietl")
|
||||||
list?.forEach { item ->
|
list?.forEach { item ->
|
||||||
val id = item.attr("rel").toLongOrNull() ?: return@forEach
|
val id = item.attr("rel").toLongOrNull() ?: return@forEach
|
||||||
|
|
||||||
val subjectEl = item.select("td:eq(0)").first()
|
val subjectEl = item.select("td:eq(0)").first()
|
||||||
var hasAttachments = false
|
|
||||||
if (subjectEl?.getElementsByTag("a")?.size ?: 0 > 0) {
|
|
||||||
hasAttachments = true
|
|
||||||
}
|
|
||||||
val subject = subjectEl?.ownText() ?: ""
|
val subject = subjectEl?.ownText() ?: ""
|
||||||
|
|
||||||
val readByString = item.select("td:eq(2)").first()?.text() ?: ""
|
val attachmentsEl = item.select("td:eq(1)").first()
|
||||||
|
var hasAttachments = false
|
||||||
|
if (attachmentsEl?.getElementsByTag("a")?.size ?: 0 > 0) {
|
||||||
|
hasAttachments = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val readByString = item.select("td:eq(4)").first()?.text() ?: ""
|
||||||
val (readBy, sentTo) = Regexes.MOBIDZIENNIK_MESSAGE_SENT_READ_BY.find(readByString).let {
|
val (readBy, sentTo) = Regexes.MOBIDZIENNIK_MESSAGE_SENT_READ_BY.find(readByString).let {
|
||||||
(it?.get(1)?.toIntOrNull() ?: 0) to (it?.get(2)?.toIntOrNull() ?: 0)
|
(it?.get(1)?.toIntOrNull() ?: 0) to (it?.get(2)?.toIntOrNull() ?: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val recipientEl = item.select("td:eq(1) a span").first()
|
val recipientEl = item.select("td:eq(2) a span").first()
|
||||||
val recipientNames = recipientEl?.ownText()?.split(", ")
|
val recipientNames = recipientEl?.ownText()?.split(", ")
|
||||||
val readState = when (readBy) {
|
val readState = when (readBy) {
|
||||||
0 -> 0
|
0 -> 0
|
||||||
@ -69,8 +75,13 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
|
|||||||
data.messageRecipientIgnoreList.add(MessageRecipient(profileId, recipientId, -1, readState, id))
|
data.messageRecipientIgnoreList.add(MessageRecipient(profileId, recipientId, -1, readState, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
val addedDateEl = item.select("td:eq(3) small").first()
|
val addedDateEl = item.select("td:eq(3)").first()
|
||||||
val addedDate = Date.fromIsoHm(addedDateEl?.text())
|
val (date, time) = data.parseDateTime(addedDateEl?.text()?.trim() ?: "")
|
||||||
|
if (date.month > currentMonth) {
|
||||||
|
currentYear--
|
||||||
|
}
|
||||||
|
currentMonth = date.month
|
||||||
|
date.year = currentYear
|
||||||
|
|
||||||
val message = Message(
|
val message = Message(
|
||||||
profileId = profileId,
|
profileId = profileId,
|
||||||
@ -79,7 +90,7 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
|
|||||||
subject = subject,
|
subject = subject,
|
||||||
body = null,
|
body = null,
|
||||||
senderId = null,
|
senderId = null,
|
||||||
addedDate = addedDate
|
addedDate = date.combineWith(time)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (hasAttachments)
|
if (hasAttachments)
|
||||||
|
@ -137,31 +137,6 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.webPermissions = data.webPermissions.toMutableMap().also { map ->
|
|
||||||
val permissions = Regexes.VULCAN_WEB_PERMISSIONS.find(text)?.let { it[1] }
|
|
||||||
if (permissions?.isNotBlank() == true) {
|
|
||||||
val studentId = permissions.split("|")
|
|
||||||
.getOrNull(0)
|
|
||||||
?.base64DecodeToString()
|
|
||||||
?.toJsonObject()
|
|
||||||
?.getJsonArray("AuthInfos")
|
|
||||||
?.asJsonObjectList()
|
|
||||||
?.flatMap { authInfo ->
|
|
||||||
authInfo.getJsonArray("UczenIds")
|
|
||||||
?.map { it.asInt }
|
|
||||||
?: listOf()
|
|
||||||
}
|
|
||||||
?.firstOrNull()
|
|
||||||
?.toString()
|
|
||||||
data.app.cookieJar.set(
|
|
||||||
data.webHost ?: "vulcan.net.pl",
|
|
||||||
"idBiezacyUczen",
|
|
||||||
studentId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
map[symbol] = permissions
|
|
||||||
}
|
|
||||||
|
|
||||||
val schoolSymbols = mutableListOf<String>()
|
val schoolSymbols = mutableListOf<String>()
|
||||||
val clientUrl = "://uonetplus-uczen.${data.webHost}/$symbol/"
|
val clientUrl = "://uonetplus-uczen.${data.webHost}/$symbol/"
|
||||||
var clientIndex = text.indexOf(clientUrl)
|
var clientIndex = text.indexOf(clientUrl)
|
||||||
@ -186,6 +161,42 @@ open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.webPermissions = data.webPermissions.toMutableMap().also { map ->
|
||||||
|
val permissions = Regexes.VULCAN_WEB_PERMISSIONS.find(text)?.let { it[1] }
|
||||||
|
if (permissions?.isNotBlank() == true) {
|
||||||
|
val json = permissions.split("|")
|
||||||
|
.getOrNull(0)
|
||||||
|
?.base64DecodeToString()
|
||||||
|
?.toJsonObject()
|
||||||
|
val unitIds = json
|
||||||
|
?.getJsonArray("Units")
|
||||||
|
?.asJsonObjectList()
|
||||||
|
?.filter { unit ->
|
||||||
|
unit.getString("Symbol") in schoolSymbols
|
||||||
|
}
|
||||||
|
?.mapNotNull { it.getInt("Id") } ?: emptyList()
|
||||||
|
val studentId = json
|
||||||
|
?.getJsonArray("AuthInfos")
|
||||||
|
?.asJsonObjectList()
|
||||||
|
?.filter { authInfo ->
|
||||||
|
authInfo.getInt("JednostkaSprawozdawczaId") in unitIds
|
||||||
|
}
|
||||||
|
?.flatMap { authInfo ->
|
||||||
|
authInfo.getJsonArray("UczenIds")
|
||||||
|
?.map { it.asInt }
|
||||||
|
?: listOf()
|
||||||
|
}
|
||||||
|
?.firstOrNull()
|
||||||
|
?.toString()
|
||||||
|
data.app.cookieJar.set(
|
||||||
|
data.webHost ?: "vulcan.net.pl",
|
||||||
|
"idBiezacyUczen",
|
||||||
|
studentId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
map[symbol] = permissions
|
||||||
|
}
|
||||||
|
|
||||||
onSuccess(text, schoolSymbols)
|
onSuccess(text, schoolSymbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||||
|
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_TEACHERS
|
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_TEACHERS
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_TEACHERS
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_TEACHERS
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
import pl.szczodrzynski.edziennik.ext.DAY
|
import pl.szczodrzynski.edziennik.ext.DAY
|
||||||
import pl.szczodrzynski.edziennik.ext.getString
|
import pl.szczodrzynski.edziennik.ext.getString
|
||||||
|
|
||||||
@ -25,20 +27,32 @@ class VulcanHebeTeachers(
|
|||||||
TAG,
|
TAG,
|
||||||
VULCAN_HEBE_ENDPOINT_TEACHERS,
|
VULCAN_HEBE_ENDPOINT_TEACHERS,
|
||||||
HebeFilterType.BY_PERIOD,
|
HebeFilterType.BY_PERIOD,
|
||||||
lastSync = lastSync,
|
lastSync = 0L,
|
||||||
) { list, _ ->
|
) { list, _ ->
|
||||||
list.forEach { person ->
|
list.forEach { person ->
|
||||||
val name = person.getString("Name")
|
val name = person.getString("Name")
|
||||||
val surname = person.getString("Surname")
|
val surname = person.getString("Surname")
|
||||||
val displayName = person.getString("DisplayName")
|
val displayName = person.getString("DisplayName")
|
||||||
val subjectName = person.getString("Description") ?: return@apiGetList
|
val subjectName = person.getString("Description") ?: return@forEach
|
||||||
|
|
||||||
|
if (subjectName.isBlank()) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
val teacher = data.getTeacherByFirstLast(
|
val teacher = data.getTeacherByFirstLast(
|
||||||
name?.plus(" ")?.plus(surname) ?: displayName ?: return@forEach
|
name?.plus(" ")?.plus(surname) ?: displayName ?: return@forEach
|
||||||
)
|
)
|
||||||
|
|
||||||
teacher.addSubject(data.getSubject(null, subjectName).id)
|
when (subjectName) {
|
||||||
|
"Pedagog" -> teacher.setTeacherType(Teacher.TYPE_PEDAGOGUE)
|
||||||
|
else -> {
|
||||||
|
val subjectId = data.getSubject(null, subjectName).id
|
||||||
|
if (!teacher.subjects.contains(subjectId))
|
||||||
|
teacher.addSubject(subjectId)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.teacherOnConflictStrategy = OnConflictStrategy.REPLACE
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_TEACHERS, 2 * DAY)
|
data.setSyncNext(ENDPOINT_VULCAN_HEBE_TEACHERS, 2 * DAY)
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_TEACHERS)
|
onSuccess(ENDPOINT_VULCAN_HEBE_TEACHERS)
|
||||||
}
|
}
|
||||||
|
@ -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.MTIzNDU2Nzg5MDoVA49hWj===.$param2".sha256()
|
return "$param1.MTIzNDU2Nzg5MDMIlcxGrq===.$param2".sha256()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,10 @@ import android.os.Process
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||||
|
import com.chuckerteam.chucker.api.Chucker
|
||||||
|
import com.chuckerteam.chucker.api.Chucker.SCREEN_HTTP
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -95,6 +98,13 @@ class LabPageFragment : LazyFragment(), CoroutineScope {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (App.enableChucker) {
|
||||||
|
b.openChucker.isVisible = true
|
||||||
|
b.openChucker.onClick {
|
||||||
|
startActivity(Chucker.getLaunchIntent(activity, SCREEN_HTTP))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b.disableDebug.onClick {
|
b.disableDebug.onClick {
|
||||||
app.config.devMode = false
|
app.config.devMode = false
|
||||||
App.devMode = false
|
App.devMode = false
|
||||||
|
@ -262,7 +262,7 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
|||||||
if (credential.caseMode == FormField.CaseMode.UPPER_CASE)
|
if (credential.caseMode == FormField.CaseMode.UPPER_CASE)
|
||||||
text = text.uppercase()
|
text = text.uppercase()
|
||||||
if (credential.caseMode == FormField.CaseMode.LOWER_CASE)
|
if (credential.caseMode == FormField.CaseMode.LOWER_CASE)
|
||||||
text = text.uppercase()
|
text = text.lowercase()
|
||||||
|
|
||||||
credential.stripTextRegex?.let {
|
credential.stripTextRegex?.let {
|
||||||
text = text.replace(it.toRegex(), "")
|
text = text.replace(it.toRegex(), "")
|
||||||
|
@ -47,6 +47,15 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Chucker" />
|
android:text="Chucker" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/openChucker"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Open Chucker"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/last10unseen"
|
android:id="@+id/last10unseen"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -857,7 +857,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 && Kacper Ziubryniewicz\nSeptember 2018 - Oktober 2021</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2022</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>
|
||||||
|
@ -348,7 +348,7 @@
|
|||||||
<string name="event_information">information</string>
|
<string name="event_information">information</string>
|
||||||
<string name="event_list_added_by_format">Added %1$s by %2$s%3$s</string>
|
<string name="event_list_added_by_format">Added %1$s by %2$s%3$s</string>
|
||||||
<string name="event_list_added_by_self_format">Added %1$s by you%3$s</string>
|
<string name="event_list_added_by_self_format">Added %1$s by you%3$s</string>
|
||||||
<string name="event_list_added_by_unknown_format">Adde %1$s%3$s</string>
|
<string name="event_list_added_by_unknown_format">Added %1$s%3$s</string>
|
||||||
<string name="event_list_shared_by_format">{cmd-share-variant} %1$s by %2$s%3$s</string>
|
<string name="event_list_shared_by_format">{cmd-share-variant} %1$s by %2$s%3$s</string>
|
||||||
<string name="event_list_shared_by_self_format">{cmd-share-variant} %1$s by you%3$s</string>
|
<string name="event_list_shared_by_self_format">{cmd-share-variant} %1$s by you%3$s</string>
|
||||||
<string name="event_manual_remove">Removing event…</string>
|
<string name="event_manual_remove">Removing event…</string>
|
||||||
@ -859,7 +859,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 && Kacper Ziubryniewicz\nSeptember 2018 - October 2021</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2022</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>
|
||||||
@ -1287,7 +1287,7 @@
|
|||||||
<string name="attendance_details_time">Time</string>
|
<string name="attendance_details_time">Time</string>
|
||||||
<string name="settings_about_github_subtext">Help with app development on GitHub</string>
|
<string name="settings_about_github_subtext">Help with app development on GitHub</string>
|
||||||
<string name="build_platform">Distribution</string>
|
<string name="build_platform">Distribution</string>
|
||||||
<string name="build_validate_progress">Build verification in progress...</string>
|
<string name="build_validate_progress">Build verification in progress…</string>
|
||||||
<string name="attendance_tab_months">By months</string>
|
<string name="attendance_tab_months">By months</string>
|
||||||
<string name="attendance_tab_summary">Summary</string>
|
<string name="attendance_tab_summary">Summary</string>
|
||||||
<string name="attendance_details_type">Type</string>
|
<string name="attendance_details_type">Type</string>
|
||||||
@ -1307,7 +1307,7 @@
|
|||||||
<string name="settings_about_homepage_subtext">Get help or support authors</string>
|
<string name="settings_about_homepage_subtext">Get help or support authors</string>
|
||||||
<string name="build_invalid_title">Information about application version</string>
|
<string name="build_invalid_title">Information about application version</string>
|
||||||
<string name="home_archive_close_no_target_title">No current profile</string>
|
<string name="home_archive_close_no_target_title">No current profile</string>
|
||||||
<string name="login_platform_list_loading">Loading e-registers list...</string>
|
<string name="login_platform_list_loading">Loading e-registers list…</string>
|
||||||
<string name="login_mode_podlasie_api">Log in using token</string>
|
<string name="login_mode_podlasie_api">Log in using token</string>
|
||||||
<string name="login_mode_podlasie_api_guide">Provide mobile app token.</string>
|
<string name="login_mode_podlasie_api_guide">Provide mobile app token.</string>
|
||||||
<string name="attendance_config_title">Attendance configuration</string>
|
<string name="attendance_config_title">Attendance configuration</string>
|
||||||
@ -1321,10 +1321,10 @@
|
|||||||
<string name="login_mode_vulcan_api">Use token, symbol and PIN code</string>
|
<string name="login_mode_vulcan_api">Use token, symbol and PIN code</string>
|
||||||
<string name="login_mode_vulcan_api_hint">Register device on journal VULCAN® page</string>
|
<string name="login_mode_vulcan_api_hint">Register device on journal VULCAN® page</string>
|
||||||
<string name="login_mode_vulcan_web">Use e-mail/username and password</string>
|
<string name="login_mode_vulcan_web">Use e-mail/username and password</string>
|
||||||
<string name="edziennik_progress_login_podlasie_api">Logging in to PPE...</string>
|
<string name="edziennik_progress_login_podlasie_api">Logging in to PPE…</string>
|
||||||
<string name="login_type_podlasie">Podlaska Platforma Edukacyjna</string>
|
<string name="login_type_podlasie">Podlaska Platforma Edukacyjna</string>
|
||||||
<string name="login_mode_edudziennik_web">Log in using e-mail and password</string>
|
<string name="login_mode_edudziennik_web">Log in using e-mail and password</string>
|
||||||
<string name="edziennik_progress_login_vulcan_web_main">Logging in to VULCAN® register...</string>
|
<string name="edziennik_progress_login_vulcan_web_main">Logging in to VULCAN® register…</string>
|
||||||
<string name="login_mode_librus_jst">Login via VULCAN® platform</string>
|
<string name="login_mode_librus_jst">Login via VULCAN® platform</string>
|
||||||
<string name="login_mode_librus_email">Log in using e-mail</string>
|
<string name="login_mode_librus_email">Log in using e-mail</string>
|
||||||
<string name="attendance_details_id">Attendance ID</string>
|
<string name="attendance_details_id">Attendance ID</string>
|
||||||
@ -1377,4 +1377,78 @@
|
|||||||
<string name="menu_teachers">Teachers</string>
|
<string name="menu_teachers">Teachers</string>
|
||||||
<string name="edziennik_progress_endpoint_addressbook">Syncing addressbook…</string>
|
<string name="edziennik_progress_endpoint_addressbook">Syncing addressbook…</string>
|
||||||
<string name="send_message">Send message</string>
|
<string name="send_message">Send message</string>
|
||||||
|
<string name="color_black">Black</string>
|
||||||
|
<string name="color_grey">Gray</string>
|
||||||
|
<string name="card_type_notes">Notes</string>
|
||||||
|
<string name="menu_notes">Notes</string>
|
||||||
|
<string name="notes_editor_dialog_title">Edit note</string>
|
||||||
|
<string name="notes_editor_color">Color</string>
|
||||||
|
<string name="color_brown">Brown</string>
|
||||||
|
<string name="color_pink">Pink</string>
|
||||||
|
<string name="color_dark_blue">Dark blue</string>
|
||||||
|
<string name="color_purple">Purple</string>
|
||||||
|
<string name="color_blue">Blue</string>
|
||||||
|
<string name="color_teal">Teal</string>
|
||||||
|
<string name="color_green">Green</string>
|
||||||
|
<string name="color_yellow">Yellow</string>
|
||||||
|
<string name="color_orange">Orange</string>
|
||||||
|
<string name="color_red">Red</string>
|
||||||
|
<string name="notes_action_add">Add note</string>
|
||||||
|
<string name="notes_type_grade">Grade</string>
|
||||||
|
<string name="privacy_policy_dialog_html"><![CDATA[By using the application, you confirm that you have <a href="https://szkolny.eu/privacy-policy">read the Privacy Policy</a> and accept its provisions.<br /><br />The authors of the application are not responsible for the use of the Szkolny.eu application.]]></string>
|
||||||
|
<string name="login_chooser_version_format">Szkolny.eu v%s\n%s</string>
|
||||||
|
<string name="agenda_config_appearance">Appearance</string>
|
||||||
|
<string name="agenda_config_elearning">Online learning</string>
|
||||||
|
<string name="event_type_elearning">online lesson</string>
|
||||||
|
<string name="menu_messages_config">Messages settings</string>
|
||||||
|
<string name="message_delete">Delete</string>
|
||||||
|
<string name="message_reply">Reply</string>
|
||||||
|
<string name="message_forward">Forward</string>
|
||||||
|
<string name="discard">Discard</string>
|
||||||
|
<string name="messages_compose_draft_saved">Draft message saved</string>
|
||||||
|
<string name="messages_tab_draft">Drafts</string>
|
||||||
|
<string name="messages_compose_send_long">Send a message</string>
|
||||||
|
<string name="notes_button">Notes</string>
|
||||||
|
<string name="notes_list_dialog_title">Notes</string>
|
||||||
|
<string name="notes_added_by_you_format">Added on %1$s</string>
|
||||||
|
<string name="notes_type_attendance">Attendance</string>
|
||||||
|
<string name="notes_type_behavior">Behavior</string>
|
||||||
|
<string name="notes_type_day">Day</string>
|
||||||
|
<string name="notes_type_event">Event</string>
|
||||||
|
<string name="notes_type_lesson">Lesson</string>
|
||||||
|
<string name="notes_type_message">Message</string>
|
||||||
|
<string name="notes_details_id">Note ID</string>
|
||||||
|
<string name="notes_details_owner_id">Owner ID</string>
|
||||||
|
<string name="notes_type_announcement">Announcement</string>
|
||||||
|
<string name="styled_text_dialog_title">Edit text</string>
|
||||||
|
<string name="login_qr_decoding_error">The QR code doesn\'t seem correct</string>
|
||||||
|
<string name="notes_no_data_hint">You can add notes and share them with your class using the Add button.</string>
|
||||||
|
<string name="legend_notes_added">{cmd-playlist-edit} notes added</string>
|
||||||
|
<string name="legend_notes_added_replaced">{cmd-playlist-edit} notes added\n{cmd-swap-horizontal} text replaced with a note</string>
|
||||||
|
<string name="notes_no_data">No notes added yet</string>
|
||||||
|
<string name="messages_compose_discard_draft_text">Do you want to discard the saved version of the message?\n\nThis will also cancel your changes and delete your message.</string>
|
||||||
|
<string name="messages_compose_discard_draft">Discard draft</string>
|
||||||
|
<string name="messages_compose_draft_discarded">Draft message deleted</string>
|
||||||
|
<string name="messages_compose_discard_draft_title">Discard draft</string>
|
||||||
|
<string name="notes_details_dialog_title">Note</string>
|
||||||
|
<string name="notes_editor_topic">Note title (optional)</string>
|
||||||
|
<string name="notes_editor_body">Note text</string>
|
||||||
|
<string name="notes_editor_share_hint">The classmates will see your note next to this item.</string>
|
||||||
|
<string name="notes_editor_replace_hint">The content of the note will be visible instead of the original content of the item.</string>
|
||||||
|
<string name="notes_editor_body_error">Enter the note text</string>
|
||||||
|
<string name="color_none">None</string>
|
||||||
|
<string name="notification_type_new_shared_note">Note shared</string>
|
||||||
|
<string name="notes_editor_confirmation_text">Do you want to delete this note?\n\nIt will be deleted on your device and on classmates\' devices.</string>
|
||||||
|
<string name="notes_editor_progress_unsharing">Deleting shared note…</string>
|
||||||
|
<string name="notes_editor_progress_sharing">Sharing the note…</string>
|
||||||
|
<string name="notes_editor_replace_text">Replace original content</string>
|
||||||
|
<string name="card_notes_header_title">Newest notes</string>
|
||||||
|
<string name="messages_compose_save_draft_title">Save changes</string>
|
||||||
|
<string name="messages_compose_save_draft_text">Do you want to save your changes as a draft?\n\nIt will be possible to edit and send the message later.</string>
|
||||||
|
<string name="messages_compose_body_load_failed">The original message could not be loaded.</string>
|
||||||
|
<string name="message_download">Download again</string>
|
||||||
|
<string name="hint_message_star">Mark with a star</string>
|
||||||
|
<string name="dialog_lesson_attendance_details">Details</string>
|
||||||
|
<string name="menu_agenda_config">Agenda settings</string>
|
||||||
|
<string name="registration_config_note_sharing_title">Share notes</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -926,7 +926,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 && Kacper Ziubryniewicz\nwrzesień 2018 - październik 2021</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nwrzesień 2018 - 2022</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>
|
||||||
@ -1547,4 +1547,6 @@
|
|||||||
<string name="color_black">Czarny</string>
|
<string name="color_black">Czarny</string>
|
||||||
<string name="card_type_notes">Notatki</string>
|
<string name="card_type_notes">Notatki</string>
|
||||||
<string name="card_notes_header_title">Najnowsze notatki</string>
|
<string name="card_notes_header_title">Najnowsze notatki</string>
|
||||||
|
<string name="login_summary_account_child">(uczeń)</string>
|
||||||
|
<string name="login_summary_account_parent">(rodzic)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -5,8 +5,8 @@ buildscript {
|
|||||||
kotlin_version = '1.5.30'
|
kotlin_version = '1.5.30'
|
||||||
|
|
||||||
release = [
|
release = [
|
||||||
versionName: "4.11-rc.2",
|
versionName: "4.11.2",
|
||||||
versionCode: 4110020
|
versionCode: 4110299
|
||||||
]
|
]
|
||||||
|
|
||||||
setup = [
|
setup = [
|
||||||
|
Reference in New Issue
Block a user