mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-12 13:40:47 +02:00
Compare commits
202 Commits
v4.0-beta.
...
api-v2
Author | SHA1 | Date | |
---|---|---|---|
dc9e6081c5 | |||
26f8c03570 | |||
97e0f36f09 | |||
9b13552b73 | |||
d8559637a5 | |||
00a90a14dc | |||
d56afb034b | |||
0327ba37f1 | |||
12a54e58b5 | |||
238250e8c9 | |||
041bfc6cc0 | |||
8a4866cb62 | |||
0e4d609bbf | |||
f07b12bd87 | |||
0413dbffa2 | |||
c214b48409 | |||
91a6366548 | |||
03c9932b8c | |||
ea4919a25d | |||
f98b174857 | |||
c0aeb0d2f3 | |||
fcb627aac6 | |||
7f0aea29cd | |||
f6dcbb6594 | |||
b790421693 | |||
f5a7799924 | |||
b052b5bd66 | |||
12d8de1def | |||
9303483470 | |||
f8adc86a0e | |||
db57c258c5 | |||
ddb2760c16 | |||
14d267a95a | |||
a6c4053896 | |||
949a68ec1d | |||
93333a8c48 | |||
da48c059ec | |||
ee5566d1ef | |||
b794b30346 | |||
0db6393bb0 | |||
fcc3c55110 | |||
328c07eaf4 | |||
b004ec048e | |||
b9f83875a0 | |||
8c869d082b | |||
043f8210ba | |||
41a79caf83 | |||
0427fa6087 | |||
2f3c912dbe | |||
219a7443c0 | |||
6deb408d80 | |||
c6e1ff2164 | |||
bc0918a115 | |||
55ff9173be | |||
d4d548846f | |||
ef4527f140 | |||
0b1e7242bb | |||
30b6ac2a06 | |||
a7fa7cb5e4 | |||
f3e87f9016 | |||
a983af6c28 | |||
114c841f0c | |||
e271048577 | |||
b8c5925e82 | |||
9bda6c8869 | |||
d1608d308c | |||
b8e1e1d33a | |||
8099a037e7 | |||
af23c932a6 | |||
4edabbb186 | |||
37a5bea79b | |||
40cdc7d713 | |||
49825aca48 | |||
1d57c4e705 | |||
87ae5787ee | |||
20f16c25a3 | |||
6f1ec79d9b | |||
18c7eea89c | |||
f73060aeb6 | |||
2f653b83b6 | |||
445dec907d | |||
927316d24b | |||
3957453ed6 | |||
0296c704cb | |||
1e7fe972de | |||
c95bc656ea | |||
a082d95b04 | |||
6866dd4801 | |||
2186da416e | |||
22d859fcde | |||
39514b69b3 | |||
c384736840 | |||
507657f273 | |||
60641742ed | |||
0fc6f07986 | |||
1b2bdc0580 | |||
9bac239f77 | |||
371acb2d2a | |||
454f82e139 | |||
e8da249353 | |||
c7950c53da | |||
b5502478e4 | |||
4480a7e486 | |||
7c7dff743b | |||
c568cd3f2e | |||
6ec2bc6f21 | |||
af3b6f3a97 | |||
d855118610 | |||
c9992d9fe8 | |||
85fe2636cc | |||
35f4a31a76 | |||
1e494ebb70 | |||
ed93627505 | |||
b9b4b0036f | |||
4aa31424d6 | |||
8a825227cb | |||
cc1b581d7e | |||
9936d90ae2 | |||
df1a241b2b | |||
ae89b33fb7 | |||
e05b483f5c | |||
715f536b23 | |||
930813fb8a | |||
acd5e9b998 | |||
06011bf4ae | |||
30e15b813c | |||
fcd7a7f349 | |||
42ef40439e | |||
098beb14fe | |||
0b186a754a | |||
d00963b53d | |||
e282af0e80 | |||
630361849c | |||
88a1de50ca | |||
d8263d0b6a | |||
611ab0f100 | |||
70c307b796 | |||
054a233ad6 | |||
55268f1c43 | |||
1bec6d281c | |||
f17a02be54 | |||
4e8fdd2225 | |||
59819b4a96 | |||
673378d8d9 | |||
30044d6b21 | |||
ee43d40680 | |||
1354faf8c7 | |||
1bfb3781ab | |||
d7d0c6f822 | |||
2bea18dc3c | |||
f998f2d956 | |||
faa77ee5fb | |||
88ec463284 | |||
b7df71d7d9 | |||
6a28dbd2c4 | |||
010f7fa1fe | |||
209f98594f | |||
54121c99a3 | |||
f6f1370edf | |||
d5863485f9 | |||
afc88d316b | |||
b141279811 | |||
1997ea25d5 | |||
f4b49eecd4 | |||
a4493ec964 | |||
af8bda9e92 | |||
06d252e4ca | |||
67be456bb0 | |||
aa5e225148 | |||
367f46fac8 | |||
d2f14093ec | |||
43ed621879 | |||
15c8134d13 | |||
c2b8f71467 | |||
a6b91c3a14 | |||
164cfbfd0d | |||
0bb340e96e | |||
f0447dc455 | |||
626bbfa7a4 | |||
169a900f01 | |||
d0992eaf54 | |||
fc21d757c3 | |||
54363ee919 | |||
fdad3b9997 | |||
4ad826ebe8 | |||
f5e1e9fdd9 | |||
82b232d0e5 | |||
c8c1fe5367 | |||
71128e0244 | |||
453bcaa1f6 | |||
48898ab1d4 | |||
a095520d0d | |||
2e0c6fa6a5 | |||
bfbc0861df | |||
3a500f3f28 | |||
df8094c39c | |||
448fd0e884 | |||
4717b4549e | |||
57a8d72f1c | |||
7e57617e04 | |||
37ddd643ac | |||
bcf3fef303 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -86,4 +86,5 @@ app/schemas/
|
||||
|
||||
signatures/
|
||||
|
||||
app/.cxx
|
||||
app/.cxx
|
||||
/i18n/
|
||||
|
10
.idea/jarRepositories.xml
generated
10
.idea/jarRepositories.xml
generated
@ -41,5 +41,15 @@
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven4" />
|
||||
<option name="name" value="maven4" />
|
||||
<option name="url" value="https://dl.bintray.com/undervoid/Powerpermission" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven4" />
|
||||
<option name="name" value="maven4" />
|
||||
<option name="url" value="https://dl.bintray.com/undervoid/PowerPermission" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
1
annotation/.gitignore
vendored
Normal file
1
annotation/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
29
annotation/build.gradle
Normal file
29
annotation/build.gradle
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-28.
|
||||
*/
|
||||
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
|
||||
sourceCompatibility = "7"
|
||||
targetCompatibility = "7"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-28.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.annotation
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@MustBeDocumented
|
||||
annotation class SelectiveDao(
|
||||
val db: KClass<*>
|
||||
)
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-28.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.annotation
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@MustBeDocumented
|
||||
annotation class UpdateSelective(
|
||||
val primaryKeys: Array<String>,
|
||||
val skippedColumns: Array<String> = []
|
||||
)
|
@ -128,6 +128,7 @@ dependencies {
|
||||
implementation "com.mikepenz:iconics-core:${versions.iconics}"
|
||||
implementation "com.mikepenz:iconics-views:${versions.iconics}"
|
||||
implementation "com.mikepenz:community-material-typeface:${versions.font_cmd}@aar"
|
||||
implementation "com.mikepenz:materialize:1.2.1"
|
||||
|
||||
implementation "com.github.kuba2k2:NavLib:${versions.navlib}"
|
||||
|
||||
@ -166,8 +167,8 @@ dependencies {
|
||||
//implementation project(":Navigation")
|
||||
implementation project(":szkolny-font")
|
||||
|
||||
debugImplementation "com.github.ChuckerTeam.Chucker:library:3.0.1"
|
||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1"
|
||||
implementation "com.github.ChuckerTeam.Chucker:library:3.0.1"
|
||||
//releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1"
|
||||
|
||||
//implementation 'com.github.wulkanowy:uonet-request-signer:master-SNAPSHOT'
|
||||
//implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1'
|
||||
@ -190,6 +191,16 @@ dependencies {
|
||||
implementation 'com.github.jetradarmobile:android-snowfall:1.2.0'
|
||||
|
||||
implementation "io.coil-kt:coil:0.9.2"
|
||||
|
||||
implementation 'com.github.kuba2k2:NumberSlidingPicker:2921225f76'
|
||||
|
||||
implementation project(":annotation")
|
||||
kapt project(":codegen")
|
||||
|
||||
implementation 'com.google.android:flexbox:2.0.1'
|
||||
|
||||
implementation 'com.qifan.powerpermission:powerpermission:1.0.0'
|
||||
implementation 'com.qifan.powerpermission:powerpermission-coroutines:1.0.0'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@ -24,12 +24,19 @@
|
||||
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.entity.Event { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.full.EventFull { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel { *; }
|
||||
-keepclassmembers class pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig { public *; }
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider
|
||||
|
||||
-keepnames class androidx.appcompat.view.menu.MenuBuilder { setHeaderTitleInt(java.lang.CharSequence); }
|
||||
-keepclassmembernames class androidx.appcompat.view.menu.StandardMenuPopup { private *; }
|
||||
-keepnames class androidx.appcompat.view.menu.MenuPopupHelper { showPopup(int, int, boolean, boolean); }
|
||||
|
||||
-keepclassmembernames class com.mikepenz.materialdrawer.widget.MiniDrawerSliderView { private *; }
|
||||
|
||||
-keep class .R
|
||||
-keep class **.R$* {
|
||||
<fields>;
|
||||
|
@ -14,6 +14,9 @@
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<!-- PowerPermission uses minSdk 21, it's safe to override as it is used only in >= 23 -->
|
||||
<uses-sdk tools:overrideLibrary="com.qifan.powerpermission.coroutines, com.qifan.powerpermission.core" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
@ -62,7 +65,7 @@
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/AppTheme.NoDisplay">
|
||||
android:theme="@style/AppTheme.Dark.NoDisplay">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
@ -84,7 +87,7 @@
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/AppTheme.NoDisplay" />
|
||||
android:theme="@style/AppTheme.Dark.NoDisplay" />
|
||||
<!-- NOTIFICATIONS -->
|
||||
<receiver android:name=".ui.widgets.notifications.WidgetNotificationsProvider"
|
||||
android:label="@string/widget_notifications_title">
|
||||
|
@ -1,36 +1,32 @@
|
||||
<h3>Wersja 4.0-beta.7, 2020-02-08</h3>
|
||||
<h3>Wersja 4.0, 2020-04-19</h3>
|
||||
<ul>
|
||||
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkosć oraz poprawność pobieranych danych.</li>
|
||||
<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 👏</li>
|
||||
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkość oraz poprawność pobieranych danych</li>
|
||||
<li>Udoskonalony wygląd Szkolnego - sprawi, że korzystanie z aplikacji będzie jeszcze przyjemniejsze</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>Łatwiejsze dodawanie własnych wydarzeń</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>
|
||||
<li><strike>Występują natomiast nowe błędy, dlatego proszę o ich zgłaszanie :)</strike></li>
|
||||
</ul>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<b>Uwaga.</b> Ponieważ to wersja <i>beta</i>, niektóre funkcje mogą nie działać prawidłowo.<br>
|
||||
Staramy się usuwać takie przypadki, jednak na chwilę obecną mogą występować błędy w:
|
||||
<ul>
|
||||
<li>Wysyłanie wiadomości może czasami nie działać - proszę o zgłaszanie wszystkich błędów na naszym serwerze Discord</li>
|
||||
<li>Terminarz - brak informacji o odwołanych lekcjach w dialogu</li>
|
||||
<li>Cisza nocna w powiadomieniach jeszcze nie działa.</li>
|
||||
</ul>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
Dzięki za korzystanie ze Szkolnego!<br>
|
||||
<i>© Kuba Szczodrzyński, Kacper Ziubryniewicz 2020</i>
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
/*secret password - removed for source code publication*/
|
||||
static toys AES_IV[16] = {
|
||||
0x21, 0xd7, 0x64, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
0x38, 0xd4, 0x73, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
||||
|
||||
|
@ -4,9 +4,6 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ShortcutInfo
|
||||
@ -31,9 +28,6 @@ import com.hypertrack.hyperlog.HyperLog
|
||||
import com.mikepenz.iconics.Iconics
|
||||
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
|
||||
import im.wangchao.mhttp.MHttp
|
||||
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar
|
||||
import im.wangchao.mhttp.internal.cookie.cache.SetCookieCache
|
||||
import im.wangchao.mhttp.internal.cookie.persistence.SharedPrefsCookiePersistor
|
||||
import kotlinx.coroutines.*
|
||||
import me.leolin.shortcutbadger.ShortcutBadger
|
||||
import okhttp3.OkHttpClient
|
||||
@ -44,10 +38,12 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.network.NetworkUtils
|
||||
import pl.szczodrzynski.edziennik.network.cookie.DumbCookieJar
|
||||
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
||||
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity
|
||||
import pl.szczodrzynski.edziennik.utils.*
|
||||
import pl.szczodrzynski.edziennik.utils.managers.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@ -61,27 +57,15 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
get() = profile.id
|
||||
|
||||
var devMode = false
|
||||
var debugMode = false
|
||||
}
|
||||
|
||||
val notifications by lazy { Notifications() }
|
||||
inner class Notifications {
|
||||
val syncId = 1
|
||||
val syncKey = "pl.szczodrzynski.edziennik.SYNC"
|
||||
val syncChannelName: String by lazy { getString(R.string.notification_channel_get_data_name) }
|
||||
val syncChannelDesc: String by lazy { getString(R.string.notification_channel_get_data_desc) }
|
||||
val dataId = 50
|
||||
val dataKey = "pl.szczodrzynski.edziennik.DATA"
|
||||
val dataChannelName: String by lazy { getString(R.string.notification_channel_notifications_name) }
|
||||
val dataChannelDesc: String by lazy { getString(R.string.notification_channel_notifications_desc) }
|
||||
val dataQuietId = 60
|
||||
val dataQuietKey = "pl.szczodrzynski.edziennik.DATA_QUIET"
|
||||
val dataQuietChannelName: String by lazy { getString(R.string.notification_channel_notifications_quiet_name) }
|
||||
val dataQuietChannelDesc: String by lazy { getString(R.string.notification_channel_notifications_quiet_desc) }
|
||||
val updatesId = 100
|
||||
val updatesKey = "pl.szczodrzynski.edziennik.UPDATES"
|
||||
val updatesChannelName: String by lazy { getString(R.string.notification_channel_updates_name) }
|
||||
val updatesChannelDesc: String by lazy { getString(R.string.notification_channel_updates_desc) }
|
||||
}
|
||||
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
|
||||
val userActionManager by lazy { UserActionManager(this) }
|
||||
val gradesManager by lazy { GradesManager(this) }
|
||||
val timetableManager by lazy { TimetableManager(this) }
|
||||
val eventManager by lazy { EventManager(this) }
|
||||
val permissionManager by lazy { PermissionManager(this) }
|
||||
|
||||
val db
|
||||
get() = App.db
|
||||
@ -99,7 +83,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
.setMinimumLoggingLevel(Log.VERBOSE)
|
||||
.build()
|
||||
|
||||
val preferences by lazy { getSharedPreferences(getString(R.string.preference_file), Context.MODE_PRIVATE) }
|
||||
val permissionChecker by lazy { PermissionChecker(this) }
|
||||
val networkUtils by lazy { NetworkUtils(this) }
|
||||
val gson by lazy { Gson() }
|
||||
@ -122,7 +105,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
.readTimeout(10, TimeUnit.SECONDS)
|
||||
builder.installHttpsSupport(this)
|
||||
|
||||
if (devMode || BuildConfig.DEBUG) {
|
||||
if (debugMode || BuildConfig.DEBUG) {
|
||||
HyperLog.initialize(this)
|
||||
HyperLog.setLogLevel(Log.VERBOSE)
|
||||
HyperLog.setLogFormat(DebugLogFormat(this))
|
||||
@ -139,7 +122,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
.followSslRedirects(false)
|
||||
.build()
|
||||
}
|
||||
val cookieJar by lazy { PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(this)) }
|
||||
val cookieJar by lazy { DumbCookieJar(this) }
|
||||
|
||||
/* _____ _ _
|
||||
/ ____(_) | |
|
||||
@ -177,13 +160,18 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
Iconics.registerFont(SzkolnyFont)
|
||||
App.db = AppDb(this)
|
||||
Themes.themeInt = config.ui.theme
|
||||
debugMode = config.debugMode
|
||||
MHttp.instance().customOkHttpClient(http)
|
||||
|
||||
if (!profileLoadById(config.lastProfileId)) {
|
||||
db.profileDao().firstId?.let { profileLoadById(it) }
|
||||
}
|
||||
|
||||
devMode = "f054761fbdb6a238" == deviceId || BuildConfig.DEBUG
|
||||
config.ui.language?.let {
|
||||
setLanguage(it)
|
||||
}
|
||||
|
||||
devMode = BuildConfig.DEBUG
|
||||
|
||||
Signing.getCert(this)
|
||||
|
||||
@ -193,6 +181,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
|
||||
if (config.devModePassword != null)
|
||||
checkDevModePassword()
|
||||
debugMode = devMode || config.debugMode
|
||||
|
||||
if (config.sync.enabled)
|
||||
SyncWorker.scheduleNext(this@App, false)
|
||||
@ -251,29 +240,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
)
|
||||
} // shortcuts - end
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(notifications.syncKey, notifications.syncChannelName, NotificationManager.IMPORTANCE_MIN).apply {
|
||||
description = notifications.syncChannelDesc
|
||||
})
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(notifications.dataKey, notifications.dataChannelName, NotificationManager.IMPORTANCE_HIGH).apply {
|
||||
description = notifications.dataChannelDesc
|
||||
enableLights(true)
|
||||
lightColor = 0xff2196f3.toInt()
|
||||
})
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(notifications.dataQuietKey, notifications.dataQuietChannelName, NotificationManager.IMPORTANCE_LOW).apply {
|
||||
description = notifications.dataQuietChannelDesc
|
||||
setSound(null, null)
|
||||
enableVibration(false)
|
||||
})
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(notifications.updatesKey, notifications.updatesChannelName, NotificationManager.IMPORTANCE_DEFAULT).apply {
|
||||
description = notifications.updatesChannelDesc
|
||||
})
|
||||
}
|
||||
notificationChannelsManager.registerAllChannels()
|
||||
|
||||
|
||||
if (config.appInstalledTime == 0L)
|
||||
@ -394,4 +361,4 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-11.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik;
|
||||
|
||||
import android.graphics.Paint;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.databinding.BindingAdapter;
|
||||
|
||||
public class Binding {
|
||||
@BindingAdapter("strikeThrough")
|
||||
public static void strikeThrough(TextView textView, Boolean strikeThrough) {
|
||||
if (strikeThrough) {
|
||||
textView.setPaintFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
} else {
|
||||
textView.setPaintFlags(textView.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
}
|
||||
}
|
||||
}
|
20
app/src/main/java/pl/szczodrzynski/edziennik/Binding.kt
Normal file
20
app/src/main/java/pl/szczodrzynski/edziennik/Binding.kt
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-11.
|
||||
*/
|
||||
package pl.szczodrzynski.edziennik
|
||||
|
||||
import android.graphics.Paint
|
||||
import android.widget.TextView
|
||||
import androidx.databinding.BindingAdapter
|
||||
|
||||
object Binding {
|
||||
@JvmStatic
|
||||
@BindingAdapter("strikeThrough")
|
||||
fun strikeThrough(textView: TextView, strikeThrough: Boolean) {
|
||||
if (strikeThrough) {
|
||||
textView.paintFlags = textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||
} else {
|
||||
textView.paintFlags = textView.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ package pl.szczodrzynski.edziennik
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
@ -10,6 +12,7 @@ import android.content.res.Resources
|
||||
import android.database.Cursor
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffColorFilter
|
||||
import android.graphics.Rect
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
@ -23,10 +26,8 @@ import android.util.Base64
|
||||
import android.util.Base64.NO_WRAP
|
||||
import android.util.Base64.encodeToString
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import android.view.WindowManager
|
||||
import android.widget.*
|
||||
import androidx.annotation.*
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.database.getIntOrNull
|
||||
@ -36,10 +37,15 @@ import androidx.core.util.forEach
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.google.android.gms.security.ProviderInstaller
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import im.wangchao.mhttp.Response
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
@ -49,15 +55,23 @@ import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.TlsVersion
|
||||
import okio.Buffer
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApiException
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
||||
import pl.szczodrzynski.edziennik.network.TLSSocketFactory
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import java.io.InterruptedIOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.math.BigInteger
|
||||
import java.net.ConnectException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
import java.nio.charset.Charset
|
||||
import java.security.KeyStore
|
||||
import java.security.MessageDigest
|
||||
@ -67,6 +81,7 @@ import java.util.zip.CRC32
|
||||
import javax.crypto.Mac
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.SSLException
|
||||
import javax.net.ssl.TrustManagerFactory
|
||||
import javax.net.ssl.X509TrustManager
|
||||
import kotlin.Pair
|
||||
@ -86,8 +101,8 @@ fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) n
|
||||
fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong }
|
||||
fun JsonObject?.getFloat(key: String): Float? = get(key)?.let { if(it.isJsonNull) null else it.asFloat }
|
||||
fun JsonObject?.getChar(key: String): Char? = get(key)?.let { if(it.isJsonNull) null else it.asCharacter }
|
||||
fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonNull) null else it.asJsonObject }
|
||||
fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonNull) null else it.asJsonArray }
|
||||
fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonObject) it.asJsonObject else null }
|
||||
fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonArray) it.asJsonArray else null }
|
||||
|
||||
fun JsonObject?.getBoolean(key: String, defaultValue: Boolean): Boolean = get(key)?.let { if (it.isJsonNull) defaultValue else it.asBoolean } ?: defaultValue
|
||||
fun JsonObject?.getString(key: String, defaultValue: String): String = get(key)?.let { if (it.isJsonNull) defaultValue else it.asString } ?: defaultValue
|
||||
@ -95,8 +110,19 @@ fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if
|
||||
fun JsonObject?.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: defaultValue
|
||||
fun JsonObject?.getFloat(key: String, defaultValue: Float): Float = get(key)?.let { if(it.isJsonNull) defaultValue else it.asFloat } ?: defaultValue
|
||||
fun JsonObject?.getChar(key: String, defaultValue: Char): Char = get(key)?.let { if(it.isJsonNull) defaultValue else it.asCharacter } ?: defaultValue
|
||||
fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonObject } ?: defaultValue
|
||||
fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonArray } ?: defaultValue
|
||||
fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonObject) it.asJsonObject else defaultValue } ?: defaultValue
|
||||
fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonArray) it.asJsonArray else defaultValue } ?: defaultValue
|
||||
|
||||
fun JsonArray.getBoolean(key: Int): Boolean? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asBoolean }
|
||||
fun JsonArray.getString(key: Int): String? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asString }
|
||||
fun JsonArray.getInt(key: Int): Int? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asInt }
|
||||
fun JsonArray.getLong(key: Int): Long? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asLong }
|
||||
fun JsonArray.getFloat(key: Int): Float? = if (key >= size()) null else get(key)?.let { if(it.isJsonNull) null else it.asFloat }
|
||||
fun JsonArray.getChar(key: Int): Char? = if (key >= size()) null else get(key)?.let { if(it.isJsonNull) null else it.asCharacter }
|
||||
fun JsonArray.getJsonObject(key: Int): JsonObject? = if (key >= size()) null else get(key)?.let { if (it.isJsonObject) it.asJsonObject else null }
|
||||
fun JsonArray.getJsonArray(key: Int): JsonArray? = if (key >= size()) null else get(key)?.let { if (it.isJsonArray) it.asJsonArray else null }
|
||||
|
||||
fun String.toJsonObject(): JsonObject? = try { JsonParser().parse(this).asJsonObject } catch (ignore: Exception) { null }
|
||||
|
||||
operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value)
|
||||
operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value)
|
||||
@ -116,6 +142,10 @@ fun CharSequence?.isNotNullNorEmpty(): Boolean {
|
||||
return this != null && this.isNotEmpty()
|
||||
}
|
||||
|
||||
fun <T> Collection<T>?.isNotNullNorEmpty(): Boolean {
|
||||
return this != null && this.isNotEmpty()
|
||||
}
|
||||
|
||||
fun CharSequence?.isNotNullNorBlank(): Boolean {
|
||||
return this != null && this.isNotBlank()
|
||||
}
|
||||
@ -135,6 +165,13 @@ fun Bundle?.getString(key: String, defaultValue: String): String {
|
||||
return this?.getString(key, defaultValue) ?: defaultValue
|
||||
}
|
||||
|
||||
fun Bundle?.getIntOrNull(key: String): Int? {
|
||||
return this?.get(key) as? Int
|
||||
}
|
||||
fun <T : Any> Bundle?.get(key: String): T? {
|
||||
return this?.get(key) as? T?
|
||||
}
|
||||
|
||||
/**
|
||||
* ` The quick BROWN_fox Jumps OveR THE LAZy-DOG. `
|
||||
*
|
||||
@ -417,7 +454,7 @@ operator fun MatchResult.get(group: Int): String {
|
||||
return groupValues[group]
|
||||
}
|
||||
|
||||
fun Activity.setLanguage(language: String) {
|
||||
fun Context.setLanguage(language: String) {
|
||||
val locale = Locale(language.toLowerCase(Locale.ROOT))
|
||||
val configuration = resources.configuration
|
||||
Locale.setDefault(locale)
|
||||
@ -426,7 +463,6 @@ fun Activity.setLanguage(language: String) {
|
||||
}
|
||||
configuration.locale = locale
|
||||
resources.updateConfiguration(configuration, resources.displayMetrics)
|
||||
baseContext.resources.updateConfiguration(configuration, baseContext.resources.displayMetrics)
|
||||
}
|
||||
|
||||
/*
|
||||
@ -535,7 +571,7 @@ fun CharSequence?.asBoldSpannable(): Spannable {
|
||||
spannable.setSpan(StyleSpan(Typeface.BOLD), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return spannable
|
||||
}
|
||||
fun CharSequence.asSpannable(vararg spans: Any, substring: String? = null, ignoreCase: Boolean = false): Spannable {
|
||||
fun CharSequence.asSpannable(vararg spans: Any, substring: String? = null, ignoreCase: Boolean = false, ignoreDiacritics: Boolean = false): Spannable {
|
||||
val spannable = SpannableString(this)
|
||||
if (substring == null) {
|
||||
spans.forEach {
|
||||
@ -543,17 +579,44 @@ fun CharSequence.asSpannable(vararg spans: Any, substring: String? = null, ignor
|
||||
}
|
||||
}
|
||||
else if (substring.isNotEmpty()) {
|
||||
var index = indexOf(substring, ignoreCase = ignoreCase)
|
||||
val string =
|
||||
if (ignoreDiacritics)
|
||||
this.cleanDiacritics()
|
||||
else this
|
||||
|
||||
var index = string.indexOf(substring, ignoreCase = ignoreCase)
|
||||
.takeIf { it != -1 } ?: indexOf(substring, ignoreCase = ignoreCase)
|
||||
while (index >= 0) {
|
||||
spans.forEach {
|
||||
spannable.setSpan(it, index, index + substring.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
index = indexOf(substring, startIndex = index + 1, ignoreCase = ignoreCase)
|
||||
index = string.indexOf(substring, startIndex = index + 1, ignoreCase = ignoreCase)
|
||||
.takeIf { it != -1 } ?: indexOf(substring, startIndex = index + 1, ignoreCase = ignoreCase)
|
||||
}
|
||||
}
|
||||
return spannable
|
||||
}
|
||||
|
||||
fun CharSequence.cleanDiacritics(): String {
|
||||
val nameClean = StringBuilder()
|
||||
forEach {
|
||||
val ch = when (it) {
|
||||
'ż' -> 'z'
|
||||
'ó' -> 'o'
|
||||
'ł' -> 'l'
|
||||
'ć' -> 'c'
|
||||
'ę' -> 'e'
|
||||
'ś' -> 's'
|
||||
'ą' -> 'a'
|
||||
'ź' -> 'z'
|
||||
'ń' -> 'n'
|
||||
else -> it
|
||||
}
|
||||
nameClean.append(ch)
|
||||
}
|
||||
return nameClean.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new read-only list only of those given elements, that are not empty.
|
||||
* Applies for CharSequence and descendants.
|
||||
@ -697,6 +760,13 @@ inline fun <T : View> T.onClick(crossinline onClickListener: (v: T) -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <T : View> T.onLongClick(crossinline onLongClickListener: (v: T) -> Boolean) {
|
||||
setOnLongClickListener { v: View ->
|
||||
onLongClickListener(v as T)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <T : CompoundButton> T.onChange(crossinline onChangeListener: (v: T, isChecked: Boolean) -> Unit) {
|
||||
setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
@ -704,6 +774,19 @@ inline fun <T : CompoundButton> T.onChange(crossinline onChangeListener: (v: T,
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <T : MaterialButton> T.onChange(crossinline onChangeListener: (v: T, isChecked: Boolean) -> Unit) {
|
||||
clearOnCheckedChangeListeners()
|
||||
addOnCheckedChangeListener { buttonView, isChecked ->
|
||||
onChangeListener(buttonView as T, isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
fun View.attachToastHint(stringRes: Int) = onLongClick {
|
||||
Toast.makeText(it.context, stringRes, Toast.LENGTH_SHORT).show()
|
||||
true
|
||||
}
|
||||
|
||||
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
|
||||
observe(lifecycleOwner, object : Observer<T> {
|
||||
override fun onChanged(t: T?) {
|
||||
@ -759,7 +842,7 @@ fun View.findParentById(targetId: Int): View? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: () -> Unit) = launch {
|
||||
fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: suspend CoroutineScope.() -> Unit) = launch {
|
||||
delay(delayMillis)
|
||||
if (repeatMillis > 0) {
|
||||
while (true) {
|
||||
@ -983,6 +1066,7 @@ fun Context.getNotificationTitle(type: Int): String {
|
||||
Notification.TYPE_FEEDBACK_MESSAGE -> R.string.notification_type_feedback_message
|
||||
Notification.TYPE_NEW_ANNOUNCEMENT -> R.string.notification_type_new_announcement
|
||||
Notification.TYPE_AUTO_ARCHIVING -> R.string.notification_type_auto_archiving
|
||||
Notification.TYPE_TEACHER_ABSENCE -> R.string.notification_type_new_teacher_absence
|
||||
Notification.TYPE_GENERAL -> R.string.notification_type_general
|
||||
else -> R.string.notification_type_general
|
||||
})
|
||||
@ -1034,5 +1118,130 @@ fun CharSequence.containsAll(list: List<CharSequence>, ignoreCase: Boolean = fal
|
||||
return true
|
||||
}
|
||||
|
||||
fun RadioButton.setOnSelectedListener(listener: (buttonView: CompoundButton) -> Unit)
|
||||
inline fun RadioButton.setOnSelectedListener(crossinline listener: (buttonView: CompoundButton) -> Unit)
|
||||
= setOnCheckedChangeListener { buttonView, isChecked -> if (isChecked) listener(buttonView) }
|
||||
|
||||
fun Response.toErrorCode() = when (this.code()) {
|
||||
400 -> ERROR_REQUEST_HTTP_400
|
||||
401 -> ERROR_REQUEST_HTTP_401
|
||||
403 -> ERROR_REQUEST_HTTP_403
|
||||
404 -> ERROR_REQUEST_HTTP_404
|
||||
405 -> ERROR_REQUEST_HTTP_405
|
||||
410 -> ERROR_REQUEST_HTTP_410
|
||||
424 -> ERROR_REQUEST_HTTP_424
|
||||
500 -> ERROR_REQUEST_HTTP_500
|
||||
503 -> ERROR_REQUEST_HTTP_503
|
||||
else -> null
|
||||
}
|
||||
fun Throwable.toErrorCode() = when (this) {
|
||||
is UnknownHostException -> ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND
|
||||
is SSLException -> ERROR_REQUEST_FAILURE_SSL_ERROR
|
||||
is SocketTimeoutException -> ERROR_REQUEST_FAILURE_TIMEOUT
|
||||
is InterruptedIOException, is ConnectException -> ERROR_REQUEST_FAILURE_NO_INTERNET
|
||||
is SzkolnyApiException -> this.error?.toErrorCode()
|
||||
else -> null
|
||||
}
|
||||
private fun ApiResponse.Error.toErrorCode() = when (this.code) {
|
||||
else -> ERROR_API_EXCEPTION
|
||||
}
|
||||
fun Throwable.toApiError(tag: String) = ApiError.fromThrowable(tag, this)
|
||||
|
||||
inline fun <A, B, R> ifNotNull(a: A?, b: B?, code: (A, B) -> R): R? {
|
||||
if (a != null && b != null) {
|
||||
return code(a, b)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmName("averageOrNullOfInt")
|
||||
fun Iterable<Int>.averageOrNull() = this.average().let { if (it.isNaN()) null else it }
|
||||
@kotlin.jvm.JvmName("averageOrNullOfFloat")
|
||||
fun Iterable<Float>.averageOrNull() = this.average().let { if (it.isNaN()) null else it }
|
||||
|
||||
fun String.copyToClipboard(context: Context) {
|
||||
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clipData = ClipData.newPlainText("Tekst", this)
|
||||
clipboard.primaryClip = clipData
|
||||
}
|
||||
|
||||
fun TextView.getTextPosition(range: IntRange): Rect {
|
||||
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
|
||||
// Initialize global value
|
||||
var parentTextViewRect = Rect()
|
||||
|
||||
// Initialize values for the computing of clickedText position
|
||||
//val completeText = parentTextView.text as SpannableString
|
||||
val textViewLayout = this.layout
|
||||
|
||||
val startOffsetOfClickedText = range.first//completeText.getSpanStart(clickedText)
|
||||
val endOffsetOfClickedText = range.last//completeText.getSpanEnd(clickedText)
|
||||
var startXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal(startOffsetOfClickedText)
|
||||
var endXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal(endOffsetOfClickedText)
|
||||
|
||||
// Get the rectangle of the clicked text
|
||||
val currentLineStartOffset = textViewLayout.getLineForOffset(startOffsetOfClickedText)
|
||||
val currentLineEndOffset = textViewLayout.getLineForOffset(endOffsetOfClickedText)
|
||||
val keywordIsInMultiLine = currentLineStartOffset != currentLineEndOffset
|
||||
textViewLayout.getLineBounds(currentLineStartOffset, parentTextViewRect)
|
||||
|
||||
// Update the rectangle position to his real position on screen
|
||||
val parentTextViewLocation = intArrayOf(0, 0)
|
||||
this.getLocationOnScreen(parentTextViewLocation)
|
||||
|
||||
val parentTextViewTopAndBottomOffset = (parentTextViewLocation[1] - this.scrollY + this.compoundPaddingTop)
|
||||
parentTextViewRect.top += parentTextViewTopAndBottomOffset
|
||||
parentTextViewRect.bottom += parentTextViewTopAndBottomOffset
|
||||
|
||||
// In the case of multi line text, we have to choose what rectangle take
|
||||
if (keywordIsInMultiLine) {
|
||||
val screenHeight = windowManager.defaultDisplay.height
|
||||
val dyTop = parentTextViewRect.top
|
||||
val dyBottom = screenHeight - parentTextViewRect.bottom
|
||||
val onTop = dyTop > dyBottom
|
||||
|
||||
if (onTop) {
|
||||
endXCoordinatesOfClickedText = textViewLayout.getLineRight(currentLineStartOffset);
|
||||
} else {
|
||||
parentTextViewRect = Rect()
|
||||
textViewLayout.getLineBounds(currentLineEndOffset, parentTextViewRect);
|
||||
parentTextViewRect.top += parentTextViewTopAndBottomOffset;
|
||||
parentTextViewRect.bottom += parentTextViewTopAndBottomOffset;
|
||||
startXCoordinatesOfClickedText = textViewLayout.getLineLeft(currentLineEndOffset);
|
||||
}
|
||||
}
|
||||
|
||||
parentTextViewRect.left += (
|
||||
parentTextViewLocation[0] +
|
||||
startXCoordinatesOfClickedText +
|
||||
this.compoundPaddingLeft -
|
||||
this.scrollX
|
||||
).toInt()
|
||||
parentTextViewRect.right = (
|
||||
parentTextViewRect.left +
|
||||
endXCoordinatesOfClickedText -
|
||||
startXCoordinatesOfClickedText
|
||||
).toInt()
|
||||
|
||||
return parentTextViewRect
|
||||
}
|
||||
|
||||
inline fun ViewPager.addOnPageSelectedListener(crossinline block: (position: Int) -> Unit) = addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
override fun onPageSelected(position: Int) { block(position) }
|
||||
})
|
||||
|
||||
val SwipeRefreshLayout.onScrollListener: RecyclerView.OnScrollListener
|
||||
get() = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
if (recyclerView.canScrollVertically(-1))
|
||||
this@onScrollListener.isEnabled = false
|
||||
if (!recyclerView.canScrollVertically(-1) && newState == RecyclerView.SCROLL_STATE_IDLE)
|
||||
this@onScrollListener.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
operator fun <K, V> Iterable<Pair<K, V>>.get(key: K): V? {
|
||||
return firstOrNull { it.first == key }?.second
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
@ -21,7 +20,6 @@ import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.danimahardhika.cafebar.CafeBar
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.mikepenz.iconics.IconicsColor
|
||||
@ -32,8 +30,8 @@ import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
|
||||
import com.mikepenz.materialdrawer.model.DividerDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile
|
||||
import com.mikepenz.materialdrawer.model.interfaces.*
|
||||
import com.mikepenz.materialdrawer.model.utils.withIsHiddenInMiniDrawer
|
||||
import kotlinx.coroutines.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -42,7 +40,6 @@ import pl.droidsonroids.gif.GifDrawable
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.data.api.events.*
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata.*
|
||||
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
||||
@ -51,27 +48,28 @@ import pl.szczodrzynski.edziennik.sync.SyncWorker
|
||||
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.ServerMessageDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.sync.SyncViewListDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.MainSnackbar
|
||||
import pl.szczodrzynski.edziennik.ui.modules.behaviour.BehaviourFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.DebugFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.LabFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
|
||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesListFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessageFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesListFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.compose.MessagesComposeFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsListFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
|
||||
@ -91,7 +89,6 @@ import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
|
||||
import pl.szczodrzynski.navlib.drawer.NavDrawer
|
||||
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
|
||||
import pl.szczodrzynski.navlib.drawer.items.withAppTitle
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
@ -131,6 +128,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
const val TARGET_MESSAGES_DETAILS = 503
|
||||
const val TARGET_MESSAGES_COMPOSE = 504
|
||||
const val TARGET_WEB_PUSH = 140
|
||||
const val TARGET_LAB = 1000
|
||||
|
||||
const val HOME_ID = DRAWER_ITEM_HOME
|
||||
|
||||
@ -155,7 +153,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.withBadgeTypeId(TYPE_EVENT)
|
||||
.isInDrawer(true)
|
||||
|
||||
list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesListFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline)
|
||||
.withBadgeTypeId(TYPE_GRADE)
|
||||
.isInDrawer(true)
|
||||
@ -187,7 +185,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
|
||||
// static drawer items
|
||||
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsListFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_bell_ring_outline)
|
||||
.isInDrawer(true)
|
||||
.isStatic(true)
|
||||
@ -228,7 +226,14 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES)
|
||||
list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class)
|
||||
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||
if (App.debugMode) {
|
||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||
list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_flask_outline)
|
||||
.isInDrawer(true)
|
||||
.isBelowSeparator(true)
|
||||
.isStatic(true)
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
@ -286,8 +291,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
setContentView(b.root)
|
||||
|
||||
Log.d(TAG, Signing.appPassword)
|
||||
|
||||
mainSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar)
|
||||
errorSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar)
|
||||
|
||||
@ -364,7 +367,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
false
|
||||
}
|
||||
drawerProfileLongClickListener = { _, profile, _, view ->
|
||||
if (profile is ProfileDrawerItem) {
|
||||
if (view != null && profile is ProfileDrawerItem) {
|
||||
showProfileContextMenu(profile, view)
|
||||
true
|
||||
}
|
||||
@ -411,8 +414,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
R.color.md_green_500
|
||||
)
|
||||
|
||||
isStoragePermissionGranted()
|
||||
|
||||
SyncWorker.scheduleNext(app)
|
||||
UpdateWorker.scheduleNext(app)
|
||||
|
||||
@ -448,6 +449,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
// WHAT'S NEW DIALOG
|
||||
if (app.config.appVersion < BuildConfig.VERSION_CODE) {
|
||||
// force an AppSync after update
|
||||
app.config.sync.lastAppSync = 0L
|
||||
ChangelogDialog(this)
|
||||
if (app.config.appVersion < 170) {
|
||||
//Intent intent = new Intent(this, ChangelogIntroActivity.class);
|
||||
@ -511,7 +514,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline)
|
||||
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
||||
)
|
||||
if (App.devMode) {
|
||||
if (App.debugMode) {
|
||||
bottomSheet += BottomSheetPrimaryItem(false)
|
||||
.withTitle(R.string.menu_debug)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_android_studio)
|
||||
@ -567,7 +570,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
EdziennikTask.syncProfile(
|
||||
App.profileId,
|
||||
listOf(navTargetId to fragmentParam),
|
||||
arguments
|
||||
arguments = arguments
|
||||
).enqueue(this)
|
||||
}
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
@ -659,6 +662,10 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onUserActionRequiredEvent(event: UserActionRequiredEvent) {
|
||||
app.userActionManager.execute(this, event.profileId, event.type)
|
||||
}
|
||||
|
||||
private fun fragmentToSyncName(currentFragment: Int): Int {
|
||||
return when (currentFragment) {
|
||||
@ -713,10 +720,28 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
intentTargetId = TARGET_FEEDBACK
|
||||
false
|
||||
}
|
||||
"userActionRequired" -> {
|
||||
app.userActionManager.execute(
|
||||
this,
|
||||
extras.getInt("profileId"),
|
||||
extras.getInt("type")
|
||||
)
|
||||
true
|
||||
}
|
||||
"createManualEvent" -> {
|
||||
val date = extras.getString("eventDate")?.let { Date.fromY_m_d(it) } ?: Date.getToday()
|
||||
EventManualDialog(
|
||||
this,
|
||||
App.profileId,
|
||||
defaultDate = date
|
||||
)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
if (handled)
|
||||
if (handled && !navLoading) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (extras?.containsKey("reloadProfileId") == true) {
|
||||
@ -860,9 +885,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
app.profileLoad(id) {
|
||||
MessagesFragment.pageSelection = -1
|
||||
MessagesListFragment.tapPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
||||
MessagesListFragment.topPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
||||
MessagesListFragment.bottomPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
||||
|
||||
setDrawerItems()
|
||||
// the drawer profile is updated automatically when the drawer item is clicked
|
||||
@ -887,15 +909,16 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
loadTarget(target, arguments)
|
||||
}
|
||||
}
|
||||
private fun loadTarget(target: NavTarget, arguments: Bundle? = null) {
|
||||
d("NavDebug", "loadTarget(target = $target, arguments = $arguments)")
|
||||
private fun loadTarget(target: NavTarget, args: Bundle? = null) {
|
||||
d("NavDebug", "loadTarget(target = $target, args = $args)")
|
||||
|
||||
val arguments = args ?: navBackStack.firstOrNull { it.first.id == target.id }?.second ?: Bundle()
|
||||
bottomSheet.close()
|
||||
bottomSheet.removeAllContextual()
|
||||
bottomSheet.toggleGroupEnabled = false
|
||||
bottomSheet.onCloseListener = null
|
||||
drawer.close()
|
||||
drawer.setSelection(target.id, fireOnClick = false)
|
||||
if (drawer.getSelection() != target.id)
|
||||
drawer.setSelection(target.id, fireOnClick = false)
|
||||
navView.toolbar.setTitle(target.title ?: target.name)
|
||||
navView.bottomBar.fabEnable = false
|
||||
navView.bottomBar.fabExtended = false
|
||||
@ -937,6 +960,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
navBackStack.removeAt(navBackStack.lastIndex)
|
||||
}
|
||||
navTarget = target
|
||||
navArguments = arguments
|
||||
|
||||
return@let null
|
||||
}?.let {
|
||||
@ -946,7 +970,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
R.anim.task_open_enter,
|
||||
R.anim.task_open_exit
|
||||
)
|
||||
navBackStack.add(navTarget to arguments)
|
||||
navBackStack.add(navTarget to navArguments)
|
||||
navTarget = target
|
||||
navArguments = arguments
|
||||
}
|
||||
@ -1043,11 +1067,12 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
val item = DrawerPrimaryItem()
|
||||
.withIdentifier(target.id.toLong())
|
||||
.withName(target.name)
|
||||
.withHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id))
|
||||
.withIsHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id))
|
||||
.also { if (target.description != null) it.withDescription(target.description!!) }
|
||||
.also { if (target.icon != null) it.withIcon(target.icon!!) }
|
||||
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
|
||||
.also { if (target.badgeTypeId != null) it.withBadgeStyle(drawer.badgeStyle)}
|
||||
.withSelectedBackgroundAnimated(false)
|
||||
|
||||
if (target.badgeTypeId != null)
|
||||
drawer.addUnreadCounterType(target.badgeTypeId!!, target.id)
|
||||
@ -1107,7 +1132,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
drawer.addProfileSettings(*drawerProfiles.toTypedArray())
|
||||
}
|
||||
|
||||
private fun showProfileContextMenu(profile: IProfile<*>, view: View) {
|
||||
private fun showProfileContextMenu(profile: IProfile, view: View) {
|
||||
val profileId = profile.identifier.toInt()
|
||||
val popupMenu = PopupMenu(this, view)
|
||||
popupMenu.menu.add(0, 1, 1, R.string.profile_menu_open_settings)
|
||||
@ -1120,7 +1145,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
loadTarget(DRAWER_ITEM_SETTINGS, null)
|
||||
} else if (item.itemId == 2) {
|
||||
ProfileRemoveDialog(this, profileId, profile.name?.getText(this)?.toString() ?: "?")
|
||||
ProfileRemoveDialog(this, profileId, profile.name?.getText(this) ?: "?")
|
||||
}
|
||||
true
|
||||
}
|
||||
@ -1131,7 +1156,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
private var targetHomeId: Int = -1
|
||||
override fun onBackPressed() {
|
||||
if (!b.navView.onBackPressed()) {
|
||||
if (App.config.ui.openDrawerOnBackPressed) {
|
||||
if (App.config.ui.openDrawerOnBackPressed && ((navTarget.popTo == null && navTarget.popToHome)
|
||||
|| navTarget.id == DRAWER_ITEM_HOME)) {
|
||||
b.navView.drawer.toggle()
|
||||
} else {
|
||||
navigateUp()
|
||||
|
@ -22,7 +22,7 @@ import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
||||
companion object {
|
||||
const val DATA_VERSION = 10
|
||||
const val DATA_VERSION = 12
|
||||
}
|
||||
|
||||
private val job = Job()
|
||||
@ -75,6 +75,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
||||
get() { mPrivacyPolicyAccepted = mPrivacyPolicyAccepted ?: values.get("privacyPolicyAccepted", false); return mPrivacyPolicyAccepted ?: false }
|
||||
set(value) { set("privacyPolicyAccepted", value); mPrivacyPolicyAccepted = value }
|
||||
|
||||
private var mDebugMode: Boolean? = null
|
||||
var debugMode: Boolean
|
||||
get() { mDebugMode = mDebugMode ?: values.get("debugMode", false); return mDebugMode ?: false }
|
||||
set(value) { set("debugMode", value); mDebugMode = value }
|
||||
|
||||
private var mDevModePassword: String? = null
|
||||
var devModePassword: String?
|
||||
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }
|
||||
@ -125,4 +130,4 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
||||
db.configDao().add(ConfigEntry(-1, key, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,17 +6,11 @@ package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import pl.szczodrzynski.edziennik.config.utils.get
|
||||
import pl.szczodrzynski.edziennik.config.utils.set
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
|
||||
|
||||
class ConfigGrades(private val config: Config) {
|
||||
companion object {
|
||||
const val ORDER_BY_DATE_DESC = 0
|
||||
const val ORDER_BY_SUBJECT_ASC = 1
|
||||
const val ORDER_BY_DATE_ASC = 2
|
||||
const val ORDER_BY_SUBJECT_DESC = 3
|
||||
}
|
||||
|
||||
private var mOrderBy: Int? = null
|
||||
var orderBy: Int
|
||||
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: ORDER_BY_DATE_DESC }
|
||||
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: GradesManager.ORDER_BY_DATE_DESC }
|
||||
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.config
|
||||
import pl.szczodrzynski.edziennik.config.utils.get
|
||||
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
||||
import pl.szczodrzynski.edziennik.config.utils.set
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class ConfigSync(private val config: Config) {
|
||||
private var mDontShowAppManagerDialog: Boolean? = null
|
||||
@ -19,6 +20,11 @@ class ConfigSync(private val config: Config) {
|
||||
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
||||
set(value) { config.set("syncEnabled", value); mSyncEnabled = value }
|
||||
|
||||
private var mWebPushEnabled: Boolean? = null
|
||||
var webPushEnabled: Boolean
|
||||
get() { mWebPushEnabled = mWebPushEnabled ?: config.values.get("webPushEnabled", true); return mWebPushEnabled ?: true }
|
||||
set(value) { config.set("webPushEnabled", value); mWebPushEnabled = value }
|
||||
|
||||
private var mSyncOnlyWifi: Boolean? = null
|
||||
var onlyWifi: Boolean
|
||||
get() { mSyncOnlyWifi = mSyncOnlyWifi ?: config.values.get("syncOnlyWifi", false); return mSyncOnlyWifi ?: notifyAboutUpdates }
|
||||
@ -34,20 +40,30 @@ class ConfigSync(private val config: Config) {
|
||||
get() { mNotifyAboutUpdates = mNotifyAboutUpdates ?: config.values.get("notifyAboutUpdates", true); return mNotifyAboutUpdates ?: true }
|
||||
set(value) { config.set("notifyAboutUpdates", value); mNotifyAboutUpdates = value }
|
||||
|
||||
private var mLastAppSync: Long? = null
|
||||
var lastAppSync: Long
|
||||
get() { mLastAppSync = mLastAppSync ?: config.values.get("lastAppSync", 0L); return mLastAppSync ?: 0L }
|
||||
set(value) { config.set("lastAppSync", value); mLastAppSync = value }
|
||||
|
||||
/* ____ _ _ _
|
||||
/ __ \ (_) | | | |
|
||||
| | | |_ _ _ ___| |_ | |__ ___ _ _ _ __ ___
|
||||
| | | | | | | |/ _ \ __| | '_ \ / _ \| | | | '__/ __|
|
||||
| |__| | |_| | | __/ |_ | | | | (_) | |_| | | \__ \
|
||||
\___\_\\__,_|_|\___|\__| |_| |_|\___/ \__,_|_| |__*/
|
||||
private var mQuietHoursStart: Long? = null
|
||||
var quietHoursStart: Long
|
||||
get() { mQuietHoursStart = mQuietHoursStart ?: config.values.get("quietHoursStart", 0L); return mQuietHoursStart ?: 0L }
|
||||
private var mQuietHoursEnabled: Boolean? = null
|
||||
var quietHoursEnabled: Boolean
|
||||
get() { mQuietHoursEnabled = mQuietHoursEnabled ?: config.values.get("quietHoursEnabled", false); return mQuietHoursEnabled ?: false }
|
||||
set(value) { config.set("quietHoursEnabled", value); mQuietHoursEnabled = value }
|
||||
|
||||
private var mQuietHoursStart: Time? = null
|
||||
var quietHoursStart: Time?
|
||||
get() { mQuietHoursStart = mQuietHoursStart ?: config.values.get("quietHoursStart", null as Time?); return mQuietHoursStart }
|
||||
set(value) { config.set("quietHoursStart", value); mQuietHoursStart = value }
|
||||
|
||||
private var mQuietHoursEnd: Long? = null
|
||||
var quietHoursEnd: Long
|
||||
get() { mQuietHoursEnd = mQuietHoursEnd ?: config.values.get("quietHoursEnd", 0L); return mQuietHoursEnd ?: 0L }
|
||||
private var mQuietHoursEnd: Time? = null
|
||||
var quietHoursEnd: Time?
|
||||
get() { mQuietHoursEnd = mQuietHoursEnd ?: config.values.get("quietHoursEnd", null as Time?); return mQuietHoursEnd }
|
||||
set(value) { config.set("quietHoursEnd", value); mQuietHoursEnd = value }
|
||||
|
||||
private var mQuietDuringLessons: Boolean? = null
|
||||
@ -90,4 +106,4 @@ class ConfigSync(private val config: Config) {
|
||||
var tokenVulcanList: List<Int>
|
||||
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
|
||||
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.config
|
||||
import pl.szczodrzynski.edziennik.config.utils.get
|
||||
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
||||
import pl.szczodrzynski.edziennik.config.utils.set
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel
|
||||
|
||||
class ConfigUI(private val config: Config) {
|
||||
private var mTheme: Int? = null
|
||||
@ -45,11 +44,6 @@ class ConfigUI(private val config: Config) {
|
||||
get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false }
|
||||
set(value) { config.set("openDrawerOnBackPressed", value); mOpenDrawerOnBackPressed = value }
|
||||
|
||||
private var mHomeCards: List<HomeCardModel>? = null
|
||||
var homeCards: List<HomeCardModel>
|
||||
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
|
||||
set(value) { config.set("homeCards", value); mHomeCards = value }
|
||||
|
||||
private var mSnowfall: Boolean? = null
|
||||
var snowfall: Boolean
|
||||
get() { mSnowfall = mSnowfall ?: config.values.get("snowfall", false); return mSnowfall ?: false }
|
||||
|
@ -18,7 +18,7 @@ import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEntry>) : CoroutineScope, AbstractConfig {
|
||||
companion object {
|
||||
const val DATA_VERSION = 1
|
||||
const val DATA_VERSION = 2
|
||||
}
|
||||
|
||||
private val job = Job()
|
||||
@ -29,8 +29,8 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
|
||||
|
||||
val grades by lazy { ProfileConfigGrades(this) }
|
||||
val ui by lazy { ProfileConfigUI(this) }
|
||||
val sync by lazy { ProfileConfigSync(this) }
|
||||
/*
|
||||
val sync by lazy { ConfigSync(this) }
|
||||
val timetable by lazy { ConfigTimetable(this) }
|
||||
val grades by lazy { ConfigGrades(this) }*/
|
||||
|
||||
@ -56,4 +56,4 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
|
||||
db.configDao().add(ConfigEntry(profileId, key, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,10 @@
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import pl.szczodrzynski.edziennik.config.utils.get
|
||||
import pl.szczodrzynski.edziennik.config.utils.getFloat
|
||||
import pl.szczodrzynski.edziennik.config.utils.set
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.COLOR_MODE_WEIGHTED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.YEAR_ALL_GRADES
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
|
||||
|
||||
class ProfileConfigGrades(private val config: ProfileConfig) {
|
||||
private var mColorMode: Int? = null
|
||||
@ -20,8 +21,32 @@ class ProfileConfigGrades(private val config: ProfileConfig) {
|
||||
get() { mYearAverageMode = mYearAverageMode ?: config.values.get("yearAverageMode", YEAR_ALL_GRADES); return mYearAverageMode ?: YEAR_ALL_GRADES }
|
||||
set(value) { config.set("yearAverageMode", value); mYearAverageMode = value }
|
||||
|
||||
private var mCountZeroToAvg: Boolean? = null
|
||||
var countZeroToAvg: Boolean
|
||||
get() { mCountZeroToAvg = mCountZeroToAvg ?: config.values.get("countZeroToAvg", true); return mCountZeroToAvg ?: true }
|
||||
set(value) { config.set("countZeroToAvg", value); mCountZeroToAvg = value }
|
||||
private var mHideImproved: Boolean? = null
|
||||
var hideImproved: Boolean
|
||||
get() { mHideImproved = mHideImproved ?: config.values.get("hideImproved", false); return mHideImproved ?: false }
|
||||
set(value) { config.set("hideImproved", value); mHideImproved = value }
|
||||
|
||||
private var mAverageWithoutWeight: Boolean? = null
|
||||
var averageWithoutWeight: Boolean
|
||||
get() { mAverageWithoutWeight = mAverageWithoutWeight ?: config.values.get("averageWithoutWeight", true); return mAverageWithoutWeight ?: true }
|
||||
set(value) { config.set("averageWithoutWeight", value); mAverageWithoutWeight = value }
|
||||
|
||||
private var mPlusValue: Float? = null
|
||||
var plusValue: Float?
|
||||
get() { mPlusValue = mPlusValue ?: config.values.getFloat("plusValue"); return mPlusValue }
|
||||
set(value) { config.set("plusValue", value); mPlusValue = value }
|
||||
private var mMinusValue: Float? = null
|
||||
var minusValue: Float?
|
||||
get() { mMinusValue = mMinusValue ?: config.values.getFloat("minusValue"); return mMinusValue }
|
||||
set(value) { config.set("minusValue", value); mMinusValue = value }
|
||||
|
||||
private var mDontCountEnabled: Boolean? = null
|
||||
var dontCountEnabled: Boolean
|
||||
get() { mDontCountEnabled = mDontCountEnabled ?: config.values.get("dontCountEnabled", false); return mDontCountEnabled ?: false }
|
||||
set(value) { config.set("dontCountEnabled", value); mDontCountEnabled = value }
|
||||
|
||||
private var mDontCountGrades: List<String>? = null
|
||||
var dontCountGrades: List<String>
|
||||
get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() }
|
||||
set(value) { config.set("dontCountGrades", value); mDontCountGrades = value }
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-2-21.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import pl.szczodrzynski.edziennik.config.utils.get
|
||||
import pl.szczodrzynski.edziennik.config.utils.set
|
||||
|
||||
class ProfileConfigSync(private val config: ProfileConfig) {
|
||||
private var mNotificationFilter: List<Int>? = null
|
||||
var notificationFilter: List<Int>
|
||||
get() { mNotificationFilter = mNotificationFilter ?: config.values.get("notificationFilter", listOf()); return mNotificationFilter ?: listOf() }
|
||||
set(value) { config.set("notificationFilter", value); mNotificationFilter = value }
|
||||
}
|
@ -7,10 +7,16 @@ package pl.szczodrzynski.edziennik.config
|
||||
import pl.szczodrzynski.edziennik.config.utils.get
|
||||
import pl.szczodrzynski.edziennik.config.utils.set
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel
|
||||
|
||||
class ProfileConfigUI(private val config: ProfileConfig) {
|
||||
private var mAgendaViewType: Int? = null
|
||||
var agendaViewType: Int
|
||||
get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: AGENDA_DEFAULT }
|
||||
set(value) { config.set("agendaViewType", value); mAgendaViewType = value }
|
||||
|
||||
private var mHomeCards: List<HomeCardModel>? = null
|
||||
var homeCards: List<HomeCardModel>
|
||||
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
|
||||
set(value) { config.set("homeCards", value); mHomeCards = value }
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_VULCAN
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.math.abs
|
||||
|
||||
class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
|
||||
init { config.apply {
|
||||
@ -42,9 +43,7 @@ class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
|
||||
devModePassword = p.getString("$s.devModePassword", null).fix()
|
||||
sync.tokenApp = p.getString("$s.fcmToken", null).fix()
|
||||
timetable.bellSyncMultiplier = p.getString("$s.bellSyncMultiplier", null)?.toIntOrNull() ?: 0
|
||||
sync.quietHoursStart = p.getString("$s.quietHoursStart", null)?.toLongOrNull() ?: 0
|
||||
appRateSnackbarTime = p.getString("$s.appRateSnackbarTime", null)?.toLongOrNull() ?: 0
|
||||
sync.quietHoursEnd = p.getString("$s.quietHoursEnd", null)?.toLongOrNull() ?: 0
|
||||
timetable.countInSeconds = p.getString("$s.countInSeconds", null)?.toBoolean() ?: false
|
||||
ui.headerBackground = p.getString("$s.headerBackground", null).fix()
|
||||
ui.appBackground = p.getString("$s.appBackground", null).fix()
|
||||
@ -59,6 +58,22 @@ class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
|
||||
sync.notifyAboutUpdates = p.getString("$s.notifyAboutUpdates", null)?.toBoolean() ?: true
|
||||
timetable.bellSyncDiff = p.getString("$s.bellSyncDiff", null)?.let { Gson().fromJson(it, Time::class.java) }
|
||||
|
||||
val startMillis = p.getString("$s.quietHoursStart", null)?.toLongOrNull() ?: 0
|
||||
val endMillis = p.getString("$s.quietHoursEnd", null)?.toLongOrNull() ?: 0
|
||||
if (startMillis > 0) {
|
||||
try {
|
||||
sync.quietHoursStart = Time.fromMillis(abs(startMillis))
|
||||
sync.quietHoursEnd = Time.fromMillis(abs(endMillis))
|
||||
sync.quietHoursEnabled = true
|
||||
}
|
||||
catch (_: Exception) {}
|
||||
}
|
||||
else {
|
||||
sync.quietHoursEnabled = false
|
||||
sync.quietHoursStart = null
|
||||
sync.quietHoursEnd = null
|
||||
}
|
||||
|
||||
sync.tokenMobidziennikList = listOf()
|
||||
sync.tokenVulcanList = listOf()
|
||||
sync.tokenLibrusList = listOf()
|
||||
@ -78,4 +93,4 @@ class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
|
||||
private fun String?.fix(): String? {
|
||||
return this?.replace("\"", "")?.let { if (it == "null") null else it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,10 +94,14 @@ fun HashMap<String, String?>.getLongList(key: String, default: List<Long>?): Lis
|
||||
return this[key]?.let { gson.fromJson<List<Long>>(it, object: TypeToken<List<Long>>(){}.type) } ?: default
|
||||
}
|
||||
|
||||
fun HashMap<String, String?>.getFloat(key: String): Float? {
|
||||
return this[key]?.toFloatOrNull()
|
||||
}
|
||||
|
||||
fun List<ConfigEntry>.toHashMap(profileId: Int, map: HashMap<String, String?>) {
|
||||
map.clear()
|
||||
forEach {
|
||||
if (it.profileId == profileId)
|
||||
map[it.key] = it.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,9 @@ import pl.szczodrzynski.edziennik.BuildConfig
|
||||
import pl.szczodrzynski.edziennik.HOUR
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.config.Config
|
||||
import pl.szczodrzynski.edziennik.config.ConfigGrades.Companion.ORDER_BY_DATE_DESC
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.math.abs
|
||||
|
||||
class ConfigMigration(app: App, config: Config) {
|
||||
init { config.apply {
|
||||
@ -43,8 +45,9 @@ class ConfigMigration(app: App, config: Config) {
|
||||
sync.interval = 1*HOUR.toInt()
|
||||
sync.notifyAboutUpdates = true
|
||||
sync.onlyWifi = false
|
||||
sync.quietHoursStart = 0
|
||||
sync.quietHoursEnd = 0
|
||||
sync.quietHoursEnabled = false
|
||||
sync.quietHoursStart = null
|
||||
sync.quietHoursEnd = null
|
||||
sync.quietDuringLessons = false
|
||||
sync.tokenApp = null
|
||||
sync.tokenMobidziennik = null
|
||||
@ -61,14 +64,47 @@ class ConfigMigration(app: App, config: Config) {
|
||||
dataVersion = 2
|
||||
}
|
||||
|
||||
if (dataVersion < 3) {
|
||||
update = null
|
||||
privacyPolicyAccepted = false
|
||||
debugMode = false
|
||||
devModePassword = null
|
||||
appInstalledTime = 0L
|
||||
appRateSnackbarTime = 0L
|
||||
|
||||
dataVersion = 3
|
||||
}
|
||||
|
||||
if (dataVersion < 10) {
|
||||
ui.openDrawerOnBackPressed = false
|
||||
ui.homeCards = listOf()
|
||||
ui.snowfall = false
|
||||
ui.bottomSheetOpened = false
|
||||
sync.dontShowAppManagerDialog = false
|
||||
sync.webPushEnabled = true
|
||||
sync.lastAppSync = 0L
|
||||
|
||||
|
||||
dataVersion = 10
|
||||
}
|
||||
|
||||
if (dataVersion < 11) {
|
||||
val startMillis = config.values.get("quietHoursStart", 0L)
|
||||
val endMillis = config.values.get("quietHoursEnd", 0L)
|
||||
if (startMillis > 0) {
|
||||
try {
|
||||
sync.quietHoursStart = Time.fromMillis(abs(startMillis))
|
||||
sync.quietHoursEnd = Time.fromMillis(abs(endMillis))
|
||||
sync.quietHoursEnabled = true
|
||||
}
|
||||
catch (_: Exception) {}
|
||||
}
|
||||
else {
|
||||
sync.quietHoursEnabled = false
|
||||
sync.quietHoursStart = null
|
||||
sync.quietHoursEnd = null
|
||||
}
|
||||
|
||||
dataVersion = 11
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -5,20 +5,33 @@
|
||||
package pl.szczodrzynski.edziennik.config.utils
|
||||
|
||||
import pl.szczodrzynski.edziennik.config.ProfileConfig
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.COLOR_MODE_WEIGHTED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.YEAR_ALL_GRADES
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
|
||||
|
||||
class ProfileConfigMigration(config: ProfileConfig) {
|
||||
init { config.apply {
|
||||
|
||||
if (dataVersion < 1) {
|
||||
grades.colorMode = COLOR_MODE_WEIGHTED
|
||||
grades.countZeroToAvg = true
|
||||
grades.yearAverageMode = YEAR_ALL_GRADES
|
||||
grades.hideImproved = false
|
||||
grades.averageWithoutWeight = true
|
||||
grades.plusValue = null
|
||||
grades.minusValue = null
|
||||
grades.dontCountEnabled = false
|
||||
grades.dontCountGrades = listOf()
|
||||
ui.agendaViewType = AGENDA_DEFAULT
|
||||
// no migration for ui.homeCards
|
||||
|
||||
dataVersion = 1
|
||||
}
|
||||
|
||||
if (dataVersion < 2) {
|
||||
sync.notificationFilter = sync.notificationFilter + Notification.TYPE_TEACHER_ABSENCE
|
||||
|
||||
dataVersion = 2
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import pl.szczodrzynski.edziennik.data.api.task.ErrorReportTask
|
||||
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
|
||||
import pl.szczodrzynski.edziennik.data.api.task.SzkolnyTask
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.toApiError
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
@ -37,6 +38,9 @@ class ApiService : Service() {
|
||||
context.startService(Intent(context, ApiService::class.java))
|
||||
EventBus.getDefault().postSticky(request)
|
||||
}
|
||||
|
||||
var lastEventTime = System.currentTimeMillis()
|
||||
var taskCancelTries = 0
|
||||
}
|
||||
|
||||
private val app by lazy { applicationContext as App }
|
||||
@ -54,6 +58,7 @@ class ApiService : Service() {
|
||||
private var taskIsRunning = false
|
||||
private var taskRunning: IApiTask? = null // for debug purposes
|
||||
private var taskRunningId = -1
|
||||
private var taskStartTime = 0L
|
||||
private var taskMaximumId = 0
|
||||
|
||||
private var taskProfileId = -1
|
||||
@ -62,9 +67,6 @@ class ApiService : Service() {
|
||||
|
||||
private val notification by lazy { EdziennikNotification(app) }
|
||||
|
||||
private var lastEventTime = System.currentTimeMillis()
|
||||
private var taskCancelTries = 0
|
||||
|
||||
/* ______ _ _ _ _ _____ _ _ _ _
|
||||
| ____| | | (_) (_) | / ____| | | | | | |
|
||||
| |__ __| |_____ ___ _ __ _ __ _| | __ | | __ _| | | |__ __ _ ___| | __
|
||||
@ -74,7 +76,7 @@ class ApiService : Service() {
|
||||
private val taskCallback = object : EdziennikCallback {
|
||||
override fun onCompleted() {
|
||||
lastEventTime = System.currentTimeMillis()
|
||||
d(TAG, "Task $taskRunningId (profile $taskProfileId) - $taskProgressText - finished")
|
||||
d(TAG, "Task $taskRunningId (profile $taskProfileId) finished in ${System.currentTimeMillis()-taskStartTime}")
|
||||
EventBus.getDefault().postSticky(ApiTaskFinishedEvent(taskProfileId))
|
||||
clearTask()
|
||||
|
||||
@ -86,9 +88,16 @@ class ApiService : Service() {
|
||||
lastEventTime = System.currentTimeMillis()
|
||||
d(TAG, "Task $taskRunningId threw an error - $apiError")
|
||||
apiError.profileId = taskProfileId
|
||||
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
|
||||
errorList.add(apiError)
|
||||
apiError.throwable?.printStackTrace()
|
||||
|
||||
if (app.userActionManager.requiresUserAction(apiError)) {
|
||||
app.userActionManager.sendToUser(apiError)
|
||||
}
|
||||
else {
|
||||
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
|
||||
errorList.add(apiError)
|
||||
apiError.throwable?.printStackTrace()
|
||||
}
|
||||
|
||||
if (apiError.isCritical) {
|
||||
taskRunning?.cancel()
|
||||
notification.setCriticalError().post()
|
||||
@ -155,7 +164,7 @@ class ApiService : Service() {
|
||||
taskProgress = -1f
|
||||
taskProgressText = task.taskName
|
||||
|
||||
d(TAG, "Executing task $taskRunningId ($taskProgressText) - $task")
|
||||
d(TAG, "Executing task $taskRunningId - ${task::class.java.name}")
|
||||
|
||||
// update the notification
|
||||
notification.setCurrentTask(taskRunningId, taskProgressText).post()
|
||||
@ -165,6 +174,7 @@ class ApiService : Service() {
|
||||
|
||||
task.profile?.let { syncingProfiles.add(it) }
|
||||
|
||||
taskStartTime = System.currentTimeMillis()
|
||||
try {
|
||||
when (task) {
|
||||
is EdziennikTask -> task.run(app, taskCallback)
|
||||
@ -172,7 +182,7 @@ class ApiService : Service() {
|
||||
is SzkolnyTask -> task.run(taskCallback)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
taskCallback.onError(ApiError(TAG, EXCEPTION_API_TASK).withThrowable(e))
|
||||
taskCallback.onError(e.toApiError(TAG))
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,7 +311,7 @@ class ApiService : Service() {
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
d(TAG, "Foreground service onStartCommand")
|
||||
startForeground(app.notifications.syncId, notification.notification)
|
||||
startForeground(app.notificationChannelsManager.sync.id, notification.notification)
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,9 @@ const val FAKE_LIBRUS_TOKEN = "https://librus.szkolny.eu/access_token.php"
|
||||
const val FAKE_LIBRUS_ACCOUNT = "/synergia_accounts_fresh.php?login="
|
||||
const val FAKE_LIBRUS_ACCOUNTS = "/synergia_accounts.php"
|
||||
|
||||
val LIBRUS_USER_AGENT = "$SYSTEM_USER_AGENT LibrusMobileApp"
|
||||
val LIBRUS_USER_AGENT = "${SYSTEM_USER_AGENT}LibrusMobileApp"
|
||||
const val SYNERGIA_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/62.0"
|
||||
const val LIBRUS_CLIENT_ID = "wmSyUMo8llDAs4y9tJVYY92oyZ6h4lAt7KCuy0Gv"
|
||||
const val LIBRUS_CLIENT_ID = "6XPsKf10LPz1nxgHQLcvZ1KM48DYzlBAhxipaXY8"
|
||||
const val LIBRUS_REDIRECT_URL = "http://localhost/bar"
|
||||
const val LIBRUS_AUTHORIZE_URL = "https://portal.librus.pl/oauth2/authorize?client_id=$LIBRUS_CLIENT_ID&redirect_uri=$LIBRUS_REDIRECT_URL&response_type=code"
|
||||
const val LIBRUS_LOGIN_URL = "https://portal.librus.pl/rodzina/login/action"
|
||||
@ -56,10 +56,13 @@ const val LIBRUS_SYNERGIA_TOKEN_LOGIN_URL = "https://synergia.librus.pl/loguj/to
|
||||
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_SYNERGIA_HOMEWORK_ATTACHMENT_URL = "https://synergia.librus.pl/homework/downloadFile"
|
||||
|
||||
const val IDZIENNIK_USER_AGENT = SYNERGIA_USER_AGENT
|
||||
const val IDZIENNIK_WEB_URL = "https://iuczniowie.progman.pl/idziennik"
|
||||
const val IDZIENNIK_WEB_LOGIN = "login.aspx"
|
||||
const val IDZIENNIK_WEB_SETTINGS = "mod_panelRodzica/Ustawienia.aspx"
|
||||
const val IDZIENNIK_WEB_HOME = "mod_panelRodzica/StronaGlowna.aspx"
|
||||
const val IDZIENNIK_WEB_TIMETABLE = "mod_panelRodzica/plan/WS_Plan.asmx/pobierzPlanZajec"
|
||||
const val IDZIENNIK_WEB_GRADES = "mod_panelRodzica/oceny/WS_ocenyUcznia.asmx/pobierzOcenyUcznia"
|
||||
const val IDZIENNIK_WEB_MISSING_GRADES = "mod_panelRodzica/brak_ocen/WS_BrakOcenUcznia.asmx/pobierzBrakujaceOcenyUcznia"
|
||||
@ -73,6 +76,8 @@ const val IDZIENNIK_WEB_GET_MESSAGE = "mod_komunikator/WS_wiadomosci.asmx/Pobier
|
||||
const val IDZIENNIK_WEB_GET_RECIPIENT_LIST = "mod_komunikator/WS_wiadomosci.asmx/pobierzListeOdbiorcowPanelRodzic"
|
||||
const val IDZIENNIK_WEB_SEND_MESSAGE = "mod_komunikator/WS_wiadomosci.asmx/WyslijWiadomosc"
|
||||
const val IDZIENNIK_WEB_GET_ATTACHMENT = "mod_komunikator/Download.ashx"
|
||||
const val IDZIENNIK_WEB_GET_HOMEWORK = "mod_panelRodzica/pracaDomowa/WS_pracaDomowa.asmx/pobierzJednaPraceDomowa"
|
||||
const val IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT = "mod_panelRodzica/pracaDomowa.aspx"
|
||||
|
||||
val IDZIENNIK_API_USER_AGENT = SYSTEM_USER_AGENT
|
||||
const val IDZIENNIK_API_URL = "https://iuczniowie.progman.pl/idziennik/api"
|
||||
@ -106,5 +111,7 @@ const val VULCAN_API_ENDPOINT_MESSAGES_SENT = "mobile-api/Uczen.v3.Uczen/Wiadomo
|
||||
const val VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS = "mobile-api/Uczen.v3.Uczen/ZmienStatusWiadomosci"
|
||||
const val VULCAN_API_ENDPOINT_MESSAGES_ADD = "mobile-api/Uczen.v3.Uczen/DodajWiadomosc"
|
||||
const val VULCAN_API_ENDPOINT_PUSH = "mobile-api/Uczen.v3.Uczen/UstawPushToken"
|
||||
const val VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/WiadomosciZalacznik"
|
||||
const val VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/ZadaniaDomoweZalacznik"
|
||||
|
||||
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
||||
|
@ -8,11 +8,12 @@ import android.app.Notification
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.Bundle
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.receivers.SzkolnyReceiver
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
@ -35,16 +36,18 @@ class EdziennikNotification(val app: App) {
|
||||
var serviceClosed = false
|
||||
|
||||
private fun cancelPendingIntent(taskId: Int): PendingIntent {
|
||||
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
||||
intent.putExtra("task", "TaskCancelRequest")
|
||||
intent.putExtra("taskId", taskId)
|
||||
return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
||||
val intent = SzkolnyReceiver.getIntent(app, Bundle(
|
||||
"task" to "TaskCancelRequest",
|
||||
"taskId" to taskId
|
||||
))
|
||||
return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) as PendingIntent
|
||||
}
|
||||
private val closePendingIntent: PendingIntent
|
||||
get() {
|
||||
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
||||
intent.putExtra("task", "ServiceCloseRequest")
|
||||
return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
||||
val intent = SzkolnyReceiver.getIntent(app, Bundle(
|
||||
"task" to "ServiceCloseRequest"
|
||||
))
|
||||
return PendingIntent.getBroadcast(app, 0, intent, 0) as PendingIntent
|
||||
}
|
||||
|
||||
private fun errorCountText(): String? {
|
||||
@ -134,7 +137,7 @@ class EdziennikNotification(val app: App) {
|
||||
fun post() {
|
||||
if (serviceClosed)
|
||||
return
|
||||
notificationManager.notify(app.notifications.syncId, notification)
|
||||
notificationManager.notify(app.notificationChannelsManager.sync.id, notification)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.EndpointTimer
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_NEVER
|
||||
|
||||
fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featureIds: List<Int>, viewId: Int?) {
|
||||
fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?) {
|
||||
val data = this
|
||||
|
||||
val possibleLoginMethods = data.loginMethods.toMutableList()
|
||||
@ -46,14 +46,19 @@ fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featu
|
||||
// add all endpoint IDs and required login methods, filtering using timers
|
||||
.onEach { feature ->
|
||||
feature.endpointIds.forEach { endpoint ->
|
||||
if (onlyEndpoints?.contains(endpoint.first) == false)
|
||||
return@forEach
|
||||
(data.endpointTimers
|
||||
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id
|
||||
?: -1, endpoint.first))
|
||||
.let { timer ->
|
||||
if (timer.nextSync == SYNC_ALWAYS ||
|
||||
(viewId != null && timer.viewId == viewId) ||
|
||||
(timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
|
||||
data.targetEndpointIds.add(endpoint.first)
|
||||
if (
|
||||
onlyEndpoints?.contains(endpoint.first) == true ||
|
||||
timer.nextSync == SYNC_ALWAYS ||
|
||||
viewId != null && timer.viewId == viewId ||
|
||||
timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp
|
||||
) {
|
||||
data.targetEndpointIds[endpoint.first] = timer.lastSync
|
||||
requiredLoginMethods.add(endpoint.second)
|
||||
}
|
||||
}
|
||||
@ -76,8 +81,8 @@ fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featu
|
||||
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
||||
data.targetLoginMethodIds.sort()
|
||||
|
||||
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
||||
data.targetEndpointIds.sort()
|
||||
//data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
||||
//data.targetEndpointIds.sort()
|
||||
|
||||
progressCount = targetLoginMethodIds.size + targetEndpointIds.size
|
||||
progressStep = if (progressCount <= 0) 0f else 100f / progressCount.toFloat()
|
||||
|
@ -32,6 +32,8 @@ const val CODE_LIBRUS_DISCONNECTED = 31
|
||||
const val CODE_PROFILE_ARCHIVED = 30*/
|
||||
|
||||
const val ERROR_APP_CRASH = 1
|
||||
const val ERROR_EXCEPTION = 2
|
||||
const val ERROR_API_EXCEPTION = 3
|
||||
const val ERROR_MESSAGE_NOT_SENT = 10
|
||||
|
||||
const val ERROR_REQUEST_FAILURE = 50
|
||||
@ -59,6 +61,9 @@ const val ERROR_FILE_DOWNLOAD = 113
|
||||
|
||||
const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
|
||||
|
||||
const val ERROR_CAPTCHA_NEEDED = 3000
|
||||
const val ERROR_CAPTCHA_LIBRUS_PORTAL = 3001
|
||||
|
||||
const val CODE_INTERNAL_LIBRUS_ACCOUNT_410 = 120
|
||||
const val CODE_INTERNAL_LIBRUS_SYNERGIA_EXPIRED = 121
|
||||
const val ERROR_LOGIN_LIBRUS_API_CAPTCHA_NEEDED = 124
|
||||
@ -116,6 +121,12 @@ const val ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN = 179
|
||||
const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN = 180
|
||||
const val ERROR_LIBRUS_API_MAINTENANCE = 181
|
||||
const val ERROR_LIBRUS_PORTAL_MAINTENANCE = 182
|
||||
const val ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM = 183
|
||||
const val ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED = 184
|
||||
const val ERROR_LIBRUS_API_DEVICE_REGISTERED = 185
|
||||
const val ERROR_LIBRUS_MESSAGES_NOT_FOUND = 186
|
||||
const val ERROR_LOGIN_LIBRUS_API_INVALID_REQUEST = 187
|
||||
const val ERROR_LIBRUS_MESSAGES_ATTACHMENT_NOT_FOUND = 188
|
||||
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
||||
@ -132,6 +143,7 @@ const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID = 215
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN = 216
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER = 217
|
||||
const val ERROR_MOBIDZIENNIK_WEB_SERVER_PROBLEM = 218
|
||||
|
||||
const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
|
||||
const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302
|
||||
@ -146,6 +158,7 @@ const val ERROR_LOGIN_VULCAN_NO_PUPILS = 331
|
||||
const val ERROR_VULCAN_API_MAINTENANCE = 340
|
||||
const val ERROR_VULCAN_API_BAD_REQUEST = 341
|
||||
const val ERROR_VULCAN_API_OTHER = 342
|
||||
const val ERROR_VULCAN_ATTACHMENT_DOWNLOAD = 343
|
||||
|
||||
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN = 401
|
||||
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME = 402
|
||||
@ -195,5 +208,6 @@ const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
|
||||
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
||||
const val EXCEPTION_EDUDZIENNIK_WEB_REQUEST = 920
|
||||
const val EXCEPTION_EDUDZIENNIK_FILE_REQUEST = 921
|
||||
const val ERROR_ONEDRIVE_DOWNLOAD = 930
|
||||
|
||||
const val LOGIN_NO_ARGUMENTS = 1201
|
||||
|
@ -13,8 +13,8 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOME
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
|
||||
|
||||
internal const val FEATURE_TIMETABLE = 1
|
||||
internal const val FEATURE_AGENDA = 2
|
||||
|
@ -70,13 +70,13 @@ val librusLoginMethods = listOf(
|
||||
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_SYNERGIA, LibrusLoginSynergia::class.java)
|
||||
.withIsPossible { _, loginStore -> !loginStore.hasLoginData("fakeLogin") }
|
||||
.withRequiredLoginMethod { profile, _ ->
|
||||
if (profile?.hasStudentData("accountPassword") == false) LOGIN_METHOD_LIBRUS_API else LOGIN_METHOD_NOT_NEEDED
|
||||
if (profile?.hasStudentData("accountPassword") == false || true) LOGIN_METHOD_LIBRUS_API else LOGIN_METHOD_NOT_NEEDED
|
||||
},
|
||||
|
||||
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_MESSAGES, LibrusLoginMessages::class.java)
|
||||
.withIsPossible { _, loginStore -> !loginStore.hasLoginData("fakeLogin") }
|
||||
.withRequiredLoginMethod { profile, _ ->
|
||||
if (profile?.hasStudentData("accountPassword") == false) LOGIN_METHOD_LIBRUS_SYNERGIA else LOGIN_METHOD_NOT_NEEDED
|
||||
if (profile?.hasStudentData("accountPassword") == false || true) LOGIN_METHOD_LIBRUS_SYNERGIA else LOGIN_METHOD_NOT_NEEDED
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
package pl.szczodrzynski.edziennik.data.api
|
||||
|
||||
import kotlin.text.RegexOption.DOT_MATCHES_ALL
|
||||
import kotlin.text.RegexOption.IGNORE_CASE
|
||||
|
||||
object Regexes {
|
||||
val STYLE_CSS_COLOR by lazy {
|
||||
@ -54,6 +55,9 @@ object Regexes {
|
||||
val MOBIDZIENNIK_MESSAGE_ATTACHMENT by lazy {
|
||||
"""href="https://.+?\.mobidziennik.pl/.+?&(?:amp;)?zalacznik=([0-9]+)"(?:.+?<small.+?\(([0-9.]+)\s(M|K|G|)B\))*""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_MESSAGE_SENT_READ_BY by lazy {
|
||||
"""([0-9]+)/([0-9]+)""".toRegex()
|
||||
}
|
||||
|
||||
val MOBIDZIENNIK_MESSAGE_RECIPIENTS_JSON by lazy {
|
||||
"""odbiorcy: (\[.+?]),${'$'}""".toRegex(RegexOption.MULTILINE)
|
||||
@ -64,6 +68,39 @@ object Regexes {
|
||||
}
|
||||
|
||||
|
||||
val MOBIDZIENNIK_ATTENDANCE_TABLE by lazy {
|
||||
"""<table .+?id="obecnosci_tabela">(.+?)</table>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_ATTENDANCE_LESSON_COUNT by lazy {
|
||||
"""rel="([0-9-]{10})" colspan="([0-9]+)"""".toRegex()
|
||||
}
|
||||
val MOBIDZIENNIK_ATTENDANCE_ENTRIES by lazy {
|
||||
"""font-size:.+?class=".*?">(.*?)</td>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_ATTENDANCE_RANGE by lazy {
|
||||
"""<span>([0-9:]+) - .+? (.+?)</span></a>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_ATTENDANCE_LESSON by lazy {
|
||||
"""<strong>(.+?) - (.*?)</strong>.+?<small>.+?\((.+?), .+?(.+?)\)""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
val MOBIDZIENNIK_HOMEWORK_ROW by lazy {
|
||||
"""class="rowRolling">(.+?</div>\s*</td>)""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_HOMEWORK_ITEM by lazy {
|
||||
"""<p><b>(.+?):</b>\s*(.+?)\s*</p>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_HOMEWORK_BODY by lazy {
|
||||
"""Treść:</b>(.+?)<p><b>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_HOMEWORK_ID by lazy {
|
||||
"""zadanieFormularz\(([0-9]+),""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_HOMEWORK_ATTACHMENT by lazy {
|
||||
"""zalacznik(_zadania)?=([0-9]+)'.+?word-break">(.+?)</td>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
|
||||
|
||||
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
||||
"""<input type="hidden".+?name="([A-z0-9_]+)?".+?value="([A-z0-9_+-/=]+)?".+?>""".toRegex(DOT_MATCHES_ALL)
|
||||
@ -89,6 +126,13 @@ object Regexes {
|
||||
val IDZIENNIK_MESSAGES_RECIPIENT_PARENT by lazy {
|
||||
"""(.+?)\s\((.+)\)""".toRegex()
|
||||
}
|
||||
/*<span id="ctl00_spanSzczesliwyLos">Szczęśliwy los na dzisiaj to <b>19</b>. Los na jutro to <b>22</b></span>*/
|
||||
val IDZIENNIK_WEB_LUCKY_NUMBER by lazy {
|
||||
"""dzisiaj to <b>([0-9]+)</b>""".toRegex()
|
||||
}
|
||||
val IDZIENNIK_WEB_SELECTED_REGISTER by lazy {
|
||||
"""selected="selected" value="([0-9]+)" data-id-ucznia""".toRegex()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -99,7 +143,7 @@ object Regexes {
|
||||
|
||||
|
||||
val LIBRUS_ATTACHMENT_KEY by lazy {
|
||||
"""singleUseKey=([0-9A-f_]+)""".toRegex()
|
||||
"""singleUseKey=([0-9A-z_]+)""".toRegex()
|
||||
}
|
||||
|
||||
|
||||
@ -127,6 +171,9 @@ object Regexes {
|
||||
val EDUDZIENNIK_ANNOUNCEMENT_DESCRIPTION by lazy {
|
||||
"""<div class="desc">.*?<p>(.*?)</p>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val EDUDZIENNIK_HOMEWORK_DESCRIPTION by lazy {
|
||||
"""<div class="desc">(.*?)</div>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
val EDUDZIENNIK_SUBJECT_ID by lazy {
|
||||
"""/Courses/([\w-_]+?)/""".toRegex()
|
||||
@ -172,4 +219,20 @@ object Regexes {
|
||||
val EDUDZIENNIK_TEACHERS by lazy {
|
||||
"""<div class="teacher">.*?<p>(.+?) (.+?)</p>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
val LINKIFY_DATE_YMD by lazy {
|
||||
"""(1\d{3}|20\d{2})[\-./](1[0-2]|0?\d)[\-./]([1-2]\d|3[0-1]|0?\d)""".toRegex()
|
||||
}
|
||||
val LINKIFY_DATE_DMY by lazy {
|
||||
"""(?<![\d\-./])([1-2]\d|3[0-1]|0?\d)[\-./](1[0-2]|0?\d)(?:[\-./](1\d{3}|2?0?\d{2}))?(?![\d\-/])""".toRegex()
|
||||
}
|
||||
val LINKIFY_DATE_ABSOLUTE by lazy {
|
||||
"""([1-3][0-9]|[1-9])\s(sty|lut|mar|kwi|maj|cze|lip|sie|wrz|paź|lis|gru).*?\s(1[0-9]{3}|20[0-9]{2})?""".toRegex(IGNORE_CASE)
|
||||
}
|
||||
val LINKIFY_DATE_RELATIVE by lazy {
|
||||
"""za\s([0-9]+)?\s?(dni|dzień|tydzień|tygodnie)""".toRegex(IGNORE_CASE)
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
|
||||
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
|
||||
@ -30,14 +30,15 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
|
||||
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
|
||||
fun sync() = EdziennikTask(-1, SyncRequest())
|
||||
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, arguments))
|
||||
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, onlyEndpoints: List<Int>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, onlyEndpoints, arguments))
|
||||
fun syncProfileList(profileList: List<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList))
|
||||
fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message))
|
||||
fun messageSend(profileId: Int, recipients: List<Teacher>, subject: String, text: String) = EdziennikTask(profileId, MessageSendRequest(recipients, subject, text))
|
||||
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
|
||||
fun announcementGet(profileId: Int, announcement: AnnouncementFull) = EdziennikTask(profileId, AnnouncementGetRequest(announcement))
|
||||
fun attachmentGet(profileId: Int, message: Message, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(message, attachmentId, attachmentName))
|
||||
fun attachmentGet(profileId: Int, owner: Any, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(owner, attachmentId, attachmentName))
|
||||
fun recipientListGet(profileId: Int) = EdziennikTask(profileId, RecipientListGetRequest())
|
||||
fun eventGet(profileId: Int, event: EventFull) = EdziennikTask(profileId, EventGetRequest(event))
|
||||
}
|
||||
|
||||
private lateinit var loginStore: LoginStore
|
||||
@ -85,14 +86,16 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) }
|
||||
?: Features.getAllIds(),
|
||||
viewId = request.viewIds?.get(0)?.first,
|
||||
onlyEndpoints = request.onlyEndpoints,
|
||||
arguments = request.arguments)
|
||||
is MessageGetRequest -> edziennikInterface?.getMessage(request.message)
|
||||
is MessageSendRequest -> edziennikInterface?.sendMessage(request.recipients, request.subject, request.text)
|
||||
is FirstLoginRequest -> edziennikInterface?.firstLogin()
|
||||
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
|
||||
is AnnouncementGetRequest -> edziennikInterface?.getAnnouncement(request.announcement)
|
||||
is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.message, request.attachmentId, request.attachmentName)
|
||||
is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.owner, request.attachmentId, request.attachmentName)
|
||||
is RecipientListGetRequest -> edziennikInterface?.getRecipientList()
|
||||
is EventGetRequest -> edziennikInterface?.getEvent(request.event)
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,12 +109,13 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
|
||||
data class FirstLoginRequest(val loginStore: LoginStore)
|
||||
class SyncRequest
|
||||
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null, val arguments: JsonObject? = null)
|
||||
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null, val onlyEndpoints: List<Int>? = null, val arguments: JsonObject? = null)
|
||||
data class SyncProfileListRequest(val profileList: List<Int>)
|
||||
data class MessageGetRequest(val message: MessageFull)
|
||||
data class MessageSendRequest(val recipients: List<Teacher>, val subject: String, val text: String)
|
||||
class AnnouncementsReadRequest
|
||||
data class AnnouncementGetRequest(val announcement: AnnouncementFull)
|
||||
data class AttachmentGetRequest(val message: Message, val attachmentId: Long, val attachmentName: String)
|
||||
data class AttachmentGetRequest(val owner: Any, val attachmentId: Long, val attachmentName: String)
|
||||
class RecipientListGetRequest
|
||||
data class EventGetRequest(val event: EventFull)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikData
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebGetAnnouncement
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebGetHomework
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin.EdudziennikFirstLogin
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLogin
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLoginWeb
|
||||
@ -16,10 +17,10 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -52,9 +53,9 @@ class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStor
|
||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||
__/ |
|
||||
|__*/
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?, arguments: JsonObject?) {
|
||||
data.arguments = arguments
|
||||
data.prepare(edudziennikLoginMethods, EdudziennikFeatures, featureIds, viewId)
|
||||
data.prepare(edudziennikLoginMethods, EdudziennikFeatures, featureIds, viewId, onlyEndpoints)
|
||||
login()
|
||||
}
|
||||
|
||||
@ -94,13 +95,22 @@ class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStor
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {}
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {}
|
||||
override fun getRecipientList() {}
|
||||
|
||||
override fun getEvent(eventFull: EventFull) {
|
||||
EdudziennikLoginWeb(data) {
|
||||
EdudziennikWebGetHomework(data, eventFull) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun firstLogin() { EdudziennikFirstLogin(data) { completed() } }
|
||||
override fun cancel() {
|
||||
d(TAG, "Cancelled")
|
||||
data.cancel()
|
||||
callback.onCompleted()
|
||||
}
|
||||
|
||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||
|
@ -27,60 +27,62 @@ class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
useEndpoint(data.targetEndpointIds.removeAt(0)) {
|
||||
val id = data.targetEndpointIds.firstKey()
|
||||
val lastSync = data.targetEndpointIds.remove(id)
|
||||
useEndpoint(id, lastSync) { endpointId ->
|
||||
data.progress(data.progressStep)
|
||||
nextEndpoint(onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId")
|
||||
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
|
||||
when (endpointId) {
|
||||
ENDPOINT_EDUDZIENNIK_WEB_START -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_data)
|
||||
EdudziennikWebStart(data, onSuccess)
|
||||
EdudziennikWebStart(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_TEACHERS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
||||
EdudziennikWebTeachers(data, onSuccess)
|
||||
EdudziennikWebTeachers(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
||||
EdudziennikWebGrades(data, onSuccess)
|
||||
EdudziennikWebGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||
EdudziennikWebTimetable(data, onSuccess)
|
||||
EdudziennikWebTimetable(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_EXAMS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
||||
EdudziennikWebExams(data, onSuccess)
|
||||
EdudziennikWebExams(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
||||
EdudziennikWebAttendance(data, onSuccess)
|
||||
EdudziennikWebAttendance(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
|
||||
EdudziennikWebAnnouncements(data, onSuccess)
|
||||
EdudziennikWebAnnouncements(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
||||
EdudziennikWebHomework(data, onSuccess)
|
||||
EdudziennikWebHomework(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_EVENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_events)
|
||||
EdudziennikWebEvents(data, onSuccess)
|
||||
EdudziennikWebEvents(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_NOTES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
||||
EdudziennikWebNotes(data, onSuccess)
|
||||
EdudziennikWebNotes(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
||||
EdudziennikWebLuckyNumber(data, onSuccess)
|
||||
EdudziennikWebLuckyNumber(data, lastSync, onSuccess)
|
||||
}
|
||||
else -> onSuccess()
|
||||
else -> onSuccess(endpointId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,13 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
|
||||
import im.wangchao.mhttp.Request
|
||||
import im.wangchao.mhttp.Response
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import okhttp3.Cookie
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
open class EdudziennikWeb(open val data: DataEdudziennik) {
|
||||
open class EdudziennikWeb(open val data: DataEdudziennik, open val lastSync: Long?) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWeb"
|
||||
}
|
||||
@ -43,8 +42,8 @@ open class EdudziennikWeb(open val data: DataEdudziennik) {
|
||||
|
||||
if (semester == null && url.contains("start")) {
|
||||
profile?.also { profile ->
|
||||
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com")
|
||||
val semesterCookie = cookies.firstOrNull { it.name() == "semester" }?.value()?.toIntOrNull()
|
||||
val cookies = data.app.cookieJar.getAll("dziennikel.appspot.com")
|
||||
val semesterCookie = cookies["semester"]?.toIntOrNull()
|
||||
|
||||
semesterCookie?.let { data.currentSemester = it }
|
||||
|
||||
@ -75,13 +74,7 @@ open class EdudziennikWeb(open val data: DataEdudziennik) {
|
||||
}
|
||||
}
|
||||
|
||||
data.app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("sessionid")
|
||||
.value(data.webSessionId!!)
|
||||
.domain("dziennikel.appspot.com")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
data.app.cookieJar.set("dziennikel.appspot.com", "sessionid", data.webSessionId)
|
||||
|
||||
Request.builder()
|
||||
.url(url)
|
||||
|
@ -11,13 +11,15 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Announcement
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebAnnouncements(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebAnnouncements"
|
||||
}
|
||||
@ -66,7 +68,7 @@ class EdudziennikWebAnnouncements(override val data: DataEdudziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ANNOUNCEMENTS) }
|
||||
}
|
||||
|
@ -20,13 +20,22 @@ import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import java.util.*
|
||||
|
||||
class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebAttendance"
|
||||
}
|
||||
|
||||
init { data.profile?.also { profile ->
|
||||
webGet(TAG, data.studentEndpoint + "Presence", semester = -1) { text ->
|
||||
private var requestSemester: Int? = null
|
||||
|
||||
init {
|
||||
if (profile?.empty == true && data.currentSemester == 2) requestSemester = 1
|
||||
getAttendances()
|
||||
}
|
||||
|
||||
private fun getAttendances() { data.profile?.also { profile ->
|
||||
webGet(TAG, data.studentEndpoint + "Presence", semester = requestSemester) { text ->
|
||||
|
||||
val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
|
||||
val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
|
||||
@ -89,8 +98,13 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
||||
}
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
if (profile.empty && requestSemester == 1 && data.currentSemester == 2) {
|
||||
requestSemester = null
|
||||
getAttendances()
|
||||
} else {
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE)
|
||||
}
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE) }
|
||||
}
|
||||
|
@ -11,14 +11,16 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_EVENTS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebEvents(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebEvents"
|
||||
}
|
||||
@ -37,17 +39,16 @@ class EdudziennikWebEvents(override val data: DataEdudziennik,
|
||||
?: return@forEach
|
||||
|
||||
val eventObject = Event(
|
||||
profileId,
|
||||
id,
|
||||
date,
|
||||
null,
|
||||
title,
|
||||
-1,
|
||||
Event.TYPE_CLASS_EVENT,
|
||||
false,
|
||||
-1,
|
||||
-1,
|
||||
data.teamClass?.id ?: -1
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
date = date,
|
||||
time = null,
|
||||
topic = title,
|
||||
color = null,
|
||||
type = Event.TYPE_CLASS_EVENT,
|
||||
teacherId = -1,
|
||||
subjectId = -1,
|
||||
teamId = data.teamClass?.id ?: -1
|
||||
)
|
||||
|
||||
data.eventList.add(eventObject)
|
||||
@ -64,7 +65,7 @@ class EdudziennikWebEvents(override val data: DataEdudziennik,
|
||||
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_CLASS_EVENT))
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_EVENTS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_EVENTS)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_EVENTS) }
|
||||
}
|
||||
|
@ -20,7 +20,9 @@ import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebExams(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebExams"
|
||||
}
|
||||
@ -54,17 +56,16 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
|
||||
val eventType = data.getEventType(eventTypeId, eventTypeName)
|
||||
|
||||
val eventObject = Event(
|
||||
profileId,
|
||||
id,
|
||||
date,
|
||||
startTime,
|
||||
topic,
|
||||
-1,
|
||||
eventType.id,
|
||||
false,
|
||||
-1,
|
||||
subject.id,
|
||||
data.teamClass?.id ?: -1
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
date = date,
|
||||
time = startTime,
|
||||
topic = topic,
|
||||
color = null,
|
||||
type = eventType.id,
|
||||
teacherId = -1,
|
||||
subjectId = subject.id,
|
||||
teamId = data.teamClass?.id ?: -1
|
||||
)
|
||||
|
||||
data.eventList.add(eventObject)
|
||||
@ -84,7 +85,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
|
||||
)))
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_EXAMS)
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -12,11 +12,10 @@ import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
|
||||
class EdudziennikWebGetAnnouncement(
|
||||
override val data: DataEdudziennik,
|
||||
private val announcement: AnnouncementFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : EdudziennikWeb(data) {
|
||||
class EdudziennikWebGetAnnouncement(override val data: DataEdudziennik,
|
||||
private val announcement: AnnouncementFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : EdudziennikWeb(data, null) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebGetAnnouncement"
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import android.text.Html
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||
|
||||
class EdudziennikWebGetHomework(
|
||||
override val data: DataEdudziennik,
|
||||
val event: EventFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : EdudziennikWeb(data, null) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebGetHomework"
|
||||
}
|
||||
|
||||
init {
|
||||
if (event.attachmentNames.isNotNullNorEmpty()) {
|
||||
val id = event.attachmentNames!![0]
|
||||
|
||||
webGet(TAG, "Homework/$id") { text ->
|
||||
val description = Regexes.EDUDZIENNIK_HOMEWORK_DESCRIPTION.find(text)?.get(1)?.trim()
|
||||
|
||||
if (description != null) event.topic = Html.fromHtml(description).toString()
|
||||
|
||||
event.homeworkBody = ""
|
||||
event.attachmentNames = null
|
||||
|
||||
data.eventList += event
|
||||
data.eventListReplace = true
|
||||
|
||||
EventBus.getDefault().postSticky(EventGetEvent(event))
|
||||
onSuccess()
|
||||
}
|
||||
} else {
|
||||
EventBus.getDefault().postSticky(EventGetEvent(event))
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZI
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
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_POINT_SUM
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_FINAL
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_PROPOSED
|
||||
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.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
@ -22,7 +27,9 @@ import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebGrades(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebGrades"
|
||||
}
|
||||
@ -88,7 +95,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
||||
val columnName = info.child(4).text().trim()
|
||||
val comment = info.ownText()
|
||||
|
||||
val description = columnName + if (comment.isNotBlank()) " - $comment" else ""
|
||||
val description = columnName + if (comment.isNotBlank()) " - $comment" else null
|
||||
|
||||
val teacherName = info.child(1).text()
|
||||
val teacher = data.getTeacherByLastFirst(teacherName)
|
||||
@ -107,20 +114,20 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
||||
} ?: -1
|
||||
|
||||
val gradeObject = Grade(
|
||||
profileId,
|
||||
id,
|
||||
fullName,
|
||||
color,
|
||||
description,
|
||||
name,
|
||||
value,
|
||||
if (gradeCountToAverage) weight else 0f,
|
||||
semester,
|
||||
teacher.id,
|
||||
subject.id
|
||||
).apply {
|
||||
type = gradeType
|
||||
}
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
name = name,
|
||||
type = gradeType,
|
||||
value = value,
|
||||
weight = if (gradeCountToAverage) weight else 0f,
|
||||
color = color,
|
||||
category = fullName,
|
||||
description = description,
|
||||
comment = null,
|
||||
semester = semester,
|
||||
teacherId = teacher.id,
|
||||
subjectId = subject.id
|
||||
)
|
||||
|
||||
data.gradeList.add(gradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -137,23 +144,23 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
||||
|
||||
if (proposed != null && proposed.isNotBlank()) {
|
||||
val proposedGradeObject = Grade(
|
||||
profileId,
|
||||
(-1 * subject.id) - 1,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
proposed,
|
||||
proposed.toFloatOrNull() ?: 0f,
|
||||
0f,
|
||||
semester,
|
||||
-1,
|
||||
subject.id
|
||||
).apply {
|
||||
type = when (semester) {
|
||||
1 -> TYPE_SEMESTER1_PROPOSED
|
||||
else -> TYPE_SEMESTER2_PROPOSED
|
||||
}
|
||||
}
|
||||
profileId = profileId,
|
||||
id = (-1 * subject.id) - 1,
|
||||
name = proposed,
|
||||
type = when (semester) {
|
||||
1 -> TYPE_SEMESTER1_PROPOSED
|
||||
else -> TYPE_SEMESTER2_PROPOSED
|
||||
},
|
||||
value = proposed.toFloatOrNull() ?: 0f,
|
||||
weight = 0f,
|
||||
color = -1,
|
||||
category = null,
|
||||
description = null,
|
||||
comment = null,
|
||||
semester = semester,
|
||||
teacherId = -1,
|
||||
subjectId = subject.id
|
||||
)
|
||||
|
||||
data.gradeList.add(proposedGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -170,23 +177,23 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
||||
|
||||
if (final != null && final.isNotBlank()) {
|
||||
val finalGradeObject = Grade(
|
||||
profileId,
|
||||
(-1 * subject.id) - 2,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
final,
|
||||
final.toFloatOrNull() ?: 0f,
|
||||
0f,
|
||||
semester,
|
||||
-1,
|
||||
subject.id
|
||||
).apply {
|
||||
type = when (semester) {
|
||||
1 -> TYPE_SEMESTER1_FINAL
|
||||
else -> TYPE_SEMESTER2_FINAL
|
||||
}
|
||||
}
|
||||
profileId = profileId,
|
||||
id = (-1 * subject.id) - 2,
|
||||
name = final,
|
||||
type = when (semester) {
|
||||
1 -> TYPE_SEMESTER1_FINAL
|
||||
else -> TYPE_SEMESTER2_FINAL
|
||||
},
|
||||
value = final.toFloatOrNull() ?: 0f,
|
||||
weight = 0f,
|
||||
color = -1,
|
||||
category = null,
|
||||
description = null,
|
||||
comment = null,
|
||||
semester = semester,
|
||||
teacherId = -1,
|
||||
subjectId = subject.id
|
||||
)
|
||||
|
||||
data.gradeList.add(finalGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -218,8 +225,8 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
||||
getGrades()
|
||||
} else {
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_GRADES)
|
||||
}
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_GRADES) }
|
||||
}
|
||||
|
@ -12,14 +12,16 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebHomework(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebHomework"
|
||||
}
|
||||
@ -31,8 +33,8 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
|
||||
if (doc.getElementsByClass("message").text().trim() != "Brak prac domowych") {
|
||||
doc.getElementsByTag("tr").forEach { homeworkElement ->
|
||||
val dateElement = homeworkElement.getElementsByClass("date").first().child(0)
|
||||
val id = EDUDZIENNIK_HOMEWORK_ID.find(dateElement.attr("href"))?.get(1)?.crc32()
|
||||
?: return@forEach
|
||||
val idStr = EDUDZIENNIK_HOMEWORK_ID.find(dateElement.attr("href"))?.get(1) ?: return@forEach
|
||||
val id = idStr.crc32()
|
||||
val date = Date.fromY_m_d(dateElement.text())
|
||||
|
||||
val subjectElement = homeworkElement.child(1).child(0)
|
||||
@ -47,22 +49,23 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
|
||||
val teacherName = homeworkElement.child(2).text()
|
||||
val teacher = data.getTeacherByFirstLast(teacherName)
|
||||
|
||||
val topic = homeworkElement.child(4).text()
|
||||
val topic = homeworkElement.child(4).text()?.trim()
|
||||
|
||||
val eventObject = Event(
|
||||
profileId,
|
||||
id,
|
||||
date,
|
||||
startTime,
|
||||
topic,
|
||||
-1,
|
||||
Event.TYPE_HOMEWORK,
|
||||
false,
|
||||
teacher.id,
|
||||
subject.id,
|
||||
data.teamClass?.id ?: -1
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
date = date,
|
||||
time = startTime,
|
||||
topic = topic ?: "",
|
||||
color = null,
|
||||
type = Event.TYPE_HOMEWORK,
|
||||
teacherId = teacher.id,
|
||||
subjectId = subject.id,
|
||||
teamId = data.teamClass?.id ?: -1
|
||||
)
|
||||
|
||||
eventObject.attachmentNames = mutableListOf(idStr)
|
||||
|
||||
data.eventList.add(eventObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
@ -78,7 +81,7 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
|
||||
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_HOMEWORK) }
|
||||
}
|
||||
|
@ -7,13 +7,15 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebLuckyNumber"
|
||||
}
|
||||
@ -39,7 +41,7 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER) }
|
||||
}
|
||||
|
@ -17,7 +17,9 @@ import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebNotes(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebNotes"
|
||||
}
|
||||
@ -59,7 +61,7 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_NOTES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_NOTES)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_NOTES) }
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ import pl.szczodrzynski.edziennik.firstLettersName
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
|
||||
class EdudziennikWebStart(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebStart"
|
||||
}
|
||||
@ -29,7 +31,7 @@ class EdudziennikWebStart(override val data: DataEdudziennik,
|
||||
getSubjects(text)
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_START, MONTH)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_START)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.Edudzienni
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
|
||||
class EdudziennikWebTeachers(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebTeachers"
|
||||
}
|
||||
@ -26,7 +28,7 @@ class EdudziennikWebTeachers(override val data: DataEdudziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_TEACHERS, MONTH)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_TEACHERS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,10 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.singleOrNull
|
||||
@ -24,7 +24,9 @@ import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
|
||||
class EdudziennikWebTimetable(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : EdudziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebTimetable"
|
||||
}
|
||||
@ -142,7 +144,7 @@ class EdudziennikWebTimetable(override val data: DataEdudziennik,
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE) }
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit
|
||||
private const val TAG = "EdudziennikFirstLogin"
|
||||
}
|
||||
|
||||
private val web = EdudziennikWeb(data)
|
||||
private val web = EdudziennikWeb(data, null)
|
||||
private val profileList = mutableListOf<Profile>()
|
||||
|
||||
init {
|
||||
|
@ -24,7 +24,7 @@ class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit)
|
||||
onSuccess()
|
||||
}
|
||||
else {
|
||||
data.app.cookieJar.clearForDomain("dziennikel.appspot.com")
|
||||
data.app.cookieJar.clear("dziennikel.appspot.com")
|
||||
if (data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
|
||||
loginWithCredentials()
|
||||
}
|
||||
@ -59,8 +59,8 @@ class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit)
|
||||
}
|
||||
}
|
||||
|
||||
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com")
|
||||
val sessionId = cookies.firstOrNull { it.name() == "sessionid" }?.value()
|
||||
val cookies = data.app.cookieJar.getAll("dziennikel.appspot.com")
|
||||
val sessionId = cookies["sessionid"]
|
||||
|
||||
if (sessionId == null) {
|
||||
data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID)
|
||||
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-4-7.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.helper
|
||||
|
||||
import im.wangchao.mhttp.Request
|
||||
import im.wangchao.mhttp.Response
|
||||
import im.wangchao.mhttp.callback.FileCallbackHandler
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_ONEDRIVE_DOWNLOAD
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
|
||||
import pl.szczodrzynski.edziennik.data.api.SYSTEM_USER_AGENT
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
class OneDriveDownloadAttachment(
|
||||
app: App,
|
||||
fileUrl: String,
|
||||
val onSuccess: (file: File) -> Unit,
|
||||
val onProgress: (written: Long, total: Long) -> Unit,
|
||||
val onError: (apiError: ApiError) -> Unit
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "OneDriveDownloadAttachment"
|
||||
}
|
||||
|
||||
init {
|
||||
Request.builder()
|
||||
.url(fileUrl)
|
||||
.userAgent(SYSTEM_USER_AGENT)
|
||||
.withClient(app.httpLazy)
|
||||
.callback(object : TextCallbackHandler() {
|
||||
override fun onSuccess(text: String, response: Response) {
|
||||
val location = response.headers().get("Location")
|
||||
// https://onedrive.live.com/redir?resid=D75496A2EB87531C!706&authkey=!ABjZeh3pHMqj11Q
|
||||
if (location?.contains("onedrive.live.com/redir?resid=") != true) {
|
||||
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||
.withApiResponse(text)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
val url = location
|
||||
.replace("onedrive.live.com/redir?resid=", "storage.live.com/items/")
|
||||
.replace("?", "&")
|
||||
.replaceFirst("&", "?")
|
||||
downloadFile(url)
|
||||
}
|
||||
|
||||
override fun onFailure(response: Response, throwable: Throwable) {
|
||||
onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||
.withResponse(response)
|
||||
.withThrowable(throwable))
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
private fun downloadFile(url: String) {
|
||||
val targetFile = Utils.getStorageDir()
|
||||
|
||||
val callback = object : FileCallbackHandler(targetFile) {
|
||||
override fun onSuccess(file: File?, response: Response?) {
|
||||
if (file == null) {
|
||||
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
onSuccess(file)
|
||||
} catch (e: Exception) {
|
||||
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||
.withResponse(response)
|
||||
.withThrowable(e))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
|
||||
try {
|
||||
this@OneDriveDownloadAttachment.onProgress(bytesWritten, bytesTotal)
|
||||
} catch (e: Exception) {
|
||||
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||
.withThrowable(e))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||
onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||
.withResponse(response)
|
||||
.withThrowable(throwable))
|
||||
}
|
||||
}
|
||||
|
||||
Request.builder()
|
||||
.url(url)
|
||||
.userAgent(SYSTEM_USER_AGENT)
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik
|
||||
|
||||
import androidx.core.util.set
|
||||
import okhttp3.Cookie
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_API
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_WEB
|
||||
@ -24,18 +23,8 @@ class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(
|
||||
loginMethods.clear()
|
||||
if (isWebLoginValid()) {
|
||||
loginMethods += LOGIN_METHOD_IDZIENNIK_WEB
|
||||
app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("ASP.NET_SessionId_iDziennik")
|
||||
.value(webSessionId!!)
|
||||
.domain("iuczniowie.progman.pl")
|
||||
.secure().httpOnly().build(),
|
||||
Cookie.Builder()
|
||||
.name(".ASPXAUTH")
|
||||
.value(webAuth!!)
|
||||
.domain("iuczniowie.progman.pl")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
app.cookieJar.set("iuczniowie.progman.pl", "ASP.NET_SessionId_iDziennik", webSessionId)
|
||||
app.cookieJar.set("iuczniowie.progman.pl", ".ASPXAUTH", webAuth)
|
||||
}
|
||||
if (isApiLoginValid())
|
||||
loginMethods += LOGIN_METHOD_IDZIENNIK_API
|
||||
@ -81,6 +70,11 @@ class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(
|
||||
get() { mWebAuth = mWebAuth ?: loginStore.getLoginData("webAuth", null); return mWebAuth }
|
||||
set(value) { loginStore.putLoginData("webAuth", value); mWebAuth = value }
|
||||
|
||||
private var mWebSelectedRegister: Int? = null
|
||||
var webSelectedRegister: Int
|
||||
get() { mWebSelectedRegister = mWebSelectedRegister ?: loginStore.getLoginData("webSelectedRegister", 0); return mWebSelectedRegister ?: 0 }
|
||||
set(value) { loginStore.putLoginData("webSelectedRegister", value); mWebSelectedRegister = value }
|
||||
|
||||
/* _
|
||||
/\ (_)
|
||||
/ \ _ __ _
|
||||
|
@ -8,20 +8,15 @@ import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikData
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebGetAttachment
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebGetMessage
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebGetRecipientList
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebSendMessage
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin.IdziennikFirstLogin
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLogin
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -54,9 +49,9 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||
__/ |
|
||||
|__*/
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?, arguments: JsonObject?) {
|
||||
data.arguments = arguments
|
||||
data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId)
|
||||
data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId, onlyEndpoints)
|
||||
login()
|
||||
}
|
||||
|
||||
@ -103,10 +98,17 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
override fun markAllAnnouncementsAsRead() {}
|
||||
override fun getAnnouncement(announcement: AnnouncementFull) {}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||
login(LOGIN_METHOD_IDZIENNIK_WEB) {
|
||||
IdziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
|
||||
completed()
|
||||
if (owner is Message) {
|
||||
IdziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
else if (owner is Event) {
|
||||
IdziennikWebGetHomeworkAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,10 +121,19 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEvent(eventFull: EventFull) {
|
||||
login(LOGIN_METHOD_IDZIENNIK_WEB) {
|
||||
IdziennikWebGetHomework(data, eventFull) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun firstLogin() { IdziennikFirstLogin(data) { completed() } }
|
||||
override fun cancel() {
|
||||
d(TAG, "Cancelled")
|
||||
data.cancel()
|
||||
callback.onCompleted()
|
||||
}
|
||||
|
||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||
|
@ -18,7 +18,7 @@ import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import java.net.HttpURLConnection
|
||||
|
||||
open class IdziennikApi(open val data: DataIdziennik) {
|
||||
open class IdziennikApi(open val data: DataIdziennik, open val lastSync: Long?) {
|
||||
companion object {
|
||||
const val TAG = "IdziennikApi"
|
||||
}
|
||||
|
@ -30,60 +30,62 @@ class IdziennikData(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
useEndpoint(data.targetEndpointIds.removeAt(0)) {
|
||||
val id = data.targetEndpointIds.firstKey()
|
||||
val lastSync = data.targetEndpointIds.remove(id)
|
||||
useEndpoint(id, lastSync) { endpointId ->
|
||||
data.progress(data.progressStep)
|
||||
nextEndpoint(onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId")
|
||||
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
|
||||
when (endpointId) {
|
||||
ENDPOINT_IDZIENNIK_WEB_TIMETABLE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||
IdziennikWebTimetable(data, onSuccess)
|
||||
IdziennikWebTimetable(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
||||
IdziennikWebGrades(data, onSuccess)
|
||||
IdziennikWebGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades)
|
||||
IdziennikWebProposedGrades(data, onSuccess)
|
||||
IdziennikWebProposedGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_EXAMS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
||||
IdziennikWebExams(data, onSuccess)
|
||||
IdziennikWebExams(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_HOMEWORK -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
||||
IdziennikWebHomework(data, onSuccess)
|
||||
IdziennikWebHomework(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_NOTICES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
||||
IdziennikWebNotices(data, onSuccess)
|
||||
IdziennikWebNotices(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
|
||||
IdziennikWebAnnouncements(data, onSuccess)
|
||||
IdziennikWebAnnouncements(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_WEB_ATTENDANCE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
||||
IdziennikWebAttendance(data, onSuccess)
|
||||
IdziennikWebAttendance(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
||||
IdziennikApiCurrentRegister(data, onSuccess)
|
||||
IdziennikApiCurrentRegister(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
||||
IdziennikApiMessagesInbox(data, onSuccess)
|
||||
IdziennikApiMessagesInbox(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_IDZIENNIK_API_MESSAGES_SENT -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
|
||||
IdziennikApiMessagesSent(data, onSuccess)
|
||||
IdziennikApiMessagesSent(data, lastSync, onSuccess)
|
||||
}
|
||||
else -> onSuccess()
|
||||
else -> onSuccess(endpointId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,14 @@ import im.wangchao.mhttp.callback.JsonCallbackHandler
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebSwitchRegister
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import java.io.File
|
||||
import java.net.HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
|
||||
|
||||
open class IdziennikWeb(open val data: DataIdziennik) {
|
||||
open class IdziennikWeb(open val data: DataIdziennik, open val lastSync: Long?) {
|
||||
companion object {
|
||||
const val TAG = "IdziennikWeb"
|
||||
}
|
||||
@ -48,6 +49,17 @@ open class IdziennikWeb(open val data: DataIdziennik) {
|
||||
return
|
||||
}
|
||||
|
||||
if (response?.code() == HTTP_INTERNAL_ERROR && endpoint == IDZIENNIK_WEB_GRADES) {
|
||||
// special override for accounts where displaying grades
|
||||
// for another student requires switching it manually
|
||||
if (data.registerId != data.webSelectedRegister) {
|
||||
IdziennikWebSwitchRegister(data, data.registerId) {
|
||||
webApiGet(tag, endpoint, parameters, onSuccess)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
response?.code() == HTTP_UNAUTHORIZED -> ERROR_IDZIENNIK_WEB_ACCESS_DENIED
|
||||
response?.code() == HTTP_INTERNAL_ERROR -> ERROR_IDZIENNIK_WEB_SERVER_ERROR
|
||||
@ -115,7 +127,7 @@ open class IdziennikWeb(open val data: DataIdziennik) {
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
fun webGet(tag: String, endpoint: String, onSuccess: (text: String) -> Unit) {
|
||||
fun webGet(tag: String, endpoint: String, parameters: Map<String, Any> = emptyMap(), onSuccess: (text: String) -> Unit) {
|
||||
d(tag, "Request: Idziennik/Web - $IDZIENNIK_WEB_URL/$endpoint")
|
||||
|
||||
val callback = object : TextCallbackHandler() {
|
||||
@ -160,7 +172,14 @@ open class IdziennikWeb(open val data: DataIdziennik) {
|
||||
Request.builder()
|
||||
.url("$IDZIENNIK_WEB_URL/$endpoint")
|
||||
.userAgent(IDZIENNIK_USER_AGENT)
|
||||
.get()
|
||||
.apply {
|
||||
if (parameters.isEmpty()) get()
|
||||
else post()
|
||||
|
||||
parameters.map { (name, value) ->
|
||||
addParameter(name, value)
|
||||
}
|
||||
}
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
@ -210,6 +229,7 @@ open class IdziennikWeb(open val data: DataIdziennik) {
|
||||
.apply {
|
||||
parameters.forEach { (k, v) -> addParameter(k, v) }
|
||||
}
|
||||
.contentType("application/x-www-form-urlencoded")
|
||||
.post()
|
||||
.callback(callback)
|
||||
.build()
|
||||
|
@ -19,7 +19,9 @@ import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class IdziennikApiCurrentRegister(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikApi(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikApiCurrentRegister"
|
||||
}
|
||||
@ -27,7 +29,7 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
|
||||
init {
|
||||
apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json ->
|
||||
if (json !is JsonObject) {
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER)
|
||||
return@apiGet
|
||||
}
|
||||
|
||||
@ -67,7 +69,7 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
|
||||
|
||||
val luckyNumberObject = LuckyNumber(
|
||||
data.profileId,
|
||||
Date.getToday(),
|
||||
luckyNumberDate,
|
||||
luckyNumber
|
||||
)
|
||||
|
||||
@ -85,7 +87,7 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
|
||||
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER, syncAt = nextSync)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,20 +10,18 @@ import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_API_MESSAGES_INBOX
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.getBoolean
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.crc32
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikApi(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikApiMessagesInbox"
|
||||
}
|
||||
@ -31,15 +29,15 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
||||
init {
|
||||
apiGet(TAG, IDZIENNIK_API_MESSAGES_INBOX) { json ->
|
||||
if (json !is JsonArray) {
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX)
|
||||
return@apiGet
|
||||
}
|
||||
|
||||
json.asJsonObjectList()?.forEach { jMessage ->
|
||||
val subject = jMessage.getString("tytul")
|
||||
if (subject?.contains("(") == true && subject.startsWith("iDziennik - "))
|
||||
json.asJsonObjectList().forEach { jMessage ->
|
||||
val subject = jMessage.getString("tytul") ?: ""
|
||||
if (subject.contains("(") && subject.startsWith("iDziennik - "))
|
||||
return@forEach
|
||||
if (subject?.startsWith("Uwaga dla ucznia (klasa:") == true)
|
||||
if (subject.startsWith("Uwaga dla ucznia (klasa:"))
|
||||
return@forEach
|
||||
|
||||
val messageIdStr = jMessage.getString("id")
|
||||
@ -66,13 +64,12 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
||||
rTeacher.setTeacherType(Teacher.TYPE_OTHER)
|
||||
|
||||
val message = Message(
|
||||
profileId,
|
||||
messageId,
|
||||
subject,
|
||||
body,
|
||||
if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
|
||||
rTeacher.id,
|
||||
-1
|
||||
profileId = profileId,
|
||||
id = messageId,
|
||||
type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
|
||||
subject = subject,
|
||||
body = body,
|
||||
senderId = rTeacher.id
|
||||
)
|
||||
|
||||
val messageRecipient = MessageRecipient(
|
||||
@ -83,7 +80,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
||||
/*messageId*/ messageId
|
||||
)
|
||||
|
||||
data.messageIgnoreList.add(message)
|
||||
data.messageList.add(message)
|
||||
data.messageRecipientList.add(messageRecipient)
|
||||
data.setSeenMetadataList.add(Metadata(
|
||||
profileId,
|
||||
@ -96,7 +93,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,14 +13,16 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_SENT
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.crc32
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikApiMessagesSent(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikApi(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikApiMessagesSent"
|
||||
}
|
||||
@ -28,7 +30,7 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
|
||||
init {
|
||||
apiGet(TAG, IDZIENNIK_API_MESSAGES_SENT) { json ->
|
||||
if (json !is JsonArray) {
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT)
|
||||
return@apiGet
|
||||
}
|
||||
|
||||
@ -44,13 +46,12 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
|
||||
val sentDate = Date.fromIso(jMessage.get("dataWyslania").asString)
|
||||
|
||||
val message = Message(
|
||||
profileId,
|
||||
messageId,
|
||||
subject,
|
||||
body,
|
||||
TYPE_SENT,
|
||||
-1,
|
||||
-1
|
||||
profileId = profileId,
|
||||
id = messageId,
|
||||
type = TYPE_SENT,
|
||||
subject = subject,
|
||||
body = body,
|
||||
senderId = null
|
||||
)
|
||||
|
||||
for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) {
|
||||
@ -74,12 +75,12 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
|
||||
data.messageRecipientIgnoreList.add(messageRecipient)
|
||||
}
|
||||
|
||||
data.messageIgnoreList.add(message)
|
||||
data.messageList.add(message)
|
||||
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,17 @@ 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.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Announcement
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.getJsonObject
|
||||
import pl.szczodrzynski.edziennik.getLong
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikWebAnnouncements(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebAnnouncements"
|
||||
}
|
||||
@ -41,11 +45,11 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
|
||||
for (jAnnouncementEl in json.getAsJsonArray("ListK")) {
|
||||
val jAnnouncement = jAnnouncementEl.asJsonObject
|
||||
// jAnnouncement
|
||||
val announcementId = jAnnouncement.get("Id").asLong
|
||||
val announcementId = jAnnouncement.getLong("Id") ?: -1
|
||||
|
||||
val rTeacher = data.getTeacherByFirstLast(jAnnouncement.get("Autor").asString)
|
||||
val addedDate = java.lang.Long.parseLong(jAnnouncement.get("DataDodania").asString.replace("[^\\d]".toRegex(), ""))
|
||||
val startDate = Date.fromMillis(java.lang.Long.parseLong(jAnnouncement.get("DataWydarzenia").asString.replace("[^\\d]".toRegex(), "")))
|
||||
val rTeacher = data.getTeacherByFirstLast(jAnnouncement.getString("Autor") ?: "")
|
||||
val addedDate = jAnnouncement.getString("DataDodania")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull() ?: System.currentTimeMillis()
|
||||
val startDate = jAnnouncement.getString("DataWydarzenia")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull()?.let { Date.fromMillis(it) }
|
||||
|
||||
val announcementObject = Announcement(
|
||||
profileId,
|
||||
@ -69,7 +73,7 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,23 +4,25 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
||||
|
||||
import pl.szczodrzynski.edziennik.crc16
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_ATTENDANCE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_ATTENDANCE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.crc16
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.getJsonObject
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class IdziennikWebAttendance(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebAttendance"
|
||||
}
|
||||
@ -137,7 +139,7 @@ class IdziennikWebAttendance(override val data: DataIdziennik,
|
||||
getAttendance()
|
||||
} else {
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_ATTENDANCE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,16 @@ 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.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import java.util.*
|
||||
|
||||
class IdziennikWebExams(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebExams"
|
||||
}
|
||||
@ -63,28 +66,30 @@ class IdziennikWebExams(override val data: DataIdziennik,
|
||||
val subjectId = data.getSubject(subjectName, null, subjectName).id
|
||||
val teacherName = exam.getString("wpisal") ?: return@forEach
|
||||
val teacherId = data.getTeacherByLastFirst(teacherName).id
|
||||
val topic = exam.getString("zakres") ?: ""
|
||||
val topic = exam.getString("zakres")?.trim() ?: ""
|
||||
|
||||
val lessonList = data.db.timetableDao().getForDateNow(profileId, examDate)
|
||||
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
|
||||
|
||||
val eventType = when (exam.getString("rodzaj")) {
|
||||
"sprawdzian/praca klasowa" -> Event.TYPE_EXAM
|
||||
else -> Event.TYPE_SHORT_QUIZ
|
||||
val eventType = when (exam.getString("rodzaj")?.toLowerCase(Locale.getDefault())) {
|
||||
"sprawdzian/praca klasowa",
|
||||
"sprawdzian",
|
||||
"praca klasowa" -> Event.TYPE_EXAM
|
||||
"kartkówka" -> Event.TYPE_SHORT_QUIZ
|
||||
else -> Event.TYPE_EXAM
|
||||
}
|
||||
|
||||
val eventObject = Event(
|
||||
profileId,
|
||||
id,
|
||||
examDate,
|
||||
startTime,
|
||||
topic,
|
||||
-1,
|
||||
eventType,
|
||||
false,
|
||||
teacherId,
|
||||
subjectId,
|
||||
data.teamClass?.id ?: -1
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
date = examDate,
|
||||
time = startTime,
|
||||
topic = topic,
|
||||
color = null,
|
||||
type = eventType,
|
||||
teacherId = teacherId,
|
||||
subjectId = subjectId,
|
||||
teamId = data.teamClass?.id ?: -1
|
||||
)
|
||||
|
||||
data.eventList.add(eventObject)
|
||||
@ -116,7 +121,7 @@ class IdziennikWebExams(override val data: DataIdziennik,
|
||||
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_EXAMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,15 +14,19 @@ import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
class IdziennikWebGetAttachment(
|
||||
override val data: DataIdziennik, val message: Message, val attachmentId: Long,
|
||||
val attachmentName: String, val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data) {
|
||||
class IdziennikWebGetAttachment(override val data: DataIdziennik,
|
||||
val owner: Any,
|
||||
val attachmentId: Long,
|
||||
val attachmentName: String,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
const val TAG = "IdziennikWebGetAttachment"
|
||||
}
|
||||
|
||||
init {
|
||||
val message = owner as Message
|
||||
|
||||
val messageId = "\\[META:([A-z0-9]+);([0-9-]+)]".toRegex().find(message.body ?: "")?.get(2) ?: -1
|
||||
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
||||
|
||||
@ -32,29 +36,29 @@ class IdziennikWebGetAttachment(
|
||||
), { file ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_FINISHED,
|
||||
file.absolutePath
|
||||
)
|
||||
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
|
||||
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||
|
||||
EventBus.getDefault().post(event)
|
||||
EventBus.getDefault().postSticky(event)
|
||||
|
||||
onSuccess()
|
||||
|
||||
}) { written, _ ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_PROGRESS,
|
||||
bytesWritten = written
|
||||
)
|
||||
|
||||
EventBus.getDefault().post(event)
|
||||
EventBus.getDefault().postSticky(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-4-1.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_HOMEWORK
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.getBoolean
|
||||
import pl.szczodrzynski.edziennik.getJsonObject
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
|
||||
class IdziennikWebGetHomework(override val data: DataIdziennik,
|
||||
val event: EventFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebGetHomework"
|
||||
}
|
||||
|
||||
init {
|
||||
webApiGet(TAG, IDZIENNIK_WEB_GET_HOMEWORK, mapOf(
|
||||
"idP" to data.registerId,
|
||||
"idPD" to event.id
|
||||
)) { result ->
|
||||
val json = result.getJsonObject("d") ?: run {
|
||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
||||
.withApiResponse(result))
|
||||
return@webApiGet
|
||||
}
|
||||
|
||||
val homework = json.getJsonObject("praca") ?: return@webApiGet
|
||||
|
||||
if (homework.getBoolean("zalacznik", false)) {
|
||||
event.attachmentIds = mutableListOf(event.id)
|
||||
event.attachmentNames = mutableListOf("Załącznik do zadania")
|
||||
}
|
||||
else {
|
||||
event.attachmentIds = mutableListOf()
|
||||
event.attachmentNames = mutableListOf()
|
||||
}
|
||||
event.homeworkBody = homework.getString("tresc")
|
||||
|
||||
data.eventList.add(event)
|
||||
data.eventListReplace = true
|
||||
|
||||
EventBus.getDefault().postSticky(EventGetEvent(event))
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-4-1.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.set
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
class IdziennikWebGetHomeworkAttachment(override val data: DataIdziennik,
|
||||
val owner: Any,
|
||||
val attachmentId: Long,
|
||||
val attachmentName: String,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
const val TAG = "IdziennikWebGetHomeworkAttachment"
|
||||
}
|
||||
|
||||
init {
|
||||
val homework = owner as Event
|
||||
|
||||
/*val request = Request.Builder()
|
||||
.url("")
|
||||
.build()
|
||||
data.app.http.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||
.withThrowable(e))
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val filename = response.header("content-disposition")?.substringAfter("\"")?.substringBeforeLast("\"")
|
||||
|
||||
val file: File = File(Utils.getStorageDir(), filename)
|
||||
val sink = file.sink().buffer()
|
||||
response.body()?.source()?.let {
|
||||
sink.writeAll(it)
|
||||
}
|
||||
sink.close()
|
||||
}
|
||||
})*/
|
||||
|
||||
webGet(TAG, IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT) { text ->
|
||||
val hiddenFields = JsonObject()
|
||||
Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text).forEach {
|
||||
hiddenFields[it[1]] = it[2]
|
||||
}
|
||||
|
||||
webGetFile(TAG, IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT, Utils.getStorageDir(), mapOf(
|
||||
"__VIEWSTATE" to hiddenFields.getString("__VIEWSTATE", ""),
|
||||
"__VIEWSTATEGENERATOR" to hiddenFields.getString("__VIEWSTATEGENERATOR", ""),
|
||||
"__EVENTVALIDATION" to hiddenFields.getString("__EVENTVALIDATION", ""),
|
||||
"__EVENTTARGET" to "ctl00\$cphContent\$bt_pobraniePliku",
|
||||
"ctl00\$dxComboUczniowie" to data.registerId,
|
||||
"ctl00\$cphContent\$idPracyDomowej" to attachmentId
|
||||
), { file ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_FINISHED,
|
||||
file.absolutePath
|
||||
)
|
||||
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
|
||||
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||
|
||||
homework.attachmentNames = mutableListOf(file.name)
|
||||
data.eventList.add(homework)
|
||||
data.eventListReplace = true
|
||||
|
||||
EventBus.getDefault().postSticky(event)
|
||||
onSuccess()
|
||||
|
||||
}) { written, _ ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_PROGRESS,
|
||||
bytesWritten = written
|
||||
)
|
||||
|
||||
EventBus.getDefault().postSticky(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,18 +10,17 @@ import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_MESSAGE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikWebGetMessage(
|
||||
override val data: DataIdziennik,
|
||||
private val message: MessageFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data) {
|
||||
class IdziennikWebGetMessage(override val data: DataIdziennik,
|
||||
private val message: MessageFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
const val TAG = "IdziennikWebGetMessage"
|
||||
}
|
||||
@ -51,7 +50,11 @@ class IdziennikWebGetMessage(
|
||||
message.recipients?.clear()
|
||||
when (message.type) {
|
||||
TYPE_RECEIVED -> {
|
||||
val recipientObject = MessageRecipientFull(profileId, -1, message.id)
|
||||
val recipientObject = MessageRecipientFull(
|
||||
profileId = profileId,
|
||||
id = -1,
|
||||
messageId = message.id
|
||||
)
|
||||
|
||||
val readDateString = it.getString("DataOdczytania")
|
||||
recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis()
|
||||
@ -68,7 +71,11 @@ class IdziennikWebGetMessage(
|
||||
val recipientName = recipient.getString("NazwaOdbiorcy") ?: return@forEach
|
||||
val teacher = data.getTeacherByLastFirst(recipientName)
|
||||
|
||||
val recipientObject = MessageRecipientFull(profileId, teacher.id, message.id)
|
||||
val recipientObject = MessageRecipientFull(
|
||||
profileId = profileId,
|
||||
id = teacher.id,
|
||||
messageId = message.id
|
||||
)
|
||||
|
||||
recipientObject.readDate = recipient.getLong("Status") ?: return@forEach
|
||||
recipientObject.fullName = teacher.fullName
|
||||
@ -92,9 +99,10 @@ class IdziennikWebGetMessage(
|
||||
))
|
||||
}
|
||||
|
||||
EventBus.getDefault().postSticky(MessageGetEvent(message))
|
||||
|
||||
data.messageList.add(message)
|
||||
data.messageListReplace = true
|
||||
|
||||
EventBus.getDefault().postSticky(MessageGetEvent(message))
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ import pl.szczodrzynski.edziennik.data.api.events.RecipientListGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
|
||||
class IdziennikWebGetRecipientList(
|
||||
override val data: DataIdziennik, val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
class IdziennikWebGetRecipientList(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebGetRecipientList"
|
||||
}
|
||||
|
@ -14,12 +14,15 @@ 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.DataRemoveModel
|
||||
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.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebGrades"
|
||||
}
|
||||
@ -61,17 +64,19 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
}
|
||||
|
||||
val gradeObject = Grade(
|
||||
profileId,
|
||||
id,
|
||||
category,
|
||||
colorInt,
|
||||
"",
|
||||
name,
|
||||
value,
|
||||
weight,
|
||||
semester,
|
||||
teacher.id,
|
||||
subject.id)
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
name = name,
|
||||
type = TYPE_NORMAL,
|
||||
value = value,
|
||||
weight = weight,
|
||||
color = colorInt,
|
||||
category = category,
|
||||
description = null,
|
||||
comment = null,
|
||||
semester = semester,
|
||||
teacherId = teacher.id,
|
||||
subjectId = subject.id)
|
||||
|
||||
when (grade.getInt("Typ")) {
|
||||
0 -> {
|
||||
@ -96,17 +101,19 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
}
|
||||
|
||||
val historyObject = Grade(
|
||||
profileId,
|
||||
gradeObject.id * -1,
|
||||
historyItem.get("Kategoria").asString,
|
||||
colorInt,
|
||||
historyItem.get("Uzasadnienie").asString,
|
||||
historyItem.get("Ocena").asString,
|
||||
value,
|
||||
if (value > 0f && countToTheAverage) weight * -1f else 0f,
|
||||
historyItem.get("Semestr").asInt,
|
||||
teacher.id,
|
||||
subject.id)
|
||||
profileId = profileId,
|
||||
id = gradeObject.id * -1,
|
||||
name = historyItem.getString("Ocena") ?: "",
|
||||
type = TYPE_NORMAL,
|
||||
value = value,
|
||||
weight = if (value > 0f && countToTheAverage) weight * -1f else 0f,
|
||||
color = colorInt,
|
||||
category = historyItem.getString("Kategoria"),
|
||||
description = historyItem.getString("Uzasadnienie"),
|
||||
comment = null,
|
||||
semester = historyItem.getInt("Semestr") ?: 1,
|
||||
teacherId = teacher.id,
|
||||
subjectId = subject.id)
|
||||
historyObject.parentId = gradeObject.id
|
||||
|
||||
val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
|
||||
@ -163,7 +170,7 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_GRADES)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_IDZIENNIK_WEB_GRADES) }
|
||||
}
|
||||
|
@ -13,13 +13,15 @@ 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.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikWebHomework(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebHomework"
|
||||
}
|
||||
@ -50,13 +52,14 @@ class IdziennikWebHomework(override val data: DataIdziennik,
|
||||
json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { homework ->
|
||||
val id = homework.getLong("_recordId") ?: return@forEach
|
||||
val eventDate = Date.fromY_m_d(homework.getString("dataO") ?: return@forEach)
|
||||
val addedDate = Date.fromY_m_d(homework.getString("dataZ") ?: return@forEach)
|
||||
val subjectName = homework.getString("przed") ?: return@forEach
|
||||
val subjectId = data.getSubject(subjectName, null, subjectName).id
|
||||
val teacherName = homework.getString("usr") ?: return@forEach
|
||||
val teacherId = data.getTeacherByLastFirst(teacherName).id
|
||||
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
|
||||
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime
|
||||
val topic = homework.getString("tytul") ?: ""
|
||||
val topic = homework.getString("tytul")?.trim() ?: ""
|
||||
|
||||
val seen = when (profile?.empty) {
|
||||
true -> true
|
||||
@ -65,17 +68,16 @@ class IdziennikWebHomework(override val data: DataIdziennik,
|
||||
|
||||
|
||||
val eventObject = Event(
|
||||
profileId,
|
||||
id,
|
||||
eventDate,
|
||||
startTime,
|
||||
topic,
|
||||
-1,
|
||||
Event.TYPE_HOMEWORK,
|
||||
false,
|
||||
teacherId,
|
||||
subjectId,
|
||||
data.teamClass?.id ?: -1
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
date = eventDate,
|
||||
time = startTime,
|
||||
topic = topic,
|
||||
color = null,
|
||||
type = Event.TYPE_HOMEWORK,
|
||||
teacherId = teacherId,
|
||||
subjectId = subjectId,
|
||||
teamId = data.teamClass?.id ?: -1
|
||||
)
|
||||
|
||||
data.eventList.add(eventObject)
|
||||
@ -85,14 +87,14 @@ class IdziennikWebHomework(override val data: DataIdziennik,
|
||||
eventObject.id,
|
||||
seen,
|
||||
seen,
|
||||
System.currentTimeMillis()
|
||||
addedDate.inMillis
|
||||
))
|
||||
}
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_HOMEWORK)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,22 +4,24 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
||||
|
||||
import pl.szczodrzynski.edziennik.crc16
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_NOTICES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_NOTICES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.crc16
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
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.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.getJsonObject
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikWebNotices(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebNotices"
|
||||
}
|
||||
@ -69,7 +71,7 @@ class IdziennikWebNotices(override val data: DataIdziennik,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_NOTICES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_NOTICES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,20 @@ 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.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.TYPE_SEMESTER1_PROPOSED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.TYPE_YEAR_PROPOSED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_DESCRIPTIVE
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_PROPOSED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.getJsonArray
|
||||
import pl.szczodrzynski.edziennik.getJsonObject
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.getWordGradeValue
|
||||
|
||||
class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebProposedGrades"
|
||||
}
|
||||
@ -37,35 +39,63 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||
.withApiResponse(result))
|
||||
return@webApiGet
|
||||
}
|
||||
val manager = data.app.gradesManager
|
||||
|
||||
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { subject ->
|
||||
val subjectName = subject.getString("Przedmiot") ?: return@forEach
|
||||
val subjectObject = data.getSubject(subjectName, null, subjectName)
|
||||
|
||||
val semester1Proposed = subject.getString("OcenaSem1") ?: ""
|
||||
val semester1Value = getWordGradeValue(semester1Proposed)
|
||||
val semester1Value = manager.getGradeValue(semester1Proposed)
|
||||
val semester1Id = subjectObject.id * (-100) - 1
|
||||
val semester1Type =
|
||||
if (semester1Value == 0f) TYPE_DESCRIPTIVE
|
||||
else TYPE_SEMESTER1_PROPOSED
|
||||
val semester1Name = when {
|
||||
semester1Value == 0f -> " "
|
||||
semester1Value % 1.0f == 0f -> semester1Value.toInt().toString()
|
||||
else -> semester1Value.toString()
|
||||
}
|
||||
val semester1Color =
|
||||
if (semester1Value == 0f) 0xff536dfe.toInt()
|
||||
else -1
|
||||
|
||||
val semester2Proposed = subject.getString("OcenaSem2") ?: ""
|
||||
val semester2Value = getWordGradeValue(semester2Proposed)
|
||||
val semester2Value = manager.getGradeValue(semester2Proposed)
|
||||
val semester2Id = subjectObject.id * (-100) - 2
|
||||
val semester2Type =
|
||||
if (semester2Value == 0f) TYPE_DESCRIPTIVE
|
||||
else TYPE_YEAR_PROPOSED
|
||||
val semester2Name = when {
|
||||
semester2Value == 0f -> " "
|
||||
semester2Value % 1.0f == 0f -> semester2Value.toInt().toString()
|
||||
else -> semester2Value.toString()
|
||||
}
|
||||
val semester2Color =
|
||||
if (semester2Value == 0f) 0xffff4081.toInt()
|
||||
else -1
|
||||
|
||||
if (semester1Proposed != "") {
|
||||
val gradeObject = Grade(
|
||||
profileId,
|
||||
semester1Id,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
semester1Value.toString(),
|
||||
semester1Value.toFloat(),
|
||||
0f,
|
||||
1,
|
||||
-1,
|
||||
subjectObject.id
|
||||
).apply {
|
||||
type = TYPE_SEMESTER1_PROPOSED
|
||||
}
|
||||
profileId = profileId,
|
||||
id = semester1Id,
|
||||
name = semester1Name,
|
||||
type = semester1Type,
|
||||
value = semester1Value,
|
||||
weight = 0f,
|
||||
color = semester1Color,
|
||||
category = if (semester1Value == 0f) "Ocena opisowa semestralna" else null,
|
||||
description = if (semester1Value == 0f) semester1Proposed else null,
|
||||
comment = null,
|
||||
semester = 1,
|
||||
teacherId = -1,
|
||||
subjectId = subjectObject.id
|
||||
)
|
||||
|
||||
val addedDate = if (data.profile.empty)
|
||||
data.profile.dateSemester1Start.inMillis
|
||||
else
|
||||
System.currentTimeMillis()
|
||||
|
||||
data.gradeList.add(gradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -74,26 +104,31 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||
gradeObject.id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
addedDate
|
||||
))
|
||||
}
|
||||
|
||||
if (semester2Proposed != "") {
|
||||
val gradeObject = Grade(
|
||||
profileId,
|
||||
semester2Id,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
semester2Value.toString(),
|
||||
semester2Value.toFloat(),
|
||||
0f,
|
||||
2,
|
||||
-1,
|
||||
subjectObject.id
|
||||
).apply {
|
||||
type = TYPE_YEAR_PROPOSED
|
||||
}
|
||||
profileId = profileId,
|
||||
id = semester2Id,
|
||||
name = semester2Name,
|
||||
type = semester2Type,
|
||||
value = semester2Value,
|
||||
weight = 0f,
|
||||
color = semester2Color,
|
||||
category = if (semester2Value == 0f) "Ocena opisowa końcoworoczna" else null,
|
||||
description = if (semester2Value == 0f) semester2Proposed else null,
|
||||
comment = null,
|
||||
semester = 2,
|
||||
teacherId = -1,
|
||||
subjectId = subjectObject.id
|
||||
)
|
||||
|
||||
val addedDate = if (data.profile.empty)
|
||||
data.profile.dateSemester2Start.inMillis
|
||||
else
|
||||
System.currentTimeMillis()
|
||||
|
||||
data.gradeList.add(gradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -102,7 +137,7 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||
gradeObject.id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
addedDate
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -111,7 +146,7 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES) }
|
||||
}
|
||||
|
@ -18,13 +18,12 @@ import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import java.util.*
|
||||
|
||||
class IdziennikWebSendMessage(
|
||||
override val data: DataIdziennik,
|
||||
val recipients: List<Teacher>,
|
||||
val subject: String,
|
||||
val text: String,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data) {
|
||||
class IdziennikWebSendMessage(override val data: DataIdziennik,
|
||||
val recipients: List<Teacher>,
|
||||
val subject: String,
|
||||
val text: String,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebSendMessage"
|
||||
}
|
||||
@ -57,8 +56,8 @@ class IdziennikWebSendMessage(
|
||||
return@webApiGet
|
||||
}
|
||||
|
||||
IdziennikApiMessagesSent(data) {
|
||||
val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
|
||||
IdziennikApiMessagesSent(data, null) {
|
||||
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 event = MessageSentEvent(data.profileId, message, metadata?.addedDate)
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_HOME
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
|
||||
class IdziennikWebSwitchRegister(override val data: DataIdziennik,
|
||||
val registerId: Int,
|
||||
val onSuccess: () -> Unit
|
||||
) : IdziennikWeb(data, null) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebSwitchRegister"
|
||||
}
|
||||
|
||||
init {
|
||||
val hiddenFields = data.loginStore.getLoginData("hiddenFields", JsonObject())
|
||||
// TODO error checking
|
||||
|
||||
webGet(TAG, IDZIENNIK_WEB_HOME, mapOf(
|
||||
"__VIEWSTATE" to hiddenFields.getString("__VIEWSTATE", ""),
|
||||
"__VIEWSTATEGENERATOR" to hiddenFields.getString("__VIEWSTATEGENERATOR", ""),
|
||||
"__EVENTVALIDATION" to hiddenFields.getString("__EVENTVALIDATION", ""),
|
||||
"ctl00\$dxComboUczniowie" to registerId
|
||||
)) { text ->
|
||||
Regexes.IDZIENNIK_WEB_SELECTED_REGISTER.find(text)?.let {
|
||||
val registerId = it[1].toIntOrNull() ?: return@let
|
||||
data.webSelectedRegister = registerId
|
||||
}
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -13,17 +13,19 @@ 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.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
|
||||
class IdziennikWebTimetable(override val data: DataIdziennik,
|
||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : IdziennikWeb(data, lastSync) {
|
||||
companion object {
|
||||
private const val TAG = "IdziennikWebTimetable"
|
||||
}
|
||||
@ -187,7 +189,7 @@ class IdziennikWebTimetable(override val data: DataIdziennik,
|
||||
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_IDZIENNIK_WEB_TIMETABLE)
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
||||
private const val TAG = "IdziennikFirstLogin"
|
||||
}
|
||||
|
||||
private val web = IdziennikWeb(data)
|
||||
private val web = IdziennikWeb(data, null)
|
||||
private val profileList = mutableListOf<Profile>()
|
||||
|
||||
init {
|
||||
|
@ -7,15 +7,14 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login
|
||||
import im.wangchao.mhttp.Request
|
||||
import im.wangchao.mhttp.Response
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import okhttp3.Cookie
|
||||
import pl.szczodrzynski.edziennik.HOUR
|
||||
import pl.szczodrzynski.edziennik.MINUTE
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.getUnixDate
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
||||
companion object {
|
||||
@ -24,22 +23,12 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
||||
|
||||
init { run {
|
||||
if (data.isWebLoginValid()) {
|
||||
data.app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("ASP.NET_SessionId_iDziennik")
|
||||
.value(data.webSessionId!!)
|
||||
.domain("iuczniowie.progman.pl")
|
||||
.secure().httpOnly().build(),
|
||||
Cookie.Builder()
|
||||
.name(".ASPXAUTH")
|
||||
.value(data.webAuth!!)
|
||||
.domain("iuczniowie.progman.pl")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
data.app.cookieJar.set("iuczniowie.progman.pl", "ASP.NET_SessionId_iDziennik", data.webSessionId)
|
||||
data.app.cookieJar.set("iuczniowie.progman.pl", ".ASPXAUTH", data.webAuth)
|
||||
onSuccess()
|
||||
}
|
||||
else {
|
||||
data.app.cookieJar.clearForDomain("iuczniowie.progman.pl")
|
||||
data.app.cookieJar.clear("iuczniowie.progman.pl")
|
||||
if (data.webSchoolName != null && data.webUsername != null && data.webPassword != null) {
|
||||
loginWithCredentials()
|
||||
}
|
||||
@ -62,13 +51,47 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
||||
|
||||
// login succeeded: there is a start page
|
||||
if (text.contains("czyWyswietlicDostepMobilny")) {
|
||||
val cookies = data.app.cookieJar.getForDomain("iuczniowie.progman.pl")
|
||||
val cookies = data.app.cookieJar.getAll("iuczniowie.progman.pl")
|
||||
run {
|
||||
data.webSessionId = cookies.singleOrNull { it.name() == "ASP.NET_SessionId_iDziennik" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION
|
||||
data.webAuth = cookies.singleOrNull { it.name() == ".ASPXAUTH" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH
|
||||
data.apiBearer = cookies.singleOrNull { it.name() == "Bearer" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER
|
||||
data.webSessionId = cookies["ASP.NET_SessionId_iDziennik"] ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION
|
||||
data.webAuth = cookies[".ASPXAUTH"] ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH
|
||||
data.apiBearer = cookies["Bearer"]?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER
|
||||
data.loginExpiryTime = response.getUnixDate() + 30 * MINUTE /* after about 40 minutes the login didn't work already */
|
||||
data.apiExpiryTime = response.getUnixDate() + 12 * HOUR /* actually it expires after 24 hours but I'm not sure when does the token refresh. */
|
||||
|
||||
val hiddenFields = JsonObject()
|
||||
Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text).forEach {
|
||||
hiddenFields[it[1]] = it[2]
|
||||
}
|
||||
data.loginStore.putLoginData("hiddenFields", hiddenFields)
|
||||
|
||||
Regexes.IDZIENNIK_WEB_SELECTED_REGISTER.find(text)?.let {
|
||||
val registerId = it[1].toIntOrNull() ?: return@let
|
||||
data.webSelectedRegister = registerId
|
||||
}
|
||||
|
||||
data.profile?.let { profile ->
|
||||
Regexes.IDZIENNIK_WEB_LUCKY_NUMBER.find(text)?.also {
|
||||
val number = it[1].toIntOrNull() ?: return@also
|
||||
val luckyNumberObject = LuckyNumber(
|
||||
data.profileId,
|
||||
Date.getToday(),
|
||||
number
|
||||
)
|
||||
|
||||
data.luckyNumberList.add(luckyNumberObject)
|
||||
data.metadataList.add(
|
||||
Metadata(
|
||||
profile.id,
|
||||
Metadata.TYPE_LUCKY_NUMBER,
|
||||
luckyNumberObject.date.value.toLong(),
|
||||
true,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return@run null
|
||||
}?.let { errorCode ->
|
||||
data.error(ApiError(TAG, errorCode)
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus
|
||||
|
||||
import okhttp3.Cookie
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.currentTimeUnix
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
|
||||
@ -31,23 +30,11 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
loginMethods += LOGIN_METHOD_LIBRUS_API
|
||||
if (isSynergiaLoginValid()) {
|
||||
loginMethods += LOGIN_METHOD_LIBRUS_SYNERGIA
|
||||
app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("DZIENNIKSID")
|
||||
.value(synergiaSessionId!!)
|
||||
.domain("synergia.librus.pl")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", synergiaSessionId)
|
||||
}
|
||||
if (isMessagesLoginValid()) {
|
||||
loginMethods += LOGIN_METHOD_LIBRUS_MESSAGES
|
||||
app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("DZIENNIKSID")
|
||||
.value(messagesSessionId!!)
|
||||
.domain("wiadomosci.librus.pl")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", messagesSessionId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,6 +178,16 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L }
|
||||
set(value) { mApiTokenExpiryTime = value; profile?.putStudentData("accountTokenTime", value) ?: return; }
|
||||
|
||||
/**
|
||||
* A push device ID, generated by Librus when registering
|
||||
* a FCM token. I don't really know if this has any use,
|
||||
* but it may be worthy to save that ID.
|
||||
*/
|
||||
private var mPushDeviceId: Int? = null
|
||||
var pushDeviceId: Int
|
||||
get() { mPushDeviceId = mPushDeviceId ?: profile?.getStudentData("pushDeviceId", 0); return mPushDeviceId ?: 0 }
|
||||
set(value) { mPushDeviceId = value; profile?.putStudentData("pushDeviceId", value) ?: return; }
|
||||
|
||||
/* _____ _
|
||||
/ ____| (_)
|
||||
| (___ _ _ _ __ ___ _ __ __ _ _ __ _
|
||||
|
@ -13,6 +13,8 @@ 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.LibrusMessagesGetRecipientList
|
||||
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.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.login.LibrusLogin
|
||||
@ -24,6 +26,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -56,9 +59,9 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||
__/ |
|
||||
|__*/
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, onlyEndpoints: List<Int>?, arguments: JsonObject?) {
|
||||
data.arguments = arguments
|
||||
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
|
||||
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId, onlyEndpoints)
|
||||
login()
|
||||
}
|
||||
|
||||
@ -118,11 +121,23 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
login(LOGIN_METHOD_LIBRUS_MESSAGES) {
|
||||
LibrusMessagesGetAttachment(data, message, attachmentId, attachmentName) {
|
||||
completed()
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||
when (owner) {
|
||||
is Message -> {
|
||||
login(LOGIN_METHOD_LIBRUS_MESSAGES) {
|
||||
LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
is EventFull -> {
|
||||
login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
|
||||
LibrusSynergiaHomeworkGetAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> completed()
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,10 +149,19 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEvent(eventFull: EventFull) {
|
||||
login(LOGIN_METHOD_LIBRUS_SYNERGIA) {
|
||||
LibrusSynergiaGetHomework(data, eventFull) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun firstLogin() { LibrusFirstLogin(data) { completed() } }
|
||||
override fun cancel() {
|
||||
d(TAG, "Cancelled")
|
||||
data.cancel()
|
||||
callback.onCompleted()
|
||||
}
|
||||
|
||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||
@ -180,6 +204,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE,
|
||||
ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING,
|
||||
ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED,
|
||||
ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED,
|
||||
ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED -> {
|
||||
login()
|
||||
@ -198,7 +223,6 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID -> {
|
||||
login()
|
||||
}
|
||||
// TODO PORTAL CAPTCHA
|
||||
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC -> {
|
||||
data.timetableNotPublic = true
|
||||
data()
|
||||
@ -207,6 +231,11 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
|
||||
data()
|
||||
}
|
||||
ERROR_LIBRUS_API_DEVICE_REGISTERED -> {
|
||||
data.app.config.sync.tokenLibrusList =
|
||||
data.app.config.sync.tokenLibrusList + data.profileId
|
||||
data()
|
||||
}
|
||||
else -> callback.onError(apiError)
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,6 @@ const val ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK = 2030
|
||||
const val ENDPOINT_LIBRUS_MESSAGES_RECEIVED = 3010
|
||||
const val ENDPOINT_LIBRUS_MESSAGES_SENT = 3020
|
||||
const val ENDPOINT_LIBRUS_MESSAGES_TRASH = 3030
|
||||
const val ENDPOINT_LIBRUS_MESSAGES_RECEIVERS = 3040
|
||||
const val ENDPOINT_LIBRUS_MESSAGES_GET = 3040
|
||||
|
||||
val LibrusFeatures = listOf(
|
||||
|
||||
@ -66,7 +64,7 @@ val LibrusFeatures = listOf(
|
||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf(
|
||||
ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API
|
||||
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
|
||||
!data.app.config.sync.tokenLibrusList.contains(data.profileId)
|
||||
(data as DataLibrus).isPremium && !data.app.config.sync.tokenLibrusList.contains(data.profileId)
|
||||
},
|
||||
|
||||
|
||||
@ -118,11 +116,11 @@ val LibrusFeatures = listOf(
|
||||
* Homework - using API.
|
||||
* Sync only if account has premium access.
|
||||
*/
|
||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
|
||||
/*Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
|
||||
ENDPOINT_LIBRUS_API_HOMEWORK to LOGIN_METHOD_LIBRUS_API
|
||||
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
|
||||
(data as DataLibrus).isPremium
|
||||
},
|
||||
},*/
|
||||
/**
|
||||
* Behaviour - using API.
|
||||
*/
|
||||
@ -229,9 +227,9 @@ val LibrusFeatures = listOf(
|
||||
*/
|
||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
|
||||
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LOGIN_METHOD_LIBRUS_SYNERGIA
|
||||
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)).withShouldSync { data ->
|
||||
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA))/*.withShouldSync { data ->
|
||||
!(data as DataLibrus).isPremium
|
||||
},
|
||||
}*/,
|
||||
|
||||
/**
|
||||
* Messages inbox - using messages website.
|
||||
|
@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import java.net.HttpURLConnection.*
|
||||
|
||||
open class LibrusApi(open val data: DataLibrus) {
|
||||
open class LibrusApi(open val data: DataLibrus, open val lastSync: Long?) {
|
||||
companion object {
|
||||
private const val TAG = "LibrusApi"
|
||||
}
|
||||
@ -44,9 +44,12 @@ open class LibrusApi(open val data: DataLibrus) {
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
/*
|
||||
{"Status":"Error","Code":"DeviceRegistered","Message":"This device is alerdy registered.","Resources":{"..":{"Url":"https:\/\/api.librus.pl\/2.0\/Root"}},"Url":"https:\/\/api.librus.pl\/2.0\/ChangeRegister"}*/
|
||||
val error = if (response?.code() == 200) null else
|
||||
json.getString("Code") ?:
|
||||
json.getString("Message") ?:
|
||||
json.getString("Status") ?:
|
||||
response?.parserErrorBody
|
||||
error?.let { code ->
|
||||
when (code) {
|
||||
@ -63,6 +66,9 @@ open class LibrusApi(open val data: DataLibrus) {
|
||||
"NotesIsNotActive" -> ERROR_LIBRUS_API_NOTES_NOT_ACTIVE
|
||||
"InvalidRequest" -> ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
|
||||
"Nieprawidłowy węzeł." -> ERROR_LIBRUS_API_INCORRECT_ENDPOINT
|
||||
"NoticeboardProblem" -> ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
|
||||
"DeviceRegistered" -> ERROR_LIBRUS_API_DEVICE_REGISTERED
|
||||
"Maintenance" -> ERROR_LIBRUS_API_MAINTENANCE
|
||||
else -> ERROR_LIBRUS_API_OTHER
|
||||
}.let { errorCode ->
|
||||
if (errorCode !in ignoreErrors) {
|
||||
@ -114,6 +120,8 @@ open class LibrusApi(open val data: DataLibrus) {
|
||||
.allowErrorCode(HTTP_FORBIDDEN)
|
||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||
.allowErrorCode(HTTP_UNAVAILABLE)
|
||||
.allowErrorCode(HTTP_NOT_FOUND)
|
||||
.allowErrorCode(503)
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
|
@ -31,158 +31,163 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
useEndpoint(data.targetEndpointIds.removeAt(0)) {
|
||||
val id = data.targetEndpointIds.firstKey()
|
||||
val lastSync = data.targetEndpointIds.remove(id)
|
||||
useEndpoint(id, lastSync) { endpointId ->
|
||||
data.progress(data.progressStep)
|
||||
nextEndpoint(onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId")
|
||||
private fun useEndpoint(endpointId: Int, lastSync: Long?, onSuccess: (endpointId: Int) -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId. Last sync time = $lastSync")
|
||||
when (endpointId) {
|
||||
/**
|
||||
* API
|
||||
*/
|
||||
ENDPOINT_LIBRUS_API_ME -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
|
||||
LibrusApiMe(data, onSuccess)
|
||||
LibrusApiMe(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_SCHOOLS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_school_info)
|
||||
LibrusApiSchools(data, onSuccess)
|
||||
LibrusApiSchools(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_CLASSES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_classes)
|
||||
LibrusApiClasses(data, onSuccess)
|
||||
LibrusApiClasses(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teams)
|
||||
LibrusApiVirtualClasses(data, onSuccess)
|
||||
LibrusApiVirtualClasses(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_UNITS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_units)
|
||||
LibrusApiUnits(data, onSuccess)
|
||||
LibrusApiUnits(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_USERS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
||||
LibrusApiUsers(data, onSuccess)
|
||||
LibrusApiUsers(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_SUBJECTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_subjects)
|
||||
LibrusApiSubjects(data, onSuccess)
|
||||
LibrusApiSubjects(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_CLASSROOMS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_classrooms)
|
||||
LibrusApiClassrooms(data, onSuccess)
|
||||
LibrusApiClassrooms(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_LESSONS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_lessons)
|
||||
LibrusApiLessons(data, onSuccess)
|
||||
LibrusApiLessons(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_PUSH_CONFIG -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_push_config)
|
||||
LibrusApiPushConfig(data, lastSync, onSuccess)
|
||||
}
|
||||
// TODO push config
|
||||
ENDPOINT_LIBRUS_API_TIMETABLES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||
LibrusApiTimetables(data, onSuccess)
|
||||
LibrusApiTimetables(data, lastSync, onSuccess)
|
||||
}
|
||||
|
||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||
LibrusApiGradeCategories(data, onSuccess)
|
||||
LibrusApiGradeCategories(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||
LibrusApiBehaviourGradeCategories(data, onSuccess)
|
||||
LibrusApiBehaviourGradeCategories(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||
LibrusApiDescriptiveGradeCategories(data, onSuccess)
|
||||
LibrusApiDescriptiveGradeCategories(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||
LibrusApiTextGradeCategories(data, onSuccess)
|
||||
LibrusApiTextGradeCategories(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||
LibrusApiPointGradeCategories(data, onSuccess)
|
||||
LibrusApiPointGradeCategories(data, lastSync, onSuccess)
|
||||
}
|
||||
|
||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
|
||||
LibrusApiGradeComments(data, onSuccess)
|
||||
LibrusApiGradeComments(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
|
||||
LibrusApiBehaviourGradeComments(data, onSuccess)
|
||||
LibrusApiBehaviourGradeComments(data, lastSync, onSuccess)
|
||||
}
|
||||
|
||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
||||
LibrusApiGrades(data, onSuccess)
|
||||
LibrusApiGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_behaviour_grades)
|
||||
LibrusApiBehaviourGrades(data, onSuccess)
|
||||
LibrusApiBehaviourGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_descriptive_grades)
|
||||
LibrusApiDescriptiveGrades(data, onSuccess)
|
||||
LibrusApiDescriptiveGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_TEXT_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_descriptive_grades)
|
||||
LibrusApiTextGrades(data, onSuccess)
|
||||
LibrusApiTextGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_POINT_GRADES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_point_grades)
|
||||
LibrusApiPointGrades(data, onSuccess)
|
||||
LibrusApiPointGrades(data, lastSync, onSuccess)
|
||||
}
|
||||
|
||||
ENDPOINT_LIBRUS_API_EVENT_TYPES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_event_types)
|
||||
LibrusApiEventTypes(data, onSuccess)
|
||||
LibrusApiEventTypes(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_EVENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_events)
|
||||
LibrusApiEvents(data, onSuccess)
|
||||
LibrusApiEvents(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_HOMEWORK -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
||||
LibrusApiHomework(data, onSuccess)
|
||||
LibrusApiHomework(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_LUCKY_NUMBER -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
||||
LibrusApiLuckyNumber(data, onSuccess)
|
||||
LibrusApiLuckyNumber(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_NOTICE_TYPES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_notice_types)
|
||||
LibrusApiNoticeTypes(data, onSuccess)
|
||||
LibrusApiNoticeTypes(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_NOTICES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
||||
LibrusApiNotices(data, onSuccess)
|
||||
LibrusApiNotices(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance_types)
|
||||
LibrusApiAttendanceTypes(data, onSuccess)
|
||||
LibrusApiAttendanceTypes(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_ATTENDANCES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
||||
LibrusApiAttendances(data, onSuccess)
|
||||
LibrusApiAttendances(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_ANNOUNCEMENTS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
|
||||
LibrusApiAnnouncements(data, onSuccess)
|
||||
LibrusApiAnnouncements(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_PT_MEETINGS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_pt_meetings)
|
||||
LibrusApiPtMeetings(data, onSuccess)
|
||||
LibrusApiPtMeetings(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_day_types)
|
||||
LibrusApiTeacherFreeDayTypes(data, onSuccess)
|
||||
LibrusApiTeacherFreeDayTypes(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_days)
|
||||
LibrusApiTeacherFreeDays(data, onSuccess)
|
||||
LibrusApiTeacherFreeDays(data, lastSync, onSuccess)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,11 +195,11 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||
*/
|
||||
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
||||
LibrusSynergiaHomework(data, onSuccess)
|
||||
LibrusSynergiaHomework(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_SYNERGIA_INFO -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
|
||||
LibrusSynergiaInfo(data, onSuccess)
|
||||
LibrusSynergiaInfo(data, lastSync, onSuccess)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,14 +207,14 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||
*/
|
||||
ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
||||
LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, onSuccess = onSuccess)
|
||||
LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, onSuccess = onSuccess)
|
||||
}
|
||||
ENDPOINT_LIBRUS_MESSAGES_SENT -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
|
||||
LibrusMessagesGetList(data, type = Message.TYPE_SENT, onSuccess = onSuccess)
|
||||
LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = lastSync, onSuccess = onSuccess)
|
||||
}
|
||||
|
||||
else -> onSuccess()
|
||||
else -> onSuccess(endpointId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import im.wangchao.mhttp.body.MediaTypeUtils
|
||||
import im.wangchao.mhttp.callback.FileCallbackHandler
|
||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import okhttp3.Cookie
|
||||
import org.json.JSONObject
|
||||
import org.json.XML
|
||||
import org.jsoup.Jsoup
|
||||
@ -30,7 +29,7 @@ import javax.xml.transform.TransformerFactory
|
||||
import javax.xml.transform.dom.DOMSource
|
||||
import javax.xml.transform.stream.StreamResult
|
||||
|
||||
open class LibrusMessages(open val data: DataLibrus) {
|
||||
open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
|
||||
companion object {
|
||||
private const val TAG = "LibrusMessages"
|
||||
}
|
||||
@ -55,13 +54,20 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||
}
|
||||
|
||||
when {
|
||||
text.contains("<message>Niepoprawny login i/lub hasło.</message>") -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
|
||||
text.contains("stop.png") -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
||||
text.contains("eAccessDeny") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||
text.contains("OffLine") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
|
||||
text.contains("<status>error</status>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
|
||||
text.contains("<type>eVarWhitThisNameNotExists</type>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||
text.contains("<error>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
|
||||
text.contains("<message>Niepoprawny login i/lub hasło.</message>") -> ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN
|
||||
text.contains("<message>Nie odnaleziono wiadomości.</message>") -> ERROR_LIBRUS_MESSAGES_NOT_FOUND
|
||||
text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
|
||||
text.contains("eAccessDeny") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
|
||||
text.contains("OffLine") -> ERROR_LIBRUS_MESSAGES_MAINTENANCE
|
||||
text.contains("<status>error</status>") -> ERROR_LIBRUS_MESSAGES_ERROR
|
||||
text.contains("<type>eVarWhitThisNameNotExists</type>") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
|
||||
text.contains("<error>") -> ERROR_LIBRUS_MESSAGES_OTHER
|
||||
else -> null
|
||||
}?.let { errorCode ->
|
||||
data.error(ApiError(tag, errorCode)
|
||||
.withApiResponse(text)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
@ -82,14 +88,7 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||
}
|
||||
}
|
||||
|
||||
data.app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("DZIENNIKSID")
|
||||
.value(data.messagesSessionId!!)
|
||||
.domain("wiadomosci.librus.pl")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
|
||||
data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
|
||||
|
||||
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
val doc = docBuilder.newDocument()
|
||||
@ -139,13 +138,20 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||
}
|
||||
|
||||
when {
|
||||
text.contains("<message>Niepoprawny login i/lub hasło.</message>") -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
|
||||
text.contains("stop.png") -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
||||
text.contains("eAccessDeny") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||
text.contains("OffLine") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
|
||||
text.contains("<status>error</status>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
|
||||
text.contains("<type>eVarWhitThisNameNotExists</type>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||
text.contains("<error>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
|
||||
text.contains("<message>Niepoprawny login i/lub hasło.</message>") -> ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN
|
||||
text.contains("<message>Nie odnaleziono wiadomości.</message>") -> ERROR_LIBRUS_MESSAGES_NOT_FOUND
|
||||
text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
|
||||
text.contains("eAccessDeny") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
|
||||
text.contains("OffLine") -> ERROR_LIBRUS_MESSAGES_MAINTENANCE
|
||||
text.contains("<status>error</status>") -> ERROR_LIBRUS_MESSAGES_ERROR
|
||||
text.contains("<type>eVarWhitThisNameNotExists</type>") -> ERROR_LIBRUS_MESSAGES_ACCESS_DENIED
|
||||
text.contains("<error>") -> ERROR_LIBRUS_MESSAGES_OTHER
|
||||
else -> null
|
||||
}?.let { errorCode ->
|
||||
data.error(ApiError(tag, errorCode)
|
||||
.withApiResponse(text)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
@ -166,14 +172,7 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||
}
|
||||
}
|
||||
|
||||
data.app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("DZIENNIKSID")
|
||||
.value(data.messagesSessionId!!)
|
||||
.domain("wiadomosci.librus.pl")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
|
||||
data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
|
||||
|
||||
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
val doc = docBuilder.newDocument()
|
||||
@ -253,10 +252,11 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
fun sandboxGetFile(tag: String, action: String, targetFile: File, onSuccess: (file: File) -> Unit,
|
||||
fun sandboxGetFile(tag: String, url: String, targetFile: File, onSuccess: (file: File) -> Unit,
|
||||
method: Int = GET,
|
||||
onProgress: (written: Long, total: Long) -> Unit) {
|
||||
|
||||
d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
|
||||
d(tag, "Request: Librus/Messages - $url")
|
||||
|
||||
val callback = object : FileCallbackHandler(targetFile) {
|
||||
override fun onSuccess(file: File?, response: Response?) {
|
||||
@ -292,9 +292,14 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||
}
|
||||
|
||||
Request.builder()
|
||||
.url("$LIBRUS_SANDBOX_URL$action")
|
||||
.url(url)
|
||||
.userAgent(SYNERGIA_USER_AGENT)
|
||||
.post()
|
||||
.also {
|
||||
when (method) {
|
||||
POST -> it.post()
|
||||
else -> it.get()
|
||||
}
|
||||
}
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
|
@ -44,6 +44,7 @@ open class LibrusPortal(open val data: DataLibrus) {
|
||||
"Access token is invalid" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
|
||||
"ApiDisabled" -> ERROR_LIBRUS_PORTAL_API_DISABLED
|
||||
"Account not found" -> ERROR_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND
|
||||
"Unable to refresh the account" -> ERROR_LIBRUS_PORTAL_MAINTENANCE
|
||||
else -> when (json.getString("hint")) {
|
||||
"Error while decoding to JSON" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
|
||||
else -> ERROR_LIBRUS_PORTAL_OTHER
|
||||
@ -97,6 +98,7 @@ open class LibrusPortal(open val data: DataLibrus) {
|
||||
.allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
|
||||
.allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST)
|
||||
.allowErrorCode(HttpURLConnection.HTTP_GONE)
|
||||
.allowErrorCode(424)
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
|
@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
open class LibrusSynergia(open val data: DataLibrus) {
|
||||
open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
|
||||
companion object {
|
||||
private const val TAG = "LibrusSynergia"
|
||||
}
|
||||
@ -35,7 +35,7 @@ open class LibrusSynergia(open val data: DataLibrus) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!text.contains("jesteś zalogowany")) {
|
||||
if (!text.contains("jesteś zalogowany") && !text.contains("Podgląd zadania")) {
|
||||
when {
|
||||
text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
|
||||
text.contains("Przerwa techniczna") -> ERROR_LIBRUS_SYNERGIA_MAINTENANCE
|
||||
@ -48,7 +48,6 @@ open class LibrusSynergia(open val data: DataLibrus) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
onSuccess(text)
|
||||
} catch (e: Exception) {
|
||||
@ -90,4 +89,42 @@ open class LibrusSynergia(open val data: DataLibrus) {
|
||||
.build()
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
fun redirectUrlGet(tag: String, url: String, onSuccess: (url: String) -> Unit) {
|
||||
val callback = object : TextCallbackHandler() {
|
||||
override fun onSuccess(text: String?, response: Response) {
|
||||
val redirectUrl = response.headers().get("Location")
|
||||
|
||||
if (redirectUrl != null) {
|
||||
try {
|
||||
onSuccess(redirectUrl)
|
||||
} catch (e: Exception) {
|
||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_SYNERGIA_REQUEST)
|
||||
.withResponse(response)
|
||||
.withThrowable(e)
|
||||
.withApiResponse(text))
|
||||
}
|
||||
} else {
|
||||
data.error(ApiError(tag, ERROR_LIBRUS_SYNERGIA_OTHER)
|
||||
.withResponse(response)
|
||||
.withApiResponse(text))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
||||
.withResponse(response)
|
||||
.withThrowable(throwable))
|
||||
}
|
||||
}
|
||||
|
||||
Request.builder()
|
||||
.url(url)
|
||||
.userAgent(LIBRUS_USER_AGENT)
|
||||
.withClient(data.app.httpLazy)
|
||||
.get()
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
}
|
||||
}
|
||||
|
@ -6,25 +6,28 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
|
||||
import pl.szczodrzynski.edziennik.data.api.POST
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
|
||||
class LibrusApiAnnouncementMarkAsRead(
|
||||
override val data: DataLibrus,
|
||||
private val announcement: AnnouncementFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : LibrusApi(data) {
|
||||
class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
|
||||
private val announcement: AnnouncementFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : LibrusApi(data, null) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiAnnouncementMarkAsRead"
|
||||
}
|
||||
|
||||
init {
|
||||
apiGet(TAG, "SchoolNotices/MarkAsRead/${announcement.idString}", method = POST,
|
||||
ignoreErrors = listOf(ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS)) {
|
||||
ignoreErrors = listOf(
|
||||
ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS,
|
||||
ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
|
||||
)) {
|
||||
announcement.seen = true
|
||||
|
||||
EventBus.getDefault().postSticky(AnnouncementGetEvent(announcement))
|
||||
|
@ -9,12 +9,14 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ANNOUNCEMENTS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Announcement
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class LibrusApiAnnouncements(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiAnnouncements"
|
||||
}
|
||||
@ -58,7 +60,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ANNOUNCEMENTS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_ANNOUNCEMENTS)
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.AttendanceType
|
||||
|
||||
class LibrusApiAttendanceTypes(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiAttendanceTypes"
|
||||
}
|
||||
@ -43,7 +45,7 @@ class LibrusApiAttendanceTypes(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 4*DAY)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,12 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class LibrusApiAttendances(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiAttendances"
|
||||
}
|
||||
@ -40,10 +43,10 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
||||
val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id")
|
||||
val semester = attendance.getInt("Semester") ?: return@forEach
|
||||
val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
|
||||
val typeObject = data.attendanceTypes.get(type)
|
||||
val typeObject = data.attendanceTypes[type] ?: null
|
||||
val topic = typeObject?.name ?: ""
|
||||
|
||||
val startTime = data.lessonRanges.get(lessonNo).startTime
|
||||
val startTime = data.lessonRanges.get(lessonNo)?.startTime
|
||||
|
||||
val lesson = if (lessonId != -1L)
|
||||
data.librusLessons.singleOrNull { it.lessonId == lessonId }
|
||||
@ -57,14 +60,14 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
||||
semester,
|
||||
topic,
|
||||
lessonDate,
|
||||
startTime,
|
||||
typeObject.type
|
||||
startTime ?: Time(0, 0, 0),
|
||||
typeObject?.type ?: Attendance.TYPE_CUSTOM
|
||||
)
|
||||
|
||||
val addedDate = Date.fromIso(attendance.getString("AddDate") ?: return@forEach)
|
||||
|
||||
data.attendanceList.add(attendanceObject)
|
||||
if(typeObject.type != Attendance.TYPE_PRESENT) {
|
||||
if(typeObject?.type != Attendance.TYPE_PRESENT) {
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_ATTENDANCE,
|
||||
@ -77,7 +80,7 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
|
||||
|
||||
class LibrusApiBehaviourGradeCategories(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiBehaviourGradeCategories"
|
||||
}
|
||||
@ -40,7 +42,7 @@ class LibrusApiBehaviourGradeCategories(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES, 1 * WEEK)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
|
||||
class LibrusApiBehaviourGradeComments(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiBehaviourGradeComments"
|
||||
}
|
||||
@ -38,7 +40,7 @@ class LibrusApiBehaviourGradeComments(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,38 +9,54 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_SUM
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiBehaviourGrades"
|
||||
}
|
||||
|
||||
private val nameFormat by lazy { DecimalFormat("#.##") }
|
||||
|
||||
private val types by lazy {
|
||||
mapOf(
|
||||
1 to ("wz" to "wzorowe"),
|
||||
2 to ("bdb" to "bardzo dobre"),
|
||||
3 to ("db" to "dobre"),
|
||||
4 to ("popr" to "poprawne"),
|
||||
5 to ("ndp" to "nieodpowiednie"),
|
||||
6 to ("ng" to "naganne")
|
||||
)
|
||||
}
|
||||
|
||||
init { data.profile?.also { profile ->
|
||||
apiGet(TAG, "BehaviourGrades/Points") { json ->
|
||||
|
||||
if (data.startPointsSemester1 > 0) {
|
||||
val semester1StartGradeObject = Grade(
|
||||
profileId,
|
||||
-101,
|
||||
data.app.getString(R.string.grade_start_points),
|
||||
0xffbdbdbd.toInt(),
|
||||
data.app.getString(R.string.grade_start_points_format, 1),
|
||||
nameFormat.format(data.startPointsSemester1),
|
||||
data.startPointsSemester1.toFloat(),
|
||||
-1f,
|
||||
1,
|
||||
-1,
|
||||
1
|
||||
).apply { type = Grade.TYPE_POINT_SUM }
|
||||
profileId = profileId,
|
||||
id = -101,
|
||||
name = nameFormat.format(data.startPointsSemester1),
|
||||
type = TYPE_POINT_SUM,
|
||||
value = data.startPointsSemester1.toFloat(),
|
||||
weight = 0f,
|
||||
color = 0xffbdbdbd.toInt(),
|
||||
category = data.app.getString(R.string.grade_start_points),
|
||||
description = data.app.getString(R.string.grade_start_points_format, 1),
|
||||
comment = null,
|
||||
semester = 1,
|
||||
teacherId = -1,
|
||||
subjectId = 1
|
||||
)
|
||||
|
||||
data.gradeList.add(semester1StartGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -55,18 +71,20 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
|
||||
if (data.startPointsSemester2 > 0) {
|
||||
val semester2StartGradeObject = Grade(
|
||||
profileId,
|
||||
-102,
|
||||
data.app.getString(R.string.grade_start_points),
|
||||
0xffbdbdbd.toInt(),
|
||||
data.app.getString(R.string.grade_start_points_format, 2),
|
||||
nameFormat.format(data.startPointsSemester2),
|
||||
data.startPointsSemester2.toFloat(),
|
||||
-1f,
|
||||
2,
|
||||
-1,
|
||||
1
|
||||
).apply { type = Grade.TYPE_POINT_SUM }
|
||||
profileId = profileId,
|
||||
id = -102,
|
||||
name = nameFormat.format(data.startPointsSemester2),
|
||||
type = TYPE_POINT_SUM,
|
||||
value = data.startPointsSemester2.toFloat(),
|
||||
weight = -1f,
|
||||
color = 0xffbdbdbd.toInt(),
|
||||
category = data.app.getString(R.string.grade_start_points),
|
||||
description = data.app.getString(R.string.grade_start_points_format, 2),
|
||||
comment = null,
|
||||
semester = 2,
|
||||
teacherId = -1,
|
||||
subjectId = 1
|
||||
)
|
||||
|
||||
data.gradeList.add(semester2StartGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -88,8 +106,12 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
val addedDate = grade.getString("AddDate")?.let { Date.fromIso(it) }
|
||||
?: System.currentTimeMillis()
|
||||
|
||||
val text = grade.getString("Text")
|
||||
val type = grade.getJsonObject("BehaviourGrade")?.getInt("Id")?.let { types[it] }
|
||||
|
||||
val name = when {
|
||||
value != null -> (if (value >= 0) "+" else "") + nameFormat.format(value)
|
||||
type != null -> type.first
|
||||
value != null -> (if (value > 0) "+" else "") + nameFormat.format(value)
|
||||
shortName != null -> shortName
|
||||
else -> return@forEach
|
||||
}
|
||||
@ -108,32 +130,33 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
|
||||
val categoryName = category?.text ?: ""
|
||||
|
||||
val description = grade.getJsonArray("Comments")?.asJsonObjectList()?.let { comments ->
|
||||
if (comments.isNotEmpty()) {
|
||||
data.gradeCategories.singleOrNull {
|
||||
it.type == GradeCategory.TYPE_BEHAVIOUR_COMMENT
|
||||
&& it.categoryId == comments[0].asJsonObject.getLong("Id")
|
||||
}?.text
|
||||
} else null
|
||||
} ?: ""
|
||||
val comments = grade.getJsonArray("Comments")
|
||||
?.asJsonObjectList()
|
||||
?.mapNotNull { comment ->
|
||||
val cId = comment.getLong("Id") ?: return@mapNotNull null
|
||||
data.gradeCategories[cId]?.text
|
||||
} ?: listOf()
|
||||
|
||||
val description = listOfNotNull(type?.second) + comments
|
||||
|
||||
val valueFrom = value ?: category?.valueFrom ?: 0f
|
||||
val valueTo = category?.valueTo ?: 0f
|
||||
|
||||
val gradeObject = Grade(
|
||||
profileId,
|
||||
id,
|
||||
categoryName,
|
||||
color,
|
||||
description,
|
||||
name,
|
||||
valueFrom,
|
||||
-1f,
|
||||
semester,
|
||||
teacherId,
|
||||
1
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
name = name,
|
||||
type = TYPE_POINT_SUM,
|
||||
value = valueFrom,
|
||||
weight = -1f,
|
||||
color = color,
|
||||
category = categoryName,
|
||||
description = text ?: description.join(" - "),
|
||||
comment = if (text != null) description.join(" - ") else null,
|
||||
semester = semester,
|
||||
teacherId = teacherId,
|
||||
subjectId = 1
|
||||
).apply {
|
||||
type = Grade.TYPE_POINT_SUM
|
||||
valueMax = valueTo
|
||||
}
|
||||
|
||||
@ -150,7 +173,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(profile.currentSemester, Grade.TYPE_POINT_SUM))
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES) }
|
||||
}
|
||||
|
@ -15,7 +15,9 @@ import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class LibrusApiClasses(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiClasses"
|
||||
}
|
||||
@ -55,7 +57,7 @@ class LibrusApiClasses(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_CLASSES, 4 * DAY)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_CLASSES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ import pl.szczodrzynski.edziennik.data.db.entity.Classroom
|
||||
import java.util.*
|
||||
|
||||
class LibrusApiClassrooms(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiClassrooms"
|
||||
}
|
||||
@ -39,7 +41,7 @@ class LibrusApiClassrooms(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_CLASSROOMS, 4*DAY)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_CLASSROOMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
|
||||
|
||||
class LibrusApiDescriptiveGradeCategories(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiDescriptiveGradeCategories"
|
||||
}
|
||||
@ -39,7 +41,7 @@ class LibrusApiDescriptiveGradeCategories(override val data: DataLibrus,
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES, 1 * DAY)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,16 +9,18 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.TYPE_DESCRIPTIVE_TEXT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.TYPE_TEXT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_DESCRIPTIVE_TEXT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_TEXT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.GradeCategory
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class LibrusApiDescriptiveGrades(override val data: DataLibrus,
|
||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : LibrusApi(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "LibrusApiDescriptiveGrades"
|
||||
}
|
||||
@ -51,20 +53,20 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
|
||||
val addedDate = Date.fromIso(grade.getString("AddDate") ?: return@forEach)
|
||||
|
||||
val gradeObject = Grade(
|
||||
profileId,
|
||||
id,
|
||||
category?.text ?: "",
|
||||
category?.color ?: -1,
|
||||
description,
|
||||
" ",
|
||||
0f,
|
||||
0f,
|
||||
semester,
|
||||
teacherId,
|
||||
subjectId
|
||||
).apply {
|
||||
this.type = type
|
||||
}
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
name = " ",
|
||||
type = type,
|
||||
value = 0f,
|
||||
weight = 0f,
|
||||
color = category?.color ?: -1,
|
||||
category = category?.text,
|
||||
description = description,
|
||||
comment = null,
|
||||
semester = semester,
|
||||
teacherId = teacherId,
|
||||
subjectId = subjectId
|
||||
)
|
||||
|
||||
data.gradeList.add(gradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
@ -85,7 +87,7 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
|
||||
})
|
||||
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
onSuccess(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES)
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
} ?: onSuccess(ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES) }
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user