mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-26 03:55:29 +02:00
Compare commits
7 Commits
v3.9.16-de
...
v3.2.1
Author | SHA1 | Date | |
---|---|---|---|
6a2c863fcc | |||
cf69273de1 | |||
fa99b7fd11 | |||
9c5653b52e | |||
88ad8523a0 | |||
a15f59fbd1 | |||
188470a043 |
7
.gitignore
vendored
7
.gitignore
vendored
@ -47,7 +47,6 @@ captures/
|
|||||||
.idea/modules.xml
|
.idea/modules.xml
|
||||||
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
.idea/navEditor.xml
|
.idea/navEditor.xml
|
||||||
.idea/copyright/profiles_settings.xml
|
|
||||||
|
|
||||||
# Keystore files
|
# Keystore files
|
||||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
@ -81,9 +80,3 @@ lint/generated/
|
|||||||
lint/outputs/
|
lint/outputs/
|
||||||
lint/tmp/
|
lint/tmp/
|
||||||
# lint/reports/
|
# lint/reports/
|
||||||
|
|
||||||
app/schemas/
|
|
||||||
|
|
||||||
signatures/
|
|
||||||
|
|
||||||
app/.cxx
|
|
1
.idea/.name
generated
1
.idea/.name
generated
@ -1 +0,0 @@
|
|||||||
Szkolny.eu
|
|
3
.idea/copyright/profiles_settings.xml
generated
Normal file
3
.idea/copyright/profiles_settings.xml
generated
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<component name="CopyrightManager">
|
||||||
|
<settings default="kubasz" />
|
||||||
|
</component>
|
9
.idea/misc.xml
generated
9
.idea/misc.xml
generated
@ -5,13 +5,6 @@
|
|||||||
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
||||||
</configurations>
|
</configurations>
|
||||||
</component>
|
</component>
|
||||||
<component name="EntryPointsManager">
|
|
||||||
<list size="2">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="androidx.databinding.BindingAdapter" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
|
||||||
</list>
|
|
||||||
</component>
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="NullableNotNullManager">
|
<component name="NullableNotNullManager">
|
||||||
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
||||||
<option name="myDefaultNotNull" value="androidx.annotation.RecentlyNonNull" />
|
<option name="myDefaultNotNull" value="androidx.annotation.RecentlyNonNull" />
|
||||||
@ -51,7 +44,7 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -15,12 +15,6 @@ android {
|
|||||||
versionCode release.versionCode
|
versionCode release.versionCode
|
||||||
versionName release.versionName
|
versionName release.versionName
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
cppFlags "-std=c++11"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
applicationVariants.all { variant ->
|
applicationVariants.all { variant ->
|
||||||
@ -68,12 +62,6 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/library-core_release.kotlin_module'
|
exclude 'META-INF/library-core_release.kotlin_module'
|
||||||
}
|
}
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
path "src/main/cpp/CMakeLists.txt"
|
|
||||||
version "3.10.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*task finalizeBundleDebug(type: Copy) {
|
/*task finalizeBundleDebug(type: Copy) {
|
||||||
@ -143,7 +131,7 @@ dependencies {
|
|||||||
implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true}
|
implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true}
|
||||||
implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update
|
implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update
|
||||||
implementation "com.jaredrummler:colorpicker:1.0.2"
|
implementation "com.jaredrummler:colorpicker:1.0.2"
|
||||||
implementation "com.squareup.okhttp3:okhttp:3.12.2"
|
implementation "com.squareup.okhttp3:okhttp:3.12.0"
|
||||||
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update
|
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update
|
||||||
implementation "com.wdullaer:materialdatetimepicker:4.1.2"
|
implementation "com.wdullaer:materialdatetimepicker:4.1.2"
|
||||||
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
||||||
@ -164,29 +152,6 @@ dependencies {
|
|||||||
implementation project(":nachos")
|
implementation project(":nachos")
|
||||||
//implementation project(":Navigation")
|
//implementation project(":Navigation")
|
||||||
implementation project(":szkolny-font")
|
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.wulkanowy:uonet-request-signer:master-SNAPSHOT'
|
|
||||||
//implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1'
|
|
||||||
|
|
||||||
//implementation "org.redundent:kotlin-xml-builder:1.5.3"
|
|
||||||
|
|
||||||
implementation "io.github.wulkanowy:signer-android:0.1.1"
|
|
||||||
|
|
||||||
implementation "androidx.work:work-runtime-ktx:${versions.work}"
|
|
||||||
|
|
||||||
implementation 'com.hypertrack:hyperlog:0.0.10'
|
|
||||||
|
|
||||||
implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584'
|
|
||||||
|
|
||||||
implementation 'com.github.kuba2k2:Tachyon:551943a6b5'
|
|
||||||
|
|
||||||
implementation "com.squareup.retrofit2:retrofit:${versions.retrofit}"
|
|
||||||
implementation "com.squareup.retrofit2:converter-gson:${versions.retrofit}"
|
|
||||||
|
|
||||||
implementation 'com.github.jetradarmobile:android-snowfall:1.2.0'
|
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
||||||
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.Event { *; }
|
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.Event { *; }
|
||||||
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.EventFull { *; }
|
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.EventFull { *; }
|
||||||
-keep class pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel { *; }
|
|
||||||
-keepclassmembers class pl.szczodrzynski.edziennik.widgets.WidgetConfig { public *; }
|
-keepclassmembers class pl.szczodrzynski.edziennik.widgets.WidgetConfig { public *; }
|
||||||
-keepnames class pl.szczodrzynski.edziennik.WidgetTimetable
|
-keepnames class pl.szczodrzynski.edziennik.WidgetTimetable
|
||||||
-keepnames class pl.szczodrzynski.edziennik.notifications.WidgetNotifications
|
-keepnames class pl.szczodrzynski.edziennik.notifications.WidgetNotifications
|
||||||
@ -41,21 +40,3 @@
|
|||||||
-keep class okhttp3.** { *; }
|
-keep class okhttp3.** { *; }
|
||||||
|
|
||||||
-keep class com.google.android.material.tabs.** {*;}
|
-keep class com.google.android.material.tabs.** {*;}
|
||||||
|
|
||||||
# ServiceLoader support
|
|
||||||
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
|
|
||||||
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
|
|
||||||
|
|
||||||
# Most of volatile fields are updated with AFU and should not be mangled
|
|
||||||
-keepclassmembernames class kotlinx.** {
|
|
||||||
volatile <fields>;
|
|
||||||
}
|
|
||||||
|
|
||||||
-keepclasseswithmembernames class * {
|
|
||||||
native <methods>;
|
|
||||||
}
|
|
||||||
|
|
||||||
-keep class pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing { public final byte[] pleaseStopRightNow(java.lang.String, long); }
|
|
||||||
|
|
||||||
-keepclassmembernames class pl.szczodrzynski.edziennik.data.api.szkolny.request.** { *; }
|
|
||||||
-keepclassmembernames class pl.szczodrzynski.edziennik.data.api.szkolny.response.** { *; }
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF4caf50"
|
|
||||||
android:pathData="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/>
|
|
||||||
</vector>
|
|
@ -1,13 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-25.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M12,8A4,4 0,0 1,16 12A4,4 0,0 1,12 16A4,4 0,0 1,8 12A4,4 0,0 1,12 8M12,10A2,2 0,0 0,10 12A2,2 0,0 0,12 14A2,2 0,0 0,14 12A2,2 0,0 0,12 10M10,22C9.75,22 9.54,21.82 9.5,21.58L9.13,18.93C8.5,18.68 7.96,18.34 7.44,17.94L4.95,18.95C4.73,19.03 4.46,18.95 4.34,18.73L2.34,15.27C2.21,15.05 2.27,14.78 2.46,14.63L4.57,12.97L4.5,12L4.57,11L2.46,9.37C2.27,9.22 2.21,8.95 2.34,8.73L4.34,5.27C4.46,5.05 4.73,4.96 4.95,5.05L7.44,6.05C7.96,5.66 8.5,5.32 9.13,5.07L9.5,2.42C9.54,2.18 9.75,2 10,2H14C14.25,2 14.46,2.18 14.5,2.42L14.87,5.07C15.5,5.32 16.04,5.66 16.56,6.05L19.05,5.05C19.27,4.96 19.54,5.05 19.66,5.27L21.66,8.73C21.79,8.95 21.73,9.22 21.54,9.37L19.43,11L19.5,12L19.43,13L21.54,14.63C21.73,14.78 21.79,15.05 21.66,15.27L19.66,18.73C19.54,18.95 19.27,19.04 19.05,18.95L16.56,17.95C16.04,18.34 15.5,18.68 14.87,18.93L14.5,21.58C14.46,21.82 14.25,22 14,22H10M11.25,4L10.88,6.61C9.68,6.86 8.62,7.5 7.85,8.39L5.44,7.35L4.69,8.65L6.8,10.2C6.4,11.37 6.4,12.64 6.8,13.8L4.68,15.36L5.43,16.66L7.86,15.62C8.63,16.5 9.68,17.14 10.87,17.38L11.24,20H12.76L13.13,17.39C14.32,17.14 15.37,16.5 16.14,15.62L18.57,16.66L19.32,15.36L17.2,13.81C17.6,12.64 17.6,11.37 17.2,10.2L19.31,8.65L18.56,7.35L16.15,8.39C15.38,7.5 14.32,6.86 13.12,6.62L12.75,4H11.25Z"/>
|
|
||||||
</vector>
|
|
@ -15,14 +15,10 @@
|
|||||||
android:theme="@style/SplashTheme"
|
android:theme="@style/SplashTheme"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:ignore="UnusedAttribute">
|
tools:ignore="UnusedAttribute">
|
||||||
<activity
|
|
||||||
android:name=".ui.modules.login.LoginLibrusCaptchaActivity"
|
|
||||||
android:theme="@android:style/Theme.Dialog"
|
|
||||||
android:excludeFromRecents="true"/>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:configChanges="orientation|screenSize"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:theme="@style/SplashTheme">
|
android:theme="@style/SplashTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -33,7 +29,7 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.messages.MessagesComposeActivity"
|
android:name="pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/messages_compose_title"
|
android:label="@string/messages_compose_title"
|
||||||
android:theme="@style/AppTheme.Black" />
|
android:theme="@style/AppTheme.Black" />
|
||||||
@ -43,7 +39,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.login.LoginActivity"
|
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:theme="@style/AppTheme.Light" />
|
android:theme="@style/AppTheme.Light" />
|
||||||
@ -105,23 +101,22 @@
|
|||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/AppTheme.NoDisplay" />
|
android:theme="@style/AppTheme.NoDisplay" />
|
||||||
<activity android:name=".widgets.timetable.LessonDialogActivity"
|
|
||||||
android:configChanges="orientation|keyboardHidden"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:noHistory="true"
|
|
||||||
android:theme="@style/AppTheme.NoDisplay" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.settings.SettingsLicenseActivity"
|
android:name=".ui.modules.settings.SettingsLicenseActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:theme="@style/Base.Theme.AppCompat" />
|
android:theme="@style/Base.Theme.AppCompat" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.webpush.WebPushConfigActivity"
|
android:name=".ui.modules.webpush.WebPushConfigActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:theme="@style/AppTheme.Dark" />
|
android:theme="@style/AppTheme.Dark" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.home.CounterActivity"
|
android:name=".ui.modules.home.CounterActivity"
|
||||||
android:theme="@style/AppTheme.Black" />
|
android:theme="@style/AppTheme.Black" />
|
||||||
@ -174,6 +169,7 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_notifications_info" />
|
android:resource="@xml/widget_notifications_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.luckynumber.WidgetLuckyNumber"
|
android:name=".widgets.luckynumber.WidgetLuckyNumber"
|
||||||
android:label="@string/widget_lucky_number_title">
|
android:label="@string/widget_lucky_number_title">
|
||||||
@ -192,6 +188,7 @@
|
|||||||
<action android:name="android.intent.action.USER_PRESENT" />
|
<action android:name="android.intent.action.USER_PRESENT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".receivers.BootReceiver">
|
<receiver android:name=".receivers.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
@ -199,24 +196,6 @@
|
|||||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".sync.FirebaseBroadcastReceiver"
|
|
||||||
android:exported="true"
|
|
||||||
android:permission="com.google.android.c2dm.permission.SEND">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".receivers.SzkolnyReceiver"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="pl.szczodrzynski.edziennik.SZKOLNY_MAIN" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".sync.MyFirebaseMessagingService"
|
android:name=".sync.MyFirebaseMessagingService"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
@ -235,7 +214,10 @@
|
|||||||
|
|
||||||
<service android:name=".Notifier$GetDataRetryService" />
|
<service android:name=".Notifier$GetDataRetryService" />
|
||||||
|
|
||||||
<service android:name="pl.szczodrzynski.edziennik.data.api.ApiService" />
|
<service
|
||||||
|
android:name=".sync.SyncService"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/sync_service" />
|
||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
@ -31,11 +31,70 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<h3>Wersja 4.0, 2019-jeszcze-nie-wiem-kiedy</h3>
|
<h3>Wersja 3.2.1, 2019-12-10</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>UWAGA. To jest wersja in-development. Wiele funkcji może nie działać prawidłowo (lub wcale), co oznacza tylko że nie zostały jeszcze przeniesione
|
<li>Poprawa synchronizacji w Mobidzienniku.</li>
|
||||||
z wersji 3.x. Proszę o cierpliwość oraz <b>nie udostępnianie</b> tej wersji <u>nikomu</u>.</li>
|
</ul>
|
||||||
<li>Bardzo dużo zmian</li>
|
|
||||||
|
<h3>Wersja 3.2, 2019-10-31</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Możliwość zmiany języka aplikacji.</li>
|
||||||
|
<li>Vulcan: obsługa dziennika edu.lublin.eu.</li>
|
||||||
|
<li>Opcja oznaczenia wszystkich powiadomień jako nieprzeczytane (na stronie głównej).</li>
|
||||||
|
<li>Librus: pokazywanie sali podczas zastępstwa.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Wersja 3.1.1, 2019-10-09</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Librus: poprawiona synchronizacja kategorii i kolorów ocen.</li>
|
||||||
|
<li>Zmieniony kolor dolnego paska w ciemnym motywie.</li>
|
||||||
|
<li>Zaktualizowany licznik czasu lekcji.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Wersja 3.1, 2019-09-29</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Poprawiony interfejs zadań domowych.</li>
|
||||||
|
<li>Librus: wyświetlanie komentarzy ocen.</li>
|
||||||
|
<li>Librus: wyświetlanie nieobecności nauczycieli w Terminarzu.</li>
|
||||||
|
<li>Librus: usprawniona synchronizacja ocen.</li>
|
||||||
|
<li>Poprawki angielskiego tłumaczenia.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Wersja 3.0.3, 2019-09-26</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Librus: poprawka kilku błędów synchronizacji.</li>
|
||||||
|
<li>Vulcan: prawidłowe oznaczanie wiadomości jako przeczytana.</li>
|
||||||
|
<li>Vulcan: poprawiona synchronizacja wiadomości i frekwencji.</li>
|
||||||
|
<li>Vulcan: poprawka błędów logowania.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Wersja 3.0.2, 2019-09-24</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Librus: pobieranie Bieżących ocen opisowych.</li>
|
||||||
|
<li>Poprawki UI: kolor ikon paska statusu w jasnym motywie.</li>
|
||||||
|
<li>Poprawka braku skanera QR do przekazywania powiadomień.</li>
|
||||||
|
<li>Poprawka wyboru koloru i daty własnego wydarzenia, które crashowały aplikację.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Wersja 3.0.1, 2019-09-19</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Librus: Poprawa błędu synchronizacji.</li>
|
||||||
|
<li>Poprawki UI związane z paskiem nawigacji.</li>
|
||||||
|
<li>Mobidziennik: Pobieranie ocen w niektórych przedmiotach.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Wersja 3.0, 2019-09-13</h3>
|
||||||
|
<ul>
|
||||||
|
<li><b>Nowy wygląd i sposób nawigacji</b> w całej aplikacji.</li>
|
||||||
|
<li>Menu nawigacji można teraz otworzyć przyciskiem na <b>dolnym pasku</b>. Pociągnięcie w górę tego paska wyświetla <b>menu kontekstowe</b> dotyczące danego widoku.</li>
|
||||||
|
<li>Założyliśmy serwer Discord! <a href="https://discord.gg/n9e8pWr">https://discord.gg/n9e8pWr</a></li>
|
||||||
|
<br>
|
||||||
|
<li>Librus: poprawka powielonych ogłoszeń szkolnych.</li>
|
||||||
|
<li>Naprawiłem błąd nieskończonej synchronizacji w Vulcanie.</li>
|
||||||
|
<li>Naprawiłem crash launchera przy dodaniu widgetu.</li>
|
||||||
|
<li>Naprawiłem częste crashe związane z widokiem kalendarza.</li>
|
||||||
|
<li>Nowe, ładniejsze (choć trochę) motywy kolorów.</li>
|
||||||
|
<li>Dużo drobnych poprawek UI i działania aplikacji.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!--<i>
|
<!--<i>
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
# For more information about using CMake with Android Studio, read the
|
|
||||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
|
||||||
|
|
||||||
# Sets the minimum version of CMake required to build the native library.
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.4.1)
|
|
||||||
|
|
||||||
# Creates and names a library, sets it as either STATIC
|
|
||||||
# or SHARED, and provides the relative paths to its source code.
|
|
||||||
# You can define multiple libraries, and CMake builds them for you.
|
|
||||||
# Gradle automatically packages shared libraries with your APK.
|
|
||||||
|
|
||||||
add_library( # Sets the name of the library.
|
|
||||||
szkolny-signing
|
|
||||||
|
|
||||||
# Sets the library as a shared library.
|
|
||||||
SHARED
|
|
||||||
|
|
||||||
# Provides a relative path to your source file(s).
|
|
||||||
szkolny-signing.cpp)
|
|
||||||
|
|
||||||
# Searches for a specified prebuilt library and stores the path as a
|
|
||||||
# variable. Because CMake includes system libraries in the search path by
|
|
||||||
# default, you only need to specify the name of the public NDK library
|
|
||||||
# you want to add. CMake verifies that the library exists before
|
|
||||||
# completing its build.
|
|
||||||
|
|
||||||
#[[find_library( # Sets the name of the path variable.
|
|
||||||
log-lib
|
|
||||||
|
|
||||||
# Specifies the name of the NDK library that
|
|
||||||
# you want CMake to locate.
|
|
||||||
log )]]
|
|
||||||
|
|
||||||
# Specifies libraries CMake should link to your target library. You
|
|
||||||
# can link multiple libraries, such as libraries you define in this
|
|
||||||
# build script, prebuilt third-party libraries, or system libraries.
|
|
||||||
|
|
||||||
target_link_libraries( # Specifies the target library.
|
|
||||||
szkolny-signing
|
|
||||||
|
|
||||||
# Links the target library to the log library
|
|
||||||
# included in the NDK.
|
|
||||||
${log-lib} )
|
|
@ -1,520 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <memory.h>
|
|
||||||
#include "aes.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define airport(x) (((x) << 8) | ((x) >> 24))
|
|
||||||
|
|
||||||
#define TRUE 1
|
|
||||||
#define FALSE 0
|
|
||||||
|
|
||||||
static const toys wtf[16][16] = {
|
|
||||||
{0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76},
|
|
||||||
{0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0},
|
|
||||||
{0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15},
|
|
||||||
{0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75},
|
|
||||||
{0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84},
|
|
||||||
{0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF},
|
|
||||||
{0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8},
|
|
||||||
{0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2},
|
|
||||||
{0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73},
|
|
||||||
{0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB},
|
|
||||||
{0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79},
|
|
||||||
{0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08},
|
|
||||||
{0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A},
|
|
||||||
{0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E},
|
|
||||||
{0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF},
|
|
||||||
{0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const toys help_me[256][6] = {
|
|
||||||
{0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x03,0x09,0x0b,0x0d,0x0e},
|
|
||||||
{0x04,0x06,0x12,0x16,0x1a,0x1c},{0x06,0x05,0x1b,0x1d,0x17,0x12},
|
|
||||||
{0x08,0x0c,0x24,0x2c,0x34,0x38},{0x0a,0x0f,0x2d,0x27,0x39,0x36},
|
|
||||||
{0x0c,0x0a,0x36,0x3a,0x2e,0x24},{0x0e,0x09,0x3f,0x31,0x23,0x2a},
|
|
||||||
{0x10,0x18,0x48,0x58,0x68,0x70},{0x12,0x1b,0x41,0x53,0x65,0x7e},
|
|
||||||
{0x14,0x1e,0x5a,0x4e,0x72,0x6c},{0x16,0x1d,0x53,0x45,0x7f,0x62},
|
|
||||||
{0x18,0x14,0x6c,0x74,0x5c,0x48},{0x1a,0x17,0x65,0x7f,0x51,0x46},
|
|
||||||
{0x1c,0x12,0x7e,0x62,0x46,0x54},{0x1e,0x11,0x77,0x69,0x4b,0x5a},
|
|
||||||
{0x20,0x30,0x90,0xb0,0xd0,0xe0},{0x22,0x33,0x99,0xbb,0xdd,0xee},
|
|
||||||
{0x24,0x36,0x82,0xa6,0xca,0xfc},{0x26,0x35,0x8b,0xad,0xc7,0xf2},
|
|
||||||
{0x28,0x3c,0xb4,0x9c,0xe4,0xd8},{0x2a,0x3f,0xbd,0x97,0xe9,0xd6},
|
|
||||||
{0x2c,0x3a,0xa6,0x8a,0xfe,0xc4},{0x2e,0x39,0xaf,0x81,0xf3,0xca},
|
|
||||||
{0x30,0x28,0xd8,0xe8,0xb8,0x90},{0x32,0x2b,0xd1,0xe3,0xb5,0x9e},
|
|
||||||
{0x34,0x2e,0xca,0xfe,0xa2,0x8c},{0x36,0x2d,0xc3,0xf5,0xaf,0x82},
|
|
||||||
{0x38,0x24,0xfc,0xc4,0x8c,0xa8},{0x3a,0x27,0xf5,0xcf,0x81,0xa6},
|
|
||||||
{0x3c,0x22,0xee,0xd2,0x96,0xb4},{0x3e,0x21,0xe7,0xd9,0x9b,0xba},
|
|
||||||
{0x40,0x60,0x3b,0x7b,0xbb,0xdb},{0x42,0x63,0x32,0x70,0xb6,0xd5},
|
|
||||||
{0x44,0x66,0x29,0x6d,0xa1,0xc7},{0x46,0x65,0x20,0x66,0xac,0xc9},
|
|
||||||
{0x48,0x6c,0x1f,0x57,0x8f,0xe3},{0x4a,0x6f,0x16,0x5c,0x82,0xed},
|
|
||||||
{0x4c,0x6a,0x0d,0x41,0x95,0xff},{0x4e,0x69,0x04,0x4a,0x98,0xf1},
|
|
||||||
{0x50,0x78,0x73,0x23,0xd3,0xab},{0x52,0x7b,0x7a,0x28,0xde,0xa5},
|
|
||||||
{0x54,0x7e,0x61,0x35,0xc9,0xb7},{0x56,0x7d,0x68,0x3e,0xc4,0xb9},
|
|
||||||
{0x58,0x74,0x57,0x0f,0xe7,0x93},{0x5a,0x77,0x5e,0x04,0xea,0x9d},
|
|
||||||
{0x5c,0x72,0x45,0x19,0xfd,0x8f},{0x5e,0x71,0x4c,0x12,0xf0,0x81},
|
|
||||||
{0x60,0x50,0xab,0xcb,0x6b,0x3b},{0x62,0x53,0xa2,0xc0,0x66,0x35},
|
|
||||||
{0x64,0x56,0xb9,0xdd,0x71,0x27},{0x66,0x55,0xb0,0xd6,0x7c,0x29},
|
|
||||||
{0x68,0x5c,0x8f,0xe7,0x5f,0x03},{0x6a,0x5f,0x86,0xec,0x52,0x0d},
|
|
||||||
{0x6c,0x5a,0x9d,0xf1,0x45,0x1f},{0x6e,0x59,0x94,0xfa,0x48,0x11},
|
|
||||||
{0x70,0x48,0xe3,0x93,0x03,0x4b},{0x72,0x4b,0xea,0x98,0x0e,0x45},
|
|
||||||
{0x74,0x4e,0xf1,0x85,0x19,0x57},{0x76,0x4d,0xf8,0x8e,0x14,0x59},
|
|
||||||
{0x78,0x44,0xc7,0xbf,0x37,0x73},{0x7a,0x47,0xce,0xb4,0x3a,0x7d},
|
|
||||||
{0x7c,0x42,0xd5,0xa9,0x2d,0x6f},{0x7e,0x41,0xdc,0xa2,0x20,0x61},
|
|
||||||
{0x80,0xc0,0x76,0xf6,0x6d,0xad},{0x82,0xc3,0x7f,0xfd,0x60,0xa3},
|
|
||||||
{0x84,0xc6,0x64,0xe0,0x77,0xb1},{0x86,0xc5,0x6d,0xeb,0x7a,0xbf},
|
|
||||||
{0x88,0xcc,0x52,0xda,0x59,0x95},{0x8a,0xcf,0x5b,0xd1,0x54,0x9b},
|
|
||||||
{0x8c,0xca,0x40,0xcc,0x43,0x89},{0x8e,0xc9,0x49,0xc7,0x4e,0x87},
|
|
||||||
{0x90,0xd8,0x3e,0xae,0x05,0xdd},{0x92,0xdb,0x37,0xa5,0x08,0xd3},
|
|
||||||
{0x94,0xde,0x2c,0xb8,0x1f,0xc1},{0x96,0xdd,0x25,0xb3,0x12,0xcf},
|
|
||||||
{0x98,0xd4,0x1a,0x82,0x31,0xe5},{0x9a,0xd7,0x13,0x89,0x3c,0xeb},
|
|
||||||
{0x9c,0xd2,0x08,0x94,0x2b,0xf9},{0x9e,0xd1,0x01,0x9f,0x26,0xf7},
|
|
||||||
{0xa0,0xf0,0xe6,0x46,0xbd,0x4d},{0xa2,0xf3,0xef,0x4d,0xb0,0x43},
|
|
||||||
{0xa4,0xf6,0xf4,0x50,0xa7,0x51},{0xa6,0xf5,0xfd,0x5b,0xaa,0x5f},
|
|
||||||
{0xa8,0xfc,0xc2,0x6a,0x89,0x75},{0xaa,0xff,0xcb,0x61,0x84,0x7b},
|
|
||||||
{0xac,0xfa,0xd0,0x7c,0x93,0x69},{0xae,0xf9,0xd9,0x77,0x9e,0x67},
|
|
||||||
{0xb0,0xe8,0xae,0x1e,0xd5,0x3d},{0xb2,0xeb,0xa7,0x15,0xd8,0x33},
|
|
||||||
{0xb4,0xee,0xbc,0x08,0xcf,0x21},{0xb6,0xed,0xb5,0x03,0xc2,0x2f},
|
|
||||||
{0xb8,0xe4,0x8a,0x32,0xe1,0x05},{0xba,0xe7,0x83,0x39,0xec,0x0b},
|
|
||||||
{0xbc,0xe2,0x98,0x24,0xfb,0x19},{0xbe,0xe1,0x91,0x2f,0xf6,0x17},
|
|
||||||
{0xc0,0xa0,0x4d,0x8d,0xd6,0x76},{0xc2,0xa3,0x44,0x86,0xdb,0x78},
|
|
||||||
{0xc4,0xa6,0x5f,0x9b,0xcc,0x6a},{0xc6,0xa5,0x56,0x90,0xc1,0x64},
|
|
||||||
{0xc8,0xac,0x69,0xa1,0xe2,0x4e},{0xca,0xaf,0x60,0xaa,0xef,0x40},
|
|
||||||
{0xcc,0xaa,0x7b,0xb7,0xf8,0x52},{0xce,0xa9,0x72,0xbc,0xf5,0x5c},
|
|
||||||
{0xd0,0xb8,0x05,0xd5,0xbe,0x06},{0xd2,0xbb,0x0c,0xde,0xb3,0x08},
|
|
||||||
{0xd4,0xbe,0x17,0xc3,0xa4,0x1a},{0xd6,0xbd,0x1e,0xc8,0xa9,0x14},
|
|
||||||
{0xd8,0xb4,0x21,0xf9,0x8a,0x3e},{0xda,0xb7,0x28,0xf2,0x87,0x30},
|
|
||||||
{0xdc,0xb2,0x33,0xef,0x90,0x22},{0xde,0xb1,0x3a,0xe4,0x9d,0x2c},
|
|
||||||
{0xe0,0x90,0xdd,0x3d,0x06,0x96},{0xe2,0x93,0xd4,0x36,0x0b,0x98},
|
|
||||||
{0xe4,0x96,0xcf,0x2b,0x1c,0x8a},{0xe6,0x95,0xc6,0x20,0x11,0x84},
|
|
||||||
{0xe8,0x9c,0xf9,0x11,0x32,0xae},{0xea,0x9f,0xf0,0x1a,0x3f,0xa0},
|
|
||||||
{0xec,0x9a,0xeb,0x07,0x28,0xb2},{0xee,0x99,0xe2,0x0c,0x25,0xbc},
|
|
||||||
{0xf0,0x88,0x95,0x65,0x6e,0xe6},{0xf2,0x8b,0x9c,0x6e,0x63,0xe8},
|
|
||||||
{0xf4,0x8e,0x87,0x73,0x74,0xfa},{0xf6,0x8d,0x8e,0x78,0x79,0xf4},
|
|
||||||
{0xf8,0x84,0xb1,0x49,0x5a,0xde},{0xfa,0x87,0xb8,0x42,0x57,0xd0},
|
|
||||||
{0xfc,0x82,0xa3,0x5f,0x40,0xc2},{0xfe,0x81,0xaa,0x54,0x4d,0xcc},
|
|
||||||
{0x1b,0x9b,0xec,0xf7,0xda,0x41},{0x19,0x98,0xe5,0xfc,0xd7,0x4f},
|
|
||||||
{0x1f,0x9d,0xfe,0xe1,0xc0,0x5d},{0x1d,0x9e,0xf7,0xea,0xcd,0x53},
|
|
||||||
{0x13,0x97,0xc8,0xdb,0xee,0x79},{0x11,0x94,0xc1,0xd0,0xe3,0x77},
|
|
||||||
{0x17,0x91,0xda,0xcd,0xf4,0x65},{0x15,0x92,0xd3,0xc6,0xf9,0x6b},
|
|
||||||
{0x0b,0x83,0xa4,0xaf,0xb2,0x31},{0x09,0x80,0xad,0xa4,0xbf,0x3f},
|
|
||||||
{0x0f,0x85,0xb6,0xb9,0xa8,0x2d},{0x0d,0x86,0xbf,0xb2,0xa5,0x23},
|
|
||||||
{0x03,0x8f,0x80,0x83,0x86,0x09},{0x01,0x8c,0x89,0x88,0x8b,0x07},
|
|
||||||
{0x07,0x89,0x92,0x95,0x9c,0x15},{0x05,0x8a,0x9b,0x9e,0x91,0x1b},
|
|
||||||
{0x3b,0xab,0x7c,0x47,0x0a,0xa1},{0x39,0xa8,0x75,0x4c,0x07,0xaf},
|
|
||||||
{0x3f,0xad,0x6e,0x51,0x10,0xbd},{0x3d,0xae,0x67,0x5a,0x1d,0xb3},
|
|
||||||
{0x33,0xa7,0x58,0x6b,0x3e,0x99},{0x31,0xa4,0x51,0x60,0x33,0x97},
|
|
||||||
{0x37,0xa1,0x4a,0x7d,0x24,0x85},{0x35,0xa2,0x43,0x76,0x29,0x8b},
|
|
||||||
{0x2b,0xb3,0x34,0x1f,0x62,0xd1},{0x29,0xb0,0x3d,0x14,0x6f,0xdf},
|
|
||||||
{0x2f,0xb5,0x26,0x09,0x78,0xcd},{0x2d,0xb6,0x2f,0x02,0x75,0xc3},
|
|
||||||
{0x23,0xbf,0x10,0x33,0x56,0xe9},{0x21,0xbc,0x19,0x38,0x5b,0xe7},
|
|
||||||
{0x27,0xb9,0x02,0x25,0x4c,0xf5},{0x25,0xba,0x0b,0x2e,0x41,0xfb},
|
|
||||||
{0x5b,0xfb,0xd7,0x8c,0x61,0x9a},{0x59,0xf8,0xde,0x87,0x6c,0x94},
|
|
||||||
{0x5f,0xfd,0xc5,0x9a,0x7b,0x86},{0x5d,0xfe,0xcc,0x91,0x76,0x88},
|
|
||||||
{0x53,0xf7,0xf3,0xa0,0x55,0xa2},{0x51,0xf4,0xfa,0xab,0x58,0xac},
|
|
||||||
{0x57,0xf1,0xe1,0xb6,0x4f,0xbe},{0x55,0xf2,0xe8,0xbd,0x42,0xb0},
|
|
||||||
{0x4b,0xe3,0x9f,0xd4,0x09,0xea},{0x49,0xe0,0x96,0xdf,0x04,0xe4},
|
|
||||||
{0x4f,0xe5,0x8d,0xc2,0x13,0xf6},{0x4d,0xe6,0x84,0xc9,0x1e,0xf8},
|
|
||||||
{0x43,0xef,0xbb,0xf8,0x3d,0xd2},{0x41,0xec,0xb2,0xf3,0x30,0xdc},
|
|
||||||
{0x47,0xe9,0xa9,0xee,0x27,0xce},{0x45,0xea,0xa0,0xe5,0x2a,0xc0},
|
|
||||||
{0x7b,0xcb,0x47,0x3c,0xb1,0x7a},{0x79,0xc8,0x4e,0x37,0xbc,0x74},
|
|
||||||
{0x7f,0xcd,0x55,0x2a,0xab,0x66},{0x7d,0xce,0x5c,0x21,0xa6,0x68},
|
|
||||||
{0x73,0xc7,0x63,0x10,0x85,0x42},{0x71,0xc4,0x6a,0x1b,0x88,0x4c},
|
|
||||||
{0x77,0xc1,0x71,0x06,0x9f,0x5e},{0x75,0xc2,0x78,0x0d,0x92,0x50},
|
|
||||||
{0x6b,0xd3,0x0f,0x64,0xd9,0x0a},{0x69,0xd0,0x06,0x6f,0xd4,0x04},
|
|
||||||
{0x6f,0xd5,0x1d,0x72,0xc3,0x16},{0x6d,0xd6,0x14,0x79,0xce,0x18},
|
|
||||||
{0x63,0xdf,0x2b,0x48,0xed,0x32},{0x61,0xdc,0x22,0x43,0xe0,0x3c},
|
|
||||||
{0x67,0xd9,0x39,0x5e,0xf7,0x2e},{0x65,0xda,0x30,0x55,0xfa,0x20},
|
|
||||||
{0x9b,0x5b,0x9a,0x01,0xb7,0xec},{0x99,0x58,0x93,0x0a,0xba,0xe2},
|
|
||||||
{0x9f,0x5d,0x88,0x17,0xad,0xf0},{0x9d,0x5e,0x81,0x1c,0xa0,0xfe},
|
|
||||||
{0x93,0x57,0xbe,0x2d,0x83,0xd4},{0x91,0x54,0xb7,0x26,0x8e,0xda},
|
|
||||||
{0x97,0x51,0xac,0x3b,0x99,0xc8},{0x95,0x52,0xa5,0x30,0x94,0xc6},
|
|
||||||
{0x8b,0x43,0xd2,0x59,0xdf,0x9c},{0x89,0x40,0xdb,0x52,0xd2,0x92},
|
|
||||||
{0x8f,0x45,0xc0,0x4f,0xc5,0x80},{0x8d,0x46,0xc9,0x44,0xc8,0x8e},
|
|
||||||
{0x83,0x4f,0xf6,0x75,0xeb,0xa4},{0x81,0x4c,0xff,0x7e,0xe6,0xaa},
|
|
||||||
{0x87,0x49,0xe4,0x63,0xf1,0xb8},{0x85,0x4a,0xed,0x68,0xfc,0xb6},
|
|
||||||
{0xbb,0x6b,0x0a,0xb1,0x67,0x0c},{0xb9,0x68,0x03,0xba,0x6a,0x02},
|
|
||||||
{0xbf,0x6d,0x18,0xa7,0x7d,0x10},{0xbd,0x6e,0x11,0xac,0x70,0x1e},
|
|
||||||
{0xb3,0x67,0x2e,0x9d,0x53,0x34},{0xb1,0x64,0x27,0x96,0x5e,0x3a},
|
|
||||||
{0xb7,0x61,0x3c,0x8b,0x49,0x28},{0xb5,0x62,0x35,0x80,0x44,0x26},
|
|
||||||
{0xab,0x73,0x42,0xe9,0x0f,0x7c},{0xa9,0x70,0x4b,0xe2,0x02,0x72},
|
|
||||||
{0xaf,0x75,0x50,0xff,0x15,0x60},{0xad,0x76,0x59,0xf4,0x18,0x6e},
|
|
||||||
{0xa3,0x7f,0x66,0xc5,0x3b,0x44},{0xa1,0x7c,0x6f,0xce,0x36,0x4a},
|
|
||||||
{0xa7,0x79,0x74,0xd3,0x21,0x58},{0xa5,0x7a,0x7d,0xd8,0x2c,0x56},
|
|
||||||
{0xdb,0x3b,0xa1,0x7a,0x0c,0x37},{0xd9,0x38,0xa8,0x71,0x01,0x39},
|
|
||||||
{0xdf,0x3d,0xb3,0x6c,0x16,0x2b},{0xdd,0x3e,0xba,0x67,0x1b,0x25},
|
|
||||||
{0xd3,0x37,0x85,0x56,0x38,0x0f},{0xd1,0x34,0x8c,0x5d,0x35,0x01},
|
|
||||||
{0xd7,0x31,0x97,0x40,0x22,0x13},{0xd5,0x32,0x9e,0x4b,0x2f,0x1d},
|
|
||||||
{0xcb,0x23,0xe9,0x22,0x64,0x47},{0xc9,0x20,0xe0,0x29,0x69,0x49},
|
|
||||||
{0xcf,0x25,0xfb,0x34,0x7e,0x5b},{0xcd,0x26,0xf2,0x3f,0x73,0x55},
|
|
||||||
{0xc3,0x2f,0xcd,0x0e,0x50,0x7f},{0xc1,0x2c,0xc4,0x05,0x5d,0x71},
|
|
||||||
{0xc7,0x29,0xdf,0x18,0x4a,0x63},{0xc5,0x2a,0xd6,0x13,0x47,0x6d},
|
|
||||||
{0xfb,0x0b,0x31,0xca,0xdc,0xd7},{0xf9,0x08,0x38,0xc1,0xd1,0xd9},
|
|
||||||
{0xff,0x0d,0x23,0xdc,0xc6,0xcb},{0xfd,0x0e,0x2a,0xd7,0xcb,0xc5},
|
|
||||||
{0xf3,0x07,0x15,0xe6,0xe8,0xef},{0xf1,0x04,0x1c,0xed,0xe5,0xe1},
|
|
||||||
{0xf7,0x01,0x07,0xf0,0xf2,0xf3},{0xf5,0x02,0x0e,0xfb,0xff,0xfd},
|
|
||||||
{0xeb,0x13,0x79,0x92,0xb4,0xa7},{0xe9,0x10,0x70,0x99,0xb9,0xa9},
|
|
||||||
{0xef,0x15,0x6b,0x84,0xae,0xbb},{0xed,0x16,0x62,0x8f,0xa3,0xb5},
|
|
||||||
{0xe3,0x1f,0x5d,0xbe,0x80,0x9f},{0xe1,0x1c,0x54,0xb5,0x8d,0x91},
|
|
||||||
{0xe7,0x19,0x4f,0xa8,0x9a,0x83},{0xe5,0x1a,0x46,0xa3,0x97,0x8d}
|
|
||||||
};
|
|
||||||
|
|
||||||
void throat(const toys *decide, toys *selection, size_t plane)
|
|
||||||
{
|
|
||||||
size_t idx;
|
|
||||||
|
|
||||||
for (idx = 0; idx < plane; idx++)
|
|
||||||
selection[idx] ^= decide[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
int death(const toys *squirrel, size_t dear, toys *awful, const arrest *wrong, int magic, const toys *fit)
|
|
||||||
{
|
|
||||||
toys supermarket[calculator], software[calculator], bookstore[calculator];
|
|
||||||
int brainwash, jellybean;
|
|
||||||
|
|
||||||
if (dear % calculator != 0)
|
|
||||||
return(FALSE);
|
|
||||||
|
|
||||||
brainwash = dear / calculator;
|
|
||||||
|
|
||||||
memcpy(bookstore, fit, calculator);
|
|
||||||
|
|
||||||
for (jellybean = 0; jellybean < brainwash; jellybean++) {
|
|
||||||
memcpy(supermarket, &squirrel[jellybean * calculator], calculator);
|
|
||||||
throat(bookstore, supermarket, calculator);
|
|
||||||
punishment(supermarket, software, wrong, magic);
|
|
||||||
memcpy(&awful[jellybean * calculator], software, calculator);
|
|
||||||
memcpy(bookstore, software, calculator);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
arrest please(arrest lol)
|
|
||||||
{
|
|
||||||
unsigned int apps;
|
|
||||||
|
|
||||||
apps = (int)wtf[(lol >> 4) & 0x0000000F][lol & 0x0000000F];
|
|
||||||
apps += (int)wtf[(lol >> 12) & 0x0000000F][(lol >> 8) & 0x0000000F] << 8;
|
|
||||||
apps += (int)wtf[(lol >> 20) & 0x0000000F][(lol >> 16) & 0x0000000F] << 16;
|
|
||||||
apps += (int)wtf[(lol >> 28) & 0x0000000F][(lol >> 24) & 0x0000000F] << 24;
|
|
||||||
return(apps);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stoprightnow(const toys *fuckoff, arrest *waste, int roadtrip)
|
|
||||||
{
|
|
||||||
int tour=4,cause,lively,reply;
|
|
||||||
arrest nope,desert[]={0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
|
|
||||||
0x40000000, 0x80000000, 0x1b000000, 0x36000000, 0x6c000000, 0xd8000000,
|
|
||||||
0xab000000, 0x4d000000, 0x9a000000};
|
|
||||||
|
|
||||||
switch (roadtrip) {
|
|
||||||
case 128: cause = 10; lively = 4; break;
|
|
||||||
case 192: cause = 12; lively = 6; break;
|
|
||||||
case 256: cause = 14; lively = 8; break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (reply=0; reply < lively; ++reply) {
|
|
||||||
waste[reply] = ((fuckoff[4 * reply]) << 24) | ((fuckoff[4 * reply + 1]) << 16) |
|
|
||||||
((fuckoff[4 * reply + 2]) << 8) | ((fuckoff[4 * reply + 3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (reply = lively; reply < tour * (cause + 1); ++reply) {
|
|
||||||
nope = waste[reply - 1];
|
|
||||||
if ((reply % lively) == 0)
|
|
||||||
nope = please(airport(nope)) ^ desert[(reply - 1) / lively];
|
|
||||||
else if (lively > 6 && (reply % lively) == 4)
|
|
||||||
nope = please(nope);
|
|
||||||
waste[reply] = waste[reply - lively] ^ nope;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hot(toys rare[][4], const arrest powerful[])
|
|
||||||
{
|
|
||||||
toys interfere[4];
|
|
||||||
|
|
||||||
// memcpy(interfere,&powerful[idx],4); // Not accurate for big endian machines
|
|
||||||
// Subkey 1
|
|
||||||
interfere[0] = powerful[0] >> 24;
|
|
||||||
interfere[1] = powerful[0] >> 16;
|
|
||||||
interfere[2] = powerful[0] >> 8;
|
|
||||||
interfere[3] = powerful[0];
|
|
||||||
rare[0][0] ^= interfere[0];
|
|
||||||
rare[1][0] ^= interfere[1];
|
|
||||||
rare[2][0] ^= interfere[2];
|
|
||||||
rare[3][0] ^= interfere[3];
|
|
||||||
// Subkey 2
|
|
||||||
interfere[0] = powerful[1] >> 24;
|
|
||||||
interfere[1] = powerful[1] >> 16;
|
|
||||||
interfere[2] = powerful[1] >> 8;
|
|
||||||
interfere[3] = powerful[1];
|
|
||||||
rare[0][1] ^= interfere[0];
|
|
||||||
rare[1][1] ^= interfere[1];
|
|
||||||
rare[2][1] ^= interfere[2];
|
|
||||||
rare[3][1] ^= interfere[3];
|
|
||||||
// Subkey 3
|
|
||||||
interfere[0] = powerful[2] >> 24;
|
|
||||||
interfere[1] = powerful[2] >> 16;
|
|
||||||
interfere[2] = powerful[2] >> 8;
|
|
||||||
interfere[3] = powerful[2];
|
|
||||||
rare[0][2] ^= interfere[0];
|
|
||||||
rare[1][2] ^= interfere[1];
|
|
||||||
rare[2][2] ^= interfere[2];
|
|
||||||
rare[3][2] ^= interfere[3];
|
|
||||||
// Subkey 4
|
|
||||||
interfere[0] = powerful[3] >> 24;
|
|
||||||
interfere[1] = powerful[3] >> 16;
|
|
||||||
interfere[2] = powerful[3] >> 8;
|
|
||||||
interfere[3] = powerful[3];
|
|
||||||
rare[0][3] ^= interfere[0];
|
|
||||||
rare[1][3] ^= interfere[1];
|
|
||||||
rare[2][3] ^= interfere[2];
|
|
||||||
rare[3][3] ^= interfere[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
void numerous(toys vigorous[][4])
|
|
||||||
{
|
|
||||||
vigorous[0][0] = wtf[vigorous[0][0] >> 4][vigorous[0][0] & 0x0F];
|
|
||||||
vigorous[0][1] = wtf[vigorous[0][1] >> 4][vigorous[0][1] & 0x0F];
|
|
||||||
vigorous[0][2] = wtf[vigorous[0][2] >> 4][vigorous[0][2] & 0x0F];
|
|
||||||
vigorous[0][3] = wtf[vigorous[0][3] >> 4][vigorous[0][3] & 0x0F];
|
|
||||||
vigorous[1][0] = wtf[vigorous[1][0] >> 4][vigorous[1][0] & 0x0F];
|
|
||||||
vigorous[1][1] = wtf[vigorous[1][1] >> 4][vigorous[1][1] & 0x0F];
|
|
||||||
vigorous[1][2] = wtf[vigorous[1][2] >> 4][vigorous[1][2] & 0x0F];
|
|
||||||
vigorous[1][3] = wtf[vigorous[1][3] >> 4][vigorous[1][3] & 0x0F];
|
|
||||||
vigorous[2][0] = wtf[vigorous[2][0] >> 4][vigorous[2][0] & 0x0F];
|
|
||||||
vigorous[2][1] = wtf[vigorous[2][1] >> 4][vigorous[2][1] & 0x0F];
|
|
||||||
vigorous[2][2] = wtf[vigorous[2][2] >> 4][vigorous[2][2] & 0x0F];
|
|
||||||
vigorous[2][3] = wtf[vigorous[2][3] >> 4][vigorous[2][3] & 0x0F];
|
|
||||||
vigorous[3][0] = wtf[vigorous[3][0] >> 4][vigorous[3][0] & 0x0F];
|
|
||||||
vigorous[3][1] = wtf[vigorous[3][1] >> 4][vigorous[3][1] & 0x0F];
|
|
||||||
vigorous[3][2] = wtf[vigorous[3][2] >> 4][vigorous[3][2] & 0x0F];
|
|
||||||
vigorous[3][3] = wtf[vigorous[3][3] >> 4][vigorous[3][3] & 0x0F];
|
|
||||||
}
|
|
||||||
|
|
||||||
void crowded(toys chalk[][4])
|
|
||||||
{
|
|
||||||
int t;
|
|
||||||
|
|
||||||
// Shift left by 1
|
|
||||||
t = chalk[1][0];
|
|
||||||
chalk[1][0] = chalk[1][1];
|
|
||||||
chalk[1][1] = chalk[1][2];
|
|
||||||
chalk[1][2] = chalk[1][3];
|
|
||||||
chalk[1][3] = t;
|
|
||||||
// Shift left by 2
|
|
||||||
t = chalk[2][0];
|
|
||||||
chalk[2][0] = chalk[2][2];
|
|
||||||
chalk[2][2] = t;
|
|
||||||
t = chalk[2][1];
|
|
||||||
chalk[2][1] = chalk[2][3];
|
|
||||||
chalk[2][3] = t;
|
|
||||||
// Shift left by 3
|
|
||||||
t = chalk[3][0];
|
|
||||||
chalk[3][0] = chalk[3][3];
|
|
||||||
chalk[3][3] = chalk[3][2];
|
|
||||||
chalk[3][2] = chalk[3][1];
|
|
||||||
chalk[3][1] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scale(toys oh_no[][4])
|
|
||||||
{
|
|
||||||
toys idk[4];
|
|
||||||
|
|
||||||
// Column 1
|
|
||||||
idk[0] = oh_no[0][0];
|
|
||||||
idk[1] = oh_no[1][0];
|
|
||||||
idk[2] = oh_no[2][0];
|
|
||||||
idk[3] = oh_no[3][0];
|
|
||||||
oh_no[0][0] = help_me[idk[0]][0];
|
|
||||||
oh_no[0][0] ^= help_me[idk[1]][1];
|
|
||||||
oh_no[0][0] ^= idk[2];
|
|
||||||
oh_no[0][0] ^= idk[3];
|
|
||||||
oh_no[1][0] = idk[0];
|
|
||||||
oh_no[1][0] ^= help_me[idk[1]][0];
|
|
||||||
oh_no[1][0] ^= help_me[idk[2]][1];
|
|
||||||
oh_no[1][0] ^= idk[3];
|
|
||||||
oh_no[2][0] = idk[0];
|
|
||||||
oh_no[2][0] ^= idk[1];
|
|
||||||
oh_no[2][0] ^= help_me[idk[2]][0];
|
|
||||||
oh_no[2][0] ^= help_me[idk[3]][1];
|
|
||||||
oh_no[3][0] = help_me[idk[0]][1];
|
|
||||||
oh_no[3][0] ^= idk[1];
|
|
||||||
oh_no[3][0] ^= idk[2];
|
|
||||||
oh_no[3][0] ^= help_me[idk[3]][0];
|
|
||||||
// Column 2
|
|
||||||
idk[0] = oh_no[0][1];
|
|
||||||
idk[1] = oh_no[1][1];
|
|
||||||
idk[2] = oh_no[2][1];
|
|
||||||
idk[3] = oh_no[3][1];
|
|
||||||
oh_no[0][1] = help_me[idk[0]][0];
|
|
||||||
oh_no[0][1] ^= help_me[idk[1]][1];
|
|
||||||
oh_no[0][1] ^= idk[2];
|
|
||||||
oh_no[0][1] ^= idk[3];
|
|
||||||
oh_no[1][1] = idk[0];
|
|
||||||
oh_no[1][1] ^= help_me[idk[1]][0];
|
|
||||||
oh_no[1][1] ^= help_me[idk[2]][1];
|
|
||||||
oh_no[1][1] ^= idk[3];
|
|
||||||
oh_no[2][1] = idk[0];
|
|
||||||
oh_no[2][1] ^= idk[1];
|
|
||||||
oh_no[2][1] ^= help_me[idk[2]][0];
|
|
||||||
oh_no[2][1] ^= help_me[idk[3]][1];
|
|
||||||
oh_no[3][1] = help_me[idk[0]][1];
|
|
||||||
oh_no[3][1] ^= idk[1];
|
|
||||||
oh_no[3][1] ^= idk[2];
|
|
||||||
oh_no[3][1] ^= help_me[idk[3]][0];
|
|
||||||
// Column 3
|
|
||||||
idk[0] = oh_no[0][2];
|
|
||||||
idk[1] = oh_no[1][2];
|
|
||||||
idk[2] = oh_no[2][2];
|
|
||||||
idk[3] = oh_no[3][2];
|
|
||||||
oh_no[0][2] = help_me[idk[0]][0];
|
|
||||||
oh_no[0][2] ^= help_me[idk[1]][1];
|
|
||||||
oh_no[0][2] ^= idk[2];
|
|
||||||
oh_no[0][2] ^= idk[3];
|
|
||||||
oh_no[1][2] = idk[0];
|
|
||||||
oh_no[1][2] ^= help_me[idk[1]][0];
|
|
||||||
oh_no[1][2] ^= help_me[idk[2]][1];
|
|
||||||
oh_no[1][2] ^= idk[3];
|
|
||||||
oh_no[2][2] = idk[0];
|
|
||||||
oh_no[2][2] ^= idk[1];
|
|
||||||
oh_no[2][2] ^= help_me[idk[2]][0];
|
|
||||||
oh_no[2][2] ^= help_me[idk[3]][1];
|
|
||||||
oh_no[3][2] = help_me[idk[0]][1];
|
|
||||||
oh_no[3][2] ^= idk[1];
|
|
||||||
oh_no[3][2] ^= idk[2];
|
|
||||||
oh_no[3][2] ^= help_me[idk[3]][0];
|
|
||||||
// Column 4
|
|
||||||
idk[0] = oh_no[0][3];
|
|
||||||
idk[1] = oh_no[1][3];
|
|
||||||
idk[2] = oh_no[2][3];
|
|
||||||
idk[3] = oh_no[3][3];
|
|
||||||
oh_no[0][3] = help_me[idk[0]][0];
|
|
||||||
oh_no[0][3] ^= help_me[idk[1]][1];
|
|
||||||
oh_no[0][3] ^= idk[2];
|
|
||||||
oh_no[0][3] ^= idk[3];
|
|
||||||
oh_no[1][3] = idk[0];
|
|
||||||
oh_no[1][3] ^= help_me[idk[1]][0];
|
|
||||||
oh_no[1][3] ^= help_me[idk[2]][1];
|
|
||||||
oh_no[1][3] ^= idk[3];
|
|
||||||
oh_no[2][3] = idk[0];
|
|
||||||
oh_no[2][3] ^= idk[1];
|
|
||||||
oh_no[2][3] ^= help_me[idk[2]][0];
|
|
||||||
oh_no[2][3] ^= help_me[idk[3]][1];
|
|
||||||
oh_no[3][3] = help_me[idk[0]][1];
|
|
||||||
oh_no[3][3] ^= idk[1];
|
|
||||||
oh_no[3][3] ^= idk[2];
|
|
||||||
oh_no[3][3] ^= help_me[idk[3]][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void punishment(const toys friends[], toys number[], const arrest wish[], int hang)
|
|
||||||
{
|
|
||||||
toys burst[4][4];
|
|
||||||
|
|
||||||
burst[0][0] = friends[0];
|
|
||||||
burst[1][0] = friends[1];
|
|
||||||
burst[2][0] = friends[2];
|
|
||||||
burst[3][0] = friends[3];
|
|
||||||
burst[0][1] = friends[4];
|
|
||||||
burst[1][1] = friends[5];
|
|
||||||
burst[2][1] = friends[6];
|
|
||||||
burst[3][1] = friends[7];
|
|
||||||
burst[0][2] = friends[8];
|
|
||||||
burst[1][2] = friends[9];
|
|
||||||
burst[2][2] = friends[10];
|
|
||||||
burst[3][2] = friends[11];
|
|
||||||
burst[0][3] = friends[12];
|
|
||||||
burst[1][3] = friends[13];
|
|
||||||
burst[2][3] = friends[14];
|
|
||||||
burst[3][3] = friends[15];
|
|
||||||
|
|
||||||
hot(burst, &wish[0]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[4]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[8]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[12]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[16]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[20]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[24]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[28]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[32]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[36]);
|
|
||||||
if (hang != 128) {
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[40]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[44]);
|
|
||||||
if (hang != 192) {
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[48]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
scale(burst);
|
|
||||||
hot(burst, &wish[52]);
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
hot(burst, &wish[56]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
hot(burst, &wish[48]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
numerous(burst);
|
|
||||||
crowded(burst);
|
|
||||||
hot(burst, &wish[40]);
|
|
||||||
}
|
|
||||||
|
|
||||||
number[0] = burst[0][0];
|
|
||||||
number[1] = burst[1][0];
|
|
||||||
number[2] = burst[2][0];
|
|
||||||
number[3] = burst[3][0];
|
|
||||||
number[4] = burst[0][1];
|
|
||||||
number[5] = burst[1][1];
|
|
||||||
number[6] = burst[2][1];
|
|
||||||
number[7] = burst[3][1];
|
|
||||||
number[8] = burst[0][2];
|
|
||||||
number[9] = burst[1][2];
|
|
||||||
number[10] = burst[2][2];
|
|
||||||
number[11] = burst[3][2];
|
|
||||||
number[12] = burst[0][3];
|
|
||||||
number[13] = burst[1][3];
|
|
||||||
number[14] = burst[2][3];
|
|
||||||
number[15] = burst[3][3];
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
#ifndef AES_H
|
|
||||||
#define AES_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define calculator 16
|
|
||||||
|
|
||||||
typedef unsigned char toys;
|
|
||||||
typedef unsigned int arrest;
|
|
||||||
|
|
||||||
void stoprightnow(const toys *fuckoff,
|
|
||||||
arrest *waste,
|
|
||||||
int roadtrip);
|
|
||||||
|
|
||||||
void punishment(const toys *friends,
|
|
||||||
toys *number,
|
|
||||||
const arrest *wish,
|
|
||||||
int hang);
|
|
||||||
|
|
||||||
int death(const toys *squirrel,
|
|
||||||
size_t dear,
|
|
||||||
toys *awful,
|
|
||||||
const arrest *wrong,
|
|
||||||
int magic,
|
|
||||||
const toys *fit);
|
|
||||||
|
|
||||||
#endif // AES_H
|
|
@ -1,55 +0,0 @@
|
|||||||
#include "jni.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
||||||
|
|
||||||
char *kill_me(const char *coil, size_t room) {
|
|
||||||
int canvas = 0;
|
|
||||||
size_t irritating;
|
|
||||||
int exchange = 0;
|
|
||||||
char *untidy = NULL;
|
|
||||||
char *excellent = NULL;
|
|
||||||
int sincere = 0;
|
|
||||||
char development[4];
|
|
||||||
int trade = 0;
|
|
||||||
irritating = room / 3;
|
|
||||||
exchange = room % 3;
|
|
||||||
if (exchange > 0) {
|
|
||||||
irritating += 1;
|
|
||||||
}
|
|
||||||
irritating = irritating * 4 + 1;
|
|
||||||
untidy = (char *) malloc(irritating);
|
|
||||||
|
|
||||||
if (untidy == NULL) {
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
memset(untidy, 0, irritating);
|
|
||||||
excellent = untidy;
|
|
||||||
while (sincere < room) {
|
|
||||||
exchange = 0;
|
|
||||||
canvas = 0;
|
|
||||||
memset(development, '\0', 4);
|
|
||||||
while (exchange < 3) {
|
|
||||||
if (sincere >= room) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
canvas = ((canvas << 8) | (coil[sincere] & 0xFF));
|
|
||||||
sincere++;
|
|
||||||
exchange++;
|
|
||||||
}
|
|
||||||
canvas = (canvas << ((3 - exchange) * 8));
|
|
||||||
for (trade = 0; trade < 4; trade++) {
|
|
||||||
if (exchange < trade) {
|
|
||||||
development[trade] = 0x40;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
development[trade] = (canvas >> ((3 - trade) * 6)) & 0x3F;
|
|
||||||
}
|
|
||||||
*excellent = base[development[trade]];
|
|
||||||
excellent++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*excellent = '\0';
|
|
||||||
return untidy;
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
#include <jni.h>
|
|
||||||
#include <string>
|
|
||||||
#include "aes.c"
|
|
||||||
#include "aes.h"
|
|
||||||
#include "base64.cpp"
|
|
||||||
|
|
||||||
#define overrated (2*1024*1024)
|
|
||||||
#define teeth 256
|
|
||||||
|
|
||||||
/*secret password - removed for source code publication*/
|
|
||||||
static toys AES_IV[16] = {
|
|
||||||
0x97, 0x0e, 0x93, 0xd3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
||||||
|
|
||||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
|
||||||
Java_pl_szczodrzynski_edziennik_data_api_szkolny_interceptor_Signing_iLoveApple(
|
|
||||||
JNIEnv* nut,
|
|
||||||
jobject guitar,
|
|
||||||
jbyteArray school,
|
|
||||||
jstring history,
|
|
||||||
jlong brush) {
|
|
||||||
|
|
||||||
unsigned int chickens = (unsigned int) (nut->GetArrayLength(school));
|
|
||||||
if (chickens <= 0 || chickens >= overrated) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *leg = (unsigned char*) nut->GetByteArrayElements(school, NULL);
|
|
||||||
if (!leg) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
jclass partner = nut->FindClass("pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing");
|
|
||||||
jmethodID example = nut->GetMethodID(partner, "pleaseStopRightNow", "(Ljava/lang/String;J)[B");
|
|
||||||
jobject bait = nut->CallObjectMethod(guitar, example, history, brush);
|
|
||||||
unsigned char* lick = (unsigned char*) nut->GetByteArrayElements((jbyteArray)bait, NULL);
|
|
||||||
|
|
||||||
unsigned int cruel = chickens % calculator;
|
|
||||||
unsigned int snake = calculator - cruel;
|
|
||||||
unsigned int baseball = chickens + snake;
|
|
||||||
|
|
||||||
unsigned char* rain = agony(chickens, lick, leg);
|
|
||||||
char* dress = kill_me((char *) rain, baseball);
|
|
||||||
free(rain);
|
|
||||||
|
|
||||||
return nut->NewStringUTF(dress);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat) {
|
|
||||||
unsigned int young = laugh % calculator;
|
|
||||||
unsigned int thirsty = calculator - young;
|
|
||||||
unsigned int ants = laugh + thirsty;
|
|
||||||
|
|
||||||
unsigned char *shirt = (unsigned char *) malloc(ants);
|
|
||||||
memset(shirt, 0, ants);
|
|
||||||
memcpy(shirt, heat, laugh);
|
|
||||||
if (thirsty > 0) {
|
|
||||||
memset(shirt + laugh, (unsigned char) thirsty, thirsty);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char * crazy = (unsigned char*) malloc(ants);
|
|
||||||
if (!crazy) {
|
|
||||||
free(shirt);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(crazy, ants, 0);
|
|
||||||
|
|
||||||
unsigned int lamp[calculator * 4] = {0 };
|
|
||||||
stoprightnow(box, lamp, teeth);
|
|
||||||
|
|
||||||
death(shirt, ants, crazy, lamp, teeth,
|
|
||||||
AES_IV);
|
|
||||||
|
|
||||||
free(shirt);
|
|
||||||
|
|
||||||
return crazy;
|
|
||||||
}
|
|
@ -18,14 +18,9 @@ import android.os.Handler;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
import com.evernote.android.job.JobManager;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
|
||||||
import androidx.work.Configuration;
|
|
||||||
|
|
||||||
import com.chuckerteam.chucker.api.ChuckerCollector;
|
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor;
|
|
||||||
import com.chuckerteam.chucker.api.RetentionManager;
|
|
||||||
import com.google.android.gms.security.ProviderInstaller;
|
import com.google.android.gms.security.ProviderInstaller;
|
||||||
import com.google.firebase.FirebaseApp;
|
import com.google.firebase.FirebaseApp;
|
||||||
import com.google.firebase.FirebaseOptions;
|
import com.google.firebase.FirebaseOptions;
|
||||||
@ -35,7 +30,6 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.hypertrack.hyperlog.HyperLog;
|
|
||||||
import com.mikepenz.iconics.Iconics;
|
import com.mikepenz.iconics.Iconics;
|
||||||
import com.mikepenz.iconics.IconicsColor;
|
import com.mikepenz.iconics.IconicsColor;
|
||||||
import com.mikepenz.iconics.IconicsDrawable;
|
import com.mikepenz.iconics.IconicsDrawable;
|
||||||
@ -58,6 +52,8 @@ import javax.net.ssl.TrustManager;
|
|||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
import cat.ereza.customactivityoncrash.config.CaocConfig;
|
import cat.ereza.customactivityoncrash.config.CaocConfig;
|
||||||
import im.wangchao.mhttp.MHttp;
|
import im.wangchao.mhttp.MHttp;
|
||||||
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar;
|
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar;
|
||||||
@ -67,37 +63,34 @@ import me.leolin.shortcutbadger.ShortcutBadger;
|
|||||||
import okhttp3.ConnectionSpec;
|
import okhttp3.ConnectionSpec;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.TlsVersion;
|
import okhttp3.TlsVersion;
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing;
|
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity;
|
||||||
import pl.szczodrzynski.edziennik.config.Config;
|
import pl.szczodrzynski.edziennik.data.api.Edziennik;
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Iuczniowie;
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Librus;
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Mobidziennik;
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Vulcan;
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb;
|
import pl.szczodrzynski.edziennik.data.db.AppDb;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog;
|
import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.AppConfig;
|
||||||
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
||||||
import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
|
import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncWorker;
|
import pl.szczodrzynski.edziennik.receivers.JobsCreator;
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity;
|
import pl.szczodrzynski.edziennik.sync.SyncJob;
|
||||||
import pl.szczodrzynski.edziennik.utils.DebugLogFormat;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.PermissionChecker;
|
import pl.szczodrzynski.edziennik.utils.PermissionChecker;
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
import pl.szczodrzynski.edziennik.utils.Utils;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.AppConfig;
|
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
||||||
|
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_VULCAN;
|
||||||
|
|
||||||
public class App extends androidx.multidex.MultiDexApplication implements Configuration.Provider {
|
public class App extends androidx.multidex.MultiDexApplication {
|
||||||
private static final String TAG = "App";
|
private static final String TAG = "App";
|
||||||
public static int profileId = -1;
|
public static int profileId = -1;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
@Override
|
|
||||||
public Configuration getWorkManagerConfiguration() {
|
|
||||||
return new Configuration.Builder()
|
|
||||||
.setMinimumLoggingLevel(Log.VERBOSE)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static final int REQUEST_TIMEOUT = 10 * 1000;
|
public static final int REQUEST_TIMEOUT = 10 * 1000;
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
@ -134,6 +127,12 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
public PersistentCookieJar cookieJar;
|
public PersistentCookieJar cookieJar;
|
||||||
public OkHttpClient http;
|
public OkHttpClient http;
|
||||||
public OkHttpClient httpLazy;
|
public OkHttpClient httpLazy;
|
||||||
|
//public Jakdojade apiJakdojade;
|
||||||
|
public Edziennik apiEdziennik;
|
||||||
|
public Mobidziennik apiMobidziennik;
|
||||||
|
public Iuczniowie apiIuczniowie;
|
||||||
|
public Librus apiLibrus;
|
||||||
|
public Vulcan apiVulcan;
|
||||||
|
|
||||||
public SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE
|
public SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE
|
||||||
public AppConfig appConfig; // APPCONFIG: common for all profiles
|
public AppConfig appConfig; // APPCONFIG: common for all profiles
|
||||||
@ -143,11 +142,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
//public Register register; // REGISTER for current profile, read from registerStore
|
//public Register register; // REGISTER for current profile, read from registerStore
|
||||||
|
|
||||||
public ProfileFull profile;
|
public ProfileFull profile;
|
||||||
public Config config;
|
|
||||||
private static Config mConfig;
|
|
||||||
public static Config getConfig() {
|
|
||||||
return mConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// other stuff
|
// other stuff
|
||||||
public Gson gson;
|
public Gson gson;
|
||||||
@ -196,10 +190,12 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
db = AppDb.getDatabase(this);
|
db = AppDb.getDatabase(this);
|
||||||
gson = new Gson();
|
gson = new Gson();
|
||||||
networkUtils = new NetworkUtils(this);
|
networkUtils = new NetworkUtils(this);
|
||||||
|
apiEdziennik = new Edziennik(this);
|
||||||
config = new Config(db);
|
//apiJakdojade = new Jakdojade(this);
|
||||||
config.migrate(this);
|
apiMobidziennik = new Mobidziennik(this);
|
||||||
mConfig = config;
|
apiIuczniowie = new Iuczniowie(this);
|
||||||
|
apiLibrus = new Librus(this);
|
||||||
|
apiVulcan = new Vulcan(this);
|
||||||
|
|
||||||
Iconics.init(getApplicationContext());
|
Iconics.init(getApplicationContext());
|
||||||
Iconics.registerFont(SzkolnyFont.INSTANCE);
|
Iconics.registerFont(SzkolnyFont.INSTANCE);
|
||||||
@ -211,35 +207,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(this));
|
cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(this));
|
||||||
|
|
||||||
appSharedPrefs = getSharedPreferences(getString(R.string.preference_file_global), Context.MODE_PRIVATE);
|
|
||||||
|
|
||||||
loadConfig();
|
|
||||||
|
|
||||||
Signing.INSTANCE.getCert(this);
|
|
||||||
|
|
||||||
Themes.INSTANCE.setThemeInt(config.getUi().getTheme());
|
|
||||||
|
|
||||||
try {
|
|
||||||
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
|
|
||||||
for (Signature signature: packageInfo.signatures) {
|
|
||||||
byte[] signatureBytes = signature.toByteArray();
|
|
||||||
MessageDigest md = MessageDigest.getInstance("SHA");
|
|
||||||
md.update(signatureBytes);
|
|
||||||
this.signature = Base64.encodeToString(md.digest(), Base64.NO_WRAP);
|
|
||||||
//Log.d(TAG, "Signature is "+this.signature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("f054761fbdb6a238".equals(deviceId) || BuildConfig.DEBUG) {
|
|
||||||
devMode = true;
|
|
||||||
}
|
|
||||||
else if (config.getDevModePassword() != null) {
|
|
||||||
checkDevModePassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder()
|
OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder()
|
||||||
.cache(null)
|
.cache(null)
|
||||||
.followRedirects(true)
|
.followRedirects(true)
|
||||||
@ -287,16 +254,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App.devMode || BuildConfig.DEBUG) {
|
|
||||||
HyperLog.initialize(this);
|
|
||||||
HyperLog.setLogLevel(Log.VERBOSE);
|
|
||||||
HyperLog.setLogFormat(new DebugLogFormat(this));
|
|
||||||
|
|
||||||
ChuckerCollector chuckerCollector = new ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR);
|
|
||||||
ChuckerInterceptor chuckerInterceptor = new ChuckerInterceptor(this, chuckerCollector);
|
|
||||||
httpBuilder.addInterceptor(chuckerInterceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
http = httpBuilder.build();
|
http = httpBuilder.build();
|
||||||
httpLazy = http.newBuilder().followRedirects(false).followSslRedirects(false).build();
|
httpLazy = http.newBuilder().followRedirects(false).followSslRedirects(false).build();
|
||||||
|
|
||||||
@ -305,13 +262,41 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
//register = new Register(mContext);
|
//register = new Register(mContext);
|
||||||
|
|
||||||
|
appSharedPrefs = getSharedPreferences(getString(R.string.preference_file_global), Context.MODE_PRIVATE);
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
|
||||||
|
Themes.INSTANCE.setThemeInt(appConfig.appTheme);
|
||||||
|
|
||||||
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
||||||
|
|
||||||
if (config.getSync().getEnabled()) {
|
try {
|
||||||
SyncWorker.Companion.scheduleNext(this, false);
|
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
|
||||||
|
for (Signature signature: packageInfo.signatures) {
|
||||||
|
byte[] signatureBytes = signature.toByteArray();
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA");
|
||||||
|
md.update(signatureBytes);
|
||||||
|
this.signature = Base64.encodeToString(md.digest(), Base64.DEFAULT);
|
||||||
|
//Log.d(TAG, "Signature is "+this.signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("f054761fbdb6a238".equals(deviceId)) {
|
||||||
|
devMode = true;
|
||||||
|
}
|
||||||
|
else if (appConfig.devModePassword != null) {
|
||||||
|
checkDevModePassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
JobManager.create(this).addJobCreator(new JobsCreator());
|
||||||
|
if (appConfig.registerSyncEnabled) {
|
||||||
|
SyncJob.schedule(this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SyncWorker.Companion.cancelNext(this);
|
SyncJob.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
db.metadataDao().countUnseen().observeForever(count -> {
|
db.metadataDao().countUnseen().observeForever(count -> {
|
||||||
@ -371,10 +356,11 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutTimetable, shortcutAgenda, shortcutGrades, shortcutHomework, shortcutMessages));
|
shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutTimetable, shortcutAgenda, shortcutGrades, shortcutHomework, shortcutMessages));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getAppInstalledTime() == 0) {
|
if (appConfig.appInstalledTime == 0) {
|
||||||
try {
|
try {
|
||||||
config.setAppInstalledTime(getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime);
|
appConfig.appInstalledTime = getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime;
|
||||||
config.setAppRateSnackbarTime(config.getAppInstalledTime() + 7 * 24 * 60 * 60 * 1000);
|
appConfig.appRateSnackbarTime = appConfig.appInstalledTime + 7 * 24 * 60 * 60 * 1000;
|
||||||
|
saveConfig("appInstalledTime", "appRateSnackbarTime");
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -414,20 +400,20 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
FirebaseApp pushMobidziennikApp = FirebaseApp.initializeApp(
|
FirebaseApp pushMobidziennikApp = FirebaseApp.initializeApp(
|
||||||
this,
|
this,
|
||||||
new FirebaseOptions.Builder()
|
new FirebaseOptions.Builder()
|
||||||
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
|
.setApplicationId("1:1029629079999:android:58bb378dab031f42")
|
||||||
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
|
.setGcmSenderId("1029629079999")
|
||||||
.build(),
|
.build(),
|
||||||
"Mobidziennik2"
|
"Mobidziennik"
|
||||||
);
|
);
|
||||||
|
|
||||||
FirebaseApp pushLibrusApp = FirebaseApp.initializeApp(
|
/*FirebaseApp pushLibrusApp = FirebaseApp.initializeApp(
|
||||||
this,
|
this,
|
||||||
new FirebaseOptions.Builder()
|
new FirebaseOptions.Builder()
|
||||||
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
||||||
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
||||||
.build(),
|
.build(),
|
||||||
"Librus"
|
"Librus"
|
||||||
);
|
);*/
|
||||||
|
|
||||||
FirebaseApp pushVulcanApp = FirebaseApp.initializeApp(
|
FirebaseApp pushVulcanApp = FirebaseApp.initializeApp(
|
||||||
this,
|
this,
|
||||||
@ -442,23 +428,23 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
final long startTime = System.currentTimeMillis();
|
final long startTime = System.currentTimeMillis();
|
||||||
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
||||||
Log.d(TAG, "Token for App is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId()+". Time is "+(System.currentTimeMillis() - startTime));
|
Log.d(TAG, "Token for App is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId()+". Time is "+(System.currentTimeMillis() - startTime));
|
||||||
config.getSync().setTokenApp(instanceIdResult.getToken());
|
appConfig.fcmToken = instanceIdResult.getToken();
|
||||||
});
|
});
|
||||||
/*FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
||||||
Log.d(TAG, "Token for Mobidziennik is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
Log.d(TAG, "Token for Mobidziennik is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
||||||
appConfig.fcmTokens.put(LOGIN_TYPE_MOBIDZIENNIK, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
appConfig.fcmTokens.put(LOGIN_TYPE_MOBIDZIENNIK, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
||||||
});
|
});
|
||||||
FirebaseInstanceId.getInstance(pushLibrusApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
/*FirebaseInstanceId.getInstance(pushLibrusApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
||||||
Log.d(TAG, "Token for Librus is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
Log.d(TAG, "Token for Librus is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
||||||
appConfig.fcmTokens.put(LOGIN_TYPE_LIBRUS, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
appConfig.fcmTokens.put(LOGIN_TYPE_LIBRUS, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
||||||
});
|
});*/
|
||||||
FirebaseInstanceId.getInstance(pushVulcanApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
FirebaseInstanceId.getInstance(pushVulcanApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
||||||
Log.d(TAG, "Token for Vulcan is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
Log.d(TAG, "Token for Vulcan is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
||||||
Pair<String, List<Integer>> pair = appConfig.fcmTokens.get(LOGIN_TYPE_VULCAN);
|
Pair<String, List<Integer>> pair = appConfig.fcmTokens.get(LOGIN_TYPE_VULCAN);
|
||||||
if (pair == null || pair.first == null || !pair.first.equals(instanceIdResult.getToken())) {
|
if (pair == null || pair.first == null || !pair.first.equals(instanceIdResult.getToken())) {
|
||||||
appConfig.fcmTokens.put(LOGIN_TYPE_VULCAN, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
appConfig.fcmTokens.put(LOGIN_TYPE_VULCAN, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
||||||
}
|
}
|
||||||
});*/
|
});
|
||||||
|
|
||||||
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(getPackageName());
|
FirebaseMessaging.getInstance().subscribeToTopic(getPackageName());
|
||||||
@ -521,8 +507,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Log.w(TAG, "Should remove app.appConfig."+fieldName);
|
appSharedPrefs.edit().remove("app.appConfig."+fieldName).apply();
|
||||||
//appSharedPrefs.edit().remove("app.appConfig."+fieldName).apply(); TODO migration
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -594,11 +579,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
//appSharedPrefs.edit().putString("config", gson.toJson(appConfig)).apply();
|
//appSharedPrefs.edit().putString("config", gson.toJson(appConfig)).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void profileSave() {
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
db.profileDao().add(profile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void profileSaveAsync() {
|
public void profileSaveAsync() {
|
||||||
AsyncTask.execute(() -> {
|
AsyncTask.execute(() -> {
|
||||||
@ -619,6 +600,14 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
db.profileDao().add(profileFull);
|
db.profileDao().add(profileFull);
|
||||||
db.loginStoreDao().add(profileFull);
|
db.loginStoreDao().add(profileFull);
|
||||||
}
|
}
|
||||||
|
public void profileSaveFull(Profile profile, LoginStore loginStore) {
|
||||||
|
db.profileDao().add(profile);
|
||||||
|
db.loginStoreDao().add(loginStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileFull profileGetOrNull(int id) {
|
||||||
|
return db.profileDao().getByIdNow(id);
|
||||||
|
}
|
||||||
|
|
||||||
public void profileLoadById(int id) {
|
public void profileLoadById(int id) {
|
||||||
profileLoadById(id, false);
|
profileLoadById(id, false);
|
||||||
@ -632,7 +621,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
if (profile == null || profile.getId() != id) {
|
if (profile == null || profile.getId() != id) {
|
||||||
profile = db.profileDao().getFullByIdNow(id);
|
profile = db.profileDao().getByIdNow(id);
|
||||||
/*if (profile == null) {
|
/*if (profile == null) {
|
||||||
profileLoadById(id);
|
profileLoadById(id);
|
||||||
return;
|
return;
|
||||||
@ -641,7 +630,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1);
|
MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1);
|
||||||
profileId = profile.getId();
|
profileId = profile.getId();
|
||||||
appSharedPrefs.edit().putInt("current_profile_id", profile.getId()).apply();
|
appSharedPrefs.edit().putInt("current_profile_id", profile.getId()).apply();
|
||||||
config.setProfile(profileId);
|
|
||||||
}
|
}
|
||||||
else if (!loadedLast) {
|
else if (!loadedLast) {
|
||||||
profileLoadById(profileLastId(), true);
|
profileLoadById(profileLastId(), true);
|
||||||
@ -660,7 +648,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
/*public void profileRemove(int id)
|
/*public void profileRemove(int id)
|
||||||
{
|
{
|
||||||
Profile profile = db.profileDao().getFullByIdNow(id);
|
Profile profile = db.profileDao().getByIdNow(id);
|
||||||
|
|
||||||
if (profile.id == profile.loginStoreId) {
|
if (profile.id == profile.loginStoreId) {
|
||||||
// this profile is the owner of the login store
|
// this profile is the owner of the login store
|
||||||
@ -712,8 +700,12 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
public void checkDevModePassword() {
|
public void checkDevModePassword() {
|
||||||
try {
|
try {
|
||||||
devMode = Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.getDevModePassword()).equals("ok here you go it's enabled now")
|
if (Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", appConfig.devModePassword).equals("ok here you go it's enabled now")) {
|
||||||
|| BuildConfig.DEBUG;
|
devMode = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
devMode = false;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
devMode = false;
|
devMode = false;
|
||||||
|
@ -1,319 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.work.Configuration
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScope {
|
|
||||||
companion object {
|
|
||||||
var devMode = false
|
|
||||||
}
|
|
||||||
|
|
||||||
//lateinit var db: AppDb
|
|
||||||
//val config by lazy { Config(db); // TODO migrate }
|
|
||||||
|
|
||||||
private val job = Job()
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Main
|
|
||||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
|
||||||
.setMinimumLoggingLevel(Log.VERBOSE)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
/*val preferences by lazy { getSharedPreferences(getString(R.string.preference_file), Context.MODE_PRIVATE) }
|
|
||||||
val notifier by lazy { Notifier(this) }
|
|
||||||
val permissionChecker by lazy { PermissionChecker(this) }
|
|
||||||
|
|
||||||
lateinit var profile: ProfileFull
|
|
||||||
|
|
||||||
/* _ _ _______ _______ _____
|
|
||||||
| | | |__ __|__ __| __ \
|
|
||||||
| |__| | | | | | | |__) |
|
|
||||||
| __ | | | | | | ___/
|
|
||||||
| | | | | | | | | |
|
|
||||||
|_| |_| |_| |_| |*/
|
|
||||||
val http: OkHttpClient by lazy {
|
|
||||||
val builder = OkHttpClient.Builder()
|
|
||||||
.cache(null)
|
|
||||||
.followRedirects(true)
|
|
||||||
.followSslRedirects(true)
|
|
||||||
.retryOnConnectionFailure(true)
|
|
||||||
.cookieJar(cookieJar)
|
|
||||||
.connectTimeout(20, TimeUnit.SECONDS)
|
|
||||||
.writeTimeout(5, TimeUnit.SECONDS)
|
|
||||||
.readTimeout(10, TimeUnit.SECONDS)
|
|
||||||
builder.installHttpsSupport()
|
|
||||||
|
|
||||||
if (devMode || BuildConfig.DEBUG) {
|
|
||||||
HyperLog.initialize(this)
|
|
||||||
HyperLog.setLogLevel(Log.VERBOSE)
|
|
||||||
HyperLog.setLogFormat(DebugLogFormat(this))
|
|
||||||
val chuckerCollector = ChuckerCollector(this, true, Period.ONE_HOUR)
|
|
||||||
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
|
||||||
builder.addInterceptor(chuckerInterceptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.build()
|
|
||||||
}
|
|
||||||
val httpLazy: OkHttpClient by lazy {
|
|
||||||
http.newBuilder()
|
|
||||||
.followRedirects(false)
|
|
||||||
.followSslRedirects(false)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
val cookieJar by lazy { PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(this)) }
|
|
||||||
|
|
||||||
/* _____ _ _
|
|
||||||
/ ____(_) | |
|
|
||||||
| (___ _ __ _ _ __ __ _| |_ _ _ _ __ ___
|
|
||||||
\___ \| |/ _` | '_ \ / _` | __| | | | '__/ _ \
|
|
||||||
____) | | (_| | | | | (_| | |_| |_| | | | __/
|
|
||||||
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
private val deviceId: String by lazy { Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) ?: "" }
|
|
||||||
private val signature: String by lazy {
|
|
||||||
var str = ""
|
|
||||||
try {
|
|
||||||
val packageInfo: PackageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
|
|
||||||
for (signature in packageInfo.signatures) {
|
|
||||||
val signatureBytes = signature.toByteArray()
|
|
||||||
val md = MessageDigest.getInstance("SHA")
|
|
||||||
md.update(signatureBytes)
|
|
||||||
str = Base64.encodeToString(md.digest(), Base64.DEFAULT)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
str
|
|
||||||
}
|
|
||||||
private var unreadBadgesAvailable = true
|
|
||||||
|
|
||||||
/* _____ _
|
|
||||||
/ ____| | |
|
|
||||||
___ _ __ | | _ __ ___ __ _| |_ ___
|
|
||||||
/ _ \| '_ \| | | '__/ _ \/ _` | __/ _ \
|
|
||||||
| (_) | | | | |____| | | __/ (_| | || __/
|
|
||||||
\___/|_| |_|\_____|_| \___|\__,_|\__\__*/
|
|
||||||
override fun onCreate() {
|
|
||||||
super.onCreate()
|
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
|
||||||
CaocConfig.Builder.create()
|
|
||||||
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM)
|
|
||||||
.enabled(true)
|
|
||||||
.showErrorDetails(true)
|
|
||||||
.showRestartButton(true)
|
|
||||||
.logErrorOnRestart(true)
|
|
||||||
.trackActivities(true)
|
|
||||||
.minTimeBetweenCrashesMs(60*1000)
|
|
||||||
.errorDrawable(R.drawable.ic_rip)
|
|
||||||
.restartActivity(MainActivity::class.java)
|
|
||||||
.errorActivity(CrashActivity::class.java)
|
|
||||||
.apply()
|
|
||||||
Iconics.init(applicationContext)
|
|
||||||
Iconics.registerFont(SzkolnyFont)
|
|
||||||
db = AppDb.getDatabase(this)
|
|
||||||
Themes.themeInt = config.ui.theme
|
|
||||||
MHttp.instance().customOkHttpClient(http)
|
|
||||||
|
|
||||||
devMode = "f054761fbdb6a238" == deviceId || BuildConfig.DEBUG
|
|
||||||
if (config.devModePassword != null)
|
|
||||||
checkDevModePassword()
|
|
||||||
|
|
||||||
Signing.getCert(this)
|
|
||||||
|
|
||||||
launch { async(Dispatchers.Default) {
|
|
||||||
if (config.sync.enabled) {
|
|
||||||
scheduleNext(this@App, false)
|
|
||||||
} else {
|
|
||||||
cancelNext(this@App)
|
|
||||||
}
|
|
||||||
|
|
||||||
db.metadataDao().countUnseen().observeForever { count: Int ->
|
|
||||||
if (unreadBadgesAvailable)
|
|
||||||
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
|
||||||
val shortcutManager = getSystemService(ShortcutManager::class.java)
|
|
||||||
|
|
||||||
val shortcutTimetable = ShortcutInfo.Builder(this@App, "item_timetable")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
|
|
||||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable))
|
|
||||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
|
|
||||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda))
|
|
||||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_AGENDA))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
|
|
||||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades))
|
|
||||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_GRADES))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
|
|
||||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework))
|
|
||||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOMEWORK))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
|
|
||||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages))
|
|
||||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_MESSAGES))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
shortcutManager.dynamicShortcuts = listOf(
|
|
||||||
shortcutTimetable,
|
|
||||||
shortcutAgenda,
|
|
||||||
shortcutGrades,
|
|
||||||
shortcutHomework,
|
|
||||||
shortcutMessages
|
|
||||||
)
|
|
||||||
} // shortcuts - end
|
|
||||||
|
|
||||||
if (config.appInstalledTime == 0L)
|
|
||||||
try {
|
|
||||||
config.appInstalledTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
|
|
||||||
config.appRateSnackbarTime = config.appInstalledTime + 7*DAY*MS
|
|
||||||
} catch (e: NameNotFoundException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
val pushMobidziennikApp = FirebaseApp.initializeApp(
|
|
||||||
this@App,
|
|
||||||
FirebaseOptions.Builder()
|
|
||||||
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
|
|
||||||
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
|
|
||||||
.build(),
|
|
||||||
"Mobidziennik2"
|
|
||||||
)
|
|
||||||
|
|
||||||
val pushLibrusApp = FirebaseApp.initializeApp(
|
|
||||||
this@App,
|
|
||||||
FirebaseOptions.Builder()
|
|
||||||
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
|
||||||
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
|
||||||
.build(),
|
|
||||||
"Librus"
|
|
||||||
)
|
|
||||||
|
|
||||||
val pushVulcanApp = FirebaseApp.initializeApp(
|
|
||||||
this@App,
|
|
||||||
FirebaseOptions.Builder()
|
|
||||||
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
|
||||||
.setApplicationId("1:987828170337:android:ac97431a0a4578c3")
|
|
||||||
.build(),
|
|
||||||
"Vulcan"
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
|
||||||
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
|
|
||||||
val token = instanceIdResult.token
|
|
||||||
config.sync.tokenApp = token
|
|
||||||
}
|
|
||||||
FirebaseInstanceId.getInstance(pushMobidziennikApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
||||||
val token = instanceIdResult.token
|
|
||||||
if (token != config.sync.tokenMobidziennik) {
|
|
||||||
config.sync.tokenMobidziennik = token
|
|
||||||
config.sync.tokenMobidziennikList = listOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FirebaseInstanceId.getInstance(pushLibrusApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
||||||
val token = instanceIdResult.token
|
|
||||||
if (token != config.sync.tokenLibrus) {
|
|
||||||
config.sync.tokenLibrus = token
|
|
||||||
config.sync.tokenLibrusList = listOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FirebaseInstanceId.getInstance(pushVulcanApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
||||||
val token = instanceIdResult.token
|
|
||||||
if (token != config.sync.tokenVulcan) {
|
|
||||||
config.sync.tokenVulcan = token
|
|
||||||
config.sync.tokenVulcanList = listOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun profileLoad(profileId: Int) {
|
|
||||||
db.profileDao().getFullByIdNow(profileId)?.also {
|
|
||||||
profile = it
|
|
||||||
} ?: run {
|
|
||||||
if (!::profile.isInitialized) {
|
|
||||||
profile = ProfileFull(-1, "", "", -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun profileLoad(profileId: Int, onSuccess: (profile: ProfileFull) -> Unit) {
|
|
||||||
launch {
|
|
||||||
val deferred = async(Dispatchers.Default) {
|
|
||||||
profileLoad(profileId)
|
|
||||||
}
|
|
||||||
deferred.await()
|
|
||||||
onSuccess(profile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun OkHttpClient.Builder.installHttpsSupport() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
ProviderInstaller.installIfNeeded(this@App)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("OkHttpTLSCompat", "Play Services not found or outdated")
|
|
||||||
|
|
||||||
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
|
|
||||||
trustManagerFactory.init(null as KeyStore?)
|
|
||||||
|
|
||||||
val x509TrustManager = trustManagerFactory.trustManagers.singleOrNull { it is X509TrustManager } as X509TrustManager?
|
|
||||||
?: return
|
|
||||||
|
|
||||||
val sc = SSLContext.getInstance("TLSv1.2")
|
|
||||||
sc.init(null, null, null)
|
|
||||||
sslSocketFactory(TLSSocketFactory(sc.socketFactory), x509TrustManager)
|
|
||||||
val cs: ConnectionSpec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
|
||||||
.tlsVersions(TlsVersion.TLS_1_0)
|
|
||||||
.tlsVersions(TlsVersion.TLS_1_1)
|
|
||||||
.tlsVersions(TlsVersion.TLS_1_2)
|
|
||||||
.build()
|
|
||||||
val specs: MutableList<ConnectionSpec> = ArrayList()
|
|
||||||
specs.add(cs)
|
|
||||||
specs.add(ConnectionSpec.COMPATIBLE_TLS)
|
|
||||||
specs.add(ConnectionSpec.CLEARTEXT)
|
|
||||||
connectionSpecs(specs)
|
|
||||||
}
|
|
||||||
} catch (exc: Exception) {
|
|
||||||
Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkDevModePassword() {
|
|
||||||
devMode = try {
|
|
||||||
Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.devModePassword) == "ok here you go it's enabled now" || BuildConfig.DEBUG
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,53 +4,17 @@ import android.Manifest
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.graphics.PorterDuffColorFilter
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.*
|
|
||||||
import android.text.style.ForegroundColorSpan
|
|
||||||
import android.text.style.StrikethroughSpan
|
|
||||||
import android.text.style.StyleSpan
|
|
||||||
import android.util.Base64.NO_WRAP
|
|
||||||
import android.util.Base64.encodeToString
|
|
||||||
import android.util.LongSparseArray
|
|
||||||
import android.util.SparseArray
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.CompoundButton
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.annotation.*
|
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.util.forEach
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonElement
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import okhttp3.RequestBody
|
|
||||||
import okio.Buffer
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
import pl.szczodrzynski.navlib.R
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.navlib.crc16
|
||||||
import pl.szczodrzynski.navlib.getColorFromRes
|
import pl.szczodrzynski.navlib.getColorFromRes
|
||||||
import java.math.BigInteger
|
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.CRC32
|
|
||||||
import javax.crypto.Mac
|
|
||||||
import javax.crypto.spec.SecretKeySpec
|
|
||||||
|
|
||||||
|
|
||||||
fun List<Teacher>.byId(id: Long) = firstOrNull { it.id == id }
|
fun List<Teacher>.byId(id: Long) = firstOrNull { it.id == id }
|
||||||
fun List<Teacher>.byNameFirstLast(nameFirstLast: String) = firstOrNull { it.name + " " + it.surname == nameFirstLast }
|
fun List<Teacher>.byNameFirstLast(nameFirstLast: String) = firstOrNull { it.name + " " + it.surname == nameFirstLast }
|
||||||
@ -58,25 +22,11 @@ fun List<Teacher>.byNameLastFirst(nameLastFirst: String) = firstOrNull { it.surn
|
|||||||
fun List<Teacher>.byNameFDotLast(nameFDotLast: String) = firstOrNull { it.name + "." + it.surname == nameFDotLast }
|
fun List<Teacher>.byNameFDotLast(nameFDotLast: String) = firstOrNull { it.name + "." + it.surname == nameFDotLast }
|
||||||
fun List<Teacher>.byNameFDotSpaceLast(nameFDotSpaceLast: String) = firstOrNull { it.name + ". " + it.surname == nameFDotSpaceLast }
|
fun List<Teacher>.byNameFDotSpaceLast(nameFDotSpaceLast: String) = firstOrNull { it.name + ". " + it.surname == nameFDotSpaceLast }
|
||||||
|
|
||||||
fun JsonObject?.get(key: String): JsonElement? = this?.get(key)
|
fun JsonObject.getString(key: String): String? = get(key).let { if (it.isJsonNull) null else it.asString }
|
||||||
|
fun JsonObject.getInt(key: String): Int? = get(key).let { if (it.isJsonNull) null else it.asInt }
|
||||||
fun JsonObject?.getBoolean(key: String): Boolean? = get(key)?.let { if (it.isJsonNull) null else it.asBoolean }
|
fun JsonObject.getLong(key: String): Long? = get(key).let { if (it.isJsonNull) null else it.asLong }
|
||||||
fun JsonObject?.getString(key: String): String? = get(key)?.let { if (it.isJsonNull) null else it.asString }
|
fun JsonObject.getJsonObject(key: String): JsonObject? = get(key).let { if (it.isJsonNull) null else it.asJsonObject }
|
||||||
fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) null else it.asInt }
|
fun JsonObject.getJsonArray(key: String): JsonArray? = get(key).let { if (it.isJsonNull) null else it.asJsonArray }
|
||||||
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?.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?.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
|
|
||||||
fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (it.isJsonNull) defaultValue else it.asInt } ?: defaultValue
|
|
||||||
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?.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 JsonArray?.asJsonObjectList() = this?.map { it.asJsonObject }
|
|
||||||
|
|
||||||
fun CharSequence?.isNotNullNorEmpty(): Boolean {
|
fun CharSequence?.isNotNullNorEmpty(): Boolean {
|
||||||
return this != null && this.isNotEmpty()
|
return this != null && this.isNotEmpty()
|
||||||
@ -97,65 +47,8 @@ fun Bundle?.getString(key: String, defaultValue: String): String {
|
|||||||
return this?.getString(key, defaultValue) ?: defaultValue
|
return this?.getString(key, defaultValue) ?: defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.fixName(): String {
|
|
||||||
return this.fixWhiteSpaces().toProperCase()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.toProperCase(): String = changeStringCase(this)
|
|
||||||
|
|
||||||
fun String.swapFirstLastName(): String {
|
|
||||||
return this.split(" ").let {
|
|
||||||
if (it.size > 1)
|
|
||||||
it[1]+" "+it[0]
|
|
||||||
else
|
|
||||||
it[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.getFirstLastName(): Pair<String, String>? {
|
|
||||||
return this.split(" ").let {
|
|
||||||
if (it.size >= 2) Pair(it[0], it[1])
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.getLastFirstName() = this.getFirstLastName()
|
|
||||||
|
|
||||||
fun changeStringCase(s: String): String {
|
|
||||||
val delimiters = " '-/"
|
|
||||||
val sb = StringBuilder()
|
|
||||||
var capNext = true
|
|
||||||
for (ch in s.toCharArray()) {
|
|
||||||
var c = ch
|
|
||||||
c = if (capNext)
|
|
||||||
Character.toUpperCase(c)
|
|
||||||
else
|
|
||||||
Character.toLowerCase(c)
|
|
||||||
sb.append(c)
|
|
||||||
capNext = delimiters.indexOf(c) >= 0
|
|
||||||
}
|
|
||||||
return sb.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildFullName(firstName: String?, lastName: String?): String {
|
|
||||||
return "$firstName $lastName".fixName()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.getShortName(): String {
|
|
||||||
return split(" ").let {
|
|
||||||
if (it.size > 1)
|
|
||||||
"${it[0]} ${it[1][0]}."
|
|
||||||
else
|
|
||||||
it[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List<String>.join(delimiter: String): String {
|
|
||||||
return this.joinToString(delimiter)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun colorFromName(context: Context, name: String?): Int {
|
fun colorFromName(context: Context, name: String?): Int {
|
||||||
var crc = (name ?: "").crc16()
|
var crc = crc16(name ?: "")
|
||||||
crc = (crc and 0xff) or (crc shr 8)
|
crc = (crc and 0xff) or (crc shr 8)
|
||||||
crc %= 16
|
crc %= 16
|
||||||
val color = when (crc) {
|
val color = when (crc) {
|
||||||
@ -179,9 +72,8 @@ fun colorFromName(context: Context, name: String?): Int {
|
|||||||
return context.getColorFromRes(color)
|
return context.getColorFromRes(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutableList<Profile>.filterOutArchived(): MutableList<Profile> {
|
fun MutableList<out Profile>.filterOutArchived() {
|
||||||
this.removeAll { it.archived }
|
this.removeAll { it.archived }
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.isStoragePermissionGranted(): Boolean {
|
fun Activity.isStoragePermissionGranted(): Boolean {
|
||||||
@ -197,106 +89,6 @@ fun Activity.isStoragePermissionGranted(): Boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Response?.getUnixDate(): Long {
|
|
||||||
val rfcDate = this?.headers()?.get("date") ?: return currentTimeUnix()
|
|
||||||
val pattern = "EEE, dd MMM yyyy HH:mm:ss Z"
|
|
||||||
val format = SimpleDateFormat(pattern, Locale.ENGLISH)
|
|
||||||
return format.parse(rfcDate).time / 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
const val MINUTE = 60L
|
|
||||||
const val HOUR = 60L*MINUTE
|
|
||||||
const val DAY = 24L*HOUR
|
|
||||||
const val WEEK = 7L*DAY
|
|
||||||
const val MONTH = 30L*DAY
|
|
||||||
const val YEAR = 365L*DAY
|
|
||||||
const val MS = 1000L
|
|
||||||
|
|
||||||
fun <T> LongSparseArray<T>.values(): List<T> {
|
|
||||||
val result = mutableListOf<T>()
|
|
||||||
forEach { _, value ->
|
|
||||||
result += value
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> SparseArray<T>.values(): List<T> {
|
|
||||||
val result = mutableListOf<T>()
|
|
||||||
forEach { _, value ->
|
|
||||||
result += value
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> List<T>.toSparseArray(destination: SparseArray<T>, key: (T) -> Int) {
|
|
||||||
forEach {
|
|
||||||
destination.put(key(it), it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun <T> List<T>.toSparseArray(destination: LongSparseArray<T>, key: (T) -> Long) {
|
|
||||||
forEach {
|
|
||||||
destination.put(key(it), it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> List<T>.toSparseArray(key: (T) -> Int): SparseArray<T> {
|
|
||||||
val result = SparseArray<T>()
|
|
||||||
toSparseArray(result, key)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
fun <T> List<T>.toSparseArray(key: (T) -> Long): LongSparseArray<T> {
|
|
||||||
val result = LongSparseArray<T>()
|
|
||||||
toSparseArray(result, key)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> SparseArray<T>.singleOrNull(predicate: (T) -> Boolean): T? {
|
|
||||||
forEach { _, value ->
|
|
||||||
if (predicate(value))
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
fun <T> LongSparseArray<T>.singleOrNull(predicate: (T) -> Boolean): T? {
|
|
||||||
forEach { _, value ->
|
|
||||||
if (predicate(value))
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.fixWhiteSpaces() = buildString(length) {
|
|
||||||
var wasWhiteSpace = true
|
|
||||||
for (c in this@fixWhiteSpaces) {
|
|
||||||
if (c.isWhitespace()) {
|
|
||||||
if (!wasWhiteSpace) {
|
|
||||||
append(c)
|
|
||||||
wasWhiteSpace = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
append(c)
|
|
||||||
wasWhiteSpace = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.trimEnd()
|
|
||||||
|
|
||||||
fun List<Team>.getById(id: Long): Team? {
|
|
||||||
return singleOrNull { it.id == id }
|
|
||||||
}
|
|
||||||
fun LongSparseArray<Team>.getById(id: Long): Team? {
|
|
||||||
forEach { _, value ->
|
|
||||||
if (value.id == id)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun MatchResult.get(group: Int): String {
|
|
||||||
if (group >= groupValues.size)
|
|
||||||
return ""
|
|
||||||
return groupValues[group]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Activity.setLanguage(language: String) {
|
fun Activity.setLanguage(language: String) {
|
||||||
val locale = Locale(language.toLowerCase(Locale.ROOT))
|
val locale = Locale(language.toLowerCase(Locale.ROOT))
|
||||||
val configuration = resources.configuration
|
val configuration = resources.configuration
|
||||||
@ -345,299 +137,3 @@ fun initDefaultLocale() {
|
|||||||
Locale.setDefault(it)
|
Locale.setDefault(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.crc16(): Int {
|
|
||||||
var crc = 0xFFFF
|
|
||||||
for (aBuffer in this) {
|
|
||||||
crc = crc.ushr(8) or (crc shl 8) and 0xffff
|
|
||||||
crc = crc xor (aBuffer.toInt() and 0xff) // byte to int, trunc sign
|
|
||||||
crc = crc xor (crc and 0xff shr 4)
|
|
||||||
crc = crc xor (crc shl 12 and 0xffff)
|
|
||||||
crc = crc xor (crc and 0xFF shl 5 and 0xffff)
|
|
||||||
}
|
|
||||||
crc = crc and 0xffff
|
|
||||||
return crc + 32768
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.crc32(): Long {
|
|
||||||
val crc = CRC32()
|
|
||||||
crc.update(toByteArray())
|
|
||||||
return crc.value
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.hmacSHA1(password: String): String {
|
|
||||||
val key = SecretKeySpec(password.toByteArray(), "HmacSHA1")
|
|
||||||
|
|
||||||
val mac = Mac.getInstance("HmacSHA1").apply {
|
|
||||||
init(key)
|
|
||||||
update(this@hmacSHA1.toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
return encodeToString(mac.doFinal(), NO_WRAP)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.md5(): String {
|
|
||||||
val md = MessageDigest.getInstance("MD5")
|
|
||||||
return BigInteger(1, md.digest(toByteArray())).toString(16).padStart(32, '0')
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.sha256(): ByteArray {
|
|
||||||
val md = MessageDigest.getInstance("SHA-256")
|
|
||||||
md.update(toByteArray())
|
|
||||||
return md.digest()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun RequestBody.bodyToString(): String {
|
|
||||||
val buffer = Buffer()
|
|
||||||
writeTo(buffer)
|
|
||||||
return buffer.readUtf8()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Long.formatDate(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this)
|
|
||||||
|
|
||||||
fun CharSequence?.asColoredSpannable(colorInt: Int): Spannable {
|
|
||||||
val spannable = SpannableString(this)
|
|
||||||
spannable.setSpan(ForegroundColorSpan(colorInt), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
return spannable
|
|
||||||
}
|
|
||||||
fun CharSequence?.asStrikethroughSpannable(): Spannable {
|
|
||||||
val spannable = SpannableString(this)
|
|
||||||
spannable.setSpan(StrikethroughSpan(), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
return spannable
|
|
||||||
}
|
|
||||||
fun CharSequence?.asItalicSpannable(): Spannable {
|
|
||||||
val spannable = SpannableString(this)
|
|
||||||
spannable.setSpan(StyleSpan(Typeface.ITALIC), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
return spannable
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new read-only list only of those given elements, that are not empty.
|
|
||||||
* Applies for CharSequence and descendants.
|
|
||||||
*/
|
|
||||||
fun <T : CharSequence> listOfNotEmpty(vararg elements: T): List<T> = elements.filterNot { it.isEmpty() }
|
|
||||||
|
|
||||||
fun List<CharSequence?>.concat(delimiter: String? = null): CharSequence {
|
|
||||||
if (this.isEmpty()) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.size == 1) {
|
|
||||||
return this[0] ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var spanned = false
|
|
||||||
for (piece in this) {
|
|
||||||
if (piece is Spanned) {
|
|
||||||
spanned = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var first = true
|
|
||||||
if (spanned) {
|
|
||||||
val ssb = SpannableStringBuilder()
|
|
||||||
for (piece in this) {
|
|
||||||
if (piece == null)
|
|
||||||
continue
|
|
||||||
if (!first && delimiter != null)
|
|
||||||
ssb.append(delimiter)
|
|
||||||
first = false
|
|
||||||
ssb.append(piece)
|
|
||||||
}
|
|
||||||
return SpannedString(ssb)
|
|
||||||
} else {
|
|
||||||
val sb = StringBuilder()
|
|
||||||
for (piece in this) {
|
|
||||||
if (piece == null)
|
|
||||||
continue
|
|
||||||
if (!first && delimiter != null)
|
|
||||||
sb.append(delimiter)
|
|
||||||
first = false
|
|
||||||
sb.append(piece)
|
|
||||||
}
|
|
||||||
return sb.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun TextView.setText(@StringRes resid: Int, vararg formatArgs: Any) {
|
|
||||||
text = context.getString(resid, *formatArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun JsonObject(vararg properties: Pair<String, Any?>): JsonObject {
|
|
||||||
return JsonObject().apply {
|
|
||||||
for (property in properties) {
|
|
||||||
when (property.second) {
|
|
||||||
is JsonElement -> add(property.first, property.second as JsonElement?)
|
|
||||||
is String -> addProperty(property.first, property.second as String?)
|
|
||||||
is Char -> addProperty(property.first, property.second as Char?)
|
|
||||||
is Number -> addProperty(property.first, property.second as Number?)
|
|
||||||
is Boolean -> addProperty(property.first, property.second as Boolean?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun JsonArray?.isNullOrEmpty(): Boolean = (this?.size() ?: 0) == 0
|
|
||||||
fun JsonArray.isEmpty(): Boolean = this.size() == 0
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
inline fun <T : View> T.onClick(crossinline onClickListener: (v: T) -> Unit) {
|
|
||||||
setOnClickListener { v: View ->
|
|
||||||
onClickListener(v as T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
inline fun <T : CompoundButton> T.onChange(crossinline onChangeListener: (v: T, isChecked: Boolean) -> Unit) {
|
|
||||||
setOnCheckedChangeListener { buttonView, isChecked ->
|
|
||||||
onChangeListener(buttonView as T, isChecked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
|
|
||||||
observe(lifecycleOwner, object : Observer<T> {
|
|
||||||
override fun onChanged(t: T?) {
|
|
||||||
observer.onChanged(t)
|
|
||||||
removeObserver(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a value in dp to pixels.
|
|
||||||
*/
|
|
||||||
val Int.dp: Int
|
|
||||||
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
|
||||||
/**
|
|
||||||
* Convert a value in pixels to dp.
|
|
||||||
*/
|
|
||||||
val Int.px: Int
|
|
||||||
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
fun @receiver:AttrRes Int.resolveAttr(context: Context?): Int {
|
|
||||||
val typedValue = TypedValue()
|
|
||||||
context?.theme?.resolveAttribute(this, typedValue, true)
|
|
||||||
return typedValue.data
|
|
||||||
}
|
|
||||||
@ColorInt
|
|
||||||
fun @receiver:ColorRes Int.resolveColor(context: Context): Int {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
context.resources.getColor(this, context.theme)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.resources.getColor(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun @receiver:DrawableRes Int.resolveDrawable(context: Context): Drawable {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
context.resources.getDrawable(this, context.theme)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.resources.getDrawable(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun View.findParentById(targetId: Int): View? {
|
|
||||||
if (id == targetId) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
val viewParent = this.parent ?: return null
|
|
||||||
if (viewParent is View) {
|
|
||||||
return viewParent.findParentById(targetId)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: () -> Unit) = launch {
|
|
||||||
delay(delayMillis)
|
|
||||||
if (repeatMillis > 0) {
|
|
||||||
while (true) {
|
|
||||||
action()
|
|
||||||
delay(repeatMillis)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
action()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun Time?.compareTo(other: Time?): Int {
|
|
||||||
if (this == null && other == null)
|
|
||||||
return 0
|
|
||||||
if (this == null)
|
|
||||||
return -1
|
|
||||||
if (other == null)
|
|
||||||
return 1
|
|
||||||
return this.compareTo(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun StringBuilder.plusAssign(str: String?) {
|
|
||||||
this.append(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.timeTill(time: Int, delimiter: String = " "): String {
|
|
||||||
val parts = mutableListOf<Pair<Int, Int>>()
|
|
||||||
|
|
||||||
val hours = time / 3600
|
|
||||||
val minutes = (time - hours*3600) / 60
|
|
||||||
val seconds = time - minutes*60 - hours*3600
|
|
||||||
|
|
||||||
var prefixAdded = false
|
|
||||||
if (hours > 0) {
|
|
||||||
if (!prefixAdded) parts += R.plurals.time_till_text to hours; prefixAdded = true
|
|
||||||
parts += R.plurals.time_till_hours to hours
|
|
||||||
}
|
|
||||||
if (minutes > 0) {
|
|
||||||
if (!prefixAdded) parts += R.plurals.time_till_text to minutes; prefixAdded = true
|
|
||||||
parts += R.plurals.time_till_minutes to minutes
|
|
||||||
}
|
|
||||||
if (hours == 0 && minutes < 10) {
|
|
||||||
if (!prefixAdded) parts += R.plurals.time_till_text to seconds; prefixAdded = true
|
|
||||||
parts += R.plurals.time_till_seconds to seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
return parts.joinToString(delimiter) { resources.getQuantityString(it.first, it.second, it.second) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.timeLeft(time: Int, delimiter: String = " "): String {
|
|
||||||
val parts = mutableListOf<Pair<Int, Int>>()
|
|
||||||
|
|
||||||
val hours = time / 3600
|
|
||||||
val minutes = (time - hours*3600) / 60
|
|
||||||
val seconds = time - minutes*60 - hours*3600
|
|
||||||
|
|
||||||
var prefixAdded = false
|
|
||||||
if (hours > 0) {
|
|
||||||
if (!prefixAdded) parts += R.plurals.time_left_text to hours
|
|
||||||
prefixAdded = true
|
|
||||||
parts += R.plurals.time_left_hours to hours
|
|
||||||
}
|
|
||||||
if (minutes > 0) {
|
|
||||||
if (!prefixAdded) parts += R.plurals.time_left_text to minutes
|
|
||||||
prefixAdded = true
|
|
||||||
parts += R.plurals.time_left_minutes to minutes
|
|
||||||
}
|
|
||||||
if (hours == 0 && minutes < 10) {
|
|
||||||
if (!prefixAdded) parts += R.plurals.time_left_text to seconds
|
|
||||||
prefixAdded = true
|
|
||||||
parts += R.plurals.time_left_seconds to seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
return parts.joinToString(delimiter) { resources.getQuantityString(it.first, it.second, it.second) }
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> Any?.instanceOfOrNull(): T? {
|
|
||||||
return when (this) {
|
|
||||||
is T -> this
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Drawable.setTintColor(color: Int): Drawable {
|
|
||||||
colorFilter = PorterDuffColorFilter(
|
|
||||||
color,
|
|
||||||
PorterDuff.Mode.SRC_ATOP
|
|
||||||
)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
@ -6,11 +6,9 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import android.provider.Settings
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -21,7 +19,6 @@ import androidx.core.graphics.ColorUtils
|
|||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.navigation.NavOptions
|
import androidx.navigation.NavOptions
|
||||||
import com.danimahardhika.cafebar.CafeBar
|
import com.danimahardhika.cafebar.CafeBar
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import com.mikepenz.iconics.IconicsColor
|
import com.mikepenz.iconics.IconicsColor
|
||||||
import com.mikepenz.iconics.IconicsDrawable
|
import com.mikepenz.iconics.IconicsDrawable
|
||||||
import com.mikepenz.iconics.IconicsSize
|
import com.mikepenz.iconics.IconicsSize
|
||||||
@ -32,49 +29,41 @@ import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
|||||||
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
|
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile
|
import com.mikepenz.materialdrawer.model.interfaces.IProfile
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import org.greenrobot.eventbus.Subscribe
|
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
|
||||||
import pl.droidsonroids.gif.GifDrawable
|
import pl.droidsonroids.gif.GifDrawable
|
||||||
import pl.szczodrzynski.edziennik.App.APP_URL
|
import pl.szczodrzynski.edziennik.App.APP_URL
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.*
|
import pl.szczodrzynski.edziennik.data.api.AppError
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.interfaces.SyncCallback
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull
|
||||||
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
||||||
import pl.szczodrzynski.edziennik.network.ServerRequest
|
import pl.szczodrzynski.edziennik.network.ServerRequest
|
||||||
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
import pl.szczodrzynski.edziennik.sync.SyncJob
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
||||||
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.agenda.AgendaFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment
|
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment
|
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.behaviour.BehaviourFragment
|
import pl.szczodrzynski.edziennik.ui.modules.behaviour.BehaviourFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
|
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
|
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesFragment
|
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
|
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessageFragment
|
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesDetailsFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
|
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
|
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment
|
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushFragment
|
|
||||||
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
|
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.dpToPx
|
import pl.szczodrzynski.edziennik.utils.Utils.dpToPx
|
||||||
import pl.szczodrzynski.edziennik.utils.appManagerIntentList
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.NavTarget
|
import pl.szczodrzynski.edziennik.utils.models.NavTarget
|
||||||
import pl.szczodrzynski.navlib.*
|
import pl.szczodrzynski.navlib.*
|
||||||
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_HALF_TRANSPARENT
|
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_HALF_TRANSPARENT
|
||||||
@ -87,7 +76,7 @@ import pl.szczodrzynski.navlib.drawer.items.withAppTitle
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
companion object {
|
companion object {
|
||||||
@ -119,7 +108,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
const val TARGET_HELP = 502
|
const val TARGET_HELP = 502
|
||||||
const val TARGET_FEEDBACK = 120
|
const val TARGET_FEEDBACK = 120
|
||||||
const val TARGET_MESSAGES_DETAILS = 503
|
const val TARGET_MESSAGES_DETAILS = 503
|
||||||
const val TARGET_WEB_PUSH = 140
|
|
||||||
|
|
||||||
const val HOME_ID = DRAWER_ITEM_HOME
|
const val HOME_ID = DRAWER_ITEM_HOME
|
||||||
|
|
||||||
@ -127,9 +115,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val list: MutableList<NavTarget> = mutableListOf()
|
val list: MutableList<NavTarget> = mutableListOf()
|
||||||
|
|
||||||
// home item
|
// home item
|
||||||
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragmentV2::class)
|
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragment::class)
|
||||||
.withTitle(R.string.app_name)
|
.withTitle(R.string.app_name)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_home_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_home)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
.isStatic(true)
|
.isStatic(true)
|
||||||
.withPopToHome(false)
|
.withPopToHome(false)
|
||||||
@ -140,50 +128,50 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_AGENDA, R.string.menu_agenda, AgendaFragment::class)
|
list += NavTarget(DRAWER_ITEM_AGENDA, R.string.menu_agenda, AgendaFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_calendar_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_calendar)
|
||||||
.withBadgeTypeId(TYPE_EVENT)
|
.withBadgeTypeId(TYPE_EVENT)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesFragment::class)
|
list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_numeric_5_box)
|
||||||
.withBadgeTypeId(TYPE_GRADE)
|
.withBadgeTypeId(TYPE_GRADE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_MESSAGES, R.string.menu_messages, MessagesFragment::class)
|
list += NavTarget(DRAWER_ITEM_MESSAGES, R.string.menu_messages, MessagesFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_email_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_email)
|
||||||
.withBadgeTypeId(TYPE_MESSAGE)
|
.withBadgeTypeId(TYPE_MESSAGE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_HOMEWORK, R.string.menu_homework, HomeworkFragment::class)
|
list += NavTarget(DRAWER_ITEM_HOMEWORK, R.string.menu_homework, HomeworkFragment::class)
|
||||||
.withIcon(SzkolnyFont.Icon.szf_notebook_outline)
|
.withIcon(SzkolnyFont.Icon.szf_file_document_edit)
|
||||||
.withBadgeTypeId(TYPE_HOMEWORK)
|
.withBadgeTypeId(TYPE_HOMEWORK)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_BEHAVIOUR, R.string.menu_notices, BehaviourFragment::class)
|
list += NavTarget(DRAWER_ITEM_BEHAVIOUR, R.string.menu_notices, BehaviourFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_emoticon_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_message_alert)
|
||||||
.withBadgeTypeId(TYPE_NOTICE)
|
.withBadgeTypeId(TYPE_NOTICE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_ATTENDANCE, R.string.menu_attendance, AttendanceFragment::class)
|
list += NavTarget(DRAWER_ITEM_ATTENDANCE, R.string.menu_attendance, AttendanceFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_calendar_remove_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_calendar_remove)
|
||||||
.withBadgeTypeId(TYPE_ATTENDANCE)
|
.withBadgeTypeId(TYPE_ATTENDANCE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_ANNOUNCEMENTS, R.string.menu_announcements, AnnouncementsFragment::class)
|
list += NavTarget(DRAWER_ITEM_ANNOUNCEMENTS, R.string.menu_announcements, AnnouncementsFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_bullhorn_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_bulletin_board)
|
||||||
.withBadgeTypeId(TYPE_ANNOUNCEMENT)
|
.withBadgeTypeId(TYPE_ANNOUNCEMENT)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
|
|
||||||
// static drawer items
|
// static drawer items
|
||||||
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsFragment::class)
|
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_bell_ring_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_bell_ring)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
.isStatic(true)
|
.isStatic(true)
|
||||||
.isBelowSeparator(true)
|
.isBelowSeparator(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_SETTINGS, R.string.menu_settings, SettingsNewFragment::class)
|
list += NavTarget(DRAWER_ITEM_SETTINGS, R.string.menu_settings, SettingsNewFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_settings_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_settings)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
.isStatic(true)
|
.isStatic(true)
|
||||||
.isBelowSeparator(true)
|
.isBelowSeparator(true)
|
||||||
@ -202,7 +190,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.isInProfileList(false)
|
.isInProfileList(false)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_PROFILE_SYNC_ALL, R.string.menu_sync_all, null)
|
list += NavTarget(DRAWER_PROFILE_SYNC_ALL, R.string.menu_sync_all, null)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_download_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_sync)
|
||||||
.isInProfileList(true)
|
.isInProfileList(true)
|
||||||
|
|
||||||
|
|
||||||
@ -210,8 +198,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
list += NavTarget(TARGET_GRADES_EDITOR, R.string.menu_grades_editor, GradesEditorFragment::class)
|
list += NavTarget(TARGET_GRADES_EDITOR, R.string.menu_grades_editor, GradesEditorFragment::class)
|
||||||
list += NavTarget(TARGET_HELP, R.string.menu_help, HelpFragment::class)
|
list += NavTarget(TARGET_HELP, R.string.menu_help, HelpFragment::class)
|
||||||
list += NavTarget(TARGET_FEEDBACK, R.string.menu_feedback, FeedbackFragment::class)
|
list += NavTarget(TARGET_FEEDBACK, R.string.menu_feedback, FeedbackFragment::class)
|
||||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class)
|
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessagesDetailsFragment::class)
|
||||||
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
|
|
||||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||||
|
|
||||||
list
|
list
|
||||||
@ -222,7 +209,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val navView: NavView by lazy { b.navView }
|
val navView: NavView by lazy { b.navView }
|
||||||
val drawer: NavDrawer by lazy { navView.drawer }
|
val drawer: NavDrawer by lazy { navView.drawer }
|
||||||
val bottomSheet: NavBottomSheet by lazy { navView.bottomSheet }
|
val bottomSheet: NavBottomSheet by lazy { navView.bottomSheet }
|
||||||
val errorSnackbar: ErrorSnackbar by lazy { ErrorSnackbar(this) }
|
|
||||||
|
|
||||||
val swipeRefreshLayout: SwipeRefreshLayoutNoTouch by lazy { b.swipeRefreshLayout }
|
val swipeRefreshLayout: SwipeRefreshLayoutNoTouch by lazy { b.swipeRefreshLayout }
|
||||||
|
|
||||||
@ -232,7 +218,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private val fragmentManager by lazy { supportFragmentManager }
|
private val fragmentManager by lazy { supportFragmentManager }
|
||||||
private lateinit var navTarget: NavTarget
|
private lateinit var navTarget: NavTarget
|
||||||
val navTargetId
|
private val navTargetId
|
||||||
get() = navTarget.id
|
get() = navTarget.id
|
||||||
|
|
||||||
private val navBackStack = mutableListOf<NavTarget>()
|
private val navBackStack = mutableListOf<NavTarget>()
|
||||||
@ -249,16 +235,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
setTheme(Themes.appTheme)
|
setTheme(Themes.appTheme)
|
||||||
|
|
||||||
app.config.ui.language?.let {
|
app.appConfig.language?.let {
|
||||||
setLanguage(it)
|
setLanguage(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(b.root)
|
setContentView(b.root)
|
||||||
|
|
||||||
Log.d(TAG, Signing.appPassword)
|
|
||||||
|
|
||||||
errorSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar)
|
|
||||||
|
|
||||||
navLoading = true
|
navLoading = true
|
||||||
|
|
||||||
b.navView.apply {
|
b.navView.apply {
|
||||||
@ -314,10 +296,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawer.apply {
|
drawer.apply {
|
||||||
setAccountHeaderBackground(app.config.ui.headerBackground)
|
setAccountHeaderBackground(app.appConfig.headerBackground)
|
||||||
|
|
||||||
drawerProfileListEmptyListener = {
|
drawerProfileListEmptyListener = {
|
||||||
app.config.loginFinished = false
|
app.appConfig.loginFinished = false
|
||||||
app.saveConfig("loginFinished")
|
app.saveConfig("loginFinished")
|
||||||
profileListEmptyListener()
|
profileListEmptyListener()
|
||||||
}
|
}
|
||||||
@ -342,7 +324,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
drawerProfileSettingClickListener = this@MainActivity.profileSettingClickListener
|
drawerProfileSettingClickListener = this@MainActivity.profileSettingClickListener
|
||||||
|
|
||||||
miniDrawerVisibleLandscape = null
|
miniDrawerVisibleLandscape = null
|
||||||
miniDrawerVisiblePortrait = app.config.ui.miniMenuVisible
|
miniDrawerVisiblePortrait = app.appConfig.miniDrawerVisible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +340,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (!profileListEmpty) {
|
if (!profileListEmpty) {
|
||||||
handleIntent(intent?.extras)
|
handleIntent(intent?.extras)
|
||||||
}
|
}
|
||||||
app.db.profileDao().allFull.observe(this, Observer { profiles ->
|
app.db.profileDao().getAllFull().observe(this, Observer { profiles ->
|
||||||
// TODO fix weird -1 profiles ???
|
// TODO fix weird -1 profiles ???
|
||||||
profiles.removeAll { it.id < 0 }
|
profiles.removeAll { it.id < 0 }
|
||||||
drawer.setProfileList(profiles)
|
drawer.setProfileList(profiles)
|
||||||
@ -375,7 +357,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (app.profile != null)
|
if (app.profile != null)
|
||||||
setDrawerItems()
|
setDrawerItems()
|
||||||
|
|
||||||
app.db.metadataDao().unreadCounts.observe(this, Observer { unreadCounters ->
|
app.db.metadataDao().getUnreadCounts().observe(this, Observer { unreadCounters ->
|
||||||
unreadCounters.map {
|
unreadCounters.map {
|
||||||
it.type = it.thingType
|
it.type = it.thingType
|
||||||
}
|
}
|
||||||
@ -384,48 +366,35 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
b.swipeRefreshLayout.isEnabled = true
|
b.swipeRefreshLayout.isEnabled = true
|
||||||
b.swipeRefreshLayout.setOnRefreshListener { this.syncCurrentFeature() }
|
b.swipeRefreshLayout.setOnRefreshListener { this.syncCurrentFeature() }
|
||||||
b.swipeRefreshLayout.setColorSchemeResources(
|
|
||||||
R.color.md_blue_500,
|
|
||||||
R.color.md_amber_500,
|
|
||||||
R.color.md_green_500
|
|
||||||
)
|
|
||||||
|
|
||||||
isStoragePermissionGranted()
|
isStoragePermissionGranted()
|
||||||
|
|
||||||
SyncWorker.scheduleNext(app)
|
SyncJob.schedule(app)
|
||||||
|
|
||||||
// APP BACKGROUND
|
// APP BACKGROUND
|
||||||
if (app.config.ui.appBackground != null) {
|
if (app.appConfig.appBackground != null) {
|
||||||
try {
|
try {
|
||||||
app.config.ui.appBackground?.let {
|
var bg = app.appConfig.appBackground
|
||||||
var bg = it
|
val bgDir = File(Environment.getExternalStoragePublicDirectory("Szkolny.eu"), "bg")
|
||||||
val bgDir = File(Environment.getExternalStoragePublicDirectory("Szkolny.eu"), "bg")
|
if (bgDir.exists()) {
|
||||||
if (bgDir.exists()) {
|
val files = bgDir.listFiles()
|
||||||
val files = bgDir.listFiles()
|
val r = Random()
|
||||||
val r = Random()
|
val i = r.nextInt(files.size)
|
||||||
val i = r.nextInt(files.size)
|
bg = files[i].toString()
|
||||||
bg = files[i].toString()
|
}
|
||||||
}
|
val linearLayout = b.root
|
||||||
val linearLayout = b.root
|
if (bg.endsWith(".gif")) {
|
||||||
if (bg.endsWith(".gif")) {
|
linearLayout.background = GifDrawable(bg)
|
||||||
linearLayout.background = GifDrawable(bg)
|
} else {
|
||||||
} else {
|
linearLayout.background = BitmapDrawable.createFromPath(bg)
|
||||||
linearLayout.background = BitmapDrawable.createFromPath(bg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IT'S WINTER MY DUDES
|
|
||||||
val today = Date.getToday()
|
|
||||||
if ((today.month == 12 || today.month == 1) && app.config.ui.snowfall) {
|
|
||||||
b.rootFrame.addView(layoutInflater.inflate(R.layout.snowfall, b.rootFrame, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WHAT'S NEW DIALOG
|
// WHAT'S NEW DIALOG
|
||||||
if (app.config.appVersion < BuildConfig.VERSION_CODE) {
|
if (app.appConfig.lastAppVersion != BuildConfig.VERSION_CODE) {
|
||||||
ServerRequest(app, app.requestScheme + APP_URL + "main.php?just_updated", "MainActivity/JU")
|
ServerRequest(app, app.requestScheme + APP_URL + "main.php?just_updated", "MainActivity/JU")
|
||||||
.run { e, result ->
|
.run { e, result ->
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
@ -436,20 +405,21 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (app.config.appVersion < 170) {
|
if (app.appConfig.lastAppVersion < 170) {
|
||||||
//Intent intent = new Intent(this, ChangelogIntroActivity.class);
|
//Intent intent = new Intent(this, ChangelogIntroActivity.class);
|
||||||
//startActivity(intent);
|
//startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
app.config.appVersion = BuildConfig.VERSION_CODE
|
app.appConfig.lastAppVersion = BuildConfig.VERSION_CODE
|
||||||
|
app.saveConfig("lastAppVersion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RATE SNACKBAR
|
// RATE SNACKBAR
|
||||||
if (app.config.appRateSnackbarTime != 0L && app.config.appRateSnackbarTime <= System.currentTimeMillis()) {
|
if (app.appConfig.appRateSnackbarTime != 0L && app.appConfig.appRateSnackbarTime <= System.currentTimeMillis()) {
|
||||||
navView.coordinator.postDelayed({
|
navView.coordinator.postDelayed({
|
||||||
CafeBar.builder(this)
|
CafeBar.builder(this)
|
||||||
.content(R.string.rate_snackbar_text)
|
.content(R.string.rate_snackbar_text)
|
||||||
.icon(IconicsDrawable(this).icon(CommunityMaterial.Icon2.cmd_star_outline).size(IconicsSize.dp(20)).color(IconicsColor.colorInt(Themes.getPrimaryTextColor(this))))
|
.icon(IconicsDrawable(this).icon(CommunityMaterial.Icon2.cmd_star).size(IconicsSize.dp(20)).color(IconicsColor.colorInt(Themes.getPrimaryTextColor(this))))
|
||||||
.positiveText(R.string.rate_snackbar_positive)
|
.positiveText(R.string.rate_snackbar_positive)
|
||||||
.positiveColor(-0xb350b0)
|
.positiveColor(-0xb350b0)
|
||||||
.negativeText(R.string.rate_snackbar_negative)
|
.negativeText(R.string.rate_snackbar_negative)
|
||||||
@ -459,17 +429,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.onPositive { cafeBar ->
|
.onPositive { cafeBar ->
|
||||||
Utils.openGooglePlay(this)
|
Utils.openGooglePlay(this)
|
||||||
cafeBar.dismiss()
|
cafeBar.dismiss()
|
||||||
app.config.appRateSnackbarTime = 0
|
app.appConfig.appRateSnackbarTime = 0
|
||||||
|
app.saveConfig("appRateSnackbarTime")
|
||||||
}
|
}
|
||||||
.onNegative { cafeBar ->
|
.onNegative { cafeBar ->
|
||||||
Toast.makeText(this, "Szkoda, opinie innych pomagają mi rozwijać aplikację.", Toast.LENGTH_LONG).show()
|
Toast.makeText(this, "Szkoda, opinie innych pomagają mi rozwijać aplikację.", Toast.LENGTH_LONG).show()
|
||||||
cafeBar.dismiss()
|
cafeBar.dismiss()
|
||||||
app.config.appRateSnackbarTime = 0
|
app.appConfig.appRateSnackbarTime = 0
|
||||||
|
app.saveConfig("appRateSnackbarTime")
|
||||||
}
|
}
|
||||||
.onNeutral { cafeBar ->
|
.onNeutral { cafeBar ->
|
||||||
Toast.makeText(this, "OK", Toast.LENGTH_LONG).show()
|
Toast.makeText(this, "OK", Toast.LENGTH_LONG).show()
|
||||||
cafeBar.dismiss()
|
cafeBar.dismiss()
|
||||||
app.config.appRateSnackbarTime = System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000
|
app.appConfig.appRateSnackbarTime = System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000
|
||||||
|
app.saveConfig("appRateSnackbarTime")
|
||||||
}
|
}
|
||||||
.autoDismiss(false)
|
.autoDismiss(false)
|
||||||
.swipeToDismiss(true)
|
.swipeToDismiss(true)
|
||||||
@ -483,34 +456,27 @@ class MainActivity : AppCompatActivity() {
|
|||||||
bottomSheet.appendItems(
|
bottomSheet.appendItems(
|
||||||
BottomSheetPrimaryItem(false)
|
BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_sync)
|
.withTitle(R.string.menu_sync)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_download_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_sync)
|
||||||
.withOnClickListener(View.OnClickListener {
|
.withOnClickListener(View.OnClickListener {
|
||||||
bottomSheet.close()
|
bottomSheet.close()
|
||||||
SyncViewListDialog(this, navTargetId)
|
app.apiEdziennik.guiSyncFeature(app, this, App.profileId, R.string.sync_dialog_title, R.string.sync_dialog_text, R.string.sync_done, fragmentToFeature(navTargetId))
|
||||||
}),
|
}),
|
||||||
BottomSheetSeparatorItem(false),
|
BottomSheetSeparatorItem(false),
|
||||||
BottomSheetPrimaryItem(false)
|
BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_settings)
|
.withTitle(R.string.menu_settings)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_settings_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_settings)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_SETTINGS) }),
|
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_SETTINGS) }),
|
||||||
BottomSheetPrimaryItem(false)
|
BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_feedback)
|
.withTitle(R.string.menu_feedback)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_help_circle)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
||||||
)
|
)
|
||||||
if (App.devMode) {
|
if (App.devMode) {
|
||||||
bottomSheet += BottomSheetPrimaryItem(false)
|
bottomSheet += BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_debug)
|
.withTitle(R.string.menu_debug)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_android_studio)
|
.withIcon(CommunityMaterial.Icon.cmd_android_debug_bridge)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) })
|
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) })
|
||||||
}
|
}
|
||||||
|
|
||||||
EventBus.getDefault().register(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
EventBus.getDefault().unregister(this)
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var profileListEmptyListener = {
|
var profileListEmptyListener = {
|
||||||
@ -525,7 +491,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
profileListEmptyListener()
|
profileListEmptyListener()
|
||||||
}
|
}
|
||||||
DRAWER_PROFILE_SYNC_ALL -> {
|
DRAWER_PROFILE_SYNC_ALL -> {
|
||||||
EdziennikTask.sync().enqueue(this)
|
SyncJob.run(app)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
loadTarget(id)
|
loadTarget(id)
|
||||||
@ -545,99 +511,52 @@ class MainActivity : AppCompatActivity() {
|
|||||||
fun syncCurrentFeature() {
|
fun syncCurrentFeature() {
|
||||||
swipeRefreshLayout.isRefreshing = true
|
swipeRefreshLayout.isRefreshing = true
|
||||||
Toast.makeText(this, fragmentToSyncName(navTargetId), Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, fragmentToSyncName(navTargetId), Toast.LENGTH_SHORT).show()
|
||||||
val fragmentParam = when (navTargetId) {
|
val callback = object : SyncCallback {
|
||||||
DRAWER_ITEM_MESSAGES -> MessagesFragment.pageSelection
|
override fun onLoginFirst(profileList: List<Profile>, loginStore: LoginStore) {
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
val arguments = when (navTargetId) {
|
|
||||||
DRAWER_ITEM_TIMETABLE -> JsonObject("weekStart" to TimetableFragment.pageSelection?.weekStart?.stringY_m_d)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
EdziennikTask.syncProfile(
|
|
||||||
App.profileId,
|
|
||||||
listOf(navTargetId to fragmentParam),
|
|
||||||
arguments
|
|
||||||
).enqueue(this)
|
|
||||||
}
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onSyncStartedEvent(event: ApiTaskStartedEvent) {
|
|
||||||
swipeRefreshLayout.isRefreshing = true
|
|
||||||
if (event.profileId == App.profileId) {
|
|
||||||
navView.toolbar.apply {
|
|
||||||
subtitleFormat = null
|
|
||||||
subtitleFormatWithUnread = null
|
|
||||||
subtitle = getString(R.string.toolbar_subtitle_syncing)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
override fun onSuccess(activityContext: Context, profileFull: ProfileFull) {
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
swipeRefreshLayout.isRefreshing = false
|
||||||
fun onSyncProgressEvent(event: ApiTaskProgressEvent) {
|
}
|
||||||
if (event.profileId == App.profileId) {
|
|
||||||
navView.toolbar.apply {
|
override fun onError(activityContext: Context, error: AppError) {
|
||||||
subtitleFormat = null
|
swipeRefreshLayout.isRefreshing = false
|
||||||
subtitleFormatWithUnread = null
|
app.apiEdziennik.guiShowErrorSnackbar(this@MainActivity, error)
|
||||||
subtitle = if (event.progress < 0f)
|
}
|
||||||
event.progressText ?: ""
|
|
||||||
else
|
override fun onProgress(progressStep: Int) {
|
||||||
getString(R.string.toolbar_subtitle_syncing_format, event.progress.roundToInt(), event.progressText ?: "")
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActionStarted(stringResId: Int) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val feature = fragmentToFeature(navTargetId)
|
||||||
|
if (feature == FEATURE_ALL) {
|
||||||
|
swipeRefreshLayout.isRefreshing = false
|
||||||
|
app.apiEdziennik.guiSync(app, this, App.profileId, R.string.sync_dialog_title, R.string.sync_dialog_text, R.string.sync_done)
|
||||||
|
} else {
|
||||||
|
app.apiEdziennik.guiSyncSilent(app, this, App.profileId, callback, feature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
private fun fragmentToFeature(currentFragment: Int): Int {
|
||||||
fun onSyncProfileFinishedEvent(event: ApiTaskFinishedEvent) {
|
return when (currentFragment) {
|
||||||
if (event.profileId == App.profileId) {
|
DRAWER_ITEM_TIMETABLE -> FEATURE_TIMETABLE
|
||||||
navView.toolbar.apply {
|
DRAWER_ITEM_AGENDA -> FEATURE_AGENDA
|
||||||
subtitleFormat = R.string.toolbar_subtitle
|
DRAWER_ITEM_GRADES -> FEATURE_GRADES
|
||||||
subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread
|
DRAWER_ITEM_HOMEWORK -> FEATURE_HOMEWORK
|
||||||
subtitle = "Gotowe"
|
DRAWER_ITEM_BEHAVIOUR -> FEATURE_NOTICES
|
||||||
|
DRAWER_ITEM_ATTENDANCE -> FEATURE_ATTENDANCE
|
||||||
|
DRAWER_ITEM_MESSAGES -> when (MessagesFragment.pageSelection) {
|
||||||
|
1 -> FEATURE_MESSAGES_OUTBOX
|
||||||
|
else -> FEATURE_MESSAGES_INBOX
|
||||||
}
|
}
|
||||||
|
DRAWER_ITEM_ANNOUNCEMENTS -> FEATURE_ANNOUNCEMENTS
|
||||||
|
else -> FEATURE_ALL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onSyncFinishedEvent(event: ApiTaskAllFinishedEvent) {
|
|
||||||
swipeRefreshLayout.isRefreshing = false
|
|
||||||
}
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onSyncErrorEvent(event: ApiTaskErrorEvent) {
|
|
||||||
navView.toolbar.apply {
|
|
||||||
subtitleFormat = R.string.toolbar_subtitle
|
|
||||||
subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread
|
|
||||||
subtitle = "Gotowe"
|
|
||||||
}
|
|
||||||
errorSnackbar.addError(event.error).show()
|
|
||||||
}
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
|
||||||
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
|
|
||||||
if (app.appConfig.dontShowAppManagerDialog)
|
|
||||||
return
|
|
||||||
MaterialAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.app_manager_dialog_title)
|
|
||||||
.setMessage(R.string.app_manager_dialog_text)
|
|
||||||
.setPositiveButton(R.string.ok) { dialog, which ->
|
|
||||||
try {
|
|
||||||
for (intent in appManagerIntentList) {
|
|
||||||
if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
|
|
||||||
startActivity(intent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
try {
|
|
||||||
startActivity(Intent(Settings.ACTION_SETTINGS))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.setNeutralButton(R.string.dont_ask_again) { dialog, which ->
|
|
||||||
app.appConfig.dontShowAppManagerDialog = true
|
|
||||||
app.saveConfig("dontShowAppManagerDialog")
|
|
||||||
}
|
|
||||||
.setCancelable(false)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fragmentToSyncName(currentFragment: Int): Int {
|
private fun fragmentToSyncName(currentFragment: Int): Int {
|
||||||
return when (currentFragment) {
|
return when (currentFragment) {
|
||||||
DRAWER_ITEM_TIMETABLE -> R.string.sync_feature_timetable
|
DRAWER_ITEM_TIMETABLE -> R.string.sync_feature_timetable
|
||||||
@ -668,11 +587,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
private fun handleIntent(extras: Bundle?) {
|
private fun handleIntent(extras: Bundle?) {
|
||||||
|
|
||||||
d(TAG, "handleIntent() {")
|
Log.d(TAG, "handleIntent() {")
|
||||||
extras?.keySet()?.forEach { key ->
|
extras?.keySet()?.forEach { key ->
|
||||||
d(TAG, " \"$key\": "+extras.get(key))
|
Log.d(TAG, " \"$key\": "+extras.get(key))
|
||||||
}
|
}
|
||||||
d(TAG, "}")
|
Log.d(TAG, "}")
|
||||||
|
|
||||||
if (extras?.containsKey("reloadProfileId") == true) {
|
if (extras?.containsKey("reloadProfileId") == true) {
|
||||||
val reloadProfileId = extras.getInt("reloadProfileId", -1)
|
val reloadProfileId = extras.getInt("reloadProfileId", -1)
|
||||||
@ -701,33 +620,29 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (navLoading) {
|
if (navLoading) {
|
||||||
|
navLoading = false
|
||||||
b.fragment.removeAllViews()
|
b.fragment.removeAllViews()
|
||||||
if (intentTargetId == -1)
|
if (intentTargetId == -1)
|
||||||
intentTargetId = HOME_ID
|
intentTargetId = HOME_ID
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
app.profile == null || app.profile.id == -1 -> {
|
app.profile == null -> {
|
||||||
if (intentProfileId == -1)
|
if (intentProfileId == -1)
|
||||||
intentProfileId = app.appSharedPrefs.getInt("current_profile_id", 1)
|
intentProfileId = app.appSharedPrefs.getInt("current_profile_id", 1)
|
||||||
loadProfile(intentProfileId, intentTargetId, extras)
|
loadProfile(intentProfileId, intentTargetId)
|
||||||
}
|
}
|
||||||
intentProfileId != -1 -> {
|
intentProfileId != -1 -> {
|
||||||
if (app.profile.id != intentProfileId)
|
loadProfile(intentProfileId, intentTargetId)
|
||||||
loadProfile(intentProfileId, intentTargetId, extras)
|
|
||||||
else
|
|
||||||
loadTarget(intentTargetId, extras)
|
|
||||||
}
|
}
|
||||||
intentTargetId != -1 -> {
|
intentTargetId != -1 -> {
|
||||||
drawer.currentProfile = app.profile.id
|
drawer.currentProfile = app.profile.id
|
||||||
if (navTargetId != intentTargetId || navLoading)
|
loadTarget(intentTargetId, extras)
|
||||||
loadTarget(intentTargetId, extras)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
drawer.currentProfile = app.profile.id
|
drawer.currentProfile = app.profile.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
navLoading = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recreate() {
|
override fun recreate() {
|
||||||
@ -775,7 +690,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!app.config.loginFinished)
|
if (!app.appConfig.loginFinished)
|
||||||
finish()
|
finish()
|
||||||
else {
|
else {
|
||||||
handleIntent(data?.extras)
|
handleIntent(data?.extras)
|
||||||
@ -800,7 +715,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
fun loadProfile(id: Int) = loadProfile(id, navTargetId)
|
fun loadProfile(id: Int) = loadProfile(id, navTargetId)
|
||||||
fun loadProfile(id: Int, arguments: Bundle?) = loadProfile(id, navTargetId, arguments)
|
fun loadProfile(id: Int, arguments: Bundle?) = loadProfile(id, navTargetId, arguments)
|
||||||
fun loadProfile(id: Int, drawerSelection: Int, arguments: Bundle? = null) {
|
fun loadProfile(id: Int, drawerSelection: Int, arguments: Bundle? = null) {
|
||||||
//d("NavDebug", "loadProfile(id = $id, drawerSelection = $drawerSelection)")
|
Log.d("NavDebug", "loadProfile(id = $id, drawerSelection = $drawerSelection)")
|
||||||
if (app.profile != null && App.profileId == id) {
|
if (app.profile != null && App.profileId == id) {
|
||||||
drawer.currentProfile = app.profile.id
|
drawer.currentProfile = app.profile.id
|
||||||
loadTarget(drawerSelection, arguments)
|
loadTarget(drawerSelection, arguments)
|
||||||
@ -812,16 +727,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
this.runOnUiThread {
|
this.runOnUiThread {
|
||||||
if (app.profile == null) {
|
if (app.profile == null) {
|
||||||
LoginActivity.firstCompleted = false
|
LoginActivity.firstCompleted = false
|
||||||
if (app.config.loginFinished) {
|
if (app.appConfig.loginFinished) {
|
||||||
// this shouldn't run
|
// this shouldn't run
|
||||||
profileListEmptyListener()
|
profileListEmptyListener()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setDrawerItems()
|
setDrawerItems()
|
||||||
// the drawer profile is updated automatically when the drawer item is clicked
|
drawer.currentProfile = app.profile.id
|
||||||
// update it manually when switching profiles from other source
|
|
||||||
//if (drawer.currentProfile != app.profile.id)
|
|
||||||
drawer.currentProfile = app.profile.id
|
|
||||||
loadTarget(drawerSelection, arguments)
|
loadTarget(drawerSelection, arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -843,7 +755,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun loadTarget(target: NavTarget, arguments: Bundle? = null) {
|
private fun loadTarget(target: NavTarget, arguments: Bundle? = null) {
|
||||||
d("NavDebug", "loadItem(id = ${target.id})")
|
Log.d("NavDebug", "loadItem(id = ${target.id})")
|
||||||
|
|
||||||
bottomSheet.close()
|
bottomSheet.close()
|
||||||
bottomSheet.removeAllContextual()
|
bottomSheet.removeAllContextual()
|
||||||
@ -856,7 +768,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
navView.bottomBar.fabExtended = false
|
navView.bottomBar.fabExtended = false
|
||||||
navView.bottomBar.setFabOnClickListener(null)
|
navView.bottomBar.setFabOnClickListener(null)
|
||||||
|
|
||||||
d("NavDebug", "Navigating from ${navTarget.fragmentClass?.java?.simpleName} to ${target.fragmentClass?.java?.simpleName}")
|
Log.d("NavDebug", "Navigating from ${navTarget.fragmentClass?.java?.simpleName} to ${target.fragmentClass?.java?.simpleName}")
|
||||||
|
|
||||||
val fragment = target.fragmentClass?.java?.newInstance() ?: return
|
val fragment = target.fragmentClass?.java?.newInstance() ?: return
|
||||||
fragment.arguments = arguments
|
fragment.arguments = arguments
|
||||||
@ -915,9 +827,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d("NavDebug", "Current fragment ${navTarget.fragmentClass?.java?.simpleName}, pop to home ${navTarget.popToHome}, back stack:")
|
Log.d("NavDebug", "Current fragment ${navTarget.fragmentClass?.java?.simpleName}, pop to home ${navTarget.popToHome}, back stack:")
|
||||||
navBackStack.forEachIndexed { index, target2 ->
|
navBackStack.forEachIndexed { index, target2 ->
|
||||||
d("NavDebug", " - $index: ${target2.fragmentClass?.java?.simpleName}")
|
Log.d("NavDebug", " - $index: ${target2.fragmentClass?.java?.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.replace(R.id.fragment, fragment)
|
transaction.replace(R.id.fragment, fragment)
|
||||||
@ -961,9 +873,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
* that something has changed in the bottom sheet.
|
* that something has changed in the bottom sheet.
|
||||||
*/
|
*/
|
||||||
fun gainAttention() {
|
fun gainAttention() {
|
||||||
b.navView.postDelayed({
|
/*b.navView.postDelayed({
|
||||||
navView.gainAttentionOnBottomBar()
|
navView.gainAttentionOnBottomBar()
|
||||||
}, 2000)
|
}, 2000)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fun gainAttentionFAB() {
|
fun gainAttentionFAB() {
|
||||||
@ -988,7 +900,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val item = DrawerPrimaryItem()
|
val item = DrawerPrimaryItem()
|
||||||
.withIdentifier(target.id.toLong())
|
.withIdentifier(target.id.toLong())
|
||||||
.withName(target.name)
|
.withName(target.name)
|
||||||
.withHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id))
|
.withHiddenInMiniDrawer(!app.appConfig.miniDrawerButtonIds.contains(target.id))
|
||||||
.also { if (target.description != null) it.withDescription(target.description!!) }
|
.also { if (target.description != null) it.withDescription(target.description!!) }
|
||||||
.also { if (target.icon != null) it.withIcon(target.icon!!) }
|
.also { if (target.icon != null) it.withIcon(target.icon!!) }
|
||||||
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
|
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
|
||||||
@ -1008,7 +920,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setDrawerItems() {
|
fun setDrawerItems() {
|
||||||
d("NavDebug", "setDrawerItems() app.profile = ${app.profile ?: "null"}")
|
Log.d("NavDebug", "setDrawerItems() app.profile = ${app.profile ?: "null"}")
|
||||||
val drawerItems = arrayListOf<IDrawerItem<*>>()
|
val drawerItems = arrayListOf<IDrawerItem<*>>()
|
||||||
val drawerProfiles = arrayListOf<ProfileSettingDrawerItem>()
|
val drawerProfiles = arrayListOf<ProfileSettingDrawerItem>()
|
||||||
|
|
||||||
@ -1066,7 +978,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
loadTarget(DRAWER_ITEM_SETTINGS, null)
|
loadTarget(DRAWER_ITEM_SETTINGS, null)
|
||||||
} else if (item.itemId == 2) {
|
} else if (item.itemId == 2) {
|
||||||
ProfileRemoveDialog(this, profileId, profile.name?.getText(this)?.toString() ?: "?")
|
app.apiEdziennik.guiRemoveProfile(this@MainActivity, profileId, profile.name?.getText(this).toString())
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -1077,11 +989,30 @@ class MainActivity : AppCompatActivity() {
|
|||||||
private var targetHomeId: Int = -1
|
private var targetHomeId: Int = -1
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
if (!b.navView.onBackPressed()) {
|
if (!b.navView.onBackPressed()) {
|
||||||
if (App.getConfig().ui.openDrawerOnBackPressed) {
|
|
||||||
b.navView.drawer.toggle()
|
navigateUp()
|
||||||
|
|
||||||
|
/*val currentDestinationId = navController.currentDestination?.id
|
||||||
|
|
||||||
|
if (if (targetHomeId != -1 && targetPopToHomeList.contains(navController.currentDestination?.id)) {
|
||||||
|
if (!navController.popBackStack(targetHomeId, false)) {
|
||||||
|
navController.navigateUp()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
navController.navigateUp()
|
||||||
|
}) {
|
||||||
|
val currentId = navController.currentDestination?.id ?: -1
|
||||||
|
val drawerSelection = navTargetList
|
||||||
|
.singleOrNull {
|
||||||
|
it.navGraphId == currentId
|
||||||
|
}?.also {
|
||||||
|
navView.toolbar.setTitle(it.title ?: it.name)
|
||||||
|
}?.id ?: -1
|
||||||
|
drawer.setSelection(drawerSelection, false)
|
||||||
} else {
|
} else {
|
||||||
navigateUp()
|
super.onBackPressed()
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,22 +8,24 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
||||||
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||||
|
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
||||||
|
import pl.szczodrzynski.edziennik.sync.SyncJob;
|
||||||
|
import pl.szczodrzynski.edziennik.sync.SyncService;
|
||||||
|
|
||||||
import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
|
import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
|
||||||
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
|
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
|
||||||
|
import static pl.szczodrzynski.edziennik.sync.SyncService.ACTION_CANCEL;
|
||||||
|
|
||||||
public class Notifier {
|
public class Notifier {
|
||||||
|
|
||||||
@ -34,14 +36,14 @@ public class Notifier {
|
|||||||
private static String CHANNEL_GET_DATA_DESC;
|
private static String CHANNEL_GET_DATA_DESC;
|
||||||
private static final String GROUP_KEY_GET_DATA = "pl.szczodrzynski.edziennik.GET_DATA";
|
private static final String GROUP_KEY_GET_DATA = "pl.szczodrzynski.edziennik.GET_DATA";
|
||||||
|
|
||||||
public static final int ID_NOTIFICATIONS = 1337002;
|
private static final int ID_NOTIFICATIONS = 1337002;
|
||||||
public static String CHANNEL_NOTIFICATIONS_NAME;
|
private static String CHANNEL_NOTIFICATIONS_NAME;
|
||||||
public static String CHANNEL_NOTIFICATIONS_DESC;
|
private static String CHANNEL_NOTIFICATIONS_DESC;
|
||||||
public static final String GROUP_KEY_NOTIFICATIONS = "pl.szczodrzynski.edziennik.NOTIFICATIONS";
|
public static final String GROUP_KEY_NOTIFICATIONS = "pl.szczodrzynski.edziennik.NOTIFICATIONS";
|
||||||
|
|
||||||
public static final int ID_NOTIFICATIONS_QUIET = 1337002;
|
private static final int ID_NOTIFICATIONS_QUIET = 1337002;
|
||||||
public static String CHANNEL_NOTIFICATIONS_QUIET_NAME;
|
private static String CHANNEL_NOTIFICATIONS_QUIET_NAME;
|
||||||
public static String CHANNEL_NOTIFICATIONS_QUIET_DESC;
|
private static String CHANNEL_NOTIFICATIONS_QUIET_DESC;
|
||||||
public static final String GROUP_KEY_NOTIFICATIONS_QUIET = "pl.szczodrzynski.edziennik.NOTIFICATIONS_QUIET";
|
public static final String GROUP_KEY_NOTIFICATIONS_QUIET = "pl.szczodrzynski.edziennik.NOTIFICATIONS_QUIET";
|
||||||
|
|
||||||
private static final int ID_UPDATES = 1337003;
|
private static final int ID_UPDATES = 1337003;
|
||||||
@ -50,9 +52,9 @@ public class Notifier {
|
|||||||
private static final String GROUP_KEY_UPDATES = "pl.szczodrzynski.edziennik.UPDATES";
|
private static final String GROUP_KEY_UPDATES = "pl.szczodrzynski.edziennik.UPDATES";
|
||||||
|
|
||||||
private App app;
|
private App app;
|
||||||
public NotificationManager notificationManager;
|
private NotificationManager notificationManager;
|
||||||
private NotificationCompat.Builder getDataNotificationBuilder;
|
private NotificationCompat.Builder getDataNotificationBuilder;
|
||||||
public int notificationColor;
|
private int notificationColor;
|
||||||
|
|
||||||
Notifier(App _app) {
|
Notifier(App _app) {
|
||||||
this.app = _app;
|
this.app = _app;
|
||||||
@ -69,7 +71,7 @@ public class Notifier {
|
|||||||
notificationColor = ContextCompat.getColor(app.getContext(), R.color.colorPrimary);
|
notificationColor = ContextCompat.getColor(app.getContext(), R.color.colorPrimary);
|
||||||
notificationManager = (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
|
notificationManager = (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
NotificationChannel channelGetData = new NotificationChannel(GROUP_KEY_GET_DATA, CHANNEL_GET_DATA_NAME, NotificationManager.IMPORTANCE_MIN);
|
NotificationChannel channelGetData = new NotificationChannel(GROUP_KEY_GET_DATA, CHANNEL_GET_DATA_NAME, NotificationManager.IMPORTANCE_LOW);
|
||||||
channelGetData.setDescription(CHANNEL_GET_DATA_DESC);
|
channelGetData.setDescription(CHANNEL_GET_DATA_DESC);
|
||||||
notificationManager.createNotificationChannel(channelGetData);
|
notificationManager.createNotificationChannel(channelGetData);
|
||||||
|
|
||||||
@ -93,8 +95,8 @@ public class Notifier {
|
|||||||
|
|
||||||
public boolean shouldBeQuiet() {
|
public boolean shouldBeQuiet() {
|
||||||
long now = Time.getNow().getInMillis();
|
long now = Time.getNow().getInMillis();
|
||||||
long start = app.config.getSync().getQuietHoursStart();
|
long start = app.appConfig.quietHoursStart;
|
||||||
long end = app.config.getSync().getQuietHoursEnd();
|
long end = app.appConfig.quietHoursEnd;
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
end += 1000 * 60 * 60 * 24;
|
end += 1000 * 60 * 60 * 24;
|
||||||
//Log.d(TAG, "Night passing");
|
//Log.d(TAG, "Night passing");
|
||||||
@ -104,16 +106,16 @@ public class Notifier {
|
|||||||
//Log.d(TAG, "Now is smaller");
|
//Log.d(TAG, "Now is smaller");
|
||||||
}
|
}
|
||||||
//Log.d(TAG, "Start is "+start+", now is "+now+", end is "+end);
|
//Log.d(TAG, "Start is "+start+", now is "+now+", end is "+end);
|
||||||
return start > 0 && now >= start && now <= end;
|
return app.appConfig.quietHoursStart > 0 && now >= start && now <= end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNotificationDefaults() {
|
private int getNotificationDefaults() {
|
||||||
return (shouldBeQuiet() ? 0 : Notification.DEFAULT_ALL);
|
return (shouldBeQuiet() ? 0 : Notification.DEFAULT_ALL);
|
||||||
}
|
}
|
||||||
public String getNotificationGroup() {
|
private String getNotificationGroup() {
|
||||||
return shouldBeQuiet() ? GROUP_KEY_NOTIFICATIONS_QUIET : GROUP_KEY_NOTIFICATIONS;
|
return shouldBeQuiet() ? GROUP_KEY_NOTIFICATIONS_QUIET : GROUP_KEY_NOTIFICATIONS;
|
||||||
}
|
}
|
||||||
public int getNotificationPriority() {
|
private int getNotificationPriority() {
|
||||||
return shouldBeQuiet() ? PRIORITY_DEFAULT : PRIORITY_MAX;
|
return shouldBeQuiet() ? PRIORITY_DEFAULT : PRIORITY_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,17 +126,17 @@ public class Notifier {
|
|||||||
| |__| | (_| | || (_| | | |__| | __/ |_
|
| |__| | (_| | || (_| | | |__| | __/ |_
|
||||||
|_____/ \__,_|\__\__,_| \_____|\___|\_*/
|
|_____/ \__,_|\__\__,_| \_____|\___|\_*/
|
||||||
public Notification notificationGetDataShow(int maxProgress) {
|
public Notification notificationGetDataShow(int maxProgress) {
|
||||||
/*Intent notificationIntent = new Intent(app.getContext(), SyncService.class);
|
Intent notificationIntent = new Intent(app.getContext(), SyncService.class);
|
||||||
notificationIntent.setAction(ACTION_CANCEL);
|
notificationIntent.setAction(ACTION_CANCEL);
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);*/
|
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
getDataNotificationBuilder = new NotificationCompat.Builder(app, GROUP_KEY_GET_DATA)
|
getDataNotificationBuilder = new NotificationCompat.Builder(app, GROUP_KEY_GET_DATA)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
.setColor(notificationColor)
|
.setColor(notificationColor)
|
||||||
.setContentTitle(app.getString(R.string.notification_get_data_title))
|
.setContentTitle(app.getString(R.string.notification_get_data_title))
|
||||||
.setContentText(app.getString(R.string.notification_get_data_text))
|
.setContentText(app.getString(R.string.notification_get_data_text))
|
||||||
//.addAction(R.drawable.ic_notification, app.getString(R.string.notification_get_data_cancel), pendingIntent)
|
.addAction(R.drawable.ic_notification, app.getString(R.string.notification_get_data_cancel), pendingIntent)
|
||||||
//.setGroup(GROUP_KEY_GET_DATA)
|
//.setGroup(GROUP_KEY_GET_DATA)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setProgress(maxProgress, 0, false)
|
.setProgress(maxProgress, 0, false)
|
||||||
@ -206,8 +208,10 @@ public class Notifier {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
SyncJob.run((App) getApplication(), intent.getExtras().getInt("failedProfileId", -1), -1);
|
||||||
|
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
assert notificationManager != null;
|
||||||
|
notificationManager.cancel(ID_GET_DATA_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,14 +315,13 @@ public class Notifier {
|
|||||||
\____/| .__/ \__,_|\__,_|\__\___||___/
|
\____/| .__/ \__,_|\__,_|\__\___||___/
|
||||||
| |
|
| |
|
||||||
|*/
|
|*/
|
||||||
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename, boolean updateDirect) {
|
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename) {
|
||||||
if (!app.config.getSync().getNotifyAboutUpdates())
|
if (!app.appConfig.notifyAboutUpdates)
|
||||||
return;
|
return;
|
||||||
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
||||||
.putExtra("update_version", updateVersion)
|
.putExtra("update_version", updateVersion)
|
||||||
.putExtra("update_url", updateUrl)
|
.putExtra("update_url", updateUrl)
|
||||||
.putExtra("update_filename", updateFilename)
|
.putExtra("update_filename", updateFilename);
|
||||||
.putExtra("update_direct", updateDirect);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
@ -340,7 +343,7 @@ public class Notifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notificationUpdatesHide() {
|
public void notificationUpdatesHide() {
|
||||||
if (!app.config.getSync().getNotifyAboutUpdates())
|
if (!app.appConfig.notifyAboutUpdates)
|
||||||
return;
|
return;
|
||||||
notificationManager.cancel(ID_UPDATES);
|
notificationManager.cancel(ID_UPDATES);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,450 @@
|
|||||||
|
package pl.szczodrzynski.edziennik;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.appwidget.AppWidgetManager;
|
||||||
|
import android.appwidget.AppWidgetProvider;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.RemoteViews;
|
||||||
|
|
||||||
|
import com.mikepenz.iconics.IconicsColor;
|
||||||
|
import com.mikepenz.iconics.IconicsDrawable;
|
||||||
|
import com.mikepenz.iconics.IconicsSize;
|
||||||
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel;
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Week;
|
||||||
|
import pl.szczodrzynski.edziennik.widgets.WidgetConfig;
|
||||||
|
import pl.szczodrzynski.edziennik.sync.SyncJob;
|
||||||
|
import pl.szczodrzynski.edziennik.widgets.timetable.LessonDetailsActivity;
|
||||||
|
import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService;
|
||||||
|
|
||||||
|
import static pl.szczodrzynski.edziennik.ExtensionsKt.filterOutArchived;
|
||||||
|
import static pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK;
|
||||||
|
import static pl.szczodrzynski.edziennik.utils.Utils.bs;
|
||||||
|
|
||||||
|
|
||||||
|
public class WidgetTimetable extends AppWidgetProvider {
|
||||||
|
|
||||||
|
|
||||||
|
public static final String ACTION_SYNC_DATA = "ACTION_SYNC_DATA";
|
||||||
|
private static final String TAG = "WidgetTimetable";
|
||||||
|
private static int modeInt = 0;
|
||||||
|
|
||||||
|
public WidgetTimetable() {
|
||||||
|
// Start the worker thread
|
||||||
|
//HandlerThread sWorkerThread = new HandlerThread("WidgetTimetable-worker");
|
||||||
|
//sWorkerThread.start();
|
||||||
|
//Handler sWorkerQueue = new Handler(sWorkerThread.getLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SparseArray<List<ItemWidgetTimetableModel>> timetables = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (ACTION_SYNC_DATA.equals(intent.getAction())){
|
||||||
|
SyncJob.run((App) context.getApplicationContext());
|
||||||
|
}
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PendingIntent getPendingSelfIntent(Context context, String action) {
|
||||||
|
Intent intent = new Intent(context, WidgetTimetable.class);
|
||||||
|
intent.setAction(action);
|
||||||
|
return getPendingSelfIntent(context, intent);
|
||||||
|
}
|
||||||
|
public static PendingIntent getPendingSelfIntent(Context context, Intent intent) {
|
||||||
|
return PendingIntent.getBroadcast(context, 0, intent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap drawableToBitmap (Drawable drawable) {
|
||||||
|
|
||||||
|
if (drawable instanceof BitmapDrawable) {
|
||||||
|
return ((BitmapDrawable)drawable).getBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
drawable.draw(canvas);
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||||
|
ComponentName thisWidget = new ComponentName(context, WidgetTimetable.class);
|
||||||
|
|
||||||
|
timetables = new SparseArray<>();
|
||||||
|
//timetables.clear();
|
||||||
|
|
||||||
|
App app = (App)context.getApplicationContext();
|
||||||
|
|
||||||
|
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||||
|
// There may be multiple widgets active, so update all of them
|
||||||
|
for (int appWidgetId : allWidgetIds) {
|
||||||
|
|
||||||
|
//d(TAG, "thr "+Thread.currentThread().getName());
|
||||||
|
|
||||||
|
WidgetConfig widgetConfig = app.appConfig.widgetTimetableConfigs.get(appWidgetId);
|
||||||
|
if (widgetConfig == null) {
|
||||||
|
widgetConfig = new WidgetConfig(app.profileFirstId());
|
||||||
|
app.appConfig.widgetTimetableConfigs.put(appWidgetId, widgetConfig);
|
||||||
|
app.appConfig.savePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteViews views;
|
||||||
|
if (widgetConfig.bigStyle) {
|
||||||
|
views = new RemoteViews(context.getPackageName(), widgetConfig.darkTheme ? R.layout.widget_timetable_dark_big : R.layout.widget_timetable_big);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
views = new RemoteViews(context.getPackageName(), widgetConfig.darkTheme ? R.layout.widget_timetable_dark : R.layout.widget_timetable);
|
||||||
|
}
|
||||||
|
|
||||||
|
PorterDuff.Mode mode = PorterDuff.Mode.DST_IN;
|
||||||
|
/*if (widgetConfig.darkTheme) {
|
||||||
|
switch (modeInt) {
|
||||||
|
case 0:
|
||||||
|
mode = PorterDuff.Mode.ADD;
|
||||||
|
d(TAG, "ADD");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mode = PorterDuff.Mode.DST_ATOP;
|
||||||
|
d(TAG, "DST_ATOP");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mode = PorterDuff.Mode.DST_IN;
|
||||||
|
d(TAG, "DST_IN");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
mode = PorterDuff.Mode.DST_OUT;
|
||||||
|
d(TAG, "DST_OUT");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
mode = PorterDuff.Mode.DST_OVER;
|
||||||
|
d(TAG, "DST_OVER");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
mode = PorterDuff.Mode.LIGHTEN;
|
||||||
|
d(TAG, "LIGHTEN");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
mode = PorterDuff.Mode.MULTIPLY;
|
||||||
|
d(TAG, "MULTIPLY");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
mode = PorterDuff.Mode.OVERLAY;
|
||||||
|
d(TAG, "OVERLAY");
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
mode = PorterDuff.Mode.SCREEN;
|
||||||
|
d(TAG, "SCREEN");
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
mode = PorterDuff.Mode.SRC_ATOP;
|
||||||
|
d(TAG, "SRC_ATOP");
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
mode = PorterDuff.Mode.SRC_IN;
|
||||||
|
d(TAG, "SRC_IN");
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
mode = PorterDuff.Mode.SRC_OUT;
|
||||||
|
d(TAG, "SRC_OUT");
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
mode = PorterDuff.Mode.SRC_OVER;
|
||||||
|
d(TAG, "SRC_OVER");
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
mode = PorterDuff.Mode.XOR;
|
||||||
|
d(TAG, "XOR");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
modeInt = 0;
|
||||||
|
mode = PorterDuff.Mode.ADD;
|
||||||
|
d(TAG, "ADD");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||||
|
// this code seems to crash the launcher on >= P
|
||||||
|
float transparency = widgetConfig.opacity; //0...1
|
||||||
|
long colorFilter = 0x01000000L * (long) (255f * transparency);
|
||||||
|
try {
|
||||||
|
final Method[] declaredMethods = Class.forName("android.widget.RemoteViews").getDeclaredMethods();
|
||||||
|
final int len = declaredMethods.length;
|
||||||
|
if (len > 0) {
|
||||||
|
for (int m = 0; m < len; m++) {
|
||||||
|
final Method method = declaredMethods[m];
|
||||||
|
if (method.getName().equals("setDrawableParameters")) {
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(views, R.id.widgetTimetableListView, true, -1, (int) colorFilter, mode, -1);
|
||||||
|
method.invoke(views, R.id.widgetTimetableHeader, true, -1, (int) colorFilter, mode, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent refreshIntent = new Intent(context, WidgetTimetable.class);
|
||||||
|
refreshIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
||||||
|
refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
|
||||||
|
PendingIntent pendingRefreshIntent = PendingIntent.getBroadcast(context,
|
||||||
|
0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, pendingRefreshIntent);
|
||||||
|
|
||||||
|
views.setOnClickPendingIntent(R.id.widgetTimetableSync, WidgetTimetable.getPendingSelfIntent(context, ACTION_SYNC_DATA));
|
||||||
|
|
||||||
|
views.setImageViewBitmap(R.id.widgetTimetableRefresh, new IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh)
|
||||||
|
.color(IconicsColor.colorInt(Color.WHITE))
|
||||||
|
.size(IconicsSize.dp(widgetConfig.bigStyle ? 24 : 16)).toBitmap());
|
||||||
|
|
||||||
|
views.setImageViewBitmap(R.id.widgetTimetableSync, new IconicsDrawable(context, CommunityMaterial.Icon2.cmd_sync)
|
||||||
|
.color(IconicsColor.colorInt(Color.WHITE))
|
||||||
|
.size(IconicsSize.dp(widgetConfig.bigStyle ? 24 : 16)).toBitmap());
|
||||||
|
|
||||||
|
boolean unified = widgetConfig.profileId == -1;
|
||||||
|
|
||||||
|
List<Profile> profileList = new ArrayList<>();
|
||||||
|
if (unified) {
|
||||||
|
profileList = app.db.profileDao().getAllNow();
|
||||||
|
filterOutArchived(profileList);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Profile profile = app.db.profileDao().getByIdNow(widgetConfig.profileId);
|
||||||
|
if (profile != null) {
|
||||||
|
profileList.add(profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//d(TAG, "Profiles: "+ Arrays.toString(profileList.toArray()));
|
||||||
|
|
||||||
|
if (profileList == null || profileList.size() == 0) {
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE);
|
||||||
|
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_profile_doesnt_exist));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE);
|
||||||
|
//Register profile;
|
||||||
|
|
||||||
|
long bellSyncDiffMillis = 0;
|
||||||
|
if (app.appConfig.bellSyncDiff != null) {
|
||||||
|
bellSyncDiffMillis = app.appConfig.bellSyncDiff.hour * 60 * 60 * 1000 + app.appConfig.bellSyncDiff.minute * 60 * 1000 + app.appConfig.bellSyncDiff.second * 1000;
|
||||||
|
bellSyncDiffMillis *= app.appConfig.bellSyncMultiplier;
|
||||||
|
bellSyncDiffMillis *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ItemWidgetTimetableModel> lessonList = new ArrayList<>();
|
||||||
|
|
||||||
|
Time syncedNow = Time.fromMillis(Time.getNow().getInMillis() + bellSyncDiffMillis);
|
||||||
|
|
||||||
|
Date today = Date.getToday();
|
||||||
|
|
||||||
|
int openProfileId = -1;
|
||||||
|
Date displayingDate = null;
|
||||||
|
int displayingWeekDay = 0;
|
||||||
|
if (unified) {
|
||||||
|
views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.widget_timetable_title_unified));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
views.setTextViewText(R.id.widgetTimetableSubtitle, profileList.get(0).getName());
|
||||||
|
openProfileId = profileList.get(0).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LessonFull> lessons = app.db.lessonDao().getAllWeekNow(unified ? -1 : openProfileId, today.clone().stepForward(0, 0, -today.getWeekDay()), today);
|
||||||
|
|
||||||
|
int scrollPos = 0;
|
||||||
|
|
||||||
|
for (Profile profile: profileList) {
|
||||||
|
Date profileDisplayingDate = HomeFragment.findDateWithLessons(profile.getId(), lessons, syncedNow, 1);
|
||||||
|
int profileDisplayingWeekDay = profileDisplayingDate.getWeekDay();
|
||||||
|
int dayDiff = Date.diffDays(profileDisplayingDate, Date.getToday());
|
||||||
|
|
||||||
|
//d(TAG, "For profile "+profile.name+" displayingDate is "+profileDisplayingDate.getStringY_m_d());
|
||||||
|
if (displayingDate == null || profileDisplayingDate.getValue() < displayingDate.getValue()) {
|
||||||
|
displayingDate = profileDisplayingDate;
|
||||||
|
displayingWeekDay = profileDisplayingWeekDay;
|
||||||
|
//d(TAG, "Setting as global dd");
|
||||||
|
if (dayDiff == 0) {
|
||||||
|
views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.day_today_format, Week.getFullDayName(displayingWeekDay)));
|
||||||
|
} else if (dayDiff == 1) {
|
||||||
|
views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.day_tomorrow_format, Week.getFullDayName(displayingWeekDay)));
|
||||||
|
} else {
|
||||||
|
views.setTextViewText(R.id.widgetTimetableTitle, Week.getFullDayName(displayingWeekDay) + " " + profileDisplayingDate.getStringDm());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Profile profile: profileList) {
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
List<EventFull> events = app.db.eventDao().getAllByDateNow(profile.getId(), displayingDate);
|
||||||
|
if (events == null)
|
||||||
|
events = new ArrayList<>();
|
||||||
|
|
||||||
|
if (unified) {
|
||||||
|
ItemWidgetTimetableModel separator = new ItemWidgetTimetableModel();
|
||||||
|
separator.profileId = profile.getId();
|
||||||
|
separator.bigStyle = widgetConfig.bigStyle;
|
||||||
|
separator.darkTheme = widgetConfig.darkTheme;
|
||||||
|
separator.separatorProfileName = profile.getName();
|
||||||
|
lessonList.add(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (LessonFull lesson : lessons) {
|
||||||
|
//d(TAG, "Profile "+profile.id+" Lesson profileId "+lesson.profileId+" weekDay "+lesson.weekDay+", "+lesson);
|
||||||
|
if (profile.getId() != lesson.profileId || displayingWeekDay != lesson.weekDay)
|
||||||
|
continue;
|
||||||
|
//d(TAG, "Not skipped");
|
||||||
|
ItemWidgetTimetableModel model = new ItemWidgetTimetableModel();
|
||||||
|
|
||||||
|
model.bigStyle = widgetConfig.bigStyle;
|
||||||
|
model.darkTheme = widgetConfig.darkTheme;
|
||||||
|
|
||||||
|
model.profileId = profile.getId();
|
||||||
|
|
||||||
|
model.lessonDate = displayingDate;
|
||||||
|
model.startTime = lesson.startTime;
|
||||||
|
model.endTime = lesson.endTime;
|
||||||
|
|
||||||
|
model.lessonPassed = (syncedNow.getValue() > lesson.endTime.getValue()) && displayingWeekDay == Week.getTodayWeekDay();
|
||||||
|
model.lessonCurrent = (Time.inRange(lesson.startTime, lesson.endTime, syncedNow)) && displayingWeekDay == Week.getTodayWeekDay();
|
||||||
|
|
||||||
|
if (model.lessonCurrent) {
|
||||||
|
scrollPos = pos;
|
||||||
|
} else if (model.lessonPassed) {
|
||||||
|
scrollPos = pos + 1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
model.subjectName = bs(lesson.subjectLongName);
|
||||||
|
model.classroomName = lesson.classroomName;
|
||||||
|
|
||||||
|
model.bellSyncDiffMillis = bellSyncDiffMillis;
|
||||||
|
|
||||||
|
if (lesson.changeId != 0) {
|
||||||
|
if (lesson.changeType == LessonChange.TYPE_CHANGE) {
|
||||||
|
model.lessonChange = true;
|
||||||
|
if (lesson.changedClassroomName()) {
|
||||||
|
model.newClassroomName = lesson.changeClassroomName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lesson.changedSubjectLongName()) {
|
||||||
|
model.newSubjectName = lesson.changeSubjectLongName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lesson.changeType == LessonChange.TYPE_CANCELLED) {
|
||||||
|
model.lessonCancelled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (EventFull event : events) {
|
||||||
|
if (event.startTime == null)
|
||||||
|
continue;
|
||||||
|
if (event.eventDate.getValue() == displayingDate.getValue()
|
||||||
|
&& event.startTime.getValue() == lesson.startTime.getValue()) {
|
||||||
|
model.eventColors.add(event.type == TYPE_HOMEWORK ? ItemWidgetTimetableModel.EVENT_COLOR_HOMEWORK : event.getColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lessonList.add(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lessonList.size() == 0) {
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE);
|
||||||
|
views.setRemoteAdapter(R.id.widgetTimetableListView, new Intent());
|
||||||
|
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons));
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE);
|
||||||
|
|
||||||
|
timetables.put(appWidgetId, lessonList);
|
||||||
|
//WidgetTimetableListProvider.widgetsLessons.put(appWidgetId, lessons);
|
||||||
|
//views.setRemoteAdapter(R.id.widgetTimetableListView, new Intent());
|
||||||
|
Intent listIntent = new Intent(context, WidgetTimetableService.class);
|
||||||
|
listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||||
|
listIntent.setData(Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME)));
|
||||||
|
views.setRemoteAdapter(R.id.widgetTimetableListView, listIntent);
|
||||||
|
|
||||||
|
// template to handle the click listener for each item
|
||||||
|
Intent intentTemplate = new Intent(context, LessonDetailsActivity.class);
|
||||||
|
// Old activities shouldn't be in the history stack
|
||||||
|
intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
PendingIntent pendingIntentTimetable = PendingIntent.getActivity(context,
|
||||||
|
0,
|
||||||
|
intentTemplate,
|
||||||
|
0);
|
||||||
|
views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable);
|
||||||
|
|
||||||
|
Intent openIntent = new Intent(context, MainActivity.class);
|
||||||
|
openIntent.setAction("android.intent.action.MAIN");
|
||||||
|
if (!unified) {
|
||||||
|
openIntent.putExtra("profileId", openProfileId);
|
||||||
|
openIntent.putExtra("timetableDate", displayingDate.getValue());
|
||||||
|
}
|
||||||
|
openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE);
|
||||||
|
PendingIntent pendingOpenIntent = PendingIntent.getActivity(context,
|
||||||
|
appWidgetId, openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent);
|
||||||
|
|
||||||
|
if (!unified)
|
||||||
|
views.setScrollPosition(R.id.widgetTimetableListView, scrollPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||||
|
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetTimetableListView);
|
||||||
|
}
|
||||||
|
//modeInt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnabled(Context context) {
|
||||||
|
// Enter relevant functionality for when the first widget is created
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleted(Context context, int[] appWidgetIds) {
|
||||||
|
App app = (App) context.getApplicationContext();
|
||||||
|
for (int appWidgetId: appWidgetIds) {
|
||||||
|
app.appConfig.widgetTimetableConfigs.remove(appWidgetId);
|
||||||
|
}
|
||||||
|
app.saveConfig("widgetTimetableConfigs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,371 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik
|
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.appwidget.AppWidgetManager
|
|
||||||
import android.appwidget.AppWidgetProvider
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.graphics.drawable.BitmapDrawable
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.SparseArray
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.RemoteViews
|
|
||||||
import com.mikepenz.iconics.IconicsDrawable
|
|
||||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
|
||||||
import com.mikepenz.iconics.utils.colorInt
|
|
||||||
import com.mikepenz.iconics.utils.sizeDp
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.WidgetConfig
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.timetable.LessonDialogActivity
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService
|
|
||||||
import java.lang.reflect.InvocationTargetException
|
|
||||||
|
|
||||||
|
|
||||||
class WidgetTimetable : AppWidgetProvider() {
|
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
if (ACTION_SYNC_DATA == intent.action) {
|
|
||||||
EdziennikTask.sync().enqueue(context)
|
|
||||||
}
|
|
||||||
super.onReceive(context, intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
|
||||||
val thisWidget = ComponentName(context, WidgetTimetable::class.java)
|
|
||||||
|
|
||||||
timetables = SparseArray()
|
|
||||||
//timetables.clear();
|
|
||||||
|
|
||||||
val app = context.applicationContext as App
|
|
||||||
|
|
||||||
var bellSyncDiffMillis: Long = 0
|
|
||||||
app.config.timetable.bellSyncDiff?.let {
|
|
||||||
bellSyncDiffMillis = (it.hour * 60 * 60 * 1000 + it.minute * 60 * 1000 + it.second * 1000).toLong()
|
|
||||||
bellSyncDiffMillis *= app.config.timetable.bellSyncMultiplier.toLong()
|
|
||||||
bellSyncDiffMillis *= -1
|
|
||||||
}
|
|
||||||
|
|
||||||
val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget)
|
|
||||||
|
|
||||||
allWidgetIds?.forEach { appWidgetId ->
|
|
||||||
var widgetConfig = app.appConfig.widgetTimetableConfigs[appWidgetId]
|
|
||||||
if (widgetConfig == null) {
|
|
||||||
widgetConfig = WidgetConfig(app.profileFirstId())
|
|
||||||
app.appConfig.widgetTimetableConfigs[appWidgetId] = widgetConfig
|
|
||||||
app.appConfig.savePending = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val views = if (widgetConfig.bigStyle) {
|
|
||||||
RemoteViews(context.packageName, if (widgetConfig.darkTheme) R.layout.widget_timetable_dark_big else R.layout.widget_timetable_big)
|
|
||||||
} else {
|
|
||||||
RemoteViews(context.packageName, if (widgetConfig.darkTheme) R.layout.widget_timetable_dark else R.layout.widget_timetable)
|
|
||||||
}
|
|
||||||
|
|
||||||
val refreshIntent = Intent(app, WidgetTimetable::class.java)
|
|
||||||
refreshIntent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
|
||||||
refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
|
|
||||||
val pendingRefreshIntent = PendingIntent.getBroadcast(context,
|
|
||||||
0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, pendingRefreshIntent)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetTimetableSync, getPendingSelfIntent(context, ACTION_SYNC_DATA))
|
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.widgetTimetableRefresh, IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh)
|
|
||||||
.colorInt(Color.WHITE)
|
|
||||||
.sizeDp(if (widgetConfig.bigStyle) 24 else 16).toBitmap())
|
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.widgetTimetableSync, IconicsDrawable(context, CommunityMaterial.Icon.cmd_download_outline)
|
|
||||||
.colorInt(Color.WHITE)
|
|
||||||
.sizeDp(if (widgetConfig.bigStyle) 24 else 16).toBitmap())
|
|
||||||
|
|
||||||
prepareAppWidget(app, appWidgetId, views, widgetConfig, bellSyncDiffMillis)
|
|
||||||
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
||||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetTimetableListView)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareAppWidget(
|
|
||||||
app: App,
|
|
||||||
appWidgetId: Int,
|
|
||||||
views: RemoteViews,
|
|
||||||
widgetConfig: WidgetConfig,
|
|
||||||
bellSyncDiffMillis: Long
|
|
||||||
) {
|
|
||||||
// get the current bell-synced time
|
|
||||||
val now = Time.fromMillis(Time.getNow().inMillis + bellSyncDiffMillis)
|
|
||||||
|
|
||||||
// set the widget transparency
|
|
||||||
val mode = PorterDuff.Mode.DST_IN
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
|
||||||
// this code seems to crash the launcher on >= P
|
|
||||||
val transparency = widgetConfig.opacity //0...1
|
|
||||||
val colorFilter = 0x01000000L * (255f * transparency).toLong()
|
|
||||||
try {
|
|
||||||
val declaredMethods = Class.forName("android.widget.RemoteViews").declaredMethods
|
|
||||||
val len = declaredMethods.size
|
|
||||||
if (len > 0) {
|
|
||||||
for (m in 0 until len) {
|
|
||||||
val method = declaredMethods[m]
|
|
||||||
if (method.name == "setDrawableParameters") {
|
|
||||||
method.isAccessible = true
|
|
||||||
method.invoke(views, R.id.widgetTimetableListView, true, -1, colorFilter.toInt(), mode, -1)
|
|
||||||
method.invoke(views, R.id.widgetTimetableHeader, true, -1, colorFilter.toInt(), mode, -1)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: ClassNotFoundException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: InvocationTargetException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val unified = widgetConfig.profileId == -1
|
|
||||||
|
|
||||||
// get all profiles or one profile with the specified id
|
|
||||||
val profileList = if (unified)
|
|
||||||
app.db.profileDao().allNow.filterOutArchived()
|
|
||||||
else
|
|
||||||
listOfNotNull(app.db.profileDao().getByIdNow(widgetConfig.profileId))
|
|
||||||
|
|
||||||
// no profile was found
|
|
||||||
if (profileList.isEmpty()) {
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE)
|
|
||||||
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_profile_doesnt_exist))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE)
|
|
||||||
|
|
||||||
// set lesson search bounds
|
|
||||||
val today = Date.getToday()
|
|
||||||
val searchEnd = today.clone().stepForward(0, 0, 7)
|
|
||||||
|
|
||||||
var scrollPos = 0
|
|
||||||
|
|
||||||
var profileId: Int? = null
|
|
||||||
var displayingDate: Date? = null
|
|
||||||
|
|
||||||
val models = mutableListOf<ItemWidgetTimetableModel>()
|
|
||||||
|
|
||||||
// get all lessons within the search bounds
|
|
||||||
val lessonList = app.db.timetableDao().getBetweenDatesNow(today, searchEnd)
|
|
||||||
|
|
||||||
for (profile in profileList) {
|
|
||||||
|
|
||||||
// add a profile separator with its name
|
|
||||||
if (unified) {
|
|
||||||
val separator = ItemWidgetTimetableModel()
|
|
||||||
separator.profileId = profile.id
|
|
||||||
separator.bigStyle = widgetConfig.bigStyle
|
|
||||||
separator.darkTheme = widgetConfig.darkTheme
|
|
||||||
separator.separatorProfileName = profile.name
|
|
||||||
models.add(separator)
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for lessons to display
|
|
||||||
val timetableDate = Date.getToday()
|
|
||||||
var checkedDays = 0
|
|
||||||
var lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
|
|
||||||
while ((lessons.isEmpty() || lessons.none {
|
|
||||||
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
|
|
||||||
}) && checkedDays < 7) {
|
|
||||||
timetableDate.stepForward(0, 0, 1)
|
|
||||||
lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
|
|
||||||
checkedDays++
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the displayingDate to show in the header
|
|
||||||
if (!unified) {
|
|
||||||
if (lessons.isNotEmpty())
|
|
||||||
displayingDate = timetableDate
|
|
||||||
profileId = profile.id
|
|
||||||
}
|
|
||||||
|
|
||||||
// get all events for the current date
|
|
||||||
val events = app.db.eventDao().getAllByDateNow(profile.id, timetableDate)?.filterNotNull() ?: emptyList()
|
|
||||||
|
|
||||||
lessons.forEachIndexed { pos, lesson ->
|
|
||||||
val model = ItemWidgetTimetableModel()
|
|
||||||
|
|
||||||
model.bigStyle = widgetConfig.bigStyle
|
|
||||||
model.darkTheme = widgetConfig.darkTheme
|
|
||||||
|
|
||||||
model.profileId = profile.id
|
|
||||||
|
|
||||||
model.lessonId = lesson.id
|
|
||||||
model.lessonDate = timetableDate
|
|
||||||
model.startTime = lesson.displayStartTime
|
|
||||||
model.endTime = lesson.displayEndTime
|
|
||||||
|
|
||||||
// check if the lesson has already passed or it's currently in progress
|
|
||||||
if (lesson.displayDate == today) {
|
|
||||||
lesson.displayEndTime?.let { endTime ->
|
|
||||||
model.lessonPassed = now > endTime
|
|
||||||
lesson.displayStartTime?.let { startTime ->
|
|
||||||
model.lessonCurrent = now in startTime..endTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set where should the list view scroll to
|
|
||||||
if (model.lessonCurrent) {
|
|
||||||
scrollPos = pos
|
|
||||||
} else if (model.lessonPassed) {
|
|
||||||
scrollPos = pos + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the subject and classroom name
|
|
||||||
model.subjectName = lesson.displaySubjectName
|
|
||||||
model.classroomName = lesson.displayClassroom
|
|
||||||
|
|
||||||
// set the bell sync to calculate progress in ListProvider
|
|
||||||
model.bellSyncDiffMillis = bellSyncDiffMillis
|
|
||||||
|
|
||||||
// make the model aware of the lesson type
|
|
||||||
when (lesson.type) {
|
|
||||||
Lesson.TYPE_CANCELLED -> {
|
|
||||||
model.lessonCancelled = true
|
|
||||||
}
|
|
||||||
Lesson.TYPE_CHANGE,
|
|
||||||
Lesson.TYPE_SHIFTED_SOURCE,
|
|
||||||
Lesson.TYPE_SHIFTED_TARGET -> {
|
|
||||||
model.lessonChange = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add every event on this lesson
|
|
||||||
for (event in events) {
|
|
||||||
if (event.startTime == null || event.startTime != lesson.displayStartTime)
|
|
||||||
continue
|
|
||||||
model.eventColors.add(if (event.type == TYPE_HOMEWORK) ItemWidgetTimetableModel.EVENT_COLOR_HOMEWORK else event.getColor())
|
|
||||||
}
|
|
||||||
|
|
||||||
models += model
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unified) {
|
|
||||||
// set the title for an unified widget
|
|
||||||
views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.widget_timetable_title_unified))
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableSubtitle, View.GONE)
|
|
||||||
} else {
|
|
||||||
// set the title to present the widget's profile
|
|
||||||
views.setTextViewText(R.id.widgetTimetableTitle, profileList[0].name)
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableTitle, View.VISIBLE)
|
|
||||||
// make the subtitle show current date for these lessons
|
|
||||||
displayingDate?.let {
|
|
||||||
when (Date.diffDays(it, Date.getToday())) {
|
|
||||||
0 -> views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.day_today_format, Week.getFullDayName(it.weekDay)))
|
|
||||||
1 -> views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.day_tomorrow_format, Week.getFullDayName(it.weekDay)))
|
|
||||||
else -> views.setTextViewText(R.id.widgetTimetableSubtitle, Week.getFullDayName(it.weekDay) + " " + it.formattedString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// intent running when the header is clicked
|
|
||||||
val openIntent = Intent(app, MainActivity::class.java)
|
|
||||||
openIntent.action = "android.intent.action.MAIN"
|
|
||||||
if (!unified) {
|
|
||||||
// per-profile widget should redirect to it + correct day
|
|
||||||
profileId?.let {
|
|
||||||
openIntent.putExtra("profileId", it)
|
|
||||||
}
|
|
||||||
displayingDate?.let {
|
|
||||||
openIntent.putExtra("timetableDate", it.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE)
|
|
||||||
val pendingOpenIntent = PendingIntent.getActivity(app, appWidgetId, openIntent, 0)
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent)
|
|
||||||
|
|
||||||
if (lessonList.isEmpty()) {
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE)
|
|
||||||
views.setRemoteAdapter(R.id.widgetTimetableListView, Intent())
|
|
||||||
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
timetables!!.put(appWidgetId, models)
|
|
||||||
|
|
||||||
// apply the list service to the list view
|
|
||||||
val listIntent = Intent(app, WidgetTimetableService::class.java)
|
|
||||||
listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
|
||||||
listIntent.data = Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME))
|
|
||||||
views.setRemoteAdapter(R.id.widgetTimetableListView, listIntent)
|
|
||||||
|
|
||||||
// create an intent used to display the lesson details dialog
|
|
||||||
val intentTemplate = Intent(app, LessonDialogActivity::class.java)
|
|
||||||
intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
|
||||||
val pendingIntentTimetable = PendingIntent.getActivity(app, appWidgetId, intentTemplate, 0)
|
|
||||||
views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable)
|
|
||||||
|
|
||||||
if (!unified)
|
|
||||||
views.setScrollPosition(R.id.widgetTimetableListView, scrollPos)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onEnabled(context: Context) {
|
|
||||||
// Enter relevant functionality for when the first widget is created
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
|
||||||
val app = context.applicationContext as App
|
|
||||||
for (appWidgetId in appWidgetIds) {
|
|
||||||
app.appConfig.widgetTimetableConfigs.remove(appWidgetId)
|
|
||||||
}
|
|
||||||
app.saveConfig("widgetTimetableConfigs")
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
|
|
||||||
val ACTION_SYNC_DATA = "ACTION_SYNC_DATA"
|
|
||||||
private val TAG = "WidgetTimetable"
|
|
||||||
private val modeInt = 0
|
|
||||||
|
|
||||||
var timetables: SparseArray<List<ItemWidgetTimetableModel>>? = null
|
|
||||||
|
|
||||||
fun getPendingSelfIntent(context: Context, action: String): PendingIntent {
|
|
||||||
val intent = Intent(context, WidgetTimetable::class.java)
|
|
||||||
intent.action = action
|
|
||||||
return getPendingSelfIntent(context, intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPendingSelfIntent(context: Context, intent: Intent): PendingIntent {
|
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun drawableToBitmap(drawable: Drawable): Bitmap {
|
|
||||||
|
|
||||||
if (drawable is BitmapDrawable) {
|
|
||||||
return drawable.bitmap
|
|
||||||
}
|
|
||||||
|
|
||||||
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
|
|
||||||
val canvas = Canvas(bitmap)
|
|
||||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
|
||||||
drawable.draw(canvas)
|
|
||||||
|
|
||||||
return bitmap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
|
||||||
|
|
||||||
interface AbstractConfig {
|
|
||||||
fun set(key: String, value: String?)
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
|
||||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.ConfigMigration
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
|
||||||
companion object {
|
|
||||||
const val DATA_VERSION = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
private val job = Job()
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Default
|
|
||||||
|
|
||||||
val values: HashMap<String, String?> = hashMapOf()
|
|
||||||
|
|
||||||
val ui by lazy { ConfigUI(this) }
|
|
||||||
val sync by lazy { ConfigSync(this) }
|
|
||||||
val timetable by lazy { ConfigTimetable(this) }
|
|
||||||
val grades by lazy { ConfigGrades(this) }
|
|
||||||
|
|
||||||
private var mDataVersion: Int? = null
|
|
||||||
var dataVersion: Int
|
|
||||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
|
||||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
|
||||||
|
|
||||||
private var mAppVersion: Int? = null
|
|
||||||
var appVersion: Int
|
|
||||||
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE }
|
|
||||||
set(value) { set("appVersion", value); mAppVersion = value }
|
|
||||||
|
|
||||||
private var mLoginFinished: Boolean? = null
|
|
||||||
var loginFinished: Boolean
|
|
||||||
get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false }
|
|
||||||
set(value) { set("loginFinished", value); mLoginFinished = value }
|
|
||||||
|
|
||||||
private var mDevModePassword: String? = null
|
|
||||||
var devModePassword: String?
|
|
||||||
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }
|
|
||||||
set(value) { set("devModePassword", value); mDevModePassword = value }
|
|
||||||
|
|
||||||
private var mAppInstalledTime: Long? = null
|
|
||||||
var appInstalledTime: Long
|
|
||||||
get() { mAppInstalledTime = mAppInstalledTime ?: values.get("appInstalledTime", 0L); return mAppInstalledTime ?: 0L }
|
|
||||||
set(value) { set("appInstalledTime", value); mAppInstalledTime = value }
|
|
||||||
|
|
||||||
private var mAppRateSnackbarTime: Long? = null
|
|
||||||
var appRateSnackbarTime: Long
|
|
||||||
get() { mAppRateSnackbarTime = mAppRateSnackbarTime ?: values.get("appRateSnackbarTime", 0L); return mAppRateSnackbarTime ?: 0L }
|
|
||||||
set(value) { set("appRateSnackbarTime", value); mAppRateSnackbarTime = value }
|
|
||||||
|
|
||||||
private var rawEntries: List<ConfigEntry> = db.configDao().getAllNow()
|
|
||||||
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
|
|
||||||
init {
|
|
||||||
rawEntries.toHashMap(-1, values)
|
|
||||||
}
|
|
||||||
fun migrate(app: App) {
|
|
||||||
if (dataVersion < DATA_VERSION)
|
|
||||||
ConfigMigration(app, this)
|
|
||||||
}
|
|
||||||
fun getFor(profileId: Int): ProfileConfig {
|
|
||||||
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, rawEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setProfile(profileId: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun set(key: String, value: String?) {
|
|
||||||
values[key] = value
|
|
||||||
launch {
|
|
||||||
db.configDao().add(ConfigEntry(-1, key, value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
|
|
||||||
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 ?: 0 }
|
|
||||||
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
class ConfigSync(private val config: Config) {
|
|
||||||
private var mSyncEnabled: Boolean? = null
|
|
||||||
var enabled: Boolean
|
|
||||||
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
|
||||||
set(value) { config.set("syncEnabled", value); mSyncEnabled = value }
|
|
||||||
|
|
||||||
private var mSyncOnlyWifi: Boolean? = null
|
|
||||||
var onlyWifi: Boolean
|
|
||||||
get() { mSyncOnlyWifi = mSyncOnlyWifi ?: config.values.get("syncOnlyWifi", false); return mSyncOnlyWifi ?: notifyAboutUpdates }
|
|
||||||
set(value) { config.set("syncOnlyWifi", value); mSyncOnlyWifi = value }
|
|
||||||
|
|
||||||
private var mSyncInterval: Int? = null
|
|
||||||
var interval: Int
|
|
||||||
get() { mSyncInterval = mSyncInterval ?: config.values.get("syncInterval", 60*60); return mSyncInterval ?: 60*60 }
|
|
||||||
set(value) { config.set("syncInterval", value); mSyncInterval = value }
|
|
||||||
|
|
||||||
private var mNotifyAboutUpdates: Boolean? = null
|
|
||||||
var notifyAboutUpdates: Boolean
|
|
||||||
get() { mNotifyAboutUpdates = mNotifyAboutUpdates ?: config.values.get("notifyAboutUpdates", true); return mNotifyAboutUpdates ?: true }
|
|
||||||
set(value) { config.set("notifyAboutUpdates", value); mNotifyAboutUpdates = value }
|
|
||||||
|
|
||||||
/* ____ _ _ _
|
|
||||||
/ __ \ (_) | | | |
|
|
||||||
| | | |_ _ _ ___| |_ | |__ ___ _ _ _ __ ___
|
|
||||||
| | | | | | | |/ _ \ __| | '_ \ / _ \| | | | '__/ __|
|
|
||||||
| |__| | |_| | | __/ |_ | | | | (_) | |_| | | \__ \
|
|
||||||
\___\_\\__,_|_|\___|\__| |_| |_|\___/ \__,_|_| |__*/
|
|
||||||
private var mQuietHoursStart: Long? = null
|
|
||||||
var quietHoursStart: Long
|
|
||||||
get() { mQuietHoursStart = mQuietHoursStart ?: config.values.get("quietHoursStart", 0L); return mQuietHoursStart ?: 0L }
|
|
||||||
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 }
|
|
||||||
set(value) { config.set("quietHoursEnd", value); mQuietHoursEnd = value }
|
|
||||||
|
|
||||||
private var mQuietDuringLessons: Boolean? = null
|
|
||||||
var quietDuringLessons: Boolean
|
|
||||||
get() { mQuietDuringLessons = mQuietDuringLessons ?: config.values.get("quietDuringLessons", false); return mQuietDuringLessons ?: false }
|
|
||||||
set(value) { config.set("quietDuringLessons", value); mQuietDuringLessons = value }
|
|
||||||
|
|
||||||
/* ______ _____ __ __ _______ _
|
|
||||||
| ____/ ____| \/ | |__ __| | |
|
|
||||||
| |__ | | | \ / | | | ___ | | _____ _ __ ___
|
|
||||||
| __|| | | |\/| | | |/ _ \| |/ / _ \ '_ \/ __|
|
|
||||||
| | | |____| | | | | | (_) | < __/ | | \__ \
|
|
||||||
|_| \_____|_| |_| |_|\___/|_|\_\___|_| |_|__*/
|
|
||||||
private var mTokenApp: String? = null
|
|
||||||
var tokenApp: String?
|
|
||||||
get() { mTokenApp = mTokenApp ?: config.values.get("tokenApp", null as String?); return mTokenApp }
|
|
||||||
set(value) { config.set("tokenApp", value); mTokenApp = value }
|
|
||||||
private var mTokenMobidziennik: String? = null
|
|
||||||
var tokenMobidziennik: String?
|
|
||||||
get() { mTokenMobidziennik = mTokenMobidziennik ?: config.values.get("tokenMobidziennik", null as String?); return mTokenMobidziennik }
|
|
||||||
set(value) { config.set("tokenMobidziennik", value); mTokenMobidziennik = value }
|
|
||||||
private var mTokenLibrus: String? = null
|
|
||||||
var tokenLibrus: String?
|
|
||||||
get() { mTokenLibrus = mTokenLibrus ?: config.values.get("tokenLibrus", null as String?); return mTokenLibrus }
|
|
||||||
set(value) { config.set("tokenLibrus", value); mTokenLibrus = value }
|
|
||||||
private var mTokenVulcan: String? = null
|
|
||||||
var tokenVulcan: String?
|
|
||||||
get() { mTokenVulcan = mTokenVulcan ?: config.values.get("tokenVulcan", null as String?); return mTokenVulcan }
|
|
||||||
set(value) { config.set("tokenVulcan", value); mTokenVulcan = value }
|
|
||||||
|
|
||||||
private var mTokenMobidziennikList: List<Int>? = null
|
|
||||||
var tokenMobidziennikList: List<Int>
|
|
||||||
get() { mTokenMobidziennikList = mTokenMobidziennikList ?: config.values.getIntList("tokenMobidziennikList", listOf()); return mTokenMobidziennikList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenMobidziennikList", value); mTokenMobidziennikList = value }
|
|
||||||
private var mTokenLibrusList: List<Int>? = null
|
|
||||||
var tokenLibrusList: List<Int>
|
|
||||||
get() { mTokenLibrusList = mTokenLibrusList ?: config.values.getIntList("tokenLibrusList", listOf()); return mTokenLibrusList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenLibrusList", value); mTokenLibrusList = value }
|
|
||||||
private var mTokenVulcanList: List<Int>? = null
|
|
||||||
var tokenVulcanList: List<Int>
|
|
||||||
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class ConfigTimetable(private val config: Config) {
|
|
||||||
private var mBellSyncMultiplier: Int? = null
|
|
||||||
var bellSyncMultiplier: Int
|
|
||||||
get() { mBellSyncMultiplier = mBellSyncMultiplier ?: config.values.get("bellSyncMultiplier", 0); return mBellSyncMultiplier ?: 0 }
|
|
||||||
set(value) { config.set("bellSyncMultiplier", value); mBellSyncMultiplier = value }
|
|
||||||
|
|
||||||
private var mBellSyncDiff: Time? = null
|
|
||||||
var bellSyncDiff: Time?
|
|
||||||
get() { mBellSyncDiff = mBellSyncDiff ?: config.values.get("bellSyncDiff", null as Time?); return mBellSyncDiff }
|
|
||||||
set(value) { config.set("bellSyncDiff", value); mBellSyncDiff = value }
|
|
||||||
|
|
||||||
private var mCountInSeconds: Boolean? = null
|
|
||||||
var countInSeconds: Boolean
|
|
||||||
get() { mCountInSeconds = mCountInSeconds ?: config.values.get("countInSeconds", false); return mCountInSeconds ?: false }
|
|
||||||
set(value) { config.set("countInSeconds", value); mCountInSeconds = value }
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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
|
|
||||||
var theme: Int
|
|
||||||
get() { mTheme = mTheme ?: config.values.get("theme", 1); return mTheme ?: 1 }
|
|
||||||
set(value) { config.set("theme", value); mTheme = value }
|
|
||||||
|
|
||||||
private var mLanguage: String? = null
|
|
||||||
var language: String?
|
|
||||||
get() { mLanguage = mLanguage ?: config.values.get("language", null as String?); return mLanguage }
|
|
||||||
set(value) { config.set("language", value); mLanguage = value }
|
|
||||||
|
|
||||||
private var mHeaderBackground: String? = null
|
|
||||||
var headerBackground: String?
|
|
||||||
get() { mHeaderBackground = mHeaderBackground ?: config.values.get("headerBg", null as String?); return mHeaderBackground }
|
|
||||||
set(value) { config.set("headerBg", value); mHeaderBackground = value }
|
|
||||||
|
|
||||||
private var mAppBackground: String? = null
|
|
||||||
var appBackground: String?
|
|
||||||
get() { mAppBackground = mAppBackground ?: config.values.get("appBg", null as String?); return mAppBackground }
|
|
||||||
set(value) { config.set("appBg", value); mAppBackground = value }
|
|
||||||
|
|
||||||
private var mMiniMenuVisible: Boolean? = null
|
|
||||||
var miniMenuVisible: Boolean
|
|
||||||
get() { mMiniMenuVisible = mMiniMenuVisible ?: config.values.get("miniMenuVisible", false); return mMiniMenuVisible ?: false }
|
|
||||||
set(value) { config.set("miniMenuVisible", value); mMiniMenuVisible = value }
|
|
||||||
|
|
||||||
private var mMiniMenuButtons: List<Int>? = null
|
|
||||||
var miniMenuButtons: List<Int>
|
|
||||||
get() { mMiniMenuButtons = mMiniMenuButtons ?: config.values.getIntList("miniMenuButtons", listOf()); return mMiniMenuButtons ?: listOf() }
|
|
||||||
set(value) { config.set("miniMenuButtons", value); mMiniMenuButtons = value }
|
|
||||||
|
|
||||||
private var mOpenDrawerOnBackPressed: Boolean? = null
|
|
||||||
var openDrawerOnBackPressed: Boolean
|
|
||||||
get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false }
|
|
||||||
set(value) { config.set("openDrawerOnBackPressed", value); mOpenDrawerOnBackPressed = value }
|
|
||||||
|
|
||||||
private var mAgendaViewType: Int? = null
|
|
||||||
var agendaViewType: Int
|
|
||||||
get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: 0 }
|
|
||||||
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 }
|
|
||||||
|
|
||||||
private var mSnowfall: Boolean? = null
|
|
||||||
var snowfall: Boolean
|
|
||||||
get() { mSnowfall = mSnowfall ?: config.values.get("snowfall", false); return mSnowfall ?: false }
|
|
||||||
set(value) { config.set("snowfall", value); mSnowfall = value }
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEntry>) : CoroutineScope, AbstractConfig {
|
|
||||||
companion object {
|
|
||||||
const val DATA_VERSION = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
private val job = Job()
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Default
|
|
||||||
|
|
||||||
val values: HashMap<String, String?> = hashMapOf()
|
|
||||||
|
|
||||||
val grades by lazy { ProfileConfigGrades(this) }
|
|
||||||
/*
|
|
||||||
val sync by lazy { ConfigSync(this) }
|
|
||||||
val timetable by lazy { ConfigTimetable(this) }
|
|
||||||
val grades by lazy { ConfigGrades(this) }*/
|
|
||||||
|
|
||||||
private var mDataVersion: Int? = null
|
|
||||||
var dataVersion: Int
|
|
||||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
|
||||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
|
||||||
|
|
||||||
init {
|
|
||||||
rawEntries.toHashMap(profileId, values)
|
|
||||||
/*if (dataVersion < DATA_VERSION)
|
|
||||||
ProfileConfigMigration(this)*/
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun set(key: String, value: String?) {
|
|
||||||
values[key] = value
|
|
||||||
launch {
|
|
||||||
db.configDao().add(ConfigEntry(profileId, key, value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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.modules.profiles.Profile.Companion.COLOR_MODE_WEIGHTED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.YEAR_ALL_GRADES
|
|
||||||
|
|
||||||
class ProfileConfigGrades(private val config: ProfileConfig) {
|
|
||||||
private var mColorMode: Int? = null
|
|
||||||
var colorMode: Int
|
|
||||||
get() { mColorMode = mColorMode ?: config.values.get("gradesColorMode", COLOR_MODE_WEIGHTED); return mColorMode ?: COLOR_MODE_WEIGHTED }
|
|
||||||
set(value) { config.set("gradesColorMode", value); mColorMode = value }
|
|
||||||
|
|
||||||
private var mYearAverageMode: Int? = null
|
|
||||||
var yearAverageMode: Int
|
|
||||||
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 }
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.db
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy
|
|
||||||
import androidx.room.Query
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface ConfigDao {
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun add(entry: ConfigEntry)
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun addAll(list: List<ConfigEntry>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM config WHERE profileId = -1")
|
|
||||||
fun getAllNow(): List<ConfigEntry>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM config WHERE profileId = :profileId")
|
|
||||||
fun getAllNow(profileId: Int): List<ConfigEntry>
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.db
|
|
||||||
|
|
||||||
import androidx.room.Entity
|
|
||||||
|
|
||||||
@Entity(tableName = "config", primaryKeys = ["profileId", "key"])
|
|
||||||
data class ConfigEntry(
|
|
||||||
val profileId: Int = -1,
|
|
||||||
val key: String,
|
|
||||||
val value: String?
|
|
||||||
)
|
|
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
|
||||||
|
|
||||||
import com.google.gson.*
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
import pl.szczodrzynski.edziennik.config.AbstractConfig
|
|
||||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
private val gson = Gson()
|
|
||||||
|
|
||||||
fun AbstractConfig.set(key: String, value: Int) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Boolean) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Long) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Float) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Date?) {
|
|
||||||
set(key, value?.stringY_m_d)
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Time?) {
|
|
||||||
set(key, value?.stringValue)
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: JsonElement?) {
|
|
||||||
set(key, value?.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: List<Any>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.setStringList(key: String, value: List<String>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.setIntList(key: String, value: List<Int>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.setLongList(key: String, value: List<Long>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: String?): String? {
|
|
||||||
return this[key] ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: Boolean): Boolean {
|
|
||||||
return this[key]?.toBoolean() ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: Int): Int {
|
|
||||||
return this[key]?.toIntOrNull() ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: Long): Long {
|
|
||||||
return this[key]?.toLongOrNull() ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: Float): Float {
|
|
||||||
return this[key]?.toFloatOrNull() ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: Date?): Date? {
|
|
||||||
return this[key]?.let { Date.fromY_m_d(it) } ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: Time?): Time? {
|
|
||||||
return this[key]?.let { Time.fromHms(it) } ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: JsonObject?): JsonObject? {
|
|
||||||
return this[key]?.let { JsonParser().parse(it)?.asJsonObject } ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.get(key: String, default: JsonArray?): JsonArray? {
|
|
||||||
return this[key]?.let { JsonParser().parse(it)?.asJsonArray } ?: default
|
|
||||||
}
|
|
||||||
/* !!! cannot use mutable list here - modifying it will not update the DB */
|
|
||||||
fun <T> HashMap<String, String?>.get(key: String, default: List<T>?, classOfT: Class<T>): List<T>? {
|
|
||||||
return this[key]?.let { ConfigGsonUtils().deserializeList<T>(gson, it, classOfT) } ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.getStringList(key: String, default: List<String>?): List<String>? {
|
|
||||||
return this[key]?.let { gson.fromJson<List<String>>(it, object: TypeToken<List<String>>(){}.type) } ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.getIntList(key: String, default: List<Int>?): List<Int>? {
|
|
||||||
return this[key]?.let { gson.fromJson<List<Int>>(it, object: TypeToken<List<Int>>(){}.type) } ?: default
|
|
||||||
}
|
|
||||||
fun HashMap<String, String?>.getLongList(key: String, default: List<Long>?): List<Long>? {
|
|
||||||
return this[key]?.let { gson.fromJson<List<Long>>(it, object: TypeToken<List<Long>>(){}.type) } ?: default
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List<ConfigEntry>.toHashMap(profileId: Int, map: HashMap<String, String?>) {
|
|
||||||
map.clear()
|
|
||||||
forEach {
|
|
||||||
if (it.profileId == profileId)
|
|
||||||
map[it.key] = it.value
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-12-2.
|
|
||||||
*/
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
|
||||||
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.JsonParser
|
|
||||||
import pl.szczodrzynski.edziennik.getInt
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class ConfigGsonUtils {
|
|
||||||
fun <T> deserializeList(gson: Gson, str: String?, classOfT: Class<T>): List<T> {
|
|
||||||
val json = JsonParser().parse(str)
|
|
||||||
val list: MutableList<T> = mutableListOf()
|
|
||||||
if (!json.isJsonArray)
|
|
||||||
return list
|
|
||||||
|
|
||||||
json.asJsonArray.forEach { e ->
|
|
||||||
when (classOfT) {
|
|
||||||
String::class.java -> {
|
|
||||||
list += e.asString as T
|
|
||||||
}
|
|
||||||
HomeCardModel::class.java -> {
|
|
||||||
val o = e.asJsonObject
|
|
||||||
list += HomeCardModel(
|
|
||||||
o.getInt("profileId", 0),
|
|
||||||
o.getInt("cardId", 0)
|
|
||||||
) as T
|
|
||||||
}
|
|
||||||
Time::class.java -> {
|
|
||||||
val o = e.asJsonObject
|
|
||||||
list += Time(
|
|
||||||
o.getInt("hour", 0),
|
|
||||||
o.getInt("minute", 0),
|
|
||||||
o.getInt("second", 0)
|
|
||||||
) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
|
||||||
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.config.Config
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class ConfigMigration(app: App, config: Config) {
|
|
||||||
init { config.apply {
|
|
||||||
val p = app.getSharedPreferences("pl.szczodrzynski.edziennik_profiles", Context.MODE_PRIVATE)
|
|
||||||
val s = "app.appConfig"
|
|
||||||
|
|
||||||
if (dataVersion < 1) {
|
|
||||||
ui.theme = p.getString("$s.appTheme", null)?.toIntOrNull() ?: 1
|
|
||||||
sync.enabled = p.getString("$s.registerSyncEnabled", null)?.toBoolean() ?: true
|
|
||||||
sync.interval = p.getString("$s.registerSyncEnabled", null)?.toIntOrNull() ?: 3600
|
|
||||||
val oldButtons = p.getString("$s.miniDrawerButtonIds", null)?.let { str ->
|
|
||||||
str.replace("[\\[\\]]*".toRegex(), "")
|
|
||||||
.split(",\\s?".toRegex())
|
|
||||||
.mapNotNull { it.toIntOrNull() }
|
|
||||||
}
|
|
||||||
ui.miniMenuButtons = oldButtons ?: listOf(
|
|
||||||
MainActivity.DRAWER_ITEM_HOME,
|
|
||||||
MainActivity.DRAWER_ITEM_TIMETABLE,
|
|
||||||
MainActivity.DRAWER_ITEM_AGENDA,
|
|
||||||
MainActivity.DRAWER_ITEM_GRADES,
|
|
||||||
MainActivity.DRAWER_ITEM_MESSAGES,
|
|
||||||
MainActivity.DRAWER_ITEM_HOMEWORK,
|
|
||||||
MainActivity.DRAWER_ITEM_SETTINGS
|
|
||||||
)
|
|
||||||
dataVersion = 1
|
|
||||||
}
|
|
||||||
if (dataVersion < 2) {
|
|
||||||
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()
|
|
||||||
ui.language = p.getString("$s.language", null).fix()
|
|
||||||
appVersion = p.getString("$s.lastAppVersion", null)?.toIntOrNull() ?: BuildConfig.VERSION_CODE
|
|
||||||
appInstalledTime = p.getString("$s.appInstalledTime", null)?.toLongOrNull() ?: 0
|
|
||||||
grades.orderBy = p.getString("$s.gradesOrderBy", null)?.toIntOrNull() ?: 0
|
|
||||||
sync.quietDuringLessons = p.getString("$s.quietDuringLessons", null)?.toBoolean() ?: false
|
|
||||||
ui.miniMenuVisible = p.getString("$s.miniDrawerVisible", null)?.toBoolean() ?: false
|
|
||||||
loginFinished = p.getString("$s.loginFinished", null)?.toBoolean() ?: false
|
|
||||||
sync.onlyWifi = p.getString("$s.registerSyncOnlyWifi", null)?.toBoolean() ?: false
|
|
||||||
sync.notifyAboutUpdates = p.getString("$s.notifyAboutUpdates", null)?.toBoolean() ?: true
|
|
||||||
timetable.bellSyncDiff = p.getString("$s.bellSyncDiff", null)?.let { Gson().fromJson(it, Time::class.java) }
|
|
||||||
|
|
||||||
sync.tokenMobidziennikList = listOf()
|
|
||||||
sync.tokenVulcanList = listOf()
|
|
||||||
sync.tokenLibrusList = listOf()
|
|
||||||
val tokens = p.getString("$s.fcmTokens", null)?.let { Gson().fromJson<Map<Int, Pair<String, List<Int>>>>(it, object: TypeToken<Map<Int, Pair<String, List<Int>>>>(){}.type) }
|
|
||||||
tokens?.forEach {
|
|
||||||
val token = it.value.first
|
|
||||||
when (it.key) {
|
|
||||||
LOGIN_TYPE_MOBIDZIENNIK -> sync.tokenMobidziennik = token
|
|
||||||
LOGIN_TYPE_VULCAN -> sync.tokenVulcan = token
|
|
||||||
LOGIN_TYPE_LIBRUS -> sync.tokenLibrus = token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dataVersion = 2
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
private fun String?.fix(): String? {
|
|
||||||
return this?.replace("\"", "")?.let { if (it == "null") null else it }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-12-1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.config.Config
|
|
||||||
|
|
||||||
class ProfileConfigMigration(app: App, config: Config) {
|
|
||||||
init { config.apply {
|
|
||||||
val p = app.getSharedPreferences("pl.szczodrzynski.edziennik_profiles", Context.MODE_PRIVATE)
|
|
||||||
val s = "app.appConfig"
|
|
||||||
|
|
||||||
if (dataVersion < 1) {
|
|
||||||
|
|
||||||
//dataVersion = 1
|
|
||||||
}
|
|
||||||
if (dataVersion < 2) {
|
|
||||||
//gradesColorMode do profilu !
|
|
||||||
//agendaViewType do profilu !
|
|
||||||
// app.appConfig.dontCountZeroToAverage do profilu !
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
@ -1,301 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
import android.app.Service
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.IBinder
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import org.greenrobot.eventbus.Subscribe
|
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.requests.ServiceCloseRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.requests.TaskCancelRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.task.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import kotlin.math.min
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
class ApiService : Service() {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "ApiService"
|
|
||||||
const val NOTIFICATION_API_CHANNEL_ID = "pl.szczodrzynski.edziennik.GET_DATA"
|
|
||||||
fun start(context: Context) {
|
|
||||||
context.startService(Intent(context, ApiService::class.java))
|
|
||||||
}
|
|
||||||
fun startAndRequest(context: Context, request: Any) {
|
|
||||||
context.startService(Intent(context, ApiService::class.java))
|
|
||||||
EventBus.getDefault().postSticky(request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val app by lazy { applicationContext as App }
|
|
||||||
|
|
||||||
private val syncingProfiles = mutableListOf<ProfileFull>()
|
|
||||||
|
|
||||||
private val finishingTaskQueue = mutableListOf(
|
|
||||||
SzkolnyTask.sync(syncingProfiles),
|
|
||||||
NotifyTask()
|
|
||||||
)
|
|
||||||
private val taskQueue = mutableListOf<IApiTask>()
|
|
||||||
private val errorList = mutableListOf<ApiError>()
|
|
||||||
|
|
||||||
private var serviceClosed = false
|
|
||||||
private var taskCancelled = false
|
|
||||||
private var taskIsRunning = false
|
|
||||||
private var taskRunning: IApiTask? = null // for debug purposes
|
|
||||||
private var taskRunningId = -1
|
|
||||||
private var taskMaximumId = 0
|
|
||||||
|
|
||||||
private var taskProfileId = -1
|
|
||||||
private var taskProgress = -1f
|
|
||||||
private var taskProgressText: String? = null
|
|
||||||
|
|
||||||
private val notification by lazy { EdziennikNotification(this) }
|
|
||||||
|
|
||||||
private var lastEventTime = System.currentTimeMillis()
|
|
||||||
private var taskCancelTries = 0
|
|
||||||
|
|
||||||
/* ______ _ _ _ _ _____ _ _ _ _
|
|
||||||
| ____| | | (_) (_) | / ____| | | | | | |
|
|
||||||
| |__ __| |_____ ___ _ __ _ __ _| | __ | | __ _| | | |__ __ _ ___| | __
|
|
||||||
| __| / _` |_ / |/ _ \ '_ \| '_ \| | |/ / | | / _` | | | '_ \ / _` |/ __| |/ /
|
|
||||||
| |___| (_| |/ /| | __/ | | | | | | | < | |___| (_| | | | |_) | (_| | (__| <
|
|
||||||
|______\__,_/___|_|\___|_| |_|_| |_|_|_|\_\ \_____\__,_|_|_|_.__/ \__,_|\___|_|\*/
|
|
||||||
private val taskCallback = object : EdziennikCallback {
|
|
||||||
override fun onCompleted() {
|
|
||||||
lastEventTime = System.currentTimeMillis()
|
|
||||||
d(TAG, "Task $taskRunningId (profile $taskProfileId) - $taskProgressText - finished")
|
|
||||||
EventBus.getDefault().post(ApiTaskFinishedEvent(taskProfileId))
|
|
||||||
clearTask()
|
|
||||||
|
|
||||||
notification.setIdle().post()
|
|
||||||
runTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(apiError: ApiError) {
|
|
||||||
lastEventTime = System.currentTimeMillis()
|
|
||||||
d(TAG, "Task $taskRunningId threw an error - $apiError")
|
|
||||||
apiError.profileId = taskProfileId
|
|
||||||
EventBus.getDefault().post(ApiTaskErrorEvent(apiError))
|
|
||||||
errorList.add(apiError)
|
|
||||||
apiError.throwable?.printStackTrace()
|
|
||||||
if (apiError.isCritical) {
|
|
||||||
taskRunning?.cancel()
|
|
||||||
notification.setCriticalError().post()
|
|
||||||
clearTask()
|
|
||||||
runTask()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
notification.addError().post()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
|
||||||
lastEventTime = System.currentTimeMillis()
|
|
||||||
if (step <= 0)
|
|
||||||
return
|
|
||||||
if (taskProgress < 0)
|
|
||||||
taskProgress = 0f
|
|
||||||
taskProgress += step
|
|
||||||
taskProgress = min(100f, taskProgress)
|
|
||||||
d(TAG, "Task $taskRunningId progress: ${taskProgress.roundToInt()}%")
|
|
||||||
EventBus.getDefault().post(ApiTaskProgressEvent(taskProfileId, taskProgress, taskProgressText))
|
|
||||||
notification.setProgress(taskProgress).post()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartProgress(stringRes: Int) {
|
|
||||||
lastEventTime = System.currentTimeMillis()
|
|
||||||
taskProgressText = getString(stringRes)
|
|
||||||
d(TAG, "Task $taskRunningId progress: $taskProgressText")
|
|
||||||
EventBus.getDefault().post(ApiTaskProgressEvent(taskProfileId, taskProgress, taskProgressText))
|
|
||||||
notification.setProgressText(taskProgressText).post()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _______ _ _ _
|
|
||||||
|__ __| | | | | (_)
|
|
||||||
| | __ _ ___| | __ _____ _____ ___ _ _| |_ _ ___ _ __
|
|
||||||
| |/ _` / __| |/ / / _ \ \/ / _ \/ __| | | | __| |/ _ \| '_ \
|
|
||||||
| | (_| \__ \ < | __/> < __/ (__| |_| | |_| | (_) | | | |
|
|
||||||
|_|\__,_|___/_|\_\ \___/_/\_\___|\___|\__,_|\__|_|\___/|_| |*/
|
|
||||||
private fun runTask() {
|
|
||||||
checkIfTaskFrozen()
|
|
||||||
if (taskIsRunning)
|
|
||||||
return
|
|
||||||
if (taskCancelled || serviceClosed || (taskQueue.isEmpty() && finishingTaskQueue.isEmpty())) {
|
|
||||||
serviceClosed = false
|
|
||||||
allCompleted()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
lastEventTime = System.currentTimeMillis()
|
|
||||||
|
|
||||||
val task = if (taskQueue.isEmpty()) finishingTaskQueue.removeAt(0) else taskQueue.removeAt(0)
|
|
||||||
task.taskId = ++taskMaximumId
|
|
||||||
task.prepare(app)
|
|
||||||
taskIsRunning = true
|
|
||||||
taskRunningId = task.taskId
|
|
||||||
taskRunning = task
|
|
||||||
taskProfileId = task.profileId
|
|
||||||
taskProgress = -1f
|
|
||||||
taskProgressText = task.taskName
|
|
||||||
|
|
||||||
d(TAG, "Executing task $taskRunningId ($taskProgressText) - $task")
|
|
||||||
|
|
||||||
// update the notification
|
|
||||||
notification.setCurrentTask(taskRunningId, taskProgressText).post()
|
|
||||||
|
|
||||||
// post an event
|
|
||||||
EventBus.getDefault().post(ApiTaskStartedEvent(taskProfileId, task.profile))
|
|
||||||
|
|
||||||
task.profile?.let { syncingProfiles.add(it) }
|
|
||||||
|
|
||||||
try {
|
|
||||||
when (task) {
|
|
||||||
is EdziennikTask -> task.run(app, taskCallback)
|
|
||||||
is NotifyTask -> task.run(app, taskCallback)
|
|
||||||
is ErrorReportTask -> task.run(app, taskCallback, notification, errorList)
|
|
||||||
is SzkolnyTask -> task.run(app, taskCallback)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
taskCallback.onError(ApiError(TAG, EXCEPTION_API_TASK).withThrowable(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a task is inactive for more than 30 seconds.
|
|
||||||
* If the user tries to cancel a task with no success at least three times,
|
|
||||||
* consider it frozen as well.
|
|
||||||
*
|
|
||||||
* This usually means it is broken and won't become active again.
|
|
||||||
* This method cancels the task and removes any pointers to it.
|
|
||||||
*/
|
|
||||||
private fun checkIfTaskFrozen(): Boolean {
|
|
||||||
if (System.currentTimeMillis() - lastEventTime > 30*1000
|
|
||||||
|| taskCancelTries >= 3) {
|
|
||||||
val time = System.currentTimeMillis() - lastEventTime
|
|
||||||
d(TAG, "!!! Task $taskRunningId froze for $time ms. $taskRunning")
|
|
||||||
clearTask()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the service if the current task is frozen/broken.
|
|
||||||
*/
|
|
||||||
private fun stopIfTaskFrozen() {
|
|
||||||
if (checkIfTaskFrozen()) {
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove any task descriptors or pointers from the service.
|
|
||||||
*/
|
|
||||||
private fun clearTask() {
|
|
||||||
taskIsRunning = false
|
|
||||||
taskRunningId = -1
|
|
||||||
taskRunning = null
|
|
||||||
taskProfileId = -1
|
|
||||||
taskProgress = -1f
|
|
||||||
taskProgressText = null
|
|
||||||
taskCancelled = false
|
|
||||||
taskCancelTries = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun allCompleted() {
|
|
||||||
EventBus.getDefault().post(ApiTaskAllFinishedEvent())
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ______ _ ____
|
|
||||||
| ____| | | | _ \
|
|
||||||
| |____ _____ _ __ | |_| |_) |_ _ ___
|
|
||||||
| __\ \ / / _ \ '_ \| __| _ <| | | / __|
|
|
||||||
| |___\ V / __/ | | | |_| |_) | |_| \__ \
|
|
||||||
|______\_/ \___|_| |_|\__|____/ \__,_|__*/
|
|
||||||
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
|
|
||||||
fun onApiTask(task: IApiTask) {
|
|
||||||
EventBus.getDefault().removeStickyEvent(task)
|
|
||||||
d(TAG, task.toString())
|
|
||||||
|
|
||||||
if (task is EdziennikTask) {
|
|
||||||
when (task.request) {
|
|
||||||
is EdziennikTask.SyncRequest -> app.db.profileDao().idsForSyncNow.forEach {
|
|
||||||
taskQueue += EdziennikTask.syncProfile(it)
|
|
||||||
}
|
|
||||||
is EdziennikTask.SyncProfileListRequest -> task.request.profileList.forEach {
|
|
||||||
taskQueue += EdziennikTask.syncProfile(it)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
taskQueue += task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
taskQueue += task
|
|
||||||
}
|
|
||||||
d(TAG, "EventBus received an IApiTask: $task")
|
|
||||||
d(TAG, "Current queue:")
|
|
||||||
taskQueue.forEach {
|
|
||||||
d(TAG, " - $it")
|
|
||||||
}
|
|
||||||
runTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
|
|
||||||
fun onTaskCancelRequest(request: TaskCancelRequest) {
|
|
||||||
EventBus.getDefault().removeStickyEvent(request)
|
|
||||||
d(TAG, request.toString())
|
|
||||||
|
|
||||||
taskCancelTries++
|
|
||||||
taskCancelled = true
|
|
||||||
taskRunning?.cancel()
|
|
||||||
stopIfTaskFrozen()
|
|
||||||
}
|
|
||||||
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
|
|
||||||
fun onServiceCloseRequest(request: ServiceCloseRequest) {
|
|
||||||
EventBus.getDefault().removeStickyEvent(request)
|
|
||||||
d(TAG, request.toString())
|
|
||||||
|
|
||||||
serviceClosed = true
|
|
||||||
taskCancelled = true
|
|
||||||
taskRunning?.cancel()
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _____ _ _ _
|
|
||||||
/ ____| (_) (_) | |
|
|
||||||
| (___ ___ _ ____ ___ ___ ___ _____ _____ _ __ _ __ _ __| | ___ ___
|
|
||||||
\___ \ / _ \ '__\ \ / / |/ __/ _ \ / _ \ \ / / _ \ '__| '__| |/ _` |/ _ \/ __|
|
|
||||||
____) | __/ | \ V /| | (_| __/ | (_) \ V / __/ | | | | | (_| | __/\__ \
|
|
||||||
|_____/ \___|_| \_/ |_|\___\___| \___/ \_/ \___|_| |_| |_|\__,_|\___||__*/
|
|
||||||
override fun onCreate() {
|
|
||||||
d(TAG, "Service created")
|
|
||||||
EventBus.getDefault().register(this)
|
|
||||||
notification.setIdle().setCloseAction()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
||||||
d(TAG, "Foreground service onStartCommand")
|
|
||||||
startForeground(EdziennikNotification.NOTIFICATION_ID, notification.notification)
|
|
||||||
return START_NOT_STICKY
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
EventBus.getDefault().unregister(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,4 @@
|
|||||||
/*
|
package pl.szczodrzynski.edziennik.data.api;
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-26
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.models;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
@ -51,10 +47,11 @@ public class AppError {
|
|||||||
public static final int CODE_LIBRUS_DISCONNECTED = 31;
|
public static final int CODE_LIBRUS_DISCONNECTED = 31;
|
||||||
public static final int CODE_PROFILE_ARCHIVED = 30;
|
public static final int CODE_PROFILE_ARCHIVED = 30;
|
||||||
|
|
||||||
|
|
||||||
public static final int CODE_INTERNAL_MISSING_DATA = 100;
|
public static final int CODE_INTERNAL_MISSING_DATA = 100;
|
||||||
// internal errors - not for user's information.
|
// internal errors - not for user's information.
|
||||||
// these error codes are processed in API main classes
|
// these error codes are processed in API main classes
|
||||||
|
public static final int CODE_INTERNAL_LIBRUS_ACCOUNT_410 = 120;
|
||||||
|
public static final int CODE_INTERNAL_LIBRUS_ACCOUNT_410_ = 120;
|
||||||
|
|
||||||
public String TAG;
|
public String TAG;
|
||||||
public int line;
|
public int line;
|
||||||
@ -89,10 +86,10 @@ public class AppError {
|
|||||||
this(TAG, line, errorCode, null, null, null, throwable, apiResponse);
|
this(TAG, line, errorCode, null, null, null, throwable, apiResponse);
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, Throwable throwable, JsonObject apiResponse) {
|
public AppError(String TAG, int line, int errorCode, Throwable throwable, JsonObject apiResponse) {
|
||||||
this(TAG, line, errorCode, null, null, null, throwable, apiResponse == null ? null : apiResponse.toString());
|
this(TAG, line, errorCode, null, null, null, throwable, apiResponse.toString());
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, String errorText, Response response, JsonObject apiResponse) {
|
public AppError(String TAG, int line, int errorCode, String errorText, Response response, JsonObject apiResponse) {
|
||||||
this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse == null ? null : apiResponse.toString());
|
this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse.toString());
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, String errorText, Response response, String apiResponse) {
|
public AppError(String TAG, int line, int errorCode, String errorText, Response response, String apiResponse) {
|
||||||
this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse);
|
this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse);
|
||||||
@ -101,7 +98,7 @@ public class AppError {
|
|||||||
this(TAG, line, errorCode, errorText, null, null, null, apiResponse);
|
this(TAG, line, errorCode, errorText, null, null, null, apiResponse);
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, String errorText, JsonObject apiResponse) {
|
public AppError(String TAG, int line, int errorCode, String errorText, JsonObject apiResponse) {
|
||||||
this(TAG, line, errorCode, errorText, null, null, null, apiResponse == null ? null : apiResponse.toString());
|
this(TAG, line, errorCode, errorText, null, null, null, apiResponse.toString());
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, String errorText) {
|
public AppError(String TAG, int line, int errorCode, String errorText) {
|
||||||
this(TAG, line, errorCode, errorText, null, null, null, null);
|
this(TAG, line, errorCode, errorText, null, null, null, null);
|
||||||
@ -110,7 +107,7 @@ public class AppError {
|
|||||||
this(TAG, line, errorCode, null, null, null, null, apiResponse.toString());
|
this(TAG, line, errorCode, null, null, null, null, apiResponse.toString());
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, JsonObject apiResponse) {
|
public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, JsonObject apiResponse) {
|
||||||
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse == null ? null : apiResponse.toString());
|
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse.toString());
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, String apiResponse) {
|
public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, String apiResponse) {
|
||||||
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse);
|
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse);
|
||||||
@ -119,7 +116,7 @@ public class AppError {
|
|||||||
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse);
|
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse);
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, Response response, JsonObject apiResponse) {
|
public AppError(String TAG, int line, int errorCode, Response response, JsonObject apiResponse) {
|
||||||
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse == null ? null : apiResponse.toString());
|
this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDetails(Context context) {
|
public String getDetails(Context context) {
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-19.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
|
||||||
|
|
||||||
const val GET = 0
|
|
||||||
const val POST = 1
|
|
||||||
|
|
||||||
val SYSTEM_USER_AGENT = System.getProperty("http.agent") ?: "Dalvik/2.1.0 Android"
|
|
||||||
|
|
||||||
val SERVER_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME} $SYSTEM_USER_AGENT"
|
|
||||||
|
|
||||||
const val FAKE_LIBRUS_API = "http://librus.szkolny.eu/api"
|
|
||||||
const val FAKE_LIBRUS_PORTAL = "http://librus.szkolny.eu"
|
|
||||||
const val FAKE_LIBRUS_AUTHORIZE = "http://librus.szkolny.eu/authorize.php"
|
|
||||||
const val FAKE_LIBRUS_LOGIN = "http://librus.szkolny.eu/login_action.php"
|
|
||||||
const val FAKE_LIBRUS_TOKEN = "http://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"
|
|
||||||
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_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"
|
|
||||||
const val LIBRUS_TOKEN_URL = "https://portal.librus.pl/oauth2/access_token"
|
|
||||||
|
|
||||||
const val LIBRUS_ACCOUNT_URL = "/v2/SynergiaAccounts/fresh/" // + login
|
|
||||||
const val LIBRUS_ACCOUNTS_URL = "/v2/SynergiaAccounts"
|
|
||||||
|
|
||||||
/** https://api.librus.pl/2.0 */
|
|
||||||
const val LIBRUS_API_URL = "https://api.librus.pl/2.0"
|
|
||||||
/** https://portal.librus.pl/api */
|
|
||||||
const val LIBRUS_PORTAL_URL = "https://portal.librus.pl/api"
|
|
||||||
/** https://api.librus.pl/OAuth/Token */
|
|
||||||
const val LIBRUS_API_TOKEN_URL = "https://api.librus.pl/OAuth/Token"
|
|
||||||
/** https://api.librus.pl/OAuth/TokenJST */
|
|
||||||
const val LIBRUS_API_TOKEN_JST_URL = "https://api.librus.pl/OAuth/TokenJST"
|
|
||||||
const val LIBRUS_API_AUTHORIZATION = "Mjg6ODRmZGQzYTg3YjAzZDNlYTZmZmU3NzdiNThiMzMyYjE="
|
|
||||||
const val LIBRUS_API_SECRET_JST = "18b7c1ee08216f636a1b1a2440e68398"
|
|
||||||
const val LIBRUS_API_CLIENT_ID_JST = "49"
|
|
||||||
//const val LIBRUS_API_CLIENT_ID_JST_REFRESH = "42"
|
|
||||||
|
|
||||||
const val LIBRUS_JST_DEMO_CODE = "68656A21"
|
|
||||||
const val LIBRUS_JST_DEMO_PIN = "1290"
|
|
||||||
|
|
||||||
const val LIBRUS_SYNERGIA_URL = "https://synergia.librus.pl"
|
|
||||||
/** https://synergia.librus.pl/loguj/token/TOKEN/przenies */
|
|
||||||
const val LIBRUS_SYNERGIA_TOKEN_LOGIN_URL = "https://synergia.librus.pl/loguj/token/TOKEN/przenies"
|
|
||||||
|
|
||||||
const val LIBRUS_MESSAGES_URL = "https://wiadomosci.librus.pl/module"
|
|
||||||
const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action="
|
|
||||||
|
|
||||||
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_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"
|
|
||||||
const val IDZIENNIK_WEB_EXAMS = "mod_panelRodzica/sprawdziany/mod_sprawdzianyPanel.asmx/pobierzListe"
|
|
||||||
const val IDZIENNIK_WEB_HOMEWORK = "mod_panelRodzica/pracaDomowa/WS_pracaDomowa.asmx/pobierzPraceDomowe"
|
|
||||||
const val IDZIENNIK_WEB_NOTICES = "mod_panelRodzica/uwagi/WS_uwagiUcznia.asmx/pobierzUwagiUcznia"
|
|
||||||
const val IDZIENNIK_WEB_ATTENDANCE = "mod_panelRodzica/obecnosci/WS_obecnosciUcznia.asmx/pobierzObecnosciUcznia"
|
|
||||||
const val IDZIENNIK_WEB_ANNOUNCEMENTS = "mod_panelRodzica/tabOgl/WS_tablicaOgloszen.asmx/GetOgloszenia"
|
|
||||||
const val IDZIENNIK_WEB_MESSAGES_LIST = "mod_komunikator/WS_wiadomosci.asmx/PobierzListeWiadomosci"
|
|
||||||
|
|
||||||
val IDZIENNIK_API_USER_AGENT = SYSTEM_USER_AGENT
|
|
||||||
const val IDZIENNIK_API_URL = "https://iuczniowie.progman.pl/idziennik/api"
|
|
||||||
const val IDZIENNIK_API_CURRENT_REGISTER = "Uczniowie/\$STUDENT_ID/AktualnyDziennik"
|
|
||||||
const val IDZIENNIK_API_GRADES = "Uczniowie/\$STUDENT_ID/Oceny/" /* + semester */
|
|
||||||
const val IDZIENNIK_API_MESSAGES_INBOX = "Wiadomosci/Odebrane"
|
|
||||||
const val IDZIENNIK_API_MESSAGES_SENT = "Wiadomosci/Wyslane"
|
|
||||||
|
|
||||||
|
|
||||||
val MOBIDZIENNIK_USER_AGENT = SYSTEM_USER_AGENT
|
|
||||||
|
|
||||||
const val VULCAN_API_USER_AGENT = "MobileUserAgent"
|
|
||||||
const val VULCAN_API_APP_NAME = "VULCAN-Android-ModulUcznia"
|
|
||||||
const val VULCAN_API_APP_VERSION = "19.4.1.436"
|
|
||||||
const val VULCAN_API_PASSWORD = "CE75EA598C7743AD9B0B7328DED85B06"
|
|
||||||
const val VULCAN_API_PASSWORD_FAKELOG = "012345678901234567890123456789AB"
|
|
||||||
val VULCAN_API_DEVICE_NAME = "Szkolny.eu ${Build.MODEL}"
|
|
||||||
|
|
||||||
const val VULCAN_API_ENDPOINT_CERTIFICATE = "mobile-api/Uczen.v3.UczenStart/Certyfikat"
|
|
||||||
const val VULCAN_API_ENDPOINT_STUDENT_LIST = "mobile-api/Uczen.v3.UczenStart/ListaUczniow"
|
|
||||||
const val VULCAN_API_ENDPOINT_DICTIONARIES = "mobile-api/Uczen.v3.Uczen/Slowniki"
|
|
||||||
const val VULCAN_API_ENDPOINT_TIMETABLE = "mobile-api/Uczen.v3.Uczen/PlanLekcjiZeZmianami"
|
|
||||||
const val VULCAN_API_ENDPOINT_GRADES = "mobile-api/Uczen.v3.Uczen/Oceny"
|
|
||||||
const val VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS = "mobile-api/Uczen.v3.Uczen/OcenyPodsumowanie"
|
|
||||||
const val VULCAN_API_ENDPOINT_EVENTS = "mobile-api/Uczen.v3.Uczen/Sprawdziany"
|
|
||||||
const val VULCAN_API_ENDPOINT_HOMEWORK = "mobile-api/Uczen.v3.Uczen/ZadaniaDomowe"
|
|
||||||
const val VULCAN_API_ENDPOINT_NOTICES = "mobile-api/Uczen.v3.Uczen/UwagiUcznia"
|
|
||||||
const val VULCAN_API_ENDPOINT_ATTENDANCE = "mobile-api/Uczen.v3.Uczen/Frekwencje"
|
|
||||||
const val VULCAN_API_ENDPOINT_MESSAGES_RECEIVED = "mobile-api/Uczen.v3.Uczen/WiadomosciOdebrane"
|
|
||||||
const val VULCAN_API_ENDPOINT_MESSAGES_SENT = "mobile-api/Uczen.v3.Uczen/WiadomosciWyslane"
|
|
||||||
const val VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS = "mobile-api/Uczen.v3.Uczen/ZmienStatusWiadomosci"
|
|
||||||
const val VULCAN_API_ENDPOINT_PUSH = "mobile-api/Uczen.v3.Uczen/UstawPushToken"
|
|
@ -1,210 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ANNOUNCEMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES
|
|
||||||
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.R
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_LUCKY_NUMBER
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_ANNOUNCEMENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_ATTENDANCE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_EVENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_GRADE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_MESSAGE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_NEW_NOTICE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification.Companion.TYPE_TIMETABLE_LESSON_CHANGE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notification.getNotificationTitle
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class DataNotifications(val data: Data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "DataNotifications"
|
|
||||||
}
|
|
||||||
|
|
||||||
val app = data.app
|
|
||||||
val profileId = data.profile?.id ?: -1
|
|
||||||
val profileName = data.profile?.name ?: ""
|
|
||||||
val profile = data.profile
|
|
||||||
val loginStore = data.loginStore
|
|
||||||
|
|
||||||
init { run {
|
|
||||||
if (profile == null) {
|
|
||||||
return@run
|
|
||||||
}
|
|
||||||
|
|
||||||
for (lesson in app.db.timetableDao().getNotNotifiedNow(profileId)) {
|
|
||||||
val text = app.getString(R.string.notification_lesson_change_format, lesson.getDisplayChangeType(app), if (lesson.displayDate == null) "" else lesson.displayDate!!.formattedString, lesson.changeSubjectName)
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_TIMETABLE_LESSON_CHANGE),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_TIMETABLE_LESSON_CHANGE,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_TIMETABLE,
|
|
||||||
addedDate = lesson.addedDate
|
|
||||||
).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
for (event in app.db.eventDao().getNotNotifiedNow(profileId)) {
|
|
||||||
val text = if (event.type == Event.TYPE_HOMEWORK)
|
|
||||||
app.getString(
|
|
||||||
if (event.subjectLongName.isNullOrEmpty())
|
|
||||||
R.string.notification_homework_no_subject_format
|
|
||||||
else
|
|
||||||
R.string.notification_homework_format,
|
|
||||||
event.subjectLongName,
|
|
||||||
event.eventDate.formattedString
|
|
||||||
)
|
|
||||||
else
|
|
||||||
app.getString(
|
|
||||||
if (event.subjectLongName.isNullOrEmpty())
|
|
||||||
R.string.notification_event_no_subject_format
|
|
||||||
else
|
|
||||||
R.string.notification_event_format,
|
|
||||||
event.typeName,
|
|
||||||
event.eventDate.formattedString,
|
|
||||||
event.subjectLongName
|
|
||||||
)
|
|
||||||
val type = if (event.type == Event.TYPE_HOMEWORK) TYPE_NEW_HOMEWORK else TYPE_NEW_EVENT
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(type),
|
|
||||||
text = text,
|
|
||||||
type = type,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = if (event.type == Event.TYPE_HOMEWORK) DRAWER_ITEM_HOMEWORK else DRAWER_ITEM_AGENDA,
|
|
||||||
addedDate = event.addedDate
|
|
||||||
).addExtra("eventId", event.id).addExtra("eventDate", event.eventDate.value.toLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
val today = Date.getToday()
|
|
||||||
val todayValue = today.value
|
|
||||||
profile.currentSemester = profile.dateToSemester(today)
|
|
||||||
|
|
||||||
for (grade in app.db.gradeDao().getNotNotifiedNow(profileId)) {
|
|
||||||
val gradeName = when (grade.type) {
|
|
||||||
TYPE_SEMESTER1_PROPOSED, TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format_2, grade.name)
|
|
||||||
TYPE_SEMESTER1_FINAL, TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format_2, grade.name)
|
|
||||||
TYPE_YEAR_PROPOSED -> app.getString(R.string.grade_year_proposed_format_2, grade.name)
|
|
||||||
TYPE_YEAR_FINAL -> app.getString(R.string.grade_year_final_format_2, grade.name)
|
|
||||||
else -> grade.name
|
|
||||||
}
|
|
||||||
val text = app.getString(R.string.notification_grade_format, gradeName, grade.subjectLongName)
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_NEW_GRADE),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_NEW_GRADE,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_GRADES,
|
|
||||||
addedDate = grade.addedDate
|
|
||||||
).addExtra("gradeId", grade.id).addExtra("gradesSubjectId", grade.subjectId)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (notice in app.db.noticeDao().getNotNotifiedNow(profileId)) {
|
|
||||||
val noticeTypeStr = if (notice.type == Notice.TYPE_POSITIVE) app.getString(R.string.notification_notice_praise) else if (notice.type == Notice.TYPE_NEGATIVE) app.getString(R.string.notification_notice_warning) else app.getString(R.string.notification_notice_new)
|
|
||||||
val text = app.getString(R.string.notification_notice_format, noticeTypeStr, notice.teacherFullName, Date.fromMillis(notice.addedDate).formattedString)
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_NEW_NOTICE),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_NEW_NOTICE,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_BEHAVIOUR,
|
|
||||||
addedDate = notice.addedDate
|
|
||||||
).addExtra("noticeId", notice.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (attendance in app.db.attendanceDao().getNotNotifiedNow(profileId)) {
|
|
||||||
var attendanceTypeStr = app.getString(R.string.notification_type_attendance)
|
|
||||||
when (attendance.type) {
|
|
||||||
Attendance.TYPE_ABSENT -> attendanceTypeStr = app.getString(R.string.notification_absence)
|
|
||||||
Attendance.TYPE_ABSENT_EXCUSED -> attendanceTypeStr = app.getString(R.string.notification_absence_excused)
|
|
||||||
Attendance.TYPE_BELATED -> attendanceTypeStr = app.getString(R.string.notification_belated)
|
|
||||||
Attendance.TYPE_BELATED_EXCUSED -> attendanceTypeStr = app.getString(R.string.notification_belated_excused)
|
|
||||||
Attendance.TYPE_RELEASED -> attendanceTypeStr = app.getString(R.string.notification_release)
|
|
||||||
}
|
|
||||||
val text = app.getString(
|
|
||||||
if (attendance.subjectLongName.isNullOrEmpty())
|
|
||||||
R.string.notification_attendance_no_lesson_format
|
|
||||||
else
|
|
||||||
R.string.notification_attendance_format,
|
|
||||||
attendanceTypeStr,
|
|
||||||
attendance.subjectLongName,
|
|
||||||
attendance.lessonDate.formattedString
|
|
||||||
)
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_NEW_ATTENDANCE),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_NEW_ATTENDANCE,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_ATTENDANCE,
|
|
||||||
addedDate = attendance.addedDate
|
|
||||||
).addExtra("attendanceId", attendance.id).addExtra("attendanceSubjectId", attendance.subjectId)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (announcement in app.db.announcementDao().getNotNotifiedNow(profileId)) {
|
|
||||||
val text = app.context.getString(R.string.notification_announcement_format, announcement.subject)
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_NEW_ANNOUNCEMENT),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_NEW_ANNOUNCEMENT,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_ANNOUNCEMENTS,
|
|
||||||
addedDate = announcement.addedDate
|
|
||||||
).addExtra("announcementId", announcement.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (message in app.db.messageDao().getReceivedNotNotifiedNow(profileId)) {
|
|
||||||
val text = app.context.getString(R.string.notification_message_format, message.senderFullName, message.subject)
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_NEW_MESSAGE),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_NEW_MESSAGE,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_MESSAGES,
|
|
||||||
addedDate = message.addedDate
|
|
||||||
).addExtra("messageType", Message.TYPE_RECEIVED.toLong()).addExtra("messageId", message.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
val luckyNumbers = app.db.luckyNumberDao().getNotNotifiedNow(profileId)
|
|
||||||
luckyNumbers?.removeAll { it.date < today }
|
|
||||||
luckyNumbers?.forEach { luckyNumber ->
|
|
||||||
val text = when (luckyNumber.date.value) {
|
|
||||||
todayValue -> // LN for today
|
|
||||||
app.getString(if (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) R.string.notification_lucky_number_yours_format else R.string.notification_lucky_number_format, luckyNumber.number)
|
|
||||||
todayValue + 1 -> // LN for tomorrow
|
|
||||||
app.getString(if (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) R.string.notification_lucky_number_yours_tomorrow_format else R.string.notification_lucky_number_tomorrow_format, luckyNumber.number)
|
|
||||||
else -> // LN for later
|
|
||||||
app.getString(if (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) R.string.notification_lucky_number_yours_later_format else R.string.notification_lucky_number_later_format, luckyNumber.date.formattedString, luckyNumber.number)
|
|
||||||
}
|
|
||||||
data.notifications += Notification(
|
|
||||||
title = app.getNotificationTitle(TYPE_LUCKY_NUMBER),
|
|
||||||
text = text,
|
|
||||||
type = TYPE_LUCKY_NUMBER,
|
|
||||||
profileId = profileId,
|
|
||||||
profileName = profileName,
|
|
||||||
viewId = DRAWER_ITEM_HOME,
|
|
||||||
addedDate = luckyNumber.addedDate
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.db.metadataDao().setAllNotified(profileId, true)
|
|
||||||
}}
|
|
||||||
}
|
|
1171
app/src/main/java/pl/szczodrzynski/edziennik/data/api/Edziennik.java
Normal file
1171
app/src/main/java/pl/szczodrzynski/edziennik/data/api/Edziennik.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
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.R
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
|
|
||||||
class EdziennikNotification(val context: Context) {
|
|
||||||
companion object {
|
|
||||||
const val NOTIFICATION_ID = 20191001
|
|
||||||
}
|
|
||||||
|
|
||||||
private val notificationManager by lazy { context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
|
||||||
|
|
||||||
private val notificationBuilder: NotificationCompat.Builder by lazy {
|
|
||||||
NotificationCompat.Builder(context, ApiService.NOTIFICATION_API_CHANNEL_ID)
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
|
||||||
.setPriority(PRIORITY_MIN)
|
|
||||||
.setOngoing(true)
|
|
||||||
.setLocalOnly(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
val notification: Notification
|
|
||||||
get() = notificationBuilder.build()
|
|
||||||
|
|
||||||
private var errorCount = 0
|
|
||||||
private var criticalErrorCount = 0
|
|
||||||
|
|
||||||
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(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
|
||||||
}
|
|
||||||
private val closePendingIntent: PendingIntent
|
|
||||||
get() {
|
|
||||||
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
|
||||||
intent.putExtra("task", "ServiceCloseRequest")
|
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun errorCountText(): String? {
|
|
||||||
var result = ""
|
|
||||||
if (criticalErrorCount > 0) {
|
|
||||||
result += context.resources.getQuantityString(R.plurals.critical_errors_format, criticalErrorCount, criticalErrorCount)
|
|
||||||
}
|
|
||||||
if (criticalErrorCount > 0 && errorCount > 0) {
|
|
||||||
result += ", "
|
|
||||||
}
|
|
||||||
if (errorCount > 0) {
|
|
||||||
result += context.resources.getQuantityString(R.plurals.normal_errors_format, errorCount, errorCount)
|
|
||||||
}
|
|
||||||
return if (result.isEmpty()) null else result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setIdle(): EdziennikNotification {
|
|
||||||
notificationBuilder.setContentTitle(context.getString(R.string.edziennik_notification_api_title))
|
|
||||||
notificationBuilder.setProgress(0, 0, false)
|
|
||||||
notificationBuilder.apply {
|
|
||||||
val str = context.getString(R.string.edziennik_notification_api_text)
|
|
||||||
setStyle(NotificationCompat.BigTextStyle().bigText(str))
|
|
||||||
setContentText(str)
|
|
||||||
}
|
|
||||||
setCloseAction()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addError(): EdziennikNotification {
|
|
||||||
errorCount++
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
fun setCriticalError(): EdziennikNotification {
|
|
||||||
criticalErrorCount++
|
|
||||||
notificationBuilder.setContentTitle(context.getString(R.string.edziennik_notification_api_error_title))
|
|
||||||
notificationBuilder.setProgress(0, 0, false)
|
|
||||||
notificationBuilder.apply {
|
|
||||||
val str = errorCountText()
|
|
||||||
setStyle(NotificationCompat.BigTextStyle().bigText(str))
|
|
||||||
setContentText(str)
|
|
||||||
}
|
|
||||||
setCloseAction()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setProgress(progress: Float): EdziennikNotification {
|
|
||||||
notificationBuilder.setProgress(100, progress.roundToInt(), progress < 0f)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
fun setProgressText(progressText: String?): EdziennikNotification {
|
|
||||||
notificationBuilder.setContentTitle(progressText)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setCurrentTask(taskId: Int, progressText: String?): EdziennikNotification {
|
|
||||||
notificationBuilder.setProgress(100, 0, true)
|
|
||||||
notificationBuilder.setContentTitle(progressText)
|
|
||||||
notificationBuilder.apply {
|
|
||||||
val str = errorCountText()
|
|
||||||
setStyle(NotificationCompat.BigTextStyle().bigText(str))
|
|
||||||
setContentText(str)
|
|
||||||
}
|
|
||||||
setCancelAction(taskId)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setCloseAction(): EdziennikNotification {
|
|
||||||
notificationBuilder.mActions.clear()
|
|
||||||
notificationBuilder.addAction(
|
|
||||||
NotificationCompat.Action(
|
|
||||||
R.drawable.ic_notification,
|
|
||||||
context.getString(R.string.edziennik_notification_api_close),
|
|
||||||
closePendingIntent
|
|
||||||
))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
private fun setCancelAction(taskId: Int) {
|
|
||||||
notificationBuilder.mActions.clear()
|
|
||||||
notificationBuilder.addAction(
|
|
||||||
NotificationCompat.Action(
|
|
||||||
R.drawable.ic_notification,
|
|
||||||
context.getString(R.string.edziennik_notification_api_cancel),
|
|
||||||
cancelPendingIntent(taskId)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun post() {
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER
|
|
||||||
|
|
||||||
fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featureIds: List<Int>, viewId: Int?) {
|
|
||||||
val data = this
|
|
||||||
|
|
||||||
val possibleLoginMethods = data.loginMethods.toMutableList()
|
|
||||||
|
|
||||||
for (loginMethod in loginMethods) {
|
|
||||||
if (loginMethod.isPossible(profile, loginStore))
|
|
||||||
possibleLoginMethods += loginMethod.loginMethodId
|
|
||||||
}
|
|
||||||
|
|
||||||
//var highestLoginMethod = 0
|
|
||||||
var endpointList = mutableListOf<Feature>()
|
|
||||||
val requiredLoginMethods = mutableListOf<Int>()
|
|
||||||
|
|
||||||
data.targetEndpointIds.clear()
|
|
||||||
data.targetLoginMethodIds.clear()
|
|
||||||
|
|
||||||
// get all endpoints for every feature, only if possible to login and possible/necessary to sync
|
|
||||||
for (featureId in featureIds) {
|
|
||||||
features.filter {
|
|
||||||
it.featureId == featureId // feature ID matches
|
|
||||||
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
|
|
||||||
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
|
|
||||||
}.let {
|
|
||||||
endpointList.addAll(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val timestamp = System.currentTimeMillis()
|
|
||||||
|
|
||||||
endpointList = endpointList
|
|
||||||
// sort the endpoint list by feature ID and priority
|
|
||||||
.sortedWith(compareBy(Feature::featureId, Feature::priority))
|
|
||||||
// select only the most important endpoint for each feature
|
|
||||||
.distinctBy { it.featureId }
|
|
||||||
.toMutableList()
|
|
||||||
// add all endpoint IDs and required login methods, filtering using timers
|
|
||||||
.onEach { feature ->
|
|
||||||
feature.endpointIds.forEach { endpoint ->
|
|
||||||
(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)
|
|
||||||
requiredLoginMethods.add(endpoint.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check every login method for any dependencies
|
|
||||||
for (loginMethodId in requiredLoginMethods) {
|
|
||||||
var requiredLoginMethod: Int? = loginMethodId
|
|
||||||
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
|
|
||||||
loginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
|
|
||||||
if (requiredLoginMethod != null)
|
|
||||||
data.targetLoginMethodIds.add(requiredLoginMethod!!)
|
|
||||||
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort and distinct every login method and endpoint
|
|
||||||
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
|
|
||||||
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
|
||||||
data.targetEndpointIds.sort()
|
|
||||||
|
|
||||||
progressCount = targetLoginMethodIds.size + targetEndpointIds.size
|
|
||||||
progressStep = if (progressCount <= 0) 0f else 100f / progressCount.toFloat()
|
|
||||||
}
|
|
@ -1,179 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-21.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
/*const val CODE_OTHER = 0
|
|
||||||
const val CODE_OK = 1
|
|
||||||
const val CODE_NO_INTERNET = 10
|
|
||||||
const val CODE_SSL_ERROR = 13
|
|
||||||
const val CODE_ARCHIVED = 5
|
|
||||||
const val CODE_MAINTENANCE = 6
|
|
||||||
const val CODE_LOGIN_ERROR = 7
|
|
||||||
const val CODE_ACCOUNT_MISMATCH = 8
|
|
||||||
const val CODE_APP_SERVER_ERROR = 9
|
|
||||||
const val CODE_MULTIACCOUNT_SETUP = 12
|
|
||||||
const val CODE_TIMEOUT = 11
|
|
||||||
const val CODE_PROFILE_NOT_FOUND = 14
|
|
||||||
const val CODE_ATTACHMENT_NOT_AVAILABLE = 28
|
|
||||||
const val CODE_INVALID_LOGIN = 2
|
|
||||||
const val CODE_INVALID_SERVER_ADDRESS = 21
|
|
||||||
const val CODE_INVALID_SCHOOL_NAME = 22
|
|
||||||
const val CODE_INVALID_DEVICE = 23
|
|
||||||
const val CODE_OLD_PASSWORD = 4
|
|
||||||
const val CODE_INVALID_TOKEN = 24
|
|
||||||
const val CODE_EXPIRED_TOKEN = 27
|
|
||||||
const val CODE_INVALID_SYMBOL = 25
|
|
||||||
const val CODE_INVALID_PIN = 26
|
|
||||||
const val CODE_LIBRUS_NOT_ACTIVATED = 29
|
|
||||||
const val CODE_SYNERGIA_NOT_ACTIVATED = 32
|
|
||||||
const val CODE_LIBRUS_DISCONNECTED = 31
|
|
||||||
const val CODE_PROFILE_ARCHIVED = 30*/
|
|
||||||
|
|
||||||
const val ERROR_REQUEST_FAILURE = 50
|
|
||||||
const val ERROR_REQUEST_HTTP_400 = 51
|
|
||||||
const val ERROR_REQUEST_HTTP_401 = 52
|
|
||||||
const val ERROR_REQUEST_HTTP_403 = 53
|
|
||||||
const val ERROR_REQUEST_HTTP_404 = 54
|
|
||||||
const val ERROR_REQUEST_HTTP_405 = 55
|
|
||||||
const val ERROR_REQUEST_HTTP_410 = 56
|
|
||||||
const val ERROR_REQUEST_HTTP_500 = 57
|
|
||||||
const val ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND = 60
|
|
||||||
const val ERROR_REQUEST_FAILURE_TIMEOUT = 61
|
|
||||||
const val ERROR_REQUEST_FAILURE_NO_INTERNET = 62
|
|
||||||
const val ERROR_RESPONSE_EMPTY = 100
|
|
||||||
const val ERROR_LOGIN_DATA_MISSING = 101
|
|
||||||
const val ERROR_PROFILE_MISSING = 105
|
|
||||||
const val ERROR_INVALID_LOGIN_MODE = 110
|
|
||||||
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
|
||||||
const val ERROR_NOT_IMPLEMENTED = 112
|
|
||||||
const val ERROR_FILE_DOWNLOAD = 113
|
|
||||||
|
|
||||||
const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
|
|
||||||
|
|
||||||
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
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_CONNECTION_PROBLEMS = 125
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_INVALID_CLIENT = 126
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_REG_ACCEPT_NEEDED = 127
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_CHANGE_PASSWORD_ERROR = 128
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_PASSWORD_CHANGE_REQUIRED = 129
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN = 130
|
|
||||||
const val ERROR_LOGIN_LIBRUS_API_OTHER = 131
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING = 132
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED = 133
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR = 134
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_TOKEN_MISSING = 139
|
|
||||||
const val ERROR_LIBRUS_API_TOKEN_EXPIRED = 140
|
|
||||||
const val ERROR_LIBRUS_API_INSUFFICIENT_SCOPES = 141
|
|
||||||
const val ERROR_LIBRUS_API_OTHER = 142
|
|
||||||
const val ERROR_LIBRUS_API_ACCESS_DENIED = 143
|
|
||||||
const val ERROR_LIBRUS_API_RESOURCE_NOT_FOUND = 144
|
|
||||||
const val ERROR_LIBRUS_API_DATA_NOT_FOUND = 145
|
|
||||||
const val ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC = 146
|
|
||||||
const val ERROR_LIBRUS_API_RESOURCE_ACCESS_DENIED = 147
|
|
||||||
const val ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS = 148
|
|
||||||
const val ERROR_LIBRUS_API_INCORRECT_ENDPOINT = 149
|
|
||||||
const val ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE = 150
|
|
||||||
const val ERROR_LIBRUS_API_NOTES_NOT_ACTIVE = 151
|
|
||||||
const val ERROR_LOGIN_LIBRUS_SYNERGIA_NO_TOKEN = 152
|
|
||||||
const val ERROR_LOGIN_LIBRUS_SYNERGIA_TOKEN_INVALID = 153
|
|
||||||
const val ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID = 154
|
|
||||||
const val ERROR_LIBRUS_MESSAGES_ACCESS_DENIED = 155
|
|
||||||
const val ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED = 156
|
|
||||||
const val ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID = 157
|
|
||||||
const val ERROR_LIBRUS_PORTAL_ACCESS_DENIED = 158
|
|
||||||
const val ERROR_LIBRUS_PORTAL_API_DISABLED = 159
|
|
||||||
const val ERROR_LIBRUS_PORTAL_SYNERGIA_DISCONNECTED = 160
|
|
||||||
const val ERROR_LIBRUS_PORTAL_OTHER = 161
|
|
||||||
const val ERROR_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND = 162
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_OTHER = 163
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED = 164
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED = 165
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_NO_CLIENT_ID = 166
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE = 167
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_NO_REFRESH = 168
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_NO_REDIRECT = 169
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_UNSUPPORTED_GRANT = 170
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_CLIENT_ID = 171
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID = 172
|
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED = 173
|
|
||||||
const val ERROR_LIBRUS_SYNERGIA_OTHER = 174
|
|
||||||
const val ERROR_LIBRUS_SYNERGIA_MAINTENANCE = 175
|
|
||||||
const val ERROR_LIBRUS_MESSAGES_MAINTENANCE = 176
|
|
||||||
const val ERROR_LIBRUS_MESSAGES_ERROR = 177
|
|
||||||
const val ERROR_LIBRUS_MESSAGES_OTHER = 178
|
|
||||||
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_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_DEVICE = 203
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED = 204
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_MAINTENANCE = 205
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS = 206
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OTHER = 210
|
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED = 211
|
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY = 212
|
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE = 216
|
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID = 213
|
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID = 215
|
|
||||||
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_PIN = 309
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING = 310
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_PIN_1_REMAINING = 311
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_PIN_2_REMAINING = 312
|
|
||||||
const val ERROR_LOGIN_VULCAN_EXPIRED_TOKEN = 321
|
|
||||||
const val ERROR_LOGIN_VULCAN_OTHER = 322
|
|
||||||
const val ERROR_LOGIN_VULCAN_ONLY_KINDERGARTEN = 330
|
|
||||||
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_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN = 401
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME = 402
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED = 403
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_MAINTENANCE = 404
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_SERVER_ERROR = 405
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_OTHER = 410
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_API_NO_ACCESS = 411 /* {"d":{"__type":"mds.Web.mod_komunikator.WS_mod_wiadomosci+detailWiadomosci","Wiadomosc":{"_recordId":0,"DataNadania":null,"DataOdczytania":null,"Nadawca":null,"ListaOdbiorcow":[],"Tytul":null,"Text":null,"ListaZal":[]},"Bledy":{"__type":"mds.Module.Globalne+sBledy","CzyJestBlad":true,"ListaBledow":["Nie masz dostępu do tych zasobów!"],"ListaKodowBledow":[]},"czyJestWiecej":false}} */
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION = 420
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH = 421
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER = 422
|
|
||||||
const val ERROR_IDZIENNIK_WEB_ACCESS_DENIED = 430
|
|
||||||
const val ERROR_IDZIENNIK_WEB_OTHER = 431
|
|
||||||
const val ERROR_IDZIENNIK_WEB_MAINTENANCE = 432
|
|
||||||
const val ERROR_IDZIENNIK_WEB_SERVER_ERROR = 433
|
|
||||||
const val ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED = 434
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR = 440
|
|
||||||
const val ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA = 441
|
|
||||||
const val ERROR_IDZIENNIK_API_ACCESS_DENIED = 450
|
|
||||||
const val ERROR_IDZIENNIK_API_OTHER = 451
|
|
||||||
|
|
||||||
const val ERROR_TEMPLATE_WEB_OTHER = 801
|
|
||||||
|
|
||||||
const val EXCEPTION_API_TASK = 900
|
|
||||||
const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901
|
|
||||||
const val EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN = 902
|
|
||||||
const val EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903
|
|
||||||
const val EXCEPTION_LIBRUS_API_REQUEST = 904
|
|
||||||
const val EXCEPTION_LIBRUS_SYNERGIA_REQUEST = 905
|
|
||||||
const val EXCEPTION_MOBIDZIENNIK_WEB_REQUEST = 906
|
|
||||||
const val EXCEPTION_VULCAN_API_REQUEST = 907
|
|
||||||
const val EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST = 908
|
|
||||||
const val EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST = 909
|
|
||||||
const val EXCEPTION_NOTIFY = 910
|
|
||||||
const val EXCEPTION_LIBRUS_MESSAGES_REQUEST = 911
|
|
||||||
const val EXCEPTION_IDZIENNIK_WEB_REQUEST = 912
|
|
||||||
const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
|
|
||||||
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
|
||||||
|
|
||||||
const val LOGIN_NO_ARGUMENTS = 1201
|
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-29.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ANNOUNCEMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES
|
|
||||||
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.modules.messages.Message.TYPE_RECEIVED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
|
||||||
|
|
||||||
internal const val FEATURE_TIMETABLE = 1
|
|
||||||
internal const val FEATURE_AGENDA = 2
|
|
||||||
internal const val FEATURE_GRADES = 3
|
|
||||||
internal const val FEATURE_HOMEWORK = 4
|
|
||||||
internal const val FEATURE_BEHAVIOUR = 5
|
|
||||||
internal const val FEATURE_ATTENDANCE = 6
|
|
||||||
internal const val FEATURE_MESSAGES_INBOX = 7
|
|
||||||
internal const val FEATURE_MESSAGES_SENT = 8
|
|
||||||
internal const val FEATURE_ANNOUNCEMENTS = 9
|
|
||||||
|
|
||||||
internal const val FEATURE_ALWAYS_NEEDED = 100
|
|
||||||
internal const val FEATURE_STUDENT_INFO = 101
|
|
||||||
internal const val FEATURE_STUDENT_NUMBER = 109
|
|
||||||
internal const val FEATURE_SCHOOL_INFO = 102
|
|
||||||
internal const val FEATURE_CLASS_INFO = 103
|
|
||||||
internal const val FEATURE_TEAM_INFO = 104
|
|
||||||
internal const val FEATURE_LUCKY_NUMBER = 105
|
|
||||||
internal const val FEATURE_TEACHERS = 106
|
|
||||||
internal const val FEATURE_SUBJECTS = 107
|
|
||||||
internal const val FEATURE_CLASSROOMS = 108
|
|
||||||
internal const val FEATURE_PUSH_CONFIG = 120
|
|
||||||
|
|
||||||
object Features {
|
|
||||||
private fun getAllNecessary(): List<Int> = listOf(
|
|
||||||
FEATURE_ALWAYS_NEEDED,
|
|
||||||
FEATURE_STUDENT_INFO,
|
|
||||||
FEATURE_STUDENT_NUMBER,
|
|
||||||
FEATURE_SCHOOL_INFO,
|
|
||||||
FEATURE_CLASS_INFO,
|
|
||||||
FEATURE_TEAM_INFO,
|
|
||||||
FEATURE_LUCKY_NUMBER,
|
|
||||||
FEATURE_TEACHERS,
|
|
||||||
FEATURE_SUBJECTS,
|
|
||||||
FEATURE_CLASSROOMS)
|
|
||||||
|
|
||||||
private fun getAllFeatures(): List<Int> = listOf(
|
|
||||||
FEATURE_TIMETABLE,
|
|
||||||
FEATURE_AGENDA,
|
|
||||||
FEATURE_GRADES,
|
|
||||||
FEATURE_HOMEWORK,
|
|
||||||
FEATURE_BEHAVIOUR,
|
|
||||||
FEATURE_ATTENDANCE,
|
|
||||||
FEATURE_MESSAGES_INBOX,
|
|
||||||
FEATURE_MESSAGES_SENT,
|
|
||||||
FEATURE_ANNOUNCEMENTS)
|
|
||||||
|
|
||||||
fun getAllIds(): List<Int> = getAllFeatures() + getAllNecessary()
|
|
||||||
|
|
||||||
fun getIdsByView(targetId: Int, targetType: Int): List<Int> {
|
|
||||||
return (when (targetId) {
|
|
||||||
DRAWER_ITEM_HOME -> getAllFeatures()
|
|
||||||
DRAWER_ITEM_TIMETABLE -> listOf(FEATURE_TIMETABLE)
|
|
||||||
DRAWER_ITEM_AGENDA -> listOf(FEATURE_AGENDA)
|
|
||||||
DRAWER_ITEM_GRADES -> listOf(FEATURE_GRADES)
|
|
||||||
DRAWER_ITEM_MESSAGES -> when (targetType) {
|
|
||||||
TYPE_RECEIVED -> listOf(FEATURE_MESSAGES_INBOX)
|
|
||||||
TYPE_SENT -> listOf(FEATURE_MESSAGES_SENT)
|
|
||||||
else -> listOf(FEATURE_MESSAGES_INBOX, FEATURE_MESSAGES_SENT)
|
|
||||||
}
|
|
||||||
DRAWER_ITEM_HOMEWORK -> listOf(FEATURE_HOMEWORK)
|
|
||||||
DRAWER_ITEM_BEHAVIOUR -> listOf(FEATURE_BEHAVIOUR)
|
|
||||||
DRAWER_ITEM_ATTENDANCE -> listOf(FEATURE_ATTENDANCE)
|
|
||||||
DRAWER_ITEM_ANNOUNCEMENTS -> listOf(FEATURE_ANNOUNCEMENTS)
|
|
||||||
else -> getAllFeatures()
|
|
||||||
} + getAllNecessary()).sorted()
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
3872
app/src/main/java/pl/szczodrzynski/edziennik/data/api/Librus.java
Normal file
3872
app/src/main/java/pl/szczodrzynski/edziennik/data/api/Librus.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-20.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginMessages
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPortal
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginSynergia
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
|
||||||
|
|
||||||
// librus
|
|
||||||
// mobidziennik
|
|
||||||
// idziennik
|
|
||||||
// vulcan
|
|
||||||
// mobireg
|
|
||||||
|
|
||||||
const val SYNERGIA_API_ENABLED = true
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const val LOGIN_TYPE_IDZIENNIK = 3
|
|
||||||
|
|
||||||
const val LOGIN_TYPE_TEMPLATE = 21
|
|
||||||
|
|
||||||
// LOGIN MODES
|
|
||||||
const val LOGIN_MODE_IDZIENNIK_WEB = 0
|
|
||||||
|
|
||||||
const val LOGIN_MODE_TEMPLATE_WEB = 0
|
|
||||||
|
|
||||||
// LOGIN METHODS
|
|
||||||
const val LOGIN_METHOD_NOT_NEEDED = -1
|
|
||||||
const val LOGIN_METHOD_IDZIENNIK_WEB = 100
|
|
||||||
const val LOGIN_METHOD_IDZIENNIK_API = 200
|
|
||||||
const val LOGIN_METHOD_TEMPLATE_WEB = 100
|
|
||||||
const val LOGIN_METHOD_TEMPLATE_API = 200
|
|
||||||
|
|
||||||
const val LOGIN_TYPE_LIBRUS = 2
|
|
||||||
const val LOGIN_MODE_LIBRUS_EMAIL = 0
|
|
||||||
const val LOGIN_MODE_LIBRUS_SYNERGIA = 1
|
|
||||||
const val LOGIN_MODE_LIBRUS_JST = 2
|
|
||||||
const val LOGIN_METHOD_LIBRUS_PORTAL = 100
|
|
||||||
const val LOGIN_METHOD_LIBRUS_API = 200
|
|
||||||
const val LOGIN_METHOD_LIBRUS_SYNERGIA = 300
|
|
||||||
const val LOGIN_METHOD_LIBRUS_MESSAGES = 400
|
|
||||||
val librusLoginMethods = listOf(
|
|
||||||
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_PORTAL, LibrusLoginPortal::class.java)
|
|
||||||
.withIsPossible { _, loginStore ->
|
|
||||||
loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL
|
|
||||||
}
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_API, LibrusLoginApi::class.java)
|
|
||||||
.withIsPossible { _, loginStore ->
|
|
||||||
loginStore.mode != LOGIN_MODE_LIBRUS_SYNERGIA || SYNERGIA_API_ENABLED
|
|
||||||
}
|
|
||||||
.withRequiredLoginMethod { _, loginStore ->
|
|
||||||
if (loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) LOGIN_METHOD_LIBRUS_PORTAL else LOGIN_METHOD_NOT_NEEDED
|
|
||||||
},
|
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const val LOGIN_TYPE_MOBIDZIENNIK = 1
|
|
||||||
const val LOGIN_MODE_MOBIDZIENNIK_WEB = 0
|
|
||||||
const val LOGIN_METHOD_MOBIDZIENNIK_WEB = 100
|
|
||||||
const val LOGIN_METHOD_MOBIDZIENNIK_API2 = 300
|
|
||||||
val mobidziennikLoginMethods = listOf(
|
|
||||||
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_WEB, MobidziennikLoginWeb::class.java)
|
|
||||||
.withIsPossible { _, _ -> true }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }/*,
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_API2, MobidziennikLoginApi2::class.java)
|
|
||||||
.withIsPossible { _, loginStore -> loginStore.hasLoginData("email") }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }*/
|
|
||||||
)
|
|
||||||
|
|
||||||
const val LOGIN_TYPE_VULCAN = 4
|
|
||||||
const val LOGIN_MODE_VULCAN_API = 0
|
|
||||||
const val LOGIN_MODE_VULCAN_WEB = 1
|
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_MAIN = 100
|
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_NEW = 200
|
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_OLD = 300
|
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_MESSAGES = 400
|
|
||||||
const val LOGIN_METHOD_VULCAN_API = 500
|
|
||||||
val vulcanLoginMethods = listOf(
|
|
||||||
/*LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_MAIN, VulcanLoginWebMain::class.java)
|
|
||||||
.withIsPossible { _, _ -> false }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_NEW, VulcanLoginWebNew::class.java)
|
|
||||||
.withIsPossible { _, _ -> false }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_OLD, VulcanLoginWebOld::class.java)
|
|
||||||
.withIsPossible { _, _ -> false }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },*/
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_API, VulcanLoginApi::class.java)
|
|
||||||
.withIsPossible { _, _ -> true }
|
|
||||||
.withRequiredLoginMethod { _, loginStore ->
|
|
||||||
if (loginStore.mode == LOGIN_MODE_VULCAN_WEB) LOGIN_METHOD_VULCAN_WEB_NEW else LOGIN_METHOD_NOT_NEEDED
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val idziennikLoginMethods = listOf(
|
|
||||||
LoginMethod(LOGIN_TYPE_IDZIENNIK, LOGIN_METHOD_IDZIENNIK_WEB, IdziennikLoginWeb::class.java)
|
|
||||||
.withIsPossible { _, _ -> true }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_IDZIENNIK, LOGIN_METHOD_IDZIENNIK_API, IdziennikLoginApi::class.java)
|
|
||||||
.withIsPossible { _, _ -> true }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_IDZIENNIK_WEB }
|
|
||||||
)
|
|
||||||
|
|
||||||
val templateLoginMethods = listOf(
|
|
||||||
LoginMethod(LOGIN_TYPE_TEMPLATE, LOGIN_METHOD_TEMPLATE_WEB, TemplateLoginWeb::class.java)
|
|
||||||
.withIsPossible { _, _ -> true }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_TEMPLATE, LOGIN_METHOD_TEMPLATE_API, TemplateLoginApi::class.java)
|
|
||||||
.withIsPossible { _, _ -> true }
|
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_TEMPLATE_WEB }
|
|
||||||
)
|
|
File diff suppressed because it is too large
Load Diff
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api
|
|
||||||
|
|
||||||
object Regexes {
|
|
||||||
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
|
|
||||||
"""<div.*?>\n*\s*(.+?)\s*\n*(?:<.*?)??</div>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_GRADES_COLOR by lazy {
|
|
||||||
"""background-color:([#A-Fa-f0-9]+);""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_GRADES_CATEGORY by lazy {
|
|
||||||
"""> (.+?):</span>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_GRADES_CLASS_AVERAGE by lazy {
|
|
||||||
"""Średnia ocen:.*<strong>([0-9]*\.?[0-9]*)</strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_GRADES_ADDED_DATE by lazy {
|
|
||||||
"""Wpisano:.*<strong>.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)</strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_GRADES_COUNT_TO_AVG by lazy {
|
|
||||||
"""Liczona do średniej:.*?<strong>nie<br/?></strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_GRADES_DETAILS by lazy {
|
|
||||||
"""<strong.*?>(.+?)</strong>.*?<sup>.+?</sup>.*?(?:<small>\((.+?)\)</small>.*?)?<span>.*?Wartość oceny:.*?<strong>([0-9.]+)</strong>.*?Wpisał\(a\):.*?<strong>(.+?)</strong>.*?(?:Komentarz:.*?<strong>(.+?)</strong>)?</span>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
|
|
||||||
val MOBIDZIENNIK_EVENT_TYPE by lazy {
|
|
||||||
"""\(([0-9A-ząęóżźńśłć]*?)\)$""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_LUCKY_NUMBER by lazy {
|
|
||||||
"""class="szczesliwy_numerek".*>0*([0-9]+)(?:/0*[0-9]+)*</a>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_CLASS_CALENDAR by lazy {
|
|
||||||
"""events: (.+),$""".toRegex(RegexOption.MULTILINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val MOBIDZIENNIK_MESSAGE_READ_DATE by lazy {
|
|
||||||
"""czas przeczytania:.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_MESSAGE_SENT_READ_DATE by lazy {
|
|
||||||
""".+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_MESSAGE_ATTACHMENT by lazy {
|
|
||||||
"""href="https://.+?\.mobidziennik.pl/.+?&(?:amp;)?zalacznik=([0-9]+)"(?:.+?<small.+?\(([0-9.]+)\s(M|K|G|)B\))*""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
|
||||||
"""<input type="hidden".+?name="([A-z0-9_]+)?".+?value="([A-z0-9_+-/=]+)?".+?>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val IDZIENNIK_LOGIN_ERROR by lazy {
|
|
||||||
"""id="spanErrorMessage">(.*?)</""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME by lazy {
|
|
||||||
"""Imię i nazwisko:.+?">(.+?)</div>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val IDZIENNIK_LOGIN_FIRST_IS_PARENT by lazy {
|
|
||||||
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
|
|
||||||
}
|
|
||||||
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy {
|
|
||||||
"""name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
|
|
||||||
"""<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val IDZIENNIK_LOGIN_FIRST_STUDENT by lazy {
|
|
||||||
"""<option.*?value="([0-9]+)"\sdata-id-ucznia="([A-z0-9]+?)".*?>(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)</option>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val VULCAN_SHITFT_ANNOTATION by lazy {
|
|
||||||
"""\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val LIBRUS_ATTACHMENT_KEY by lazy {
|
|
||||||
"""singleUseKey=([0-9A-f_]+)""".toRegex()
|
|
||||||
}
|
|
||||||
}
|
|
1694
app/src/main/java/pl/szczodrzynski/edziennik/data/api/Vulcan.java
Normal file
1694
app/src/main/java/pl/szczodrzynski/edziennik/data/api/Vulcan.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-25.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
|
||||||
|
|
||||||
class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
|
||||||
|
|
||||||
fun isWebLoginValid() = loginExpiryTime-30 > currentTimeUnix() && webSessionId.isNotNullNorEmpty() && webAuth.isNotNullNorEmpty()
|
|
||||||
fun isApiLoginValid() = apiExpiryTime-30 > currentTimeUnix() && apiBearer.isNotNullNorEmpty()
|
|
||||||
|
|
||||||
override fun satisfyLoginMethods() {
|
|
||||||
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()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
if (isApiLoginValid())
|
|
||||||
loginMethods += LOGIN_METHOD_IDZIENNIK_API
|
|
||||||
}
|
|
||||||
|
|
||||||
private var mLoginExpiryTime: Long? = null
|
|
||||||
var loginExpiryTime: Long
|
|
||||||
get() { mLoginExpiryTime = mLoginExpiryTime ?: loginStore.getLoginData("loginExpiryTime", 0L); return mLoginExpiryTime ?: 0L }
|
|
||||||
set(value) { loginStore.putLoginData("loginExpiryTime", value); mLoginExpiryTime = value }
|
|
||||||
|
|
||||||
private var mApiExpiryTime: Long? = null
|
|
||||||
var apiExpiryTime: Long
|
|
||||||
get() { mApiExpiryTime = mApiExpiryTime ?: loginStore.getLoginData("apiExpiryTime", 0L); return mApiExpiryTime ?: 0L }
|
|
||||||
set(value) { loginStore.putLoginData("apiExpiryTime", value); mApiExpiryTime = value }
|
|
||||||
|
|
||||||
/* __ __ _
|
|
||||||
\ \ / / | |
|
|
||||||
\ \ /\ / /__| |__
|
|
||||||
\ \/ \/ / _ \ '_ \
|
|
||||||
\ /\ / __/ |_) |
|
|
||||||
\/ \/ \___|_._*/
|
|
||||||
private var mWebSchoolName: String? = null
|
|
||||||
var webSchoolName: String?
|
|
||||||
get() { mWebSchoolName = mWebSchoolName ?: loginStore.getLoginData("schoolName", null); return mWebSchoolName }
|
|
||||||
set(value) { loginStore.putLoginData("schoolName", value); mWebSchoolName = value }
|
|
||||||
private var mWebUsername: String? = null
|
|
||||||
var webUsername: String?
|
|
||||||
get() { mWebUsername = mWebUsername ?: loginStore.getLoginData("username", null); return mWebUsername }
|
|
||||||
set(value) { loginStore.putLoginData("username", value); mWebUsername = value }
|
|
||||||
private var mWebPassword: String? = null
|
|
||||||
var webPassword: String?
|
|
||||||
get() { mWebPassword = mWebPassword ?: loginStore.getLoginData("password", null); return mWebPassword }
|
|
||||||
set(value) { loginStore.putLoginData("password", value); mWebPassword = value }
|
|
||||||
|
|
||||||
private var mWebSessionId: String? = null
|
|
||||||
var webSessionId: String?
|
|
||||||
get() { mWebSessionId = mWebSessionId ?: loginStore.getLoginData("webSessionId", null); return mWebSessionId }
|
|
||||||
set(value) { loginStore.putLoginData("webSessionId", value); mWebSessionId = value }
|
|
||||||
private var mWebAuth: String? = null
|
|
||||||
var webAuth: String?
|
|
||||||
get() { mWebAuth = mWebAuth ?: loginStore.getLoginData("webAuth", null); return mWebAuth }
|
|
||||||
set(value) { loginStore.putLoginData("webAuth", value); mWebAuth = value }
|
|
||||||
|
|
||||||
/* _
|
|
||||||
/\ (_)
|
|
||||||
/ \ _ __ _
|
|
||||||
/ /\ \ | '_ \| |
|
|
||||||
/ ____ \| |_) | |
|
|
||||||
/_/ \_\ .__/|_|
|
|
||||||
| |
|
|
||||||
|*/
|
|
||||||
private var mApiBearer: String? = null
|
|
||||||
var apiBearer: String?
|
|
||||||
get() { mApiBearer = mApiBearer ?: loginStore.getLoginData("apiBearer", null); return mApiBearer }
|
|
||||||
set(value) { loginStore.putLoginData("apiBearer", value); mApiBearer = value }
|
|
||||||
|
|
||||||
/* ____ _ _
|
|
||||||
/ __ \| | | |
|
|
||||||
| | | | |_| |__ ___ _ __
|
|
||||||
| | | | __| '_ \ / _ \ '__|
|
|
||||||
| |__| | |_| | | | __/ |
|
|
||||||
\____/ \__|_| |_|\___|*/
|
|
||||||
private var mStudentId: String? = null
|
|
||||||
var studentId: String?
|
|
||||||
get() { mStudentId = mStudentId ?: profile?.getStudentData("studentId", null); return mStudentId }
|
|
||||||
set(value) { profile?.putStudentData("studentId", value) ?: return; mStudentId = value }
|
|
||||||
|
|
||||||
private var mRegisterId: Int? = null
|
|
||||||
var registerId: Int
|
|
||||||
get() { mRegisterId = mRegisterId ?: profile?.getStudentData("registerId", 0); return mRegisterId ?: 0 }
|
|
||||||
set(value) { profile?.putStudentData("registerId", value) ?: return; mRegisterId = value }
|
|
||||||
|
|
||||||
private var mSchoolYearId: Int? = null
|
|
||||||
var schoolYearId: Int
|
|
||||||
get() { mSchoolYearId = mSchoolYearId ?: profile?.getStudentData("schoolYearId", 0); return mSchoolYearId ?: 0 }
|
|
||||||
set(value) { profile?.putStudentData("schoolYearId", value) ?: return; mSchoolYearId = value }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* _ _ _ _ _
|
|
||||||
| | | | | (_) |
|
|
||||||
| | | | |_ _| |___
|
|
||||||
| | | | __| | / __|
|
|
||||||
| |__| | |_| | \__ \
|
|
||||||
\____/ \__|_|_|__*/
|
|
||||||
fun getSubject(name: String, id: Long?, shortName: String): Subject {
|
|
||||||
var subject = if (id == null)
|
|
||||||
subjectList.singleOrNull { it.longName == name }
|
|
||||||
else
|
|
||||||
subjectList.singleOrNull { it.id == id }
|
|
||||||
|
|
||||||
if (subject == null) {
|
|
||||||
subject = Subject(profileId, id ?: name.crc16().toLong(), name, shortName)
|
|
||||||
subjectList[subject.id] = subject
|
|
||||||
}
|
|
||||||
return subject
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacher(firstName: String, lastName: String): Teacher {
|
|
||||||
val teacher = teacherList.singleOrNull { it.fullName == "$firstName $lastName" }
|
|
||||||
return validateTeacher(teacher, firstName, lastName)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacher(firstNameChar: Char, lastName: String): Teacher {
|
|
||||||
val teacher = teacherList.singleOrNull { it.shortName == "$firstNameChar.$lastName" }
|
|
||||||
return validateTeacher(teacher, firstNameChar.toString(), lastName)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacherByLastFirst(nameLastFirst: String): Teacher {
|
|
||||||
val nameParts = nameLastFirst.split(" ")
|
|
||||||
return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[1], nameParts[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacherByFirstLast(nameFirstLast: String): Teacher {
|
|
||||||
val nameParts = nameFirstLast.split(" ")
|
|
||||||
return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[0], nameParts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacherByFDotLast(nameFDotLast: String): Teacher {
|
|
||||||
val nameParts = nameFDotLast.split(".")
|
|
||||||
return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[0][0], nameParts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacherByFDotSpaceLast(nameFDotSpaceLast: String): Teacher {
|
|
||||||
val nameParts = nameFDotSpaceLast.split(".")
|
|
||||||
return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[0][0], nameParts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun validateTeacher(teacher: Teacher?, firstName: String, lastName: String): Teacher {
|
|
||||||
(teacher ?: Teacher(profileId, -1, firstName, lastName).apply {
|
|
||||||
id = shortName.crc16().toLong()
|
|
||||||
teacherList[id] = this
|
|
||||||
}).apply {
|
|
||||||
if (firstName.length > 1)
|
|
||||||
name = firstName
|
|
||||||
surname = lastName
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-25.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikData
|
|
||||||
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.idziennikLoginMethods
|
|
||||||
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.api.prepare
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
|
|
||||||
class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "Idziennik"
|
|
||||||
}
|
|
||||||
|
|
||||||
val internalErrorList = mutableListOf<Int>()
|
|
||||||
val data: DataIdziennik
|
|
||||||
|
|
||||||
init {
|
|
||||||
data = DataIdziennik(app, profile, loginStore).apply {
|
|
||||||
callback = wrapCallback(this@Idziennik.callback)
|
|
||||||
satisfyLoginMethods()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun completed() {
|
|
||||||
data.saveData()
|
|
||||||
data.notify {
|
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
|
||||||
|__ __| | /\ | | (_) | | |
|
|
||||||
| | | |__ ___ / \ | | __ _ ___ _ __ _| |_| |__ _ __ ___
|
|
||||||
| | | '_ \ / _ \ / /\ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \
|
|
||||||
| | | | | | __/ / ____ \| | (_| | (_) | | | | |_| | | | | | | | |
|
|
||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
|
||||||
data.arguments = arguments
|
|
||||||
data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId)
|
|
||||||
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
|
||||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
|
||||||
IdziennikLogin(data) {
|
|
||||||
IdziennikData(data) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getMessage(message: MessageFull) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun firstLogin() {
|
|
||||||
IdziennikFirstLogin(data) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cancel() {
|
|
||||||
d(TAG, "Cancelled")
|
|
||||||
data.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
|
||||||
return object : EdziennikCallback {
|
|
||||||
override fun onCompleted() {
|
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
|
||||||
callback.onProgress(step)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartProgress(stringRes: Int) {
|
|
||||||
callback.onStartProgress(stringRes)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(apiError: ApiError) {
|
|
||||||
when (apiError.errorCode) {
|
|
||||||
in internalErrorList -> {
|
|
||||||
// finish immediately if the same error occurs twice during the same sync
|
|
||||||
callback.onError(apiError)
|
|
||||||
}
|
|
||||||
CODE_INTERNAL_LIBRUS_ACCOUNT_410 -> {
|
|
||||||
internalErrorList.add(apiError.errorCode)
|
|
||||||
loginStore.removeLoginData("refreshToken") // force a clean login
|
|
||||||
//loginLibrus()
|
|
||||||
}
|
|
||||||
else -> callback.onError(apiError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-25.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
|
||||||
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_TIMETABLE = 1030
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_GRADES = 1040
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES = 1050
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_EXAMS = 1060
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_HOMEWORK = 1061
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_NOTICES = 1070
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS = 1080
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_ATTENDANCE = 1090
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_MESSAGES_INBOX = 1110
|
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_MESSAGES_SENT = 1120
|
|
||||||
const val ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER = 2010
|
|
||||||
const val ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX = 2110
|
|
||||||
const val ENDPOINT_IDZIENNIK_API_MESSAGES_SENT = 2120
|
|
||||||
|
|
||||||
val IdziennikFeatures = listOf(
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_TIMETABLE, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_GRADES, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_GRADES to LOGIN_METHOD_IDZIENNIK_WEB,
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_AGENDA, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_EXAMS to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_HOMEWORK, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_HOMEWORK to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_BEHAVIOUR, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_NOTICES to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_ATTENDANCE, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_ANNOUNCEMENTS, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
|
||||||
|
|
||||||
/*Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_INBOX, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_MESSAGES_INBOX to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)).withPriority(2),
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_SENT, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_MESSAGES_SENT to LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)).withPriority(2),*/
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_INBOX, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX to LOGIN_METHOD_IDZIENNIK_API
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_API)),
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_MESSAGES_SENT, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_API_MESSAGES_SENT to LOGIN_METHOD_IDZIENNIK_API
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_API)),
|
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_LUCKY_NUMBER, listOf(
|
|
||||||
ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER to LOGIN_METHOD_IDZIENNIK_API
|
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_API))
|
|
||||||
)
|
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-29.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonElement
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import com.google.gson.JsonParser
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
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.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
|
|
||||||
open class IdziennikApi(open val data: DataIdziennik) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "IdziennikApi"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun apiGet(tag: String, endpointTemplate: String, method: Int = GET, parameters: Map<String, Any> = emptyMap(), onSuccess: (json: JsonElement) -> Unit) {
|
|
||||||
val endpoint = endpointTemplate.replace("\$STUDENT_ID", data.studentId ?: "")
|
|
||||||
Utils.d(tag, "Request: Idziennik/API - $IDZIENNIK_API_URL/$endpoint")
|
|
||||||
|
|
||||||
val callback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
if (text == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val json = try {
|
|
||||||
JsonParser().parse(text)
|
|
||||||
} catch (_: Exception) { null }
|
|
||||||
|
|
||||||
var error: String? = null
|
|
||||||
if (json == null) {
|
|
||||||
error = text
|
|
||||||
}
|
|
||||||
else if (json is JsonObject) {
|
|
||||||
error = if (response?.code() == 200) null else
|
|
||||||
json.getString("message") ?: json.toString()
|
|
||||||
}
|
|
||||||
error?.let { code ->
|
|
||||||
when (code) {
|
|
||||||
"Authorization has been denied for this request." -> ERROR_IDZIENNIK_API_ACCESS_DENIED
|
|
||||||
else -> ERROR_IDZIENNIK_API_OTHER
|
|
||||||
}.let { errorCode ->
|
|
||||||
data.error(ApiError(tag, errorCode)
|
|
||||||
.withApiResponse(text)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(json!!)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_IDZIENNIK_API_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$IDZIENNIK_API_URL/$endpoint")
|
|
||||||
.userAgent(IDZIENNIK_API_USER_AGENT)
|
|
||||||
.addHeader("Authorization", "Bearer ${data.apiBearer}")
|
|
||||||
.apply {
|
|
||||||
when (method) {
|
|
||||||
GET -> get()
|
|
||||||
POST -> {
|
|
||||||
postJson()
|
|
||||||
val json = JsonObject()
|
|
||||||
parameters.map { (name, value) ->
|
|
||||||
when (value) {
|
|
||||||
is JsonObject -> json.add(name, value)
|
|
||||||
is JsonArray -> json.add(name, value)
|
|
||||||
is String -> json.addProperty(name, value)
|
|
||||||
is Int -> json.addProperty(name, value)
|
|
||||||
is Long -> json.addProperty(name, value)
|
|
||||||
is Float -> json.addProperty(name, value)
|
|
||||||
is Char -> json.addProperty(name, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setJsonBody(json)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_INTERNAL_ERROR)
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-25.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiCurrentRegister
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiMessagesInbox
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api.IdziennikApiMessagesSent
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.*
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
|
|
||||||
class IdziennikData(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikData"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
nextEndpoint(onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nextEndpoint(onSuccess: () -> Unit) {
|
|
||||||
if (data.targetEndpointIds.isEmpty()) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (data.cancelled) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
useEndpoint(data.targetEndpointIds.removeAt(0)) {
|
|
||||||
data.progress(data.progressStep)
|
|
||||||
nextEndpoint(onSuccess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
|
|
||||||
Utils.d(TAG, "Using endpoint $endpointId")
|
|
||||||
when (endpointId) {
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_TIMETABLE -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
|
||||||
IdziennikWebTimetable(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_GRADES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
|
||||||
IdziennikWebGrades(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_proposed_grades)
|
|
||||||
IdziennikWebProposedGrades(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_EXAMS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
|
||||||
IdziennikWebExams(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_HOMEWORK -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
|
||||||
IdziennikWebHomework(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_NOTICES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
|
||||||
IdziennikWebNotices(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
|
|
||||||
IdziennikWebAnnouncements(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_WEB_ATTENDANCE -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
|
||||||
IdziennikWebAttendance(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
|
||||||
IdziennikApiCurrentRegister(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
|
||||||
IdziennikApiMessagesInbox(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_IDZIENNIK_API_MESSAGES_SENT -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
|
|
||||||
IdziennikApiMessagesSent(data, onSuccess)
|
|
||||||
}
|
|
||||||
else -> onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-25.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
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.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import java.net.HttpURLConnection.HTTP_INTERNAL_ERROR
|
|
||||||
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
|
|
||||||
|
|
||||||
open class IdziennikWeb(open val data: DataIdziennik) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "IdziennikWeb"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun webApiGet(tag: String, endpoint: String, parameters: Map<String, Any> = emptyMap(), onSuccess: (json: JsonObject) -> Unit) {
|
|
||||||
d(tag, "Request: Idziennik/Web/API - $IDZIENNIK_WEB_URL/$endpoint")
|
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
|
||||||
if (json == null && response?.parserErrorBody == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
response?.code() == HTTP_UNAUTHORIZED -> ERROR_IDZIENNIK_WEB_ACCESS_DENIED
|
|
||||||
response?.code() == HTTP_INTERNAL_ERROR -> ERROR_IDZIENNIK_WEB_SERVER_ERROR
|
|
||||||
response?.parserErrorBody != null -> when {
|
|
||||||
response.parserErrorBody.contains("Identyfikator zgłoszenia") -> ERROR_IDZIENNIK_WEB_SERVER_ERROR
|
|
||||||
response.parserErrorBody.contains("Hasło dostępu do systemu wygasło") -> ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED
|
|
||||||
response.parserErrorBody.contains("Trwają prace konserwacyjne") -> ERROR_IDZIENNIK_WEB_MAINTENANCE
|
|
||||||
else -> ERROR_IDZIENNIK_WEB_OTHER
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}?.let { errorCode ->
|
|
||||||
data.error(ApiError(TAG, errorCode)
|
|
||||||
.withApiResponse(json?.toString() ?: response?.parserErrorBody)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == null) {
|
|
||||||
data.error(ApiError(tag, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(json)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_IDZIENNIK_WEB_API_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(json))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$IDZIENNIK_WEB_URL/$endpoint")
|
|
||||||
.userAgent(IDZIENNIK_USER_AGENT)
|
|
||||||
.postJson()
|
|
||||||
.apply {
|
|
||||||
val json = JsonObject()
|
|
||||||
parameters.map { (name, value) ->
|
|
||||||
when (value) {
|
|
||||||
is JsonObject -> json.add(name, value)
|
|
||||||
is JsonArray -> json.add(name, value)
|
|
||||||
is String -> json.addProperty(name, value)
|
|
||||||
is Int -> json.addProperty(name, value)
|
|
||||||
is Long -> json.addProperty(name, value)
|
|
||||||
is Float -> json.addProperty(name, value)
|
|
||||||
is Char -> json.addProperty(name, value)
|
|
||||||
is Boolean -> json.addProperty(name, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setJsonBody(json)
|
|
||||||
}
|
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
|
||||||
.allowErrorCode(HTTP_INTERNAL_ERROR)
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun webGet(tag: String, endpoint: String, onSuccess: (text: String) -> Unit) {
|
|
||||||
d(tag, "Request: Idziennik/Web - $IDZIENNIK_WEB_URL/$endpoint")
|
|
||||||
|
|
||||||
val callback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
if (text == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text.contains("czyWyswietlicDostepMobilny")) {
|
|
||||||
when {
|
|
||||||
text.contains("Identyfikator zgłoszenia") -> ERROR_IDZIENNIK_WEB_SERVER_ERROR
|
|
||||||
text.contains("Hasło dostępu do systemu wygasło") -> ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED
|
|
||||||
text.contains("Trwają prace konserwacyjne") -> ERROR_IDZIENNIK_WEB_MAINTENANCE
|
|
||||||
else -> ERROR_IDZIENNIK_WEB_OTHER
|
|
||||||
}.let { errorCode ->
|
|
||||||
data.error(ApiError(TAG, errorCode)
|
|
||||||
.withApiResponse(text)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(text)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_IDZIENNIK_WEB_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$IDZIENNIK_WEB_URL/$endpoint")
|
|
||||||
.userAgent(IDZIENNIK_USER_AGENT)
|
|
||||||
.get()
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-29.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.DAY
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_API_CURRENT_REGISTER
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.getInt
|
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikApiCurrentRegister"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
data.profile?.luckyNumber = -1
|
|
||||||
data.profile?.luckyNumberDate = null
|
|
||||||
|
|
||||||
apiGet(TAG, IDZIENNIK_API_CURRENT_REGISTER) { json ->
|
|
||||||
if (json !is JsonObject) {
|
|
||||||
onSuccess()
|
|
||||||
return@apiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
var nextSync = System.currentTimeMillis() + 14*DAY*1000
|
|
||||||
|
|
||||||
val settings = json.getJsonObject("ustawienia")?.apply {
|
|
||||||
profile?.dateSemester1Start = getString("poczatekSemestru1")?.let { Date.fromY_m_d(it) }
|
|
||||||
profile?.dateSemester2Start = getString("koniecSemestru1")?.let { Date.fromY_m_d(it).stepForward(0, 0, 1) }
|
|
||||||
profile?.dateYearEnd = getString("koniecSemestru2")?.let { Date.fromY_m_d(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
json.getInt("szczesliwyNumerek")?.let { luckyNumber ->
|
|
||||||
val luckyNumberDate = Date.getToday()
|
|
||||||
settings.getString("godzinaPublikacjiSzczesliwegoLosu")
|
|
||||||
?.let { Time.fromH_m(it) }
|
|
||||||
?.let { publishTime ->
|
|
||||||
val now = Time.getNow()
|
|
||||||
if (publishTime.value < 150000 && now.value < publishTime.value) {
|
|
||||||
nextSync = luckyNumberDate.combineWith(publishTime)
|
|
||||||
luckyNumberDate.stepForward(0, 0, -1) // the lucky number is still for yesterday
|
|
||||||
}
|
|
||||||
else if (publishTime.value >= 150000 && now.value > publishTime.value) {
|
|
||||||
luckyNumberDate.stepForward(0, 0, 1) // the lucky number is already for tomorrow
|
|
||||||
nextSync = luckyNumberDate.combineWith(publishTime)
|
|
||||||
}
|
|
||||||
else if (publishTime.value < 150000) {
|
|
||||||
nextSync = luckyNumberDate
|
|
||||||
.clone()
|
|
||||||
.stepForward(0, 0, 1)
|
|
||||||
.combineWith(publishTime)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nextSync = luckyNumberDate.combineWith(publishTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val luckyNumberObject = LuckyNumber(
|
|
||||||
data.profileId,
|
|
||||||
Date.getToday(),
|
|
||||||
luckyNumber
|
|
||||||
)
|
|
||||||
|
|
||||||
data.luckyNumberList.add(luckyNumberObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_LUCKY_NUMBER,
|
|
||||||
luckyNumberObject.date.value.toLong(),
|
|
||||||
data.profile?.empty ?: false,
|
|
||||||
data.profile?.empty ?: false,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_API_CURRENT_REGISTER, syncAt = nextSync)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-30.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
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.asJsonObjectList
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_DELETED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikApiMessagesInbox"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, IDZIENNIK_API_MESSAGES_INBOX) { json ->
|
|
||||||
if (json !is JsonArray) {
|
|
||||||
onSuccess()
|
|
||||||
return@apiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
json.asJsonObjectList()?.forEach { jMessage ->
|
|
||||||
val subject = jMessage.getString("tytul")
|
|
||||||
if (subject?.contains("(") == true && subject.startsWith("iDziennik - "))
|
|
||||||
return@forEach
|
|
||||||
if (subject?.startsWith("Uwaga dla ucznia (klasa:") == true)
|
|
||||||
return@forEach
|
|
||||||
|
|
||||||
val messageIdStr = jMessage.getString("id")
|
|
||||||
val messageId = crc32((messageIdStr + "0").toByteArray())
|
|
||||||
|
|
||||||
var body = "[META:$messageIdStr;-1]"
|
|
||||||
body += jMessage.getString("tresc")?.replace("\n".toRegex(), "<br>")
|
|
||||||
|
|
||||||
val readDate = if (jMessage.getBoolean("odczytana") == true) Date.fromIso(jMessage.getString("wersjaRekordu")) else 0
|
|
||||||
val sentDate = Date.fromIso(jMessage.getString("dataWyslania"))
|
|
||||||
|
|
||||||
val sender = jMessage.getAsJsonObject("nadawca")
|
|
||||||
val rTeacher = data.getTeacher(
|
|
||||||
sender.getString("imie") ?: "",
|
|
||||||
sender.getString("nazwisko") ?: ""
|
|
||||||
)
|
|
||||||
rTeacher.loginId = sender.getString("id") + ":" + sender.getString("usr")
|
|
||||||
|
|
||||||
val message = Message(
|
|
||||||
profileId,
|
|
||||||
messageId,
|
|
||||||
subject,
|
|
||||||
body,
|
|
||||||
if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
|
|
||||||
rTeacher.id,
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
|
|
||||||
val messageRecipient = MessageRecipient(
|
|
||||||
profileId,
|
|
||||||
-1 /* me */,
|
|
||||||
-1,
|
|
||||||
readDate,
|
|
||||||
/*messageId*/ messageId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.messageIgnoreList.add(message)
|
|
||||||
data.messageRecipientList.add(messageRecipient)
|
|
||||||
data.messageMetadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_MESSAGE,
|
|
||||||
message.id,
|
|
||||||
readDate > 0,
|
|
||||||
readDate > 0 || profile?.empty ?: false,
|
|
||||||
sentDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-30.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.api
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import pl.szczodrzynski.edziennik.DAY
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_API_MESSAGES_SENT
|
|
||||||
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.asJsonObjectList
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikApiMessagesSent"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, IDZIENNIK_API_MESSAGES_SENT) { json ->
|
|
||||||
if (json !is JsonArray) {
|
|
||||||
onSuccess()
|
|
||||||
return@apiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
json.asJsonObjectList()?.forEach { jMessage ->
|
|
||||||
val messageIdStr = jMessage.get("id").asString
|
|
||||||
val messageId = crc32((messageIdStr + "1").toByteArray())
|
|
||||||
|
|
||||||
val subject = jMessage.get("tytul").asString
|
|
||||||
|
|
||||||
var body = "[META:$messageIdStr;-1]"
|
|
||||||
body += jMessage.get("tresc").asString.replace("\n".toRegex(), "<br>")
|
|
||||||
|
|
||||||
val sentDate = Date.fromIso(jMessage.get("dataWyslania").asString)
|
|
||||||
|
|
||||||
val message = Message(
|
|
||||||
profileId,
|
|
||||||
messageId,
|
|
||||||
subject,
|
|
||||||
body,
|
|
||||||
TYPE_SENT,
|
|
||||||
-1,
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
|
|
||||||
for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) {
|
|
||||||
val recipient = recipientEl.asJsonObject
|
|
||||||
var firstName = recipient.get("imie").asString
|
|
||||||
var lastName = recipient.get("nazwisko").asString
|
|
||||||
if (firstName.isEmpty() || lastName.isEmpty()) {
|
|
||||||
firstName = "usunięty"
|
|
||||||
lastName = "użytkownik"
|
|
||||||
}
|
|
||||||
val rTeacher = data.getTeacher(firstName, lastName)
|
|
||||||
rTeacher.loginId = recipient.get("id").asString + ":" + recipient.get("usr").asString
|
|
||||||
|
|
||||||
val messageRecipient = MessageRecipient(
|
|
||||||
profileId,
|
|
||||||
rTeacher.id,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
/*messageId*/ messageId
|
|
||||||
)
|
|
||||||
data.messageRecipientIgnoreList.add(messageRecipient)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.messageIgnoreList.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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_ANNOUNCEMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class IdziennikWebAnnouncements(override val data: DataIdziennik,
|
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebAnnouncements"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
val param = JsonObject()
|
|
||||||
param.add("parametryFiltrow", JsonArray())
|
|
||||||
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_ANNOUNCEMENTS, mapOf(
|
|
||||||
"uczenId" to (data.studentId ?: ""),
|
|
||||||
"param" to param
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
for (jAnnouncementEl in json.getAsJsonArray("ListK")) {
|
|
||||||
val jAnnouncement = jAnnouncementEl.asJsonObject
|
|
||||||
// jAnnouncement
|
|
||||||
val announcementId = jAnnouncement.get("Id").asLong
|
|
||||||
|
|
||||||
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 announcementObject = Announcement(
|
|
||||||
profileId,
|
|
||||||
announcementId,
|
|
||||||
jAnnouncement.get("Temat").asString,
|
|
||||||
jAnnouncement.get("Tresc").asString,
|
|
||||||
startDate,
|
|
||||||
null,
|
|
||||||
rTeacher.id
|
|
||||||
)
|
|
||||||
data.announcementList.add(announcementObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_ANNOUNCEMENT,
|
|
||||||
announcementObject.id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
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.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebAttendance"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var attendanceYear = Date.getToday().year
|
|
||||||
private var attendanceMonth = Date.getToday().month
|
|
||||||
private var attendancePrevMonthChecked = false
|
|
||||||
|
|
||||||
init {
|
|
||||||
getAttendance()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAttendance() {
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_ATTENDANCE, mapOf(
|
|
||||||
"idPozDziennika" to data.registerId,
|
|
||||||
"mc" to attendanceMonth,
|
|
||||||
"rok" to attendanceYear,
|
|
||||||
"dataTygodnia" to ""
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
for (jAttendanceEl in json.getAsJsonArray("Obecnosci")) {
|
|
||||||
val jAttendance = jAttendanceEl.asJsonObject
|
|
||||||
// jAttendance
|
|
||||||
val attendanceTypeIdziennik = jAttendance.get("TypObecnosci").asInt
|
|
||||||
if (attendanceTypeIdziennik == 5 || attendanceTypeIdziennik == 7)
|
|
||||||
continue
|
|
||||||
val attendanceDate = Date.fromY_m_d(jAttendance.get("Data").asString)
|
|
||||||
val attendanceTime = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
|
|
||||||
if (attendanceDate.combineWith(attendanceTime) > System.currentTimeMillis())
|
|
||||||
continue
|
|
||||||
|
|
||||||
val attendanceId = jAttendance.get("IdLesson").asString.crc16().toLong()
|
|
||||||
val rSubject = data.getSubject(jAttendance.get("Przedmiot").asString, jAttendance.get("IdPrzedmiot").asLong, "")
|
|
||||||
val rTeacher = data.getTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").asString)
|
|
||||||
|
|
||||||
var attendanceName = "obecność"
|
|
||||||
var attendanceType = Attendance.TYPE_CUSTOM
|
|
||||||
|
|
||||||
when (attendanceTypeIdziennik) {
|
|
||||||
1 /* nieobecność usprawiedliwiona */ -> {
|
|
||||||
attendanceName = "nieobecność usprawiedliwiona"
|
|
||||||
attendanceType = TYPE_ABSENT_EXCUSED
|
|
||||||
}
|
|
||||||
2 /* spóźnienie */ -> {
|
|
||||||
attendanceName = "spóźnienie"
|
|
||||||
attendanceType = TYPE_BELATED
|
|
||||||
}
|
|
||||||
3 /* nieobecność nieusprawiedliwiona */ -> {
|
|
||||||
attendanceName = "nieobecność nieusprawiedliwiona"
|
|
||||||
attendanceType = TYPE_ABSENT
|
|
||||||
}
|
|
||||||
4 /* zwolnienie */, 9 /* zwolniony / obecny */ -> {
|
|
||||||
attendanceType = TYPE_RELEASED
|
|
||||||
if (attendanceTypeIdziennik == 4)
|
|
||||||
attendanceName = "zwolnienie"
|
|
||||||
if (attendanceTypeIdziennik == 9)
|
|
||||||
attendanceName = "zwolnienie / obecność"
|
|
||||||
}
|
|
||||||
0 /* obecny */, 8 /* Wycieczka */ -> {
|
|
||||||
attendanceType = TYPE_PRESENT
|
|
||||||
if (attendanceTypeIdziennik == 8)
|
|
||||||
attendanceName = "wycieczka"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val semester = profile?.dateToSemester(attendanceDate) ?: 1
|
|
||||||
|
|
||||||
val attendanceObject = Attendance(
|
|
||||||
profileId,
|
|
||||||
attendanceId,
|
|
||||||
rTeacher.id,
|
|
||||||
rSubject.id,
|
|
||||||
semester,
|
|
||||||
attendanceName,
|
|
||||||
attendanceDate,
|
|
||||||
attendanceTime,
|
|
||||||
attendanceType
|
|
||||||
)
|
|
||||||
|
|
||||||
data.attendanceList.add(attendanceObject)
|
|
||||||
if (attendanceObject.type != TYPE_PRESENT) {
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_ATTENDANCE,
|
|
||||||
attendanceObject.id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val attendanceDateValue = attendanceYear * 10000 + attendanceMonth * 100
|
|
||||||
if (profile?.empty == true && attendanceDateValue > profile?.getSemesterStart(1)?.value ?: 99999999) {
|
|
||||||
attendancePrevMonthChecked = true // do not need to check prev month later
|
|
||||||
attendanceMonth--
|
|
||||||
if (attendanceMonth < 1) {
|
|
||||||
attendanceMonth = 12
|
|
||||||
attendanceYear--
|
|
||||||
}
|
|
||||||
getAttendance()
|
|
||||||
} else if (!attendancePrevMonthChecked /* get also the previous month */) {
|
|
||||||
attendanceMonth--
|
|
||||||
if (attendanceMonth < 1) {
|
|
||||||
attendanceMonth = 12
|
|
||||||
attendanceYear--
|
|
||||||
}
|
|
||||||
attendancePrevMonthChecked = true
|
|
||||||
getAttendance()
|
|
||||||
} else {
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_EXAMS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_EXAMS
|
|
||||||
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.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class IdziennikWebExams(override val data: DataIdziennik,
|
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebExams"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var examsYear = Date.getToday().year
|
|
||||||
private var examsMonth = Date.getToday().month
|
|
||||||
private var examsMonthsChecked = 0
|
|
||||||
private var examsNextMonthChecked = false // TO DO temporary // no more // idk
|
|
||||||
|
|
||||||
init {
|
|
||||||
getExams()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getExams() {
|
|
||||||
val param = JsonObject().apply {
|
|
||||||
addProperty("strona", 1)
|
|
||||||
addProperty("iloscNaStrone", "99")
|
|
||||||
addProperty("iloscRekordow", -1)
|
|
||||||
addProperty("kolumnaSort", "ss.Nazwa,sp.Data_sprawdzianu")
|
|
||||||
addProperty("kierunekSort", 0)
|
|
||||||
addProperty("maxIloscZaznaczonych", 0)
|
|
||||||
addProperty("panelFiltrow", 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_EXAMS, mapOf(
|
|
||||||
"idP" to data.registerId,
|
|
||||||
"rok" to examsYear,
|
|
||||||
"miesiac" to examsMonth,
|
|
||||||
"param" to param
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { exam ->
|
|
||||||
val id = exam.getLong("_recordId") ?: return@forEach
|
|
||||||
val examDate = Date.fromY_m_d(exam.getString("data") ?: return@forEach)
|
|
||||||
val subjectName = exam.getString("przedmiot") ?: return@forEach
|
|
||||||
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 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 eventObject = Event(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
examDate,
|
|
||||||
startTime,
|
|
||||||
topic,
|
|
||||||
-1,
|
|
||||||
eventType,
|
|
||||||
false,
|
|
||||||
teacherId,
|
|
||||||
subjectId,
|
|
||||||
data.teamClass?.id ?: -1
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_EVENT,
|
|
||||||
eventObject.id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profile?.empty == true && examsMonthsChecked < 3 /* how many months backwards to check? */) {
|
|
||||||
examsMonthsChecked++
|
|
||||||
examsMonth--
|
|
||||||
if (examsMonth < 1) {
|
|
||||||
examsMonth = 12
|
|
||||||
examsYear--
|
|
||||||
}
|
|
||||||
getExams()
|
|
||||||
} else if (!examsNextMonthChecked /* get also one month forward */) {
|
|
||||||
val showDate = Date.getToday().stepForward(0, 1, 0)
|
|
||||||
examsYear = showDate.year
|
|
||||||
examsMonth = showDate.month
|
|
||||||
examsNextMonthChecked = true
|
|
||||||
getExams()
|
|
||||||
} else {
|
|
||||||
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class IdziennikWebGrades(override val data: DataIdziennik,
|
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebGrades"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_GRADES, mapOf(
|
|
||||||
"idPozDziennika" to data.registerId
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.onEach { subjectJson ->
|
|
||||||
val subject = data.getSubject(
|
|
||||||
subjectJson.getString("Przedmiot") ?: return@onEach,
|
|
||||||
subjectJson.getLong("IdPrzedmiotu") ?: return@onEach,
|
|
||||||
subjectJson.getString("Przedmiot") ?: return@onEach
|
|
||||||
)
|
|
||||||
subjectJson.getJsonArray("Oceny")?.asJsonObjectList()?.forEach { grade ->
|
|
||||||
val id = grade.getLong("idK") ?: return@forEach
|
|
||||||
val category = grade.getString("Kategoria") ?: ""
|
|
||||||
val name = grade.getString("Ocena") ?: "?"
|
|
||||||
val semester = grade.getInt("Semestr") ?: 1
|
|
||||||
val teacher = data.getTeacherByLastFirst(grade.getString("Wystawil") ?: return@forEach)
|
|
||||||
|
|
||||||
val countToAverage = grade.getBoolean("DoSredniej") ?: true
|
|
||||||
var value = grade.getFloat("WartoscDoSred") ?: 0.0f
|
|
||||||
val weight = if (countToAverage)
|
|
||||||
grade.getFloat("Waga") ?: 0.0f
|
|
||||||
else
|
|
||||||
0.0f
|
|
||||||
|
|
||||||
val gradeColor = grade.getString("Kolor") ?: ""
|
|
||||||
var colorInt = 0xff2196f3.toInt()
|
|
||||||
if (gradeColor.isNotEmpty()) {
|
|
||||||
colorInt = Color.parseColor("#$gradeColor")
|
|
||||||
}
|
|
||||||
|
|
||||||
val gradeObject = Grade(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
category,
|
|
||||||
colorInt,
|
|
||||||
"",
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
weight,
|
|
||||||
semester,
|
|
||||||
teacher.id,
|
|
||||||
subject.id)
|
|
||||||
|
|
||||||
when (grade.getInt("Typ")) {
|
|
||||||
0 -> {
|
|
||||||
val history = grade.getJsonArray("Historia")?.asJsonObjectList()
|
|
||||||
if (history?.isNotEmpty() == true) {
|
|
||||||
var sum = gradeObject.value * gradeObject.weight
|
|
||||||
var count = gradeObject.weight
|
|
||||||
for (historyItem in history) {
|
|
||||||
val countToTheAverage = historyItem.getBoolean("DoSredniej") ?: false
|
|
||||||
value = historyItem.get("WartoscDoSred").asFloat
|
|
||||||
val weight = historyItem.get("Waga").asFloat
|
|
||||||
|
|
||||||
if (value > 0 && countToTheAverage) {
|
|
||||||
sum += value * weight
|
|
||||||
count += weight
|
|
||||||
}
|
|
||||||
|
|
||||||
val historyObject = Grade(
|
|
||||||
profileId,
|
|
||||||
gradeObject.id * -1,
|
|
||||||
historyItem.get("Kategoria").asString,
|
|
||||||
Color.parseColor("#" + historyItem.get("Kolor").asString),
|
|
||||||
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)
|
|
||||||
historyObject.parentId = gradeObject.id
|
|
||||||
|
|
||||||
val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
|
|
||||||
|
|
||||||
data.gradeList.add(historyObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
historyObject.id,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
// update the current grade's value with an average of all historical grades and itself
|
|
||||||
if (sum > 0 && count > 0) {
|
|
||||||
gradeObject.value = sum / count
|
|
||||||
}
|
|
||||||
gradeObject.isImprovement = true // gradeObject is the improved grade. Originals are historyObjects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1 -> {
|
|
||||||
gradeObject.type = Grade.TYPE_SEMESTER1_FINAL
|
|
||||||
gradeObject.name = name
|
|
||||||
gradeObject.weight = 0f
|
|
||||||
}
|
|
||||||
2 -> {
|
|
||||||
gradeObject.type = Grade.TYPE_YEAR_FINAL
|
|
||||||
gradeObject.name = name
|
|
||||||
gradeObject.weight = 0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
|
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
id,
|
|
||||||
data.profile?.empty ?: false,
|
|
||||||
data.profile?.empty ?: false,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_HOMEWORK
|
|
||||||
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.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class IdziennikWebHomework(override val data: DataIdziennik,
|
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebHomework"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
val param = JsonObject().apply {
|
|
||||||
addProperty("strona", 1)
|
|
||||||
addProperty("iloscNaStrone", 997)
|
|
||||||
addProperty("iloscRekordow", -1)
|
|
||||||
addProperty("kolumnaSort", "DataZadania")
|
|
||||||
addProperty("kierunekSort", 0)
|
|
||||||
addProperty("maxIloscZaznaczonych", 0)
|
|
||||||
addProperty("panelFiltrow", 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_HOMEWORK, mapOf(
|
|
||||||
"idP" to data.registerId,
|
|
||||||
"data" to Date.getToday().stringY_m_d,
|
|
||||||
"wszystkie" to true,
|
|
||||||
"param" to param
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 seen = when (profile?.empty) {
|
|
||||||
true -> true
|
|
||||||
else -> eventDate < Date.getToday()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val eventObject = Event(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
eventDate,
|
|
||||||
startTime,
|
|
||||||
topic,
|
|
||||||
-1,
|
|
||||||
Event.TYPE_HOMEWORK,
|
|
||||||
false,
|
|
||||||
teacherId,
|
|
||||||
subjectId,
|
|
||||||
data.teamClass?.id ?: -1
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_HOMEWORK,
|
|
||||||
eventObject.id,
|
|
||||||
seen,
|
|
||||||
seen,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
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.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.*
|
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class IdziennikWebNotices(override val data: DataIdziennik,
|
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebNotices"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_NOTICES, mapOf(
|
|
||||||
"idPozDziennika" to data.registerId
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
for (jNoticeEl in json.getAsJsonArray("SUwaga")) {
|
|
||||||
val jNotice = jNoticeEl.asJsonObject
|
|
||||||
// jNotice
|
|
||||||
val noticeId = jNotice.get("id").asString.crc16().toLong()
|
|
||||||
|
|
||||||
val rTeacher = data.getTeacherByLastFirst(jNotice.get("Nauczyciel").asString)
|
|
||||||
val addedDate = Date.fromY_m_d(jNotice.get("Data").asString)
|
|
||||||
|
|
||||||
var nType = TYPE_NEUTRAL
|
|
||||||
val jType = jNotice.get("Typ").asString
|
|
||||||
if (jType == "n") {
|
|
||||||
nType = TYPE_NEGATIVE
|
|
||||||
} else if (jType == "p") {
|
|
||||||
nType = TYPE_POSITIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
val noticeObject = Notice(
|
|
||||||
profileId,
|
|
||||||
noticeId,
|
|
||||||
jNotice.get("Tresc").asString,
|
|
||||||
jNotice.get("Semestr").asInt,
|
|
||||||
nType,
|
|
||||||
rTeacher.id)
|
|
||||||
data.noticeList.add(noticeObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_NOTICE,
|
|
||||||
noticeObject.id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate.inMillis
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_NOTICES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-28.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_MISSING_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.asJsonObjectList
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebProposedGrades"
|
|
||||||
}
|
|
||||||
|
|
||||||
init { data.profile?.also { profile ->
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_MISSING_GRADES, mapOf(
|
|
||||||
"idPozDziennika" to data.registerId
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
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 semester1Id = subjectObject.id * (-100) - 1
|
|
||||||
|
|
||||||
val semester2Proposed = subject.getString("OcenaSem2") ?: ""
|
|
||||||
val semester2Value = getWordGradeValue(semester2Proposed)
|
|
||||||
val semester2Id = subjectObject.id * (-100) - 2
|
|
||||||
|
|
||||||
if (semester1Proposed != "") {
|
|
||||||
val gradeObject = Grade(
|
|
||||||
profileId,
|
|
||||||
semester1Id,
|
|
||||||
"",
|
|
||||||
-1,
|
|
||||||
"",
|
|
||||||
semester1Value.toString(),
|
|
||||||
semester1Value.toFloat(),
|
|
||||||
0f,
|
|
||||||
1,
|
|
||||||
-1,
|
|
||||||
subjectObject.id
|
|
||||||
).apply {
|
|
||||||
type = TYPE_SEMESTER1_PROPOSED
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
gradeObject.id,
|
|
||||||
profile.empty,
|
|
||||||
profile.empty,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semester2Proposed != "") {
|
|
||||||
val gradeObject = Grade(
|
|
||||||
profileId,
|
|
||||||
semester2Id,
|
|
||||||
"",
|
|
||||||
-1,
|
|
||||||
"",
|
|
||||||
semester2Value.toString(),
|
|
||||||
semester2Value.toFloat(),
|
|
||||||
0f,
|
|
||||||
2,
|
|
||||||
-1,
|
|
||||||
subjectObject.id
|
|
||||||
).apply {
|
|
||||||
type = TYPE_YEAR_PROPOSED
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
gradeObject.id,
|
|
||||||
profile.empty,
|
|
||||||
profile.empty,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
@ -1,192 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-22
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
|
||||||
|
|
||||||
import androidx.core.util.set
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_TIMETABLE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_TIMETABLE
|
|
||||||
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.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
|
||||||
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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikWebTimetable"
|
|
||||||
}
|
|
||||||
|
|
||||||
init { data.profile?.also { profile ->
|
|
||||||
val currentWeekStart = Week.getWeekStart()
|
|
||||||
|
|
||||||
if (Date.getToday().weekDay > 4) {
|
|
||||||
currentWeekStart.stepForward(0, 0, 7)
|
|
||||||
}
|
|
||||||
|
|
||||||
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
|
||||||
|
|
||||||
val weekStart = Date.fromY_m_d(getDate)
|
|
||||||
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
|
||||||
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_TIMETABLE, mapOf(
|
|
||||||
"idPozDziennika" to data.registerId,
|
|
||||||
"pidRokSzkolny" to data.schoolYearId,
|
|
||||||
"data" to "${weekStart.stringY_m_d}T10:00:00.000Z"
|
|
||||||
)) { result ->
|
|
||||||
val json = result.getJsonObject("d") ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
|
||||||
.withApiResponse(result))
|
|
||||||
return@webApiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
json.getJsonArray("GodzinyLekcyjne")?.asJsonObjectList()?.forEach { range ->
|
|
||||||
val lessonRange = LessonRange(
|
|
||||||
profileId,
|
|
||||||
range.getInt("LiczbaP") ?: return@forEach,
|
|
||||||
range.getString("Poczatek")?.let { Time.fromH_m(it) } ?: return@forEach,
|
|
||||||
range.getString("Koniec")?.let { Time.fromH_m(it) } ?: return@forEach
|
|
||||||
)
|
|
||||||
data.lessonRanges[lessonRange.lessonNumber] = lessonRange
|
|
||||||
}
|
|
||||||
|
|
||||||
val dates = mutableSetOf<Int>()
|
|
||||||
val lessons = mutableListOf<Lesson>()
|
|
||||||
|
|
||||||
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { lesson ->
|
|
||||||
val subject = data.getSubject(
|
|
||||||
lesson.getString("Nazwa") ?: return@forEach,
|
|
||||||
lesson.getLong("Id"),
|
|
||||||
lesson.getString("Skrot") ?: ""
|
|
||||||
)
|
|
||||||
val teacher = data.getTeacherByFDotLast(lesson.getString("Nauczyciel")
|
|
||||||
?: return@forEach)
|
|
||||||
|
|
||||||
val newSubjectName = lesson.getString("PrzedmiotZastepujacy")
|
|
||||||
val newSubject = when (newSubjectName.isNullOrBlank()) {
|
|
||||||
true -> null
|
|
||||||
else -> data.getSubject(newSubjectName, null, newSubjectName)
|
|
||||||
}
|
|
||||||
|
|
||||||
val newTeacherName = lesson.getString("NauZastepujacy")
|
|
||||||
val newTeacher = when (newTeacherName.isNullOrBlank()) {
|
|
||||||
true -> null
|
|
||||||
else -> data.getTeacherByFDotLast(newTeacherName)
|
|
||||||
}
|
|
||||||
|
|
||||||
val weekDay = lesson.getInt("DzienTygodnia")?.minus(1) ?: return@forEach
|
|
||||||
val lessonRange = data.lessonRanges[lesson.getInt("Godzina")?.plus(1)
|
|
||||||
?: return@forEach]
|
|
||||||
val lessonDate = weekStart.clone().stepForward(0, 0, weekDay)
|
|
||||||
val classroom = lesson.getString("NazwaSali")
|
|
||||||
|
|
||||||
val type = lesson.getInt("TypZastepstwa") ?: -1
|
|
||||||
|
|
||||||
val lessonObject = Lesson(profileId, -1)
|
|
||||||
|
|
||||||
when (type) {
|
|
||||||
1, 2, 3, 4, 5 -> {
|
|
||||||
lessonObject.apply {
|
|
||||||
this.type = Lesson.TYPE_CHANGE
|
|
||||||
|
|
||||||
this.date = lessonDate
|
|
||||||
this.lessonNumber = lessonRange.lessonNumber
|
|
||||||
this.startTime = lessonRange.startTime
|
|
||||||
this.endTime = lessonRange.endTime
|
|
||||||
this.subjectId = newSubject?.id
|
|
||||||
this.teacherId = newTeacher?.id
|
|
||||||
this.teamId = data.teamClass?.id
|
|
||||||
this.classroom = classroom
|
|
||||||
|
|
||||||
this.oldDate = lessonDate
|
|
||||||
this.oldLessonNumber = lessonRange.lessonNumber
|
|
||||||
this.oldStartTime = lessonRange.startTime
|
|
||||||
this.oldEndTime = lessonRange.endTime
|
|
||||||
this.oldSubjectId = subject.id
|
|
||||||
this.oldTeacherId = teacher.id
|
|
||||||
this.oldTeamId = data.teamClass?.id
|
|
||||||
this.oldClassroom = classroom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0 -> {
|
|
||||||
lessonObject.apply {
|
|
||||||
this.type = Lesson.TYPE_CANCELLED
|
|
||||||
|
|
||||||
this.oldDate = lessonDate
|
|
||||||
this.oldLessonNumber = lessonRange.lessonNumber
|
|
||||||
this.oldStartTime = lessonRange.startTime
|
|
||||||
this.oldEndTime = lessonRange.endTime
|
|
||||||
this.oldSubjectId = subject.id
|
|
||||||
this.oldTeacherId = teacher.id
|
|
||||||
this.oldTeamId = data.teamClass?.id
|
|
||||||
this.oldClassroom = classroom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
lessonObject.apply {
|
|
||||||
this.type = Lesson.TYPE_NORMAL
|
|
||||||
|
|
||||||
this.date = lessonDate
|
|
||||||
this.lessonNumber = lessonRange.lessonNumber
|
|
||||||
this.startTime = lessonRange.startTime
|
|
||||||
this.endTime = lessonRange.endTime
|
|
||||||
this.subjectId = subject.id
|
|
||||||
this.teacherId = teacher.id
|
|
||||||
this.teamId = data.teamClass?.id
|
|
||||||
this.classroom = classroom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lessonObject.id = lessonObject.buildId()
|
|
||||||
|
|
||||||
dates.add(lessonDate.value)
|
|
||||||
lessons.add(lessonObject)
|
|
||||||
|
|
||||||
val seen = profile.empty || lessonDate < Date.getToday()
|
|
||||||
|
|
||||||
if (lessonObject.type != Lesson.TYPE_NORMAL && lessonDate >= Date.getToday()) {
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_LESSON_CHANGE,
|
|
||||||
lessonObject.id,
|
|
||||||
seen,
|
|
||||||
seen,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val date: Date = weekStart.clone()
|
|
||||||
while (date <= weekEnd) {
|
|
||||||
if (!dates.contains(date.value)) {
|
|
||||||
lessons.add(Lesson(profileId, date.value.toLong()).apply {
|
|
||||||
this.type = Lesson.TYPE_NO_LESSONS
|
|
||||||
this.date = date.clone()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
date.stepForward(0, 0, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
|
||||||
|
|
||||||
data.lessonNewList.addAll(lessons)
|
|
||||||
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_SETTINGS
|
|
||||||
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.edziennik.idziennik.login.IdziennikLoginWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.fixName
|
|
||||||
import pl.szczodrzynski.edziennik.get
|
|
||||||
import pl.szczodrzynski.edziennik.swapFirstLastName
|
|
||||||
|
|
||||||
class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikFirstLogin"
|
|
||||||
}
|
|
||||||
|
|
||||||
private val web = IdziennikWeb(data)
|
|
||||||
private val profileList = mutableListOf<Profile>()
|
|
||||||
|
|
||||||
init {
|
|
||||||
IdziennikLoginWeb(data) {
|
|
||||||
web.webGet(TAG, IDZIENNIK_WEB_SETTINGS) { text ->
|
|
||||||
//val accounts = json.getJsonArray("accounts")
|
|
||||||
|
|
||||||
val isParent = Regexes.IDZIENNIK_LOGIN_FIRST_IS_PARENT.find(text)?.get(1) != "0"
|
|
||||||
val accountNameLong = if (isParent)
|
|
||||||
Regexes.IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME.find(text)?.get(1)?.swapFirstLastName()?.fixName()
|
|
||||||
else
|
|
||||||
null
|
|
||||||
|
|
||||||
var schoolYearName: String? = null
|
|
||||||
val schoolYear = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let {
|
|
||||||
schoolYearName = it[2]
|
|
||||||
it[1].toIntOrNull()
|
|
||||||
} ?: run {
|
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR)
|
|
||||||
.withApiResponse(text))
|
|
||||||
return@webGet
|
|
||||||
}
|
|
||||||
|
|
||||||
Regexes.IDZIENNIK_LOGIN_FIRST_STUDENT.findAll(text)
|
|
||||||
.toMutableList()
|
|
||||||
.reversed()
|
|
||||||
.forEach { match ->
|
|
||||||
val registerId = match[1].toIntOrNull() ?: return@forEach
|
|
||||||
val studentId = match[2]
|
|
||||||
val firstName = match[3]
|
|
||||||
val lastName = match[4]
|
|
||||||
val className = match[5] + " " + match[6]
|
|
||||||
|
|
||||||
val profile = Profile()
|
|
||||||
profile.studentNameLong = "$firstName $lastName".fixName()
|
|
||||||
profile.studentNameShort = "$firstName ${lastName[0]}.".fixName()
|
|
||||||
profile.accountNameLong = accountNameLong
|
|
||||||
profile.studentClassName = className
|
|
||||||
profile.studentSchoolYear = schoolYearName
|
|
||||||
profile.name = profile.studentNameLong
|
|
||||||
profile.subname = data.webUsername
|
|
||||||
profile.empty = true
|
|
||||||
profile.putStudentData("studentId", studentId)
|
|
||||||
profile.putStudentData("registerId", registerId)
|
|
||||||
profile.putStudentData("schoolYearId", schoolYear)
|
|
||||||
profileList.add(profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-25.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_API
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_WEB
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
|
|
||||||
class IdziennikLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikLogin"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var cancelled = false
|
|
||||||
|
|
||||||
init {
|
|
||||||
nextLoginMethod(onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nextLoginMethod(onSuccess: () -> Unit) {
|
|
||||||
if (data.targetLoginMethodIds.isEmpty()) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (cancelled) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
useLoginMethod(data.targetLoginMethodIds.removeAt(0)) { usedMethodId ->
|
|
||||||
data.progress(data.progressStep)
|
|
||||||
if (usedMethodId != -1)
|
|
||||||
data.loginMethods.add(usedMethodId)
|
|
||||||
nextLoginMethod(onSuccess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun useLoginMethod(loginMethodId: Int, onSuccess: (usedMethodId: Int) -> Unit) {
|
|
||||||
// this should never be true
|
|
||||||
if (data.loginMethods.contains(loginMethodId)) {
|
|
||||||
onSuccess(-1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Utils.d(TAG, "Using login method $loginMethodId")
|
|
||||||
when (loginMethodId) {
|
|
||||||
LOGIN_METHOD_IDZIENNIK_WEB -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_login_idziennik_web)
|
|
||||||
IdziennikLoginWeb(data) { onSuccess(loginMethodId) }
|
|
||||||
}
|
|
||||||
LOGIN_METHOD_IDZIENNIK_API -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_login_idziennik_api)
|
|
||||||
IdziennikLoginApi(data) { onSuccess(loginMethodId) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
|
||||||
|
|
||||||
class IdziennikLoginApi(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikLoginApi"
|
|
||||||
}
|
|
||||||
|
|
||||||
init { run {
|
|
||||||
if (data.isApiLoginValid()) {
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-26.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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.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.utils.Utils
|
|
||||||
|
|
||||||
class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "IdziennikLoginWeb"
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
))
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data.app.cookieJar.clearForDomain("iuczniowie.progman.pl")
|
|
||||||
if (data.webSchoolName != null && data.webUsername != null && data.webPassword != null) {
|
|
||||||
loginWithCredentials()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
private fun loginWithCredentials() {
|
|
||||||
Utils.d(TAG, "Request: Idziennik/Login/Web - $IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN")
|
|
||||||
|
|
||||||
val loginCallback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
if (text.isNullOrEmpty()) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// login succeeded: there is a start page
|
|
||||||
if (text.contains("czyWyswietlicDostepMobilny")) {
|
|
||||||
val cookies = data.app.cookieJar.getForDomain("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.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. */
|
|
||||||
return@run null
|
|
||||||
}?.let { errorCode ->
|
|
||||||
data.error(ApiError(TAG, errorCode)
|
|
||||||
.withApiResponse(text)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val errorText = Regexes.IDZIENNIK_LOGIN_ERROR.find(text)?.get(1)
|
|
||||||
when {
|
|
||||||
errorText?.contains("nieprawidłową nazwę szkoły") == true -> ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME
|
|
||||||
errorText?.contains("nieprawidłowy login lub hasło") == true -> ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN
|
|
||||||
text.contains("Identyfikator zgłoszenia") -> ERROR_LOGIN_IDZIENNIK_WEB_SERVER_ERROR
|
|
||||||
text.contains("Hasło dostępu do systemu wygasło") -> ERROR_LOGIN_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED
|
|
||||||
text.contains("Trwają prace konserwacyjne") -> ERROR_LOGIN_IDZIENNIK_WEB_MAINTENANCE
|
|
||||||
else -> ERROR_LOGIN_IDZIENNIK_WEB_OTHER
|
|
||||||
}.let { errorCode ->
|
|
||||||
data.error(ApiError(TAG, errorCode)
|
|
||||||
.withApiResponse(text)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val getCallback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
Request.builder()
|
|
||||||
.url("$IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN")
|
|
||||||
.userAgent(IDZIENNIK_USER_AGENT)
|
|
||||||
.addHeader("Origin", "https://iuczniowie.progman.pl")
|
|
||||||
.addHeader("Referer", "$IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN")
|
|
||||||
.apply {
|
|
||||||
Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text ?: return@apply).forEach {
|
|
||||||
addParameter(it[1], it[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.addParameter("ctl00\$ContentPlaceHolder\$nazwaPrzegladarki", IDZIENNIK_USER_AGENT)
|
|
||||||
.addParameter("ctl00\$ContentPlaceHolder\$NazwaSzkoly", data.webSchoolName)
|
|
||||||
.addParameter("ctl00\$ContentPlaceHolder\$UserName", data.webUsername)
|
|
||||||
.addParameter("ctl00\$ContentPlaceHolder\$Password", data.webPassword)
|
|
||||||
.addParameter("ctl00\$ContentPlaceHolder\$captcha", "")
|
|
||||||
.addParameter("ctl00\$ContentPlaceHolder\$Logowanie", "Zaloguj")
|
|
||||||
.post()
|
|
||||||
.allowErrorCode(502)
|
|
||||||
.callback(loginCallback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$IDZIENNIK_WEB_URL/$IDZIENNIK_WEB_LOGIN")
|
|
||||||
.userAgent(IDZIENNIK_USER_AGENT)
|
|
||||||
.get()
|
|
||||||
.allowErrorCode(502)
|
|
||||||
.callback(getCallback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,272 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-21.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus
|
|
||||||
|
|
||||||
import okhttp3.Cookie
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_MESSAGES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_PORTAL
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_SYNERGIA
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
|
||||||
import pl.szczodrzynski.edziennik.currentTimeUnix
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
|
||||||
|
|
||||||
class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
|
||||||
|
|
||||||
fun isPortalLoginValid() = portalTokenExpiryTime-30 > currentTimeUnix() && portalRefreshToken.isNotNullNorEmpty() && portalAccessToken.isNotNullNorEmpty()
|
|
||||||
fun isApiLoginValid() = apiTokenExpiryTime-30 > currentTimeUnix() && apiAccessToken.isNotNullNorEmpty()
|
|
||||||
fun isSynergiaLoginValid() = synergiaSessionIdExpiryTime-30 > currentTimeUnix() && synergiaSessionId.isNotNullNorEmpty()
|
|
||||||
fun isMessagesLoginValid() = messagesSessionIdExpiryTime-30 > currentTimeUnix() && messagesSessionId.isNotNullNorEmpty()
|
|
||||||
|
|
||||||
override fun satisfyLoginMethods() {
|
|
||||||
loginMethods.clear()
|
|
||||||
if (isPortalLoginValid())
|
|
||||||
loginMethods += LOGIN_METHOD_LIBRUS_PORTAL
|
|
||||||
if (isApiLoginValid())
|
|
||||||
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()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
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()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getColor(id: Int?): Int {
|
|
||||||
return when (id) {
|
|
||||||
1 -> 0xFFF0E68C
|
|
||||||
2 -> 0xFF87CEFA
|
|
||||||
3 -> 0xFFB0C4DE
|
|
||||||
4 -> 0xFFF0F8FF
|
|
||||||
5 -> 0xFFF0FFFF
|
|
||||||
6 -> 0xFFF5F5DC
|
|
||||||
7 -> 0xFFFFEBCD
|
|
||||||
8 -> 0xFFFFF8DC
|
|
||||||
9 -> 0xFFA9A9A9
|
|
||||||
10 -> 0xFFBDB76B
|
|
||||||
11 -> 0xFF8FBC8F
|
|
||||||
12 -> 0xFFDCDCDC
|
|
||||||
13 -> 0xFFDAA520
|
|
||||||
14 -> 0xFFE6E6FA
|
|
||||||
15 -> 0xFFFFA07A
|
|
||||||
16 -> 0xFF32CD32
|
|
||||||
17 -> 0xFF66CDAA
|
|
||||||
18 -> 0xFF66CDAA
|
|
||||||
19 -> 0xFFC0C0C0
|
|
||||||
20 -> 0xFFD2B48C
|
|
||||||
21 -> 0xFF3333FF
|
|
||||||
22 -> 0xFF7B68EE
|
|
||||||
23 -> 0xFFBA55D3
|
|
||||||
24 -> 0xFFFFB6C1
|
|
||||||
25 -> 0xFFFF1493
|
|
||||||
26 -> 0xFFDC143C
|
|
||||||
27 -> 0xFFFF0000
|
|
||||||
28 -> 0xFFFF8C00
|
|
||||||
29 -> 0xFFFFD700
|
|
||||||
30 -> 0xFFADFF2F
|
|
||||||
31 -> 0xFF7CFC00
|
|
||||||
else -> 0xff2196f3
|
|
||||||
}.toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _____ _ _
|
|
||||||
| __ \ | | | |
|
|
||||||
| |__) |__ _ __| |_ __ _| |
|
|
||||||
| ___/ _ \| '__| __/ _` | |
|
|
||||||
| | | (_) | | | || (_| | |
|
|
||||||
|_| \___/|_| \__\__,_|*/
|
|
||||||
private var mPortalEmail: String? = null
|
|
||||||
var portalEmail: String?
|
|
||||||
get() { mPortalEmail = mPortalEmail ?: loginStore.getLoginData("email", null); return mPortalEmail }
|
|
||||||
set(value) { loginStore.putLoginData("email", value); mPortalEmail = value }
|
|
||||||
private var mPortalPassword: String? = null
|
|
||||||
var portalPassword: String?
|
|
||||||
get() { mPortalPassword = mPortalPassword ?: loginStore.getLoginData("password", null); return mPortalPassword }
|
|
||||||
set(value) { loginStore.putLoginData("password", value); mPortalPassword = value }
|
|
||||||
|
|
||||||
private var mPortalAccessToken: String? = null
|
|
||||||
var portalAccessToken: String?
|
|
||||||
get() { mPortalAccessToken = mPortalAccessToken ?: loginStore.getLoginData("accessToken", null); return mPortalAccessToken }
|
|
||||||
set(value) { loginStore.putLoginData("accessToken", value); mPortalAccessToken = value }
|
|
||||||
private var mPortalRefreshToken: String? = null
|
|
||||||
var portalRefreshToken: String?
|
|
||||||
get() { mPortalRefreshToken = mPortalRefreshToken ?: loginStore.getLoginData("refreshToken", null); return mPortalRefreshToken }
|
|
||||||
set(value) { loginStore.putLoginData("refreshToken", value); mPortalRefreshToken = value }
|
|
||||||
private var mPortalTokenExpiryTime: Long? = null
|
|
||||||
var portalTokenExpiryTime: Long
|
|
||||||
get() { mPortalTokenExpiryTime = mPortalTokenExpiryTime ?: loginStore.getLoginData("tokenExpiryTime", 0L); return mPortalTokenExpiryTime ?: 0L }
|
|
||||||
set(value) { loginStore.putLoginData("tokenExpiryTime", value); mPortalTokenExpiryTime = value }
|
|
||||||
|
|
||||||
/* _____ _____
|
|
||||||
/\ | __ \_ _|
|
|
||||||
/ \ | |__) || |
|
|
||||||
/ /\ \ | ___/ | |
|
|
||||||
/ ____ \| | _| |_
|
|
||||||
/_/ \_\_| |____*/
|
|
||||||
/**
|
|
||||||
* A Synergia login, like 1234567u.
|
|
||||||
* Used: for login (API Login Method) in Synergia mode.
|
|
||||||
* Used: for login (Synergia Login Method) in Synergia mode.
|
|
||||||
* And also in various places in [pl.szczodrzynski.edziennik.api.v2.models.Feature]s
|
|
||||||
*/
|
|
||||||
private var mApiLogin: String? = null
|
|
||||||
var apiLogin: String?
|
|
||||||
get() { mApiLogin = mApiLogin ?: profile?.getStudentData("accountLogin", null); return mApiLogin }
|
|
||||||
set(value) { profile?.putStudentData("accountLogin", value) ?: return; mApiLogin = value }
|
|
||||||
/**
|
|
||||||
* A Synergia password.
|
|
||||||
* Used: for login (API Login Method) in Synergia mode.
|
|
||||||
* Used: for login (Synergia Login Method) in Synergia mode.
|
|
||||||
*/
|
|
||||||
private var mApiPassword: String? = null
|
|
||||||
var apiPassword: String?
|
|
||||||
get() { mApiPassword = mApiPassword ?: profile?.getStudentData("accountPassword", null); return mApiPassword }
|
|
||||||
set(value) { profile?.putStudentData("accountPassword", value) ?: return; mApiPassword = value }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JST login Code.
|
|
||||||
* Used only during first login in JST mode.
|
|
||||||
*/
|
|
||||||
private var mApiCode: String? = null
|
|
||||||
var apiCode: String?
|
|
||||||
get() { mApiCode = mApiCode ?: loginStore.getLoginData("accountCode", null); return mApiCode }
|
|
||||||
set(value) { loginStore.putLoginData("accountCode", value) ?: return; mApiCode = value }
|
|
||||||
/**
|
|
||||||
* A JST login PIN.
|
|
||||||
* Used only during first login in JST mode.
|
|
||||||
*/
|
|
||||||
private var mApiPin: String? = null
|
|
||||||
var apiPin: String?
|
|
||||||
get() { mApiPin = mApiPin ?: loginStore.getLoginData("accountPin", null); return mApiPin }
|
|
||||||
set(value) { loginStore.putLoginData("accountPin", value) ?: return; mApiPin = value }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Synergia API access token.
|
|
||||||
* Used in all Api Endpoints.
|
|
||||||
* Created in Login Method Api.
|
|
||||||
* Applicable for all login modes.
|
|
||||||
*/
|
|
||||||
private var mApiAccessToken: String? = null
|
|
||||||
var apiAccessToken: String?
|
|
||||||
get() { mApiAccessToken = mApiAccessToken ?: profile?.getStudentData("accountToken", null); return mApiAccessToken }
|
|
||||||
set(value) { mApiAccessToken = value; profile?.putStudentData("accountToken", value) ?: return; }
|
|
||||||
/**
|
|
||||||
* A Synergia API refresh token.
|
|
||||||
* Used when refreshing the [apiAccessToken] in JST, Synergia modes.
|
|
||||||
*/
|
|
||||||
private var mApiRefreshToken: String? = null
|
|
||||||
var apiRefreshToken: String?
|
|
||||||
get() { mApiRefreshToken = mApiRefreshToken ?: profile?.getStudentData("accountRefreshToken", null); return mApiRefreshToken }
|
|
||||||
set(value) { mApiRefreshToken = value; profile?.putStudentData("accountRefreshToken", value) ?: return; }
|
|
||||||
/**
|
|
||||||
* The expiry time for [apiAccessToken], as a UNIX timestamp.
|
|
||||||
* Used when refreshing the [apiAccessToken] in JST, Synergia modes.
|
|
||||||
* Used when refreshing the [apiAccessToken] in Portal mode ([pl.szczodrzynski.edziennik.api.v2.librus.login.SynergiaTokenExtractor])
|
|
||||||
*/
|
|
||||||
private var mApiTokenExpiryTime: Long? = null
|
|
||||||
var apiTokenExpiryTime: Long
|
|
||||||
get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L }
|
|
||||||
set(value) { mApiTokenExpiryTime = value; profile?.putStudentData("accountTokenTime", value) ?: return; }
|
|
||||||
|
|
||||||
/* _____ _
|
|
||||||
/ ____| (_)
|
|
||||||
| (___ _ _ _ __ ___ _ __ __ _ _ __ _
|
|
||||||
\___ \| | | | '_ \ / _ \ '__/ _` | |/ _` |
|
|
||||||
____) | |_| | | | | __/ | | (_| | | (_| |
|
|
||||||
|_____/ \__, |_| |_|\___|_| \__, |_|\__,_|
|
|
||||||
__/ | __/ |
|
|
||||||
|___/ |__*/
|
|
||||||
/**
|
|
||||||
* A Synergia web Session ID (DZIENNIKSID).
|
|
||||||
* Used in endpoints with Synergia login method.
|
|
||||||
*/
|
|
||||||
private var mSynergiaSessionId: String? = null
|
|
||||||
var synergiaSessionId: String?
|
|
||||||
get() { mSynergiaSessionId = mSynergiaSessionId ?: profile?.getStudentData("accountSID", null); return mSynergiaSessionId }
|
|
||||||
set(value) { profile?.putStudentData("accountSID", value) ?: return; mSynergiaSessionId = value }
|
|
||||||
/**
|
|
||||||
* The expiry time for [synergiaSessionId], as a UNIX timestamp.
|
|
||||||
* Used in endpoints with Synergia login method.
|
|
||||||
* TODO verify how long is the session ID valid.
|
|
||||||
*/
|
|
||||||
private var mSynergiaSessionIdExpiryTime: Long? = null
|
|
||||||
var synergiaSessionIdExpiryTime: Long
|
|
||||||
get() { mSynergiaSessionIdExpiryTime = mSynergiaSessionIdExpiryTime ?: profile?.getStudentData("accountSIDTime", 0L); return mSynergiaSessionIdExpiryTime ?: 0L }
|
|
||||||
set(value) { profile?.putStudentData("accountSIDTime", value) ?: return; mSynergiaSessionIdExpiryTime = value }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Messages web Session ID (DZIENNIKSID).
|
|
||||||
* Used in endpoints with Messages login method.
|
|
||||||
*/
|
|
||||||
private var mMessagesSessionId: String? = null
|
|
||||||
var messagesSessionId: String?
|
|
||||||
get() { mMessagesSessionId = mMessagesSessionId ?: profile?.getStudentData("messagesSID", null); return mMessagesSessionId }
|
|
||||||
set(value) { profile?.putStudentData("messagesSID", value) ?: return; mMessagesSessionId = value }
|
|
||||||
/**
|
|
||||||
* The expiry time for [messagesSessionId], as a UNIX timestamp.
|
|
||||||
* Used in endpoints with Messages login method.
|
|
||||||
* TODO verify how long is the session ID valid.
|
|
||||||
*/
|
|
||||||
private var mMessagesSessionIdExpiryTime: Long? = null
|
|
||||||
var messagesSessionIdExpiryTime: Long
|
|
||||||
get() { mMessagesSessionIdExpiryTime = mMessagesSessionIdExpiryTime ?: profile?.getStudentData("messagesSIDTime", 0L); return mMessagesSessionIdExpiryTime ?: 0L }
|
|
||||||
set(value) { profile?.putStudentData("messagesSIDTime", value) ?: return; mMessagesSessionIdExpiryTime = value }
|
|
||||||
|
|
||||||
/* ____ _ _
|
|
||||||
/ __ \| | | |
|
|
||||||
| | | | |_| |__ ___ _ __
|
|
||||||
| | | | __| '_ \ / _ \ '__|
|
|
||||||
| |__| | |_| | | | __/ |
|
|
||||||
\____/ \__|_| |_|\___|*/
|
|
||||||
var isPremium
|
|
||||||
get() = profile?.getStudentData("isPremium", false) ?: false
|
|
||||||
set(value) { profile?.putStudentData("isPremium", value) }
|
|
||||||
|
|
||||||
private var mSchoolName: String? = null
|
|
||||||
var schoolName: String?
|
|
||||||
get() { mSchoolName = mSchoolName ?: profile?.getStudentData("schoolName", null); return mSchoolName }
|
|
||||||
set(value) { profile?.putStudentData("schoolName", value) ?: return; mSchoolName = value }
|
|
||||||
|
|
||||||
private var mUnitId: Long? = null
|
|
||||||
var unitId: Long
|
|
||||||
get() { mUnitId = mUnitId ?: profile?.getStudentData("unitId", 0L); return mUnitId ?: 0L }
|
|
||||||
set(value) { profile?.putStudentData("unitId", value) ?: return; mUnitId = value }
|
|
||||||
|
|
||||||
private var mStartPointsSemester1: Int? = null
|
|
||||||
var startPointsSemester1: Int
|
|
||||||
get() { mStartPointsSemester1 = mStartPointsSemester1 ?: profile?.getStudentData("startPointsSemester1", 0); return mStartPointsSemester1 ?: 0 }
|
|
||||||
set(value) { profile?.putStudentData("startPointsSemester1", value) ?: return; mStartPointsSemester1 = value }
|
|
||||||
private var mStartPointsSemester2: Int? = null
|
|
||||||
var startPointsSemester2: Int
|
|
||||||
get() { mStartPointsSemester2 = mStartPointsSemester2 ?: profile?.getStudentData("startPointsSemester2", 0); return mStartPointsSemester2 ?: 0 }
|
|
||||||
set(value) { profile?.putStudentData("startPointsSemester2", value) ?: return; mStartPointsSemester2 = value }
|
|
||||||
|
|
||||||
private var mEnablePointGrades: Boolean? = null
|
|
||||||
var enablePointGrades: Boolean
|
|
||||||
get() { mEnablePointGrades = mEnablePointGrades ?: profile?.getStudentData("enablePointGrades", true); return mEnablePointGrades ?: true }
|
|
||||||
set(value) { profile?.putStudentData("enablePointGrades", value) ?: return; mEnablePointGrades = value }
|
|
||||||
private var mEnableDescriptiveGrades: Boolean? = null
|
|
||||||
var enableDescriptiveGrades: Boolean
|
|
||||||
get() { mEnableDescriptiveGrades = mEnableDescriptiveGrades ?: profile?.getStudentData("enableDescriptiveGrades", true); return mEnableDescriptiveGrades ?: true }
|
|
||||||
set(value) { profile?.putStudentData("enableDescriptiveGrades", value) ?: return; mEnableDescriptiveGrades = value }
|
|
||||||
}
|
|
@ -1,219 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-21.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusData
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetAttachment
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetMessage
|
|
||||||
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.*
|
|
||||||
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.modules.login.LoginStore
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
|
|
||||||
class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "Librus"
|
|
||||||
}
|
|
||||||
|
|
||||||
val internalErrorList = mutableListOf<Int>()
|
|
||||||
val data: DataLibrus
|
|
||||||
|
|
||||||
init {
|
|
||||||
data = DataLibrus(app, profile, loginStore).apply {
|
|
||||||
callback = wrapCallback(this@Librus.callback)
|
|
||||||
satisfyLoginMethods()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun completed() {
|
|
||||||
data.saveData()
|
|
||||||
data.notify {
|
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
|
||||||
|__ __| | /\ | | (_) | | |
|
|
||||||
| | | |__ ___ / \ | | __ _ ___ _ __ _| |_| |__ _ __ ___
|
|
||||||
| | | '_ \ / _ \ / /\ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \
|
|
||||||
| | | | | | __/ / ____ \| | (_| | (_) | | | | |_| | | | | | | | |
|
|
||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|
||||||
__/ |
|
|
||||||
|__*/
|
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
|
||||||
data.arguments = arguments
|
|
||||||
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun login() {
|
|
||||||
d(TAG, "Trying to login with ${data.targetLoginMethodIds}")
|
|
||||||
if (internalErrorList.isNotEmpty()) {
|
|
||||||
d(TAG, " - Internal errors:")
|
|
||||||
internalErrorList.forEach { d(TAG, " - code $it") }
|
|
||||||
}
|
|
||||||
LibrusLogin(data) {
|
|
||||||
data()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun data() {
|
|
||||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
|
||||||
if (internalErrorList.isNotEmpty()) {
|
|
||||||
d(TAG, " - Internal errors:")
|
|
||||||
internalErrorList.forEach { d(TAG, " - code $it") }
|
|
||||||
}
|
|
||||||
LibrusData(data) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getMessage(message: MessageFull) {
|
|
||||||
LibrusLoginPortal(data) {
|
|
||||||
LibrusLoginApi(data) {
|
|
||||||
LibrusLoginSynergia(data) {
|
|
||||||
LibrusLoginMessages(data) {
|
|
||||||
LibrusMessagesGetMessage(data, message) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {
|
|
||||||
LibrusLoginPortal(data) {
|
|
||||||
LibrusLoginApi(data) {
|
|
||||||
LibrusLoginSynergia(data) {
|
|
||||||
LibrusSynergiaMarkAllAnnouncementsAsRead(data) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
|
||||||
LibrusLoginPortal(data) {
|
|
||||||
LibrusLoginApi(data) {
|
|
||||||
LibrusLoginSynergia(data) {
|
|
||||||
LibrusLoginMessages(data) {
|
|
||||||
LibrusMessagesGetAttachment(data, message, attachmentId, attachmentName) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun firstLogin() {
|
|
||||||
LibrusFirstLogin(data) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cancel() {
|
|
||||||
d(TAG, "Cancelled")
|
|
||||||
data.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
|
||||||
return object : EdziennikCallback {
|
|
||||||
override fun onCompleted() {
|
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
|
||||||
callback.onProgress(step)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartProgress(stringRes: Int) {
|
|
||||||
callback.onStartProgress(stringRes)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(apiError: ApiError) {
|
|
||||||
if (apiError.errorCode in internalErrorList) {
|
|
||||||
// finish immediately if the same error occurs twice during the same sync
|
|
||||||
callback.onError(apiError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
internalErrorList.add(apiError.errorCode)
|
|
||||||
when (apiError.errorCode) {
|
|
||||||
ERROR_LIBRUS_PORTAL_ACCESS_DENIED -> {
|
|
||||||
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_PORTAL)
|
|
||||||
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_PORTAL)
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
data.portalTokenExpiryTime = 0
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LIBRUS_API_ACCESS_DENIED,
|
|
||||||
ERROR_LIBRUS_API_TOKEN_EXPIRED -> {
|
|
||||||
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_API)
|
|
||||||
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_API)
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
data.apiTokenExpiryTime = 0
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED -> {
|
|
||||||
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_SYNERGIA)
|
|
||||||
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_SYNERGIA)
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
data.synergiaSessionIdExpiryTime = 0
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LIBRUS_MESSAGES_ACCESS_DENIED -> {
|
|
||||||
data.loginMethods.remove(LOGIN_METHOD_LIBRUS_MESSAGES)
|
|
||||||
data.targetLoginMethodIds.add(LOGIN_METHOD_LIBRUS_MESSAGES)
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
data.messagesSessionIdExpiryTime = 0
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE,
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING,
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED,
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED -> {
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_NO_REFRESH,
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED,
|
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID -> {
|
|
||||||
data.portalRefreshToken = null
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LOGIN_LIBRUS_SYNERGIA_TOKEN_INVALID,
|
|
||||||
ERROR_LOGIN_LIBRUS_SYNERGIA_NO_TOKEN,
|
|
||||||
ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID -> {
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID -> {
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
// TODO PORTAL CAPTCHA
|
|
||||||
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC -> {
|
|
||||||
loginStore.putLoginData("timetableNotPublic", true)
|
|
||||||
data()
|
|
||||||
}
|
|
||||||
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
|
|
||||||
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
|
|
||||||
data()
|
|
||||||
}
|
|
||||||
else -> callback.onError(apiError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
|
||||||
|
|
||||||
const val ENDPOINT_LIBRUS_API_ME = 1001
|
|
||||||
const val ENDPOINT_LIBRUS_API_SCHOOLS = 1002
|
|
||||||
const val ENDPOINT_LIBRUS_API_CLASSES = 1003
|
|
||||||
const val ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES = 1004
|
|
||||||
const val ENDPOINT_LIBRUS_API_UNITS = 1005
|
|
||||||
const val ENDPOINT_LIBRUS_API_USERS = 1006
|
|
||||||
const val ENDPOINT_LIBRUS_API_SUBJECTS = 1007
|
|
||||||
const val ENDPOINT_LIBRUS_API_CLASSROOMS = 1008
|
|
||||||
const val ENDPOINT_LIBRUS_API_PUSH_CONFIG = 1010
|
|
||||||
const val ENDPOINT_LIBRUS_API_TIMETABLES = 1015
|
|
||||||
const val ENDPOINT_LIBRUS_API_SUBSTITUTIONS = 1016
|
|
||||||
const val ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES = 1021
|
|
||||||
const val ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES = 1022
|
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES = 1023
|
|
||||||
const val ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES = 1024
|
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADE_CATEGORIES = 1025
|
|
||||||
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES = 1026
|
|
||||||
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS = 1027
|
|
||||||
const val ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS = 1030
|
|
||||||
const val ENDPOINT_LIBRUS_API_NORMAL_GRADES = 1031
|
|
||||||
const val ENDPOINT_LIBRUS_API_POINT_GRADES = 1032
|
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES = 1033
|
|
||||||
const val ENDPOINT_LIBRUS_API_TEXT_GRADES = 1034
|
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADES = 1035
|
|
||||||
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES = 1036
|
|
||||||
const val ENDPOINT_LIBRUS_API_EVENT_TYPES = 1040
|
|
||||||
const val ENDPOINT_LIBRUS_API_EVENTS = 1041
|
|
||||||
const val ENDPOINT_LIBRUS_API_HOMEWORK = 1050
|
|
||||||
const val ENDPOINT_LIBRUS_API_LUCKY_NUMBER = 1060
|
|
||||||
const val ENDPOINT_LIBRUS_API_NOTICE_TYPES = 1070
|
|
||||||
const val ENDPOINT_LIBRUS_API_NOTICES = 1071
|
|
||||||
const val ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES = 1080
|
|
||||||
const val ENDPOINT_LIBRUS_API_ATTENDANCES = 1081
|
|
||||||
const val ENDPOINT_LIBRUS_API_ANNOUNCEMENTS = 1090
|
|
||||||
const val ENDPOINT_LIBRUS_API_PT_MEETINGS = 1100
|
|
||||||
const val ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES = 1109
|
|
||||||
const val ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS = 1110
|
|
||||||
const val ENDPOINT_LIBRUS_API_SCHOOL_FREE_DAYS = 1120
|
|
||||||
const val ENDPOINT_LIBRUS_API_CLASS_FREE_DAYS = 1130
|
|
||||||
const val ENDPOINT_LIBRUS_SYNERGIA_INFO = 2010
|
|
||||||
const val ENDPOINT_LIBRUS_SYNERGIA_GRADES = 2020
|
|
||||||
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(
|
|
||||||
|
|
||||||
// push config
|
|
||||||
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)
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timetable - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_TIMETABLE, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_TIMETABLES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_SUBSTITUTIONS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Agenda - using API.
|
|
||||||
* Events, Parent-teacher meetings, free days (teacher/school/class).
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_AGENDA, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_EVENTS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_EVENT_TYPES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_PT_MEETINGS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_SCHOOL_FREE_DAYS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_CLASS_FREE_DAYS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Grades - using API.
|
|
||||||
* All grades + categories.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_GRADES, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_POINT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_POINT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_TEXT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Homework - using API.
|
|
||||||
* Sync only if account has premium access.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_BEHAVIOUR, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_NOTICES to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Attendance - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_ATTENDANCE, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_ATTENDANCES to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Announcements - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_ANNOUNCEMENTS, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_ANNOUNCEMENTS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Student info - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_STUDENT_INFO, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_ME to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* School info - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_SCHOOL_INFO, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_SCHOOLS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_UNITS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Class info - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_CLASS_INFO, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_CLASSES to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Team info - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_TEAM_INFO, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Lucky number - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_LUCKY_NUMBER, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_LUCKY_NUMBER to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data -> data.shouldSyncLuckyNumber() },
|
|
||||||
/**
|
|
||||||
* Teacher list - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_TEACHERS, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_USERS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Subject list - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_SUBJECTS, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_SUBJECTS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
/**
|
|
||||||
* Classroom list - using API.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_CLASSROOMS, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_CLASSROOMS to LOGIN_METHOD_LIBRUS_API
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Student info - using synergia scrapper.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_STUDENT_INFO, listOf(
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_INFO to LOGIN_METHOD_LIBRUS_SYNERGIA
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)),
|
|
||||||
/**
|
|
||||||
* Student number - using synergia scrapper.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_STUDENT_NUMBER, listOf(
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_INFO to LOGIN_METHOD_LIBRUS_SYNERGIA
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)),
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grades - using API + synergia scrapper.
|
|
||||||
*/
|
|
||||||
/*Feature(LOGIN_TYPE_LIBRUS, FEATURE_GRADES, listOf(
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GC to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_GRADES to LOGIN_METHOD_LIBRUS_SYNERGIA
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API, LOGIN_METHOD_LIBRUS_SYNERGIA)),*/
|
|
||||||
/*Endpoint(LOGIN_TYPE_LIBRUS, FEATURE_GRADES, listOf(
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_GRADES to LOGIN_METHOD_LIBRUS_SYNERGIA
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)),*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Homework - using scrapper.
|
|
||||||
* Sync only if account has not premium access.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LOGIN_METHOD_LIBRUS_SYNERGIA
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)).withShouldSync { data ->
|
|
||||||
!(data as DataLibrus).isPremium
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Messages inbox - using messages website.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_MESSAGES_INBOX, listOf(
|
|
||||||
ENDPOINT_LIBRUS_MESSAGES_RECEIVED to LOGIN_METHOD_LIBRUS_MESSAGES
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_MESSAGES)),
|
|
||||||
/**
|
|
||||||
* Messages sent - using messages website.
|
|
||||||
*/
|
|
||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_MESSAGES_SENT, listOf(
|
|
||||||
ENDPOINT_LIBRUS_MESSAGES_SENT to LOGIN_METHOD_LIBRUS_MESSAGES
|
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_MESSAGES))
|
|
||||||
)
|
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-9-21.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import java.net.HttpURLConnection.*
|
|
||||||
|
|
||||||
open class LibrusApi(open val data: DataLibrus) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LibrusApi"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun apiGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject) -> Unit) {
|
|
||||||
|
|
||||||
d(tag, "Request: Librus/Api - ${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
|
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
|
||||||
if (response?.code() == HTTP_UNAVAILABLE) {
|
|
||||||
data.error(ApiError(tag, ERROR_LIBRUS_API_MAINTENANCE)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == null && response?.parserErrorBody == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val error = if (response?.code() == 200) null else
|
|
||||||
json.getString("Code") ?:
|
|
||||||
json.getString("Message") ?:
|
|
||||||
response?.parserErrorBody
|
|
||||||
error?.let { code ->
|
|
||||||
when (code) {
|
|
||||||
"TokenIsExpired" -> ERROR_LIBRUS_API_TOKEN_EXPIRED
|
|
||||||
"Insufficient scopes" -> ERROR_LIBRUS_API_INSUFFICIENT_SCOPES
|
|
||||||
"Request is denied" -> ERROR_LIBRUS_API_ACCESS_DENIED
|
|
||||||
"Resource not found" -> ERROR_LIBRUS_API_RESOURCE_NOT_FOUND
|
|
||||||
"NotFound" -> ERROR_LIBRUS_API_DATA_NOT_FOUND
|
|
||||||
"AccessDeny" -> when (json.getString("Message")) {
|
|
||||||
"Student timetable is not public" -> ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC
|
|
||||||
else -> ERROR_LIBRUS_API_RESOURCE_ACCESS_DENIED
|
|
||||||
}
|
|
||||||
"LuckyNumberIsNotActive" -> ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE
|
|
||||||
"NotesIsNotActive" -> ERROR_LIBRUS_API_NOTES_NOT_ACTIVE
|
|
||||||
"InvalidRequest" -> ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
|
|
||||||
"Nieprawidłowy węzeł." -> ERROR_LIBRUS_API_INCORRECT_ENDPOINT
|
|
||||||
else -> ERROR_LIBRUS_API_OTHER
|
|
||||||
}.let { errorCode ->
|
|
||||||
data.error(ApiError(tag, errorCode)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == null) {
|
|
||||||
data.error(ApiError(tag, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(json)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_API_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(json))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
// TODO add hotfix for Classrooms 500
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
|
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
|
||||||
.addHeader("Authorization", "Bearer ${data.apiAccessToken}")
|
|
||||||
.apply {
|
|
||||||
when (method) {
|
|
||||||
GET -> get()
|
|
||||||
POST -> post()
|
|
||||||
}
|
|
||||||
if (payload != null)
|
|
||||||
setJsonBody(payload)
|
|
||||||
}
|
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
|
||||||
.allowErrorCode(HTTP_UNAVAILABLE)
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-5.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetList
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaHomework
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.LibrusSynergiaInfo
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
|
|
||||||
class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LibrusEndpoints"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
nextEndpoint(onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nextEndpoint(onSuccess: () -> Unit) {
|
|
||||||
if (data.targetEndpointIds.isEmpty()) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (data.cancelled) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
useEndpoint(data.targetEndpointIds.removeAt(0)) {
|
|
||||||
data.progress(data.progressStep)
|
|
||||||
nextEndpoint(onSuccess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
|
|
||||||
Utils.d(TAG, "Using endpoint $endpointId")
|
|
||||||
when (endpointId) {
|
|
||||||
/**
|
|
||||||
* API
|
|
||||||
*/
|
|
||||||
ENDPOINT_LIBRUS_API_ME -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
|
|
||||||
LibrusApiMe(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_SCHOOLS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_school_info)
|
|
||||||
LibrusApiSchools(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_CLASSES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_classes)
|
|
||||||
LibrusApiClasses(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_VIRTUAL_CLASSES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teams)
|
|
||||||
LibrusApiVirtualClasses(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_UNITS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_units)
|
|
||||||
LibrusApiUnits(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_USERS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
|
||||||
LibrusApiUsers(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_SUBJECTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_subjects)
|
|
||||||
LibrusApiSubjects(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_CLASSROOMS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_classrooms)
|
|
||||||
LibrusApiClassrooms(data, onSuccess)
|
|
||||||
}
|
|
||||||
// TODO push config
|
|
||||||
ENDPOINT_LIBRUS_API_TIMETABLES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
|
||||||
LibrusApiTimetables(data, onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
|
||||||
LibrusApiGradeCategories(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
|
||||||
LibrusApiBehaviourGradeCategories(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
|
|
||||||
LibrusApiGradeComments(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
|
|
||||||
LibrusApiBehaviourGradeComments(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
|
||||||
LibrusApiGrades(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_behaviour_grades)
|
|
||||||
LibrusApiBehaviourGrades(data, onSuccess)
|
|
||||||
}
|
|
||||||
// TODO grades
|
|
||||||
|
|
||||||
ENDPOINT_LIBRUS_API_EVENT_TYPES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_event_types)
|
|
||||||
LibrusApiEventTypes(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_EVENTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_events)
|
|
||||||
LibrusApiEvents(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_HOMEWORK -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
|
||||||
LibrusApiHomework(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_LUCKY_NUMBER -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
|
||||||
LibrusApiLuckyNumber(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_NOTICE_TYPES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_notice_types)
|
|
||||||
LibrusApiNoticeTypes(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_NOTICES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
|
||||||
LibrusApiNotices(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance_types)
|
|
||||||
LibrusApiAttendanceTypes(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_ATTENDANCES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
|
||||||
LibrusApiAttendances(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_ANNOUNCEMENTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_announcements)
|
|
||||||
LibrusApiAnnouncements(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_PT_MEETINGS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_pt_meetings)
|
|
||||||
LibrusApiPtMeetings(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAY_TYPES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_day_types)
|
|
||||||
LibrusApiTeacherFreeDayTypes(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_TEACHER_FREE_DAYS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teacher_free_days)
|
|
||||||
LibrusApiTeacherFreeDays(data, onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SYNERGIA
|
|
||||||
*/
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
|
||||||
LibrusSynergiaHomework(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_SYNERGIA_INFO -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
|
|
||||||
LibrusSynergiaInfo(data, onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MESSAGES
|
|
||||||
*/
|
|
||||||
ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
|
||||||
LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, onSuccess = onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_MESSAGES_SENT -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
|
|
||||||
LibrusMessagesGetList(data, type = Message.TYPE_SENT, onSuccess = onSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-24
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
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.jsoup.Jsoup
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import org.jsoup.parser.Parser
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import java.io.File
|
|
||||||
import java.io.StringWriter
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
|
||||||
import javax.xml.transform.OutputKeys
|
|
||||||
import javax.xml.transform.TransformerFactory
|
|
||||||
import javax.xml.transform.dom.DOMSource
|
|
||||||
import javax.xml.transform.stream.StreamResult
|
|
||||||
|
|
||||||
open class LibrusMessages(open val data: DataLibrus) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LibrusMessages"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun messagesGet(tag: String, endpoint: String, method: Int = POST,
|
|
||||||
parameters: Map<String, Any>? = null, onSuccess: (doc: Document) -> Unit) {
|
|
||||||
|
|
||||||
d(tag, "Request: Librus/Messages - $LIBRUS_MESSAGES_URL/$endpoint")
|
|
||||||
|
|
||||||
val callback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
if (text.isNullOrEmpty()) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val doc = Jsoup.parse(text, "", Parser.xmlParser())
|
|
||||||
onSuccess(doc)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.app.cookieJar.saveFromResponse(null, listOf(
|
|
||||||
Cookie.Builder()
|
|
||||||
.name("DZIENNIKSID")
|
|
||||||
.value(data.messagesSessionId!!)
|
|
||||||
.domain("wiadomosci.librus.pl")
|
|
||||||
.secure().httpOnly().build()
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
|
||||||
val doc = docBuilder.newDocument()
|
|
||||||
val serviceElement = doc.createElement("service")
|
|
||||||
val headerElement = doc.createElement("header")
|
|
||||||
val dataElement = doc.createElement("data")
|
|
||||||
for ((key, value) in parameters.orEmpty()) {
|
|
||||||
val element = doc.createElement(key)
|
|
||||||
element.appendChild(doc.createTextNode(value.toString()))
|
|
||||||
dataElement.appendChild(element)
|
|
||||||
}
|
|
||||||
serviceElement.appendChild(headerElement)
|
|
||||||
serviceElement.appendChild(dataElement)
|
|
||||||
doc.appendChild(serviceElement)
|
|
||||||
val transformer = TransformerFactory.newInstance().newTransformer()
|
|
||||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
|
|
||||||
val stringWriter = StringWriter()
|
|
||||||
transformer.transform(DOMSource(doc), StreamResult(stringWriter))
|
|
||||||
val requestXml = stringWriter.toString()
|
|
||||||
|
|
||||||
/*val requestXml = xml("service") {
|
|
||||||
"header" { }
|
|
||||||
"data" {
|
|
||||||
for ((key, value) in parameters.orEmpty()) {
|
|
||||||
key {
|
|
||||||
-value.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.toString(PrintOptions(
|
|
||||||
singleLineTextElements = true,
|
|
||||||
useSelfClosingTags = true
|
|
||||||
))*/
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$LIBRUS_MESSAGES_URL/$endpoint")
|
|
||||||
.userAgent(SYNERGIA_USER_AGENT)
|
|
||||||
.setTextBody(requestXml, MediaTypeUtils.APPLICATION_XML)
|
|
||||||
.apply {
|
|
||||||
when (method) {
|
|
||||||
GET -> get()
|
|
||||||
POST -> post()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sandboxGet(tag: String, action: String, parameters: Map<String, Any>? = null,
|
|
||||||
onSuccess: (json: JsonObject) -> Unit) {
|
|
||||||
|
|
||||||
d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
|
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
|
||||||
if (json == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(json)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(json))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$LIBRUS_SANDBOX_URL$action")
|
|
||||||
.userAgent(SYNERGIA_USER_AGENT)
|
|
||||||
.apply {
|
|
||||||
parameters?.forEach { (k, v) ->
|
|
||||||
addParameter(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.post()
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sandboxGetFile(tag: String, action: String, targetFile: File, onSuccess: (file: File) -> Unit,
|
|
||||||
onProgress: (written: Long, total: Long) -> Unit) {
|
|
||||||
|
|
||||||
d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
|
|
||||||
|
|
||||||
val callback = object : FileCallbackHandler(targetFile) {
|
|
||||||
override fun onSuccess(file: File?, response: Response?) {
|
|
||||||
if (file == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(file)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
|
|
||||||
try {
|
|
||||||
onProgress(bytesWritten, bytesTotal)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST)
|
|
||||||
.withThrowable(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$LIBRUS_SANDBOX_URL$action")
|
|
||||||
.userAgent(SYNERGIA_USER_AGENT)
|
|
||||||
.post()
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
|
|
||||||
open class LibrusPortal(open val data: DataLibrus) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LibrusPortal"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun portalGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject, response: Response?) -> Unit) {
|
|
||||||
|
|
||||||
d(tag, "Request: Librus/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_PORTAL else LIBRUS_PORTAL_URL}$endpoint")
|
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
|
||||||
if (json == null) {
|
|
||||||
data.error(ApiError(tag, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val error = if (response?.code() == 200) null else
|
|
||||||
json.getString("reason") ?:
|
|
||||||
json.getString("message") ?:
|
|
||||||
json.getString("hint") ?:
|
|
||||||
json.getString("Code")
|
|
||||||
error?.let { code ->
|
|
||||||
when (code) {
|
|
||||||
"requires_an_action" -> ERROR_LIBRUS_PORTAL_SYNERGIA_DISCONNECTED
|
|
||||||
"Access token is invalid" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
|
|
||||||
"ApiDisabled" -> ERROR_LIBRUS_PORTAL_API_DISABLED
|
|
||||||
"Account not found" -> ERROR_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND
|
|
||||||
else -> when (json.getString("hint")) {
|
|
||||||
"Error while decoding to JSON" -> ERROR_LIBRUS_PORTAL_ACCESS_DENIED
|
|
||||||
else -> ERROR_LIBRUS_PORTAL_OTHER
|
|
||||||
}
|
|
||||||
}.let { errorCode ->
|
|
||||||
data.error(ApiError(tag, errorCode)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (response?.code() == HttpURLConnection.HTTP_OK) {
|
|
||||||
try {
|
|
||||||
onSuccess(json, response)
|
|
||||||
} catch (e: NullPointerException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(json))
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(json))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url((if (data.fakeLogin) FAKE_LIBRUS_PORTAL else LIBRUS_PORTAL_URL) + endpoint)
|
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
|
||||||
.addHeader("Authorization", "Bearer ${data.portalAccessToken}")
|
|
||||||
.apply {
|
|
||||||
when (method) {
|
|
||||||
GET -> get()
|
|
||||||
POST -> post()
|
|
||||||
}
|
|
||||||
if (payload != null)
|
|
||||||
setJsonBody(payload)
|
|
||||||
}
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_NOT_FOUND)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_GONE)
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-21.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
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) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LibrusSynergia"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun synergiaGet(tag: String, endpoint: String, method: Int = GET,
|
|
||||||
parameters: Map<String, Any> = emptyMap(), onSuccess: (text: String) -> Unit) {
|
|
||||||
d(tag, "Request: Librus/Synergia - $LIBRUS_SYNERGIA_URL/$endpoint")
|
|
||||||
|
|
||||||
val callback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
if (text.isNullOrEmpty()) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text.contains("jesteś zalogowany")) {
|
|
||||||
when {
|
|
||||||
text.contains("stop.png") -> ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED
|
|
||||||
text.contains("Przerwa techniczna") -> ERROR_LIBRUS_SYNERGIA_MAINTENANCE
|
|
||||||
else -> ERROR_LIBRUS_SYNERGIA_OTHER
|
|
||||||
}.let { errorCode ->
|
|
||||||
data.error(ApiError(tag, errorCode)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(text))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(text)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_LIBRUS_SYNERGIA_REQUEST)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(e)
|
|
||||||
.withApiResponse(text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*data.app.cookieJar.saveFromResponse(null, listOf(
|
|
||||||
Cookie.Builder()
|
|
||||||
.name("DZIENNIKSID")
|
|
||||||
.value(data.synergiaSessionId!!)
|
|
||||||
.domain("synergia.librus.pl")
|
|
||||||
.secure().httpOnly().build()
|
|
||||||
))*/
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$LIBRUS_SYNERGIA_URL/$endpoint")
|
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
|
||||||
.apply {
|
|
||||||
when (method) {
|
|
||||||
GET -> get()
|
|
||||||
POST -> post()
|
|
||||||
}
|
|
||||||
parameters.map { (name, value) ->
|
|
||||||
addParameter(name, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-13
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ANNOUNCEMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class LibrusApiAnnouncements(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiAnnouncements"
|
|
||||||
}
|
|
||||||
|
|
||||||
init { data.profile?.also { profile ->
|
|
||||||
apiGet(TAG, "SchoolNotices") { json ->
|
|
||||||
val announcements = json.getJsonArray("SchoolNotices").asJsonObjectList()
|
|
||||||
|
|
||||||
announcements?.forEach { announcement ->
|
|
||||||
val id = announcement.getString("Id")?.crc32() ?: return@forEach
|
|
||||||
val subject = announcement.getString("Subject") ?: ""
|
|
||||||
val text = announcement.getString("Content") ?: ""
|
|
||||||
val startDate = Date.fromY_m_d(announcement.getString("StartDate"))
|
|
||||||
val endDate = Date.fromY_m_d(announcement.getString("EndDate"))
|
|
||||||
val teacherId = announcement.getJsonObject("AddedBy")?.getLong("Id") ?: -1
|
|
||||||
val addedDate = announcement.getString("CreationDate")?.let { Date.fromIso(it) }
|
|
||||||
?: System.currentTimeMillis()
|
|
||||||
val read = announcement.getBoolean("WasRead") ?: false
|
|
||||||
|
|
||||||
val announcementObject = Announcement(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
subject,
|
|
||||||
text,
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
teacherId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.announcementList.add(announcementObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_ANNOUNCEMENT,
|
|
||||||
id,
|
|
||||||
read,
|
|
||||||
profile.empty || read,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ANNOUNCEMENTS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-13
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.AttendanceType
|
|
||||||
|
|
||||||
class LibrusApiAttendanceTypes(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiAttendanceTypes"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Attendances/Types") { json ->
|
|
||||||
val attendanceTypes = json.getJsonArray("Types").asJsonObjectList()
|
|
||||||
|
|
||||||
attendanceTypes?.forEach { attendanceType ->
|
|
||||||
val id = attendanceType.getLong("Id") ?: return@forEach
|
|
||||||
val name = attendanceType.getString("Name") ?: ""
|
|
||||||
val color = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") } ?: -1
|
|
||||||
|
|
||||||
val standardId = when (attendanceType.getBoolean("Standard") ?: false) {
|
|
||||||
true -> id
|
|
||||||
false -> attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id
|
|
||||||
}
|
|
||||||
val type = when (standardId) {
|
|
||||||
1L -> Attendance.TYPE_ABSENT
|
|
||||||
2L -> Attendance.TYPE_BELATED
|
|
||||||
3L -> Attendance.TYPE_ABSENT_EXCUSED
|
|
||||||
4L -> Attendance.TYPE_RELEASED
|
|
||||||
/*100*/else -> Attendance.TYPE_PRESENT
|
|
||||||
}
|
|
||||||
|
|
||||||
data.attendanceTypes.put(id, AttendanceType(profileId, id, name, type, color))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 4*DAY)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-13
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import androidx.core.util.isEmpty
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ATTENDANCES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class LibrusApiAttendances(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiAttendances"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (data.attendanceTypes.isEmpty()) {
|
|
||||||
data.db.attendanceTypeDao().getAllNow(profileId).toSparseArray(data.attendanceTypes) { it.id }
|
|
||||||
}
|
|
||||||
|
|
||||||
apiGet(TAG, "Attendances") { json ->
|
|
||||||
val attendances = json.getJsonArray("Attendances").asJsonObjectList()
|
|
||||||
|
|
||||||
attendances?.forEach { attendance ->
|
|
||||||
val id = Utils.strToInt((attendance.getString("Id") ?: return@forEach)
|
|
||||||
.replace("[^\\d.]".toRegex(), "")).toLong()
|
|
||||||
val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id") ?: -1
|
|
||||||
val lessonNo = attendance.getInt("LessonNo") ?: return@forEach
|
|
||||||
val startTime = data.lessonRanges.get(lessonNo).startTime
|
|
||||||
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
|
|
||||||
val semester = attendance.getInt("Semester") ?: return@forEach
|
|
||||||
val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
|
|
||||||
val typeObject = data.attendanceTypes.get(type)
|
|
||||||
val topic = typeObject?.name ?: ""
|
|
||||||
|
|
||||||
val lessonList = data.db.timetableDao().getForDateNow(profileId, lessonDate)
|
|
||||||
val subjectId = lessonList.firstOrNull { it.startTime == startTime }?.subjectId ?: -1
|
|
||||||
|
|
||||||
val attendanceObject = Attendance(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
teacherId,
|
|
||||||
subjectId,
|
|
||||||
semester,
|
|
||||||
topic,
|
|
||||||
lessonDate,
|
|
||||||
startTime,
|
|
||||||
typeObject.type
|
|
||||||
)
|
|
||||||
|
|
||||||
val addedDate = Date.fromIso(attendance.getString("AddDate") ?: return@forEach)
|
|
||||||
|
|
||||||
data.attendanceList.add(attendanceObject)
|
|
||||||
if(typeObject.type != Attendance.TYPE_PRESENT) {
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_ATTENDANCE,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-3
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
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_CATEGORIES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
|
|
||||||
class LibrusApiBehaviourGradeCategories(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiBehaviourGradeCategories"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "BehaviourGrades/Points/Categories") { json ->
|
|
||||||
json.getJsonArray("Categories")?.asJsonObjectList()?.forEach { category ->
|
|
||||||
val id = category.getLong("Id") ?: return@forEach
|
|
||||||
val name = category.getString("Name") ?: ""
|
|
||||||
val valueFrom = category.getFloat("ValueFrom") ?: 0f
|
|
||||||
val valueTo = category.getFloat("ValueTo") ?: 0f
|
|
||||||
|
|
||||||
val gradeCategoryObject = GradeCategory(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
-1f,
|
|
||||||
Color.BLUE,
|
|
||||||
name
|
|
||||||
).apply {
|
|
||||||
type = GradeCategory.TYPE_BEHAVIOUR
|
|
||||||
setValueRange(valueFrom, valueTo)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeCategories.put(id, gradeCategoryObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_CATEGORIES, 1 * WEEK)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-7
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
|
|
||||||
class LibrusApiBehaviourGradeComments(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiBehaviourGradeComments"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "BehaviourGrades/Points/Comments") { json ->
|
|
||||||
|
|
||||||
json.getJsonArray("Comments")?.asJsonObjectList()?.forEach { comment ->
|
|
||||||
val id = comment.getLong("Id") ?: return@forEach
|
|
||||||
val text = comment.getString("Text")?.fixWhiteSpaces() ?: return@forEach
|
|
||||||
|
|
||||||
val gradeCategoryObject = GradeCategory(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
-1f,
|
|
||||||
-1,
|
|
||||||
text
|
|
||||||
).apply {
|
|
||||||
type = GradeCategory.TYPE_BEHAVIOUR_COMMENT
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeCategories.put(id, gradeCategoryObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADE_COMMENTS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-3
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import java.text.DecimalFormat
|
|
||||||
|
|
||||||
class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiBehaviourGrades"
|
|
||||||
}
|
|
||||||
|
|
||||||
private val nameFormat by lazy { DecimalFormat("#.##") }
|
|
||||||
|
|
||||||
init { data.profile?.let { profile ->
|
|
||||||
apiGet(TAG, "BehaviourGrades/Points") { json ->
|
|
||||||
|
|
||||||
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_BEHAVIOUR }
|
|
||||||
|
|
||||||
data.gradeList.add(semester1StartGradeObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
semester1StartGradeObject.id,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
profile.getSemesterStart(1).inMillis
|
|
||||||
))
|
|
||||||
|
|
||||||
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_BEHAVIOUR }
|
|
||||||
|
|
||||||
data.gradeList.add(semester2StartGradeObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
semester2StartGradeObject.id,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
profile.getSemesterStart(2).inMillis
|
|
||||||
))
|
|
||||||
|
|
||||||
json.getJsonArray("Grades")?.asJsonObjectList()?.forEach { grade ->
|
|
||||||
val id = grade.getLong("Id") ?: return@forEach
|
|
||||||
val value = grade.getFloat("Value")
|
|
||||||
val shortName = grade.getString("ShortName")
|
|
||||||
val semester = grade.getInt("Semester") ?: profile.currentSemester
|
|
||||||
val teacherId = grade.getJsonObject("AddedBy")?.getLong("Id") ?: -1
|
|
||||||
val addedDate = grade.getString("AddDate")?.let { Date.fromIso(it) }
|
|
||||||
?: System.currentTimeMillis()
|
|
||||||
|
|
||||||
val name = when {
|
|
||||||
value != null -> (if (value >= 0) "+" else "") + nameFormat.format(value)
|
|
||||||
shortName != null -> shortName
|
|
||||||
else -> return@forEach
|
|
||||||
}
|
|
||||||
|
|
||||||
val color = data.getColor(when {
|
|
||||||
value == null || value == 0f -> 12
|
|
||||||
value > 0 -> 16
|
|
||||||
value < 0 -> 26
|
|
||||||
else -> 12
|
|
||||||
})
|
|
||||||
|
|
||||||
val categoryId = grade.getJsonObject("Category")?.getLong("Id") ?: -1
|
|
||||||
val category = data.gradeCategories.singleOrNull {
|
|
||||||
it.categoryId == categoryId && it.type == GradeCategory.TYPE_BEHAVIOUR
|
|
||||||
}
|
|
||||||
|
|
||||||
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 valueFrom = value ?: category?.valueFrom ?: 0f
|
|
||||||
val valueTo = category?.valueTo ?: 0f
|
|
||||||
|
|
||||||
val gradeObject = Grade(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
categoryName,
|
|
||||||
color,
|
|
||||||
description,
|
|
||||||
name,
|
|
||||||
valueFrom,
|
|
||||||
-1f,
|
|
||||||
semester,
|
|
||||||
teacherId,
|
|
||||||
1
|
|
||||||
).apply {
|
|
||||||
type = Grade.TYPE_BEHAVIOUR
|
|
||||||
valueMax = valueTo
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
id,
|
|
||||||
profile.empty,
|
|
||||||
profile.empty,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-14
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.DAY
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_CLASSES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.getLong
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class LibrusApiClasses(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiClasses"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Classes") { json ->
|
|
||||||
json.getJsonObject("Class")?.also { studentClass ->
|
|
||||||
val id = studentClass.getLong("Id") ?: return@also
|
|
||||||
val name = studentClass.getString("Number") +
|
|
||||||
studentClass.getString("Symbol")
|
|
||||||
val code = data.schoolName + ":" + name
|
|
||||||
val teacherId = studentClass.getJsonObject("ClassTutor")?.getLong("Id") ?: -1
|
|
||||||
|
|
||||||
val teamObject = Team(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
1,
|
|
||||||
code,
|
|
||||||
teacherId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.teamList.put(id, teamObject)
|
|
||||||
|
|
||||||
data.unitId = studentClass.getJsonObject("Unit").getLong("Id") ?: 0L
|
|
||||||
|
|
||||||
profile?.apply {
|
|
||||||
dateSemester1Start = Date.fromY_m_d(studentClass.getString("BeginSchoolYear")
|
|
||||||
?: return@apply)
|
|
||||||
dateSemester2Start = Date.fromY_m_d(studentClass.getString("EndFirstSemester")
|
|
||||||
?: return@apply)
|
|
||||||
dateYearEnd = Date.fromY_m_d(studentClass.getString("EndSchoolYear")
|
|
||||||
?: return@apply)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_CLASSES, 4 * DAY)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-24.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_CLASSROOMS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.classrooms.Classroom
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class LibrusApiClassrooms(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiClassrooms"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Classrooms") { json ->
|
|
||||||
val classrooms = json.getJsonArray("Classrooms").asJsonObjectList()
|
|
||||||
|
|
||||||
classrooms?.forEach { classroom ->
|
|
||||||
val id = classroom.getLong("Id") ?: return@forEach
|
|
||||||
val name = classroom.getString("Name")?.toLowerCase(Locale.getDefault()) ?: ""
|
|
||||||
val symbol = classroom.getString("Symbol")?.toLowerCase(Locale.getDefault()) ?: ""
|
|
||||||
val nameShort = name.split(" ").onEach { it[0] }.joinToString()
|
|
||||||
|
|
||||||
val friendlyName = if (name != symbol && !name.contains(symbol) && !nameShort.contains(symbol)) {
|
|
||||||
classroom.getString("Symbol") + " " + classroom.getString("Name")
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
classroom.getString("Name") ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
data.classrooms.put(id, Classroom(profileId, id, friendlyName))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_CLASSROOMS, 4*DAY)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-24.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_EVENT_TYPES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventType
|
|
||||||
|
|
||||||
class LibrusApiEventTypes(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiEventTypes"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "HomeWorks/Categories") { json ->
|
|
||||||
val eventTypes = json.getJsonArray("Categories").asJsonObjectList()
|
|
||||||
|
|
||||||
eventTypes?.forEach { eventType ->
|
|
||||||
val id = eventType.getLong("Id") ?: return@forEach
|
|
||||||
val name = eventType.getString("Name") ?: ""
|
|
||||||
val color = data.getColor(eventType.getJsonObject("Color")?.getInt("Id"))
|
|
||||||
|
|
||||||
data.eventTypes.put(id, EventType(profileId, id, name, color))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_EVENT_TYPES, 4*DAY)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-4.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import androidx.core.util.isEmpty
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_EVENTS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class LibrusApiEvents(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiEvents"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (data.eventTypes.isEmpty()) {
|
|
||||||
data.db.eventTypeDao().getAllNow(profileId).toSparseArray(data.eventTypes) { it.id }
|
|
||||||
}
|
|
||||||
|
|
||||||
apiGet(TAG, "HomeWorks") { json ->
|
|
||||||
val events = json.getJsonArray("HomeWorks").asJsonObjectList()
|
|
||||||
|
|
||||||
events?.forEach { event ->
|
|
||||||
val id = event.getLong("Id") ?: return@forEach
|
|
||||||
val eventDate = Date.fromY_m_d(event.getString("Date"))
|
|
||||||
val topic = event.getString("Content") ?: ""
|
|
||||||
val type = event.getJsonObject("Category")?.getInt("Id") ?: -1
|
|
||||||
val teacherId = event.getJsonObject("CreatedBy")?.getLong("Id") ?: -1
|
|
||||||
val subjectId = event.getJsonObject("Subject")?.getLong("Id") ?: -1
|
|
||||||
val teamId = event.getJsonObject("Class")?.getLong("Id") ?: -1
|
|
||||||
|
|
||||||
val lessonNo = event.getInt("LessonNo")
|
|
||||||
val lessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNo }
|
|
||||||
val startTime = lessonRange?.startTime ?: Time.fromH_m(event.getString("TimeFrom"))
|
|
||||||
val addedDate = Date.fromIso(event.getString("AddDate"))
|
|
||||||
|
|
||||||
val eventObject = Event(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
eventDate,
|
|
||||||
startTime,
|
|
||||||
topic,
|
|
||||||
-1,
|
|
||||||
type,
|
|
||||||
false,
|
|
||||||
teacherId,
|
|
||||||
subjectId,
|
|
||||||
teamId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_EVENT,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_EVENTS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-5
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
|
|
||||||
class LibrusApiGradeCategories(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiGradeCategories"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Grades/Categories") { json ->
|
|
||||||
json.getJsonArray("Categories")?.asJsonObjectList()?.forEach { category ->
|
|
||||||
val id = category.getLong("Id") ?: return@forEach
|
|
||||||
val name = category.getString("Name")?.fixWhiteSpaces() ?: ""
|
|
||||||
val weight = when (category.getBoolean("CountToTheAverage")) {
|
|
||||||
true -> category.getFloat("Weight") ?: 0f
|
|
||||||
else -> 0f
|
|
||||||
}
|
|
||||||
val color = category.getJsonObject("Color")?.getInt("Id")
|
|
||||||
?.let { data.getColor(it) } ?: Color.BLUE
|
|
||||||
|
|
||||||
val gradeCategoryObject = GradeCategory(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
weight,
|
|
||||||
color,
|
|
||||||
name
|
|
||||||
)
|
|
||||||
|
|
||||||
data.gradeCategories.put(id, gradeCategoryObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADE_CATEGORIES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-20
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
|
|
||||||
class LibrusApiGradeComments(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiGradeComments"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Grades/Comments") { json ->
|
|
||||||
|
|
||||||
json.getJsonArray("Comments")?.asJsonObjectList()?.forEach { comment ->
|
|
||||||
val id = comment.getLong("Id") ?: return@forEach
|
|
||||||
val text = comment.getString("Text")?.fixWhiteSpaces() ?: return@forEach
|
|
||||||
|
|
||||||
val gradeCategoryObject = GradeCategory(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
-1f,
|
|
||||||
-1,
|
|
||||||
text
|
|
||||||
).apply {
|
|
||||||
type = GradeCategory.TYPE_NORMAL_COMMENT
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeCategories.put(id, gradeCategoryObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class LibrusApiGrades(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiGrades"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Grades") { json ->
|
|
||||||
val grades = json.getJsonArray("Grades").asJsonObjectList()
|
|
||||||
|
|
||||||
grades?.forEach { grade ->
|
|
||||||
val id = grade.getLong("Id") ?: return@forEach
|
|
||||||
val categoryId = grade.getJsonObject("Category")?.getLong("Id") ?: -1
|
|
||||||
val name = grade.getString("Grade") ?: ""
|
|
||||||
val semester = grade.getInt("Semester") ?: return@forEach
|
|
||||||
val teacherId = grade.getJsonObject("AddedBy")?.getLong("Id") ?: -1
|
|
||||||
val subjectId = grade.getJsonObject("Subject")?.getLong("Id") ?: -1
|
|
||||||
val addedDate = Date.fromIso(grade.getString("AddDate"))
|
|
||||||
|
|
||||||
val category = data.gradeCategories.singleOrNull { it.categoryId == categoryId }
|
|
||||||
val categoryName = category?.text ?: ""
|
|
||||||
val color = category?.color ?: -1
|
|
||||||
var weight = category?.weight ?: 0f
|
|
||||||
val value = Utils.getGradeValue(name)
|
|
||||||
|
|
||||||
|
|
||||||
if (name == "-" || name == "+"
|
|
||||||
|| name.equals("np", ignoreCase = true)
|
|
||||||
|| name.equals("bz", ignoreCase = true)) {
|
|
||||||
weight = 0f
|
|
||||||
}
|
|
||||||
|
|
||||||
val description = grade.getJsonArray("Comments")?.asJsonObjectList()?.let { comments ->
|
|
||||||
if (comments.isNotEmpty()) {
|
|
||||||
data.gradeCategories.singleOrNull {
|
|
||||||
it.type == GradeCategory.TYPE_NORMAL_COMMENT
|
|
||||||
&& it.categoryId == comments[0].asJsonObject.getLong("Id")
|
|
||||||
}?.text
|
|
||||||
} else null
|
|
||||||
} ?: ""
|
|
||||||
|
|
||||||
val gradeObject = Grade(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
categoryName,
|
|
||||||
color,
|
|
||||||
description,
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
weight,
|
|
||||||
semester,
|
|
||||||
teacherId,
|
|
||||||
subjectId
|
|
||||||
)
|
|
||||||
|
|
||||||
when {
|
|
||||||
grade.getBoolean("IsConstituent") ?: false ->
|
|
||||||
gradeObject.type = Grade.TYPE_NORMAL
|
|
||||||
grade.getBoolean("IsSemester") ?: false -> // semester final
|
|
||||||
gradeObject.type = if (gradeObject.semester == 1) Grade.TYPE_SEMESTER1_FINAL else Grade.TYPE_SEMESTER2_FINAL
|
|
||||||
grade.getBoolean("IsSemesterProposition") ?: false -> // semester proposed
|
|
||||||
gradeObject.type = if (gradeObject.semester == 1) Grade.TYPE_SEMESTER1_PROPOSED else Grade.TYPE_SEMESTER2_PROPOSED
|
|
||||||
grade.getBoolean("IsFinal") ?: false -> // year final
|
|
||||||
gradeObject.type = Grade.TYPE_YEAR_FINAL
|
|
||||||
grade.getBoolean("IsFinalProposition") ?: false -> // year final
|
|
||||||
gradeObject.type = Grade.TYPE_YEAR_PROPOSED
|
|
||||||
}
|
|
||||||
|
|
||||||
grade.getJsonObject("Improvement")?.also {
|
|
||||||
val historicalId = it.getLong("Id")
|
|
||||||
data.gradeList.firstOrNull { grade -> grade.id == historicalId }?.also { grade ->
|
|
||||||
grade.parentId = gradeObject.id
|
|
||||||
if (grade.name == "nb") grade.weight = 0f
|
|
||||||
}
|
|
||||||
gradeObject.isImprovement = true
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class LibrusApiHomework(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiHomework"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "HomeWorkAssignments") { json ->
|
|
||||||
val homeworkList = json.getJsonArray("HomeWorkAssignments").asJsonObjectList()
|
|
||||||
|
|
||||||
homeworkList?.forEach { homework ->
|
|
||||||
val id = homework.getLong("Id") ?: return@forEach
|
|
||||||
val eventDate = Date.fromY_m_d(homework.getString("DueDate"))
|
|
||||||
val topic = homework.getString("Topic") + "\n" + homework.getString("Text")
|
|
||||||
val teacherId = homework.getJsonObject("Teacher")?.getLong("Id") ?: -1
|
|
||||||
val addedDate = Date.fromY_m_d(homework.getString("Date"))
|
|
||||||
|
|
||||||
val eventObject = Event(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
eventDate,
|
|
||||||
null,
|
|
||||||
topic,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
false,
|
|
||||||
teacherId,
|
|
||||||
-1,
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_HOMEWORK,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate.inMillis
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_HOMEWORK, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-10-14
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.DAY
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LUCKY_NUMBER
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.getInt
|
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class LibrusApiLuckyNumber(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiLuckyNumber"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
data.profile?.luckyNumber = -1
|
|
||||||
data.profile?.luckyNumberDate = null
|
|
||||||
|
|
||||||
var nextSync = System.currentTimeMillis() + 2*DAY*1000
|
|
||||||
|
|
||||||
apiGet(TAG, "LuckyNumbers") { json ->
|
|
||||||
if (json.isJsonNull) {
|
|
||||||
//profile?.luckyNumberEnabled = false
|
|
||||||
} else {
|
|
||||||
json.getJsonObject("LuckyNumber")?.also { luckyNumberEl ->
|
|
||||||
|
|
||||||
val luckyNumberDate = Date.fromY_m_d(luckyNumberEl.getString("LuckyNumberDay")) ?: Date.getToday()
|
|
||||||
val luckyNumber = luckyNumberEl.getInt("LuckyNumber") ?: -1
|
|
||||||
val luckyNumberObject = LuckyNumber(
|
|
||||||
profileId,
|
|
||||||
luckyNumberDate,
|
|
||||||
luckyNumber
|
|
||||||
)
|
|
||||||
|
|
||||||
//if (luckyNumberDate > Date.getToday()) {
|
|
||||||
nextSync = luckyNumberDate.combineWith(Time(15, 0, 0))
|
|
||||||
//}
|
|
||||||
|
|
||||||
data.luckyNumberList.add(luckyNumberObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_LUCKY_NUMBER,
|
|
||||||
luckyNumberObject.date.value.toLong(),
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_LUCKY_NUMBER, syncAt = nextSync)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ME
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
|
|
||||||
class LibrusApiMe(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiMe"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Me") { json ->
|
|
||||||
val me = json.getJsonObject("Me")
|
|
||||||
val account = me?.getJsonObject("Account")
|
|
||||||
val user = me?.getJsonObject("User")
|
|
||||||
|
|
||||||
data.isPremium = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
|
|
||||||
|
|
||||||
val isParent = account?.getInt("GroupId") == 5
|
|
||||||
data.profile?.accountNameLong =
|
|
||||||
if (isParent)
|
|
||||||
buildFullName(account?.getString("FirstName"), account?.getString("LastName"))
|
|
||||||
else null
|
|
||||||
|
|
||||||
data.profile?.studentNameLong =
|
|
||||||
buildFullName(user?.getString("FirstName"), user?.getString("LastName"))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_ME, 2*DAY)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-24.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NOTICE_TYPES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notices.NoticeType
|
|
||||||
|
|
||||||
class LibrusApiNoticeTypes(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiNoticeTypes"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Notes/Categories") { json ->
|
|
||||||
val noticeTypes = json.getJsonArray("Categories").asJsonObjectList()
|
|
||||||
|
|
||||||
noticeTypes?.forEach { noticeType ->
|
|
||||||
val id = noticeType.getLong("Id") ?: return@forEach
|
|
||||||
val name = noticeType.getString("CategoryName") ?: ""
|
|
||||||
|
|
||||||
data.noticeTypes.put(id, NoticeType(profileId, id, name))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NOTICE_TYPES, 4*DAY)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-24.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import androidx.core.util.isEmpty
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NOTICES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class LibrusApiNotices(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiNotices"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (data.noticeTypes.isEmpty()) {
|
|
||||||
data.db.noticeTypeDao().getAllNow(profileId).toSparseArray(data.noticeTypes) { it.id }
|
|
||||||
}
|
|
||||||
|
|
||||||
apiGet(TAG, "Notes") { json ->
|
|
||||||
val notes = json.getJsonArray("Notes").asJsonObjectList()
|
|
||||||
|
|
||||||
notes?.forEach { note ->
|
|
||||||
val id = note.getLong("Id") ?: return@forEach
|
|
||||||
val text = note.getString("Text") ?: ""
|
|
||||||
val categoryId = note.getJsonObject("Category")?.getLong("Id") ?: -1
|
|
||||||
val teacherId = note.getJsonObject("AddedBy")?.getLong("Id") ?: -1
|
|
||||||
val addedDate = note.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach
|
|
||||||
|
|
||||||
val type = when (note.getInt("Positive")) {
|
|
||||||
0 -> Notice.TYPE_NEGATIVE
|
|
||||||
1 -> Notice.TYPE_POSITIVE
|
|
||||||
/*2*/else -> Notice.TYPE_NEUTRAL
|
|
||||||
}
|
|
||||||
val categoryText = data.noticeTypes[categoryId]?.name ?: ""
|
|
||||||
val semester = profile?.dateToSemester(addedDate) ?: 1
|
|
||||||
|
|
||||||
val noticeObject = Notice(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
categoryText+"\n"+text,
|
|
||||||
semester,
|
|
||||||
type,
|
|
||||||
teacherId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.noticeList.add(noticeObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_NOTICE,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
addedDate.inMillis
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NOTICES, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-24.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_PT_MEETINGS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class LibrusApiPtMeetings(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiPtMeetings"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "ParentTeacherConferences") { json ->
|
|
||||||
val ptMeetings = json.getJsonArray("ParentTeacherConferences").asJsonObjectList()
|
|
||||||
|
|
||||||
ptMeetings?.forEach { meeting ->
|
|
||||||
val id = meeting.getLong("Id") ?: return@forEach
|
|
||||||
val topic = meeting.getString("Topic") ?: ""
|
|
||||||
val teacherId = meeting.getJsonObject("Teacher")?.getLong("Id") ?: -1
|
|
||||||
val eventDate = meeting.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach
|
|
||||||
val startTime = meeting.getString("Time")?.let {
|
|
||||||
if (it == "00:00:00")
|
|
||||||
null
|
|
||||||
else
|
|
||||||
Time.fromH_m_s(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val eventObject = Event(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
eventDate,
|
|
||||||
startTime,
|
|
||||||
topic,
|
|
||||||
-1,
|
|
||||||
Event.TYPE_PT_MEETING,
|
|
||||||
false,
|
|
||||||
teacherId,
|
|
||||||
-1,
|
|
||||||
data.teamClass?.id ?: -1
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_EVENT,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
profile?.empty ?: false,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_PT_MEETINGS, 12*HOUR)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user