Merge branch 'develop' into feature/new-login

# Conflicts:
#	app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt
#	app/src/main/res/values/strings.xml
This commit is contained in:
Kuba Szczodrzyński 2020-05-11 19:06:07 +02:00
commit 3ae9ba3d61
236 changed files with 6641 additions and 1845 deletions

View File

@ -24,7 +24,6 @@
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.Dark" android:theme="@style/AppTheme.Dark"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"

View File

@ -1,30 +1,8 @@
<h3>Wersja 4.0, 2020-04-19</h3> <h3>Wersja 4.1, 2020-05-09</h3>
<ul> <ul>
<li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli &#x1F44F;</li> <li>Naprawiona synchronizacja Wiadomości w Librusie.</li>
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkość oraz poprawność pobieranych danych</li> <li>Widok adresu dołączenia do lekcji online w kalendarzu (jeżeli nauczyciel wpisze adres).</li>
<li>Udoskonalony wygląd Szkolnego - sprawi, że korzystanie z aplikacji będzie jeszcze przyjemniejsze</li> <li>Nowy moduł Frekwencji, obsługujący również lekcje zdalne.</li>
<li>Wyszukiwarka wiadomości, pozwalająca na łatwe znalezienie potrzebnej konwersacji.</li>
<li>Możliwość pobierania załączników do zadań domowych oraz wiadomości w każdym dzienniku.</li>
<li>Nowa <b>Strona główna</b> - ładniejszy wygląd oraz możliwość przestawiania kart na każdym profilu</li>
<li>Nowy <b>Plan lekcji</b> - z doskonałą obsługą lekcji przesuniętych oraz dwóch lekcji o tej samej godzinie</li>
<li>Nowe <b>Oceny</b> - z możliwością zmiany wartości plusów oraz minusów oraz wyłączenia niektórych ocen ze średniej</li>
<li>Opcja wyłączenia wybranych powiadomień z aplikacji</li>
<li>Znaczki nieprzeczytanych informacji na obrazkach profili.</li>
<br>
<br>
<li>Udoskonalone tłumaczenie na j.angielski (dzięki @Predator)</li>
<li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li>
<li>Nowe, przyjemniejsze powiadomienia</li>
<li>Dużo poprawek w widoku <b>Wiadomości</b> oraz <b>Ogłoszeń</b></li>
<li>Częściowa <b>Obsługa dziennika EduDziennik</b></li>
<li>Librus: opcja logowania w dziennikach <b>Jednostek Samorządu Terytorialnego</b> oraz <b>Oświata w Radomiu</b></li>
<li>Librus: <b>poprawione obliczanie frekwencji</b></li>
<li>Librus: obsługa Zadań domowych bez posiadania Mobilnych dodatków (przez system Synergia)</li>
<li>Lepsze <b>przekazywanie powiadomień na komputer</b> oraz łatwiejsze parowanie</li>
<li>Łatwiejsze dodawanie własnych wydarzeń</li>
<li>Poprawiliśmy synchronizację w tle na niektórych telefonach</li>
<li>Usunąłem denerwujący brak zaznaczenia w lewym menu</li>
<li>Znaczna ilość błędów z poprzednich wersji już nie występuje</li>
</ul> </ul>
<br> <br>
<br> <br>

View File

@ -9,7 +9,7 @@
/*secret password - removed for source code publication*/ /*secret password - removed for source code publication*/
static toys AES_IV[16] = { static toys AES_IV[16] = {
0x38, 0xd4, 0x73, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 0xec, 0xc0, 0x3e, 0x4e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat); unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);

View File

@ -66,6 +66,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
val timetableManager by lazy { TimetableManager(this) } val timetableManager by lazy { TimetableManager(this) }
val eventManager by lazy { EventManager(this) } val eventManager by lazy { EventManager(this) }
val permissionManager by lazy { PermissionManager(this) } val permissionManager by lazy { PermissionManager(this) }
val attendanceManager by lazy { AttendanceManager(this) }
val db val db
get() = App.db get() = App.db
@ -100,9 +101,9 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
.followSslRedirects(true) .followSslRedirects(true)
.retryOnConnectionFailure(true) .retryOnConnectionFailure(true)
.cookieJar(cookieJar) .cookieJar(cookieJar)
.connectTimeout(20, TimeUnit.SECONDS) .connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
builder.installHttpsSupport(this) builder.installHttpsSupport(this)
if (debugMode || BuildConfig.DEBUG) { if (debugMode || BuildConfig.DEBUG) {

View File

@ -18,6 +18,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import com.danimahardhika.cafebar.CafeBar import com.danimahardhika.cafebar.CafeBar
@ -294,6 +295,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
mainSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar) mainSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar)
errorSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar) errorSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar)
if (BuildConfig.VERSION_NAME.contains("nightly")) {
b.nightlyText.isVisible = true
b.nightlyText.text = "Nightly\n"+BuildConfig.VERSION_NAME.substringAfterLast(".")
}
else
b.nightlyText.isVisible = false
navLoading = true navLoading = true
b.navView.apply { b.navView.apply {

View File

@ -30,6 +30,7 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
val grades by lazy { ProfileConfigGrades(this) } val grades by lazy { ProfileConfigGrades(this) }
val ui by lazy { ProfileConfigUI(this) } val ui by lazy { ProfileConfigUI(this) }
val sync by lazy { ProfileConfigSync(this) } val sync by lazy { ProfileConfigSync(this) }
val attendance by lazy { ProfileConfigAttendance(this) }
/* /*
val timetable by lazy { ConfigTimetable(this) } val timetable by lazy { ConfigTimetable(this) }
val grades by lazy { ConfigGrades(this) }*/ val grades by lazy { ConfigGrades(this) }*/

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-29.
*/
package pl.szczodrzynski.edziennik.config
import pl.szczodrzynski.edziennik.config.utils.get
import pl.szczodrzynski.edziennik.config.utils.set
class ProfileConfigAttendance(private val config: ProfileConfig) {
private var mAttendancePageSelection: Int? = null
var attendancePageSelection: Int
get() { mAttendancePageSelection = mAttendancePageSelection ?: config.values.get("attendancePageSelection", 1); return mAttendancePageSelection ?: 1 }
set(value) { config.set("attendancePageSelection", value); mAttendancePageSelection = value }
private var mUseSymbols: Boolean? = null
var useSymbols: Boolean
get() { mUseSymbols = mUseSymbols ?: config.values.get("useSymbols", false); return mUseSymbols ?: false }
set(value) { config.set("useSymbols", value); mUseSymbols = value }
private var mGroupConsecutiveDays: Boolean? = null
var groupConsecutiveDays: Boolean
get() { mGroupConsecutiveDays = mGroupConsecutiveDays ?: config.values.get("groupConsecutiveDays", true); return mGroupConsecutiveDays ?: true }
set(value) { config.set("groupConsecutiveDays", value); mGroupConsecutiveDays = value }
private var mShowPresenceInMonth: Boolean? = null
var showPresenceInMonth: Boolean
get() { mShowPresenceInMonth = mShowPresenceInMonth ?: config.values.get("showPresenceInMonth", false); return mShowPresenceInMonth ?: false }
set(value) { config.set("showPresenceInMonth", value); mShowPresenceInMonth = value }
}

View File

@ -57,6 +57,7 @@ const val LIBRUS_MESSAGES_URL = "https://wiadomosci.librus.pl/module"
const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action=" const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action="
const val LIBRUS_SYNERGIA_HOMEWORK_ATTACHMENT_URL = "https://synergia.librus.pl/homework/downloadFile" const val LIBRUS_SYNERGIA_HOMEWORK_ATTACHMENT_URL = "https://synergia.librus.pl/homework/downloadFile"
const val LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL = "https://synergia.librus.pl/wiadomosci/pobierz_zalacznik"
const val IDZIENNIK_USER_AGENT = SYNERGIA_USER_AGENT const val IDZIENNIK_USER_AGENT = SYNERGIA_USER_AGENT
const val IDZIENNIK_WEB_URL = "https://iuczniowie.progman.pl/idziennik" const val IDZIENNIK_WEB_URL = "https://iuczniowie.progman.pl/idziennik"

View File

@ -127,6 +127,7 @@ const val ERROR_LIBRUS_API_DEVICE_REGISTERED = 185
const val ERROR_LIBRUS_MESSAGES_NOT_FOUND = 186 const val ERROR_LIBRUS_MESSAGES_NOT_FOUND = 186
const val ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST = 187 const val ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST = 187
const val ERROR_LIBRUS_MESSAGES_ATTACHMENT_NOT_FOUND = 188 const val ERROR_LIBRUS_MESSAGES_ATTACHMENT_NOT_FOUND = 188
const val ERROR_LOGIN_LIBRUS_MESSAGES_TIMEOUT = 189
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201 const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202 const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202

View File

@ -68,6 +68,9 @@ object Regexes {
} }
val MOBIDZIENNIK_ATTENDANCE_TYPES by lazy {
"""Legenda:.+?normal;">(.+?)</span>""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_ATTENDANCE_TABLE by lazy { val MOBIDZIENNIK_ATTENDANCE_TABLE by lazy {
"""<table .+?id="obecnosci_tabela">(.+?)</table>""".toRegex(DOT_MATCHES_ALL) """<table .+?id="obecnosci_tabela">(.+?)</table>""".toRegex(DOT_MATCHES_ALL)
} }
@ -81,7 +84,7 @@ object Regexes {
"""<span>([0-9:]+) - .+? (.+?)</span></a>""".toRegex(DOT_MATCHES_ALL) """<span>([0-9:]+) - .+? (.+?)</span></a>""".toRegex(DOT_MATCHES_ALL)
} }
val MOBIDZIENNIK_ATTENDANCE_LESSON by lazy { val MOBIDZIENNIK_ATTENDANCE_LESSON by lazy {
"""<strong>(.+?) - (.*?)</strong>.+?<small>.+?\((.+?), .+?(.+?)\)""".toRegex(DOT_MATCHES_ALL) """<strong>(.+?)</strong>\s*<small>\s*\((.+?),\s*(.+?)\)""".toRegex(DOT_MATCHES_ALL)
} }
val MOBIDZIENNIK_HOMEWORK_ROW by lazy { val MOBIDZIENNIK_HOMEWORK_ROW by lazy {
@ -151,6 +154,9 @@ object Regexes {
val LIBRUS_ATTACHMENT_KEY by lazy { val LIBRUS_ATTACHMENT_KEY by lazy {
"""singleUseKey=([0-9A-z_]+)""".toRegex() """singleUseKey=([0-9A-z_]+)""".toRegex()
} }
val LIBRUS_MESSAGE_ID by lazy {
"""/wiadomosci/[0-9]+/[0-9]+/([0-9]+?)/""".toRegex()
}

View File

@ -45,24 +45,25 @@ class EdudziennikWebAnnouncements(override val data: DataEdudziennik,
val addedDate = Date.fromIsoHm(dateString) val addedDate = Date.fromIsoHm(dateString)
val announcementObject = Announcement( val announcementObject = Announcement(
profileId, profileId = profileId,
id, id = id,
subject, subject = subject,
null, text = null,
startDate, startDate = startDate,
null, endDate = null,
teacher.id, teacherId = teacher.id,
longId addedDate = addedDate
) ).also {
it.idString = longId
}
data.announcementIgnoreList.add(announcementObject) data.announcementList.add(announcementObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ANNOUNCEMENT, Metadata.TYPE_ANNOUNCEMENT,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }
} }

View File

@ -39,12 +39,12 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map { val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim()) val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
val symbol = type?.get(1)?.trim() val symbol = type?.get(1)?.trim() ?: "?"
val name = type?.get(2)?.trim() val name = type?.get(2)?.trim() ?: "nieznany rodzaj"
return@map Triple( return@map Triple(
symbol, symbol,
name, name,
when (name?.toLowerCase(Locale.ROOT)) { when (name.toLowerCase(Locale.ROOT)) {
"obecność" -> Attendance.TYPE_PRESENT "obecność" -> Attendance.TYPE_PRESENT
"nieobecność" -> Attendance.TYPE_ABSENT "nieobecność" -> Attendance.TYPE_ABSENT
"spóźnienie" -> Attendance.TYPE_BELATED "spóźnienie" -> Attendance.TYPE_BELATED
@ -52,7 +52,7 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
"dzień wolny" -> Attendance.TYPE_DAY_FREE "dzień wolny" -> Attendance.TYPE_DAY_FREE
"brak zajęć" -> Attendance.TYPE_DAY_FREE "brak zajęć" -> Attendance.TYPE_DAY_FREE
"oddelegowany" -> Attendance.TYPE_RELEASED "oddelegowany" -> Attendance.TYPE_RELEASED
else -> Attendance.TYPE_CUSTOM else -> Attendance.TYPE_UNKNOWN
} }
) )
} ?: emptyList() } ?: emptyList()
@ -62,38 +62,42 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
val lessonNumber = attendanceElement[2].toInt() val lessonNumber = attendanceElement[2].toInt()
val attendanceSymbol = attendanceElement[3] val attendanceSymbol = attendanceElement[3]
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date) val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
val lesson = lessons.firstOrNull { it.lessonNumber == lessonNumber } val lesson = lessons.firstOrNull { it.lessonNumber == lessonNumber }
val id = "${date.stringY_m_d}:$lessonNumber:$attendanceSymbol".crc32() val id = "${date.stringY_m_d}:$lessonNumber:$attendanceSymbol".crc32()
val (_, name, type) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol } val (typeSymbol, typeName, baseType) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol }
?: return@forEach ?: return@forEach
val startTime = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }?.startTime val startTime = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }?.startTime
?: return@forEach ?: return@forEach
val attendanceObject = Attendance( val attendanceObject = Attendance(
profileId, profileId = profileId,
id, id = id,
lesson?.displayTeacherId ?: -1, baseType = baseType,
lesson?.displaySubjectId ?: -1, typeName = typeName,
profile.currentSemester, typeShort = data.app.attendanceManager.getTypeShort(baseType),
name, typeSymbol = typeSymbol,
date, typeColor = null,
lesson?.displayStartTime ?: startTime, date = date,
type startTime = lesson?.displayStartTime ?: startTime,
) semester = profile.currentSemester,
teacherId = lesson?.displayTeacherId ?: -1,
subjectId = lesson?.displaySubjectId ?: -1
).also {
it.lessonNumber = lessonNumber
}
data.attendanceList.add(attendanceObject) data.attendanceList.add(attendanceObject)
if(type != Attendance.TYPE_PRESENT) { if (baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ATTENDANCE, Metadata.TYPE_ATTENDANCE,
id, id,
profile.empty, profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
profile.empty, profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -57,8 +57,7 @@ class EdudziennikWebEvents(override val data: DataEdudziennik,
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }

View File

@ -46,7 +46,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
if (dateString.isBlank()) return@forEach if (dateString.isBlank()) return@forEach
val date = Date.fromY_m_d(dateString) val date = Date.fromY_m_d(dateString)
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date) val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
val startTime = lessons.firstOrNull { it.displaySubjectId == subject.id }?.displayStartTime val startTime = lessons.firstOrNull { it.displaySubjectId == subject.id }?.displayStartTime
val eventTypeElement = examElement.child(3).child(0) val eventTypeElement = examElement.child(3).child(0)
@ -74,8 +74,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }

View File

@ -126,7 +126,8 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
comment = null, comment = null,
semester = semester, semester = semester,
teacherId = teacher.id, teacherId = teacher.id,
subjectId = subject.id subjectId = subject.id,
addedDate = addedDate
) )
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
@ -135,8 +136,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }
@ -168,8 +168,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
proposedGradeObject.id, proposedGradeObject.id,
profile.empty, profile.empty,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }
@ -201,8 +200,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
finalGradeObject.id, finalGradeObject.id,
profile.empty, profile.empty,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -43,7 +43,7 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
val subjectName = subjectElement.text() val subjectName = subjectElement.text()
val subject = data.getSubject(subjectId, subjectName) val subject = data.getSubject(subjectId, subjectName)
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date) val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
val startTime = lessons.firstOrNull { it.subjectId == subject.id }?.displayStartTime val startTime = lessons.firstOrNull { it.subjectId == subject.id }?.displayStartTime
val teacherName = homeworkElement.child(2).text() val teacherName = homeworkElement.child(2).text()
@ -72,8 +72,7 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
Metadata.TYPE_HOMEWORK, Metadata.TYPE_HOMEWORK,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -24,9 +24,9 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
webGet(TAG, data.schoolEndpoint + "Lucky", xhr = true) { text -> webGet(TAG, data.schoolEndpoint + "Lucky", xhr = true) { text ->
text.toIntOrNull()?.also { luckyNumber -> text.toIntOrNull()?.also { luckyNumber ->
val luckyNumberObject = LuckyNumber( val luckyNumberObject = LuckyNumber(
profileId, profileId = profileId,
Date.getToday(), date = Date.getToday(),
luckyNumber number = luckyNumber
) )
data.luckyNumberList.add(luckyNumberObject) data.luckyNumberList.add(luckyNumberObject)
@ -35,8 +35,7 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
Metadata.TYPE_LUCKY_NUMBER, Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }

View File

@ -41,12 +41,15 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
val description = noteElement.child(3).text() val description = noteElement.child(3).text()
val noticeObject = Notice( val noticeObject = Notice(
profileId, profileId = profileId,
id, id = id,
description, type = Notice.TYPE_NEUTRAL,
profile.currentSemester, semester = profile.currentSemester,
Notice.TYPE_NEUTRAL, text = description,
teacher.id category = null,
points = null,
teacherId = teacher.id,
addedDate = addedDate
) )
data.noticeList.add(noticeObject) data.noticeList.add(noticeObject)
@ -55,8 +58,7 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
Metadata.TYPE_NOTICE, Metadata.TYPE_NOTICE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }

View File

@ -124,8 +124,7 @@ class EdudziennikWebTimetable(override val data: DataEdudziennik,
Metadata.TYPE_LESSON_CHANGE, Metadata.TYPE_LESSON_CHANGE,
lessonObject.id, lessonObject.id,
seen, seen,
seen, seen
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -68,9 +68,9 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
val luckyNumberObject = LuckyNumber( val luckyNumberObject = LuckyNumber(
data.profileId, profileId = data.profileId,
luckyNumberDate, date = luckyNumberDate,
luckyNumber number = luckyNumber
) )
data.luckyNumberList.add(luckyNumberObject) data.luckyNumberList.add(luckyNumberObject)
@ -80,8 +80,7 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
Metadata.TYPE_LUCKY_NUMBER, Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
data.profile?.empty ?: false, data.profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }

View File

@ -69,7 +69,8 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED, type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
subject = subject, subject = subject,
body = body, body = body,
senderId = rTeacher.id senderId = rTeacher.id,
addedDate = sentDate
) )
val messageRecipient = MessageRecipient( val messageRecipient = MessageRecipient(
@ -87,8 +88,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
message.id, message.id,
readDate > 0, readDate > 0,
readDate > 0 || profile?.empty ?: false, readDate > 0 || profile?.empty ?: false
sentDate
)) ))
} }

View File

@ -51,7 +51,8 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
type = TYPE_SENT, type = TYPE_SENT,
subject = subject, subject = subject,
body = body, body = body,
senderId = null senderId = null,
addedDate = sentDate
) )
for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) { for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) {
@ -76,7 +77,7 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
} }
data.messageList.add(message) data.messageList.add(message)
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate)) data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true))
} }
data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES) data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)

View File

@ -52,14 +52,14 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
val startDate = jAnnouncement.getString("DataWydarzenia")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull()?.let { Date.fromMillis(it) } val startDate = jAnnouncement.getString("DataWydarzenia")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull()?.let { Date.fromMillis(it) }
val announcementObject = Announcement( val announcementObject = Announcement(
profileId, profileId = profileId,
announcementId, id = announcementId,
jAnnouncement.get("Temat").asString, subject = jAnnouncement.get("Temat").asString,
jAnnouncement.get("Tresc").asString, text = jAnnouncement.get("Tresc").asString,
startDate, startDate = startDate,
null, endDate = null,
rTeacher.id, teacherId = rTeacher.id,
null addedDate = addedDate
) )
data.announcementList.add(announcementObject) data.announcementList.add(announcementObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
@ -67,8 +67,7 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
Metadata.TYPE_ANNOUNCEMENT, Metadata.TYPE_ANNOUNCEMENT,
announcementObject.id, announcementObject.id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
addedDate
)) ))
} }

View File

@ -12,10 +12,18 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNI
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.* import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_BELATED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT_CUSTOM
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getInt
import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString
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
@ -51,71 +59,97 @@ class IdziennikWebAttendance(override val data: DataIdziennik,
for (jAttendanceEl in json.getAsJsonArray("Obecnosci")) { for (jAttendanceEl in json.getAsJsonArray("Obecnosci")) {
val jAttendance = jAttendanceEl.asJsonObject val jAttendance = jAttendanceEl.asJsonObject
// jAttendance // jAttendance
val attendanceTypeIdziennik = jAttendance.get("TypObecnosci").asInt val type = jAttendance.get("TypObecnosci").asInt
if (attendanceTypeIdziennik == 5 || attendanceTypeIdziennik == 7)
continue // skip "zajęcia nie odbyły się" and "Ferie"
val attendanceDate = Date.fromY_m_d(jAttendance.get("Data").asString) if (type == 5 || type == 7)
val attendanceTime = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
if (attendanceDate.combineWith(attendanceTime) > System.currentTimeMillis())
continue continue
val attendanceId = jAttendance.get("IdLesson").asString.crc16().toLong() val date = Date.fromY_m_d(jAttendance.get("Data").asString)
val time = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
if (date.combineWith(time) > System.currentTimeMillis())
continue
val id = jAttendance.get("IdLesson").asString.crc16().toLong()
val rSubject = data.getSubject(jAttendance.get("Przedmiot").asString, jAttendance.get("IdPrzedmiot").asLong, "") val rSubject = data.getSubject(jAttendance.get("Przedmiot").asString, jAttendance.get("IdPrzedmiot").asLong, "")
val rTeacher = data.getTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").asString) val rTeacher = data.getTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").asString)
var attendanceName = "obecność" var baseType = TYPE_UNKNOWN
var attendanceType = Attendance.TYPE_CUSTOM var typeName = "nieznany rodzaj"
var typeSymbol: String? = null
var typeColor: Long? = null
when (attendanceTypeIdziennik) { /* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosciUcznia_lmt637231494660000000.js */
1 /* nieobecność usprawiedliwiona */ -> { /* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosci_lmt637231494660000000.css */
attendanceName = "nieobecność usprawiedliwiona" when (type) {
attendanceType = TYPE_ABSENT_EXCUSED 1 -> {
baseType = TYPE_ABSENT_EXCUSED
typeName = "nieobecność usprawiedliwiona"
typeColor = 0xffffe099
} }
2 /* spóźnienie */ -> { 2 -> {
attendanceName = "spóźnienie" baseType = TYPE_BELATED
attendanceType = TYPE_BELATED typeName = "spóźnienie"
typeColor = 0xffffffaa
} }
3 /* nieobecność nieusprawiedliwiona */ -> { 3 -> {
attendanceName = "nieobecność nieusprawiedliwiona" baseType = TYPE_ABSENT
attendanceType = TYPE_ABSENT typeName = "nieobecność nieusprawiedliwiona"
typeColor = 0xffffad99
} }
4 /* zwolnienie */, 9 /* zwolniony / obecny */ -> { 4, 9 -> {
attendanceType = TYPE_RELEASED baseType = TYPE_RELEASED
if (attendanceTypeIdziennik == 4) if (type == 4) {
attendanceName = "zwolnienie" typeName = "zwolnienie"
if (attendanceTypeIdziennik == 9) typeColor = 0xffa8beff
attendanceName = "zwolnienie / obecność" }
if (type == 9) {
typeName = "zwolniony / obecny"
typeSymbol = "zb"
typeColor = 0xffff69b4
}
} }
0 /* obecny */, 8 /* Wycieczka */ -> { 8 -> {
attendanceType = TYPE_PRESENT baseType = TYPE_PRESENT_CUSTOM
if (attendanceTypeIdziennik == 8) typeName = "wycieczka"
attendanceName = "wycieczka" typeSymbol = "w"
typeColor = null
}
0 -> {
baseType = TYPE_PRESENT
typeName = "obecny"
typeColor = 0xffccffcc
} }
} }
val semester = profile?.dateToSemester(attendanceDate) ?: 1 val semester = profile?.dateToSemester(date) ?: 1
val attendanceObject = Attendance( val attendanceObject = Attendance(
profileId, profileId = profileId,
attendanceId, id = id,
rTeacher.id, baseType = baseType,
rSubject.id, typeName = typeName,
semester, typeShort = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType),
attendanceName, typeSymbol = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType),
attendanceDate, typeColor = typeColor?.toInt(),
attendanceTime, date = date,
attendanceType startTime = time,
) semester = semester,
teacherId = rTeacher.id,
subjectId = rSubject.id
).also {
it.lessonTopic = jAttendance.getString("PrzedmiotTemat")
it.lessonNumber = jAttendance.getInt("Godzina")
}
data.attendanceList.add(attendanceObject) data.attendanceList.add(attendanceObject)
if (attendanceObject.type != TYPE_PRESENT) { if (attendanceObject.baseType != TYPE_PRESENT) {
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ATTENDANCE, Metadata.TYPE_ATTENDANCE,
attendanceObject.id, attendanceObject.id,
profile?.empty ?: false, profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
profile?.empty ?: false, profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -68,7 +68,7 @@ class IdziennikWebExams(override val data: DataIdziennik,
val teacherId = data.getTeacherByLastFirst(teacherName).id val teacherId = data.getTeacherByLastFirst(teacherName).id
val topic = exam.getString("zakres")?.trim() ?: "" val topic = exam.getString("zakres")?.trim() ?: ""
val lessonList = data.db.timetableDao().getForDateNow(profileId, examDate) val lessonList = data.db.timetableDao().getAllForDateNow(profileId, examDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
val eventType = when (exam.getString("rodzaj")?.toLowerCase(Locale.getDefault())) { val eventType = when (exam.getString("rodzaj")?.toLowerCase(Locale.getDefault())) {
@ -98,8 +98,7 @@ class IdziennikWebExams(override val data: DataIdziennik,
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
eventObject.id, eventObject.id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }

View File

@ -94,8 +94,7 @@ class IdziennikWebGetMessage(override val data: DataIdziennik,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
message.id, message.id,
message.seen, message.seen,
message.notified, message.notified
message.addedDate
)) ))
} }

View File

@ -63,6 +63,8 @@ class IdziennikWebGrades(override val data: DataIdziennik,
colorInt = Color.parseColor("#$gradeColor") colorInt = Color.parseColor("#$gradeColor")
} }
val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
val gradeObject = Grade( val gradeObject = Grade(
profileId = profileId, profileId = profileId,
id = id, id = id,
@ -76,7 +78,9 @@ class IdziennikWebGrades(override val data: DataIdziennik,
comment = null, comment = null,
semester = semester, semester = semester,
teacherId = teacher.id, teacherId = teacher.id,
subjectId = subject.id) subjectId = subject.id,
addedDate = addedDate
)
when (grade.getInt("Typ")) { when (grade.getInt("Typ")) {
0 -> { 0 -> {
@ -100,6 +104,8 @@ class IdziennikWebGrades(override val data: DataIdziennik,
colorInt = Color.parseColor("#$historyColor") colorInt = Color.parseColor("#$historyColor")
} }
val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
val historyObject = Grade( val historyObject = Grade(
profileId = profileId, profileId = profileId,
id = gradeObject.id * -1, id = gradeObject.id * -1,
@ -113,19 +119,18 @@ class IdziennikWebGrades(override val data: DataIdziennik,
comment = null, comment = null,
semester = historyItem.getInt("Semestr") ?: 1, semester = historyItem.getInt("Semestr") ?: 1,
teacherId = teacher.id, teacherId = teacher.id,
subjectId = subject.id) subjectId = subject.id,
addedDate = addedDate
)
historyObject.parentId = gradeObject.id historyObject.parentId = gradeObject.id
val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
data.gradeList.add(historyObject) data.gradeList.add(historyObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
historyObject.id, historyObject.id,
true, true,
true, true
addedDate
)) ))
} }
// update the current grade's value with an average of all historical grades and itself // update the current grade's value with an average of all historical grades and itself
@ -147,8 +152,6 @@ class IdziennikWebGrades(override val data: DataIdziennik,
} }
} }
val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
@ -156,8 +159,7 @@ class IdziennikWebGrades(override val data: DataIdziennik,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
data.profile.empty, data.profile.empty,
data.profile.empty, data.profile.empty
addedDate
)) ))
} }
} }

View File

@ -57,7 +57,7 @@ class IdziennikWebHomework(override val data: DataIdziennik,
val subjectId = data.getSubject(subjectName, null, subjectName).id val subjectId = data.getSubject(subjectName, null, subjectName).id
val teacherName = homework.getString("usr") ?: return@forEach val teacherName = homework.getString("usr") ?: return@forEach
val teacherId = data.getTeacherByLastFirst(teacherName).id val teacherId = data.getTeacherByLastFirst(teacherName).id
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate) val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime
val topic = homework.getString("tytul")?.trim() ?: "" val topic = homework.getString("tytul")?.trim() ?: ""
@ -77,7 +77,8 @@ class IdziennikWebHomework(override val data: DataIdziennik,
type = Event.TYPE_HOMEWORK, type = Event.TYPE_HOMEWORK,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId, subjectId = subjectId,
teamId = data.teamClass?.id ?: -1 teamId = data.teamClass?.id ?: -1,
addedDate = addedDate.inMillis
) )
data.eventList.add(eventObject) data.eventList.add(eventObject)
@ -86,8 +87,7 @@ class IdziennikWebHomework(override val data: DataIdziennik,
Metadata.TYPE_HOMEWORK, Metadata.TYPE_HOMEWORK,
eventObject.id, eventObject.id,
seen, seen,
seen, seen
addedDate.inMillis
)) ))
} }

View File

@ -13,9 +13,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.data.db.entity.Notice.* import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEGATIVE
import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEUTRAL
import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_POSITIVE
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
class IdziennikWebNotices(override val data: DataIdziennik, class IdziennikWebNotices(override val data: DataIdziennik,
@ -53,20 +56,24 @@ class IdziennikWebNotices(override val data: DataIdziennik,
} }
val noticeObject = Notice( val noticeObject = Notice(
profileId, profileId = profileId,
noticeId, id = noticeId,
jNotice.get("Tresc").asString, type = nType,
jNotice.get("Semestr").asInt, semester = jNotice.get("Semestr").asInt,
nType, text = jNotice.getString("Tresc") ?: "",
rTeacher.id) category = null,
points = null,
teacherId = rTeacher.id,
addedDate = addedDate.inMillis
)
data.noticeList.add(noticeObject) data.noticeList.add(noticeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_NOTICE, Metadata.TYPE_NOTICE,
noticeObject.id, noticeObject.id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
addedDate.inMillis
)) ))
} }

View File

@ -76,6 +76,11 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
else -1 else -1
if (semester1Proposed != "") { if (semester1Proposed != "") {
val addedDate = if (data.profile.empty)
data.profile.dateSemester1Start.inMillis
else
System.currentTimeMillis()
val gradeObject = Grade( val gradeObject = Grade(
profileId = profileId, profileId = profileId,
id = semester1Id, id = semester1Id,
@ -89,26 +94,26 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
comment = null, comment = null,
semester = 1, semester = 1,
teacherId = -1, teacherId = -1,
subjectId = subjectObject.id subjectId = subjectObject.id,
addedDate = addedDate
) )
val addedDate = if (data.profile.empty)
data.profile.dateSemester1Start.inMillis
else
System.currentTimeMillis()
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
gradeObject.id, gradeObject.id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }
if (semester2Proposed != "") { if (semester2Proposed != "") {
val addedDate = if (data.profile.empty)
data.profile.dateSemester2Start.inMillis
else
System.currentTimeMillis()
val gradeObject = Grade( val gradeObject = Grade(
profileId = profileId, profileId = profileId,
id = semester2Id, id = semester2Id,
@ -122,22 +127,17 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
comment = null, comment = null,
semester = 2, semester = 2,
teacherId = -1, teacherId = -1,
subjectId = subjectObject.id subjectId = subjectObject.id,
addedDate = addedDate
) )
val addedDate = if (data.profile.empty)
data.profile.dateSemester2Start.inMillis
else
System.currentTimeMillis()
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
gradeObject.id, gradeObject.id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }
} }

View File

@ -59,7 +59,7 @@ class IdziennikWebSendMessage(override val data: DataIdziennik,
IdziennikApiMessagesSent(data, null) { IdziennikApiMessagesSent(data, null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event) EventBus.getDefault().postSticky(event)
onSuccess() onSuccess()

View File

@ -165,8 +165,7 @@ class IdziennikWebTimetable(override val data: DataIdziennik,
Metadata.TYPE_LESSON_CHANGE, Metadata.TYPE_LESSON_CHANGE,
lessonObject.id, lessonObject.id,
seen, seen,
seen, seen
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -74,9 +74,9 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
Regexes.IDZIENNIK_WEB_LUCKY_NUMBER.find(text)?.also { Regexes.IDZIENNIK_WEB_LUCKY_NUMBER.find(text)?.also {
val number = it[1].toIntOrNull() ?: return@also val number = it[1].toIntOrNull() ?: return@also
val luckyNumberObject = LuckyNumber( val luckyNumberObject = LuckyNumber(
data.profileId, profileId = data.profileId,
Date.getToday(), date = Date.getToday(),
number number = number
) )
data.luckyNumberList.add(luckyNumberObject) data.luckyNumberList.add(luckyNumberObject)
@ -86,8 +86,7 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
Metadata.TYPE_LUCKY_NUMBER, Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -275,4 +275,10 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
var timetableNotPublic: Boolean var timetableNotPublic: Boolean
get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false } get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false }
set(value) { profile?.putStudentData("timetableNotPublic", value) ?: return; mTimetableNotPublic = value } set(value) { profile?.putStudentData("timetableNotPublic", value) ?: return; mTimetableNotPublic = value }
/**
* Set to false when Recaptcha helper doesn't provide a working token.
* When it's set to false uses Synergia for messages.
*/
var messagesLoginSuccessful: Boolean = true
} }

View File

@ -13,9 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.Librus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetMessage import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetMessage
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetRecipientList import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetRecipientList
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesSendMessage import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesSendMessage
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaGetHomework import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaHomeworkGetAttachment
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaMarkAllAnnouncementsAsRead
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
@ -91,9 +89,8 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun getMessage(message: MessageFull) { override fun getMessage(message: MessageFull) {
login(LOGIN_METHOD_LIBRUS_MESSAGES) { login(LOGIN_METHOD_LIBRUS_MESSAGES) {
LibrusMessagesGetMessage(data, message) { if (data.messagesLoginSuccessful) LibrusMessagesGetMessage(data, message) { completed() }
completed() else LibrusSynergiaGetMessage(data, message) { completed() }
}
} }
} }
@ -124,10 +121,9 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) { override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
when (owner) { when (owner) {
is Message -> { is Message -> {
login(LOGIN_METHOD_LIBRUS_MESSAGES) { login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) { if (data.messagesLoginSuccessful) LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) { completed() }
completed() LibrusSynergiaGetAttachment(data, owner, attachmentId, attachmentName) { completed() }
}
} }
} }
is EventFull -> { is EventFull -> {

View File

@ -50,6 +50,8 @@ const val ENDPOINT_LIBRUS_API_CLASS_FREE_DAYS = 1130
const val ENDPOINT_LIBRUS_SYNERGIA_INFO = 2010 const val ENDPOINT_LIBRUS_SYNERGIA_INFO = 2010
const val ENDPOINT_LIBRUS_SYNERGIA_GRADES = 2020 const val ENDPOINT_LIBRUS_SYNERGIA_GRADES = 2020
const val ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK = 2030 const val ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK = 2030
const val ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_RECEIVED = 2040
const val ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_SENT = 2050
const val ENDPOINT_LIBRUS_MESSAGES_RECEIVED = 3010 const val ENDPOINT_LIBRUS_MESSAGES_RECEIVED = 3010
const val ENDPOINT_LIBRUS_MESSAGES_SENT = 3020 const val ENDPOINT_LIBRUS_MESSAGES_SENT = 3020
const val ENDPOINT_LIBRUS_MESSAGES_TRASH = 3030 const val ENDPOINT_LIBRUS_MESSAGES_TRASH = 3030

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-5-8.
*/
package pl.szczodrzynski.edziennik.data.api.edziennik.librus
import android.content.Context
import android.webkit.WebView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.startCoroutineTimer
import kotlin.coroutines.CoroutineContext
class LibrusRecaptchaHelper(
val context: Context,
url: String,
html: String,
val onSuccess: (url: String) -> Unit,
val onTimeout: () -> Unit
) : CoroutineScope {
companion object {
private const val TAG = "LibrusRecaptchaHelper"
}
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
private val webView by lazy {
WebView(context).also {
it.settings.javaScriptEnabled = true
it.webViewClient = WebViewClient()
}
}
private var timeout: Job? = null
inner class WebViewClient : android.webkit.WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
timeout?.cancel()
onSuccess(url)
return true
}
}
init {
launch(Dispatchers.Main) {
webView.loadDataWithBaseURL(url, html, "text/html", "UTF-8", null)
}
timeout = startCoroutineTimer(delayMillis = 10000L) {
onTimeout()
}
}
}

View File

@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.* import pl.szczodrzynski.edziennik.data.api.edziennik.librus.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetList import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetList
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaGetMessages
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaHomework import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaHomework
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaInfo import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaInfo
import pl.szczodrzynski.edziennik.data.db.entity.Message import pl.szczodrzynski.edziennik.data.db.entity.Message
@ -201,17 +202,27 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
data.startProgress(R.string.edziennik_progress_endpoint_student_info) data.startProgress(R.string.edziennik_progress_endpoint_student_info)
LibrusSynergiaInfo(data, lastSync, onSuccess) LibrusSynergiaInfo(data, lastSync, onSuccess)
} }
ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_RECEIVED -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
LibrusSynergiaGetMessages(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
}
ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_SENT -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
LibrusSynergiaGetMessages(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
}
/** /**
* MESSAGES * MESSAGES
*/ */
ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> { ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox) data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess) if (data.messagesLoginSuccessful) LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
else LibrusSynergiaGetMessages(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
} }
ENDPOINT_LIBRUS_MESSAGES_SENT -> { ENDPOINT_LIBRUS_MESSAGES_SENT -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox) data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess) if (data.messagesLoginSuccessful) LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
else LibrusSynergiaGetMessages(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
} }
else -> onSuccess(endpointId) else -> onSuccess(endpointId)

View File

@ -91,6 +91,8 @@ open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
} }
fun redirectUrlGet(tag: String, url: String, onSuccess: (url: String) -> Unit) { fun redirectUrlGet(tag: String, url: String, onSuccess: (url: String) -> Unit) {
d(tag, "Request: Librus/Synergia - $url")
val callback = object : TextCallbackHandler() { val callback = object : TextCallbackHandler() {
override fun onSuccess(text: String?, response: Response) { override fun onSuccess(text: String?, response: Response) {
val redirectUrl = response.headers().get("Location") val redirectUrl = response.headers().get("Location")

View File

@ -37,8 +37,7 @@ class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
Metadata.TYPE_ANNOUNCEMENT, Metadata.TYPE_ANNOUNCEMENT,
announcement.id, announcement.id,
announcement.seen, announcement.seen,
announcement.notified, announcement.notified
announcement.addedDate
)) ))
onSuccess() onSuccess()
} }

View File

@ -38,15 +38,17 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
val read = announcement.getBoolean("WasRead") ?: false val read = announcement.getBoolean("WasRead") ?: false
val announcementObject = Announcement( val announcementObject = Announcement(
profileId, profileId = profileId,
id, id = id,
subject, subject = subject,
text, text = text,
startDate, startDate = startDate,
endDate, endDate = endDate,
teacherId, teacherId = teacherId,
longId addedDate = addedDate
) ).also {
it.idString = longId
}
data.announcementList.add(announcementObject) data.announcementList.add(announcementObject)
data.setSeenMetadataList.add(Metadata( data.setSeenMetadataList.add(Metadata(
@ -54,8 +56,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
Metadata.TYPE_ANNOUNCEMENT, Metadata.TYPE_ANNOUNCEMENT,
id, id,
read, read,
profile.empty || read, profile.empty || read
addedDate
)) ))
} }

View File

@ -26,25 +26,39 @@ class LibrusApiAttendanceTypes(override val data: DataLibrus,
attendanceTypes?.forEach { attendanceType -> attendanceTypes?.forEach { attendanceType ->
val id = attendanceType.getLong("Id") ?: return@forEach val id = attendanceType.getLong("Id") ?: return@forEach
val name = attendanceType.getString("Name") ?: ""
val color = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") } ?: -1
val standardId = when (attendanceType.getBoolean("Standard") ?: false) { val typeName = attendanceType.getString("Name") ?: ""
true -> id val typeSymbol = attendanceType.getString("Short") ?: ""
false -> attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id val typeColor = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") }
}
val type = when (standardId) { val isStandard = attendanceType.getBoolean("Standard") ?: false
val baseType = when (attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id) {
1L -> Attendance.TYPE_ABSENT 1L -> Attendance.TYPE_ABSENT
2L -> Attendance.TYPE_BELATED 2L -> Attendance.TYPE_BELATED
3L -> Attendance.TYPE_ABSENT_EXCUSED 3L -> Attendance.TYPE_ABSENT_EXCUSED
4L -> Attendance.TYPE_RELEASED 4L -> Attendance.TYPE_RELEASED
/*100*/else -> Attendance.TYPE_PRESENT /*100*/else -> when (isStandard) {
true -> Attendance.TYPE_PRESENT
false -> Attendance.TYPE_PRESENT_CUSTOM
}
}
val typeShort = when (isStandard) {
true -> data.app.attendanceManager.getTypeShort(baseType)
false -> typeSymbol
} }
data.attendanceTypes.put(id, AttendanceType(profileId, id, name, type, color)) data.attendanceTypes.put(id, AttendanceType(
profileId,
id,
baseType,
typeName,
typeShort,
typeSymbol,
typeColor
))
} }
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 4*DAY) data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 2*DAY)
onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES) onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES)
} }
} }

View File

@ -13,7 +13,6 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiAttendances(override val data: DataLibrus, class LibrusApiAttendances(override val data: DataLibrus,
override val lastSync: Long?, override val lastSync: Long?,
@ -42,9 +41,9 @@ class LibrusApiAttendances(override val data: DataLibrus,
val lessonDate = Date.fromY_m_d(attendance.getString("Date")) val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id") val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id")
val semester = attendance.getInt("Semester") ?: return@forEach val semester = attendance.getInt("Semester") ?: return@forEach
val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
val typeObject = data.attendanceTypes[type] ?: null val typeId = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
val topic = typeObject?.name ?: "" val type = data.attendanceTypes[typeId] ?: null
val startTime = data.lessonRanges.get(lessonNo)?.startTime val startTime = data.lessonRanges.get(lessonNo)?.startTime
@ -52,29 +51,34 @@ class LibrusApiAttendances(override val data: DataLibrus,
data.librusLessons.singleOrNull { it.lessonId == lessonId } data.librusLessons.singleOrNull { it.lessonId == lessonId }
else null else null
val attendanceObject = Attendance(
profileId,
id,
teacherId ?: lesson?.teacherId ?: -1,
lesson?.subjectId ?: -1,
semester,
topic,
lessonDate,
startTime ?: Time(0, 0, 0),
typeObject?.type ?: Attendance.TYPE_CUSTOM
)
val addedDate = Date.fromIso(attendance.getString("AddDate") ?: return@forEach) val addedDate = Date.fromIso(attendance.getString("AddDate") ?: return@forEach)
val attendanceObject = Attendance(
profileId = profileId,
id = id,
baseType = type?.baseType ?: Attendance.TYPE_UNKNOWN,
typeName = type?.typeName ?: "nieznany rodzaj",
typeShort = type?.typeShort ?: "?",
typeSymbol = type?.typeSymbol ?: "?",
typeColor = type?.typeColor,
date = lessonDate,
startTime = startTime,
semester = semester,
teacherId = teacherId ?: lesson?.teacherId ?: -1,
subjectId = lesson?.subjectId ?: -1,
addedDate = addedDate
).also {
it.lessonNumber = lessonNo
}
data.attendanceList.add(attendanceObject) data.attendanceList.add(attendanceObject)
if(typeObject?.type != Attendance.TYPE_PRESENT) { if(type?.baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ATTENDANCE, Metadata.TYPE_ATTENDANCE,
id, id,
profile?.empty ?: false, profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN,
profile?.empty ?: false, profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN
addedDate
)) ))
} }
} }

View File

@ -55,7 +55,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = null, comment = null,
semester = 1, semester = 1,
teacherId = -1, teacherId = -1,
subjectId = 1 subjectId = 1,
addedDate = profile.getSemesterStart(1).inMillis
) )
data.gradeList.add(semester1StartGradeObject) data.gradeList.add(semester1StartGradeObject)
@ -64,8 +65,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
semester1StartGradeObject.id, semester1StartGradeObject.id,
true, true,
true, true
profile.getSemesterStart(1).inMillis
)) ))
} }
@ -83,7 +83,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = null, comment = null,
semester = 2, semester = 2,
teacherId = -1, teacherId = -1,
subjectId = 1 subjectId = 1,
addedDate = profile.getSemesterStart(2).inMillis
) )
data.gradeList.add(semester2StartGradeObject) data.gradeList.add(semester2StartGradeObject)
@ -92,8 +93,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
semester2StartGradeObject.id, semester2StartGradeObject.id,
true, true,
true, true
profile.getSemesterStart(2).inMillis
)) ))
} }
@ -155,7 +155,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = if (text != null) description.join(" - ") else null, comment = if (text != null) description.join(" - ") else null,
semester = semester, semester = semester,
teacherId = teacherId, teacherId = teacherId,
subjectId = 1 subjectId = 1,
addedDate = addedDate
).apply { ).apply {
valueMax = valueTo valueMax = valueTo
} }
@ -166,8 +167,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }

View File

@ -65,7 +65,8 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
comment = null, comment = null,
semester = semester, semester = semester,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId subjectId = subjectId,
addedDate = addedDate
) )
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
@ -74,8 +75,7 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }

View File

@ -35,7 +35,7 @@ class LibrusApiEvents(override val data: DataLibrus,
events?.forEach { event -> events?.forEach { event ->
val id = event.getLong("Id") ?: return@forEach val id = event.getLong("Id") ?: return@forEach
val eventDate = Date.fromY_m_d(event.getString("Date")) val eventDate = Date.fromY_m_d(event.getString("Date"))
val topic = event.getString("Content")?.trim() ?: "" var topic = event.getString("Content")?.trim() ?: ""
val type = event.getJsonObject("Category")?.getLong("Id") ?: -1 val type = event.getJsonObject("Category")?.getLong("Id") ?: -1
val teacherId = event.getJsonObject("CreatedBy")?.getLong("Id") ?: -1 val teacherId = event.getJsonObject("CreatedBy")?.getLong("Id") ?: -1
val subjectId = event.getJsonObject("Subject")?.getLong("Id") ?: -1 val subjectId = event.getJsonObject("Subject")?.getLong("Id") ?: -1
@ -46,6 +46,12 @@ class LibrusApiEvents(override val data: DataLibrus,
val startTime = lessonRange?.startTime ?: Time.fromH_m(event.getString("TimeFrom")) val startTime = lessonRange?.startTime ?: Time.fromH_m(event.getString("TimeFrom"))
val addedDate = Date.fromIso(event.getString("AddDate")) val addedDate = Date.fromIso(event.getString("AddDate"))
event.getJsonObject("onlineLessonUrl")?.let { onlineLesson ->
val text = onlineLesson.getString("text")?.let { "$it - " } ?: ""
val url = onlineLesson.getString("url")
topic += "\n\n$text$url"
}
val eventObject = Event( val eventObject = Event(
profileId = profileId, profileId = profileId,
id = id, id = id,
@ -56,7 +62,8 @@ class LibrusApiEvents(override val data: DataLibrus,
type = type, type = type,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId, subjectId = subjectId,
teamId = teamId teamId = teamId,
addedDate = addedDate
) )
data.eventList.add(eventObject) data.eventList.add(eventObject)
@ -66,8 +73,7 @@ class LibrusApiEvents(override val data: DataLibrus,
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
addedDate
)) ))
} }

View File

@ -79,7 +79,8 @@ class LibrusApiGrades(override val data: DataLibrus,
comment = null, comment = null,
semester = semester, semester = semester,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId subjectId = subjectId,
addedDate = addedDate
) )
grade.getJsonObject("Improvement")?.also { grade.getJsonObject("Improvement")?.also {
@ -98,8 +99,7 @@ class LibrusApiGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }

View File

@ -43,7 +43,8 @@ class LibrusApiHomework(override val data: DataLibrus,
type = -1, type = -1,
teacherId = teacherId, teacherId = teacherId,
subjectId = -1, subjectId = -1,
teamId = -1 teamId = -1,
addedDate = addedDate.inMillis
) )
data.eventList.add(eventObject) data.eventList.add(eventObject)
@ -52,8 +53,7 @@ class LibrusApiHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK, Metadata.TYPE_HOMEWORK,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
addedDate.inMillis
)) ))
} }

View File

@ -33,9 +33,9 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
val luckyNumberDate = Date.fromY_m_d(luckyNumberEl.getString("LuckyNumberDay")) ?: Date.getToday() val luckyNumberDate = Date.fromY_m_d(luckyNumberEl.getString("LuckyNumberDay")) ?: Date.getToday()
val luckyNumber = luckyNumberEl.getInt("LuckyNumber") ?: -1 val luckyNumber = luckyNumberEl.getInt("LuckyNumber") ?: -1
val luckyNumberObject = LuckyNumber( val luckyNumberObject = LuckyNumber(
profileId, profileId = profileId,
luckyNumberDate, date = luckyNumberDate,
luckyNumber number = luckyNumber
) )
if (luckyNumberDate >= Date.getToday()) if (luckyNumberDate >= Date.getToday())
@ -50,8 +50,7 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
Metadata.TYPE_LUCKY_NUMBER, Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
profile?.empty ?: false, profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -46,12 +46,15 @@ class LibrusApiNotices(override val data: DataLibrus,
val semester = profile?.dateToSemester(addedDate) ?: 1 val semester = profile?.dateToSemester(addedDate) ?: 1
val noticeObject = Notice( val noticeObject = Notice(
profileId, profileId = profileId,
id, id = id,
categoryText + "\n" + text, type = type,
semester, semester = semester,
type, text = text,
teacherId category = categoryText,
points = null,
teacherId = teacherId,
addedDate = addedDate.inMillis
) )
data.noticeList.add(noticeObject) data.noticeList.add(noticeObject)
@ -61,8 +64,7 @@ class LibrusApiNotices(override val data: DataLibrus,
Metadata.TYPE_NOTICE, Metadata.TYPE_NOTICE,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
addedDate.inMillis
)) ))
} }

View File

@ -56,7 +56,8 @@ class LibrusApiPointGrades(override val data: DataLibrus,
comment = null, comment = null,
semester = semester, semester = semester,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId subjectId = subjectId,
addedDate = addedDate
).apply { ).apply {
valueMax = category?.valueTo ?: 0f valueMax = category?.valueTo ?: 0f
} }
@ -67,8 +68,7 @@ class LibrusApiPointGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }

View File

@ -58,8 +58,7 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
id, id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }

View File

@ -43,15 +43,15 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
val timeTo = teacherAbsence.getString("TimeTo")?.let { Time.fromH_m_s(it) } val timeTo = teacherAbsence.getString("TimeTo")?.let { Time.fromH_m_s(it) }
val teacherAbsenceObject = TeacherAbsence( val teacherAbsenceObject = TeacherAbsence(
profileId, profileId = profileId,
id, id = id,
teacherId, type = type,
type, name = name,
name, dateFrom = dateFrom,
dateFrom, dateTo = dateTo,
dateTo, timeFrom = timeFrom,
timeFrom, timeTo = timeTo,
timeTo teacherId = teacherId
) )
data.teacherAbsenceList.add(teacherAbsenceObject) data.teacherAbsenceList.add(teacherAbsenceObject)
@ -60,8 +60,7 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
Metadata.TYPE_TEACHER_ABSENCE, Metadata.TYPE_TEACHER_ABSENCE,
id, id,
true, true,
profile?.empty ?: false, profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }

View File

@ -60,7 +60,8 @@ class LibrusApiTextGrades(override val data: DataLibrus,
comment = grade.getString("Phrase") /* whatever it is */, comment = grade.getString("Phrase") /* whatever it is */,
semester = semester, semester = semester,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId subjectId = subjectId,
addedDate = addedDate
) )
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
@ -69,8 +70,7 @@ class LibrusApiTextGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }

View File

@ -198,8 +198,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
Metadata.TYPE_LESSON_CHANGE, Metadata.TYPE_LESSON_CHANGE,
lessonObject.id, lessonObject.id,
seen, seen,
seen, seen
System.currentTimeMillis()
)) ))
} }
data.lessonList.add(lessonObject) data.lessonList.add(lessonObject)

View File

@ -97,7 +97,8 @@ class LibrusMessagesGetList(override val data: DataLibrus,
type = type, type = type,
subject = subject, subject = subject,
body = null, body = null,
senderId = senderId senderId = senderId,
addedDate = sentDate
) )
val messageRecipientObject = MessageRecipient( val messageRecipientObject = MessageRecipient(
@ -120,8 +121,7 @@ class LibrusMessagesGetList(override val data: DataLibrus,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
id, id,
notified, notified,
notified, notified
sentDate
)) ))
} }

View File

@ -150,8 +150,7 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
messageObject.id, messageObject.id,
true, true,
true, true
messageObject.addedDate
)) ))
} }

View File

@ -50,7 +50,7 @@ class LibrusMessagesSendMessage(override val data: DataLibrus,
LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = null) { LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id } val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event) EventBus.getDefault().postSticky(event)
onSuccess() onSuccess()

View File

@ -0,0 +1,24 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import pl.szczodrzynski.edziennik.data.api.LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusSandboxDownloadAttachment
import pl.szczodrzynski.edziennik.data.db.entity.Message
class LibrusSynergiaGetAttachment(override val data: DataLibrus,
val message: Message,
val attachmentId: Long,
val attachmentName: String,
val onSuccess: () -> Unit
) : LibrusSynergia(data, null) {
companion object {
const val TAG = "LibrusSynergiaGetAttachment"
}
init {
redirectUrlGet(TAG, "$LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL/${message.id}/$attachmentId") { url ->
LibrusSandboxDownloadAttachment(data, url, message, attachmentId, attachmentName, onSuccess)
}
}
}

View File

@ -0,0 +1,160 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import org.greenrobot.eventbus.EventBus
import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.swapFirstLastName
import pl.szczodrzynski.edziennik.utils.models.Date
class LibrusSynergiaGetMessage(override val data: DataLibrus,
private val messageObject: MessageFull,
val onSuccess: () -> Unit) : LibrusSynergia(data, null) {
companion object {
const val TAG = "LibrusSynergiaGetMessage"
}
init {
val endpoint = when (messageObject.type) {
Message.TYPE_SENT -> "wiadomosci/1/6/${messageObject.id}/f0"
else -> "wiadomosci/1/5/${messageObject.id}/f0"
}
data.profile?.also { profile ->
synergiaGet(TAG, endpoint) { text ->
val doc = Jsoup.parse(text)
val messageElement = doc.select(".container-message tr")[0].child(1)
val detailsElement = messageElement.child(1)
val readElement = messageElement.children().last()
val body = messageElement.select(".container-message-content").html()
messageObject.apply {
this.body = body
clearAttachments()
if (messageElement.children().size >= 5) {
messageElement.child(3).select("tr").forEachIndexed { i, attachment ->
if (i == 0) return@forEachIndexed // Skip the header
val filename = attachment.child(0).text().trim()
val attachmentId = "wiadomosci\\\\/pobierz_zalacznik\\\\/[0-9]+?\\\\/([0-9]+)\"".toRegex()
.find(attachment.select("img").attr("onclick"))?.get(1)
?: return@forEachIndexed
addAttachment(attachmentId.toLong(), filename, -1)
}
}
}
val messageRecipientList = mutableListOf<MessageRecipientFull>()
when (messageObject.type) {
Message.TYPE_RECEIVED -> {
val senderFullName = detailsElement.child(0).select(".left").text()
val senderGroupName = "\\[(.+?)]".toRegex().find(senderFullName)?.get(1)?.trim()
data.teacherList.singleOrNull { it.id == messageObject.senderId }?.apply {
setTeacherType(when (senderGroupName) {
/* https://api.librus.pl/2.0/Messages/Role */
"Pomoc techniczna Librus", "SuperAdministrator" -> Teacher.TYPE_SUPER_ADMIN
"Administrator szkoły" -> Teacher.TYPE_SCHOOL_ADMIN
"Dyrektor Szkoły" -> Teacher.TYPE_PRINCIPAL
"Nauczyciel" -> Teacher.TYPE_TEACHER
"Rodzic", "Opiekun" -> Teacher.TYPE_PARENT
"Sekretariat" -> Teacher.TYPE_SECRETARIAT
"Uczeń" -> Teacher.TYPE_STUDENT
"Pedagog/Psycholog szkolny" -> Teacher.TYPE_PEDAGOGUE
"Pracownik biblioteki" -> Teacher.TYPE_LIBRARIAN
"Inny specjalista" -> Teacher.TYPE_SPECIALIST
"Jednostka Nadrzędna" -> {
typeDescription = "Jednostka Nadrzędna"
Teacher.TYPE_OTHER
}
"Jednostka Samorządu Terytorialnego" -> {
typeDescription = "Jednostka Samorządu Terytorialnego"
Teacher.TYPE_OTHER
}
else -> Teacher.TYPE_OTHER
})
}
val readDateText = readElement.select(".left").text()
val readDate = when (readDateText.isNotNullNorEmpty()) {
true -> Date.fromIso(readDateText)
else -> 0
}
val messageRecipientObject = MessageRecipientFull(
profileId = profileId,
id = -1,
messageId = messageObject.id,
readDate = readDate
)
messageRecipientObject.fullName = profile.accountName
?: profile.studentNameLong
messageRecipientList.add(messageRecipientObject)
}
Message.TYPE_SENT -> {
readElement.select("tr").forEachIndexed { i, receiver ->
if (i == 0) return@forEachIndexed // Skip the header
val receiverFullName = receiver.child(0).text()
val receiverName = receiverFullName.split('(')[0].swapFirstLastName()
val teacher = data.teacherList.singleOrNull { it.fullName == receiverName }
val receiverId = teacher?.id ?: -1
val readDate = when (val readDateText = receiver.child(1).text().trim()) {
"NIE" -> 0
else -> Date.fromIso(readDateText)
}
val messageRecipientObject = MessageRecipientFull(
profileId = profileId,
id = receiverId,
messageId = messageObject.id,
readDate = readDate
)
messageRecipientObject.fullName = receiverName
messageRecipientList.add(messageRecipientObject)
}
}
}
if (!messageObject.seen) {
data.setSeenMetadataList.add(Metadata(
messageObject.profileId,
Metadata.TYPE_MESSAGE,
messageObject.id,
true,
true
))
}
messageObject.recipients = messageRecipientList
data.messageRecipientList.addAll(messageRecipientList)
data.messageList.add(messageObject)
data.messageListReplace = true
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
onSuccess()
}
} ?: onSuccess()
}
}

View File

@ -0,0 +1,116 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.ERROR_NOT_IMPLEMENTED
import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
import pl.szczodrzynski.edziennik.data.db.entity.*
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date
class LibrusSynergiaGetMessages(override val data: DataLibrus,
override val lastSync: Long?,
private val type: Int = Message.TYPE_RECEIVED,
archived: Boolean = false,
val onSuccess: (Int) -> Unit) : LibrusSynergia(data, lastSync) {
companion object {
const val TAG = "LibrusSynergiaGetMessages"
}
init {
val endpoint = when (type) {
Message.TYPE_RECEIVED -> "wiadomosci/5"
Message.TYPE_SENT -> "wiadomosci/6"
else -> null
}
val endpointId = when (type) {
Message.TYPE_RECEIVED -> ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_RECEIVED
else -> ENDPOINT_LIBRUS_SYNERGIA_MESSAGES_SENT
}
if (endpoint != null) {
synergiaGet(TAG, endpoint) { text ->
val doc = Jsoup.parse(text)
fun getRecipientId(name: String): Long = data.teacherList.singleOrNull {
it.fullNameLastFirst == name
}?.id ?: {
val teacherObject = Teacher(
profileId,
-1 * Utils.crc16(name.swapFirstLastName().toByteArray()).toLong(),
name.splitName()?.second!!,
name.splitName()?.first!!
)
data.teacherList.put(teacherObject.id, teacherObject)
teacherObject.id
}.invoke()
doc.select(".decorated.stretch tbody > tr").forEach { messageElement ->
val url = messageElement.select("a").first().attr("href")
val id = Regexes.LIBRUS_MESSAGE_ID.find(url)?.get(1)?.toLong() ?: return@forEach
val subject = messageElement.child(3).text()
val sentDate = Date.fromIso(messageElement.child(4).text())
val recipientName = messageElement.child(2).text().split('(')[0].fixName()
val recipientId = getRecipientId(recipientName)
val read = messageElement.child(2).attr("style").isNullOrBlank()
val senderId = when (type) {
Message.TYPE_RECEIVED -> recipientId
else -> null
}
val receiverId = when (type) {
Message.TYPE_RECEIVED -> -1
else -> recipientId
}
val notified = when (type) {
Message.TYPE_SENT -> true
else -> read || profile?.empty ?: false
}
val messageObject = Message(
profileId = profileId,
id = id,
type = type,
subject = subject,
body = null,
senderId = senderId,
addedDate = sentDate
)
val messageRecipientObject = MessageRecipient(
profileId,
receiverId,
-1,
if (read) 1 else 0,
id
)
messageObject.hasAttachments = !messageElement.child(1).select("img").isEmpty()
data.messageList.add(messageObject)
data.messageRecipientList.add(messageRecipientObject)
data.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
notified,
notified
))
}
when (type) {
Message.TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, MainActivity.DRAWER_ITEM_MESSAGES)
}
onSuccess(endpointId)
}
} else {
data.error(TAG, ERROR_NOT_IMPLEMENTED)
onSuccess(endpointId)
}
}
}

View File

@ -58,7 +58,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
elements[9].select("input").attr("onclick") elements[9].select("input").attr("onclick")
)?.get(1)?.toLong() ?: return@forEachIndexed )?.get(1)?.toLong() ?: return@forEachIndexed
val lessons = data.db.timetableDao().getForDateNow(profileId, eventDate) val lessons = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessons.firstOrNull { it.subjectId == subjectId }?.startTime val startTime = lessons.firstOrNull { it.subjectId == subjectId }?.startTime
val seen = when (profile.empty) { val seen = when (profile.empty) {
@ -76,7 +76,8 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
type = Event.TYPE_HOMEWORK, type = Event.TYPE_HOMEWORK,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId, subjectId = subjectId,
teamId = data.teamClass?.id ?: -1 teamId = data.teamClass?.id ?: -1,
addedDate = addedDate.inMillis
) )
data.eventList.add(eventObject) data.eventList.add(eventObject)
@ -85,8 +86,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK, Metadata.TYPE_HOMEWORK,
id, id,
seen, seen,
seen, seen
addedDate.inMillis
)) ))
} }
} }

View File

@ -18,6 +18,7 @@ import pl.szczodrzynski.edziennik.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import java.net.HttpURLConnection.* import java.net.HttpURLConnection.*
@Suppress("ConvertSecondaryConstructorToPrimary")
class LibrusLoginApi { class LibrusLoginApi {
companion object { companion object {
private const val TAG = "LoginLibrusApi" private const val TAG = "LoginLibrusApi"

View File

@ -10,6 +10,7 @@ import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.LibrusRecaptchaHelper
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.getUnixDate import pl.szczodrzynski.edziennik.getUnixDate
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
@ -35,17 +36,35 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
onSuccess() onSuccess()
} }
text?.contains("grecaptcha.ready") == true -> {
val url = response?.request()?.url()?.toString() ?: run {
data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
return
}
LibrusRecaptchaHelper(data.app, url, text, onSuccess = { newUrl ->
loginWithSynergia(newUrl)
}, onTimeout = {
data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_TIMEOUT, response, text)
})
}
text?.contains("<status>ok</status>") == true -> { text?.contains("<status>ok</status>") == true -> {
saveSessionId(response, text) saveSessionId(response, text)
onSuccess() onSuccess()
} }
text?.contains("<message>Niepoprawny login i/lub hasło.</message>") == true -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text) text?.contains("<message>Niepoprawny login i/lub hasło.</message>") == true -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text) text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
text?.contains("eAccessDeny") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text) text?.contains("eAccessDeny") == true -> {
// data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
data.messagesLoginSuccessful = false
onSuccess()
}
text?.contains("OffLine") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text) text?.contains("OffLine") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
text?.contains("<status>error</status>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text) text?.contains("<status>error</status>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
text?.contains("<type>eVarWhitThisNameNotExists</type>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text) text?.contains("<type>eVarWhitThisNameNotExists</type>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
text?.contains("<error>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text) text?.contains("<error>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
else -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
} }
} }

View File

@ -6,7 +6,10 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.* import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>) { class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>) {
@ -23,7 +26,7 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
val id = cols[0].toLong() val id = cols[0].toLong()
val lessonId = cols[1].toLong() val lessonId = cols[1].toLong()
data.mobiLessons.singleOrNull { it.id == lessonId }?.let { lesson -> data.mobiLessons.singleOrNull { it.id == lessonId }?.let { lesson ->
val type = when (cols[4]) { val baseType = when (cols[4]) {
"2" -> TYPE_ABSENT "2" -> TYPE_ABSENT
"5" -> TYPE_ABSENT_EXCUSED "5" -> TYPE_ABSENT_EXCUSED
"4" -> TYPE_RELEASED "4" -> TYPE_RELEASED
@ -31,16 +34,37 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
} }
val semester = data.profile?.dateToSemester(lesson.date) ?: 1 val semester = data.profile?.dateToSemester(lesson.date) ?: 1
val typeName = when (baseType) {
TYPE_ABSENT -> "nieobecność"
TYPE_ABSENT_EXCUSED -> "nieobecność usprawiedliwiona"
TYPE_RELEASED -> "zwolnienie"
TYPE_PRESENT -> "obecność"
else -> "nieznany rodzaj"
}
val typeSymbol = when (baseType) {
TYPE_ABSENT -> "|"
TYPE_ABSENT_EXCUSED -> "+"
TYPE_RELEASED -> "z"
TYPE_PRESENT -> "."
else -> "?"
}
val attendanceObject = Attendance( val attendanceObject = Attendance(
data.profileId, profileId = data.profileId,
id, id = id,
lesson.teacherId, baseType = baseType,
lesson.subjectId, typeName = typeName,
semester, typeShort = data.app.attendanceManager.getTypeShort(baseType),
lesson.topic, typeSymbol = typeSymbol,
lesson.date, typeColor = null,
lesson.startTime, date = lesson.date,
type) startTime = lesson.startTime,
semester = semester,
teacherId = lesson.teacherId,
subjectId = lesson.subjectId
).also {
it.lessonTopic = lesson.topic
}
data.attendanceList.add(attendanceObject) data.attendanceList.add(attendanceObject)
data.metadataList.add( data.metadataList.add(
@ -48,9 +72,8 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
data.profileId, data.profileId,
Metadata.TYPE_ATTENDANCE, Metadata.TYPE_ATTENDANCE,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
data.profile?.empty ?: false, data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -60,7 +60,9 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
type = type, type = type,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId, subjectId = subjectId,
teamId = teamId) teamId = teamId,
addedDate = addedDate
)
data.eventList.add(eventObject) data.eventList.add(eventObject)
data.metadataList.add( data.metadataList.add(
@ -69,8 +71,7 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false, data.profile?.empty ?: false
addedDate
)) ))
} }
} }

View File

@ -79,7 +79,9 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
comment = null, comment = null,
semester = semester, semester = semester,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId) subjectId = subjectId,
addedDate = addedDate
)
if (data.profile?.empty == true) { if (data.profile?.empty == true) {
addedDate = data.profile.dateSemester1Start.inMillis addedDate = data.profile.dateSemester1Start.inMillis
@ -92,8 +94,7 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false, data.profile?.empty ?: false
addedDate
)) ))
addedDate++ addedDate++
} }

View File

@ -40,7 +40,8 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
type = Event.TYPE_HOMEWORK, type = Event.TYPE_HOMEWORK,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId, subjectId = subjectId,
teamId = teamId) teamId = teamId
)
data.eventList.add(eventObject) data.eventList.add(eventObject)
data.metadataList.add( data.metadataList.add(
@ -49,8 +50,7 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_HOMEWORK, Metadata.TYPE_HOMEWORK,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false, data.profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -33,12 +33,16 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) {
val addedDate = Date.fromYmd(cols[7]).inMillis val addedDate = Date.fromYmd(cols[7]).inMillis
val noticeObject = Notice( val noticeObject = Notice(
data.profileId, profileId = data.profileId,
id, id = id,
text, type = type,
semester, semester = semester,
type, text = text,
teacherId) category = null,
points = null,
teacherId = teacherId,
addedDate = addedDate
)
data.noticeList.add(noticeObject) data.noticeList.add(noticeObject)
data.metadataList.add( data.metadataList.add(
@ -47,8 +51,7 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_NOTICE, Metadata.TYPE_NOTICE,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false, data.profile?.empty ?: false
addedDate
)) ))
} }
}} }}

View File

@ -8,9 +8,9 @@ import android.util.SparseArray
import androidx.core.util.set import androidx.core.util.set
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.fixName import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.keys import pl.szczodrzynski.edziennik.keys
import pl.szczodrzynski.edziennik.singleOrNull import pl.szczodrzynski.edziennik.singleOrNull
@ -97,8 +97,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_LESSON_CHANGE, Metadata.TYPE_LESSON_CHANGE,
it.id, it.id,
seen, seen,
seen, seen
System.currentTimeMillis()
)) ))
} }
data.lessonList += it data.lessonList += it

View File

@ -17,9 +17,9 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
val luckyNumber = it.groupValues[1].toInt() val luckyNumber = it.groupValues[1].toInt()
val luckyNumberObject = LuckyNumber( val luckyNumberObject = LuckyNumber(
data.profileId, profileId = data.profileId,
Date.getToday(), date = Date.getToday(),
luckyNumber number = luckyNumber
) )
data.luckyNumberList.add(luckyNumberObject) data.luckyNumberList.add(luckyNumberObject)
@ -29,8 +29,7 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
Metadata.TYPE_LUCKY_NUMBER, Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(), luckyNumberObject.date.value.toLong(),
true, true,
data.profile?.empty ?: false, data.profile?.empty ?: false
System.currentTimeMillis()
)) ))
} catch (_: Exception){} } catch (_: Exception){}
} }

View File

@ -11,7 +11,13 @@ 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.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.* import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_BELATED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT_CUSTOM
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.fixName import pl.szczodrzynski.edziennik.fixName
@ -71,6 +77,18 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
val types = Regexes.MOBIDZIENNIK_ATTENDANCE_TYPES
.find(text)
?.get(1)
?.split("<br/>")
?.map {
it.trimEnd(',')
.split(" ", limit = 2)
.let { it.getOrNull(0) to it.getOrNull(1) }
}
?.toMap()
val typeSymbols = types?.keys?.filterNotNull() ?: listOf()
Regexes.MOBIDZIENNIK_ATTENDANCE_TABLE.findAll(text).forEach { tableResult -> Regexes.MOBIDZIENNIK_ATTENDANCE_TABLE.findAll(text).forEach { tableResult ->
val table = tableResult[1] val table = tableResult[1]
val lessonDates = mutableListOf<Date>() val lessonDates = mutableListOf<Date>()
@ -92,55 +110,90 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
return@forEach return@forEach
ranges.forEach { range -> ranges.forEach { range ->
val lessonDate = dateIterator.next() val lessonDate = dateIterator.next()
val entry = entriesIterator.next() var entry = entriesIterator.next()
if (entry.isBlank()) if (entry.isBlank())
return@forEach return@forEach
val startTime = Time.fromH_m(range[1]) val startTime = Time.fromH_m(range[1])
val entryIterator = entry.iterator()
range[2].split(" / ").mapNotNull { Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON.find(it) }.forEachIndexed { index, lesson -> range[2].split(" / ").mapNotNull { Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON.find(it) }.forEachIndexed { index, lesson ->
val topic = lesson[2] val topic = lesson[1].substringAfter(" - ", missingDelimiterValue = "").takeIf { it.isNotBlank() }
if (topic.startsWith("Lekcja odwołana: ") || !entryIterator.hasNext()) if (topic?.startsWith("Lekcja odwołana: ") == true || entry.isEmpty())
return@forEachIndexed return@forEachIndexed
val subjectName = lesson[1] val subjectName = lesson[1].substringBefore(" - ")
//val team = lesson[3] //val team = lesson[3]
val teacherName = lesson[4].fixName() val teacherName = lesson[3].fixName()
val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1 val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1
val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1 val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1
val type = when (entryIterator.nextChar()) { var typeSymbol = ""
'.' -> TYPE_PRESENT for (symbol in typeSymbols) {
'|' -> TYPE_ABSENT if (entry.startsWith(symbol) && symbol.length > typeSymbol.length)
'+' -> TYPE_ABSENT_EXCUSED typeSymbol = symbol
's' -> TYPE_BELATED
'z' -> TYPE_RELEASED
else -> TYPE_PRESENT
} }
entry = entry.removePrefix(typeSymbol)
var isCounted = true
val baseType = when (typeSymbol) {
"." -> TYPE_PRESENT
"|" -> TYPE_ABSENT
"+" -> TYPE_ABSENT_EXCUSED
"s" -> TYPE_BELATED
"z" -> TYPE_RELEASED
else -> {
isCounted = false
when (typeSymbol) {
"e" -> TYPE_PRESENT_CUSTOM
"en" -> TYPE_ABSENT
"ep" -> TYPE_PRESENT_CUSTOM
else -> TYPE_UNKNOWN
}
}
}
val typeName = types?.get(typeSymbol) ?: ""
val typeColor = when (typeSymbol) {
"e" -> 0xff673ab7
"en" -> 0xffec407a
"ep" -> 0xff4caf50
else -> null
}?.toInt()
val typeShort = if (isCounted)
data.app.attendanceManager.getTypeShort(baseType)
else
typeSymbol
val semester = data.profile?.dateToSemester(lessonDate) ?: 1 val semester = data.profile?.dateToSemester(lessonDate) ?: 1
val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson[0].hashCode() and 0xFFFF) + index val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson[0].hashCode() and 0xFFFF) + index
val attendanceObject = Attendance( val attendanceObject = Attendance(
data.profileId, profileId = profileId,
id, id = id,
teacherId, baseType = baseType,
subjectId, typeName = typeName,
semester, typeShort = typeShort,
topic, typeSymbol = typeSymbol,
lessonDate, typeColor = typeColor,
startTime, date = lessonDate,
type) startTime = startTime,
semester = semester,
teacherId = teacherId,
subjectId = subjectId
).also {
it.lessonTopic = topic
it.isCounted = isCounted
}
data.attendanceList.add(attendanceObject) data.attendanceList.add(attendanceObject)
if (type != TYPE_PRESENT) { if (baseType != TYPE_PRESENT) {
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
data.profileId, data.profileId,
Metadata.TYPE_ATTENDANCE, Metadata.TYPE_ATTENDANCE,
id, id,
data.profile?.empty ?: false, data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
data.profile?.empty ?: false, data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -89,8 +89,8 @@ class MobidziennikWebCalendar(override val data: DataMobidziennik,
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
eventObject.id, eventObject.id,
profile?.empty ?: false, profile?.empty ?: false,
profile?.empty ?: false, profile?.empty ?: false
System.currentTimeMillis() /* no addedDate here though */ /* no addedDate here though */
)) ))
} }
} }

View File

@ -139,8 +139,7 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
message.id, message.id,
true, true,
true, true
message.addedDate
)) ))
} }

View File

@ -125,7 +125,8 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
comment = null, comment = null,
semester = gradeSemester, semester = gradeSemester,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId subjectId = subjectId,
addedDate = gradeAddedDateMillis
) )
gradeObject.classAverage = gradeClassAverage gradeObject.classAverage = gradeClassAverage
@ -137,8 +138,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
gradeObject.id, gradeObject.id,
profile.empty, profile.empty,
profile.empty, profile.empty
gradeAddedDateMillis
)) ))
} }
} }

View File

@ -77,11 +77,12 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
type = type, type = type,
subject = subject, subject = subject,
body = null, body = null,
senderId = senderId senderId = senderId,
addedDate = addedDate
) )
data.messageList.add(message) data.messageList.add(message)
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate)) data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true))
} }
// sync every 7 days as we probably don't expect more than // sync every 7 days as we probably don't expect more than

View File

@ -63,7 +63,8 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
type = Message.TYPE_RECEIVED, type = Message.TYPE_RECEIVED,
subject = subject, subject = subject,
body = null, body = null,
senderId = senderId senderId = senderId,
addedDate = addedDate
) )
if (hasAttachments) if (hasAttachments)
@ -76,8 +77,7 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
message.id, message.id,
isRead, isRead,
isRead || profile?.empty ?: false, isRead || profile?.empty ?: false
addedDate
)) ))
} }

View File

@ -78,7 +78,8 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
type = Message.TYPE_SENT, type = Message.TYPE_SENT,
subject = subject, subject = subject,
body = null, body = null,
senderId = null senderId = null,
addedDate = addedDate
) )
if (hasAttachments) if (hasAttachments)
@ -91,8 +92,7 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
message.id, message.id,
true, true,
true, true
addedDate
)) ))
} }

View File

@ -45,7 +45,7 @@ class MobidziennikWebSendMessage(override val data: DataMobidziennik,
MobidziennikWebMessagesAll(data, null) { MobidziennikWebMessagesAll(data, null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event) EventBus.getDefault().postSticky(event)
onSuccess() onSuccess()

View File

@ -139,6 +139,15 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
get() { mStudentSemesterId = mStudentSemesterId ?: profile?.getStudentData("studentSemesterId", 0); return mStudentSemesterId ?: 0 } get() { mStudentSemesterId = mStudentSemesterId ?: profile?.getStudentData("studentSemesterId", 0); return mStudentSemesterId ?: 0 }
set(value) { profile?.putStudentData("studentSemesterId", value) ?: return; mStudentSemesterId = value } set(value) { profile?.putStudentData("studentSemesterId", value) ?: return; mStudentSemesterId = value }
private var mSemester1Id: Int? = null
var semester1Id: Int
get() { mSemester1Id = mSemester1Id ?: profile?.getStudentData("semester1Id", 0); return mSemester1Id ?: 0 }
set(value) { profile?.putStudentData("semester1Id", value) ?: return; mSemester1Id = value }
private var mSemester2Id: Int? = null
var semester2Id: Int
get() { mSemester2Id = mSemester2Id ?: profile?.getStudentData("semester2Id", 0); return mSemester2Id ?: 0 }
set(value) { profile?.putStudentData("semester2Id", value) ?: return; mSemester2Id = value }
/** /**
* ListaUczniow/OkresNumer, e.g. 1 or 2 * ListaUczniow/OkresNumer, e.g. 1 or 2
*/ */

View File

@ -7,8 +7,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_ATTENDANCE import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_ATTENDANCE
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.TYPE_PRESENT import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
@ -25,57 +26,85 @@ class VulcanApiAttendance(override val data: DataVulcan,
data.db.attendanceTypeDao().getAllNow(profileId).toSparseArray(data.attendanceTypes) { it.id } data.db.attendanceTypeDao().getAllNow(profileId).toSparseArray(data.attendanceTypes) { it.id }
} }
val startDate: String = profile.getSemesterStart(profile.currentSemester).stringY_m_d val semesterId = data.studentSemesterId
val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d val semesterNumber = data.studentSemesterNumber
if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
getAttendance(profile, semesterId - 1, semesterNumber - 1) {
getAttendance(profile, semesterId, semesterNumber) {
finish()
}
}
}
else {
getAttendance(profile, semesterId, semesterNumber) {
finish()
}
}
} ?: onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE) }
private fun finish() {
data.setSyncNext(ENDPOINT_VULCAN_API_ATTENDANCE, SYNC_ALWAYS)
onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE)
}
private fun getAttendance(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
val startDate = profile.getSemesterStart(semesterNumber).stringY_m_d
val endDate = profile.getSemesterEnd(semesterNumber).stringY_m_d
apiGet(TAG, VULCAN_API_ENDPOINT_ATTENDANCE, parameters = mapOf( apiGet(TAG, VULCAN_API_ENDPOINT_ATTENDANCE, parameters = mapOf(
"DataPoczatkowa" to startDate, "DataPoczatkowa" to startDate,
"DataKoncowa" to endDate, "DataKoncowa" to endDate,
"IdOddzial" to data.studentClassId, "IdOddzial" to data.studentClassId,
"IdUczen" to data.studentId, "IdUczen" to data.studentId,
"IdOkresKlasyfikacyjny" to data.studentSemesterId "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ -> )) { json, _ ->
json.getJsonObject("Data")?.getJsonArray("Frekwencje")?.forEach { attendanceEl -> json.getJsonObject("Data")?.getJsonArray("Frekwencje")?.forEach { attendanceEl ->
val attendance = attendanceEl.asJsonObject val attendance = attendanceEl.asJsonObject
val attendanceCategory = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach) val type = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach)
?: return@forEach ?: return@forEach
val type = attendanceCategory.type
val id = (attendance.getInt("Dzien") ?: 0) + (attendance.getInt("Numer") ?: 0) val id = (attendance.getInt("Dzien") ?: 0) + (attendance.getInt("Numer") ?: 0)
val lessonDateMillis = Date.fromY_m_d(attendance.getString("DzienTekst")).inMillis val lessonDateMillis = Date.fromY_m_d(attendance.getString("DzienTekst")).inMillis
val lessonDate = Date.fromMillis(lessonDateMillis) val lessonDate = Date.fromMillis(lessonDateMillis)
val startTime = data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime
val lessonSemester = profile.dateToSemester(lessonDate) val lessonSemester = semesterNumber
val attendanceObject = Attendance( val attendanceObject = Attendance(
profileId, profileId = profileId,
id.toLong(), id = id.toLong(),
-1, baseType = type.baseType,
attendance.getLong("IdPrzedmiot") ?: -1, typeName = type.typeName,
lessonSemester, typeShort = type.typeShort,
attendance.getString("PrzedmiotNazwa") + attendanceCategory.name.let { " - $it" }, typeSymbol = type.typeSymbol,
lessonDate, typeColor = type.typeColor,
data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime, date = lessonDate,
type) startTime = startTime,
semester = lessonSemester,
teacherId = -1,
subjectId = attendance.getLong("IdPrzedmiot") ?: -1,
addedDate = lessonDate.combineWith(startTime)
).also {
it.lessonNumber = attendance.getInt("Numer")
it.isCounted = it.baseType != Attendance.TYPE_RELEASED
}
data.attendanceList.add(attendanceObject) data.attendanceList.add(attendanceObject)
if (attendanceObject.type != TYPE_PRESENT) { if (type.baseType != TYPE_PRESENT) {
data.metadataList.add(Metadata( data.metadataList.add(Metadata(
profileId, profileId,
Metadata.TYPE_ATTENDANCE, Metadata.TYPE_ATTENDANCE,
attendanceObject.id, attendanceObject.id,
profile.empty, profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN,
profile.empty, profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN
attendanceObject.lessonDate.combineWith(attendanceObject.startTime)
)) ))
} }
} }
data.setSyncNext(ENDPOINT_VULCAN_API_ATTENDANCE, SYNC_ALWAYS) onSuccess()
onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE)
} }
} ?: onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE) } }
} }

View File

@ -114,11 +114,11 @@ class VulcanApiDictionaries(override val data: DataVulcan,
private fun saveAttendanceType(attendanceType: JsonObject) { private fun saveAttendanceType(attendanceType: JsonObject) {
val id = attendanceType.getLong("Id") ?: return val id = attendanceType.getLong("Id") ?: return
val name = attendanceType.getString("Nazwa") ?: "" val typeName = attendanceType.getString("Nazwa") ?: ""
val absent = attendanceType.getBoolean("Nieobecnosc") ?: false val absent = attendanceType.getBoolean("Nieobecnosc") ?: false
val excused = attendanceType.getBoolean("Usprawiedliwione") ?: false val excused = attendanceType.getBoolean("Usprawiedliwione") ?: false
val type = if (absent) { val baseType = if (absent) {
if (excused) if (excused)
Attendance.TYPE_ABSENT_EXCUSED Attendance.TYPE_ABSENT_EXCUSED
else else
@ -137,15 +137,35 @@ class VulcanApiDictionaries(override val data: DataVulcan,
else if (present) else if (present)
Attendance.TYPE_PRESENT Attendance.TYPE_PRESENT
else else
Attendance.TYPE_CUSTOM Attendance.TYPE_UNKNOWN
}
val (typeColor, typeSymbol) = when (id.toInt()) {
1 -> 0xffffffff to "" // obecność
2 -> 0xffffa687 to "" // nieobecność
3 -> 0xfffcc150 to "u" // nieobecność usprawiedliwiona
4 -> 0xffede049 to "s" // spóźnienie
5 -> 0xffbbdd5f to "su" // spóźnienie usprawiedliwione
6 -> 0xffa9c9fd to "ns" // nieobecny z przyczyn szkolnych
7 -> 0xffddbbe5 to "z" // zwolniony
8 -> 0xffffffff to "" // usunięty wpis
else -> null to "?"
}
val typeShort = when (id.toInt()) {
6 -> "ns" // nieobecny z przyczyn szkolnych
8 -> "" // usunięty wpis
else -> data.app.attendanceManager.getTypeShort(baseType)
} }
val attendanceTypeObject = AttendanceType( val attendanceTypeObject = AttendanceType(
profileId, profileId,
id, id,
name, baseType,
type, typeName,
-1 typeShort,
typeSymbol,
typeColor?.toInt()
) )
data.attendanceTypes.put(id, attendanceTypeObject) data.attendanceTypes.put(id, attendanceTypeObject)

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getBoolean import pl.szczodrzynski.edziennik.getBoolean
import pl.szczodrzynski.edziennik.getJsonArray import pl.szczodrzynski.edziennik.getJsonArray
@ -31,11 +32,43 @@ class VulcanApiEvents(override val data: DataVulcan,
init { data.profile?.also { profile -> init { data.profile?.also { profile ->
val startDate: String = when (profile.empty) { val semesterId = data.studentSemesterId
true -> profile.getSemesterStart(profile.currentSemester).stringY_m_d val semesterNumber = data.studentSemesterNumber
if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
getEvents(profile, semesterId - 1, semesterNumber - 1) {
getEvents(profile, semesterId, semesterNumber) {
finish()
}
}
}
else {
getEvents(profile, semesterId, semesterNumber) {
finish()
}
}
} ?: onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS) }
private fun finish() {
when (isHomework) {
true -> {
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS)
}
false -> {
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS)
}
}
onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS)
}
private fun getEvents(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
val startDate = when (profile.empty) {
true -> profile.getSemesterStart(semesterNumber).stringY_m_d
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
} }
val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d val endDate = profile.getSemesterEnd(semesterNumber).stringY_m_d
val endpoint = when (isHomework) { val endpoint = when (isHomework) {
true -> VULCAN_API_ENDPOINT_HOMEWORK true -> VULCAN_API_ENDPOINT_HOMEWORK
@ -46,7 +79,7 @@ class VulcanApiEvents(override val data: DataVulcan,
"DataKoncowa" to endDate, "DataKoncowa" to endDate,
"IdOddzial" to data.studentClassId, "IdOddzial" to data.studentClassId,
"IdUczen" to data.studentId, "IdUczen" to data.studentId,
"IdOkresKlasyfikacyjny" to data.studentSemesterId "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ -> )) { json, _ ->
val events = json.getJsonArray("Data") val events = json.getJsonArray("Data")
@ -59,7 +92,7 @@ class VulcanApiEvents(override val data: DataVulcan,
val teacherId = event.getLong("IdPracownik") ?: -1 val teacherId = event.getLong("IdPracownik") ?: -1
val topic = event.getString("Opis")?.trim() ?: "" val topic = event.getString("Opis")?.trim() ?: ""
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate) val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
val type = when (isHomework) { val type = when (isHomework) {
@ -90,22 +123,11 @@ class VulcanApiEvents(override val data: DataVulcan,
if (isHomework) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT, if (isHomework) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
System.currentTimeMillis()
)) ))
} }
when (isHomework) { onSuccess()
true -> {
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS)
}
false -> {
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS)
}
}
onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS)
} }
} ?: onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS) } }
} }

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Grade import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import java.text.DecimalFormat import java.text.DecimalFormat
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -27,9 +28,33 @@ class VulcanApiGrades(override val data: DataVulcan,
init { data.profile?.also { profile -> init { data.profile?.also { profile ->
val semesterId = data.studentSemesterId
val semesterNumber = data.studentSemesterNumber
if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
getGrades(profile, semesterId - 1, semesterNumber - 1) {
getGrades(profile, semesterId, semesterNumber) {
finish()
}
}
}
else {
getGrades(profile, semesterId, semesterNumber) {
finish()
}
}
} ?: onSuccess(ENDPOINT_VULCAN_API_GRADES) }
private fun finish() {
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(data.studentSemesterNumber, TYPE_NORMAL))
data.setSyncNext(ENDPOINT_VULCAN_API_GRADES, SYNC_ALWAYS)
onSuccess(ENDPOINT_VULCAN_API_GRADES)
}
private fun getGrades(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
apiGet(TAG, VULCAN_API_ENDPOINT_GRADES, parameters = mapOf( apiGet(TAG, VULCAN_API_ENDPOINT_GRADES, parameters = mapOf(
"IdUczen" to data.studentId, "IdUczen" to data.studentId,
"IdOkresKlasyfikacyjny" to data.studentSemesterId "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ -> )) { json, _ ->
val grades = json.getJsonArray("Data") val grades = json.getJsonArray("Data")
@ -99,9 +124,10 @@ class VulcanApiGrades(override val data: DataVulcan,
category = category, category = category,
description = finalDescription, description = finalDescription,
comment = null, comment = null,
semester = data.studentSemesterNumber, semester = semesterNumber,
teacherId = teacherId, teacherId = teacherId,
subjectId = subjectId subjectId = subjectId,
addedDate = addedDate
) )
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
@ -110,15 +136,11 @@ class VulcanApiGrades(override val data: DataVulcan,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(data.studentSemesterNumber, Grade.TYPE_NORMAL)) onSuccess()
data.setSyncNext(ENDPOINT_VULCAN_API_GRADES, SYNC_ALWAYS)
onSuccess(ENDPOINT_VULCAN_API_GRADES)
} }
} ?: onSuccess(ENDPOINT_VULCAN_API_GRADES) } }
} }

View File

@ -37,8 +37,7 @@ class VulcanApiMessagesChangeStatus(override val data: DataVulcan,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
messageObject.id, messageObject.id,
true, true,
true, true
messageObject.addedDate
)) ))
messageObject.seen = true messageObject.seen = true

View File

@ -72,7 +72,8 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
type = TYPE_RECEIVED, type = TYPE_RECEIVED,
subject = subject, subject = subject,
body = body.replace("\n", "<br>"), body = body.replace("\n", "<br>"),
senderId = senderId senderId = senderId,
addedDate = sentDate
) )
val messageRecipientObject = MessageRecipient( val messageRecipientObject = MessageRecipient(
@ -90,8 +91,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
id, id,
readDate > 0, readDate > 0,
readDate > 0, readDate > 0
sentDate
)) ))
} }

View File

@ -97,7 +97,8 @@ class VulcanApiMessagesSent(override val data: DataVulcan,
type = TYPE_SENT, type = TYPE_SENT,
subject = subject, subject = subject,
body = body.replace("\n", "<br>"), body = body.replace("\n", "<br>"),
senderId = null senderId = null,
addedDate = sentDate
) )
data.messageList.add(messageObject) data.messageList.add(messageObject)
@ -106,8 +107,7 @@ class VulcanApiMessagesSent(override val data: DataVulcan,
Metadata.TYPE_MESSAGE, Metadata.TYPE_MESSAGE,
id, id,
true, true,
true, true
sentDate
)) ))
} }

View File

@ -11,12 +11,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonArray import pl.szczodrzynski.edziennik.getJsonArray
import pl.szczodrzynski.edziennik.getLong import pl.szczodrzynski.edziennik.getLong
import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.toSparseArray import pl.szczodrzynski.edziennik.toSparseArray
import pl.szczodrzynski.edziennik.utils.models.Date
class VulcanApiNotices(override val data: DataVulcan, class VulcanApiNotices(override val data: DataVulcan,
override val lastSync: Long?, override val lastSync: Long?,
@ -31,6 +31,29 @@ class VulcanApiNotices(override val data: DataVulcan,
data.db.noticeTypeDao().getAllNow(profileId).toSparseArray(data.noticeTypes) { it.id } data.db.noticeTypeDao().getAllNow(profileId).toSparseArray(data.noticeTypes) { it.id }
} }
val semesterId = data.studentSemesterId
val semesterNumber = data.studentSemesterNumber
if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
getNotices(profile, semesterId - 1, semesterNumber - 1) {
getNotices(profile, semesterId, semesterNumber) {
finish()
}
}
}
else {
getNotices(profile, semesterId, semesterNumber) {
finish()
}
}
} ?: onSuccess(ENDPOINT_VULCAN_API_NOTICES) }
private fun finish() {
data.setSyncNext(ENDPOINT_VULCAN_API_NOTICES, SYNC_ALWAYS)
onSuccess(ENDPOINT_VULCAN_API_NOTICES)
}
private fun getNotices(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
apiGet(TAG, VULCAN_API_ENDPOINT_NOTICES, parameters = mapOf( apiGet(TAG, VULCAN_API_ENDPOINT_NOTICES, parameters = mapOf(
"IdUczen" to data.studentId, "IdUczen" to data.studentId,
"IdOkresKlasyfikacyjny" to data.studentSemesterId "IdOkresKlasyfikacyjny" to data.studentSemesterId
@ -41,15 +64,21 @@ class VulcanApiNotices(override val data: DataVulcan,
val id = notice.getLong("Id") ?: return@forEach val id = notice.getLong("Id") ?: return@forEach
val text = notice.getString("TrescUwagi") ?: return@forEach val text = notice.getString("TrescUwagi") ?: return@forEach
val teacherId = notice.getLong("IdPracownik") ?: -1 val teacherId = notice.getLong("IdPracownik") ?: -1
val addedDate = Date.fromY_m_d(notice.getString("DataWpisuTekst")).inMillis val addedDate = notice.getLong("DataModyfikacji")?.times(1000) ?: System.currentTimeMillis()
val categoryId = notice.getLong("IdKategoriaUwag") ?: -1
val categoryText = data.noticeTypes[categoryId]?.name ?: ""
val noticeObject = Notice( val noticeObject = Notice(
profileId, profileId = profileId,
id, id = id,
text, type = Notice.TYPE_NEUTRAL,
profile.currentSemester, semester = profile.currentSemester,
Notice.TYPE_NEUTRAL, text = text,
teacherId category = categoryText,
points = null,
teacherId = teacherId,
addedDate = addedDate
) )
data.noticeList.add(noticeObject) data.noticeList.add(noticeObject)
@ -58,13 +87,11 @@ class VulcanApiNotices(override val data: DataVulcan,
Metadata.TYPE_NOTICE, Metadata.TYPE_NOTICE,
id, id,
profile.empty, profile.empty,
profile.empty, profile.empty
addedDate
)) ))
} }
data.setSyncNext(ENDPOINT_VULCAN_API_NOTICES, SYNC_ALWAYS) onSuccess()
onSuccess(ENDPOINT_VULCAN_API_NOTICES)
} }
} ?: onSuccess(ENDPOINT_VULCAN_API_NOTICES) } }
} }

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_FINAL import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_FINAL
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_PROPOSED import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_PROPOSED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.getJsonArray import pl.szczodrzynski.edziennik.getJsonArray
import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
@ -27,32 +28,54 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
init { data.profile?.also { profile -> init { data.profile?.also { profile ->
val semesterId = data.studentSemesterId
val semesterNumber = data.studentSemesterNumber
if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
getProposedGrades(profile, semesterId - 1, semesterNumber - 1) {
getProposedGrades(profile, semesterId, semesterNumber) {
finish()
}
}
}
else {
getProposedGrades(profile, semesterId, semesterNumber) {
finish()
}
}
} ?: onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY) }
private fun finish() {
data.setSyncNext(ENDPOINT_VULCAN_API_GRADES_SUMMARY, 6*HOUR)
onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY)
}
private fun getProposedGrades(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
apiGet(TAG, VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS, parameters = mapOf( apiGet(TAG, VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS, parameters = mapOf(
"IdUczen" to data.studentId, "IdUczen" to data.studentId,
"IdOkresKlasyfikacyjny" to data.studentSemesterId "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ -> )) { json, _ ->
val grades = json.getJsonObject("Data") val grades = json.getJsonObject("Data")
grades.getJsonArray("OcenyPrzewidywane")?.let { grades.getJsonArray("OcenyPrzewidywane")?.let {
processGradeList(it, isFinal = false) processGradeList(it, semesterNumber, isFinal = false)
} }
grades.getJsonArray("OcenyKlasyfikacyjne")?.let { grades.getJsonArray("OcenyKlasyfikacyjne")?.let {
processGradeList(it, isFinal = true) processGradeList(it, semesterNumber, isFinal = true)
} }
data.setSyncNext(ENDPOINT_VULCAN_API_GRADES_SUMMARY, 6*HOUR) onSuccess()
onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY)
} }
} ?: onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY) } }
private fun processGradeList(grades: JsonArray, isFinal: Boolean) { private fun processGradeList(grades: JsonArray, semesterNumber: Int, isFinal: Boolean) {
grades.asJsonObjectList()?.forEach { grade -> grades.asJsonObjectList().forEach { grade ->
val name = grade.get("Wpis").asString val name = grade.get("Wpis").asString
val value = Utils.getGradeValue(name) val value = Utils.getGradeValue(name)
val subjectId = grade.get("IdPrzedmiot").asLong val subjectId = grade.get("IdPrzedmiot").asLong
val id = subjectId * -100 - data.studentSemesterNumber val id = subjectId * -100 - semesterNumber
val color = Utils.getVulcanGradeColor(name) val color = Utils.getVulcanGradeColor(name)
@ -60,7 +83,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
profileId = profileId, profileId = profileId,
id = id, id = id,
name = name, name = name,
type = if (data.studentSemesterNumber == 1) { type = if (semesterNumber == 1) {
if (isFinal) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER1_PROPOSED if (isFinal) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER1_PROPOSED
} else { } else {
if (isFinal) TYPE_SEMESTER2_FINAL else TYPE_SEMESTER2_PROPOSED if (isFinal) TYPE_SEMESTER2_FINAL else TYPE_SEMESTER2_PROPOSED
@ -71,7 +94,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
category = "", category = "",
description = null, description = null,
comment = null, comment = null,
semester = data.studentSemesterNumber, semester = semesterNumber,
teacherId = -1, teacherId = -1,
subjectId = subjectId subjectId = subjectId
) )
@ -82,8 +105,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
Metadata.TYPE_GRADE, Metadata.TYPE_GRADE,
gradeObject.id, gradeObject.id,
data.profile?.empty ?: false, data.profile?.empty ?: false,
data.profile?.empty ?: false, data.profile?.empty ?: false
System.currentTimeMillis()
)) ))
} }
} }

View File

@ -54,7 +54,7 @@ class VulcanApiSendMessage(override val data: DataVulcan,
VulcanApiMessagesSent(data, null) { VulcanApiMessagesSent(data, null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event) EventBus.getDefault().postSticky(event)
onSuccess() onSuccess()

View File

@ -184,8 +184,7 @@ class VulcanApiTimetable(override val data: DataVulcan,
Metadata.TYPE_LESSON_CHANGE, Metadata.TYPE_LESSON_CHANGE,
lessonObject.id, lessonObject.id,
seen, seen,
seen, seen
System.currentTimeMillis()
)) ))
} }

View File

@ -60,6 +60,7 @@ class VulcanApiUpdateSemester(override val data: DataVulcan,
data.studentClassId = studentClassId data.studentClassId = studentClassId
data.studentSemesterId = studentSemesterId data.studentSemesterId = studentSemesterId
data.studentSemesterNumber = studentSemesterNumber data.studentSemesterNumber = studentSemesterNumber
data.profile.studentData["semester${studentSemesterNumber}Id"] = studentSemesterId
data.currentSemesterEndDate = currentSemesterEndDate data.currentSemesterEndDate = currentSemesterEndDate
profile.studentClassName = studentClassName profile.studentClassName = studentClassName
dateSemester1Start?.let { dateSemester1Start?.let {

View File

@ -177,6 +177,7 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
studentData["studentClassId"] = studentClassId studentData["studentClassId"] = studentClassId
studentData["studentSemesterId"] = studentSemesterId studentData["studentSemesterId"] = studentSemesterId
studentData["studentSemesterNumber"] = studentSemesterNumber studentData["studentSemesterNumber"] = studentSemesterNumber
studentData["semester${studentSemesterNumber}Id"] = studentSemesterId
studentData["schoolSymbol"] = schoolSymbol studentData["schoolSymbol"] = schoolSymbol
studentData["schoolShort"] = schoolShort studentData["schoolShort"] = schoolShort
studentData["schoolName"] = schoolCode studentData["schoolName"] = schoolCode

View File

@ -26,6 +26,11 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
} }
init { run { init { run {
if (data.studentSemesterNumber == 1 && data.semester1Id == 0)
data.semester1Id = data.studentSemesterNumber
if (data.studentSemesterNumber == 2 && data.semester2Id == 0)
data.semester2Id = data.studentSemesterNumber
copyFromLoginStore() copyFromLoginStore()
if (data.profile != null && data.isApiLoginValid()) { if (data.profile != null && data.isApiLoginValid()) {

View File

@ -88,6 +88,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
var teacherOnConflictStrategy = OnConflictStrategy.IGNORE var teacherOnConflictStrategy = OnConflictStrategy.IGNORE
var eventListReplace = false var eventListReplace = false
var messageListReplace = false var messageListReplace = false
var announcementListReplace = false
val classrooms = LongSparseArray<Classroom>() val classrooms = LongSparseArray<Classroom>()
val attendanceTypes = LongSparseArray<AttendanceType>() val attendanceTypes = LongSparseArray<AttendanceType>()
@ -120,7 +121,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
val attendanceList = mutableListOf<Attendance>() val attendanceList = mutableListOf<Attendance>()
val announcementList = mutableListOf<Announcement>() val announcementList = mutableListOf<Announcement>()
val announcementIgnoreList = mutableListOf<Announcement>()
val luckyNumberList = mutableListOf<LuckyNumber>() val luckyNumberList = mutableListOf<LuckyNumber>()
@ -178,7 +178,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
noticeList.clear() noticeList.clear()
attendanceList.clear() attendanceList.clear()
announcementList.clear() announcementList.clear()
announcementIgnoreList.clear()
luckyNumberList.clear() luckyNumberList.clear()
teacherAbsenceList.clear() teacherAbsenceList.clear()
messageList.clear() messageList.clear()
@ -284,39 +283,19 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
d("Metadata saved in ${System.currentTimeMillis()-startTime} ms") d("Metadata saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis() startTime = System.currentTimeMillis()
if (lessonList.isNotEmpty()) { db.timetableDao().putAll(lessonList, removeNotKept = true)
db.timetableDao() += lessonList db.gradeDao().putAll(gradeList, removeNotKept = true)
} db.eventDao().putAll(eventList, forceReplace = eventListReplace, removeNotKept = true)
if (gradeList.isNotEmpty()) {
db.gradeDao().addAll(gradeList)
}
if (eventList.isNotEmpty()) {
if (eventListReplace)
db.eventDao().replaceAll(eventList)
else
db.eventDao().upsertAll(eventList, removeNotKept = true)
}
if (noticeList.isNotEmpty()) { if (noticeList.isNotEmpty()) {
db.noticeDao().clear(profile.id) db.noticeDao().clear(profile.id)
db.noticeDao().addAll(noticeList) db.noticeDao().putAll(noticeList)
} }
if (attendanceList.isNotEmpty()) db.attendanceDao().putAll(attendanceList, removeNotKept = true)
db.attendanceDao().addAll(attendanceList) db.announcementDao().putAll(announcementList, forceReplace = announcementListReplace, removeNotKept = false)
if (announcementList.isNotEmpty()) db.luckyNumberDao().putAll(luckyNumberList)
db.announcementDao().addAll(announcementList) db.teacherAbsenceDao().putAll(teacherAbsenceList)
if (announcementIgnoreList.isNotEmpty())
db.announcementDao().addAllIgnore(announcementIgnoreList)
if (luckyNumberList.isNotEmpty())
db.luckyNumberDao().addAll(luckyNumberList)
if (teacherAbsenceList.isNotEmpty())
db.teacherAbsenceDao().addAll(teacherAbsenceList)
if (messageList.isNotEmpty()) { db.messageDao().putAll(messageList, forceReplace = messageListReplace, removeNotKept = false)
if (messageListReplace)
db.messageDao().replaceAll(messageList)
else
db.messageDao().upsertAll(messageList, removeNotKept = false) // TODO dataRemoveModel for messages
}
if (messageRecipientList.isNotEmpty()) if (messageRecipientList.isNotEmpty())
db.messageRecipientDao().addAll(messageRecipientList) db.messageRecipientDao().addAll(messageRecipientList)
if (messageRecipientIgnoreList.isNotEmpty()) if (messageRecipientIgnoreList.isNotEmpty())
@ -357,7 +336,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
} }
fun shouldSyncLuckyNumber(): Boolean { fun shouldSyncLuckyNumber(): Boolean {
return (db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday().value) ?: -1) == -1 return db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday()) == null
} }
/*fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) { /*fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) {

View File

@ -20,10 +20,10 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: TimetableDao) { fun commit(profileId: Int, dao: TimetableDao) {
if (dateFrom != null && dateTo != null) { if (dateFrom != null && dateTo != null) {
dao.clearBetweenDates(profileId, dateFrom, dateTo) dao.dontKeepBetweenDates(profileId, dateFrom, dateTo)
} else { } else {
dateFrom?.let { dateFrom -> dao.clearFromDate(profileId, dateFrom) } dateFrom?.let { dateFrom -> dao.dontKeepFromDate(profileId, dateFrom) }
dateTo?.let { dateTo -> dao.clearToDate(profileId, dateTo) } dateTo?.let { dateTo -> dao.dontKeepToDate(profileId, dateTo) }
} }
} }
} }
@ -69,7 +69,7 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: AttendanceDao) { fun commit(profileId: Int, dao: AttendanceDao) {
if (dateFrom != null) { if (dateFrom != null) {
dao.clearAfterDate(profileId, dateFrom) dao.dontKeepAfterDate(profileId, dateFrom)
} }
} }
} }

View File

@ -39,13 +39,13 @@ object Signing {
val appPassword by lazy { val appPassword by lazy {
iLoveApple( iLoveApple(
"ThisIsOurHardWorkPleaseDoNotCopyOrSteal(c)2019.KubaSz".sha256(), "ThisIsOurHardWorkPleaseDoNotCopyOrSteal(c)2019.KubaSz".sha256(),
BuildConfig.VERSION_NAME, BuildConfig.VERSION_NAME.substringBeforeLast('+'),
BuildConfig.VERSION_CODE.toLong() BuildConfig.VERSION_CODE.toLong()
) )
} }
/*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.MTIzNDU2Nzg5MDP/4SAI6B===.$param2".sha256() return "$param1.MTIzNDU2Nzg5MDwwzwp5Gx===.$param2".sha256()
} }
} }

View File

@ -40,8 +40,7 @@ class AppSync(val app: App, val notifications: MutableList<Notification>, val pr
Metadata.TYPE_EVENT, Metadata.TYPE_EVENT,
event.id, event.id,
isPast || markAsSeen || event.seen, isPast || markAsSeen || event.seen,
isPast || markAsSeen || event.notified, isPast || markAsSeen || event.notified
event.addedDate
) )
}) })
return app.db.eventDao().upsertAll(events).size return app.db.eventDao().upsertAll(events).size

View File

@ -53,7 +53,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
profileId = lesson.profileId, profileId = lesson.profileId,
profileName = profiles.singleOrNull { it.id == lesson.profileId }?.name, profileName = profiles.singleOrNull { it.id == lesson.profileId }?.name,
viewId = MainActivity.DRAWER_ITEM_TIMETABLE, viewId = MainActivity.DRAWER_ITEM_TIMETABLE,
addedDate = lesson.addedDate addedDate = System.currentTimeMillis()
).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "") ).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "")
} }
} }
@ -117,7 +117,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
} }
private fun gradeNotifications() { private fun gradeNotifications() {
for (grade in app.db.gradeDao().notNotifiedNow) { for (grade in app.db.gradeDao().getNotNotifiedNow()) {
val gradeName = when (grade.type) { val gradeName = when (grade.type) {
Grade.TYPE_SEMESTER1_PROPOSED, Grade.TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format_2, grade.name) Grade.TYPE_SEMESTER1_PROPOSED, Grade.TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format_2, grade.name)
Grade.TYPE_SEMESTER1_FINAL, Grade.TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format_2, grade.name) Grade.TYPE_SEMESTER1_FINAL, Grade.TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format_2, grade.name)
@ -144,7 +144,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
} }
private fun behaviourNotifications() { private fun behaviourNotifications() {
for (notice in app.db.noticeDao().notNotifiedNow) { for (notice in app.db.noticeDao().getNotNotifiedNow()) {
val noticeTypeStr = when (notice.type) { val noticeTypeStr = when (notice.type) {
Notice.TYPE_POSITIVE -> app.getString(R.string.notification_notice_praise) Notice.TYPE_POSITIVE -> app.getString(R.string.notification_notice_praise)
@ -155,7 +155,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
val text = app.getString( val text = app.getString(
R.string.notification_notice_format, R.string.notification_notice_format,
noticeTypeStr, noticeTypeStr,
notice.teacherFullName, notice.teacherName,
Date.fromMillis(notice.addedDate).formattedString Date.fromMillis(notice.addedDate).formattedString
) )
notifications += Notification( notifications += Notification(
@ -172,9 +172,9 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
} }
private fun attendanceNotifications() { private fun attendanceNotifications() {
for (attendance in app.db.attendanceDao().notNotifiedNow) { for (attendance in app.db.attendanceDao().getNotNotifiedNow()) {
val attendanceTypeStr = when (attendance.type) { val attendanceTypeStr = when (attendance.baseType) {
Attendance.TYPE_ABSENT -> app.getString(R.string.notification_absence) Attendance.TYPE_ABSENT -> app.getString(R.string.notification_absence)
Attendance.TYPE_ABSENT_EXCUSED -> app.getString(R.string.notification_absence_excused) Attendance.TYPE_ABSENT_EXCUSED -> app.getString(R.string.notification_absence_excused)
Attendance.TYPE_BELATED -> app.getString(R.string.notification_belated) Attendance.TYPE_BELATED -> app.getString(R.string.notification_belated)
@ -191,7 +191,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
R.string.notification_attendance_format, R.string.notification_attendance_format,
attendanceTypeStr, attendanceTypeStr,
attendance.subjectLongName, attendance.subjectLongName,
attendance.lessonDate.formattedString attendance.date.formattedString
) )
notifications += Notification( notifications += Notification(
id = Notification.buildId(attendance.profileId, Notification.TYPE_NEW_ATTENDANCE, attendance.id), id = Notification.buildId(attendance.profileId, Notification.TYPE_NEW_ATTENDANCE, attendance.id),
@ -207,10 +207,10 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
} }
private fun announcementNotifications() { private fun announcementNotifications() {
for (announcement in app.db.announcementDao().notNotifiedNow) { for (announcement in app.db.announcementDao().getNotNotifiedNow()) {
val text = app.getString( val text = app.getString(
R.string.notification_announcement_format, R.string.notification_announcement_format,
announcement.teacherFullName, announcement.teacherName,
announcement.subject announcement.subject
) )
notifications += Notification( notifications += Notification(
@ -247,9 +247,9 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
} }
private fun luckyNumberNotifications() { private fun luckyNumberNotifications() {
val luckyNumbers = app.db.luckyNumberDao().notNotifiedNow val luckyNumbers = app.db.luckyNumberDao().getNotNotifiedNow().toMutableList()
luckyNumbers?.removeAll { it.date < today } luckyNumbers.removeAll { it.date < today }
luckyNumbers?.forEach { luckyNumber -> luckyNumbers.forEach { luckyNumber ->
val profile = profiles.singleOrNull { it.id == luckyNumber.profileId } ?: return@forEach val profile = profiles.singleOrNull { it.id == luckyNumber.profileId } ?: return@forEach
val text = when (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) { val text = when (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) {
true -> when (luckyNumber.date.value) { true -> when (luckyNumber.date.value) {
@ -271,7 +271,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
profileId = luckyNumber.profileId, profileId = luckyNumber.profileId,
profileName = profile.name, profileName = profile.name,
viewId = MainActivity.DRAWER_ITEM_HOME, viewId = MainActivity.DRAWER_ITEM_HOME,
addedDate = luckyNumber.addedDate addedDate = System.currentTimeMillis()
) )
} }
} }
@ -280,7 +280,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
for (teacherAbsence in app.db.teacherAbsenceDao().getNotNotifiedNow()) { for (teacherAbsence in app.db.teacherAbsenceDao().getNotNotifiedNow()) {
val message = app.getString( val message = app.getString(
R.string.notification_teacher_absence_new_format, R.string.notification_teacher_absence_new_format,
teacherAbsence.teacherFullName teacherAbsence.teacherName
) )
notifications += Notification( notifications += Notification(
id = Notification.buildId(teacherAbsence.profileId, Notification.TYPE_TEACHER_ABSENCE, teacherAbsence.id), id = Notification.buildId(teacherAbsence.profileId, Notification.TYPE_TEACHER_ABSENCE, teacherAbsence.id),

View File

@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
LibrusLesson::class, LibrusLesson::class,
TimetableManual::class, TimetableManual::class,
Metadata::class Metadata::class
], version = 85) ], version = 88)
@TypeConverters( @TypeConverters(
ConverterTime::class, ConverterTime::class,
ConverterDate::class, ConverterDate::class,
@ -170,7 +170,10 @@ abstract class AppDb : RoomDatabase() {
Migration82(), Migration82(),
Migration83(), Migration83(),
Migration84(), Migration84(),
Migration85() Migration85(),
Migration86(),
Migration87(),
Migration88()
).allowMainThreadQueries().build() ).allowMainThreadQueries().build()
} }
} }

Some files were not shown because too many files have changed in this diff Show More