mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-16 07:21:54 +02:00
Compare commits
64 Commits
v4.0-beta.
...
v4.0-beta.
Author | SHA1 | Date | |
---|---|---|---|
4763033f24 | |||
3b0570d21c | |||
16bf478d1a | |||
5bf181b6d1 | |||
21b2e5d194 | |||
759afcf3ca | |||
d48c7844a4 | |||
7d8caa8df7 | |||
62f53930da | |||
9a45cbb679 | |||
8e5a10f6d8 | |||
10c57d2272 | |||
67d4d0f898 | |||
97e0d04842 | |||
3ba30ede92 | |||
1035e411ab | |||
d5ae4b7ec9 | |||
111d040cf9 | |||
8cc594d170 | |||
d8a8bed68d | |||
eedbd954bd | |||
0eb8366027 | |||
894135104b | |||
7b2e408efc | |||
e4115c122e | |||
537b16949e | |||
ca60ceb2a7 | |||
0fad12fea5 | |||
6cd2c23aac | |||
512baaa43f | |||
d097fcc973 | |||
621dbd459c | |||
840ab4b0c4 | |||
904be34a87 | |||
b7fc6fcc38 | |||
55c6e40d6d | |||
4dfb015057 | |||
e40a0ba2bb | |||
fd48f10df9 | |||
6a54e7fef7 | |||
5c4d6ed140 | |||
9ed1be3594 | |||
c5ce582678 | |||
2050083bce | |||
92e6bdb562 | |||
93e70c38b7 | |||
45b96179a5 | |||
a29a534a40 | |||
8e2297359c | |||
92ba7248ef | |||
f657d37cbd | |||
9e312f60bf | |||
85f72b78f7 | |||
40acb67ceb | |||
3ae8100bda | |||
1a3dc41edf | |||
b111d33b04 | |||
ea5720d1c8 | |||
53675122c6 | |||
4ba7997bc1 | |||
19c446d267 | |||
1abb9ac378 | |||
f9c7492726 | |||
6ece6ca52a |
@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
|
|||||||
//apply plugin: 'me.tatarka.retrolambda'
|
//apply plugin: 'me.tatarka.retrolambda'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion setup.compileSdk
|
||||||
|
|
||||||
android {
|
android {
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@ -12,7 +12,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion setup.targetSdk
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
}
|
}
|
||||||
@ -43,9 +43,9 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
// Google libraries
|
// Google libraries
|
||||||
implementation "androidx.appcompat:appcompat:${androidXAppCompat}"
|
implementation "androidx.appcompat:appcompat:${versions.appcompat}"
|
||||||
implementation "androidx.recyclerview:recyclerview:${androidXRecyclerView}"
|
implementation "androidx.recyclerview:recyclerview:${versions.recyclerView}"
|
||||||
implementation "com.google.android.material:material:${googleMaterial}"
|
implementation "com.google.android.material:material:${versions.material}"
|
||||||
|
|
||||||
// other libraries
|
// other libraries
|
||||||
//implementation 'se.emilsjolander:stickylistheaders:2.7.0'
|
//implementation 'se.emilsjolander:stickylistheaders:2.7.0'
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-kapt'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
apply plugin: 'io.fabric'
|
apply plugin: 'io.fabric'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
}
|
}
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion setup.compileSdk
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId 'pl.szczodrzynski.edziennik'
|
applicationId 'pl.szczodrzynski.edziennik'
|
||||||
minSdkVersion setup.minSdk
|
minSdkVersion setup.minSdk
|
||||||
@ -103,7 +104,7 @@ tasks.whenTaskAdded { task ->
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
|
||||||
annotationProcessor "androidx.room:room-compiler:${versions.room}"
|
kapt "androidx.room:room-compiler:${versions.room}"
|
||||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.5"
|
debugImplementation "com.amitshekhar.android:debug-db:1.0.5"
|
||||||
|
|
||||||
implementation "android.arch.navigation:navigation-fragment-ktx:${versions.navigationFragment}"
|
implementation "android.arch.navigation:navigation-fragment-ktx:${versions.navigationFragment}"
|
||||||
@ -187,6 +188,8 @@ dependencies {
|
|||||||
implementation "com.squareup.retrofit2:converter-gson:${versions.retrofit}"
|
implementation "com.squareup.retrofit2:converter-gson:${versions.retrofit}"
|
||||||
|
|
||||||
implementation 'com.github.jetradarmobile:android-snowfall:1.2.0'
|
implementation 'com.github.jetradarmobile:android-snowfall:1.2.0'
|
||||||
|
|
||||||
|
implementation "io.coil-kt:coil:0.9.2"
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
-keepclassmembers class pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig { public *; }
|
-keepclassmembers class pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig { public *; }
|
||||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider
|
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider
|
||||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider
|
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider
|
||||||
-keepnames class pl.szczodrzynski.edziennik.widgets.luckynumber.WidgetLuckyNumber
|
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider
|
||||||
|
|
||||||
-keep class .R
|
-keep class .R
|
||||||
-keep class **.R$* {
|
-keep class **.R$* {
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
<service android:name=".ui.widgets.timetable.WidgetTimetableService"
|
<service android:name=".ui.widgets.timetable.WidgetTimetableService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
<activity android:name=".ui.widgets.LessonDialogActivity"
|
<activity android:name=".ui.widgets.LessonDialogActivity"
|
||||||
|
android:label=""
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
@ -98,7 +99,7 @@
|
|||||||
<service android:name=".ui.widgets.notifications.WidgetNotificationsService"
|
<service android:name=".ui.widgets.notifications.WidgetNotificationsService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
<!-- LUCKY NUMBER -->
|
<!-- LUCKY NUMBER -->
|
||||||
<receiver android:name=".widgets.luckynumber.WidgetLuckyNumber"
|
<receiver android:name=".ui.widgets.luckynumber.WidgetLuckyNumberProvider"
|
||||||
android:label="@string/widget_lucky_number_title">
|
android:label="@string/widget_lucky_number_title">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
@ -141,12 +142,8 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".ui.modules.settings.SettingsLicenseActivity"
|
<activity android:name=".ui.modules.settings.SettingsLicenseActivity"
|
||||||
|
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".ui.modules.webpush.WebPushConfigActivity"
|
|
||||||
android:configChanges="orientation|keyboardHidden"
|
|
||||||
android:theme="@style/AppTheme.Dark" />
|
|
||||||
<activity android:name=".ui.modules.webpush.QrScannerActivity" />
|
<activity android:name=".ui.modules.webpush.QrScannerActivity" />
|
||||||
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
@ -165,18 +162,9 @@
|
|||||||
<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=".sync.UpdateDownloaderService$DownloadProgressReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
|
||||||
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
|
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
|
||||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
|
||||||
</intent-filter>
|
|
||||||
</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>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".receivers.SzkolnyReceiver"
|
<receiver android:name=".receivers.SzkolnyReceiver"
|
||||||
@ -193,16 +181,22 @@
|
|||||||
____) | __/ | \ V /| | (_| __/\__ \
|
____) | __/ | \ V /| | (_| __/\__ \
|
||||||
|_____/ \___|_| \_/ |_|\___\___||___/
|
|_____/ \___|_| \_/ |_|\___\___||___/
|
||||||
-->
|
-->
|
||||||
<service android:name=".sync.MyFirebaseMessagingService"
|
<!--<service android:name=".sync.MyFirebaseMessagingService"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
|
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>-->
|
||||||
<service android:name=".receivers.BootReceiver$NotificationActionService" />
|
|
||||||
<service android:name=".Notifier$GetDataRetryService" />
|
|
||||||
<service android:name=".data.api.ApiService" />
|
<service android:name=".data.api.ApiService" />
|
||||||
|
<service android:name=".data.firebase.MyFirebaseService"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter android:priority="10000000">
|
||||||
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
|
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<service android:name=".sync.UpdateDownloaderService" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
_____ _ _
|
_____ _ _
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<h3>Wersja 4.0-beta.2, 2020-01-06</h3>
|
<h3>Wersja 4.0-beta.6, 2020-01-28</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkosć oraz poprawność pobieranych danych.</li>
|
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkosć oraz poprawność pobieranych danych.</li>
|
||||||
<li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli 👏</li>
|
<li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli 👏</li>
|
||||||
@ -6,6 +6,7 @@
|
|||||||
<li>Nowa <b>Strona główna</b> - ładniejszy wygląd oraz możliwość przestawiania kart na każdym profilu</li>
|
<li>Nowa <b>Strona główna</b> - ładniejszy wygląd oraz możliwość przestawiania kart na każdym profilu</li>
|
||||||
<li>Nowy <b>Plan lekcji</b> - z doskonałą obsługą lekcji przesuniętych oraz dwóch lekcji o tej samej godzinie</li>
|
<li>Nowy <b>Plan lekcji</b> - z doskonałą obsługą lekcji przesuniętych oraz dwóch lekcji o tej samej godzinie</li>
|
||||||
<li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li>
|
<li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li>
|
||||||
|
<li>Nowe, przyjemniejsze powiadomienia</li>
|
||||||
<li>Łatwiejsze dodawanie własnych wydarzeń</li>
|
<li>Łatwiejsze dodawanie własnych wydarzeń</li>
|
||||||
<li>Dużo poprawek w widoku <b>Wiadomości</b> oraz <b>Ogłoszeń</b></li>
|
<li>Dużo poprawek w widoku <b>Wiadomości</b> oraz <b>Ogłoszeń</b></li>
|
||||||
<li>Częściowa <b>Obsługa dziennika EduDziennik</b></li>
|
<li>Częściowa <b>Obsługa dziennika EduDziennik</b></li>
|
||||||
@ -14,7 +15,9 @@
|
|||||||
<li>Librus: obsługa Zadań domowych bez posiadania Mobilnych dodatków (przez system Synergia)</li>
|
<li>Librus: obsługa Zadań domowych bez posiadania Mobilnych dodatków (przez system Synergia)</li>
|
||||||
<li>Lepsze <b>przekazywanie powiadomień na komputer</b> oraz łatwiejsze parowanie</li>
|
<li>Lepsze <b>przekazywanie powiadomień na komputer</b> oraz łatwiejsze parowanie</li>
|
||||||
<li>Poprawiliśmy synchronizację w tle na niektórych telefonach</li>
|
<li>Poprawiliśmy synchronizację w tle na niektórych telefonach</li>
|
||||||
|
<li>Usunąłem denerwujący brak zaznaczenia w lewym menu</li>
|
||||||
<li>Znaczna ilość błędów z poprzednich wersji już nie występuje</li>
|
<li>Znaczna ilość błędów z poprzednich wersji już nie występuje</li>
|
||||||
|
<li><strike>Występują natomiast nowe błędy, dlatego proszę o ich zgłaszanie :)</strike></li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@ -23,8 +26,8 @@
|
|||||||
Staramy się usuwać takie przypadki, jednak na chwilę obecną mogą występować błędy w:
|
Staramy się usuwać takie przypadki, jednak na chwilę obecną mogą występować błędy w:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Wysyłanie wiadomości może czasami nie działać - proszę o zgłaszanie wszystkich błędów na naszym serwerze Discord</li>
|
<li>Wysyłanie wiadomości może czasami nie działać - proszę o zgłaszanie wszystkich błędów na naszym serwerze Discord</li>
|
||||||
<li>Widget szczęśliwego numerka</li>
|
|
||||||
<li>Terminarz - brak informacji o odwołanych lekcjach w dialogu</li>
|
<li>Terminarz - brak informacji o odwołanych lekcjach w dialogu</li>
|
||||||
|
<li>Cisza nocna w powiadomieniach jeszcze nie działa.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
/*secret password - removed for source code publication*/
|
/*secret password - removed for source code publication*/
|
||||||
static toys AES_IV[16] = {
|
static toys AES_IV[16] = {
|
||||||
0xf5, 0xbe, 0x91, 0x89, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
0x4a, 0x83, 0xba, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
||||||
|
|
||||||
|
@ -1,714 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.ShortcutInfo;
|
|
||||||
import android.content.pm.ShortcutManager;
|
|
||||||
import android.content.pm.Signature;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.Icon;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.Base64;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
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.firebase.FirebaseApp;
|
|
||||||
import com.google.firebase.FirebaseOptions;
|
|
||||||
import com.google.firebase.iid.FirebaseInstanceId;
|
|
||||||
import com.google.firebase.messaging.FirebaseMessaging;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
|
||||||
import com.hypertrack.hyperlog.HyperLog;
|
|
||||||
import com.mikepenz.iconics.Iconics;
|
|
||||||
import com.mikepenz.iconics.IconicsColor;
|
|
||||||
import com.mikepenz.iconics.IconicsDrawable;
|
|
||||||
import com.mikepenz.iconics.IconicsSize;
|
|
||||||
import com.mikepenz.iconics.typeface.IIcon;
|
|
||||||
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ConcurrentModificationException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
import cat.ereza.customactivityoncrash.config.CaocConfig;
|
|
||||||
import im.wangchao.mhttp.MHttp;
|
|
||||||
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar;
|
|
||||||
import im.wangchao.mhttp.internal.cookie.cache.SetCookieCache;
|
|
||||||
import im.wangchao.mhttp.internal.cookie.persistence.SharedPrefsCookiePersistor;
|
|
||||||
import me.leolin.shortcutbadger.ShortcutBadger;
|
|
||||||
import okhttp3.ConnectionSpec;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.TlsVersion;
|
|
||||||
import pl.szczodrzynski.edziennik.config.Config;
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing;
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.DebugLog;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile;
|
|
||||||
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
|
||||||
import pl.szczodrzynski.edziennik.network.TLSSocketFactory;
|
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncWorker;
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.DebugLogFormat;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.PermissionChecker;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.AppConfig;
|
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.entity.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
|
||||||
|
|
||||||
public class App extends androidx.multidex.MultiDexApplication implements Configuration.Provider {
|
|
||||||
private static final String TAG = "App";
|
|
||||||
public static int profileId = -1;
|
|
||||||
private Context mContext;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Configuration getWorkManagerConfiguration() {
|
|
||||||
return new Configuration.Builder()
|
|
||||||
.setMinimumLoggingLevel(Log.VERBOSE)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static final int REQUEST_TIMEOUT = 10 * 1000;
|
|
||||||
|
|
||||||
// notifications
|
|
||||||
//public NotificationManager mNotificationManager;
|
|
||||||
//public final String NOTIFICATION_CHANNEL_ID_UPDATES = "4566";
|
|
||||||
//public String NOTIFICATION_CHANNEL_NAME_UPDATES;
|
|
||||||
public Notifier notifier;
|
|
||||||
|
|
||||||
public static final String APP_URL = "://edziennik.szczodrzynski.pl/app/";
|
|
||||||
|
|
||||||
public ShortcutManager shortcutManager;
|
|
||||||
|
|
||||||
public PermissionChecker permissionChecker;
|
|
||||||
|
|
||||||
public String signature = "";
|
|
||||||
public String deviceId = "";
|
|
||||||
|
|
||||||
public AppDb db;
|
|
||||||
public void debugLog(String text) {
|
|
||||||
if (!devMode)
|
|
||||||
return;
|
|
||||||
db.debugLogDao().add(new DebugLog(Utils.getCurrentTimeUsingCalendar()+": "+text));
|
|
||||||
}
|
|
||||||
public void debugLogAsync(String text) {
|
|
||||||
if (!devMode)
|
|
||||||
return;
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
db.debugLogDao().add(new DebugLog(Utils.getCurrentTimeUsingCalendar()+": "+text));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// network & APIs
|
|
||||||
public NetworkUtils networkUtils;
|
|
||||||
public PersistentCookieJar cookieJar;
|
|
||||||
public OkHttpClient http;
|
|
||||||
public OkHttpClient httpLazy;
|
|
||||||
|
|
||||||
public SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE
|
|
||||||
public AppConfig appConfig; // APPCONFIG: common for all profiles
|
|
||||||
//public AppProfile profile; // current profile
|
|
||||||
public SharedPreferences registerStore; // sharedPreferences for REGISTER
|
|
||||||
//public Register register; // REGISTER for current profile, read from registerStore
|
|
||||||
|
|
||||||
public Profile profile;
|
|
||||||
public Config config;
|
|
||||||
private static Config mConfig;
|
|
||||||
public static Config getConfig() {
|
|
||||||
return mConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// other stuff
|
|
||||||
public Gson gson;
|
|
||||||
public String requestScheme = "https";
|
|
||||||
public boolean unreadBadgesAvailable = true;
|
|
||||||
|
|
||||||
public static boolean devMode = false;
|
|
||||||
|
|
||||||
public static final boolean UPDATES_ON_PLAY_STORE = true;
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
|
||||||
public Icon getDesktopIconFromIconics(IIcon icon) {
|
|
||||||
final IconicsDrawable drawable = new IconicsDrawable(mContext, icon)
|
|
||||||
.color(IconicsColor.colorInt(Color.WHITE))
|
|
||||||
.size(IconicsSize.dp(48))
|
|
||||||
.padding(IconicsSize.dp(8))
|
|
||||||
.backgroundColor(IconicsColor.colorRes(R.color.colorPrimaryDark))
|
|
||||||
.roundedCorners(IconicsSize.dp(10));
|
|
||||||
//drawable.setStyle(Paint.Style.FILL);
|
|
||||||
final Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
|
||||||
final Canvas canvas = new Canvas(bitmap);
|
|
||||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
|
||||||
drawable.draw(canvas);
|
|
||||||
|
|
||||||
return Icon.createWithBitmap(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
|
||||||
CaocConfig.Builder.create()
|
|
||||||
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM) //default: CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM
|
|
||||||
.enabled(true) //default: true
|
|
||||||
.showErrorDetails(true) //default: true
|
|
||||||
.showRestartButton(true) //default: true
|
|
||||||
.logErrorOnRestart(true) //default: true
|
|
||||||
.trackActivities(true) //default: false
|
|
||||||
.minTimeBetweenCrashesMs(2000) //default: 3000
|
|
||||||
.errorDrawable(R.drawable.ic_rip) //default: bug image
|
|
||||||
.restartActivity(MainActivity.class) //default: null (your app's launch activity)
|
|
||||||
.errorActivity(CrashActivity.class) //default: null (default error activity)
|
|
||||||
//.eventListener(new YourCustomEventListener()) //default: null
|
|
||||||
.apply();
|
|
||||||
mContext = this;
|
|
||||||
db = AppDb.getDatabase(this);
|
|
||||||
gson = new Gson();
|
|
||||||
networkUtils = new NetworkUtils(this);
|
|
||||||
|
|
||||||
config = new Config(db);
|
|
||||||
config.migrate(this);
|
|
||||||
mConfig = config;
|
|
||||||
|
|
||||||
Iconics.init(getApplicationContext());
|
|
||||||
Iconics.registerFont(SzkolnyFont.INSTANCE);
|
|
||||||
|
|
||||||
notifier = new Notifier(this);
|
|
||||||
permissionChecker = new PermissionChecker(mContext);
|
|
||||||
|
|
||||||
deviceId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
|
|
||||||
|
|
||||||
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()
|
|
||||||
.cache(null)
|
|
||||||
.followRedirects(true)
|
|
||||||
.followSslRedirects(true)
|
|
||||||
.retryOnConnectionFailure(true)
|
|
||||||
.cookieJar(cookieJar)
|
|
||||||
.connectTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.writeTimeout(20, TimeUnit.SECONDS)
|
|
||||||
.readTimeout(40, TimeUnit.SECONDS);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
ProviderInstaller.installIfNeeded(this);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("OkHttpTLSCompat", "Play Services not found or outdated");
|
|
||||||
X509TrustManager x509TrustManager = null;
|
|
||||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
trustManagerFactory.init((KeyStore) null);
|
|
||||||
for (TrustManager trustManager: trustManagerFactory.getTrustManagers()) {
|
|
||||||
if (trustManager instanceof X509TrustManager)
|
|
||||||
x509TrustManager = (X509TrustManager) trustManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSLContext sc = SSLContext.getInstance("TLSv1.2");
|
|
||||||
sc.init(null, null, null);
|
|
||||||
httpBuilder.sslSocketFactory(new TLSSocketFactory(sc.getSocketFactory()), x509TrustManager);
|
|
||||||
|
|
||||||
ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
|
||||||
.tlsVersions(TlsVersion.TLS_1_0)
|
|
||||||
.tlsVersions(TlsVersion.TLS_1_1)
|
|
||||||
.tlsVersions(TlsVersion.TLS_1_2)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
List<ConnectionSpec> specs = new ArrayList<>();
|
|
||||||
specs.add(cs);
|
|
||||||
specs.add(ConnectionSpec.COMPATIBLE_TLS);
|
|
||||||
specs.add(ConnectionSpec.CLEARTEXT);
|
|
||||||
|
|
||||||
httpBuilder.connectionSpecs(specs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception exc) {
|
|
||||||
Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
httpLazy = http.newBuilder().followRedirects(false).followSslRedirects(false).build();
|
|
||||||
|
|
||||||
MHttp.instance()
|
|
||||||
.customOkHttpClient(http);
|
|
||||||
|
|
||||||
//register = new Register(mContext);
|
|
||||||
|
|
||||||
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
|
||||||
|
|
||||||
if (config.getSync().getEnabled()) {
|
|
||||||
SyncWorker.Companion.scheduleNext(this, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SyncWorker.Companion.cancelNext(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
db.metadataDao().countUnseen().observeForever(count -> {
|
|
||||||
Log.d("MainActivity", "Overall unseen count changed");
|
|
||||||
assert count != null;
|
|
||||||
if (unreadBadgesAvailable) {
|
|
||||||
unreadBadgesAvailable = ShortcutBadger.applyCount(this, count);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//new IonCookieManager(mContext);
|
|
||||||
|
|
||||||
new Handler().post(() -> {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
|
||||||
shortcutManager = getSystemService(ShortcutManager.class);
|
|
||||||
|
|
||||||
ShortcutInfo shortcutTimetable = new ShortcutInfo.Builder(mContext, "item_timetable")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
|
|
||||||
.setIcon(Icon.createWithResource(this, R.mipmap.ic_shortcut_timetable))
|
|
||||||
//.setIcon(getDesktopIconFromIconics(CommunityMaterial.Icon2.cmd_timetable))
|
|
||||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ShortcutInfo shortcutAgenda = new ShortcutInfo.Builder(mContext, "item_agenda")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
|
|
||||||
.setIcon(Icon.createWithResource(this, R.mipmap.ic_shortcut_agenda))
|
|
||||||
//.setIcon(getDesktopIconFromIconics(CommunityMaterial.Icon.cmd_calendar))
|
|
||||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_AGENDA))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ShortcutInfo shortcutGrades = new ShortcutInfo.Builder(mContext, "item_grades")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
|
|
||||||
.setIcon(Icon.createWithResource(this, R.mipmap.ic_shortcut_grades))
|
|
||||||
//.setIcon(getDesktopIconFromIconics(CommunityMaterial.Icon2.cmd_numeric_5_box))
|
|
||||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_GRADES))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ShortcutInfo shortcutHomework = new ShortcutInfo.Builder(mContext, "item_homeworks")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
|
|
||||||
.setIcon(Icon.createWithResource(this, R.mipmap.ic_shortcut_homework))
|
|
||||||
//.setIcon(getDesktopIconFromIconics(SzkolnyFont.Icon.szf_file_document_edit))
|
|
||||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOMEWORK))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ShortcutInfo shortcutMessages = new ShortcutInfo.Builder(mContext, "item_messages")
|
|
||||||
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
|
|
||||||
.setIcon(Icon.createWithResource(this, R.mipmap.ic_shortcut_messages))
|
|
||||||
//.setIcon(getDesktopIconFromIconics(CommunityMaterial.Icon.cmd_email))
|
|
||||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
|
||||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_MESSAGES ))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutTimetable, shortcutAgenda, shortcutGrades, shortcutHomework, shortcutMessages));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.getAppInstalledTime() == 0) {
|
|
||||||
try {
|
|
||||||
config.setAppInstalledTime(getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime);
|
|
||||||
config.setAppRateSnackbarTime(config.getAppInstalledTime() + 7 * 24 * 60 * 60 * 1000);
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Task<CapabilityInfo> capabilityInfoTask =
|
|
||||||
Wearable.getCapabilityClient(this)
|
|
||||||
.getCapability("edziennik_wear_app", CapabilityClient.FILTER_REACHABLE);
|
|
||||||
capabilityInfoTask.addOnCompleteListener((task) -> {
|
|
||||||
if (task.isSuccessful()) {
|
|
||||||
CapabilityInfo capabilityInfo = task.getResult();
|
|
||||||
assert capabilityInfo != null;
|
|
||||||
Set<Node> nodes;
|
|
||||||
nodes = capabilityInfo.getNodes();
|
|
||||||
Log.d(TAG, "Nodes "+nodes);
|
|
||||||
|
|
||||||
if (nodes.size() > 0) {
|
|
||||||
Wearable.getMessageClient(this).sendMessage(
|
|
||||||
nodes.toArray(new Node[]{})[0].getId(), "/ping", "Hello world".getBytes());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Capability request failed to return any results.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Wearable.getDataClient(this).addListener(dataEventBuffer -> {
|
|
||||||
Log.d(TAG, "onDataChanged(): " + dataEventBuffer);
|
|
||||||
|
|
||||||
for (DataEvent event : dataEventBuffer) {
|
|
||||||
if (event.getType() == DataEvent.TYPE_CHANGED) {
|
|
||||||
String path = event.getDataItem().getUri().getPath();
|
|
||||||
Log.d(TAG, "Data "+path+ " :: "+Arrays.toString(event.getDataItem().getData()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
|
|
||||||
FirebaseApp pushMobidziennikApp = FirebaseApp.initializeApp(
|
|
||||||
this,
|
|
||||||
new FirebaseOptions.Builder()
|
|
||||||
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
|
|
||||||
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
|
|
||||||
.build(),
|
|
||||||
"Mobidziennik2"
|
|
||||||
);
|
|
||||||
|
|
||||||
FirebaseApp pushLibrusApp = FirebaseApp.initializeApp(
|
|
||||||
this,
|
|
||||||
new FirebaseOptions.Builder()
|
|
||||||
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
|
||||||
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
|
||||||
.build(),
|
|
||||||
"Librus"
|
|
||||||
);
|
|
||||||
|
|
||||||
FirebaseApp pushVulcanApp = FirebaseApp.initializeApp(
|
|
||||||
this,
|
|
||||||
new FirebaseOptions.Builder()
|
|
||||||
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
|
||||||
.setApplicationId("1:987828170337:android:ac97431a0a4578c3")
|
|
||||||
.build(),
|
|
||||||
"Vulcan"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (config.getRunSync()) {
|
|
||||||
config.setRunSync(false);
|
|
||||||
EdziennikTask.Companion.sync().enqueue(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final long startTime = System.currentTimeMillis();
|
|
||||||
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
|
||||||
Log.d(TAG, "Token for App is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId()+". Time is "+(System.currentTimeMillis() - startTime));
|
|
||||||
config.getSync().setTokenApp(instanceIdResult.getToken());
|
|
||||||
});
|
|
||||||
/*FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
|
||||||
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<>()));
|
|
||||||
});
|
|
||||||
FirebaseInstanceId.getInstance(pushLibrusApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
|
||||||
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<>()));
|
|
||||||
});
|
|
||||||
FirebaseInstanceId.getInstance(pushVulcanApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
|
||||||
Log.d(TAG, "Token for Vulcan is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
|
||||||
Pair<String, List<Integer>> pair = appConfig.fcmTokens.get(LOGIN_TYPE_VULCAN);
|
|
||||||
if (pair == null || pair.first == null || !pair.first.equals(instanceIdResult.getToken())) {
|
|
||||||
appConfig.fcmTokens.put(LOGIN_TYPE_VULCAN, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
|
|
||||||
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(getPackageName());
|
|
||||||
}
|
|
||||||
catch (IllegalStateException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void loadConfig()
|
|
||||||
{
|
|
||||||
appConfig = new AppConfig(this);
|
|
||||||
|
|
||||||
|
|
||||||
if (appSharedPrefs.contains("config")) {
|
|
||||||
// remove old-format config, save the new one and empty the incorrectly-nulled config
|
|
||||||
appConfig = gson.fromJson(appSharedPrefs.getString("config", ""), AppConfig.class);
|
|
||||||
appSharedPrefs.edit().remove("config").apply();
|
|
||||||
saveConfig();
|
|
||||||
appConfig = new AppConfig(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appSharedPrefs.contains("profiles")) {
|
|
||||||
SharedPreferences.Editor appSharedPrefsEditor = appSharedPrefs.edit();
|
|
||||||
/*List<Integer> appProfileIds = gson.fromJson(appSharedPrefs.getString("profiles", ""), new TypeToken<List<Integer>>(){}.getType());
|
|
||||||
for (int id: appProfileIds) {
|
|
||||||
AppProfile appProfile = gson.fromJson(appSharedPrefs.getString("profile"+id, ""), AppProfile.class);
|
|
||||||
if (appProfile != null) {
|
|
||||||
appConfig.profiles.add(appProfile);
|
|
||||||
}
|
|
||||||
appSharedPrefsEditor.remove("profile"+id);
|
|
||||||
}*/
|
|
||||||
appSharedPrefsEditor.remove("profiles");
|
|
||||||
appSharedPrefsEditor.apply();
|
|
||||||
//profilesSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Map<String,?> keys = appSharedPrefs.getAll();
|
|
||||||
for (Map.Entry<String,?> entry : keys.entrySet()) {
|
|
||||||
if (entry.getKey().startsWith("app.appConfig.")) {
|
|
||||||
String fieldName = entry.getKey().replace("app.appConfig.", "");
|
|
||||||
|
|
||||||
try {
|
|
||||||
Field field = AppConfig.class.getField(fieldName);
|
|
||||||
Object object;
|
|
||||||
try {
|
|
||||||
object = gson.fromJson(entry.getValue().toString(), field.getGenericType());
|
|
||||||
} catch (JsonSyntaxException e) {
|
|
||||||
Log.d(TAG, "For field "+fieldName);
|
|
||||||
e.printStackTrace();
|
|
||||||
object = entry.getValue().toString();
|
|
||||||
}
|
|
||||||
if (object != null)
|
|
||||||
field.set(appConfig, object);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Log.w(TAG, "Should remove app.appConfig."+fieldName);
|
|
||||||
//appSharedPrefs.edit().remove("app.appConfig."+fieldName).apply(); TODO migration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (appConfig.lastAppVersion > BuildConfig.VERSION_CODE) {
|
|
||||||
BootReceiver br = new BootReceiver();
|
|
||||||
Intent i = new Intent();
|
|
||||||
//i.putExtra("UserChecked", true);
|
|
||||||
br.onReceive(getContext(), i);
|
|
||||||
Toast.makeText(mContext, R.string.warning_older_version_running, Toast.LENGTH_LONG).show();
|
|
||||||
//Toast.makeText(mContext, "Zaktualizuj aplikację.", Toast.LENGTH_LONG).show();
|
|
||||||
//System.exit(0);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (appConfig == null) {
|
|
||||||
appConfig = new AppConfig(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void saveConfig()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
appConfig.savePending = false;
|
|
||||||
|
|
||||||
SharedPreferences.Editor appSharedPrefsEditor = appSharedPrefs.edit();
|
|
||||||
|
|
||||||
JsonObject appConfigJson = gson.toJsonTree(appConfig).getAsJsonObject();
|
|
||||||
for (Map.Entry<String, JsonElement> entry : appConfigJson.entrySet()) {
|
|
||||||
String jsonObj;
|
|
||||||
jsonObj = entry.getValue().toString();
|
|
||||||
/*if (entry.getValue().isJsonObject()) {
|
|
||||||
jsonObj = entry.getValue().getAsJsonObject().toString();
|
|
||||||
}
|
|
||||||
else if (entry.getValue().isJsonArray()) {
|
|
||||||
jsonObj = entry.getValue().getAsJsonArray().toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jsonObj = entry.getValue().toString();
|
|
||||||
}*/
|
|
||||||
appSharedPrefsEditor.putString("app.appConfig." + entry.getKey(), jsonObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
appSharedPrefsEditor.apply();
|
|
||||||
}
|
|
||||||
catch (ConcurrentModificationException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
//appSharedPrefs.edit().putString("config", gson.toJson(appConfig)).apply();
|
|
||||||
}
|
|
||||||
public void saveConfig(String ... fieldNames)
|
|
||||||
{
|
|
||||||
appConfig.savePending = false;
|
|
||||||
|
|
||||||
SharedPreferences.Editor appSharedPrefsEditor = appSharedPrefs.edit();
|
|
||||||
|
|
||||||
for (String fieldName: fieldNames) {
|
|
||||||
try {
|
|
||||||
Object object = AppConfig.class.getField(fieldName).get(appConfig);
|
|
||||||
appSharedPrefsEditor.putString("app.appConfig."+fieldName, gson.toJson(object));
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ConcurrentModificationException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appSharedPrefsEditor.apply();
|
|
||||||
//appSharedPrefs.edit().putString("config", gson.toJson(appConfig)).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void profileSave() {
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
db.profileDao().add(profile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void profileSaveAsync() {
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
db.profileDao().add(profile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public void profileSaveAsync(Profile profile) {
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
db.profileDao().add(profile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void profileLoadById(int id) {
|
|
||||||
profileLoadById(id, false);
|
|
||||||
}
|
|
||||||
public void profileLoadById(int id, boolean loadedLast) {
|
|
||||||
//Log.d(TAG, "Loading ID "+id);
|
|
||||||
/*if (profile == null) {
|
|
||||||
profile = profileNew();
|
|
||||||
AppDb.profileId = profile.id;
|
|
||||||
appSharedPrefs.edit().putInt("current_profile_id", profile.id).apply();
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
if (profile == null || profile.getId() != id) {
|
|
||||||
profile = db.profileDao().getByIdNow(id);
|
|
||||||
/*if (profile == null) {
|
|
||||||
profileLoadById(id);
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
if (profile != null) {
|
|
||||||
MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1);
|
|
||||||
profileId = profile.getId();
|
|
||||||
appSharedPrefs.edit().putInt("current_profile_id", profile.getId()).apply();
|
|
||||||
config.setProfile(profileId);
|
|
||||||
}
|
|
||||||
else if (!loadedLast) {
|
|
||||||
profileLoadById(profileLastId(), true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
profileId = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public void profileRemove(int id)
|
|
||||||
{
|
|
||||||
Profile profile = db.profileDao().getFullByIdNow(id);
|
|
||||||
|
|
||||||
if (profile.id == profile.loginStoreId) {
|
|
||||||
// this profile is the owner of the login store
|
|
||||||
// we need to check if any other profile is using it
|
|
||||||
List<Integer> transferProfileIds = db.profileDao().getIdsByLoginStoreIdNow(profile.loginStoreId);
|
|
||||||
if (transferProfileIds.size() == 1) {
|
|
||||||
// this login store is free of users, remove it along with the profile
|
|
||||||
db.loginStoreDao().remove(profile.loginStoreId);
|
|
||||||
// the current store is removed, we are ready to remove the profile
|
|
||||||
}
|
|
||||||
else if (transferProfileIds.size() > 1) {
|
|
||||||
transferProfileIds.remove(transferProfileIds.indexOf(profile.id));
|
|
||||||
// someone is using the store
|
|
||||||
// we need to transfer it to the firstProfileId
|
|
||||||
db.loginStoreDao().changeId(profile.loginStoreId, transferProfileIds.get(0));
|
|
||||||
db.profileDao().changeStoreId(profile.loginStoreId, transferProfileIds.get(0));
|
|
||||||
// the current store is removed, we are ready to remove the profile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else, the profile uses a store that it doesn't own
|
|
||||||
// leave the store and go on with removing
|
|
||||||
|
|
||||||
Log.d(TAG, "Before removal: "+db.profileDao().getAllNow().toString());
|
|
||||||
db.profileDao().remove(profile.id);
|
|
||||||
Log.d(TAG, "After removal: "+db.profileDao().getAllNow().toString());
|
|
||||||
|
|
||||||
*//*int newId = 1;
|
|
||||||
if (appConfig.profiles.size() > 0) {
|
|
||||||
newId = appConfig.profiles.get(appConfig.profiles.size() - 1).id;
|
|
||||||
}
|
|
||||||
Log.d(TAG, "New ID: "+newId);
|
|
||||||
//Toast.makeText(mContext, "selected new id "+newId, Toast.LENGTH_SHORT).show();
|
|
||||||
profileLoadById(newId);*//*
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public int profileFirstId() {
|
|
||||||
Integer id = db.profileDao().getFirstId();
|
|
||||||
return id == null ? 1 : id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int profileLastId() {
|
|
||||||
Integer id = db.profileDao().getLastId();
|
|
||||||
return id == null ? 1 : id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Context getContext()
|
|
||||||
{
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkDevModePassword() {
|
|
||||||
try {
|
|
||||||
devMode = Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.getDevModePassword()).equals("ok here you go it's enabled now")
|
|
||||||
|| BuildConfig.DEBUG;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
devMode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -4,20 +4,93 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik
|
package pl.szczodrzynski.edziennik
|
||||||
|
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ShortcutInfo
|
||||||
|
import android.content.pm.ShortcutManager
|
||||||
|
import android.graphics.drawable.Icon
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.multidex.MultiDexApplication
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import cat.ereza.customactivityoncrash.config.CaocConfig
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||||
import kotlinx.coroutines.Job
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||||
|
import com.chuckerteam.chucker.api.RetentionManager
|
||||||
|
import com.google.firebase.FirebaseApp
|
||||||
|
import com.google.firebase.FirebaseOptions
|
||||||
|
import com.google.firebase.iid.FirebaseInstanceId
|
||||||
|
import com.google.firebase.messaging.FirebaseMessaging
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.hypertrack.hyperlog.HyperLog
|
||||||
|
import com.mikepenz.iconics.Iconics
|
||||||
|
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
|
||||||
|
import im.wangchao.mhttp.MHttp
|
||||||
|
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar
|
||||||
|
import im.wangchao.mhttp.internal.cookie.cache.SetCookieCache
|
||||||
|
import im.wangchao.mhttp.internal.cookie.persistence.SharedPrefsCookiePersistor
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import me.leolin.shortcutbadger.ShortcutBadger
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import pl.szczodrzynski.edziennik.config.Config
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
|
import pl.szczodrzynski.edziennik.network.NetworkUtils
|
||||||
|
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
||||||
|
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity
|
||||||
|
import pl.szczodrzynski.edziennik.utils.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScope {
|
class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
lateinit var db: AppDb
|
||||||
|
val config: Config by lazy { Config(db) }
|
||||||
|
var profile: Profile by mutableLazy { Profile(0, 0, 0, "") }
|
||||||
|
val profileId
|
||||||
|
get() = profile.id
|
||||||
|
|
||||||
var devMode = false
|
var devMode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
//lateinit var db: AppDb
|
val notifications by lazy { Notifications() }
|
||||||
//val config by lazy { Config(db); // TODO migrate }
|
inner class Notifications {
|
||||||
|
val syncId = 1
|
||||||
|
val syncKey = "pl.szczodrzynski.edziennik.SYNC"
|
||||||
|
val syncChannelName: String by lazy { getString(R.string.notification_channel_get_data_name) }
|
||||||
|
val syncChannelDesc: String by lazy { getString(R.string.notification_channel_get_data_desc) }
|
||||||
|
val dataId = 50
|
||||||
|
val dataKey = "pl.szczodrzynski.edziennik.DATA"
|
||||||
|
val dataChannelName: String by lazy { getString(R.string.notification_channel_notifications_name) }
|
||||||
|
val dataChannelDesc: String by lazy { getString(R.string.notification_channel_notifications_desc) }
|
||||||
|
val dataQuietId = 60
|
||||||
|
val dataQuietKey = "pl.szczodrzynski.edziennik.DATA_QUIET"
|
||||||
|
val dataQuietChannelName: String by lazy { getString(R.string.notification_channel_notifications_quiet_name) }
|
||||||
|
val dataQuietChannelDesc: String by lazy { getString(R.string.notification_channel_notifications_quiet_desc) }
|
||||||
|
val updatesId = 100
|
||||||
|
val updatesKey = "pl.szczodrzynski.edziennik.UPDATES"
|
||||||
|
val updatesChannelName: String by lazy { getString(R.string.notification_channel_updates_name) }
|
||||||
|
val updatesChannelDesc: String by lazy { getString(R.string.notification_channel_updates_desc) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val db
|
||||||
|
get() = App.db
|
||||||
|
val config
|
||||||
|
get() = App.config
|
||||||
|
val profile
|
||||||
|
get() = App.profile
|
||||||
|
val profileId
|
||||||
|
get() = App.profileId
|
||||||
|
|
||||||
private val job = Job()
|
private val job = Job()
|
||||||
override val coroutineContext: CoroutineContext
|
override val coroutineContext: CoroutineContext
|
||||||
@ -26,11 +99,10 @@ class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScop
|
|||||||
.setMinimumLoggingLevel(Log.VERBOSE)
|
.setMinimumLoggingLevel(Log.VERBOSE)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
/*val preferences by lazy { getSharedPreferences(getString(R.string.preference_file), Context.MODE_PRIVATE) }
|
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) }
|
val permissionChecker by lazy { PermissionChecker(this) }
|
||||||
|
val networkUtils by lazy { NetworkUtils(this) }
|
||||||
lateinit var profile: ProfileFull
|
val gson by lazy { Gson() }
|
||||||
|
|
||||||
/* _ _ _______ _______ _____
|
/* _ _ _______ _______ _____
|
||||||
| | | |__ __|__ __| __ \
|
| | | |__ __|__ __| __ \
|
||||||
@ -48,13 +120,13 @@ class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScop
|
|||||||
.connectTimeout(20, TimeUnit.SECONDS)
|
.connectTimeout(20, TimeUnit.SECONDS)
|
||||||
.writeTimeout(5, TimeUnit.SECONDS)
|
.writeTimeout(5, TimeUnit.SECONDS)
|
||||||
.readTimeout(10, TimeUnit.SECONDS)
|
.readTimeout(10, TimeUnit.SECONDS)
|
||||||
builder.installHttpsSupport()
|
builder.installHttpsSupport(this)
|
||||||
|
|
||||||
if (devMode || BuildConfig.DEBUG) {
|
if (devMode || BuildConfig.DEBUG) {
|
||||||
HyperLog.initialize(this)
|
HyperLog.initialize(this)
|
||||||
HyperLog.setLogLevel(Log.VERBOSE)
|
HyperLog.setLogLevel(Log.VERBOSE)
|
||||||
HyperLog.setLogFormat(DebugLogFormat(this))
|
HyperLog.setLogFormat(DebugLogFormat(this))
|
||||||
val chuckerCollector = ChuckerCollector(this, true, Period.ONE_HOUR)
|
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
|
||||||
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
||||||
builder.addInterceptor(chuckerInterceptor)
|
builder.addInterceptor(chuckerInterceptor)
|
||||||
}
|
}
|
||||||
@ -77,22 +149,7 @@ class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScop
|
|||||||
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
|
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
|
||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
private val deviceId: String by lazy { Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) ?: "" }
|
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
|
private var unreadBadgesAvailable = true
|
||||||
|
|
||||||
/* _____ _
|
/* _____ _
|
||||||
@ -118,193 +175,214 @@ class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScop
|
|||||||
.apply()
|
.apply()
|
||||||
Iconics.init(applicationContext)
|
Iconics.init(applicationContext)
|
||||||
Iconics.registerFont(SzkolnyFont)
|
Iconics.registerFont(SzkolnyFont)
|
||||||
db = AppDb.getDatabase(this)
|
App.db = AppDb(this)
|
||||||
Themes.themeInt = config.ui.theme
|
Themes.themeInt = config.ui.theme
|
||||||
MHttp.instance().customOkHttpClient(http)
|
MHttp.instance().customOkHttpClient(http)
|
||||||
|
|
||||||
|
if (!profileLoadById(config.lastProfileId)) {
|
||||||
|
db.profileDao().firstId?.let { profileLoadById(it) }
|
||||||
|
}
|
||||||
|
|
||||||
devMode = "f054761fbdb6a238" == deviceId || BuildConfig.DEBUG
|
devMode = "f054761fbdb6a238" == deviceId || BuildConfig.DEBUG
|
||||||
if (config.devModePassword != null)
|
|
||||||
checkDevModePassword()
|
|
||||||
|
|
||||||
Signing.getCert(this)
|
Signing.getCert(this)
|
||||||
|
|
||||||
launch { async(Dispatchers.Default) {
|
launch {
|
||||||
if (config.sync.enabled) {
|
withContext(Dispatchers.Default) {
|
||||||
scheduleNext(this@App, false)
|
config.migrate(this@App)
|
||||||
} else {
|
|
||||||
cancelNext(this@App)
|
if (config.devModePassword != null)
|
||||||
|
checkDevModePassword()
|
||||||
|
|
||||||
|
if (config.sync.enabled)
|
||||||
|
SyncWorker.scheduleNext(this@App, false)
|
||||||
|
else
|
||||||
|
SyncWorker.cancelNext(this@App)
|
||||||
|
|
||||||
|
if (config.sync.notifyAboutUpdates)
|
||||||
|
UpdateWorker.scheduleNext(this@App, false)
|
||||||
|
else
|
||||||
|
UpdateWorker.cancelNext(this@App)
|
||||||
|
|
||||||
|
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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
notificationManager.createNotificationChannel(
|
||||||
|
NotificationChannel(notifications.syncKey, notifications.syncChannelName, NotificationManager.IMPORTANCE_MIN).apply {
|
||||||
|
description = notifications.syncChannelDesc
|
||||||
|
})
|
||||||
|
notificationManager.createNotificationChannel(
|
||||||
|
NotificationChannel(notifications.dataKey, notifications.dataChannelName, NotificationManager.IMPORTANCE_HIGH).apply {
|
||||||
|
description = notifications.dataChannelDesc
|
||||||
|
enableLights(true)
|
||||||
|
lightColor = 0xff2196f3.toInt()
|
||||||
|
})
|
||||||
|
notificationManager.createNotificationChannel(
|
||||||
|
NotificationChannel(notifications.dataQuietKey, notifications.dataQuietChannelName, NotificationManager.IMPORTANCE_LOW).apply {
|
||||||
|
description = notifications.dataQuietChannelDesc
|
||||||
|
setSound(null, null)
|
||||||
|
enableVibration(false)
|
||||||
|
})
|
||||||
|
notificationManager.createNotificationChannel(
|
||||||
|
NotificationChannel(notifications.updatesKey, notifications.updatesChannelName, NotificationManager.IMPORTANCE_DEFAULT).apply {
|
||||||
|
description = notifications.updatesChannelDesc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (config.appInstalledTime == 0L)
|
||||||
|
try {
|
||||||
|
config.appInstalledTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
|
||||||
|
config.appRateSnackbarTime = config.appInstalledTime + 7 * DAY * MS
|
||||||
|
} catch (e: PackageManager.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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.metadataDao().countUnseen().observeForever { count: Int ->
|
db.metadataDao().countUnseen().observeForever { count: Int ->
|
||||||
if (unreadBadgesAvailable)
|
if (unreadBadgesAvailable)
|
||||||
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
|
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) {
|
|
||||||
|
private fun profileLoadById(profileId: Int): Boolean {
|
||||||
|
db.profileDao().getByIdNow(profileId)?.also {
|
||||||
|
App.profile = it
|
||||||
|
App.config.lastProfileId = it.id
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fun profileLoad(profileId: Int, onSuccess: (profile: Profile) -> Unit) {
|
||||||
launch {
|
launch {
|
||||||
val deferred = async(Dispatchers.Default) {
|
val success = withContext(Dispatchers.Default) {
|
||||||
profileLoad(profileId)
|
profileLoadById(profileId)
|
||||||
}
|
}
|
||||||
deferred.await()
|
if (success)
|
||||||
onSuccess(profile)
|
onSuccess(profile)
|
||||||
|
else
|
||||||
|
profileLoadLast(onSuccess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun profileLoadLast(onSuccess: (profile: Profile) -> Unit) {
|
||||||
private fun OkHttpClient.Builder.installHttpsSupport() {
|
launch {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
val success = withContext(Dispatchers.Default) {
|
||||||
try {
|
profileLoadById(db.profileDao().lastId ?: return@withContext false)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
if (!success) {
|
||||||
|
EventBus.getDefault().post(ProfileListEmptyEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun profileSave() = profileSave(profile)
|
||||||
|
fun profileSave(profile: Profile) {
|
||||||
|
launch(Dispatchers.Default) {
|
||||||
|
App.db.profileDao().add(profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,5 +393,5 @@ class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScop
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package pl.szczodrzynski.edziennik
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
@ -24,6 +25,7 @@ import android.util.Base64.encodeToString
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.CheckBox
|
import android.widget.CheckBox
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
|
import android.widget.RadioButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.*
|
import androidx.annotation.*
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
@ -34,6 +36,7 @@ import androidx.core.util.forEach
|
|||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
|
import com.google.android.gms.security.ProviderInstaller
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -41,23 +44,31 @@ import im.wangchao.mhttp.Response
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.ConnectionSpec
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.TlsVersion
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
||||||
|
import pl.szczodrzynski.edziennik.network.TLSSocketFactory
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import java.security.KeyStore
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.CRC32
|
import java.util.zip.CRC32
|
||||||
import javax.crypto.Mac
|
import javax.crypto.Mac
|
||||||
import javax.crypto.spec.SecretKeySpec
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.TrustManagerFactory
|
||||||
|
import javax.net.ssl.X509TrustManager
|
||||||
import kotlin.Pair
|
import kotlin.Pair
|
||||||
|
|
||||||
|
|
||||||
@ -105,6 +116,10 @@ fun CharSequence?.isNotNullNorEmpty(): Boolean {
|
|||||||
return this != null && this.isNotEmpty()
|
return this != null && this.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CharSequence?.isNotNullNorBlank(): Boolean {
|
||||||
|
return this != null && this.isNotBlank()
|
||||||
|
}
|
||||||
|
|
||||||
fun currentTimeUnix() = System.currentTimeMillis() / 1000
|
fun currentTimeUnix() = System.currentTimeMillis() / 1000
|
||||||
|
|
||||||
fun Bundle?.getInt(key: String, defaultValue: Int): Int {
|
fun Bundle?.getInt(key: String, defaultValue: Int): Int {
|
||||||
@ -638,6 +653,34 @@ fun Bundle(vararg properties: Pair<String, Any?>): Bundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun Intent(action: String? = null, vararg properties: Pair<String, Any?>): Intent {
|
||||||
|
return Intent(action).putExtras(Bundle(*properties))
|
||||||
|
}
|
||||||
|
fun Intent(packageContext: Context, cls: Class<*>, vararg properties: Pair<String, Any?>): Intent {
|
||||||
|
return Intent(packageContext, cls).putExtras(Bundle(*properties))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Bundle.toJsonObject(): JsonObject {
|
||||||
|
val json = JsonObject()
|
||||||
|
keySet()?.forEach { key ->
|
||||||
|
get(key)?.let {
|
||||||
|
when (it) {
|
||||||
|
is String -> json.addProperty(key, it)
|
||||||
|
is Char -> json.addProperty(key, it)
|
||||||
|
is Int -> json.addProperty(key, it)
|
||||||
|
is Long -> json.addProperty(key, it)
|
||||||
|
is Float -> json.addProperty(key, it)
|
||||||
|
is Short -> json.addProperty(key, it)
|
||||||
|
is Double -> json.addProperty(key, it)
|
||||||
|
is Boolean -> json.addProperty(key, it)
|
||||||
|
is Bundle -> json.add(key, it.toJsonObject())
|
||||||
|
else -> json.addProperty(key, it.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
fun Intent.toJsonObject() = extras?.toJsonObject()
|
||||||
|
|
||||||
fun JsonArray?.isNullOrEmpty(): Boolean = (this?.size() ?: 0) == 0
|
fun JsonArray?.isNullOrEmpty(): Boolean = (this?.size() ?: 0) == 0
|
||||||
fun JsonArray.isEmpty(): Boolean = this.size() == 0
|
fun JsonArray.isEmpty(): Boolean = this.size() == 0
|
||||||
@ -930,6 +973,8 @@ fun Context.getNotificationTitle(type: Int): String {
|
|||||||
Notification.TYPE_NEW_EVENT -> R.string.notification_type_new_event
|
Notification.TYPE_NEW_EVENT -> R.string.notification_type_new_event
|
||||||
Notification.TYPE_NEW_HOMEWORK -> R.string.notification_type_new_homework
|
Notification.TYPE_NEW_HOMEWORK -> R.string.notification_type_new_homework
|
||||||
Notification.TYPE_NEW_SHARED_EVENT -> R.string.notification_type_new_shared_event
|
Notification.TYPE_NEW_SHARED_EVENT -> R.string.notification_type_new_shared_event
|
||||||
|
Notification.TYPE_NEW_SHARED_HOMEWORK -> R.string.notification_type_new_shared_homework
|
||||||
|
Notification.TYPE_REMOVED_SHARED_EVENT -> R.string.notification_type_removed_shared_event
|
||||||
Notification.TYPE_NEW_MESSAGE -> R.string.notification_type_new_message
|
Notification.TYPE_NEW_MESSAGE -> R.string.notification_type_new_message
|
||||||
Notification.TYPE_NEW_NOTICE -> R.string.notification_type_notice
|
Notification.TYPE_NEW_NOTICE -> R.string.notification_type_notice
|
||||||
Notification.TYPE_NEW_ATTENDANCE -> R.string.notification_type_attendance
|
Notification.TYPE_NEW_ATTENDANCE -> R.string.notification_type_attendance
|
||||||
@ -946,3 +991,48 @@ fun Context.getNotificationTitle(type: Int): String {
|
|||||||
fun Cursor?.getString(columnName: String) = this?.getStringOrNull(getColumnIndex(columnName))
|
fun Cursor?.getString(columnName: String) = this?.getStringOrNull(getColumnIndex(columnName))
|
||||||
fun Cursor?.getInt(columnName: String) = this?.getIntOrNull(getColumnIndex(columnName))
|
fun Cursor?.getInt(columnName: String) = this?.getIntOrNull(getColumnIndex(columnName))
|
||||||
fun Cursor?.getLong(columnName: String) = this?.getLongOrNull(getColumnIndex(columnName))
|
fun Cursor?.getLong(columnName: String) = this?.getLongOrNull(getColumnIndex(columnName))
|
||||||
|
|
||||||
|
fun OkHttpClient.Builder.installHttpsSupport(context: Context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
ProviderInstaller.installIfNeeded(context)
|
||||||
|
} 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 CharSequence.containsAll(list: List<CharSequence>, ignoreCase: Boolean = false): Boolean {
|
||||||
|
for (i in list) {
|
||||||
|
if (!contains(i, ignoreCase))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RadioButton.setOnSelectedListener(listener: (buttonView: CompoundButton) -> Unit)
|
||||||
|
= setOnCheckedChangeListener { buttonView, isChecked -> if (isChecked) listener(buttonView) }
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package pl.szczodrzynski.edziennik
|
package pl.szczodrzynski.edziennik
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -9,7 +8,6 @@ import android.content.IntentFilter
|
|||||||
import android.content.pm.PackageManager
|
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.AsyncTask
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
@ -36,18 +34,22 @@ 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 kotlinx.coroutines.*
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import pl.droidsonroids.gif.GifDrawable
|
import pl.droidsonroids.gif.GifDrawable
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.*
|
import pl.szczodrzynski.edziennik.data.api.events.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
||||||
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata.*
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata.*
|
||||||
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
||||||
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
||||||
|
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
||||||
|
import pl.szczodrzynski.edziennik.ui.dialogs.ServerMessageDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.sync.SyncViewListDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.sync.SyncViewListDialog
|
||||||
@ -93,9 +95,10 @@ 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.coroutines.CoroutineContext
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
var useOldMessages = false
|
var useOldMessages = false
|
||||||
@ -108,6 +111,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
const val DRAWER_PROFILE_SYNC_ALL = 201
|
const val DRAWER_PROFILE_SYNC_ALL = 201
|
||||||
const val DRAWER_PROFILE_EXPORT_DATA = 202
|
const val DRAWER_PROFILE_EXPORT_DATA = 202
|
||||||
const val DRAWER_PROFILE_MANAGE = 203
|
const val DRAWER_PROFILE_MANAGE = 203
|
||||||
|
const val DRAWER_PROFILE_MARK_ALL_AS_READ = 204
|
||||||
const val DRAWER_ITEM_HOME = 1
|
const val DRAWER_ITEM_HOME = 1
|
||||||
const val DRAWER_ITEM_TIMETABLE = 11
|
const val DRAWER_ITEM_TIMETABLE = 11
|
||||||
const val DRAWER_ITEM_AGENDA = 12
|
const val DRAWER_ITEM_AGENDA = 12
|
||||||
@ -208,6 +212,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.withDescription(R.string.drawer_manage_profiles_desc)
|
.withDescription(R.string.drawer_manage_profiles_desc)
|
||||||
.isInProfileList(false)
|
.isInProfileList(false)
|
||||||
|
|
||||||
|
list += NavTarget(DRAWER_PROFILE_MARK_ALL_AS_READ, R.string.menu_mark_everything_as_read, null)
|
||||||
|
.withIcon(CommunityMaterial.Icon.cmd_eye_check_outline)
|
||||||
|
.isInProfileList(true)
|
||||||
|
|
||||||
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.Icon.cmd_download_outline)
|
||||||
.isInProfileList(true)
|
.isInProfileList(true)
|
||||||
@ -226,6 +234,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var job = Job()
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Main
|
||||||
|
|
||||||
val b: ActivitySzkolnyBinding by lazy { ActivitySzkolnyBinding.inflate(layoutInflater) }
|
val b: ActivitySzkolnyBinding by lazy { ActivitySzkolnyBinding.inflate(layoutInflater) }
|
||||||
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 }
|
||||||
@ -257,12 +269,21 @@ class MainActivity : AppCompatActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
d(TAG, "Activity created")
|
||||||
|
|
||||||
setTheme(Themes.appTheme)
|
setTheme(Themes.appTheme)
|
||||||
|
|
||||||
app.config.ui.language?.let {
|
app.config.ui.language?.let {
|
||||||
setLanguage(it)
|
setLanguage(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (App.profileId == 0) {
|
||||||
|
onProfileListEmptyEvent(ProfileListEmptyEvent())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d(TAG, "Profile is valid, inflating views")
|
||||||
|
|
||||||
setContentView(b.root)
|
setContentView(b.root)
|
||||||
|
|
||||||
Log.d(TAG, Signing.appPassword)
|
Log.d(TAG, Signing.appPassword)
|
||||||
@ -332,8 +353,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setAccountHeaderBackground(app.config.ui.headerBackground)
|
setAccountHeaderBackground(app.config.ui.headerBackground)
|
||||||
|
|
||||||
drawerProfileListEmptyListener = {
|
drawerProfileListEmptyListener = {
|
||||||
app.config.loginFinished = false
|
onProfileListEmptyEvent(ProfileListEmptyEvent())
|
||||||
profileListEmptyListener()
|
|
||||||
}
|
}
|
||||||
drawerItemSelectedListener = { id, position, drawerItem ->
|
drawerItemSelectedListener = { id, position, drawerItem ->
|
||||||
loadTarget(id)
|
loadTarget(id)
|
||||||
@ -362,30 +382,19 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
navTarget = navTargetList[0]
|
navTarget = navTargetList[0]
|
||||||
|
|
||||||
var profileListEmpty = drawer.profileListEmpty
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
intent?.putExtras(savedInstanceState)
|
intent?.putExtras(savedInstanceState)
|
||||||
savedInstanceState.clear()
|
savedInstanceState.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profileListEmpty) {
|
|
||||||
handleIntent(intent?.extras)
|
|
||||||
}
|
|
||||||
app.db.profileDao().all.observe(this, Observer { profiles ->
|
app.db.profileDao().all.observe(this, Observer { profiles ->
|
||||||
drawer.setProfileList(profiles.filter { it.id >= 0 }.toMutableList())
|
drawer.setProfileList(profiles.filter { it.id >= 0 }.toMutableList())
|
||||||
if (profileListEmpty) {
|
drawer.currentProfile = App.profileId
|
||||||
profileListEmpty = false
|
|
||||||
handleIntent(intent?.extras)
|
|
||||||
}
|
|
||||||
else if (app.profile != null) {
|
|
||||||
drawer.currentProfile = app.profile.id
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// if null, getAllFull will load a profile and update drawerItems
|
setDrawerItems()
|
||||||
if (app.profile != null)
|
|
||||||
setDrawerItems()
|
handleIntent(intent?.extras)
|
||||||
|
|
||||||
app.db.metadataDao().unreadCounts.observe(this, Observer { unreadCounters ->
|
app.db.metadataDao().unreadCounts.observe(this, Observer { unreadCounters ->
|
||||||
unreadCounters.map {
|
unreadCounters.map {
|
||||||
@ -405,6 +414,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
isStoragePermissionGranted()
|
isStoragePermissionGranted()
|
||||||
|
|
||||||
SyncWorker.scheduleNext(app)
|
SyncWorker.scheduleNext(app)
|
||||||
|
UpdateWorker.scheduleNext(app)
|
||||||
|
|
||||||
// APP BACKGROUND
|
// APP BACKGROUND
|
||||||
if (app.config.ui.appBackground != null) {
|
if (app.config.ui.appBackground != null) {
|
||||||
@ -509,17 +519,25 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var profileListEmptyListener = {
|
|
||||||
startActivityForResult(Intent(this, LoginActivity::class.java), REQUEST_LOGIN_ACTIVITY)
|
|
||||||
}
|
|
||||||
private var profileSettingClickListener = { id: Int, view: View? ->
|
private var profileSettingClickListener = { id: Int, view: View? ->
|
||||||
when (id) {
|
when (id) {
|
||||||
DRAWER_PROFILE_ADD_NEW -> {
|
DRAWER_PROFILE_ADD_NEW -> {
|
||||||
profileListEmptyListener()
|
startActivityForResult(Intent(this, LoginActivity::class.java), REQUEST_LOGIN_ACTIVITY)
|
||||||
}
|
}
|
||||||
DRAWER_PROFILE_SYNC_ALL -> {
|
DRAWER_PROFILE_SYNC_ALL -> {
|
||||||
EdziennikTask.sync().enqueue(this)
|
EdziennikTask.sync().enqueue(this)
|
||||||
}
|
}
|
||||||
|
DRAWER_PROFILE_MARK_ALL_AS_READ -> { launch {
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
app.db.profileDao().allNow.forEach { profile ->
|
||||||
|
if (profile.loginStoreType != LoginStore.LOGIN_TYPE_LIBRUS)
|
||||||
|
app.db.metadataDao().setAllSeenExceptMessagesAndAnnouncements(profile.id, true)
|
||||||
|
else
|
||||||
|
app.db.metadataDao().setAllSeenExceptMessages(profile.id, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Toast.makeText(this@MainActivity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show()
|
||||||
|
}}
|
||||||
else -> {
|
else -> {
|
||||||
loadTarget(id)
|
loadTarget(id)
|
||||||
}
|
}
|
||||||
@ -564,6 +582,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onProfileListEmptyEvent(event: ProfileListEmptyEvent) {
|
||||||
|
d(TAG, "Profile list is empty. Launch LoginActivity.")
|
||||||
|
app.config.loginFinished = false
|
||||||
|
startActivity(Intent(this, LoginActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onApiTaskProgressEvent(event: ApiTaskProgressEvent) {
|
fun onApiTaskProgressEvent(event: ApiTaskProgressEvent) {
|
||||||
if (event.profileId == App.profileId) {
|
if (event.profileId == App.profileId) {
|
||||||
navView.toolbar.apply {
|
navView.toolbar.apply {
|
||||||
@ -579,6 +604,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
fun onApiTaskFinishedEvent(event: ApiTaskFinishedEvent) {
|
fun onApiTaskFinishedEvent(event: ApiTaskFinishedEvent) {
|
||||||
|
EventBus.getDefault().removeStickyEvent(event)
|
||||||
if (event.profileId == App.profileId) {
|
if (event.profileId == App.profileId) {
|
||||||
navView.toolbar.apply {
|
navView.toolbar.apply {
|
||||||
subtitleFormat = R.string.toolbar_subtitle
|
subtitleFormat = R.string.toolbar_subtitle
|
||||||
@ -589,6 +615,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
fun onApiTaskAllFinishedEvent(event: ApiTaskAllFinishedEvent) {
|
fun onApiTaskAllFinishedEvent(event: ApiTaskAllFinishedEvent) {
|
||||||
|
EventBus.getDefault().removeStickyEvent(event)
|
||||||
swipeRefreshLayout.isRefreshing = false
|
swipeRefreshLayout.isRefreshing = false
|
||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
@ -604,7 +631,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
|
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
|
||||||
if (app.appConfig.dontShowAppManagerDialog)
|
EventBus.getDefault().removeStickyEvent(event)
|
||||||
|
if (app.config.sync.dontShowAppManagerDialog)
|
||||||
return
|
return
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setTitle(R.string.app_manager_dialog_title)
|
.setTitle(R.string.app_manager_dialog_title)
|
||||||
@ -626,8 +654,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setNeutralButton(R.string.dont_ask_again) { dialog, which ->
|
.setNeutralButton(R.string.dont_ask_again) { dialog, which ->
|
||||||
app.appConfig.dontShowAppManagerDialog = true
|
app.config.sync.dontShowAppManagerDialog = true
|
||||||
app.saveConfig("dontShowAppManagerDialog")
|
|
||||||
}
|
}
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.show()
|
.show()
|
||||||
@ -669,26 +696,46 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
d(TAG, "}")
|
d(TAG, "}")
|
||||||
|
|
||||||
|
var intentProfileId = -1
|
||||||
|
var intentTargetId = -1
|
||||||
|
|
||||||
|
if (extras?.containsKey("action") == true) {
|
||||||
|
val handled = when (extras.getString("action")) {
|
||||||
|
"serverMessage" -> {
|
||||||
|
ServerMessageDialog(
|
||||||
|
this,
|
||||||
|
extras.getString("serverMessageTitle") ?: getString(R.string.app_name),
|
||||||
|
extras.getString("serverMessageText") ?: ""
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
"feedbackMessage" -> {
|
||||||
|
intentTargetId = TARGET_FEEDBACK
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
if (handled)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (extras?.containsKey("reloadProfileId") == true) {
|
if (extras?.containsKey("reloadProfileId") == true) {
|
||||||
val reloadProfileId = extras.getInt("reloadProfileId", -1)
|
val reloadProfileId = extras.getInt("reloadProfileId", -1)
|
||||||
extras.remove("reloadProfileId")
|
extras.remove("reloadProfileId")
|
||||||
if (reloadProfileId == -1 || (app.profile != null && app.profile.id == reloadProfileId)) {
|
if (reloadProfileId == -1 || app.profile.id == reloadProfileId) {
|
||||||
reloadTarget()
|
reloadTarget()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var intentProfileId = -1
|
if (extras?.getInt("profileId", -1) != -1) {
|
||||||
var intentTargetId = -1
|
|
||||||
|
|
||||||
if (extras?.containsKey("profileId") == true) {
|
|
||||||
intentProfileId = extras.getInt("profileId", -1)
|
intentProfileId = extras.getInt("profileId", -1)
|
||||||
extras.remove("profileId")
|
extras?.remove("profileId")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extras?.containsKey("fragmentId") == true) {
|
if (extras?.getInt("fragmentId", -1) != -1) {
|
||||||
intentTargetId = extras.getInt("fragmentId", -1)
|
intentTargetId = extras.getInt("fragmentId", -1)
|
||||||
extras.remove("fragmentId")
|
extras?.remove("fragmentId")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (intentTargetId == -1 && navController.currentDestination?.id == R.id.loadingFragment) {
|
/*if (intentTargetId == -1 && navController.currentDestination?.id == R.id.loadingFragment) {
|
||||||
@ -702,9 +749,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
app.profile == null || app.profile.id == -1 -> {
|
app.profile.id == 0 -> {
|
||||||
if (intentProfileId == -1)
|
if (intentProfileId == -1)
|
||||||
intentProfileId = app.appSharedPrefs.getInt("current_profile_id", 1)
|
intentProfileId = app.config.lastProfileId
|
||||||
loadProfile(intentProfileId, intentTargetId, extras)
|
loadProfile(intentProfileId, intentTargetId, extras)
|
||||||
}
|
}
|
||||||
intentProfileId != -1 -> {
|
intentProfileId != -1 -> {
|
||||||
@ -743,7 +790,16 @@ class MainActivity : AppCompatActivity() {
|
|||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
d(TAG, "Activity started")
|
||||||
|
super.onStart()
|
||||||
|
}
|
||||||
|
override fun onStop() {
|
||||||
|
d(TAG, "Activity stopped")
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
d(TAG, "Activity resumed")
|
||||||
val filter = IntentFilter()
|
val filter = IntentFilter()
|
||||||
filter.addAction(Intent.ACTION_MAIN)
|
filter.addAction(Intent.ACTION_MAIN)
|
||||||
registerReceiver(intentReceiver, filter)
|
registerReceiver(intentReceiver, filter)
|
||||||
@ -751,10 +807,15 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
d(TAG, "Activity paused")
|
||||||
unregisterReceiver(intentReceiver)
|
unregisterReceiver(intentReceiver)
|
||||||
EventBus.getDefault().unregister(this)
|
EventBus.getDefault().unregister(this)
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
override fun onDestroy() {
|
||||||
|
d(TAG, "Activity destroyed")
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
@ -768,15 +829,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
if (requestCode == REQUEST_LOGIN_ACTIVITY) {
|
if (requestCode == REQUEST_LOGIN_ACTIVITY) {
|
||||||
if (resultCode == Activity.RESULT_CANCELED && false) {
|
if (!app.config.loginFinished)
|
||||||
finish()
|
finish()
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
if (!app.config.loginFinished)
|
handleIntent(data?.extras)
|
||||||
finish()
|
|
||||||
else {
|
|
||||||
handleIntent(data?.extras)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -797,34 +853,23 @@ 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)")
|
if (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)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
AsyncTask.execute {
|
app.profileLoad(id) {
|
||||||
app.profileLoadById(id)
|
|
||||||
MessagesFragment.pageSelection = -1
|
MessagesFragment.pageSelection = -1
|
||||||
MessagesListFragment.tapPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
MessagesListFragment.tapPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
||||||
MessagesListFragment.topPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
MessagesListFragment.topPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
||||||
MessagesListFragment.bottomPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
MessagesListFragment.bottomPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION)
|
||||||
|
|
||||||
this.runOnUiThread {
|
setDrawerItems()
|
||||||
if (app.profile == null) {
|
// the drawer profile is updated automatically when the drawer item is clicked
|
||||||
if (app.config.loginFinished) {
|
// update it manually when switching profiles from other source
|
||||||
// this shouldn't run
|
//if (drawer.currentProfile != app.profile.id)
|
||||||
profileListEmptyListener()
|
drawer.currentProfile = app.profileId
|
||||||
}
|
loadTarget(drawerSelection, arguments)
|
||||||
} else {
|
|
||||||
setDrawerItems()
|
|
||||||
// the drawer profile is updated automatically when the drawer item is clicked
|
|
||||||
// update it manually when switching profiles from other source
|
|
||||||
//if (drawer.currentProfile != app.profile.id)
|
|
||||||
drawer.currentProfile = app.profile.id
|
|
||||||
loadTarget(drawerSelection, arguments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun loadTarget(id: Int, arguments: Bundle? = null) {
|
fun loadTarget(id: Int, arguments: Bundle? = null) {
|
||||||
@ -969,7 +1014,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
* that something has changed in the bottom sheet.
|
* that something has changed in the bottom sheet.
|
||||||
*/
|
*/
|
||||||
fun gainAttention() {
|
fun gainAttention() {
|
||||||
if (app.config.ui.bottomSheetOpened || true)
|
if (app.config.ui.bottomSheetOpened)
|
||||||
return
|
return
|
||||||
b.navView.postDelayed({
|
b.navView.postDelayed({
|
||||||
navView.gainAttentionOnBottomBar()
|
navView.gainAttentionOnBottomBar()
|
||||||
@ -1018,12 +1063,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setDrawerItems() {
|
fun setDrawerItems() {
|
||||||
d("NavDebug", "setDrawerItems() app.profile = ${app.profile ?: "null"}")
|
d("NavDebug", "setDrawerItems() app.profile = ${app.profile}")
|
||||||
val drawerItems = arrayListOf<IDrawerItem<*>>()
|
val drawerItems = arrayListOf<IDrawerItem<*>>()
|
||||||
val drawerProfiles = arrayListOf<ProfileSettingDrawerItem>()
|
val drawerProfiles = arrayListOf<ProfileSettingDrawerItem>()
|
||||||
|
|
||||||
val supportedFragments = if (app.profile == null) arrayListOf<Int>()
|
val supportedFragments = app.profile.supportedFragments
|
||||||
else app.profile.supportedFragments
|
|
||||||
|
|
||||||
targetPopToHomeList.clear()
|
targetPopToHomeList.clear()
|
||||||
|
|
||||||
@ -1087,7 +1131,7 @@ 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) {
|
if (App.config.ui.openDrawerOnBackPressed) {
|
||||||
b.navView.drawer.toggle()
|
b.navView.drawer.toggle()
|
||||||
} else {
|
} else {
|
||||||
navigateUp()
|
navigateUp()
|
||||||
|
@ -1,350 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik;
|
|
||||||
|
|
||||||
import android.app.IntentService;
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationChannel;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
|
||||||
|
|
||||||
import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
|
|
||||||
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
|
|
||||||
|
|
||||||
public class Notifier {
|
|
||||||
|
|
||||||
private static final String TAG = "Notifier";
|
|
||||||
public static final int ID_GET_DATA = 1337000;
|
|
||||||
public static final int ID_GET_DATA_ERROR = 1337001;
|
|
||||||
private static String CHANNEL_GET_DATA_NAME;
|
|
||||||
private static String CHANNEL_GET_DATA_DESC;
|
|
||||||
private static final String GROUP_KEY_GET_DATA = "pl.szczodrzynski.edziennik.GET_DATA";
|
|
||||||
|
|
||||||
public static final int ID_NOTIFICATIONS = 1337002;
|
|
||||||
public static String CHANNEL_NOTIFICATIONS_NAME;
|
|
||||||
public static String CHANNEL_NOTIFICATIONS_DESC;
|
|
||||||
public static final String GROUP_KEY_NOTIFICATIONS = "pl.szczodrzynski.edziennik.NOTIFICATIONS";
|
|
||||||
|
|
||||||
public static final int ID_NOTIFICATIONS_QUIET = 1337002;
|
|
||||||
public static String CHANNEL_NOTIFICATIONS_QUIET_NAME;
|
|
||||||
public static String CHANNEL_NOTIFICATIONS_QUIET_DESC;
|
|
||||||
public static final String GROUP_KEY_NOTIFICATIONS_QUIET = "pl.szczodrzynski.edziennik.NOTIFICATIONS_QUIET";
|
|
||||||
|
|
||||||
private static final int ID_UPDATES = 1337003;
|
|
||||||
private static String CHANNEL_UPDATES_NAME;
|
|
||||||
private static String CHANNEL_UPDATES_DESC;
|
|
||||||
private static final String GROUP_KEY_UPDATES = "pl.szczodrzynski.edziennik.UPDATES";
|
|
||||||
|
|
||||||
private App app;
|
|
||||||
public NotificationManager notificationManager;
|
|
||||||
private NotificationCompat.Builder getDataNotificationBuilder;
|
|
||||||
public int notificationColor;
|
|
||||||
|
|
||||||
Notifier(App _app) {
|
|
||||||
this.app = _app;
|
|
||||||
|
|
||||||
CHANNEL_GET_DATA_NAME = app.getString(R.string.notification_channel_get_data_name);
|
|
||||||
CHANNEL_GET_DATA_DESC = app.getString(R.string.notification_channel_get_data_desc);
|
|
||||||
CHANNEL_NOTIFICATIONS_NAME = app.getString(R.string.notification_channel_notifications_name);
|
|
||||||
CHANNEL_NOTIFICATIONS_DESC = app.getString(R.string.notification_channel_notifications_desc);
|
|
||||||
CHANNEL_NOTIFICATIONS_QUIET_NAME = app.getString(R.string.notification_channel_notifications_quiet_name);
|
|
||||||
CHANNEL_NOTIFICATIONS_QUIET_DESC = app.getString(R.string.notification_channel_notifications_quiet_desc);
|
|
||||||
CHANNEL_UPDATES_NAME = app.getString(R.string.notification_channel_updates_name);
|
|
||||||
CHANNEL_UPDATES_DESC = app.getString(R.string.notification_channel_updates_desc);
|
|
||||||
|
|
||||||
notificationColor = ContextCompat.getColor(app.getContext(), R.color.colorPrimary);
|
|
||||||
notificationManager = (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
NotificationChannel channelGetData = new NotificationChannel(GROUP_KEY_GET_DATA, CHANNEL_GET_DATA_NAME, NotificationManager.IMPORTANCE_MIN);
|
|
||||||
channelGetData.setDescription(CHANNEL_GET_DATA_DESC);
|
|
||||||
notificationManager.createNotificationChannel(channelGetData);
|
|
||||||
|
|
||||||
NotificationChannel channelNotifications = new NotificationChannel(GROUP_KEY_NOTIFICATIONS, CHANNEL_NOTIFICATIONS_NAME, NotificationManager.IMPORTANCE_HIGH);
|
|
||||||
channelNotifications.setDescription(CHANNEL_NOTIFICATIONS_DESC);
|
|
||||||
channelNotifications.enableLights(true);
|
|
||||||
channelNotifications.setLightColor(notificationColor);
|
|
||||||
notificationManager.createNotificationChannel(channelNotifications);
|
|
||||||
|
|
||||||
NotificationChannel channelNotificationsQuiet = new NotificationChannel(GROUP_KEY_NOTIFICATIONS_QUIET, CHANNEL_NOTIFICATIONS_QUIET_NAME, NotificationManager.IMPORTANCE_DEFAULT);
|
|
||||||
channelNotificationsQuiet.setDescription(CHANNEL_NOTIFICATIONS_QUIET_DESC);
|
|
||||||
channelNotificationsQuiet.setSound(null, null);
|
|
||||||
channelNotificationsQuiet.enableVibration(false);
|
|
||||||
notificationManager.createNotificationChannel(channelNotificationsQuiet);
|
|
||||||
|
|
||||||
NotificationChannel channelUpdates = new NotificationChannel(GROUP_KEY_UPDATES, CHANNEL_UPDATES_NAME, NotificationManager.IMPORTANCE_HIGH);
|
|
||||||
channelUpdates.setDescription(CHANNEL_UPDATES_DESC);
|
|
||||||
notificationManager.createNotificationChannel(channelUpdates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldBeQuiet() {
|
|
||||||
long now = Time.getNow().getInMillis();
|
|
||||||
long start = app.config.getSync().getQuietHoursStart();
|
|
||||||
long end = app.config.getSync().getQuietHoursEnd();
|
|
||||||
if (start > end) {
|
|
||||||
end += 1000 * 60 * 60 * 24;
|
|
||||||
//Log.d(TAG, "Night passing");
|
|
||||||
}
|
|
||||||
if (start > now) {
|
|
||||||
now += 1000 * 60 * 60 * 24;
|
|
||||||
//Log.d(TAG, "Now is smaller");
|
|
||||||
}
|
|
||||||
//Log.d(TAG, "Start is "+start+", now is "+now+", end is "+end);
|
|
||||||
return start > 0 && now >= start && now <= end;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNotificationDefaults() {
|
|
||||||
return (shouldBeQuiet() ? 0 : Notification.DEFAULT_ALL);
|
|
||||||
}
|
|
||||||
public String getNotificationGroup() {
|
|
||||||
return shouldBeQuiet() ? GROUP_KEY_NOTIFICATIONS_QUIET : GROUP_KEY_NOTIFICATIONS;
|
|
||||||
}
|
|
||||||
public int getNotificationPriority() {
|
|
||||||
return shouldBeQuiet() ? PRIORITY_DEFAULT : PRIORITY_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _____ _ _____ _
|
|
||||||
| __ \ | | / ____| | |
|
|
||||||
| | | | __ _| |_ __ _ | | __ ___| |_
|
|
||||||
| | | |/ _` | __/ _` | | | |_ |/ _ \ __|
|
|
||||||
| |__| | (_| | || (_| | | |__| | __/ |_
|
|
||||||
|_____/ \__,_|\__\__,_| \_____|\___|\_*/
|
|
||||||
public Notification notificationGetDataShow(int maxProgress) {
|
|
||||||
/*Intent notificationIntent = new Intent(app.getContext(), SyncService.class);
|
|
||||||
notificationIntent.setAction(ACTION_CANCEL);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);*/
|
|
||||||
|
|
||||||
getDataNotificationBuilder = new NotificationCompat.Builder(app, GROUP_KEY_GET_DATA)
|
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
|
||||||
.setColor(notificationColor)
|
|
||||||
.setContentTitle(app.getString(R.string.notification_get_data_title))
|
|
||||||
.setContentText(app.getString(R.string.notification_get_data_text))
|
|
||||||
//.addAction(R.drawable.ic_notification, app.getString(R.string.notification_get_data_cancel), pendingIntent)
|
|
||||||
//.setGroup(GROUP_KEY_GET_DATA)
|
|
||||||
.setOngoing(true)
|
|
||||||
.setProgress(maxProgress, 0, false)
|
|
||||||
.setTicker(app.getString(R.string.notification_get_data_summary))
|
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW);
|
|
||||||
return getDataNotificationBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification notificationGetDataProgress(int progress, int maxProgress) {
|
|
||||||
getDataNotificationBuilder.setProgress(maxProgress, progress, false);
|
|
||||||
return getDataNotificationBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification notificationGetDataAction(int stringResId) {
|
|
||||||
getDataNotificationBuilder.setContentTitle(app.getString(R.string.sync_action_format, app.getString(stringResId)));
|
|
||||||
return getDataNotificationBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification notificationGetDataProfile(String profileName) {
|
|
||||||
getDataNotificationBuilder.setContentText(profileName);
|
|
||||||
return getDataNotificationBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification notificationGetDataError(String profileName, String error, int failedProfileId) {
|
|
||||||
Intent notificationIntent = new Intent(app.getContext(), Notifier.GetDataRetryService.class);
|
|
||||||
notificationIntent.putExtra("failedProfileId", failedProfileId);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
|
||||||
|
|
||||||
getDataNotificationBuilder.mActions.clear();
|
|
||||||
/*try {
|
|
||||||
//Use reflection clean up old actions
|
|
||||||
Field f = getDataNotificationBuilder.getClass().getDeclaredField("mActions");
|
|
||||||
f.setAccessible(true);
|
|
||||||
f.set(getDataNotificationBuilder, new ArrayList<NotificationCompat.Action>());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
getDataNotificationBuilder.setProgress(0, 0, false)
|
|
||||||
.setTicker(app.getString(R.string.notification_get_data_error_summary))
|
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_warning)
|
|
||||||
.addAction(R.drawable.ic_notification, app.getString(R.string.notification_get_data_once_again), pendingIntent)
|
|
||||||
.setContentTitle(app.getString(R.string.notification_get_data_error_title, profileName))
|
|
||||||
.setContentText(error)
|
|
||||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(error))
|
|
||||||
.setOngoing(false);
|
|
||||||
return getDataNotificationBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notificationPost(int id, Notification notification) {
|
|
||||||
notificationManager.notify(id, notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notificationCancel(int id) {
|
|
||||||
notificationManager.cancel(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//public void notificationGetDataHide() {
|
|
||||||
// notificationManager.cancel(ID_GET_DATA);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static class GetDataRetryService extends IntentService {
|
|
||||||
private static final String TAG = "Notifier/GetDataRetry";
|
|
||||||
|
|
||||||
public GetDataRetryService() {
|
|
||||||
super(Notifier.GetDataRetryService.class.getSimpleName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onHandleIntent(Intent intent) {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _ _ _ _ __ _ _ _
|
|
||||||
| \ | | | | (_)/ _(_) | | (_)
|
|
||||||
| \| | ___ | |_ _| |_ _ ___ __ _| |_ _ ___ _ __
|
|
||||||
| . ` |/ _ \| __| | _| |/ __/ _` | __| |/ _ \| '_ \
|
|
||||||
| |\ | (_) | |_| | | | | (_| (_| | |_| | (_) | | | |
|
|
||||||
|_| \_|\___/ \__|_|_| |_|\___\__,_|\__|_|\___/|_| |*/
|
|
||||||
public void add(pl.szczodrzynski.edziennik.utils.models.Notification notification) {
|
|
||||||
app.appConfig.notifications.add(notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postAll() {
|
|
||||||
Collections.sort(app.appConfig.notifications, (o1, o2) -> (o2.addedDate - o1.addedDate > 0) ? 1 : (o2.addedDate - o1.addedDate < 0) ? -1 : 0);
|
|
||||||
|
|
||||||
if (app.appConfig.notifications.size() > 40) {
|
|
||||||
app.appConfig.notifications.subList(40, app.appConfig.notifications.size() - 1).clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int unreadCount = 0;
|
|
||||||
List<pl.szczodrzynski.edziennik.utils.models.Notification> notificationList = new ArrayList<>();
|
|
||||||
for (pl.szczodrzynski.edziennik.utils.models.Notification notification: app.appConfig.notifications) {
|
|
||||||
if (!notification.notified) {
|
|
||||||
notification.seen = false;
|
|
||||||
notification.notified = true;
|
|
||||||
unreadCount++;
|
|
||||||
if (notificationList.size() < 10) {
|
|
||||||
notificationList.add(notification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
notification.seen = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pl.szczodrzynski.edziennik.utils.models.Notification notification: notificationList) {
|
|
||||||
Intent intent = new Intent(app, MainActivity.class);
|
|
||||||
notification.fillIntent(intent);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(app, notification.id, intent, 0);
|
|
||||||
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(app, getNotificationGroup())
|
|
||||||
// title, text, type, date
|
|
||||||
.setContentTitle(notification.title)
|
|
||||||
.setContentText(notification.text)
|
|
||||||
.setSubText(pl.szczodrzynski.edziennik.utils.models.Notification.stringType(app, notification.type))
|
|
||||||
.setWhen(notification.addedDate)
|
|
||||||
.setTicker(app.getString(R.string.notification_ticker_format, pl.szczodrzynski.edziennik.utils.models.Notification.stringType(app, notification.type)))
|
|
||||||
// icon, color, lights, priority
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
|
||||||
.setColor(notificationColor)
|
|
||||||
.setLights(0xFF00FFFF, 2000, 2000)
|
|
||||||
.setPriority(getNotificationPriority())
|
|
||||||
// channel, group, style
|
|
||||||
.setChannelId(getNotificationGroup())
|
|
||||||
.setGroup(getNotificationGroup())
|
|
||||||
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
|
|
||||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(notification.text))
|
|
||||||
// intent, auto cancel
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setAutoCancel(true);
|
|
||||||
if (!shouldBeQuiet()) {
|
|
||||||
notificationBuilder.setDefaults(getNotificationDefaults());
|
|
||||||
}
|
|
||||||
notificationManager.notify(notification.id, notificationBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notificationList.size() > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
Intent intent = new Intent(app, MainActivity.class);
|
|
||||||
intent.setAction("android.intent.action.MAIN");
|
|
||||||
intent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_NOTIFICATIONS);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(app, ID_NOTIFICATIONS,
|
|
||||||
intent, 0);
|
|
||||||
|
|
||||||
NotificationCompat.Builder groupBuilder =
|
|
||||||
new NotificationCompat.Builder(app, getNotificationGroup())
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
|
||||||
.setColor(notificationColor)
|
|
||||||
.setContentTitle(app.getString(R.string.notification_new_notification_title_format, unreadCount))
|
|
||||||
.setGroupSummary(true)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
.setChannelId(getNotificationGroup())
|
|
||||||
.setGroup(getNotificationGroup())
|
|
||||||
.setLights(0xFF00FFFF, 2000, 2000)
|
|
||||||
.setPriority(getNotificationPriority())
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setStyle(new NotificationCompat.BigTextStyle());
|
|
||||||
if (!shouldBeQuiet()) {
|
|
||||||
groupBuilder.setDefaults(getNotificationDefaults());
|
|
||||||
}
|
|
||||||
notificationManager.notify(ID_NOTIFICATIONS, groupBuilder.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _ _ _ _
|
|
||||||
| | | | | | | |
|
|
||||||
| | | |_ __ __| | __ _| |_ ___ ___
|
|
||||||
| | | | '_ \ / _` |/ _` | __/ _ \/ __|
|
|
||||||
| |__| | |_) | (_| | (_| | || __/\__ \
|
|
||||||
\____/| .__/ \__,_|\__,_|\__\___||___/
|
|
||||||
| |
|
|
||||||
|*/
|
|
||||||
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename, boolean updateDirect) {
|
|
||||||
if (!app.config.getSync().getNotifyAboutUpdates())
|
|
||||||
return;
|
|
||||||
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
|
||||||
.putExtra("update_version", updateVersion)
|
|
||||||
.putExtra("update_url", updateUrl)
|
|
||||||
.putExtra("update_filename", updateFilename)
|
|
||||||
.putExtra("update_direct", updateDirect);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
|
||||||
|
|
||||||
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(app, GROUP_KEY_UPDATES)
|
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
|
||||||
.setColor(notificationColor)
|
|
||||||
.setContentTitle(app.getString(R.string.notification_updates_title))
|
|
||||||
.setContentText(app.getString(R.string.notification_updates_text, updateVersion))
|
|
||||||
.setLights(0xFF00FFFF, 2000, 2000)
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setTicker(app.getString(R.string.notification_updates_summary))
|
|
||||||
.setPriority(PRIORITY_MAX)
|
|
||||||
.setAutoCancel(true);
|
|
||||||
if (!shouldBeQuiet()) {
|
|
||||||
notificationBuilder.setDefaults(getNotificationDefaults());
|
|
||||||
}
|
|
||||||
notificationManager.notify(ID_UPDATES, notificationBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notificationUpdatesHide() {
|
|
||||||
if (!app.config.getSync().getNotifyAboutUpdates())
|
|
||||||
return;
|
|
||||||
notificationManager.cancel(ID_UPDATES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dump() {
|
|
||||||
for (pl.szczodrzynski.edziennik.utils.models.Notification notification: app.appConfig.notifications) {
|
|
||||||
Log.d(TAG, "Profile"+notification.profileId+" Notification from "+ Date.fromMillis(notification.addedDate).getFormattedString()+" "+ Time.fromMillis(notification.addedDate).getStringHMS()+" - "+notification.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,12 +16,13 @@ import pl.szczodrzynski.edziennik.config.utils.ConfigMigration
|
|||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
||||||
companion object {
|
companion object {
|
||||||
const val DATA_VERSION = 2
|
const val DATA_VERSION = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
private val job = Job()
|
private val job = Job()
|
||||||
@ -40,6 +41,25 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
|||||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
||||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
set(value) { set("dataVersion", value); mDataVersion = value }
|
||||||
|
|
||||||
|
private var mHash: String? = null
|
||||||
|
var hash: String
|
||||||
|
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" }
|
||||||
|
set(value) { set("hash", value); mHash = value }
|
||||||
|
|
||||||
|
private var mLastProfileId: Int? = null
|
||||||
|
var lastProfileId: Int
|
||||||
|
get() { mLastProfileId = mLastProfileId ?: values.get("lastProfileId", 0); return mLastProfileId ?: 0 }
|
||||||
|
set(value) { set("lastProfileId", value); mLastProfileId = value }
|
||||||
|
|
||||||
|
private var mUpdatesChannel: String? = null
|
||||||
|
var updatesChannel: String
|
||||||
|
get() { mUpdatesChannel = mUpdatesChannel ?: values.get("updatesChannel", "release"); return mUpdatesChannel ?: "release" }
|
||||||
|
set(value) { set("updatesChannel", value); mUpdatesChannel = value }
|
||||||
|
private var mUpdate: Update? = null
|
||||||
|
var update: Update?
|
||||||
|
get() { mUpdate = mUpdate ?: values.get("update", null as Update?); return mUpdate ?: null as Update? }
|
||||||
|
set(value) { set("update", value); mUpdate = value }
|
||||||
|
|
||||||
private var mAppVersion: Int? = null
|
private var mAppVersion: Int? = null
|
||||||
var appVersion: Int
|
var appVersion: Int
|
||||||
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE }
|
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE }
|
||||||
@ -90,11 +110,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
|||||||
ConfigMigration(app, this)
|
ConfigMigration(app, this)
|
||||||
}
|
}
|
||||||
fun getFor(profileId: Int): ProfileConfig {
|
fun getFor(profileId: Int): ProfileConfig {
|
||||||
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, rawEntries)
|
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, db.configDao().getAllNow(profileId)).also {
|
||||||
}
|
profileConfigs[profileId] = it
|
||||||
fun forProfile(): ProfileConfig {
|
}
|
||||||
return profileConfigs[App.profileId] ?: ProfileConfig(db, App.profileId, rawEntries)
|
|
||||||
}
|
}
|
||||||
|
fun forProfile() = getFor(App.profileId)
|
||||||
|
|
||||||
fun setProfile(profileId: Int) {
|
fun setProfile(profileId: Int) {
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ class ConfigGrades(private val config: Config) {
|
|||||||
|
|
||||||
private var mOrderBy: Int? = null
|
private var mOrderBy: Int? = null
|
||||||
var orderBy: Int
|
var orderBy: Int
|
||||||
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: 0 }
|
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: ORDER_BY_DATE_DESC }
|
||||||
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
|
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
|
||||||
}
|
}
|
@ -9,6 +9,11 @@ import pl.szczodrzynski.edziennik.config.utils.getIntList
|
|||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
|
||||||
class ConfigSync(private val config: Config) {
|
class ConfigSync(private val config: Config) {
|
||||||
|
private var mDontShowAppManagerDialog: Boolean? = null
|
||||||
|
var dontShowAppManagerDialog: Boolean
|
||||||
|
get() { mDontShowAppManagerDialog = mDontShowAppManagerDialog ?: config.values.get("dontShowAppManagerDialog", false); return mDontShowAppManagerDialog ?: false }
|
||||||
|
set(value) { config.set("dontShowAppManagerDialog", value); mDontShowAppManagerDialog = value }
|
||||||
|
|
||||||
private var mSyncEnabled: Boolean? = null
|
private var mSyncEnabled: Boolean? = null
|
||||||
var enabled: Boolean
|
var enabled: Boolean
|
||||||
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
||||||
|
@ -45,11 +45,6 @@ class ConfigUI(private val config: Config) {
|
|||||||
get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false }
|
get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false }
|
||||||
set(value) { config.set("openDrawerOnBackPressed", value); mOpenDrawerOnBackPressed = value }
|
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
|
private var mHomeCards: List<HomeCardModel>? = null
|
||||||
var homeCards: List<HomeCardModel>
|
var homeCards: List<HomeCardModel>
|
||||||
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
|
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
|
||||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.ProfileConfigMigration
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
||||||
@ -27,6 +28,7 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
|
|||||||
val values: HashMap<String, String?> = hashMapOf()
|
val values: HashMap<String, String?> = hashMapOf()
|
||||||
|
|
||||||
val grades by lazy { ProfileConfigGrades(this) }
|
val grades by lazy { ProfileConfigGrades(this) }
|
||||||
|
val ui by lazy { ProfileConfigUI(this) }
|
||||||
/*
|
/*
|
||||||
val sync by lazy { ConfigSync(this) }
|
val sync by lazy { ConfigSync(this) }
|
||||||
val timetable by lazy { ConfigTimetable(this) }
|
val timetable by lazy { ConfigTimetable(this) }
|
||||||
@ -37,10 +39,15 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
|
|||||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
||||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
set(value) { set("dataVersion", value); mDataVersion = value }
|
||||||
|
|
||||||
|
private var mHash: String? = null
|
||||||
|
var hash: String
|
||||||
|
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" }
|
||||||
|
set(value) { set("hash", value); mHash = value }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
rawEntries.toHashMap(profileId, values)
|
rawEntries.toHashMap(profileId, values)
|
||||||
/*if (dataVersion < DATA_VERSION)
|
if (dataVersion < DATA_VERSION)
|
||||||
ProfileConfigMigration(this)*/
|
ProfileConfigMigration(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun set(key: String, value: String?) {
|
override fun set(key: String, value: String?) {
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-19.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
||||||
|
|
||||||
|
class ProfileConfigUI(private val config: ProfileConfig) {
|
||||||
|
private var mAgendaViewType: Int? = null
|
||||||
|
var agendaViewType: Int
|
||||||
|
get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: AGENDA_DEFAULT }
|
||||||
|
set(value) { config.set("agendaViewType", value); mAgendaViewType = value }
|
||||||
|
}
|
@ -22,4 +22,7 @@ interface ConfigDao {
|
|||||||
|
|
||||||
@Query("SELECT * FROM config WHERE profileId = :profileId")
|
@Query("SELECT * FROM config WHERE profileId = :profileId")
|
||||||
fun getAllNow(profileId: Int): List<ConfigEntry>
|
fun getAllNow(profileId: Int): List<ConfigEntry>
|
||||||
|
|
||||||
|
@Query("DELETE FROM config WHERE profileId = :profileId")
|
||||||
|
fun clear(profileId: Int)
|
||||||
}
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-19.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config.utils
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import pl.szczodrzynski.edziennik.BuildConfig
|
||||||
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
|
import pl.szczodrzynski.edziennik.config.Config
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_VULCAN
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
|
class AppConfigMigrationV3(p: SharedPreferences, config: Config) {
|
||||||
|
init { config.apply {
|
||||||
|
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.registerSyncInterval", 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 }
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,9 @@ fun AbstractConfig.set(key: String, value: JsonElement?) {
|
|||||||
fun AbstractConfig.set(key: String, value: List<Any>?) {
|
fun AbstractConfig.set(key: String, value: List<Any>?) {
|
||||||
set(key, value?.let { gson.toJson(it) })
|
set(key, value?.let { gson.toJson(it) })
|
||||||
}
|
}
|
||||||
|
fun AbstractConfig.set(key: String, value: Any?) {
|
||||||
|
set(key, value?.let { gson.toJson(it) })
|
||||||
|
}
|
||||||
fun AbstractConfig.setStringList(key: String, value: List<String>?) {
|
fun AbstractConfig.setStringList(key: String, value: List<String>?) {
|
||||||
set(key, value?.let { gson.toJson(it) })
|
set(key, value?.let { gson.toJson(it) })
|
||||||
}
|
}
|
||||||
@ -74,6 +77,9 @@ fun HashMap<String, String?>.get(key: String, default: JsonObject?): JsonObject?
|
|||||||
fun HashMap<String, String?>.get(key: String, default: JsonArray?): JsonArray? {
|
fun HashMap<String, String?>.get(key: String, default: JsonArray?): JsonArray? {
|
||||||
return this[key]?.let { JsonParser().parse(it)?.asJsonArray } ?: default
|
return this[key]?.let { JsonParser().parse(it)?.asJsonArray } ?: default
|
||||||
}
|
}
|
||||||
|
inline fun <reified T> HashMap<String, String?>.get(key: String, default: T?): T? {
|
||||||
|
return this[key]?.let { Gson().fromJson(it, T::class.java) } ?: default
|
||||||
|
}
|
||||||
/* !!! cannot use mutable list here - modifying it will not update the DB */
|
/* !!! 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>? {
|
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
|
return this[key]?.let { ConfigGsonUtils().deserializeList<T>(gson, it, classOfT) } ?: default
|
||||||
|
@ -5,32 +5,32 @@
|
|||||||
package pl.szczodrzynski.edziennik.config.utils
|
package pl.szczodrzynski.edziennik.config.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
import pl.szczodrzynski.edziennik.BuildConfig
|
||||||
|
import pl.szczodrzynski.edziennik.HOUR
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
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.config.Config
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.config.ConfigGrades.Companion.ORDER_BY_DATE_DESC
|
||||||
|
|
||||||
class ConfigMigration(app: App, config: Config) {
|
class ConfigMigration(app: App, config: Config) {
|
||||||
init { config.apply {
|
init { config.apply {
|
||||||
val p = app.getSharedPreferences("pl.szczodrzynski.edziennik_profiles", Context.MODE_PRIVATE)
|
|
||||||
val s = "app.appConfig"
|
|
||||||
|
|
||||||
if (dataVersion < 1) {
|
val p = app.getSharedPreferences("pl.szczodrzynski.edziennik_profiles", Context.MODE_PRIVATE)
|
||||||
ui.theme = p.getString("$s.appTheme", null)?.toIntOrNull() ?: 1
|
if (p.contains("app.appConfig.appTheme")) {
|
||||||
sync.enabled = p.getString("$s.registerSyncEnabled", null)?.toBoolean() ?: true
|
// migrate appConfig from app version 3.x and lower.
|
||||||
sync.interval = p.getString("$s.registerSyncEnabled", null)?.toIntOrNull() ?: 3600
|
// Updates dataVersion to level 2.
|
||||||
val oldButtons = p.getString("$s.miniDrawerButtonIds", null)?.let { str ->
|
AppConfigMigrationV3(p, config)
|
||||||
str.replace("[\\[\\]]*".toRegex(), "")
|
}
|
||||||
.split(",\\s?".toRegex())
|
|
||||||
.mapNotNull { it.toIntOrNull() }
|
if (dataVersion < 2) {
|
||||||
}
|
appVersion = BuildConfig.VERSION_CODE
|
||||||
ui.miniMenuButtons = oldButtons ?: listOf(
|
loginFinished = false
|
||||||
|
ui.language = null
|
||||||
|
ui.theme = 1
|
||||||
|
ui.appBackground = null
|
||||||
|
ui.headerBackground = null
|
||||||
|
ui.miniMenuVisible = false
|
||||||
|
ui.miniMenuButtons = listOf(
|
||||||
MainActivity.DRAWER_ITEM_HOME,
|
MainActivity.DRAWER_ITEM_HOME,
|
||||||
MainActivity.DRAWER_ITEM_TIMETABLE,
|
MainActivity.DRAWER_ITEM_TIMETABLE,
|
||||||
MainActivity.DRAWER_ITEM_AGENDA,
|
MainActivity.DRAWER_ITEM_AGENDA,
|
||||||
@ -39,46 +39,36 @@ class ConfigMigration(app: App, config: Config) {
|
|||||||
MainActivity.DRAWER_ITEM_HOMEWORK,
|
MainActivity.DRAWER_ITEM_HOMEWORK,
|
||||||
MainActivity.DRAWER_ITEM_SETTINGS
|
MainActivity.DRAWER_ITEM_SETTINGS
|
||||||
)
|
)
|
||||||
dataVersion = 1
|
sync.enabled = true
|
||||||
}
|
sync.interval = 1*HOUR.toInt()
|
||||||
if (dataVersion < 2) {
|
sync.notifyAboutUpdates = true
|
||||||
devModePassword = p.getString("$s.devModePassword", null).fix()
|
sync.onlyWifi = false
|
||||||
sync.tokenApp = p.getString("$s.fcmToken", null).fix()
|
sync.quietHoursStart = 0
|
||||||
timetable.bellSyncMultiplier = p.getString("$s.bellSyncMultiplier", null)?.toIntOrNull() ?: 0
|
sync.quietHoursEnd = 0
|
||||||
sync.quietHoursStart = p.getString("$s.quietHoursStart", null)?.toLongOrNull() ?: 0
|
sync.quietDuringLessons = false
|
||||||
appRateSnackbarTime = p.getString("$s.appRateSnackbarTime", null)?.toLongOrNull() ?: 0
|
sync.tokenApp = null
|
||||||
sync.quietHoursEnd = p.getString("$s.quietHoursEnd", null)?.toLongOrNull() ?: 0
|
sync.tokenMobidziennik = null
|
||||||
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.tokenMobidziennikList = listOf()
|
||||||
sync.tokenVulcanList = listOf()
|
sync.tokenLibrus = null
|
||||||
sync.tokenLibrusList = 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) }
|
sync.tokenVulcan = null
|
||||||
tokens?.forEach {
|
sync.tokenVulcanList = listOf()
|
||||||
val token = it.value.first
|
timetable.bellSyncMultiplier = 0
|
||||||
when (it.key) {
|
timetable.bellSyncDiff = null
|
||||||
LOGIN_TYPE_MOBIDZIENNIK -> sync.tokenMobidziennik = token
|
timetable.countInSeconds = false
|
||||||
LOGIN_TYPE_VULCAN -> sync.tokenVulcan = token
|
grades.orderBy = ORDER_BY_DATE_DESC
|
||||||
LOGIN_TYPE_LIBRUS -> sync.tokenLibrus = token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dataVersion = 2
|
dataVersion = 2
|
||||||
}
|
}
|
||||||
}}
|
|
||||||
|
|
||||||
private fun String?.fix(): String? {
|
if (dataVersion < 10) {
|
||||||
return this?.replace("\"", "")?.let { if (it == "null") null else it }
|
ui.openDrawerOnBackPressed = false
|
||||||
}
|
ui.homeCards = listOf()
|
||||||
|
ui.snowfall = false
|
||||||
|
ui.bottomSheetOpened = false
|
||||||
|
sync.dontShowAppManagerDialog = false
|
||||||
|
|
||||||
|
dataVersion = 10
|
||||||
|
}
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,21 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
package pl.szczodrzynski.edziennik.config.utils
|
||||||
|
|
||||||
import android.content.Context
|
import pl.szczodrzynski.edziennik.config.ProfileConfig
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
||||||
import pl.szczodrzynski.edziennik.config.Config
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.COLOR_MODE_WEIGHTED
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.YEAR_ALL_GRADES
|
||||||
|
|
||||||
class ProfileConfigMigration(app: App, config: Config) {
|
class ProfileConfigMigration(config: ProfileConfig) {
|
||||||
init { config.apply {
|
init { config.apply {
|
||||||
val p = app.getSharedPreferences("pl.szczodrzynski.edziennik_profiles", Context.MODE_PRIVATE)
|
|
||||||
val s = "app.appConfig"
|
|
||||||
|
|
||||||
if (dataVersion < 1) {
|
if (dataVersion < 1) {
|
||||||
|
grades.colorMode = COLOR_MODE_WEIGHTED
|
||||||
|
grades.countZeroToAvg = true
|
||||||
|
grades.yearAverageMode = YEAR_ALL_GRADES
|
||||||
|
ui.agendaViewType = AGENDA_DEFAULT
|
||||||
|
|
||||||
//dataVersion = 1
|
dataVersion = 1
|
||||||
}
|
|
||||||
if (dataVersion < 2) {
|
|
||||||
//gradesColorMode do profilu !
|
|
||||||
//agendaViewType do profilu !
|
|
||||||
// app.appConfig.dontCountZeroToAverage do profilu !
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
@ -12,12 +12,15 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.*
|
import pl.szczodrzynski.edziennik.data.api.events.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.requests.ServiceCloseRequest
|
import pl.szczodrzynski.edziennik.data.api.events.requests.ServiceCloseRequest
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.requests.TaskCancelRequest
|
import pl.szczodrzynski.edziennik.data.api.events.requests.TaskCancelRequest
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.api.task.*
|
import pl.szczodrzynski.edziennik.data.api.task.ErrorReportTask
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.task.SzkolnyTask
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@ -26,7 +29,7 @@ import kotlin.math.roundToInt
|
|||||||
class ApiService : Service() {
|
class ApiService : Service() {
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "ApiService"
|
const val TAG = "ApiService"
|
||||||
const val NOTIFICATION_API_CHANNEL_ID = "pl.szczodrzynski.edziennik.GET_DATA"
|
const val NOTIFICATION_API_CHANNEL_ID = "pl.szczodrzynski.edziennik.SYNC"
|
||||||
fun start(context: Context) {
|
fun start(context: Context) {
|
||||||
context.startService(Intent(context, ApiService::class.java))
|
context.startService(Intent(context, ApiService::class.java))
|
||||||
}
|
}
|
||||||
@ -40,15 +43,13 @@ class ApiService : Service() {
|
|||||||
|
|
||||||
private val syncingProfiles = mutableListOf<Profile>()
|
private val syncingProfiles = mutableListOf<Profile>()
|
||||||
|
|
||||||
private val finishingTaskQueue = mutableListOf(
|
private var szkolnyTaskFinished = false
|
||||||
SzkolnyTask.sync(syncingProfiles),
|
private val allTaskRequestList = mutableListOf<Any>()
|
||||||
NotifyTask()
|
|
||||||
)
|
|
||||||
private val allTaskList = mutableListOf<IApiTask>()
|
|
||||||
private val taskQueue = mutableListOf<IApiTask>()
|
private val taskQueue = mutableListOf<IApiTask>()
|
||||||
private val errorList = mutableListOf<ApiError>()
|
private val errorList = mutableListOf<ApiError>()
|
||||||
|
|
||||||
private var serviceClosed = false
|
private var serviceClosed = false
|
||||||
|
set(value) { field = value; notification.serviceClosed = value }
|
||||||
private var taskCancelled = false
|
private var taskCancelled = false
|
||||||
private var taskIsRunning = false
|
private var taskIsRunning = false
|
||||||
private var taskRunning: IApiTask? = null // for debug purposes
|
private var taskRunning: IApiTask? = null // for debug purposes
|
||||||
@ -59,7 +60,7 @@ class ApiService : Service() {
|
|||||||
private var taskProgress = -1f
|
private var taskProgress = -1f
|
||||||
private var taskProgressText: String? = null
|
private var taskProgressText: String? = null
|
||||||
|
|
||||||
private val notification by lazy { EdziennikNotification(this) }
|
private val notification by lazy { EdziennikNotification(app) }
|
||||||
|
|
||||||
private var lastEventTime = System.currentTimeMillis()
|
private var lastEventTime = System.currentTimeMillis()
|
||||||
private var taskCancelTries = 0
|
private var taskCancelTries = 0
|
||||||
@ -131,15 +132,20 @@ class ApiService : Service() {
|
|||||||
checkIfTaskFrozen()
|
checkIfTaskFrozen()
|
||||||
if (taskIsRunning)
|
if (taskIsRunning)
|
||||||
return
|
return
|
||||||
if (taskCancelled || serviceClosed || (taskQueue.isEmpty() && finishingTaskQueue.isEmpty())) {
|
if (taskCancelled || serviceClosed || (taskQueue.isEmpty() && szkolnyTaskFinished)) {
|
||||||
serviceClosed = false
|
|
||||||
allCompleted()
|
allCompleted()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lastEventTime = System.currentTimeMillis()
|
lastEventTime = System.currentTimeMillis()
|
||||||
|
|
||||||
val task = if (taskQueue.isEmpty()) finishingTaskQueue.removeAt(0) else taskQueue.removeAt(0)
|
val task = if (taskQueue.isNotEmpty()) {
|
||||||
|
taskQueue.removeAt(0)
|
||||||
|
} else {
|
||||||
|
szkolnyTaskFinished = true
|
||||||
|
SzkolnyTask(app, syncingProfiles)
|
||||||
|
}
|
||||||
|
|
||||||
task.taskId = ++taskMaximumId
|
task.taskId = ++taskMaximumId
|
||||||
task.prepare(app)
|
task.prepare(app)
|
||||||
taskIsRunning = true
|
taskIsRunning = true
|
||||||
@ -162,9 +168,8 @@ class ApiService : Service() {
|
|||||||
try {
|
try {
|
||||||
when (task) {
|
when (task) {
|
||||||
is EdziennikTask -> task.run(app, taskCallback)
|
is EdziennikTask -> task.run(app, taskCallback)
|
||||||
is NotifyTask -> task.run(app, taskCallback)
|
|
||||||
is ErrorReportTask -> task.run(app, taskCallback, notification, errorList)
|
is ErrorReportTask -> task.run(app, taskCallback, notification, errorList)
|
||||||
is SzkolnyTask -> task.run(app, taskCallback)
|
is SzkolnyTask -> task.run(taskCallback)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
taskCallback.onError(ApiError(TAG, EXCEPTION_API_TASK).withThrowable(e))
|
taskCallback.onError(ApiError(TAG, EXCEPTION_API_TASK).withThrowable(e))
|
||||||
@ -214,6 +219,7 @@ class ApiService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun allCompleted() {
|
private fun allCompleted() {
|
||||||
|
serviceClosed = true
|
||||||
EventBus.getDefault().postSticky(ApiTaskAllFinishedEvent())
|
EventBus.getDefault().postSticky(ApiTaskAllFinishedEvent())
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
@ -229,10 +235,12 @@ class ApiService : Service() {
|
|||||||
EventBus.getDefault().removeStickyEvent(task)
|
EventBus.getDefault().removeStickyEvent(task)
|
||||||
d(TAG, task.toString())
|
d(TAG, task.toString())
|
||||||
|
|
||||||
// fix for duplicated tasks, thank you EventBus
|
if (task is EdziennikTask) {
|
||||||
if (task in allTaskList)
|
// fix for duplicated tasks, thank you EventBus
|
||||||
return
|
if (task.request in allTaskRequestList)
|
||||||
allTaskList += task
|
return
|
||||||
|
allTaskRequestList += task.request
|
||||||
|
}
|
||||||
|
|
||||||
if (task is EdziennikTask) {
|
if (task is EdziennikTask) {
|
||||||
when (task.request) {
|
when (task.request) {
|
||||||
@ -293,11 +301,13 @@ class ApiService : Service() {
|
|||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
d(TAG, "Foreground service onStartCommand")
|
d(TAG, "Foreground service onStartCommand")
|
||||||
startForeground(EdziennikNotification.NOTIFICATION_ID, notification.notification)
|
startForeground(app.notifications.syncId, notification.notification)
|
||||||
return START_NOT_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
d(TAG, "Service destroyed")
|
||||||
|
serviceClosed = true
|
||||||
EventBus.getDefault().unregister(this)
|
EventBus.getDefault().unregister(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,209 +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.entity.Attendance
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notice
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_LUCKY_NUMBER
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_ANNOUNCEMENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_ATTENDANCE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_EVENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_GRADE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_MESSAGE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_NEW_NOTICE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_TIMETABLE_LESSON_CHANGE
|
|
||||||
import pl.szczodrzynski.edziennik.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
|
|
||||||
}
|
|
||||||
|
|
||||||
val today = Date.getToday()
|
|
||||||
val todayValue = today.value
|
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}}
|
|
||||||
}
|
|
@ -11,19 +11,16 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
class EdziennikNotification(val context: Context) {
|
class EdziennikNotification(val app: App) {
|
||||||
companion object {
|
private val notificationManager by lazy { app.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
||||||
const val NOTIFICATION_ID = 20191001
|
|
||||||
}
|
|
||||||
|
|
||||||
private val notificationManager by lazy { context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
|
||||||
|
|
||||||
private val notificationBuilder: NotificationCompat.Builder by lazy {
|
private val notificationBuilder: NotificationCompat.Builder by lazy {
|
||||||
NotificationCompat.Builder(context, ApiService.NOTIFICATION_API_CHANNEL_ID)
|
NotificationCompat.Builder(app, ApiService.NOTIFICATION_API_CHANNEL_ID)
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setPriority(PRIORITY_MIN)
|
.setPriority(PRIORITY_MIN)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
@ -35,39 +32,40 @@ class EdziennikNotification(val context: Context) {
|
|||||||
|
|
||||||
private var errorCount = 0
|
private var errorCount = 0
|
||||||
private var criticalErrorCount = 0
|
private var criticalErrorCount = 0
|
||||||
|
var serviceClosed = false
|
||||||
|
|
||||||
private fun cancelPendingIntent(taskId: Int): PendingIntent {
|
private fun cancelPendingIntent(taskId: Int): PendingIntent {
|
||||||
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
||||||
intent.putExtra("task", "TaskCancelRequest")
|
intent.putExtra("task", "TaskCancelRequest")
|
||||||
intent.putExtra("taskId", taskId)
|
intent.putExtra("taskId", taskId)
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
||||||
}
|
}
|
||||||
private val closePendingIntent: PendingIntent
|
private val closePendingIntent: PendingIntent
|
||||||
get() {
|
get() {
|
||||||
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
|
||||||
intent.putExtra("task", "ServiceCloseRequest")
|
intent.putExtra("task", "ServiceCloseRequest")
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun errorCountText(): String? {
|
private fun errorCountText(): String? {
|
||||||
var result = ""
|
var result = ""
|
||||||
if (criticalErrorCount > 0) {
|
if (criticalErrorCount > 0) {
|
||||||
result += context.resources.getQuantityString(R.plurals.critical_errors_format, criticalErrorCount, criticalErrorCount)
|
result += app.resources.getQuantityString(R.plurals.critical_errors_format, criticalErrorCount, criticalErrorCount)
|
||||||
}
|
}
|
||||||
if (criticalErrorCount > 0 && errorCount > 0) {
|
if (criticalErrorCount > 0 && errorCount > 0) {
|
||||||
result += ", "
|
result += ", "
|
||||||
}
|
}
|
||||||
if (errorCount > 0) {
|
if (errorCount > 0) {
|
||||||
result += context.resources.getQuantityString(R.plurals.normal_errors_format, errorCount, errorCount)
|
result += app.resources.getQuantityString(R.plurals.normal_errors_format, errorCount, errorCount)
|
||||||
}
|
}
|
||||||
return if (result.isEmpty()) null else result
|
return if (result.isEmpty()) null else result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setIdle(): EdziennikNotification {
|
fun setIdle(): EdziennikNotification {
|
||||||
notificationBuilder.setContentTitle(context.getString(R.string.edziennik_notification_api_title))
|
notificationBuilder.setContentTitle(app.getString(R.string.edziennik_notification_api_title))
|
||||||
notificationBuilder.setProgress(0, 0, false)
|
notificationBuilder.setProgress(0, 0, false)
|
||||||
notificationBuilder.apply {
|
notificationBuilder.apply {
|
||||||
val str = context.getString(R.string.edziennik_notification_api_text)
|
val str = app.getString(R.string.edziennik_notification_api_text)
|
||||||
setStyle(NotificationCompat.BigTextStyle().bigText(str))
|
setStyle(NotificationCompat.BigTextStyle().bigText(str))
|
||||||
setContentText(str)
|
setContentText(str)
|
||||||
}
|
}
|
||||||
@ -81,7 +79,7 @@ class EdziennikNotification(val context: Context) {
|
|||||||
}
|
}
|
||||||
fun setCriticalError(): EdziennikNotification {
|
fun setCriticalError(): EdziennikNotification {
|
||||||
criticalErrorCount++
|
criticalErrorCount++
|
||||||
notificationBuilder.setContentTitle(context.getString(R.string.edziennik_notification_api_error_title))
|
notificationBuilder.setContentTitle(app.getString(R.string.edziennik_notification_api_error_title))
|
||||||
notificationBuilder.setProgress(0, 0, false)
|
notificationBuilder.setProgress(0, 0, false)
|
||||||
notificationBuilder.apply {
|
notificationBuilder.apply {
|
||||||
val str = errorCountText()
|
val str = errorCountText()
|
||||||
@ -118,7 +116,7 @@ class EdziennikNotification(val context: Context) {
|
|||||||
notificationBuilder.addAction(
|
notificationBuilder.addAction(
|
||||||
NotificationCompat.Action(
|
NotificationCompat.Action(
|
||||||
R.drawable.ic_notification,
|
R.drawable.ic_notification,
|
||||||
context.getString(R.string.edziennik_notification_api_close),
|
app.getString(R.string.edziennik_notification_api_close),
|
||||||
closePendingIntent
|
closePendingIntent
|
||||||
))
|
))
|
||||||
return this
|
return this
|
||||||
@ -128,13 +126,15 @@ class EdziennikNotification(val context: Context) {
|
|||||||
notificationBuilder.addAction(
|
notificationBuilder.addAction(
|
||||||
NotificationCompat.Action(
|
NotificationCompat.Action(
|
||||||
R.drawable.ic_notification,
|
R.drawable.ic_notification,
|
||||||
context.getString(R.string.edziennik_notification_api_cancel),
|
app.getString(R.string.edziennik_notification_api_cancel),
|
||||||
cancelPendingIntent(taskId)
|
cancelPendingIntent(taskId)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun post() {
|
fun post() {
|
||||||
notificationManager.notify(NOTIFICATION_ID, notification)
|
if (serviceClosed)
|
||||||
|
return
|
||||||
|
notificationManager.notify(app.notifications.syncId, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,6 @@ fun Data.prepareFor(loginMethods: List<LoginMethod>, loginMethodId: Int) {
|
|||||||
possibleLoginMethods += it.loginMethodId
|
possibleLoginMethods += it.loginMethodId
|
||||||
}
|
}
|
||||||
|
|
||||||
targetEndpointIds.clear()
|
|
||||||
targetLoginMethodIds.clear()
|
targetLoginMethodIds.clear()
|
||||||
|
|
||||||
// check the login method for any dependencies
|
// check the login method for any dependencies
|
||||||
|
@ -51,6 +51,7 @@ const val ERROR_REQUEST_FAILURE_SSL_ERROR = 63
|
|||||||
const val ERROR_RESPONSE_EMPTY = 100
|
const val ERROR_RESPONSE_EMPTY = 100
|
||||||
const val ERROR_LOGIN_DATA_MISSING = 101
|
const val ERROR_LOGIN_DATA_MISSING = 101
|
||||||
const val ERROR_PROFILE_MISSING = 105
|
const val ERROR_PROFILE_MISSING = 105
|
||||||
|
const val ERROR_PROFILE_ARCHIVED = 106
|
||||||
const val ERROR_INVALID_LOGIN_MODE = 110
|
const val ERROR_INVALID_LOGIN_MODE = 110
|
||||||
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
||||||
const val ERROR_NOT_IMPLEMENTED = 112
|
const val ERROR_NOT_IMPLEMENTED = 112
|
||||||
@ -129,6 +130,8 @@ const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE = 216
|
|||||||
const val ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID = 213
|
const val ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID = 213
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
|
const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID = 215
|
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID = 215
|
||||||
|
const val ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN = 216
|
||||||
|
const val ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER = 217
|
||||||
|
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
|
const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
|
||||||
const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302
|
const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302
|
||||||
|
@ -41,6 +41,7 @@ internal const val FEATURE_PUSH_CONFIG = 120
|
|||||||
object Features {
|
object Features {
|
||||||
private fun getAllNecessary(): List<Int> = listOf(
|
private fun getAllNecessary(): List<Int> = listOf(
|
||||||
FEATURE_ALWAYS_NEEDED,
|
FEATURE_ALWAYS_NEEDED,
|
||||||
|
FEATURE_PUSH_CONFIG,
|
||||||
FEATURE_STUDENT_INFO,
|
FEATURE_STUDENT_INFO,
|
||||||
FEATURE_STUDENT_NUMBER,
|
FEATURE_STUDENT_NUMBER,
|
||||||
FEATURE_SCHOOL_INFO,
|
FEATURE_SCHOOL_INFO,
|
||||||
|
@ -11,6 +11,7 @@ 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.LibrusLoginMessages
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPortal
|
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.librus.login.LibrusLoginSynergia
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginApi2
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb
|
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.TemplateLoginApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
|
||||||
@ -86,11 +87,11 @@ const val LOGIN_METHOD_MOBIDZIENNIK_API2 = 300
|
|||||||
val mobidziennikLoginMethods = listOf(
|
val mobidziennikLoginMethods = listOf(
|
||||||
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_WEB, MobidziennikLoginWeb::class.java)
|
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_WEB, MobidziennikLoginWeb::class.java)
|
||||||
.withIsPossible { _, _ -> true }
|
.withIsPossible { _, _ -> true }
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }/*,
|
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_API2, MobidziennikLoginApi2::class.java)
|
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_API2, MobidziennikLoginApi2::class.java)
|
||||||
.withIsPossible { _, loginStore -> loginStore.hasLoginData("email") }
|
.withIsPossible { profile, _ -> profile?.getStudentData("email", null) != null }
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }*/
|
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }
|
||||||
)
|
)
|
||||||
|
|
||||||
const val LOGIN_TYPE_VULCAN = 4
|
const val LOGIN_TYPE_VULCAN = 4
|
||||||
|
@ -8,7 +8,7 @@ import kotlin.text.RegexOption.DOT_MATCHES_ALL
|
|||||||
|
|
||||||
object Regexes {
|
object Regexes {
|
||||||
val STYLE_CSS_COLOR by lazy {
|
val STYLE_CSS_COLOR by lazy {
|
||||||
"""color: \w+?;?"?""".toRegex()
|
"""color: (\w+);?""".toRegex()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -56,7 +56,11 @@ object Regexes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val MOBIDZIENNIK_MESSAGE_RECIPIENTS_JSON by lazy {
|
val MOBIDZIENNIK_MESSAGE_RECIPIENTS_JSON by lazy {
|
||||||
"""odbiorcy: (\[.+?\]),${'$'}""".toRegex(RegexOption.MULTILINE)
|
"""odbiorcy: (\[.+?]),${'$'}""".toRegex(RegexOption.MULTILINE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val MOBIDZIENNIK_ACCOUNT_EMAIL by lazy {
|
||||||
|
"""name="email" value="(.+?@.+?\..+?)"""".toRegex(DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,7 +78,7 @@ object Regexes {
|
|||||||
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
|
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
|
||||||
}
|
}
|
||||||
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy {
|
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy {
|
||||||
"""name="ctl00\\${'$'}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9]+)/([0-9]+)<""".toRegex(DOT_MATCHES_ALL)
|
"""name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9]+)/([0-9]+)<""".toRegex(DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
|
val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
|
||||||
"""<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(DOT_MATCHES_ALL)
|
"""<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(DOT_MATCHES_ALL)
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.task
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
@ -12,11 +16,13 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.template.Template
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.Vulcan
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.Vulcan
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
|
|
||||||
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
|
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
|
||||||
companion object {
|
companion object {
|
||||||
@ -57,6 +63,10 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
|||||||
private var edziennikInterface: EdziennikInterface? = null
|
private var edziennikInterface: EdziennikInterface? = null
|
||||||
|
|
||||||
internal fun run(app: App, taskCallback: EdziennikCallback) {
|
internal fun run(app: App, taskCallback: EdziennikCallback) {
|
||||||
|
if (profile?.archived == true) {
|
||||||
|
taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED))
|
||||||
|
return
|
||||||
|
}
|
||||||
edziennikInterface = when (loginStore.type) {
|
edziennikInterface = when (loginStore.type) {
|
||||||
LOGIN_TYPE_LIBRUS -> Librus(app, profile, loginStore, taskCallback)
|
LOGIN_TYPE_LIBRUS -> Librus(app, profile, loginStore, taskCallback)
|
||||||
LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback)
|
LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback)
|
@ -7,11 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
|
|||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
import pl.szczodrzynski.edziennik.data.api.models.Data
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Subject
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use http://patorjk.com/software/taag/#p=display&f=Big for the ascii art
|
* Use http://patorjk.com/software/taag/#p=display&f=Big for the ascii art
|
||||||
|
@ -15,12 +15,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.Edudzienn
|
|||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
@ -41,9 +41,7 @@ class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStor
|
|||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
data.saveData()
|
data.saveData()
|
||||||
data.notify {
|
callback.onCompleted()
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
/* _______ _ _ _ _ _
|
||||||
|
@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.*
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
open class EdudziennikWeb(open val data: DataEdudziennik) {
|
open class EdudziennikWeb(open val data: DataEdudziennik) {
|
||||||
companion object {
|
companion object {
|
||||||
@ -24,11 +25,11 @@ open class EdudziennikWeb(open val data: DataEdudziennik) {
|
|||||||
val profile
|
val profile
|
||||||
get() = data.profile
|
get() = data.profile
|
||||||
|
|
||||||
fun webGet(tag: String, endpoint: String, xhr: Boolean = false, onSuccess: (text: String) -> Unit) {
|
fun webGet(tag: String, endpoint: String, xhr: Boolean = false, semester: Int? = null, onSuccess: (text: String) -> Unit) {
|
||||||
val url = "https://dziennikel.appspot.com/" + when (endpoint.endsWith('/') || endpoint.contains('?') || endpoint.isEmpty()) {
|
val url = "https://dziennikel.appspot.com/" + when (endpoint.endsWith('/') || endpoint.contains('?') || endpoint.isEmpty()) {
|
||||||
true -> endpoint
|
true -> endpoint
|
||||||
else -> "$endpoint/"
|
else -> "$endpoint/"
|
||||||
}
|
} + (semester?.let { "?semester=" + if(it == -1) "all" else it } ?: "")
|
||||||
|
|
||||||
d(tag, "Request: Edudziennik/Web - $url")
|
d(tag, "Request: Edudziennik/Web - $url")
|
||||||
|
|
||||||
@ -40,6 +41,18 @@ open class EdudziennikWeb(open val data: DataEdudziennik) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (semester == null && url.contains("start")) {
|
||||||
|
profile?.also { profile ->
|
||||||
|
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com")
|
||||||
|
val semesterCookie = cookies.firstOrNull { it.name() == "semester" }?.value()?.toIntOrNull()
|
||||||
|
|
||||||
|
semesterCookie?.let { data.currentSemester = it }
|
||||||
|
|
||||||
|
if (semesterCookie == 2 && profile.dateSemester2Start > Date.getToday())
|
||||||
|
profile.dateSemester2Start = Date.getToday().stepForward(0, 0, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
onSuccess(text)
|
onSuccess(text)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -67,11 +80,6 @@ open class EdudziennikWeb(open val data: DataEdudziennik) {
|
|||||||
.name("sessionid")
|
.name("sessionid")
|
||||||
.value(data.webSessionId!!)
|
.value(data.webSessionId!!)
|
||||||
.domain("dziennikel.appspot.com")
|
.domain("dziennikel.appspot.com")
|
||||||
.secure().httpOnly().build(),
|
|
||||||
Cookie.Builder()
|
|
||||||
.name("semester")
|
|
||||||
.value((data.currentSemester).toString())
|
|
||||||
.domain("dziennikel.appspot.com")
|
|
||||||
.secure().httpOnly().build()
|
.secure().httpOnly().build()
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPES
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.singleOrNull
|
import pl.szczodrzynski.edziennik.singleOrNull
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
@ -26,7 +26,7 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
|||||||
}
|
}
|
||||||
|
|
||||||
init { data.profile?.also { profile ->
|
init { data.profile?.also { profile ->
|
||||||
webGet(TAG, data.studentEndpoint + "Presence") { text ->
|
webGet(TAG, data.studentEndpoint + "Presence", semester = -1) { text ->
|
||||||
|
|
||||||
val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
|
val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
|
||||||
val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
|
val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
|
||||||
@ -69,7 +69,7 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
|||||||
id,
|
id,
|
||||||
lesson?.displayTeacherId ?: -1,
|
lesson?.displayTeacherId ?: -1,
|
||||||
lesson?.displaySubjectId ?: -1,
|
lesson?.displaySubjectId ?: -1,
|
||||||
data.currentSemester,
|
profile.currentSemester,
|
||||||
name,
|
name,
|
||||||
date,
|
date,
|
||||||
lesson?.displayStartTime ?: startTime,
|
lesson?.displayStartTime ?: startTime,
|
||||||
@ -77,14 +77,16 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
|||||||
)
|
)
|
||||||
|
|
||||||
data.attendanceList.add(attendanceObject)
|
data.attendanceList.add(attendanceObject)
|
||||||
data.metadataList.add(Metadata(
|
if(type != Attendance.TYPE_PRESENT) {
|
||||||
profileId,
|
data.metadataList.add(Metadata(
|
||||||
Metadata.TYPE_ATTENDANCE,
|
profileId,
|
||||||
id,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
profile.empty,
|
id,
|
||||||
profile.empty,
|
profile.empty,
|
||||||
System.currentTimeMillis()
|
profile.empty,
|
||||||
))
|
System.currentTimeMillis()
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
||||||
|
@ -13,9 +13,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_EXAMS
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_EXAMS
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
|
|||||||
startTime,
|
startTime,
|
||||||
topic,
|
topic,
|
||||||
-1,
|
-1,
|
||||||
eventType.id.toInt(),
|
eventType.id,
|
||||||
false,
|
false,
|
||||||
-1,
|
-1,
|
||||||
subject.id,
|
subject.id,
|
||||||
|
@ -13,10 +13,10 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_GRADES
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_GRADES
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade.*
|
import pl.szczodrzynski.edziennik.data.db.entity.Grade.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
@ -27,10 +27,18 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
|||||||
private const val TAG = "EdudziennikWebGrades"
|
private const val TAG = "EdudziennikWebGrades"
|
||||||
}
|
}
|
||||||
|
|
||||||
init { data.profile?.also { profile ->
|
private var requestSemester: Int? = null
|
||||||
webGet(TAG, data.studentEndpoint + "start") { text ->
|
|
||||||
val doc = Jsoup.parse(text)
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (profile?.empty == true && data.currentSemester == 2) requestSemester = 1
|
||||||
|
getGrades()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getGrades() { data.profile?.also { profile ->
|
||||||
|
webGet(TAG, data.studentEndpoint + "start", semester = requestSemester) { text ->
|
||||||
|
val semester = requestSemester ?: data.currentSemester
|
||||||
|
|
||||||
|
val doc = Jsoup.parse(text)
|
||||||
val subjects = doc.select("#student_grades tbody").firstOrNull()?.children()
|
val subjects = doc.select("#student_grades tbody").firstOrNull()?.children()
|
||||||
|
|
||||||
subjects?.forEach { subjectElement ->
|
subjects?.forEach { subjectElement ->
|
||||||
@ -107,7 +115,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
|||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
if (gradeCountToAverage) weight else 0f,
|
if (gradeCountToAverage) weight else 0f,
|
||||||
data.currentSemester,
|
semester,
|
||||||
teacher.id,
|
teacher.id,
|
||||||
subject.id
|
subject.id
|
||||||
).apply {
|
).apply {
|
||||||
@ -137,7 +145,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
|||||||
proposed,
|
proposed,
|
||||||
proposed.toFloatOrNull() ?: 0f,
|
proposed.toFloatOrNull() ?: 0f,
|
||||||
0f,
|
0f,
|
||||||
data.currentSemester,
|
semester,
|
||||||
-1,
|
-1,
|
||||||
subject.id
|
subject.id
|
||||||
).apply {
|
).apply {
|
||||||
@ -170,7 +178,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
|||||||
final,
|
final,
|
||||||
final.toFloatOrNull() ?: 0f,
|
final.toFloatOrNull() ?: 0f,
|
||||||
0f,
|
0f,
|
||||||
data.currentSemester,
|
semester,
|
||||||
-1,
|
-1,
|
||||||
subject.id
|
subject.id
|
||||||
).apply {
|
).apply {
|
||||||
@ -201,12 +209,17 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
|
|||||||
TYPE_SEMESTER1_FINAL,
|
TYPE_SEMESTER1_FINAL,
|
||||||
TYPE_SEMESTER2_FINAL
|
TYPE_SEMESTER2_FINAL
|
||||||
).map {
|
).map {
|
||||||
DataRemoveModel.Grades.semesterWithType(data.currentSemester, it)
|
DataRemoveModel.Grades.semesterWithType(semester, it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
if (profile.empty && requestSemester == 1 && data.currentSemester == 2) {
|
||||||
onSuccess()
|
requestSemester = null
|
||||||
|
getGrades()
|
||||||
|
} else {
|
||||||
|
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
} ?: onSuccess() }
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_NOTE_ID
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_NOTES
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_NOTES
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notice
|
import pl.szczodrzynski.edziennik.data.db.entity.Notice
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
|
|||||||
profileId,
|
profileId,
|
||||||
id,
|
id,
|
||||||
description,
|
description,
|
||||||
data.currentSemester,
|
profile.currentSemester,
|
||||||
Notice.TYPE_NEUTRAL,
|
Notice.TYPE_NEUTRAL,
|
||||||
teacher.id
|
teacher.id
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,6 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||||
companion object {
|
companion object {
|
||||||
@ -62,7 +61,6 @@ class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit)
|
|||||||
|
|
||||||
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com")
|
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com")
|
||||||
val sessionId = cookies.firstOrNull { it.name() == "sessionid" }?.value()
|
val sessionId = cookies.firstOrNull { it.name() == "sessionid" }?.value()
|
||||||
val semester = cookies.firstOrNull { it.name() == "semester" }?.value()?.toIntOrNull()
|
|
||||||
|
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID)
|
data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID)
|
||||||
@ -72,14 +70,6 @@ class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.webSessionId = sessionId
|
data.webSessionId = sessionId
|
||||||
|
|
||||||
if (data.profile != null && semester != null) {
|
|
||||||
data.currentSemester = semester
|
|
||||||
|
|
||||||
if (semester == 2 && data.profile.dateSemester2Start > Date.getToday())
|
|
||||||
data.profile.dateSemester2Start = Date.getToday().stepForward(0, 0, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45 min */
|
data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45 min */
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLo
|
|||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
@ -43,9 +43,7 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
data.saveData()
|
data.saveData()
|
||||||
data.notify {
|
callback.onCompleted()
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
/* _______ _ _ _ _ _
|
||||||
|
@ -13,9 +13,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNI
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class IdziennikWebGrades(override val data: DataIdziennik,
|
class IdziennikWebGrades(override val data: DataIdziennik,
|
||||||
@ -89,11 +89,17 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
|||||||
count += weight
|
count += weight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val historyColor = historyItem.getString("Kolor") ?: ""
|
||||||
|
colorInt = 0xff2196f3.toInt()
|
||||||
|
if (historyColor.isNotEmpty()) {
|
||||||
|
colorInt = Color.parseColor("#$historyColor")
|
||||||
|
}
|
||||||
|
|
||||||
val historyObject = Grade(
|
val historyObject = Grade(
|
||||||
profileId,
|
profileId,
|
||||||
gradeObject.id * -1,
|
gradeObject.id * -1,
|
||||||
historyItem.get("Kategoria").asString,
|
historyItem.get("Kategoria").asString,
|
||||||
Color.parseColor("#" + historyItem.get("Kolor").asString),
|
colorInt,
|
||||||
historyItem.get("Uzasadnienie").asString,
|
historyItem.get("Uzasadnienie").asString,
|
||||||
historyItem.get("Ocena").asString,
|
historyItem.get("Ocena").asString,
|
||||||
value,
|
value,
|
||||||
|
@ -19,12 +19,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin
|
|||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
@ -45,9 +45,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
data.saveData()
|
data.saveData()
|
||||||
data.notify {
|
callback.onCompleted()
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
/* _______ _ _ _ _ _
|
||||||
|
@ -9,10 +9,9 @@ import pl.szczodrzynski.edziennik.*
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_ATTENDANCES
|
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.api.edziennik.librus.data.LibrusApi
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class LibrusApiAttendances(override val data: DataLibrus,
|
class LibrusApiAttendances(override val data: DataLibrus,
|
||||||
@ -33,11 +32,12 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
|||||||
val attendances = json.getJsonArray("Attendances")?.asJsonObjectList()
|
val attendances = json.getJsonArray("Attendances")?.asJsonObjectList()
|
||||||
|
|
||||||
attendances?.forEach { attendance ->
|
attendances?.forEach { attendance ->
|
||||||
val id = Utils.strToInt((attendance.getString("Id") ?: return@forEach)
|
val id = ((attendance.getString("Id") ?: return@forEach)
|
||||||
.replace("[^\\d.]".toRegex(), "")).toLong()
|
.replace("[^\\d.]".toRegex(), "")).toLong()
|
||||||
val lessonId = attendance.getJsonObject("Lesson")?.getLong("Id") ?: -1
|
val lessonId = attendance.getJsonObject("Lesson")?.getLong("Id") ?: -1
|
||||||
val lessonNo = attendance.getInt("LessonNo") ?: return@forEach
|
val lessonNo = attendance.getInt("LessonNo") ?: return@forEach
|
||||||
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
|
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
|
||||||
|
val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id")
|
||||||
val semester = attendance.getInt("Semester") ?: return@forEach
|
val semester = attendance.getInt("Semester") ?: return@forEach
|
||||||
val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
|
val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
|
||||||
val typeObject = data.attendanceTypes.get(type)
|
val typeObject = data.attendanceTypes.get(type)
|
||||||
@ -52,7 +52,7 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
|||||||
val attendanceObject = Attendance(
|
val attendanceObject = Attendance(
|
||||||
profileId,
|
profileId,
|
||||||
id,
|
id,
|
||||||
lesson?.teacherId ?: -1,
|
teacherId ?: lesson?.teacherId ?: -1,
|
||||||
lesson?.subjectId ?: -1,
|
lesson?.subjectId ?: -1,
|
||||||
semester,
|
semester,
|
||||||
topic,
|
topic,
|
||||||
|
@ -25,9 +25,10 @@ class LibrusApiClassrooms(override val data: DataLibrus,
|
|||||||
val id = classroom.getLong("Id") ?: return@forEach
|
val id = classroom.getLong("Id") ?: return@forEach
|
||||||
val name = classroom.getString("Name")?.toLowerCase(Locale.getDefault()) ?: ""
|
val name = classroom.getString("Name")?.toLowerCase(Locale.getDefault()) ?: ""
|
||||||
val symbol = classroom.getString("Symbol")?.toLowerCase(Locale.getDefault()) ?: ""
|
val symbol = classroom.getString("Symbol")?.toLowerCase(Locale.getDefault()) ?: ""
|
||||||
val nameShort = name.split(" ").onEach { it[0] }.joinToString()
|
val nameShort = name.fixWhiteSpaces().split(" ").onEach { it[0] }.joinToString()
|
||||||
|
val symbolParts = symbol.fixWhiteSpaces().split(" ")
|
||||||
|
|
||||||
val friendlyName = if (name != symbol && !name.contains(symbol) && !nameShort.contains(symbol)) {
|
val friendlyName = if (name != symbol && !name.contains(symbol) && !name.containsAll(symbolParts) && !nameShort.contains(symbol)) {
|
||||||
classroom.getString("Symbol") + " " + classroom.getString("Name")
|
classroom.getString("Symbol") + " " + classroom.getString("Name")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -10,9 +10,9 @@ 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.ENDPOINT_LIBRUS_API_EVENTS
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class LibrusApiEvents(override val data: DataLibrus,
|
|||||||
val id = event.getLong("Id") ?: return@forEach
|
val id = event.getLong("Id") ?: return@forEach
|
||||||
val eventDate = Date.fromY_m_d(event.getString("Date"))
|
val eventDate = Date.fromY_m_d(event.getString("Date"))
|
||||||
val topic = event.getString("Content") ?: ""
|
val topic = event.getString("Content") ?: ""
|
||||||
val type = event.getJsonObject("Category")?.getInt("Id") ?: -1
|
val type = event.getJsonObject("Category")?.getLong("Id") ?: -1
|
||||||
val teacherId = event.getJsonObject("CreatedBy")?.getLong("Id") ?: -1
|
val teacherId = event.getJsonObject("CreatedBy")?.getLong("Id") ?: -1
|
||||||
val subjectId = event.getJsonObject("Subject")?.getLong("Id") ?: -1
|
val subjectId = event.getJsonObject("Subject")?.getLong("Id") ?: -1
|
||||||
val teamId = event.getJsonObject("Class")?.getLong("Id") ?: -1
|
val teamId = event.getJsonObject("Class")?.getLong("Id") ?: -1
|
||||||
|
@ -23,6 +23,10 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
|
|||||||
&& webSessionKey.isNotNullNorEmpty()
|
&& webSessionKey.isNotNullNorEmpty()
|
||||||
&& webServerId.isNotNullNorEmpty()
|
&& webServerId.isNotNullNorEmpty()
|
||||||
|
|
||||||
|
fun isApi2LoginValid() = loginEmail.isNotNullNorEmpty()
|
||||||
|
&& loginId.isNotNullNorEmpty()
|
||||||
|
&& globalId.isNotNullNorEmpty()
|
||||||
|
|
||||||
override fun satisfyLoginMethods() {
|
override fun satisfyLoginMethods() {
|
||||||
loginMethods.clear()
|
loginMethods.clear()
|
||||||
if (isWebLoginValid()) {
|
if (isWebLoginValid()) {
|
||||||
@ -44,11 +48,6 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
|
|||||||
get() { mLoginServerName = mLoginServerName ?: loginStore.getLoginData("serverName", null); return mLoginServerName }
|
get() { mLoginServerName = mLoginServerName ?: loginStore.getLoginData("serverName", null); return mLoginServerName }
|
||||||
set(value) { loginStore.putLoginData("serverName", value); mLoginServerName = value }
|
set(value) { loginStore.putLoginData("serverName", value); mLoginServerName = value }
|
||||||
|
|
||||||
private var mLoginEmail: String? = null
|
|
||||||
var loginEmail: String?
|
|
||||||
get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail }
|
|
||||||
set(value) { loginStore.putLoginData("email", value); mLoginEmail = value }
|
|
||||||
|
|
||||||
private var mLoginUsername: String? = null
|
private var mLoginUsername: String? = null
|
||||||
var loginUsername: String?
|
var loginUsername: String?
|
||||||
get() { mLoginUsername = mLoginUsername ?: loginStore.getLoginData("username", null); return mLoginUsername }
|
get() { mLoginUsername = mLoginUsername ?: loginStore.getLoginData("username", null); return mLoginUsername }
|
||||||
@ -90,6 +89,48 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
|
|||||||
get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("sessionIDTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
|
get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("sessionIDTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
|
||||||
set(value) { loginStore.putLoginData("sessionIDTime", value); mWebSessionIdExpiryTime = value }
|
set(value) { loginStore.putLoginData("sessionIDTime", value); mWebSessionIdExpiryTime = value }
|
||||||
|
|
||||||
|
/* _____ _____ ___
|
||||||
|
/\ | __ \_ _| |__ \
|
||||||
|
/ \ | |__) || | ) |
|
||||||
|
/ /\ \ | ___/ | | / /
|
||||||
|
/ ____ \| | _| |_ / /_
|
||||||
|
/_/ \_\_| |_____| |___*/
|
||||||
|
/**
|
||||||
|
* A global ID (whatever it is) used in API 2
|
||||||
|
* and Firebase push from Mobidziennik.
|
||||||
|
*/
|
||||||
|
var globalId: String?
|
||||||
|
get() { mGlobalId = mGlobalId ?: profile?.getStudentData("globalId", null); return mGlobalId }
|
||||||
|
set(value) { profile?.putStudentData("globalId", value) ?: return; mGlobalId = value }
|
||||||
|
private var mGlobalId: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User's email that may or may not
|
||||||
|
* be retrieved from Web by [MobidziennikWebAccountEmail].
|
||||||
|
* Used to log in to API 2.
|
||||||
|
*/
|
||||||
|
var loginEmail: String?
|
||||||
|
get() { mLoginEmail = mLoginEmail ?: profile?.getStudentData("email", null); return mLoginEmail }
|
||||||
|
set(value) { profile?.putStudentData("email", value); mLoginEmail = value }
|
||||||
|
private var mLoginEmail: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A login ID used in the API 2.
|
||||||
|
* Looks more or less like "7063@2019@zslpoznan".
|
||||||
|
*/
|
||||||
|
var loginId: String?
|
||||||
|
get() { mLoginId = mLoginId ?: profile?.getStudentData("loginId", null); return mLoginId }
|
||||||
|
set(value) { profile?.putStudentData("loginId", value) ?: return; mLoginId = value }
|
||||||
|
private var mLoginId: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No need to explain.
|
||||||
|
*/
|
||||||
|
var ciasteczkoAutoryzacji: String?
|
||||||
|
get() { mCiasteczkoAutoryzacji = mCiasteczkoAutoryzacji ?: profile?.getStudentData("ciasteczkoAutoryzacji", null); return mCiasteczkoAutoryzacji }
|
||||||
|
set(value) { profile?.putStudentData("ciasteczkoAutoryzacji", value) ?: return; mCiasteczkoAutoryzacji = value }
|
||||||
|
private var mCiasteczkoAutoryzacji: String? = null
|
||||||
|
|
||||||
|
|
||||||
override fun saveData() {
|
override fun saveData() {
|
||||||
super.saveData()
|
super.saveData()
|
||||||
|
@ -17,12 +17,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.Mobidzie
|
|||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
@ -45,9 +45,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
data.saveData()
|
data.saveData()
|
||||||
data.notify {
|
callback.onCompleted()
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
/* _______ _ _ _ _ _
|
||||||
|
@ -27,11 +27,11 @@ val MobidziennikFeatures = listOf(
|
|||||||
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), // TODO divide features into separate view IDs (all with API_MAIN)
|
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), // TODO divide features into separate view IDs (all with API_MAIN)
|
||||||
|
|
||||||
// push config
|
// push config
|
||||||
/*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf(
|
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf(
|
||||||
ENDPOINT_MOBIDZIENNIK_API2_MAIN to LOGIN_METHOD_MOBIDZIENNIK_API2
|
ENDPOINT_MOBIDZIENNIK_API2_MAIN to LOGIN_METHOD_MOBIDZIENNIK_API2
|
||||||
), listOf(LOGIN_METHOD_MOBIDZIENNIK_API2)).withShouldSync { data ->
|
), listOf(LOGIN_METHOD_MOBIDZIENNIK_API2)).withShouldSync { data ->
|
||||||
data.app.appConfig.fcmTokens[LOGIN_TYPE_MOBIDZIENNIK]?.second?.contains(data.profileId) == false
|
!data.app.config.sync.tokenMobidziennikList.contains(data.profileId)
|
||||||
},*/
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,10 +7,8 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data
|
|||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.*
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api.MobidziennikApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api.MobidziennikApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebCalendar
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2.MobidziennikApi2Main
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebGrades
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebMessagesAll
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebMessagesInbox
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
|
||||||
class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
||||||
@ -44,6 +42,10 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
|||||||
data.startProgress(R.string.edziennik_progress_endpoint_data)
|
data.startProgress(R.string.edziennik_progress_endpoint_data)
|
||||||
MobidziennikApi(data, onSuccess)
|
MobidziennikApi(data, onSuccess)
|
||||||
}
|
}
|
||||||
|
ENDPOINT_MOBIDZIENNIK_API2_MAIN -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_push_config)
|
||||||
|
MobidziennikApi2Main(data, onSuccess)
|
||||||
|
}
|
||||||
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX -> {
|
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
||||||
MobidziennikWebMessagesInbox(data) { onSuccess() }
|
MobidziennikWebMessagesInbox(data) { onSuccess() }
|
||||||
@ -59,6 +61,10 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
|||||||
ENDPOINT_MOBIDZIENNIK_WEB_GRADES -> {
|
ENDPOINT_MOBIDZIENNIK_WEB_GRADES -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
||||||
MobidziennikWebGrades(data) { onSuccess() }
|
MobidziennikWebGrades(data) { onSuccess() }
|
||||||
|
}
|
||||||
|
ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_account_details)
|
||||||
|
MobidziennikWebAccountEmail(data) { onSuccess() }
|
||||||
}/*
|
}/*
|
||||||
ENDPOINT_MOBIDZIENNIK_WEB_NOTICES -> {
|
ENDPOINT_MOBIDZIENNIK_WEB_NOTICES -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_behaviour)
|
data.startProgress(R.string.edziennik_progress_endpoint_behaviour)
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-12.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2
|
||||||
|
|
||||||
|
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.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_API2_MAIN
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginApi2
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.getJsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.getString
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
|
||||||
|
class MobidziennikApi2Main(val data: DataMobidziennik,
|
||||||
|
val onSuccess: () -> Unit) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MobidziennikApi2Main"
|
||||||
|
}
|
||||||
|
|
||||||
|
val profileId
|
||||||
|
get() = data.profile?.id ?: -1
|
||||||
|
|
||||||
|
val profile
|
||||||
|
get() = data.profile
|
||||||
|
|
||||||
|
init {
|
||||||
|
Utils.d(TAG, "Request: Mobidziennik/Api2/Main - https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
|
||||||
|
|
||||||
|
val callback = object : JsonCallbackHandler() {
|
||||||
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
|
if (json == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.getJsonObject("error")?.let {
|
||||||
|
val text = it.getString("type") ?: it.getString("message")
|
||||||
|
when (text) {
|
||||||
|
"LOGIN_ERROR" -> ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN
|
||||||
|
// TODO other error types
|
||||||
|
else -> ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER
|
||||||
|
}.let { errorCode ->
|
||||||
|
data.error(ApiError(TAG, errorCode)
|
||||||
|
.withApiResponse(text)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = json.getJsonObject("user")
|
||||||
|
data.ciasteczkoAutoryzacji = user.getString("auth_key")
|
||||||
|
|
||||||
|
// sync always: this endpoint has .shouldSync set
|
||||||
|
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_API2_MAIN, SYNC_ALWAYS)
|
||||||
|
data.app.config.sync.tokenMobidziennikList =
|
||||||
|
data.app.config.sync.tokenMobidziennikList + profileId
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url("https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
|
||||||
|
.userAgent(MOBIDZIENNIK_USER_AGENT)
|
||||||
|
.contentType("application/x-www-form-urlencoded; charset=UTF-8")
|
||||||
|
.addParameter("login", data.loginId)
|
||||||
|
.addParameter("email", data.loginEmail)
|
||||||
|
.addParameter("haslo", data.loginPassword)
|
||||||
|
.addParameter("device", MobidziennikLoginApi2.getDevice(data.app).toString())
|
||||||
|
.apply {
|
||||||
|
data.ciasteczkoAutoryzacji?.let { addParameter("ciasteczko_autoryzacji", it) }
|
||||||
|
}
|
||||||
|
.post()
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.DAY
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||||
|
import pl.szczodrzynski.edziennik.get
|
||||||
|
|
||||||
|
class MobidziennikWebAccountEmail(override val data: DataMobidziennik,
|
||||||
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MobidziennikWebAccountEmail"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
webGet(TAG, "/dziennik/edytujprofil") { text ->
|
||||||
|
MobidziennikLuckyNumberExtractor(data, text)
|
||||||
|
|
||||||
|
val email = Regexes.MOBIDZIENNIK_ACCOUNT_EMAIL.find(text)?.let { it[1] }
|
||||||
|
data.loginEmail = email
|
||||||
|
|
||||||
|
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL, if (email == null) 3*DAY else 7*DAY)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,16 +9,16 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.getString
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.crc16
|
import pl.szczodrzynski.edziennik.utils.Utils.crc16
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class MobidziennikWebCalendar(override val data: DataMobidziennik,
|
class MobidziennikWebCalendar(override val data: DataMobidziennik,
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MobidziennikWebCalendar"
|
private const val TAG = "MobidziennikWebCalendar"
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
|
|||||||
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
|
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.fixName
|
import pl.szczodrzynski.edziennik.fixName
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.singleOrNull
|
import pl.szczodrzynski.edziennik.singleOrNull
|
||||||
@ -25,7 +25,7 @@ import pl.szczodrzynski.edziennik.utils.models.Time
|
|||||||
class MobidziennikWebGetMessage(
|
class MobidziennikWebGetMessage(
|
||||||
override val data: DataMobidziennik,
|
override val data: DataMobidziennik,
|
||||||
private val message: MessageFull,
|
private val message: MessageFull,
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MobidziennikWebGetMessage"
|
private const val TAG = "MobidziennikWebGetMessage"
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.fixWhiteSpaces
|
import pl.szczodrzynski.edziennik.fixWhiteSpaces
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.singleOrNull
|
import pl.szczodrzynski.edziennik.singleOrNull
|
||||||
@ -21,7 +21,7 @@ import pl.szczodrzynski.edziennik.utils.models.Date
|
|||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
class MobidziennikWebGrades(override val data: DataMobidziennik,
|
class MobidziennikWebGrades(override val data: DataMobidziennik,
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MobidziennikWebGrades"
|
private const val TAG = "MobidziennikWebGrades"
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import pl.szczodrzynski.edziennik.singleOrNull
|
|||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
|
class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MobidziennikWebMessagesAll"
|
private const val TAG = "MobidziennikWebMessagesAll"
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,16 @@ import org.jsoup.Jsoup
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.fixName
|
import pl.szczodrzynski.edziennik.fixName
|
||||||
import pl.szczodrzynski.edziennik.singleOrNull
|
import pl.szczodrzynski.edziennik.singleOrNull
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MobidziennikWebMessagesInbox"
|
private const val TAG = "MobidziennikWebMessagesInbox"
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
|
|||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||||
|
|
||||||
class MobidziennikWebNotices(override val data: DataMobidziennik,
|
class MobidziennikWebNotices(override val data: DataMobidziennik,
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MobidziennikWebNotices"
|
private const val TAG = "MobidziennikWebNotices"
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ class MobidziennikLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
|||||||
}
|
}
|
||||||
LOGIN_METHOD_MOBIDZIENNIK_API2 -> {
|
LOGIN_METHOD_MOBIDZIENNIK_API2 -> {
|
||||||
data.startProgress(R.string.edziennik_progress_login_mobidziennik_api2)
|
data.startProgress(R.string.edziennik_progress_login_mobidziennik_api2)
|
||||||
//MobidziennikLoginApi2(data) { onSuccess(loginMethodId) }
|
MobidziennikLoginApi2(data) { onSuccess(loginMethodId) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-12.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
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.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
|
||||||
|
class MobidziennikLoginApi2(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MobidziennikLoginApi2"
|
||||||
|
|
||||||
|
fun getDevice(app: App) = JsonObject(
|
||||||
|
"available" to true,
|
||||||
|
"platform" to "Android",
|
||||||
|
"version" to Build.VERSION.RELEASE,
|
||||||
|
"uuid" to app.deviceId,
|
||||||
|
"cordova" to "7.1.2",
|
||||||
|
"model" to "${Build.MANUFACTURER} ${Build.MODEL}",
|
||||||
|
"manufacturer" to "Aplikacja Szkolny.eu",
|
||||||
|
"isVirtual" to false,
|
||||||
|
"serial" to try { System.getProperty("ro.serialno") ?: System.getProperty("ro.boot.serialno") } catch (_: Exception) { Build.UNKNOWN },
|
||||||
|
"appVersion" to "10.6, 2020.01.09-12.15.53",
|
||||||
|
"pushRegistrationId" to app.config.sync.tokenMobidziennik
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
init { run {
|
||||||
|
if (data.isApi2LoginValid()) {
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (data.loginServerName.isNotNullNorEmpty() && data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
|
||||||
|
loginWithCredentials()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
private fun loginWithCredentials() {
|
||||||
|
Utils.d(TAG, "Request: Mobidziennik/Login/Api2 - https://mobidziennik.pl/logowanie")
|
||||||
|
|
||||||
|
val callback = object : JsonCallbackHandler() {
|
||||||
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
|
if (json == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.getJsonObject("error")?.let {
|
||||||
|
val text = it.getString("type") ?: it.getString("message")
|
||||||
|
when (text) {
|
||||||
|
"LOGIN_ERROR" -> ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN
|
||||||
|
// TODO other error types
|
||||||
|
else -> ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER
|
||||||
|
}.let { errorCode ->
|
||||||
|
data.error(ApiError(TAG, errorCode)
|
||||||
|
.withApiResponse(text)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.loginEmail = json.getString("email")
|
||||||
|
data.globalId = json.getString("id_global")
|
||||||
|
data.loginId = json.getString("login")
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url("https://mobidziennik.pl/logowanie")
|
||||||
|
.userAgent(MOBIDZIENNIK_USER_AGENT)
|
||||||
|
.contentType("application/x-www-form-urlencoded; charset=UTF-8")
|
||||||
|
.addParameter("api2", true)
|
||||||
|
.addParameter("email", data.loginEmail)
|
||||||
|
.addParameter("haslo", data.loginPassword)
|
||||||
|
.addParameter("device", getDevice(data.app).toString())
|
||||||
|
.post()
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
}
|
@ -15,12 +15,12 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
|||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.api.prepare
|
import pl.szczodrzynski.edziennik.data.api.prepare
|
||||||
import pl.szczodrzynski.edziennik.data.api.templateLoginMethods
|
import pl.szczodrzynski.edziennik.data.api.templateLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class Template(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Template(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
@ -40,9 +40,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
data.saveData()
|
data.saveData()
|
||||||
data.notify {
|
callback.onCompleted()
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
/* _______ _ _ _ _ _
|
||||||
|
@ -18,12 +18,12 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|||||||
import pl.szczodrzynski.edziennik.data.api.prepare
|
import pl.szczodrzynski.edziennik.data.api.prepare
|
||||||
import pl.szczodrzynski.edziennik.data.api.prepareFor
|
import pl.szczodrzynski.edziennik.data.api.prepareFor
|
||||||
import pl.szczodrzynski.edziennik.data.api.vulcanLoginMethods
|
import pl.szczodrzynski.edziennik.data.api.vulcanLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
@ -44,9 +44,7 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
data.saveData()
|
data.saveData()
|
||||||
data.notify {
|
callback.onCompleted()
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _______ _ _ _ _ _
|
/* _______ _ _ _ _ _
|
||||||
|
@ -4,13 +4,15 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api
|
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS
|
import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
|
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
|
|
||||||
class VulcanApiMessagesChangeStatus(
|
class VulcanApiMessagesChangeStatus(
|
||||||
override val data: DataVulcan,
|
override val data: DataVulcan,
|
||||||
@ -22,40 +24,42 @@ class VulcanApiMessagesChangeStatus(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
data.profile?.also { profile ->
|
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS, parameters = mapOf(
|
||||||
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS, parameters = mapOf(
|
"WiadomoscId" to messageObject.id,
|
||||||
"WiadomoscId" to messageObject.id,
|
"FolderWiadomosci" to "Odebrane",
|
||||||
"FolderWiadomosci" to "Odebrane",
|
"Status" to "Widoczna",
|
||||||
"Status" to "Widoczna",
|
"LoginId" to data.studentLoginId,
|
||||||
"LoginId" to data.studentLoginId,
|
"IdUczen" to data.studentId
|
||||||
"IdUczen" to data.studentId
|
)) { _, _ ->
|
||||||
)) { _, _ ->
|
|
||||||
|
|
||||||
if (!messageObject.seen) {
|
if (!messageObject.seen) {
|
||||||
data.setSeenMetadataList.add(Metadata(
|
data.setSeenMetadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_MESSAGE,
|
Metadata.TYPE_MESSAGE,
|
||||||
messageObject.id,
|
messageObject.id,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
messageObject.addedDate
|
messageObject.addedDate
|
||||||
))
|
))
|
||||||
}
|
|
||||||
|
|
||||||
if (messageObject.type != TYPE_SENT) {
|
messageObject.seen = true
|
||||||
val messageRecipientObject = MessageRecipient(
|
|
||||||
profileId,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
messageObject.id
|
|
||||||
)
|
|
||||||
|
|
||||||
data.messageRecipientList.add(messageRecipientObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
onSuccess()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (messageObject.type != TYPE_SENT) {
|
||||||
|
val messageRecipientObject = MessageRecipient(
|
||||||
|
profileId,
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
messageObject.id
|
||||||
|
)
|
||||||
|
|
||||||
|
data.messageRecipientList.add(messageRecipientObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
|
||||||
|
|
||||||
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,8 @@ import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_RECEIVED
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_INBOX
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_INBOX
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import kotlin.text.replace
|
import kotlin.text.replace
|
||||||
@ -88,7 +84,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
|
|
||||||
data.messageIgnoreList.add(messageObject)
|
data.messageIgnoreList.add(messageObject)
|
||||||
data.messageRecipientList.add(messageRecipientObject)
|
data.messageRecipientList.add(messageRecipientObject)
|
||||||
data.metadataList.add(Metadata(
|
data.setSeenMetadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_MESSAGE,
|
Metadata.TYPE_MESSAGE,
|
||||||
id,
|
id,
|
||||||
|
@ -99,7 +99,7 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
)
|
)
|
||||||
|
|
||||||
data.messageIgnoreList.add(messageObject)
|
data.messageIgnoreList.add(messageObject)
|
||||||
data.metadataList.add(Metadata(
|
data.setSeenMetadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_MESSAGE,
|
Metadata.TYPE_MESSAGE,
|
||||||
id,
|
id,
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.events
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage
|
||||||
|
|
||||||
|
data class FeedbackMessageEvent(val message: FeedbackMessage)
|
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.events
|
||||||
|
|
||||||
|
class ProfileListEmptyEvent
|
@ -93,7 +93,7 @@ class ApiError(val tag: String, var errorCode: Int) {
|
|||||||
stackTrace = throwable?.stackTraceString,
|
stackTrace = throwable?.stackTraceString,
|
||||||
request = requestString,
|
request = requestString,
|
||||||
response = responseString,
|
response = responseString,
|
||||||
apiResponse = apiResponse,
|
apiResponse = apiResponse ?: response?.parserErrorBody,
|
||||||
isCritical = isCritical
|
isCritical = isCritical
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
|||||||
if (profile == null)
|
if (profile == null)
|
||||||
return // return on first login
|
return // return on first login
|
||||||
|
|
||||||
profile.empty = false
|
|
||||||
profile.userCode = generateUserCode()
|
profile.userCode = generateUserCode()
|
||||||
|
|
||||||
db.profileDao().add(profile)
|
db.profileDao().add(profile)
|
||||||
@ -294,21 +293,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
|||||||
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
|
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notify(onSuccess: () -> Unit) {
|
|
||||||
if (profile == null) {
|
|
||||||
onSuccess()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
DataNotifications(this)
|
|
||||||
db.notificationDao().addAll(notifications)
|
|
||||||
onSuccess()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
error(ApiError(TAG, EXCEPTION_NOTIFY)
|
|
||||||
.withThrowable(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSyncNext(endpointId: Int, syncIn: Long? = null, viewId: Int? = null, syncAt: Long? = null) {
|
fun setSyncNext(endpointId: Int, syncIn: Long? = null, viewId: Int? = null, syncAt: Long? = null) {
|
||||||
EndpointTimer(profile?.id
|
EndpointTimer(profile?.id
|
||||||
?: -1, endpointId).apply {
|
?: -1, endpointId).apply {
|
||||||
@ -366,8 +350,8 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
|||||||
apiError.errorCode = when (apiError.throwable) {
|
apiError.errorCode = when (apiError.throwable) {
|
||||||
is UnknownHostException -> ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND
|
is UnknownHostException -> ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND
|
||||||
is SSLException -> ERROR_REQUEST_FAILURE_SSL_ERROR
|
is SSLException -> ERROR_REQUEST_FAILURE_SSL_ERROR
|
||||||
is InterruptedIOException, is ConnectException -> ERROR_REQUEST_FAILURE_NO_INTERNET
|
|
||||||
is SocketTimeoutException -> ERROR_REQUEST_FAILURE_TIMEOUT
|
is SocketTimeoutException -> ERROR_REQUEST_FAILURE_TIMEOUT
|
||||||
|
is InterruptedIOException, is ConnectException -> ERROR_REQUEST_FAILURE_NO_INTERNET
|
||||||
else ->
|
else ->
|
||||||
if (apiError.errorCode == ERROR_REQUEST_FAILURE)
|
if (apiError.errorCode == ERROR_REQUEST_FAILURE)
|
||||||
when (apiError.response?.code()) {
|
when (apiError.response?.code()) {
|
||||||
|
@ -47,11 +47,11 @@ open class DataRemoveModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Events(private val type: Int?, private val exceptType: Int?, private val exceptTypes: List<Int>?) : DataRemoveModel() {
|
class Events(private val type: Long?, private val exceptType: Long?, private val exceptTypes: List<Long>?) : DataRemoveModel() {
|
||||||
companion object {
|
companion object {
|
||||||
fun futureExceptType(exceptType: Int) = Events(null, exceptType, null)
|
fun futureExceptType(exceptType: Long) = Events(null, exceptType, null)
|
||||||
fun futureExceptTypes(exceptTypes: List<Int>) = Events(null, null, exceptTypes)
|
fun futureExceptTypes(exceptTypes: List<Long>) = Events(null, null, exceptTypes)
|
||||||
fun futureWithType(type: Int) = Events(type, null, null)
|
fun futureWithType(type: Long) = Events(type, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun commit(profileId: Int, dao: EventDao) {
|
fun commit(profileId: Int, dao: EventDao) {
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-13
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.szkolny
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
|
||||||
|
|
||||||
class Szkolny(val app: App, val callback: EdziennikCallback) {
|
|
||||||
|
|
||||||
private val api = SzkolnyApi(app)
|
|
||||||
|
|
||||||
fun sync(profileList: List<Profile>) {
|
|
||||||
val profiles = profileList.filter { it.registration == Profile.REGISTRATION_ENABLED }
|
|
||||||
if (profiles.isNotEmpty()) {
|
|
||||||
val events = api.getEvents(profiles)
|
|
||||||
|
|
||||||
if (events.isNotEmpty()) {
|
|
||||||
app.db.eventDao().addAll(events)
|
|
||||||
app.db.metadataDao().addAllIgnore(events.map { event ->
|
|
||||||
Metadata(
|
|
||||||
event.profileId,
|
|
||||||
Metadata.TYPE_EVENT,
|
|
||||||
event.id,
|
|
||||||
event.seen,
|
|
||||||
event.notified,
|
|
||||||
event.addedDate
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*fun shareEvent(event: EventFull) {
|
|
||||||
api.shareEvent(event)
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unshareEvent(event: EventFull) {
|
|
||||||
api.unshareEvent(event)
|
|
||||||
completed()
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private fun completed() {
|
|
||||||
callback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,15 +12,16 @@ import pl.szczodrzynski.edziennik.BuildConfig
|
|||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.DateAdapter
|
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.DateAdapter
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.TimeAdapter
|
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.TimeAdapter
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor
|
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.ErrorReportRequest
|
import pl.szczodrzynski.edziennik.data.api.szkolny.request.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.EventShareRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.ServerSyncRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.WebPushRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.WebPushResponse
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.WebPushResponse
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||||
|
import pl.szczodrzynski.edziennik.md5
|
||||||
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 retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
@ -55,31 +56,52 @@ class SzkolnyApi(val app: App) {
|
|||||||
api = retrofit.create()
|
api = retrofit.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEvents(profiles: List<Profile>): List<EventFull> {
|
private fun getDevice() = run {
|
||||||
|
val config = app.config
|
||||||
|
val device = Device(
|
||||||
|
osType = "Android",
|
||||||
|
osVersion = Build.VERSION.RELEASE,
|
||||||
|
hardware = "${Build.MANUFACTURER} ${Build.MODEL}",
|
||||||
|
pushToken = app.config.sync.tokenApp,
|
||||||
|
appVersion = BuildConfig.VERSION_NAME,
|
||||||
|
appType = BuildConfig.BUILD_TYPE,
|
||||||
|
appVersionCode = BuildConfig.VERSION_CODE,
|
||||||
|
syncInterval = app.config.sync.interval
|
||||||
|
)
|
||||||
|
device.toString().md5().let {
|
||||||
|
if (it == config.hash)
|
||||||
|
null
|
||||||
|
else {
|
||||||
|
config.hash = it
|
||||||
|
device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEvents(profiles: List<Profile>, notifications: List<Notification>, blacklistedIds: List<Long>): List<EventFull> {
|
||||||
val teams = app.db.teamDao().allNow
|
val teams = app.db.teamDao().allNow
|
||||||
val notifications = app.db.notificationDao().getNotPostedNow()
|
|
||||||
|
|
||||||
val response = api.serverSync(ServerSyncRequest(
|
val response = api.serverSync(ServerSyncRequest(
|
||||||
deviceId = app.deviceId,
|
deviceId = app.deviceId,
|
||||||
device = ServerSyncRequest.Device(
|
device = getDevice(),
|
||||||
osType = "Android",
|
|
||||||
osVersion = Build.VERSION.RELEASE,
|
|
||||||
hardware = "${Build.MANUFACTURER} ${Build.MODEL}",
|
|
||||||
pushToken = app.config.sync.tokenApp,
|
|
||||||
appVersion = BuildConfig.VERSION_NAME,
|
|
||||||
appType = BuildConfig.BUILD_TYPE,
|
|
||||||
appVersionCode = BuildConfig.VERSION_CODE,
|
|
||||||
syncInterval = app.config.sync.interval
|
|
||||||
),
|
|
||||||
userCodes = profiles.map { it.userCode },
|
userCodes = profiles.map { it.userCode },
|
||||||
users = profiles.map { profile ->
|
users = profiles.mapNotNull { profile ->
|
||||||
ServerSyncRequest.User(
|
val config = app.config.getFor(profile.id)
|
||||||
|
val user = ServerSyncRequest.User(
|
||||||
profile.userCode,
|
profile.userCode,
|
||||||
profile.studentNameLong ?: "",
|
profile.studentNameLong,
|
||||||
profile.studentNameShort ?: "",
|
profile.studentNameShort,
|
||||||
profile.loginStoreType,
|
profile.loginStoreType,
|
||||||
teams.filter { it.profileId == profile.id }.map { it.code }
|
teams.filter { it.profileId == profile.id }.map { it.code }
|
||||||
)
|
)
|
||||||
|
user.toString().md5().let {
|
||||||
|
if (it == config.hash)
|
||||||
|
null
|
||||||
|
else {
|
||||||
|
config.hash = it
|
||||||
|
user
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
notifications = notifications.map { ServerSyncRequest.Notification(it.profileName ?: "", it.type, it.text) }
|
notifications = notifications.map { ServerSyncRequest.Notification(it.profileName ?: "", it.type, it.text) }
|
||||||
)).execute().body()
|
)).execute().body()
|
||||||
@ -87,17 +109,19 @@ class SzkolnyApi(val app: App) {
|
|||||||
val events = mutableListOf<EventFull>()
|
val events = mutableListOf<EventFull>()
|
||||||
|
|
||||||
response?.data?.events?.forEach { event ->
|
response?.data?.events?.forEach { event ->
|
||||||
teams.filter { it.code == event.teamCode }.forEach { team ->
|
if (event.id in blacklistedIds)
|
||||||
val profile = profiles.firstOrNull { it.id == team.profileId }
|
return@forEach
|
||||||
|
teams.filter { it.code == event.teamCode }.onEach { team ->
|
||||||
|
val profile = profiles.firstOrNull { it.id == team.profileId } ?: return@onEach
|
||||||
|
|
||||||
events.add(event.apply {
|
events.add(EventFull(event).apply {
|
||||||
profileId = team.profileId
|
profileId = team.profileId
|
||||||
teamId = team.id
|
teamId = team.id
|
||||||
addedManually = true
|
addedManually = true
|
||||||
seen = profile?.empty ?: false
|
seen = profile.empty
|
||||||
notified = profile?.empty ?: false
|
notified = profile.empty
|
||||||
|
|
||||||
if (profile?.userCode == event.sharedBy) sharedBy = "self"
|
if (profile.userCode == event.sharedBy) sharedBy = "self"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,6 +134,7 @@ class SzkolnyApi(val app: App) {
|
|||||||
|
|
||||||
return api.shareEvent(EventShareRequest(
|
return api.shareEvent(EventShareRequest(
|
||||||
deviceId = app.deviceId,
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
sharedByName = event.sharedByName,
|
sharedByName = event.sharedByName,
|
||||||
shareTeamCode = team.code,
|
shareTeamCode = team.code,
|
||||||
event = event
|
event = event
|
||||||
@ -121,6 +146,7 @@ class SzkolnyApi(val app: App) {
|
|||||||
|
|
||||||
return api.shareEvent(EventShareRequest(
|
return api.shareEvent(EventShareRequest(
|
||||||
deviceId = app.deviceId,
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
sharedByName = event.sharedByName,
|
sharedByName = event.sharedByName,
|
||||||
unshareTeamCode = team.code,
|
unshareTeamCode = team.code,
|
||||||
eventId = event.id
|
eventId = event.id
|
||||||
@ -133,8 +159,9 @@ class SzkolnyApi(val app: App) {
|
|||||||
|
|
||||||
fun pairBrowser(browserId: String?, pairToken: String?, onError: ((List<ApiResponse.Error>) -> Unit)? = null): List<WebPushResponse.Browser> {
|
fun pairBrowser(browserId: String?, pairToken: String?, onError: ((List<ApiResponse.Error>) -> Unit)? = null): List<WebPushResponse.Browser> {
|
||||||
val response = api.webPush(WebPushRequest(
|
val response = api.webPush(WebPushRequest(
|
||||||
action = "pairBrowser",
|
|
||||||
deviceId = app.deviceId,
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
|
action = "pairBrowser",
|
||||||
browserId = browserId,
|
browserId = browserId,
|
||||||
pairToken = pairToken
|
pairToken = pairToken
|
||||||
)).execute().body()
|
)).execute().body()
|
||||||
@ -149,8 +176,9 @@ class SzkolnyApi(val app: App) {
|
|||||||
|
|
||||||
fun listBrowsers(onError: ((List<ApiResponse.Error>) -> Unit)? = null): List<WebPushResponse.Browser> {
|
fun listBrowsers(onError: ((List<ApiResponse.Error>) -> Unit)? = null): List<WebPushResponse.Browser> {
|
||||||
val response = api.webPush(WebPushRequest(
|
val response = api.webPush(WebPushRequest(
|
||||||
action = "listBrowsers",
|
deviceId = app.deviceId,
|
||||||
deviceId = app.deviceId
|
device = getDevice(),
|
||||||
|
action = "listBrowsers"
|
||||||
)).execute().body()
|
)).execute().body()
|
||||||
|
|
||||||
return response?.data?.browsers ?: emptyList()
|
return response?.data?.browsers ?: emptyList()
|
||||||
@ -158,8 +186,9 @@ class SzkolnyApi(val app: App) {
|
|||||||
|
|
||||||
fun unpairBrowser(browserId: String): List<WebPushResponse.Browser> {
|
fun unpairBrowser(browserId: String): List<WebPushResponse.Browser> {
|
||||||
val response = api.webPush(WebPushRequest(
|
val response = api.webPush(WebPushRequest(
|
||||||
action = "unpairBrowser",
|
|
||||||
deviceId = app.deviceId,
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
|
action = "unpairBrowser",
|
||||||
browserId = browserId
|
browserId = browserId
|
||||||
)).execute().body()
|
)).execute().body()
|
||||||
|
|
||||||
@ -169,7 +198,31 @@ class SzkolnyApi(val app: App) {
|
|||||||
fun errorReport(errors: List<ErrorReportRequest.Error>): ApiResponse<Nothing>? {
|
fun errorReport(errors: List<ErrorReportRequest.Error>): ApiResponse<Nothing>? {
|
||||||
return api.errorReport(ErrorReportRequest(
|
return api.errorReport(ErrorReportRequest(
|
||||||
deviceId = app.deviceId,
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
|
appVersion = BuildConfig.VERSION_NAME,
|
||||||
errors = errors
|
errors = errors
|
||||||
)).execute().body()
|
)).execute().body()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun unregisterAppUser(userCode: String): ApiResponse<Nothing>? {
|
||||||
|
return api.appUser(AppUserRequest(
|
||||||
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
|
userCode = userCode
|
||||||
|
)).execute().body()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUpdate(channel: String): ApiResponse<List<Update>>? {
|
||||||
|
return api.updates(channel).execute().body()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendFeedbackMessage(senderName: String?, targetDeviceId: String?, text: String): FeedbackMessage? {
|
||||||
|
return api.feedbackMessage(FeedbackMessageRequest(
|
||||||
|
deviceId = app.deviceId,
|
||||||
|
device = getDevice(),
|
||||||
|
senderName = senderName,
|
||||||
|
targetDeviceId = targetDeviceId,
|
||||||
|
text = text
|
||||||
|
)).execute().body()?.data?.message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,13 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.szkolny
|
package pl.szczodrzynski.edziennik.data.api.szkolny
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.ErrorReportRequest
|
import pl.szczodrzynski.edziennik.data.api.szkolny.request.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.EventShareRequest
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.ServerSyncRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.WebPushRequest
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ServerSyncResponse
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.WebPushResponse
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Query
|
||||||
|
|
||||||
interface SzkolnyService {
|
interface SzkolnyService {
|
||||||
|
|
||||||
@ -28,4 +25,13 @@ interface SzkolnyService {
|
|||||||
|
|
||||||
@POST("errorReport")
|
@POST("errorReport")
|
||||||
fun errorReport(@Body request: ErrorReportRequest): Call<ApiResponse<Nothing>>
|
fun errorReport(@Body request: ErrorReportRequest): Call<ApiResponse<Nothing>>
|
||||||
|
|
||||||
|
@POST("appUser")
|
||||||
|
fun appUser(@Body request: AppUserRequest): Call<ApiResponse<Nothing>>
|
||||||
|
|
||||||
|
@GET("updates/app")
|
||||||
|
fun updates(@Query("channel") channel: String = "release"): Call<ApiResponse<List<Update>>>
|
||||||
|
|
||||||
|
@POST("feedbackMessage")
|
||||||
|
fun feedbackMessage(@Body request: FeedbackMessageRequest): Call<ApiResponse<FeedbackMessageResponse>>
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,6 @@ object Signing {
|
|||||||
|
|
||||||
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
|
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
|
||||||
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
|
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
|
||||||
return "$param1.MTIzNDU2Nzg5MD9c4qHZ3B===.$param2".sha256()
|
return "$param1.MTIzNDU2Nzg5MDHOhFUjfn===.$param2".sha256()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
||||||
|
|
||||||
|
data class AppUserRequest(
|
||||||
|
val deviceId: String,
|
||||||
|
val device: Device? = null,
|
||||||
|
|
||||||
|
val action: String = "unregister",
|
||||||
|
val userCode: String
|
||||||
|
)
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-20.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
||||||
|
|
||||||
|
data class Device(
|
||||||
|
val osType: String,
|
||||||
|
val osVersion: String,
|
||||||
|
val hardware: String,
|
||||||
|
val pushToken: String?,
|
||||||
|
val appVersion: String,
|
||||||
|
val appType: String,
|
||||||
|
val appVersionCode: Int,
|
||||||
|
val syncInterval: Int
|
||||||
|
)
|
@ -6,6 +6,9 @@ package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
|||||||
|
|
||||||
data class ErrorReportRequest(
|
data class ErrorReportRequest(
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
|
val device: Device? = null,
|
||||||
|
|
||||||
|
val appVersion: String,
|
||||||
val errors: List<Error>
|
val errors: List<Error>
|
||||||
) {
|
) {
|
||||||
data class Error(
|
data class Error(
|
||||||
@ -20,4 +23,4 @@ data class ErrorReportRequest(
|
|||||||
val apiResponse: String?,
|
val apiResponse: String?,
|
||||||
val isCritical: Boolean
|
val isCritical: Boolean
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,10 @@ package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
|||||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||||
|
|
||||||
data class EventShareRequest (
|
data class EventShareRequest (
|
||||||
|
val deviceId: String,
|
||||||
|
val device: Device? = null,
|
||||||
|
|
||||||
val action: String = "event",
|
val action: String = "event",
|
||||||
val deviceId: String,
|
|
||||||
|
|
||||||
val sharedByName: String,
|
val sharedByName: String,
|
||||||
val shareTeamCode: String? = null,
|
val shareTeamCode: String? = null,
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
||||||
|
|
||||||
|
data class FeedbackMessageRequest(
|
||||||
|
val deviceId: String,
|
||||||
|
val device: Device? = null,
|
||||||
|
|
||||||
|
val senderName: String?,
|
||||||
|
val targetDeviceId: String?,
|
||||||
|
val text: String
|
||||||
|
)
|
@ -5,7 +5,6 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
||||||
|
|
||||||
data class ServerSyncRequest(
|
data class ServerSyncRequest(
|
||||||
|
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
val device: Device? = null,
|
val device: Device? = null,
|
||||||
|
|
||||||
@ -14,17 +13,6 @@ data class ServerSyncRequest(
|
|||||||
|
|
||||||
val notifications: List<Notification>? = null
|
val notifications: List<Notification>? = null
|
||||||
) {
|
) {
|
||||||
data class Device(
|
|
||||||
val osType: String,
|
|
||||||
val osVersion: String,
|
|
||||||
val hardware: String,
|
|
||||||
val pushToken: String?,
|
|
||||||
val appVersion: String,
|
|
||||||
val appType: String,
|
|
||||||
val appVersionCode: Int,
|
|
||||||
val syncInterval: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
data class User(
|
data class User(
|
||||||
val userCode: String,
|
val userCode: String,
|
||||||
val studentName: String,
|
val studentName: String,
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
package pl.szczodrzynski.edziennik.data.api.szkolny.request
|
||||||
|
|
||||||
data class WebPushRequest(
|
data class WebPushRequest(
|
||||||
|
val deviceId: String,
|
||||||
|
val device: Device? = null,
|
||||||
|
|
||||||
val action: String,
|
val action: String,
|
||||||
val deviceId: String,
|
|
||||||
|
|
||||||
val browserId: String? = null,
|
val browserId: String? = null,
|
||||||
val pairToken: String? = null
|
val pairToken: String? = null
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.szkolny.response
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage
|
||||||
|
|
||||||
|
data class FeedbackMessageResponse(val message: FeedbackMessage)
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.szkolny.response
|
||||||
|
|
||||||
|
data class Update(
|
||||||
|
val versionCode: Int,
|
||||||
|
val versionName: String,
|
||||||
|
val releaseDate: String,
|
||||||
|
val releaseNotes: String?,
|
||||||
|
val releaseType: String,
|
||||||
|
val isOnGooglePlay: Boolean,
|
||||||
|
val downloadUrl: String?
|
||||||
|
)
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.task
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
|
|
||||||
|
class AppSync(val app: App, val notifications: MutableList<Notification>, val profiles: List<Profile>, val api: SzkolnyApi) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "AppSync"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the app sync, sending all pending notifications
|
||||||
|
* and retrieving a list of shared events.
|
||||||
|
*
|
||||||
|
* Events are automatically saved to app database,
|
||||||
|
* along with corresponding metadata objects.
|
||||||
|
*
|
||||||
|
* @return a number of events inserted to DB, possibly needing a notification
|
||||||
|
*/
|
||||||
|
fun run(): Int {
|
||||||
|
val profiles = profiles.filter { it.registration == Profile.REGISTRATION_ENABLED && !it.archived }
|
||||||
|
if (profiles.isNotEmpty()) {
|
||||||
|
val blacklistedIds = app.db.eventDao().blacklistedIds;
|
||||||
|
val events = api.getEvents(profiles, notifications, blacklistedIds)
|
||||||
|
|
||||||
|
if (events.isNotEmpty()) {
|
||||||
|
app.db.metadataDao().addAllIgnore(events.map { event ->
|
||||||
|
Metadata(
|
||||||
|
event.profileId,
|
||||||
|
Metadata.TYPE_EVENT,
|
||||||
|
event.id,
|
||||||
|
event.seen,
|
||||||
|
event.notified,
|
||||||
|
event.addedDate
|
||||||
|
)
|
||||||
|
})
|
||||||
|
return app.db.eventDao().addAll(events).size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -39,4 +39,18 @@ abstract class IApiTask(open val profileId: Int) {
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "IApiTask(profileId=$profileId, taskId=$taskId, profile=$profile, taskName=$taskName)"
|
return "IApiTask(profileId=$profileId, taskId=$taskId, profile=$profile, taskName=$taskName)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun enqueueAll(context: Context, tasks: List<IApiTask>) {
|
||||||
|
Intent(context, ApiService::class.java).let {
|
||||||
|
if (SDK_INT >= O)
|
||||||
|
context.startForegroundService(it)
|
||||||
|
else
|
||||||
|
context.startService(it)
|
||||||
|
}
|
||||||
|
tasks.forEach {
|
||||||
|
EventBus.getDefault().postSticky(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-1-16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.task
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
|
import pl.szczodrzynski.edziennik.R
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||||
|
import pl.szczodrzynski.edziennik.getNotificationTitle
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
|
class Notifications(val app: App, val notifications: MutableList<Notification>, val profiles: List<Profile>) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "Notifications"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val today by lazy { Date.getToday() }
|
||||||
|
private val todayValue by lazy { today.value }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a [Notification] from every possible
|
||||||
|
* data type. Notifications are posted whenever
|
||||||
|
* the object's metadata `notified` property is
|
||||||
|
* set to false.
|
||||||
|
*/
|
||||||
|
fun run() {
|
||||||
|
timetableNotifications()
|
||||||
|
eventNotifications()
|
||||||
|
gradeNotifications()
|
||||||
|
behaviourNotifications()
|
||||||
|
attendanceNotifications()
|
||||||
|
announcementNotifications()
|
||||||
|
messageNotifications()
|
||||||
|
luckyNumberNotifications()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun timetableNotifications() {
|
||||||
|
for (lesson in app.db.timetableDao().getNotNotifiedNow()) {
|
||||||
|
val text = app.getString(
|
||||||
|
R.string.notification_lesson_change_format,
|
||||||
|
lesson.getDisplayChangeType(app),
|
||||||
|
if (lesson.displayDate == null) "" else lesson.displayDate!!.formattedString,
|
||||||
|
lesson.changeSubjectName
|
||||||
|
)
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(lesson.profileId, Notification.TYPE_TIMETABLE_LESSON_CHANGE, lesson.id),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_TIMETABLE_LESSON_CHANGE),
|
||||||
|
text = text,
|
||||||
|
type = Notification.TYPE_TIMETABLE_LESSON_CHANGE,
|
||||||
|
profileId = lesson.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == lesson.profileId }?.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_TIMETABLE,
|
||||||
|
addedDate = lesson.addedDate
|
||||||
|
).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun eventNotifications() {
|
||||||
|
for (event in app.db.eventDao().notNotifiedNow) {
|
||||||
|
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) Notification.TYPE_NEW_HOMEWORK else Notification.TYPE_NEW_EVENT
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(event.profileId, type, event.id),
|
||||||
|
title = app.getNotificationTitle(type),
|
||||||
|
text = text,
|
||||||
|
type = type,
|
||||||
|
profileId = event.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
|
||||||
|
viewId = if (event.type == Event.TYPE_HOMEWORK) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
|
||||||
|
addedDate = event.addedDate
|
||||||
|
).addExtra("eventId", event.id).addExtra("eventDate", event.eventDate.value.toLong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sharedEventNotifications() {
|
||||||
|
for (event in app.db.eventDao().notNotifiedNow.filter { it.sharedBy != null }) {
|
||||||
|
val text = app.getString(
|
||||||
|
R.string.notification_shared_event_format,
|
||||||
|
event.sharedByName,
|
||||||
|
event.typeName ?: "wydarzenie",
|
||||||
|
event.eventDate.formattedString,
|
||||||
|
event.topic
|
||||||
|
)
|
||||||
|
val type = if (event.type == Event.TYPE_HOMEWORK) Notification.TYPE_NEW_HOMEWORK else Notification.TYPE_NEW_EVENT
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(event.profileId, type, event.id),
|
||||||
|
title = app.getNotificationTitle(type),
|
||||||
|
text = text,
|
||||||
|
type = type,
|
||||||
|
profileId = event.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
|
||||||
|
viewId = if (event.type == Event.TYPE_HOMEWORK) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
|
||||||
|
addedDate = event.addedDate
|
||||||
|
).addExtra("eventId", event.id).addExtra("eventDate", event.eventDate.value.toLong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun gradeNotifications() {
|
||||||
|
for (grade in app.db.gradeDao().notNotifiedNow) {
|
||||||
|
val gradeName = when (grade.type) {
|
||||||
|
Grade.TYPE_SEMESTER1_PROPOSED, Grade.TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format_2, grade.name)
|
||||||
|
Grade.TYPE_SEMESTER1_FINAL, Grade.TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format_2, grade.name)
|
||||||
|
Grade.TYPE_YEAR_PROPOSED -> app.getString(R.string.grade_year_proposed_format_2, grade.name)
|
||||||
|
Grade.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
|
||||||
|
)
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(grade.profileId, Notification.TYPE_NEW_GRADE, grade.id),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_NEW_GRADE),
|
||||||
|
text = text,
|
||||||
|
type = Notification.TYPE_NEW_GRADE,
|
||||||
|
profileId = grade.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == grade.profileId }?.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_GRADES,
|
||||||
|
addedDate = grade.addedDate
|
||||||
|
).addExtra("gradeId", grade.id).addExtra("gradesSubjectId", grade.subjectId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun behaviourNotifications() {
|
||||||
|
for (notice in app.db.noticeDao().notNotifiedNow) {
|
||||||
|
|
||||||
|
val noticeTypeStr = when (notice.type) {
|
||||||
|
Notice.TYPE_POSITIVE -> app.getString(R.string.notification_notice_praise)
|
||||||
|
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
|
||||||
|
)
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(notice.profileId, Notification.TYPE_NEW_NOTICE, notice.id),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_NEW_NOTICE),
|
||||||
|
text = text,
|
||||||
|
type = Notification.TYPE_NEW_NOTICE,
|
||||||
|
profileId = notice.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == notice.profileId }?.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_BEHAVIOUR,
|
||||||
|
addedDate = notice.addedDate
|
||||||
|
).addExtra("noticeId", notice.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun attendanceNotifications() {
|
||||||
|
for (attendance in app.db.attendanceDao().notNotifiedNow) {
|
||||||
|
|
||||||
|
val attendanceTypeStr = when (attendance.type) {
|
||||||
|
Attendance.TYPE_ABSENT -> app.getString(R.string.notification_absence)
|
||||||
|
Attendance.TYPE_ABSENT_EXCUSED -> app.getString(R.string.notification_absence_excused)
|
||||||
|
Attendance.TYPE_BELATED -> app.getString(R.string.notification_belated)
|
||||||
|
Attendance.TYPE_BELATED_EXCUSED -> app.getString(R.string.notification_belated_excused)
|
||||||
|
Attendance.TYPE_RELEASED -> app.getString(R.string.notification_release)
|
||||||
|
Attendance.TYPE_DAY_FREE -> app.getString(R.string.notification_day_free)
|
||||||
|
else -> app.getString(R.string.notification_type_attendance)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(attendance.profileId, Notification.TYPE_NEW_ATTENDANCE, attendance.id),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_NEW_ATTENDANCE),
|
||||||
|
text = text,
|
||||||
|
type = Notification.TYPE_NEW_ATTENDANCE,
|
||||||
|
profileId = attendance.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == attendance.profileId }?.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_ATTENDANCE,
|
||||||
|
addedDate = attendance.addedDate
|
||||||
|
).addExtra("attendanceId", attendance.id).addExtra("attendanceSubjectId", attendance.subjectId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun announcementNotifications() {
|
||||||
|
for (announcement in app.db.announcementDao().notNotifiedNow) {
|
||||||
|
val text = app.getString(
|
||||||
|
R.string.notification_announcement_format,
|
||||||
|
announcement.teacherFullName,
|
||||||
|
announcement.subject
|
||||||
|
)
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(announcement.profileId, Notification.TYPE_NEW_ANNOUNCEMENT, announcement.id),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_NEW_ANNOUNCEMENT),
|
||||||
|
text = text,
|
||||||
|
type = Notification.TYPE_NEW_ANNOUNCEMENT,
|
||||||
|
profileId = announcement.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == announcement.profileId }?.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_ANNOUNCEMENTS,
|
||||||
|
addedDate = announcement.addedDate
|
||||||
|
).addExtra("announcementId", announcement.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun messageNotifications() {
|
||||||
|
for (message in app.db.messageDao().receivedNotNotifiedNow) {
|
||||||
|
val text = app.getString(
|
||||||
|
R.string.notification_message_format,
|
||||||
|
message.senderFullName,
|
||||||
|
message.subject
|
||||||
|
)
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(message.profileId, Notification.TYPE_NEW_MESSAGE, message.id),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_NEW_MESSAGE),
|
||||||
|
text = text,
|
||||||
|
type = Notification.TYPE_NEW_MESSAGE,
|
||||||
|
profileId = message.profileId,
|
||||||
|
profileName = profiles.singleOrNull { it.id == message.profileId }?.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_MESSAGES,
|
||||||
|
addedDate = message.addedDate
|
||||||
|
).addExtra("messageType", Message.TYPE_RECEIVED.toLong()).addExtra("messageId", message.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun luckyNumberNotifications() {
|
||||||
|
val luckyNumbers = app.db.luckyNumberDao().notNotifiedNow
|
||||||
|
luckyNumbers?.removeAll { it.date < today }
|
||||||
|
luckyNumbers?.forEach { luckyNumber ->
|
||||||
|
val profile = profiles.singleOrNull { it.id == luckyNumber.profileId } ?: return@forEach
|
||||||
|
val text = when (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) {
|
||||||
|
true -> when (luckyNumber.date.value) {
|
||||||
|
todayValue -> R.string.notification_lucky_number_yours_format
|
||||||
|
todayValue + 1 -> R.string.notification_lucky_number_yours_tomorrow_format
|
||||||
|
else -> R.string.notification_lucky_number_yours_later_format
|
||||||
|
}
|
||||||
|
else -> when (luckyNumber.date.value) {
|
||||||
|
todayValue -> R.string.notification_lucky_number_format
|
||||||
|
todayValue + 1 -> R.string.notification_lucky_number_tomorrow_format
|
||||||
|
else -> R.string.notification_lucky_number_later_format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifications += Notification(
|
||||||
|
id = Notification.buildId(luckyNumber.profileId, Notification.TYPE_LUCKY_NUMBER, luckyNumber.date.value.toLong()),
|
||||||
|
title = app.getNotificationTitle(Notification.TYPE_LUCKY_NUMBER),
|
||||||
|
text = app.getString(text, luckyNumber.date.formattedString, luckyNumber.number),
|
||||||
|
type = Notification.TYPE_LUCKY_NUMBER,
|
||||||
|
profileId = luckyNumber.profileId,
|
||||||
|
profileName = profile.name,
|
||||||
|
viewId = MainActivity.DRAWER_ITEM_HOME,
|
||||||
|
addedDate = luckyNumber.addedDate
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,90 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.task
|
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
|
||||||
import pl.szczodrzynski.edziennik.Notifier.ID_NOTIFICATIONS
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
|
||||||
import pl.szczodrzynski.edziennik.getNotificationTitle
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Notification
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class NotifyTask : IApiTask(-1) {
|
|
||||||
override fun prepare(app: App) {
|
|
||||||
taskName = app.getString(R.string.edziennik_notification_api_notify_title)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cancel() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun run(app: App, taskCallback: EdziennikCallback) {
|
|
||||||
val list = app.db.notificationDao().getNotPostedNow()
|
|
||||||
val notificationList = list.subList(0, min(10, list.size))
|
|
||||||
|
|
||||||
val unreadCount = list.size
|
|
||||||
|
|
||||||
for (notification in notificationList) {
|
|
||||||
val intent = Intent(app, MainActivity::class.java)
|
|
||||||
notification.fillIntent(intent)
|
|
||||||
val pendingIntent = PendingIntent.getActivity(app, notification.id, intent, 0)
|
|
||||||
val notificationBuilder = NotificationCompat.Builder(app, app.notifier.notificationGroup)
|
|
||||||
// title, text, type, date
|
|
||||||
.setContentTitle(notification.profileName)
|
|
||||||
.setContentText(notification.text)
|
|
||||||
.setSubText(app.getNotificationTitle(notification.type))
|
|
||||||
.setWhen(notification.addedDate)
|
|
||||||
.setTicker(app.getString(R.string.notification_ticker_format, Notification.stringType(app, notification.type)))
|
|
||||||
// icon, color, lights, priority
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
|
||||||
.setColor(app.notifier.notificationColor)
|
|
||||||
.setLights(-0xff0001, 2000, 2000)
|
|
||||||
.setPriority(app.notifier.notificationPriority)
|
|
||||||
// channel, group, style
|
|
||||||
.setChannelId(app.notifier.notificationGroup)
|
|
||||||
.setGroup(app.notifier.notificationGroup)
|
|
||||||
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
|
|
||||||
.setStyle(NotificationCompat.BigTextStyle().bigText(notification.text))
|
|
||||||
// intent, auto cancel
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
if (!app.notifier.shouldBeQuiet()) {
|
|
||||||
notificationBuilder.setDefaults(app.notifier.notificationDefaults)
|
|
||||||
}
|
|
||||||
app.notifier.notificationManager.notify(notification.id, notificationBuilder.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notificationList.isNotEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
val intent = Intent(app, MainActivity::class.java)
|
|
||||||
intent.action = "android.intent.action.MAIN"
|
|
||||||
intent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_NOTIFICATIONS)
|
|
||||||
val pendingIntent = PendingIntent.getActivity(app, ID_NOTIFICATIONS,
|
|
||||||
intent, 0)
|
|
||||||
|
|
||||||
val groupBuilder = NotificationCompat.Builder(app, app.notifier.notificationGroup)
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
|
||||||
.setColor(app.notifier.notificationColor)
|
|
||||||
.setContentTitle(app.getString(R.string.notification_new_notification_title_format, unreadCount))
|
|
||||||
.setGroupSummary(true)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
.setChannelId(app.notifier.notificationGroup)
|
|
||||||
.setGroup(app.notifier.notificationGroup)
|
|
||||||
.setLights(-0xff0001, 2000, 2000)
|
|
||||||
.setPriority(app.notifier.notificationPriority)
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setStyle(NotificationCompat.BigTextStyle())
|
|
||||||
if (!app.notifier.shouldBeQuiet()) {
|
|
||||||
groupBuilder.setDefaults(app.notifier.notificationDefaults)
|
|
||||||
}
|
|
||||||
app.notifier.notificationManager.notify(ID_NOTIFICATIONS, groupBuilder.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
app.db.notificationDao().setAllPosted()
|
|
||||||
|
|
||||||
taskCallback.onCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,172 @@
|
|||||||
|
package pl.szczodrzynski.edziennik.data.api.task
|
||||||
|
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.SparseIntArray
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.util.forEach
|
||||||
|
import androidx.core.util.set
|
||||||
|
import pl.szczodrzynski.edziennik.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_SERVER_MESSAGE
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Notification as AppNotification
|
||||||
|
|
||||||
|
class PostNotifications(val app: App, nList: List<AppNotification>) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "PostNotifications"
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public boolean shouldBeQuiet() {
|
||||||
|
long now = Time.getNow().getInMillis();
|
||||||
|
long start = app.config.getSync().getQuietHoursStart();
|
||||||
|
long end = app.config.getSync().getQuietHoursEnd();
|
||||||
|
if (start > end) {
|
||||||
|
end += 1000 * 60 * 60 * 24;
|
||||||
|
//Log.d(TAG, "Night passing");
|
||||||
|
}
|
||||||
|
if (start > now) {
|
||||||
|
now += 1000 * 60 * 60 * 24;
|
||||||
|
//Log.d(TAG, "Now is smaller");
|
||||||
|
}
|
||||||
|
//Log.d(TAG, "Start is "+start+", now is "+now+", end is "+end);
|
||||||
|
return start > 0 && now >= start && now <= end;
|
||||||
|
}*/
|
||||||
|
fun shouldBeQuiet() = false
|
||||||
|
|
||||||
|
private fun buildSummaryText(summaryCounts: SparseIntArray): CharSequence {
|
||||||
|
val summaryTexts = mutableListOf<String>()
|
||||||
|
summaryCounts.forEach { key, value ->
|
||||||
|
if (value <= 0)
|
||||||
|
return@forEach
|
||||||
|
val pluralRes = when (key) {
|
||||||
|
AppNotification.TYPE_TIMETABLE_LESSON_CHANGE -> R.plurals.notification_new_timetable_change_format
|
||||||
|
AppNotification.TYPE_NEW_GRADE -> R.plurals.notification_new_grades_format
|
||||||
|
AppNotification.TYPE_NEW_EVENT -> R.plurals.notification_new_events_format
|
||||||
|
AppNotification.TYPE_NEW_HOMEWORK -> R.plurals.notification_new_homework_format
|
||||||
|
AppNotification.TYPE_NEW_SHARED_EVENT -> R.plurals.notification_new_shared_events_format
|
||||||
|
AppNotification.TYPE_NEW_SHARED_HOMEWORK -> R.plurals.notification_new_shared_homework_format
|
||||||
|
AppNotification.TYPE_NEW_MESSAGE -> R.plurals.notification_new_messages_format
|
||||||
|
AppNotification.TYPE_NEW_NOTICE -> R.plurals.notification_new_notices_format
|
||||||
|
AppNotification.TYPE_NEW_ATTENDANCE -> R.plurals.notification_new_attendance_format
|
||||||
|
AppNotification.TYPE_LUCKY_NUMBER -> R.plurals.notification_new_lucky_number_format
|
||||||
|
AppNotification.TYPE_NEW_ANNOUNCEMENT -> R.plurals.notification_new_announcements_format
|
||||||
|
else -> R.plurals.notification_other_format
|
||||||
|
}
|
||||||
|
summaryTexts += app.resources.getQuantityString(pluralRes, value, value)
|
||||||
|
}
|
||||||
|
return summaryTexts.concat(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
init { run {
|
||||||
|
val count = nList.size
|
||||||
|
if (count == 0)
|
||||||
|
return@run
|
||||||
|
val notificationManager = app.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
val summaryCounts = SparseIntArray()
|
||||||
|
|
||||||
|
val newNotificationsText = app.resources.getQuantityString(R.plurals.notification_count_format, count, count)
|
||||||
|
val newNotificationsShortText = app.resources.getQuantityString(R.plurals.notification_count_short_format, count, count)
|
||||||
|
|
||||||
|
val intent = Intent(
|
||||||
|
app,
|
||||||
|
MainActivity::class.java,
|
||||||
|
"fragmentId" to MainActivity.DRAWER_ITEM_NOTIFICATIONS
|
||||||
|
)
|
||||||
|
val summaryIntent = PendingIntent.getActivity(app, app.notifications.dataId, intent, PendingIntent.FLAG_ONE_SHOT)
|
||||||
|
|
||||||
|
// On Nougat or newer - show maximum 8 notifications
|
||||||
|
// On Marshmallow or older - show maximum 4 notifications
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && count > 4 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && count > 8) {
|
||||||
|
val summaryList = mutableListOf<CharSequence>()
|
||||||
|
nList.forEach {
|
||||||
|
summaryCounts[it.type]++
|
||||||
|
summaryList += listOf(
|
||||||
|
it.profileName.asBoldSpannable(),
|
||||||
|
it.text
|
||||||
|
).concat(": ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a summary to show *instead* of notifications
|
||||||
|
val combined = NotificationCompat.Builder(app, app.notifications.dataKey)
|
||||||
|
.setContentTitle(app.getString(R.string.app_name))
|
||||||
|
.setContentText(buildSummaryText(summaryCounts))
|
||||||
|
.setTicker(newNotificationsText)
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setStyle(NotificationCompat.InboxStyle()
|
||||||
|
.also {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
it.setBigContentTitle(app.getString(R.string.app_name))
|
||||||
|
it.setSummaryText(newNotificationsShortText)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it.setBigContentTitle(newNotificationsText)
|
||||||
|
it.setSummaryText(app.getString(R.string.notification_click_to_see_all))
|
||||||
|
}
|
||||||
|
summaryList.forEach { line ->
|
||||||
|
it.addLine(line)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setColor(0xff2196f3.toInt())
|
||||||
|
.setLights(0xff2196f3.toInt(), 2000, 2000)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||||
|
.setGroup(app.notifications.dataKey)
|
||||||
|
.setContentIntent(summaryIntent)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.build()
|
||||||
|
notificationManager.notify(System.currentTimeMillis().toInt(), combined)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Less than 8 notifications
|
||||||
|
val notifications = nList.map {
|
||||||
|
summaryCounts[it.type]++
|
||||||
|
NotificationCompat.Builder(app, app.notifications.dataKey)
|
||||||
|
.setContentTitle(it.profileName ?: app.getString(R.string.app_name))
|
||||||
|
.setContentText(it.text)
|
||||||
|
.setSubText(if (it.type == TYPE_SERVER_MESSAGE) null else it.title)
|
||||||
|
.setTicker("${it.profileName}: ${it.title}")
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setStyle(NotificationCompat.BigTextStyle()
|
||||||
|
.bigText(it.text))
|
||||||
|
.setWhen(it.addedDate)
|
||||||
|
.setColor(0xff2196f3.toInt())
|
||||||
|
.setLights(0xff2196f3.toInt(), 2000, 2000)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||||
|
.setGroup(app.notifications.dataKey)
|
||||||
|
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
|
||||||
|
.setContentIntent(it.getPendingIntent(app))
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
val time = System.currentTimeMillis()
|
||||||
|
notificationManager.apply {
|
||||||
|
notifications.forEachIndexed { index, it ->
|
||||||
|
notificationManager.notify((time + index).toInt(), it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
val summary = NotificationCompat.Builder(app, app.notifications.dataKey)
|
||||||
|
.setContentTitle(newNotificationsText)
|
||||||
|
.setContentText(buildSummaryText(summaryCounts))
|
||||||
|
.setTicker(newNotificationsText)
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setColor(0xff2196f3.toInt())
|
||||||
|
.setLights(0xff2196f3.toInt(), 2000, 2000)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||||
|
.setGroup(app.notifications.dataKey)
|
||||||
|
.setGroupSummary(true)
|
||||||
|
.setContentIntent(summaryIntent)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
notificationManager.notify(app.notifications.dataId, summary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
@ -7,39 +7,39 @@ package pl.szczodrzynski.edziennik.data.api.task
|
|||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.Szkolny
|
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Notification
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
class SzkolnyTask(val request: Any) : IApiTask(-1) {
|
class SzkolnyTask(val app: App, val syncingProfiles: List<Profile>) : IApiTask(-1) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SzkolnyTask"
|
private const val TAG = "SzkolnyTask"
|
||||||
|
|
||||||
fun sync(profiles: List<Profile>) = SzkolnyTask(SyncRequest(profiles))
|
|
||||||
/*fun shareEvent(event: EventFull) = SzkolnyTask(ShareEventRequest(event))
|
|
||||||
fun unshareEvent(event: EventFull) = SzkolnyTask(UnshareEventRequest(event))*/
|
|
||||||
}
|
}
|
||||||
|
private val api by lazy { SzkolnyApi(app) }
|
||||||
|
private val profiles by lazy { app.db.profileDao().allNow }
|
||||||
|
override fun prepare(app: App) { taskName = app.getString(R.string.edziennik_szkolny_creating_notifications) }
|
||||||
|
override fun cancel() {}
|
||||||
|
|
||||||
private lateinit var szkolny: Szkolny
|
private val notificationList = mutableListOf<Notification>()
|
||||||
|
|
||||||
override fun prepare(app: App) {
|
internal fun run(taskCallback: EdziennikCallback) {
|
||||||
taskName = app.getString(R.string.edziennik_szkolny_api_sync_title)
|
val startTime = System.currentTimeMillis()
|
||||||
|
val notifications = Notifications(app, notificationList, profiles)
|
||||||
|
// create all e-register data notifications
|
||||||
|
notifications.run()
|
||||||
|
// send notifications to web push, get shared events
|
||||||
|
AppSync(app, notificationList, profiles, api).run()
|
||||||
|
// create notifications for shared events (not present before app sync)
|
||||||
|
notifications.sharedEventNotifications()
|
||||||
|
d(TAG, "Created ${notificationList.count()} notifications.")
|
||||||
|
// update the database
|
||||||
|
app.db.metadataDao().setAllNotified(true)
|
||||||
|
app.db.notificationDao().addAll(notificationList)
|
||||||
|
app.db.profileDao().setAllNotEmpty()
|
||||||
|
// post all notifications
|
||||||
|
PostNotifications(app, notificationList)
|
||||||
|
d(TAG, "SzkolnyTask: finished in ${System.currentTimeMillis()-startTime} ms.")
|
||||||
|
taskCallback.onCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cancel() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun run(app: App, taskCallback: EdziennikCallback) {
|
|
||||||
szkolny = Szkolny(app, taskCallback)
|
|
||||||
|
|
||||||
when (request) {
|
|
||||||
is SyncRequest -> szkolny.sync(request.profiles)
|
|
||||||
/*is ShareEventRequest -> szkolny.shareEvent(request.event)
|
|
||||||
is UnshareEventRequest -> szkolny.unshareEvent(request.event)*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class SyncRequest(val profiles: List<Profile>)
|
|
||||||
/*data class ShareEventRequest(val event: EventFull)
|
|
||||||
data class UnshareEventRequest(val event: EventFull)*/
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
165
app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt
Normal file
165
app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
package pl.szczodrzynski.edziennik.data.db
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import androidx.room.TypeConverters
|
||||||
|
import pl.szczodrzynski.edziennik.config.db.ConfigDao
|
||||||
|
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.converter.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.dao.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.migration.*
|
||||||
|
|
||||||
|
@Database(entities = [
|
||||||
|
Grade::class,
|
||||||
|
Teacher::class,
|
||||||
|
TeacherAbsence::class,
|
||||||
|
TeacherAbsenceType::class,
|
||||||
|
Subject::class,
|
||||||
|
Notice::class,
|
||||||
|
Team::class,
|
||||||
|
Attendance::class,
|
||||||
|
Event::class,
|
||||||
|
EventType::class,
|
||||||
|
LoginStore::class,
|
||||||
|
Profile::class,
|
||||||
|
LuckyNumber::class,
|
||||||
|
Announcement::class,
|
||||||
|
GradeCategory::class,
|
||||||
|
FeedbackMessage::class,
|
||||||
|
Message::class,
|
||||||
|
MessageRecipient::class,
|
||||||
|
DebugLog::class,
|
||||||
|
EndpointTimer::class,
|
||||||
|
LessonRange::class,
|
||||||
|
Notification::class,
|
||||||
|
Classroom::class,
|
||||||
|
NoticeType::class,
|
||||||
|
AttendanceType::class,
|
||||||
|
Lesson::class,
|
||||||
|
ConfigEntry::class,
|
||||||
|
LibrusLesson::class,
|
||||||
|
Metadata::class
|
||||||
|
], version = 76)
|
||||||
|
@TypeConverters(
|
||||||
|
ConverterTime::class,
|
||||||
|
ConverterDate::class,
|
||||||
|
ConverterJsonObject::class,
|
||||||
|
ConverterListLong::class,
|
||||||
|
ConverterListString::class,
|
||||||
|
ConverterDateInt::class
|
||||||
|
)
|
||||||
|
abstract class AppDb : RoomDatabase() {
|
||||||
|
abstract fun gradeDao(): GradeDao
|
||||||
|
abstract fun teacherDao(): TeacherDao
|
||||||
|
abstract fun teacherAbsenceDao(): TeacherAbsenceDao
|
||||||
|
abstract fun teacherAbsenceTypeDao(): TeacherAbsenceTypeDao
|
||||||
|
abstract fun subjectDao(): SubjectDao
|
||||||
|
abstract fun noticeDao(): NoticeDao
|
||||||
|
abstract fun teamDao(): TeamDao
|
||||||
|
abstract fun attendanceDao(): AttendanceDao
|
||||||
|
abstract fun eventDao(): EventDao
|
||||||
|
abstract fun eventTypeDao(): EventTypeDao
|
||||||
|
abstract fun loginStoreDao(): LoginStoreDao
|
||||||
|
abstract fun profileDao(): ProfileDao
|
||||||
|
abstract fun luckyNumberDao(): LuckyNumberDao
|
||||||
|
abstract fun announcementDao(): AnnouncementDao
|
||||||
|
abstract fun gradeCategoryDao(): GradeCategoryDao
|
||||||
|
abstract fun feedbackMessageDao(): FeedbackMessageDao
|
||||||
|
abstract fun messageDao(): MessageDao
|
||||||
|
abstract fun messageRecipientDao(): MessageRecipientDao
|
||||||
|
abstract fun debugLogDao(): DebugLogDao
|
||||||
|
abstract fun endpointTimerDao(): EndpointTimerDao
|
||||||
|
abstract fun lessonRangeDao(): LessonRangeDao
|
||||||
|
abstract fun notificationDao(): NotificationDao
|
||||||
|
abstract fun classroomDao(): ClassroomDao
|
||||||
|
abstract fun noticeTypeDao(): NoticeTypeDao
|
||||||
|
abstract fun attendanceTypeDao(): AttendanceTypeDao
|
||||||
|
abstract fun timetableDao(): TimetableDao
|
||||||
|
abstract fun configDao(): ConfigDao
|
||||||
|
abstract fun librusLessonDao(): LibrusLessonDao
|
||||||
|
abstract fun metadataDao(): MetadataDao
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Volatile private var instance: AppDb? = null
|
||||||
|
private val LOCK = Any()
|
||||||
|
|
||||||
|
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
|
||||||
|
instance ?: buildDatabase(context).also { instance = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildDatabase(context: Context) = Room.databaseBuilder(
|
||||||
|
context.applicationContext,
|
||||||
|
AppDb::class.java,
|
||||||
|
"edziennik.db"
|
||||||
|
).addMigrations(
|
||||||
|
Migration12(),
|
||||||
|
Migration13(),
|
||||||
|
Migration14(),
|
||||||
|
Migration15(),
|
||||||
|
Migration16(),
|
||||||
|
Migration17(),
|
||||||
|
Migration18(),
|
||||||
|
Migration19(),
|
||||||
|
Migration20(),
|
||||||
|
Migration21(),
|
||||||
|
Migration22(),
|
||||||
|
Migration23(),
|
||||||
|
Migration24(),
|
||||||
|
Migration25(),
|
||||||
|
Migration26(),
|
||||||
|
Migration27(),
|
||||||
|
Migration28(),
|
||||||
|
Migration29(),
|
||||||
|
Migration30(),
|
||||||
|
Migration31(),
|
||||||
|
Migration32(),
|
||||||
|
Migration33(),
|
||||||
|
Migration34(),
|
||||||
|
Migration35(),
|
||||||
|
Migration36(),
|
||||||
|
Migration37(),
|
||||||
|
Migration38(),
|
||||||
|
Migration39(),
|
||||||
|
Migration40(),
|
||||||
|
Migration41(),
|
||||||
|
Migration42(),
|
||||||
|
Migration43(),
|
||||||
|
Migration44(),
|
||||||
|
Migration45(),
|
||||||
|
Migration46(),
|
||||||
|
Migration47(),
|
||||||
|
Migration48(),
|
||||||
|
Migration49(),
|
||||||
|
Migration50(),
|
||||||
|
Migration51(),
|
||||||
|
Migration52(),
|
||||||
|
Migration53(),
|
||||||
|
Migration54(),
|
||||||
|
Migration55(),
|
||||||
|
Migration56(),
|
||||||
|
Migration57(),
|
||||||
|
Migration58(),
|
||||||
|
Migration59(),
|
||||||
|
Migration60(),
|
||||||
|
Migration61(),
|
||||||
|
Migration62(),
|
||||||
|
Migration63(),
|
||||||
|
Migration64(),
|
||||||
|
Migration65(),
|
||||||
|
Migration66(),
|
||||||
|
Migration67(),
|
||||||
|
Migration68(),
|
||||||
|
Migration69(),
|
||||||
|
Migration70(),
|
||||||
|
Migration71(),
|
||||||
|
Migration72(),
|
||||||
|
Migration73(),
|
||||||
|
Migration74(),
|
||||||
|
Migration75(),
|
||||||
|
Migration76()
|
||||||
|
).allowMainThreadQueries().build()
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,8 @@ import androidx.sqlite.db.SupportSQLiteQuery;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Announcement;
|
import pl.szczodrzynski.edziennik.data.db.entity.Announcement;
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull;
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ANNOUNCEMENT;
|
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ANNOUNCEMENT;
|
||||||
|
|
||||||
@ -69,4 +69,14 @@ public abstract class AnnouncementDao {
|
|||||||
public List<AnnouncementFull> getNotNotifiedNow(int profileId) {
|
public List<AnnouncementFull> getNotNotifiedNow(int profileId) {
|
||||||
return getAllNow(profileId, "notified = 0");
|
return getAllNow(profileId, "notified = 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("SELECT " +
|
||||||
|
"*, " +
|
||||||
|
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName " +
|
||||||
|
"FROM announcements " +
|
||||||
|
"LEFT JOIN teachers USING(profileId, teacherId) " +
|
||||||
|
"LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = announcements.profileId " +
|
||||||
|
"WHERE notified = 0 " +
|
||||||
|
"ORDER BY addedDate DESC")
|
||||||
|
public abstract List<AnnouncementFull> getNotNotifiedNow();
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,20 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.db.dao;
|
package pl.szczodrzynski.edziennik.data.db.dao;
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.sqlite.db.SimpleSQLiteQuery;
|
|
||||||
import androidx.sqlite.db.SupportSQLiteQuery;
|
|
||||||
import androidx.room.Dao;
|
import androidx.room.Dao;
|
||||||
import androidx.room.Insert;
|
import androidx.room.Insert;
|
||||||
import androidx.room.OnConflictStrategy;
|
import androidx.room.OnConflictStrategy;
|
||||||
import androidx.room.Query;
|
import androidx.room.Query;
|
||||||
import androidx.room.RawQuery;
|
import androidx.room.RawQuery;
|
||||||
|
import androidx.sqlite.db.SimpleSQLiteQuery;
|
||||||
|
import androidx.sqlite.db.SupportSQLiteQuery;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance;
|
import pl.szczodrzynski.edziennik.data.db.entity.Attendance;
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull;
|
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ATTENDANCE;
|
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ATTENDANCE;
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -72,6 +72,13 @@ public abstract class AttendanceDao {
|
|||||||
return getAllNow(profileId, "notified = 0");
|
return getAllNow(profileId, "notified = 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("SELECT * FROM attendances " +
|
||||||
|
"LEFT JOIN subjects USING(profileId, subjectId) " +
|
||||||
|
"LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = attendances.profileId " +
|
||||||
|
"WHERE notified = 0 " +
|
||||||
|
"ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC")
|
||||||
|
public abstract List<AttendanceFull> getNotNotifiedNow();
|
||||||
|
|
||||||
// only absent and absent_excused count as absences
|
// only absent and absent_excused count as absences
|
||||||
// all the other types are counted as being present
|
// all the other types are counted as being present
|
||||||
@Query("SELECT \n" +
|
@Query("SELECT \n" +
|
||||||
|
@ -34,7 +34,7 @@ public abstract class EventDao {
|
|||||||
public abstract long add(Event event);
|
public abstract long add(Event event);
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
public abstract void addAll(List<Event> eventList);
|
public abstract long[] addAll(List<Event> eventList);
|
||||||
|
|
||||||
@Query("DELETE FROM events WHERE profileId = :profileId")
|
@Query("DELETE FROM events WHERE profileId = :profileId")
|
||||||
public abstract void clear(int profileId);
|
public abstract void clear(int profileId);
|
||||||
@ -44,7 +44,7 @@ public abstract class EventDao {
|
|||||||
@Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND thingId = :thingId")
|
@Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND thingId = :thingId")
|
||||||
public abstract void removeMetadata(int profileId, int thingType, long thingId);
|
public abstract void removeMetadata(int profileId, int thingType, long thingId);
|
||||||
@Transaction
|
@Transaction
|
||||||
public void remove(int profileId, int type, long id) {
|
public void remove(int profileId, long type, long id) {
|
||||||
remove(profileId, id);
|
remove(profileId, id);
|
||||||
removeMetadata(profileId, type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, id);
|
removeMetadata(profileId, type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, id);
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ public abstract class EventDao {
|
|||||||
public LiveData<List<EventFull>> getAllWhere(int profileId, String filter) {
|
public LiveData<List<EventFull>> getAllWhere(int profileId, String filter) {
|
||||||
return getAll(profileId, filter);
|
return getAll(profileId, filter);
|
||||||
}
|
}
|
||||||
public LiveData<List<EventFull>> getAllByType(int profileId, int type, String filter) {
|
public LiveData<List<EventFull>> getAllByType(int profileId, long type, String filter) {
|
||||||
return getAll(profileId, "eventType = "+type+" AND "+filter);
|
return getAll(profileId, "eventType = "+type+" AND "+filter);
|
||||||
}
|
}
|
||||||
public LiveData<List<EventFull>> getAllByDate(int profileId, @NonNull Date date) {
|
public LiveData<List<EventFull>> getAllByDate(int profileId, @NonNull Date date) {
|
||||||
@ -125,6 +125,24 @@ public abstract class EventDao {
|
|||||||
return getAllNow(profileId, "notified = 0");
|
return getAllNow(profileId, "notified = 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("SELECT eventId FROM events WHERE profileId = :profileId AND eventBlacklisted = 1")
|
||||||
|
public abstract List<Long> getBlacklistedIds(int profileId);
|
||||||
|
@Query("SELECT eventId FROM events WHERE eventBlacklisted = 1")
|
||||||
|
public abstract List<Long> getBlacklistedIds();
|
||||||
|
|
||||||
|
@Query("SELECT " +
|
||||||
|
"*, " +
|
||||||
|
"eventTypes.eventTypeName AS typeName, " +
|
||||||
|
"eventTypes.eventTypeColor AS typeColor " +
|
||||||
|
"FROM events " +
|
||||||
|
"LEFT JOIN subjects USING(profileId, subjectId) " +
|
||||||
|
"LEFT JOIN eventTypes USING(profileId, eventType) " +
|
||||||
|
"LEFT JOIN metadata ON eventId = thingId AND (thingType = " + TYPE_EVENT + " OR thingType = " + TYPE_HOMEWORK + ") AND metadata.profileId = events.profileId " +
|
||||||
|
"WHERE events.eventBlacklisted = 0 AND notified = 0 " +
|
||||||
|
"GROUP BY eventId " +
|
||||||
|
"ORDER BY addedDate ASC")
|
||||||
|
public abstract List<EventFull> getNotNotifiedNow();
|
||||||
|
|
||||||
public EventFull getByIdNow(int profileId, long eventId) {
|
public EventFull getByIdNow(int profileId, long eventId) {
|
||||||
List<EventFull> eventList = getAllNow(profileId, "eventId = "+eventId);
|
List<EventFull> eventList = getAllNow(profileId, "eventId = "+eventId);
|
||||||
return eventList.size() == 0 ? null : eventList.get(0);
|
return eventList.size() == 0 ? null : eventList.get(0);
|
||||||
@ -146,13 +164,13 @@ public abstract class EventDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType = :type")
|
@Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType = :type")
|
||||||
public abstract void removeFutureWithType(int profileId, Date todayDate, int type);
|
public abstract void removeFutureWithType(int profileId, Date todayDate, long type);
|
||||||
|
|
||||||
@Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType != :exceptType")
|
@Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType != :exceptType")
|
||||||
public abstract void removeFutureExceptType(int profileId, Date todayDate, int exceptType);
|
public abstract void removeFutureExceptType(int profileId, Date todayDate, long exceptType);
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
public void removeFutureExceptTypes(int profileId, Date todayDate, List<Integer> exceptTypes) {
|
public void removeFutureExceptTypes(int profileId, Date todayDate, List<Long> exceptTypes) {
|
||||||
removeFuture(profileId, todayDate, "eventType NOT IN " + exceptTypes.toString().replace('[', '(').replace(']', ')'));
|
removeFuture(profileId, todayDate, "eventType NOT IN " + exceptTypes.toString().replace('[', '(').replace(']', ')'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.db.dao;
|
package pl.szczodrzynski.edziennik.data.db.dao;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.room.Dao;
|
import androidx.room.Dao;
|
||||||
import androidx.room.Insert;
|
import androidx.room.Insert;
|
||||||
import androidx.room.OnConflictStrategy;
|
import androidx.room.OnConflictStrategy;
|
||||||
import androidx.room.Query;
|
import androidx.room.Query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.EventType;
|
import pl.szczodrzynski.edziennik.data.db.entity.EventType;
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -26,11 +26,14 @@ public interface EventTypeDao {
|
|||||||
void clear(int profileId);
|
void clear(int profileId);
|
||||||
|
|
||||||
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId AND eventType = :typeId")
|
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId AND eventType = :typeId")
|
||||||
EventType getByIdNow(int profileId, int typeId);
|
EventType getByIdNow(int profileId, long typeId);
|
||||||
|
|
||||||
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
|
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
|
||||||
LiveData<List<EventType>> getAll(int profileId);
|
LiveData<List<EventType>> getAll(int profileId);
|
||||||
|
|
||||||
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
|
@Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
|
||||||
List<EventType> getAllNow(int profileId);
|
List<EventType> getAllNow(int profileId);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM eventTypes")
|
||||||
|
List<EventType> getAllNow();
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.db.dao;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.OnConflictStrategy;
|
|
||||||
import androidx.room.Query;
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.FeedbackMessageWithCount;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface FeedbackMessageDao {
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
void add(FeedbackMessage feedbackMessage);
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
void addAll(List<FeedbackMessage> feedbackMessageList);
|
|
||||||
|
|
||||||
@Query("DELETE FROM feedbackMessages")
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM feedbackMessages")
|
|
||||||
List<FeedbackMessage> getAllNow();
|
|
||||||
|
|
||||||
@Query("SELECT * FROM feedbackMessages WHERE fromUser = :fromUser")
|
|
||||||
List<FeedbackMessage> getAllByUserNow(String fromUser);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM feedbackMessages")
|
|
||||||
LiveData<List<FeedbackMessage>> getAll();
|
|
||||||
|
|
||||||
@Query("SELECT *, COUNT(*) AS messageCount FROM feedbackMessages GROUP BY fromUser ORDER BY sentTime DESC")
|
|
||||||
List<FeedbackMessageWithCount> getAllWithCountNow();
|
|
||||||
}
|
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
|
||||||
|
*/
|
||||||
|
package pl.szczodrzynski.edziennik.data.db.dao
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface FeedbackMessageDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun add(feedbackMessage: FeedbackMessage)
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun addAll(feedbackMessageList: List<FeedbackMessage>)
|
||||||
|
|
||||||
|
@Query("DELETE FROM feedbackMessages")
|
||||||
|
fun clear()
|
||||||
|
|
||||||
|
@get:Query("SELECT * FROM feedbackMessages ORDER BY sentTime DESC LIMIT 50")
|
||||||
|
val allNow: List<FeedbackMessage>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM feedbackMessages WHERE deviceId = :deviceId ORDER BY sentTime DESC LIMIT 50")
|
||||||
|
fun getByDeviceIdNow(deviceId: String): List<FeedbackMessage>
|
||||||
|
|
||||||
|
@get:Query("SELECT * FROM feedbackMessages")
|
||||||
|
val all: LiveData<List<FeedbackMessage>>
|
||||||
|
|
||||||
|
@get:Query("SELECT *, COUNT(*) AS count FROM feedbackMessages WHERE received = 1 AND devId IS NULL AND deviceId != 'szkolny.eu' GROUP BY deviceId ORDER BY sentTime DESC")
|
||||||
|
val allWithCountNow: List<FeedbackMessage.WithCount>
|
||||||
|
}
|
@ -83,6 +83,13 @@ public abstract class GradeDao {
|
|||||||
return getAllNow(profileId, "gradeParentId = "+parentId);
|
return getAllNow(profileId, "gradeParentId = "+parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("SELECT * FROM grades " +
|
||||||
|
"LEFT JOIN subjects USING(profileId, subjectId) " +
|
||||||
|
"LEFT JOIN metadata ON gradeId = thingId AND thingType = " + TYPE_GRADE + " AND metadata.profileId = grades.profileId " +
|
||||||
|
"WHERE notified = 0 " +
|
||||||
|
"ORDER BY addedDate DESC")
|
||||||
|
public abstract List<GradeFull> getNotNotifiedNow();
|
||||||
|
|
||||||
@RawQuery
|
@RawQuery
|
||||||
abstract GradeFull getNow(SupportSQLiteQuery query);
|
abstract GradeFull getNow(SupportSQLiteQuery query);
|
||||||
public GradeFull getNow(int profileId, String filter) {
|
public GradeFull getNow(int profileId, String filter) {
|
||||||
@ -145,7 +152,7 @@ public abstract class GradeDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<GradeFull>> getAllFromDate(int profileId, int semester, long date) {
|
public LiveData<List<GradeFull>> getAllFromDate(int profileId, long date) {
|
||||||
return getAllWhere(profileId, "gradeSemester = " + semester + " AND addedDate > " + date);
|
return getAllWhere(profileId, "addedDate > " + date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,4 +20,7 @@ interface LibrusLessonDao {
|
|||||||
|
|
||||||
@Query("SELECT * FROM librusLessons WHERE profileId = :profileId")
|
@Query("SELECT * FROM librusLessons WHERE profileId = :profileId")
|
||||||
fun getAllNow(profileId: Int): List<LibrusLesson>
|
fun getAllNow(profileId: Int): List<LibrusLesson>
|
||||||
|
|
||||||
|
@Query("DELETE FROM librusLessons WHERE profileId = :profileId")
|
||||||
|
fun clear(profileId: Int)
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@ import androidx.sqlite.db.SupportSQLiteQuery;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber;
|
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber;
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.LuckyNumberFull;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notice;
|
import pl.szczodrzynski.edziennik.data.db.entity.Notice;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.LuckyNumberFull;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_LUCKY_NUMBER;
|
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_LUCKY_NUMBER;
|
||||||
@ -78,4 +78,10 @@ public abstract class LuckyNumberDao {
|
|||||||
public List<LuckyNumberFull> getNotNotifiedNow(int profileId) {
|
public List<LuckyNumberFull> getNotNotifiedNow(int profileId) {
|
||||||
return getAllNow(profileId, "notified = 0");
|
return getAllNow(profileId, "notified = 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("SELECT * FROM luckyNumbers\n" +
|
||||||
|
"LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = luckyNumbers.profileId " +
|
||||||
|
"WHERE notified = 0 " +
|
||||||
|
"ORDER BY addedDate DESC")
|
||||||
|
public abstract List<LuckyNumberFull> getNotNotifiedNow();
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ import androidx.sqlite.db.SupportSQLiteQuery;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message;
|
import pl.szczodrzynski.edziennik.data.db.entity.Message;
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull;
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED;
|
import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED;
|
import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED;
|
||||||
@ -101,4 +101,14 @@ public abstract class MessageDao {
|
|||||||
public List<MessageFull> getReceivedNotNotifiedNow(int profileId) {
|
public List<MessageFull> getReceivedNotNotifiedNow(int profileId) {
|
||||||
return getReceivedNow(profileId, "notified = 0");
|
return getReceivedNow(profileId, "notified = 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("SELECT " +
|
||||||
|
"*, " +
|
||||||
|
"teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName " +
|
||||||
|
"FROM messages " +
|
||||||
|
"LEFT JOIN teachers ON teachers.profileId = messages.profileId AND teacherId = senderId " +
|
||||||
|
"LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = messages.profileId " +
|
||||||
|
"WHERE messageType = 0 AND notified = 0 " +
|
||||||
|
"ORDER BY addedDate DESC")
|
||||||
|
public abstract List<MessageFull> getReceivedNotNotifiedNow();
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user