mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-16 15:31:54 +02:00
Compare commits
123 Commits
v3.9.3-dev
...
v3.9.13-de
Author | SHA1 | Date | |
---|---|---|---|
1acf1547d5 | |||
5d3de35c10 | |||
8f8d613f6e | |||
6a161b3c97 | |||
3e97572100 | |||
fc3b6fd1e0 | |||
9bc7f9ac11 | |||
0a2f252405 | |||
09bc658f97 | |||
7b04202a00 | |||
acf364166b | |||
4e88efae94 | |||
8df24dc1c4 | |||
8482c27689 | |||
d1265dc1f2 | |||
47d395de71 | |||
5b443e02a3 | |||
f8a7d52b1d | |||
a133a96819 | |||
c71b8f994c | |||
9b02c97926 | |||
ab06efc934 | |||
928b73f139 | |||
a36fb09bc3 | |||
eaed4b76aa | |||
6d8960f089 | |||
ca3b6d0705 | |||
c2e7931ea6 | |||
d1a5d8cba9 | |||
c2f91e6867 | |||
55e32b8d88 | |||
462b1df767 | |||
d17d2c8417 | |||
6892832fff | |||
66d54c7c45 | |||
d432685aa8 | |||
37f3d76fb8 | |||
7961a74995 | |||
9d590508ad | |||
f79b7eaf83 | |||
ae13bf946f | |||
f116c4f1f4 | |||
867c8920a8 | |||
6e6dd34872 | |||
0759468fa7 | |||
1b1fb09211 | |||
de414c912c | |||
d274a2fed1 | |||
285b7e9b9e | |||
875efcff7e | |||
07ae37167d | |||
f689f4d427 | |||
19bc2b8b37 | |||
673116e27e | |||
59fcb0a050 | |||
cd76f99bbf | |||
6a4994b9c2 | |||
63960c5e05 | |||
540afb6a28 | |||
ae10b8abbd | |||
db2ebab879 | |||
6ec3d062df | |||
86b6060a09 | |||
83d123e341 | |||
34061695f9 | |||
de68476442 | |||
678a81a44b | |||
cfb3096d53 | |||
9b7aca745a | |||
82852389fa | |||
ce06084e6f | |||
3ca051983f | |||
cd379e4175 | |||
62fdfa2b6f | |||
9866017f7e | |||
67f98b08c6 | |||
fdb5f7ec02 | |||
04c3c7ca6e | |||
f424315d97 | |||
c907a8df37 | |||
37ea65e3fc | |||
a3e5f824c8 | |||
e0c850a455 | |||
1c6815f708 | |||
9a20511935 | |||
965f5e73d9 | |||
13b58a1d56 | |||
0a3261b8b3 | |||
dbdfc7fdd8 | |||
56062f5bfa | |||
0cbba2eb45 | |||
aa84356dd6 | |||
efaad0a4dd | |||
71015c0137 | |||
85b5667a7e | |||
dfdc6817a1 | |||
058345b9c9 | |||
831b7876b4 | |||
729cf6f08e | |||
860a16b32d | |||
9f871c077b | |||
a8f89abf7d | |||
16102de619 | |||
472e768369 | |||
131a769c26 | |||
4a0a6c54e4 | |||
c83abe57d5 | |||
c6e2519dcc | |||
74db524db6 | |||
810976d976 | |||
eb0540b5cb | |||
124437fd73 | |||
69b512e3d1 | |||
29d74e14bd | |||
f42ec8435a | |||
1052b824db | |||
0742a6a74c | |||
d4e9e1730f | |||
4eeaa54a47 | |||
5fa7409317 | |||
0bcd190714 | |||
563f08b0ab | |||
1b75424604 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -81,3 +81,5 @@ lint/generated/
|
|||||||
lint/outputs/
|
lint/outputs/
|
||||||
lint/tmp/
|
lint/tmp/
|
||||||
# lint/reports/
|
# lint/reports/
|
||||||
|
|
||||||
|
app/schemas/
|
||||||
|
7
.idea/misc.xml
generated
7
.idea/misc.xml
generated
@ -6,8 +6,9 @@
|
|||||||
</configurations>
|
</configurations>
|
||||||
</component>
|
</component>
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
<list size="1">
|
<list size="2">
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
<item index="0" class="java.lang.String" itemvalue="androidx.databinding.BindingAdapter" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
||||||
</list>
|
</list>
|
||||||
</component>
|
</component>
|
||||||
<component name="NullableNotNullManager">
|
<component name="NullableNotNullManager">
|
||||||
@ -49,7 +50,7 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -131,7 +131,7 @@ dependencies {
|
|||||||
implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true}
|
implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true}
|
||||||
implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update
|
implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update
|
||||||
implementation "com.jaredrummler:colorpicker:1.0.2"
|
implementation "com.jaredrummler:colorpicker:1.0.2"
|
||||||
implementation "com.squareup.okhttp3:okhttp:3.12.0"
|
implementation "com.squareup.okhttp3:okhttp:3.12.2"
|
||||||
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update
|
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update
|
||||||
implementation "com.wdullaer:materialdatetimepicker:4.1.2"
|
implementation "com.wdullaer:materialdatetimepicker:4.1.2"
|
||||||
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
||||||
@ -166,6 +166,10 @@ dependencies {
|
|||||||
implementation "androidx.work:work-runtime-ktx:${versions.work}"
|
implementation "androidx.work:work-runtime-ktx:${versions.work}"
|
||||||
|
|
||||||
implementation 'com.hypertrack:hyperlog:0.0.10'
|
implementation 'com.hypertrack:hyperlog:0.0.10'
|
||||||
|
|
||||||
|
implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584'
|
||||||
|
|
||||||
|
implementation 'com.github.kuba2k2:Tachyon:551943a6b5'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
||||||
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.Event { *; }
|
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.Event { *; }
|
||||||
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.EventFull { *; }
|
-keep class pl.szczodrzynski.edziennik.data.db.modules.events.EventFull { *; }
|
||||||
|
-keep class pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel { *; }
|
||||||
-keepclassmembers class pl.szczodrzynski.edziennik.widgets.WidgetConfig { public *; }
|
-keepclassmembers class pl.szczodrzynski.edziennik.widgets.WidgetConfig { public *; }
|
||||||
-keepnames class pl.szczodrzynski.edziennik.WidgetTimetable
|
-keepnames class pl.szczodrzynski.edziennik.WidgetTimetable
|
||||||
-keepnames class pl.szczodrzynski.edziennik.notifications.WidgetNotifications
|
-keepnames class pl.szczodrzynski.edziennik.notifications.WidgetNotifications
|
||||||
@ -39,4 +40,13 @@
|
|||||||
|
|
||||||
-keep class okhttp3.** { *; }
|
-keep class okhttp3.** { *; }
|
||||||
|
|
||||||
-keep class com.google.android.material.tabs.** {*;}
|
-keep class com.google.android.material.tabs.** {*;}
|
||||||
|
|
||||||
|
# ServiceLoader support
|
||||||
|
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
|
||||||
|
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
|
||||||
|
|
||||||
|
# Most of volatile fields are updated with AFU and should not be mangled
|
||||||
|
-keepclassmembernames class kotlinx.** {
|
||||||
|
volatile <fields>;
|
||||||
|
}
|
9
app/sampledata/check/ic_check.xml
Normal file
9
app/sampledata/check/ic_check.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF4caf50"
|
||||||
|
android:pathData="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/>
|
||||||
|
</vector>
|
13
app/sampledata/settings/ic_settings.xml
Normal file
13
app/sampledata/settings/ic_settings.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (c) Kuba Szczodrzyński 2019-11-25.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,8A4,4 0,0 1,16 12A4,4 0,0 1,12 16A4,4 0,0 1,8 12A4,4 0,0 1,12 8M12,10A2,2 0,0 0,10 12A2,2 0,0 0,12 14A2,2 0,0 0,14 12A2,2 0,0 0,12 10M10,22C9.75,22 9.54,21.82 9.5,21.58L9.13,18.93C8.5,18.68 7.96,18.34 7.44,17.94L4.95,18.95C4.73,19.03 4.46,18.95 4.34,18.73L2.34,15.27C2.21,15.05 2.27,14.78 2.46,14.63L4.57,12.97L4.5,12L4.57,11L2.46,9.37C2.27,9.22 2.21,8.95 2.34,8.73L4.34,5.27C4.46,5.05 4.73,4.96 4.95,5.05L7.44,6.05C7.96,5.66 8.5,5.32 9.13,5.07L9.5,2.42C9.54,2.18 9.75,2 10,2H14C14.25,2 14.46,2.18 14.5,2.42L14.87,5.07C15.5,5.32 16.04,5.66 16.56,6.05L19.05,5.05C19.27,4.96 19.54,5.05 19.66,5.27L21.66,8.73C21.79,8.95 21.73,9.22 21.54,9.37L19.43,11L19.5,12L19.43,13L21.54,14.63C21.73,14.78 21.79,15.05 21.66,15.27L19.66,18.73C19.54,18.95 19.27,19.04 19.05,18.95L16.56,17.95C16.04,18.34 15.5,18.68 14.87,18.93L14.5,21.58C14.46,21.82 14.25,22 14,22H10M11.25,4L10.88,6.61C9.68,6.86 8.62,7.5 7.85,8.39L5.44,7.35L4.69,8.65L6.8,10.2C6.4,11.37 6.4,12.64 6.8,13.8L4.68,15.36L5.43,16.66L7.86,15.62C8.63,16.5 9.68,17.14 10.87,17.38L11.24,20H12.76L13.13,17.39C14.32,17.14 15.37,16.5 16.14,15.62L18.57,16.66L19.32,15.36L17.2,13.81C17.6,12.64 17.6,11.37 17.2,10.2L19.31,8.65L18.56,7.35L16.15,8.39C15.38,7.5 14.32,6.86 13.12,6.62L12.75,4H11.25Z"/>
|
||||||
|
</vector>
|
@ -105,6 +105,11 @@
|
|||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/AppTheme.NoDisplay" />
|
android:theme="@style/AppTheme.NoDisplay" />
|
||||||
|
<activity android:name=".widgets.timetable.LessonDialogActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:noHistory="true"
|
||||||
|
android:theme="@style/AppTheme.NoDisplay" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.settings.SettingsLicenseActivity"
|
android:name=".ui.modules.settings.SettingsLicenseActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
|
@ -18,7 +18,6 @@ import android.os.Handler;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
@ -68,14 +67,9 @@ import me.leolin.shortcutbadger.ShortcutBadger;
|
|||||||
import okhttp3.ConnectionSpec;
|
import okhttp3.ConnectionSpec;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.TlsVersion;
|
import okhttp3.TlsVersion;
|
||||||
import pl.szczodrzynski.edziennik.data.api.Edziennik;
|
import pl.szczodrzynski.edziennik.config.Config;
|
||||||
import pl.szczodrzynski.edziennik.data.api.Iuczniowie;
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.Librus;
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.Mobidziennik;
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.Vulcan;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb;
|
import pl.szczodrzynski.edziennik.data.db.AppDb;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog;
|
import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
|
||||||
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
import pl.szczodrzynski.edziennik.network.NetworkUtils;
|
||||||
@ -88,9 +82,7 @@ import pl.szczodrzynski.edziennik.utils.Themes;
|
|||||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
import pl.szczodrzynski.edziennik.utils.Utils;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.AppConfig;
|
import pl.szczodrzynski.edziennik.utils.models.AppConfig;
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_LIBRUS;
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_VULCAN;
|
|
||||||
|
|
||||||
public class App extends androidx.multidex.MultiDexApplication implements Configuration.Provider {
|
public class App extends androidx.multidex.MultiDexApplication implements Configuration.Provider {
|
||||||
private static final String TAG = "App";
|
private static final String TAG = "App";
|
||||||
@ -141,12 +133,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
public PersistentCookieJar cookieJar;
|
public PersistentCookieJar cookieJar;
|
||||||
public OkHttpClient http;
|
public OkHttpClient http;
|
||||||
public OkHttpClient httpLazy;
|
public OkHttpClient httpLazy;
|
||||||
//public Jakdojade apiJakdojade;
|
|
||||||
public Edziennik apiEdziennik;
|
|
||||||
public Mobidziennik apiMobidziennik;
|
|
||||||
public Iuczniowie apiIuczniowie;
|
|
||||||
public Librus apiLibrus;
|
|
||||||
public Vulcan apiVulcan;
|
|
||||||
|
|
||||||
public SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE
|
public SharedPreferences appSharedPrefs; // sharedPreferences for APPCONFIG + JOBS STORE
|
||||||
public AppConfig appConfig; // APPCONFIG: common for all profiles
|
public AppConfig appConfig; // APPCONFIG: common for all profiles
|
||||||
@ -156,6 +142,11 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
//public Register register; // REGISTER for current profile, read from registerStore
|
//public Register register; // REGISTER for current profile, read from registerStore
|
||||||
|
|
||||||
public ProfileFull profile;
|
public ProfileFull profile;
|
||||||
|
public Config config;
|
||||||
|
private static Config mConfig;
|
||||||
|
public static Config getConfig() {
|
||||||
|
return mConfig;
|
||||||
|
}
|
||||||
|
|
||||||
// other stuff
|
// other stuff
|
||||||
public Gson gson;
|
public Gson gson;
|
||||||
@ -204,12 +195,10 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
db = AppDb.getDatabase(this);
|
db = AppDb.getDatabase(this);
|
||||||
gson = new Gson();
|
gson = new Gson();
|
||||||
networkUtils = new NetworkUtils(this);
|
networkUtils = new NetworkUtils(this);
|
||||||
apiEdziennik = new Edziennik(this);
|
|
||||||
//apiJakdojade = new Jakdojade(this);
|
config = new Config(db);
|
||||||
apiMobidziennik = new Mobidziennik(this);
|
config.migrate(this);
|
||||||
apiIuczniowie = new Iuczniowie(this);
|
mConfig = config;
|
||||||
apiLibrus = new Librus(this);
|
|
||||||
apiVulcan = new Vulcan(this);
|
|
||||||
|
|
||||||
Iconics.init(getApplicationContext());
|
Iconics.init(getApplicationContext());
|
||||||
Iconics.registerFont(SzkolnyFont.INSTANCE);
|
Iconics.registerFont(SzkolnyFont.INSTANCE);
|
||||||
@ -225,7 +214,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
|
||||||
Themes.INSTANCE.setThemeInt(appConfig.appTheme);
|
Themes.INSTANCE.setThemeInt(config.getUi().getTheme());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
|
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
|
||||||
@ -244,7 +233,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
if ("f054761fbdb6a238".equals(deviceId) || BuildConfig.DEBUG) {
|
if ("f054761fbdb6a238".equals(deviceId) || BuildConfig.DEBUG) {
|
||||||
devMode = true;
|
devMode = true;
|
||||||
}
|
}
|
||||||
else if (appConfig.devModePassword != null) {
|
else if (config.getDevModePassword() != null) {
|
||||||
checkDevModePassword();
|
checkDevModePassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +304,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
//profileLoadById(appSharedPrefs.getInt("current_profile_id", 1));
|
||||||
|
|
||||||
if (appConfig.registerSyncEnabled) {
|
if (config.getSync().getEnabled()) {
|
||||||
SyncWorker.Companion.scheduleNext(this, false);
|
SyncWorker.Companion.scheduleNext(this, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -379,11 +368,10 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutTimetable, shortcutAgenda, shortcutGrades, shortcutHomework, shortcutMessages));
|
shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutTimetable, shortcutAgenda, shortcutGrades, shortcutHomework, shortcutMessages));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appConfig.appInstalledTime == 0) {
|
if (config.getAppInstalledTime() == 0) {
|
||||||
try {
|
try {
|
||||||
appConfig.appInstalledTime = getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime;
|
config.setAppInstalledTime(getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime);
|
||||||
appConfig.appRateSnackbarTime = appConfig.appInstalledTime + 7 * 24 * 60 * 60 * 1000;
|
config.setAppRateSnackbarTime(config.getAppInstalledTime() + 7 * 24 * 60 * 60 * 1000);
|
||||||
saveConfig("appInstalledTime", "appRateSnackbarTime");
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -451,9 +439,9 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
final long startTime = System.currentTimeMillis();
|
final long startTime = System.currentTimeMillis();
|
||||||
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
||||||
Log.d(TAG, "Token for App is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId()+". Time is "+(System.currentTimeMillis() - startTime));
|
Log.d(TAG, "Token for App is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId()+". Time is "+(System.currentTimeMillis() - startTime));
|
||||||
appConfig.fcmToken = instanceIdResult.getToken();
|
config.getSync().setTokenApp(instanceIdResult.getToken());
|
||||||
});
|
});
|
||||||
FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
/*FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
|
||||||
Log.d(TAG, "Token for Mobidziennik is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
Log.d(TAG, "Token for Mobidziennik is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
|
||||||
appConfig.fcmTokens.put(LOGIN_TYPE_MOBIDZIENNIK, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
appConfig.fcmTokens.put(LOGIN_TYPE_MOBIDZIENNIK, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
||||||
});
|
});
|
||||||
@ -467,7 +455,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
if (pair == null || pair.first == null || !pair.first.equals(instanceIdResult.getToken())) {
|
if (pair == null || pair.first == null || !pair.first.equals(instanceIdResult.getToken())) {
|
||||||
appConfig.fcmTokens.put(LOGIN_TYPE_VULCAN, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
appConfig.fcmTokens.put(LOGIN_TYPE_VULCAN, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
|
|
||||||
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(getPackageName());
|
FirebaseMessaging.getInstance().subscribeToTopic(getPackageName());
|
||||||
@ -530,7 +518,8 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
appSharedPrefs.edit().remove("app.appConfig."+fieldName).apply();
|
Log.w(TAG, "Should remove app.appConfig."+fieldName);
|
||||||
|
//appSharedPrefs.edit().remove("app.appConfig."+fieldName).apply(); TODO migration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,7 +591,11 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
//appSharedPrefs.edit().putString("config", gson.toJson(appConfig)).apply();
|
//appSharedPrefs.edit().putString("config", gson.toJson(appConfig)).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void profileSave() {
|
||||||
|
AsyncTask.execute(() -> {
|
||||||
|
db.profileDao().add(profile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void profileSaveAsync() {
|
public void profileSaveAsync() {
|
||||||
AsyncTask.execute(() -> {
|
AsyncTask.execute(() -> {
|
||||||
@ -623,14 +616,6 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
db.profileDao().add(profileFull);
|
db.profileDao().add(profileFull);
|
||||||
db.loginStoreDao().add(profileFull);
|
db.loginStoreDao().add(profileFull);
|
||||||
}
|
}
|
||||||
public void profileSaveFull(Profile profile, LoginStore loginStore) {
|
|
||||||
db.profileDao().add(profile);
|
|
||||||
db.loginStoreDao().add(loginStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProfileFull profileGetOrNull(int id) {
|
|
||||||
return db.profileDao().getFullByIdNow(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void profileLoadById(int id) {
|
public void profileLoadById(int id) {
|
||||||
profileLoadById(id, false);
|
profileLoadById(id, false);
|
||||||
@ -653,6 +638,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1);
|
MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1);
|
||||||
profileId = profile.getId();
|
profileId = profile.getId();
|
||||||
appSharedPrefs.edit().putInt("current_profile_id", profile.getId()).apply();
|
appSharedPrefs.edit().putInt("current_profile_id", profile.getId()).apply();
|
||||||
|
config.setProfile(profileId);
|
||||||
}
|
}
|
||||||
else if (!loadedLast) {
|
else if (!loadedLast) {
|
||||||
profileLoadById(profileLastId(), true);
|
profileLoadById(profileLastId(), true);
|
||||||
@ -723,7 +709,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
|||||||
|
|
||||||
public void checkDevModePassword() {
|
public void checkDevModePassword() {
|
||||||
try {
|
try {
|
||||||
devMode = Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", appConfig.devModePassword).equals("ok here you go it's enabled now")
|
devMode = Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.getDevModePassword()).equals("ok here you go it's enabled now")
|
||||||
|| BuildConfig.DEBUG;
|
|| BuildConfig.DEBUG;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
319
app/src/main/java/pl/szczodrzynski/edziennik/App.kt
Normal file
319
app/src/main/java/pl/szczodrzynski/edziennik/App.kt
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.work.Configuration
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
class Szkolny : /*MultiDexApplication(),*/ Configuration.Provider, CoroutineScope {
|
||||||
|
companion object {
|
||||||
|
var devMode = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//lateinit var db: AppDb
|
||||||
|
//val config by lazy { Config(db); // TODO migrate }
|
||||||
|
|
||||||
|
private val job = Job()
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Main
|
||||||
|
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||||
|
.setMinimumLoggingLevel(Log.VERBOSE)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
/*val preferences by lazy { getSharedPreferences(getString(R.string.preference_file), Context.MODE_PRIVATE) }
|
||||||
|
val notifier by lazy { Notifier(this) }
|
||||||
|
val permissionChecker by lazy { PermissionChecker(this) }
|
||||||
|
|
||||||
|
lateinit var profile: ProfileFull
|
||||||
|
|
||||||
|
/* _ _ _______ _______ _____
|
||||||
|
| | | |__ __|__ __| __ \
|
||||||
|
| |__| | | | | | | |__) |
|
||||||
|
| __ | | | | | | ___/
|
||||||
|
| | | | | | | | | |
|
||||||
|
|_| |_| |_| |_| |*/
|
||||||
|
val http: OkHttpClient by lazy {
|
||||||
|
val builder = OkHttpClient.Builder()
|
||||||
|
.cache(null)
|
||||||
|
.followRedirects(true)
|
||||||
|
.followSslRedirects(true)
|
||||||
|
.retryOnConnectionFailure(true)
|
||||||
|
.cookieJar(cookieJar)
|
||||||
|
.connectTimeout(20, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(5, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(10, TimeUnit.SECONDS)
|
||||||
|
builder.installHttpsSupport()
|
||||||
|
|
||||||
|
if (devMode || BuildConfig.DEBUG) {
|
||||||
|
HyperLog.initialize(this)
|
||||||
|
HyperLog.setLogLevel(Log.VERBOSE)
|
||||||
|
HyperLog.setLogFormat(DebugLogFormat(this))
|
||||||
|
val chuckerCollector = ChuckerCollector(this, true, Period.ONE_HOUR)
|
||||||
|
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
||||||
|
builder.addInterceptor(chuckerInterceptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
|
val httpLazy: OkHttpClient by lazy {
|
||||||
|
http.newBuilder()
|
||||||
|
.followRedirects(false)
|
||||||
|
.followSslRedirects(false)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
val cookieJar by lazy { PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(this)) }
|
||||||
|
|
||||||
|
/* _____ _ _
|
||||||
|
/ ____(_) | |
|
||||||
|
| (___ _ __ _ _ __ __ _| |_ _ _ _ __ ___
|
||||||
|
\___ \| |/ _` | '_ \ / _` | __| | | | '__/ _ \
|
||||||
|
____) | | (_| | | | | (_| | |_| |_| | | | __/
|
||||||
|
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
|
||||||
|
__/ |
|
||||||
|
|__*/
|
||||||
|
private val deviceId: String by lazy { Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) ?: "" }
|
||||||
|
private val signature: String by lazy {
|
||||||
|
var str = ""
|
||||||
|
try {
|
||||||
|
val packageInfo: PackageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
|
||||||
|
for (signature in packageInfo.signatures) {
|
||||||
|
val signatureBytes = signature.toByteArray()
|
||||||
|
val md = MessageDigest.getInstance("SHA")
|
||||||
|
md.update(signatureBytes)
|
||||||
|
str = Base64.encodeToString(md.digest(), Base64.DEFAULT)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
str
|
||||||
|
}
|
||||||
|
private var unreadBadgesAvailable = true
|
||||||
|
|
||||||
|
/* _____ _
|
||||||
|
/ ____| | |
|
||||||
|
___ _ __ | | _ __ ___ __ _| |_ ___
|
||||||
|
/ _ \| '_ \| | | '__/ _ \/ _` | __/ _ \
|
||||||
|
| (_) | | | | |____| | | __/ (_| | || __/
|
||||||
|
\___/|_| |_|\_____|_| \___|\__,_|\__\__*/
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||||
|
CaocConfig.Builder.create()
|
||||||
|
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM)
|
||||||
|
.enabled(true)
|
||||||
|
.showErrorDetails(true)
|
||||||
|
.showRestartButton(true)
|
||||||
|
.logErrorOnRestart(true)
|
||||||
|
.trackActivities(true)
|
||||||
|
.minTimeBetweenCrashesMs(60*1000)
|
||||||
|
.errorDrawable(R.drawable.ic_rip)
|
||||||
|
.restartActivity(MainActivity::class.java)
|
||||||
|
.errorActivity(CrashActivity::class.java)
|
||||||
|
.apply()
|
||||||
|
Iconics.init(applicationContext)
|
||||||
|
Iconics.registerFont(SzkolnyFont)
|
||||||
|
db = AppDb.getDatabase(this)
|
||||||
|
Themes.themeInt = config.ui.theme
|
||||||
|
MHttp.instance().customOkHttpClient(http)
|
||||||
|
|
||||||
|
devMode = "f054761fbdb6a238" == deviceId || BuildConfig.DEBUG
|
||||||
|
if (config.devModePassword != null)
|
||||||
|
checkDevModePassword()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
launch { async(Dispatchers.Default) {
|
||||||
|
if (config.sync.enabled) {
|
||||||
|
scheduleNext(this@App, false)
|
||||||
|
} else {
|
||||||
|
cancelNext(this@App)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.metadataDao().countUnseen().observeForever { count: Int ->
|
||||||
|
if (unreadBadgesAvailable)
|
||||||
|
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||||
|
val shortcutManager = getSystemService(ShortcutManager::class.java)
|
||||||
|
|
||||||
|
val shortcutTimetable = ShortcutInfo.Builder(this@App, "item_timetable")
|
||||||
|
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
|
||||||
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable))
|
||||||
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||||
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda")
|
||||||
|
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
|
||||||
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda))
|
||||||
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||||
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_AGENDA))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades")
|
||||||
|
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
|
||||||
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades))
|
||||||
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||||
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_GRADES))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks")
|
||||||
|
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
|
||||||
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework))
|
||||||
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||||
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOMEWORK))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages")
|
||||||
|
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
|
||||||
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages))
|
||||||
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||||
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_MESSAGES))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
shortcutManager.dynamicShortcuts = listOf(
|
||||||
|
shortcutTimetable,
|
||||||
|
shortcutAgenda,
|
||||||
|
shortcutGrades,
|
||||||
|
shortcutHomework,
|
||||||
|
shortcutMessages
|
||||||
|
)
|
||||||
|
} // shortcuts - end
|
||||||
|
|
||||||
|
if (config.appInstalledTime == 0L)
|
||||||
|
try {
|
||||||
|
config.appInstalledTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
|
||||||
|
config.appRateSnackbarTime = config.appInstalledTime + 7*DAY*MS
|
||||||
|
} catch (e: NameNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
val pushMobidziennikApp = FirebaseApp.initializeApp(
|
||||||
|
this@App,
|
||||||
|
FirebaseOptions.Builder()
|
||||||
|
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
|
||||||
|
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
|
||||||
|
.build(),
|
||||||
|
"Mobidziennik2"
|
||||||
|
)
|
||||||
|
|
||||||
|
val pushLibrusApp = FirebaseApp.initializeApp(
|
||||||
|
this@App,
|
||||||
|
FirebaseOptions.Builder()
|
||||||
|
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
||||||
|
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
||||||
|
.build(),
|
||||||
|
"Librus"
|
||||||
|
)
|
||||||
|
|
||||||
|
val pushVulcanApp = FirebaseApp.initializeApp(
|
||||||
|
this@App,
|
||||||
|
FirebaseOptions.Builder()
|
||||||
|
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
||||||
|
.setApplicationId("1:987828170337:android:ac97431a0a4578c3")
|
||||||
|
.build(),
|
||||||
|
"Vulcan"
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
|
||||||
|
val token = instanceIdResult.token
|
||||||
|
config.sync.tokenApp = token
|
||||||
|
}
|
||||||
|
FirebaseInstanceId.getInstance(pushMobidziennikApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||||
|
val token = instanceIdResult.token
|
||||||
|
if (token != config.sync.tokenMobidziennik) {
|
||||||
|
config.sync.tokenMobidziennik = token
|
||||||
|
config.sync.tokenMobidziennikList = listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FirebaseInstanceId.getInstance(pushLibrusApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||||
|
val token = instanceIdResult.token
|
||||||
|
if (token != config.sync.tokenLibrus) {
|
||||||
|
config.sync.tokenLibrus = token
|
||||||
|
config.sync.tokenLibrusList = listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FirebaseInstanceId.getInstance(pushVulcanApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||||
|
val token = instanceIdResult.token
|
||||||
|
if (token != config.sync.tokenVulcan) {
|
||||||
|
config.sync.tokenVulcan = token
|
||||||
|
config.sync.tokenVulcanList = listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
|
||||||
|
} catch (e: IllegalStateException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun profileLoad(profileId: Int) {
|
||||||
|
db.profileDao().getFullByIdNow(profileId)?.also {
|
||||||
|
profile = it
|
||||||
|
} ?: run {
|
||||||
|
if (!::profile.isInitialized) {
|
||||||
|
profile = ProfileFull(-1, "", "", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun profileLoad(profileId: Int, onSuccess: (profile: ProfileFull) -> Unit) {
|
||||||
|
launch {
|
||||||
|
val deferred = async(Dispatchers.Default) {
|
||||||
|
profileLoad(profileId)
|
||||||
|
}
|
||||||
|
deferred.await()
|
||||||
|
onSuccess(profile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun OkHttpClient.Builder.installHttpsSupport() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
ProviderInstaller.installIfNeeded(this@App)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("OkHttpTLSCompat", "Play Services not found or outdated")
|
||||||
|
|
||||||
|
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
|
||||||
|
trustManagerFactory.init(null as KeyStore?)
|
||||||
|
|
||||||
|
val x509TrustManager = trustManagerFactory.trustManagers.singleOrNull { it is X509TrustManager } as X509TrustManager?
|
||||||
|
?: return
|
||||||
|
|
||||||
|
val sc = SSLContext.getInstance("TLSv1.2")
|
||||||
|
sc.init(null, null, null)
|
||||||
|
sslSocketFactory(TLSSocketFactory(sc.socketFactory), x509TrustManager)
|
||||||
|
val cs: ConnectionSpec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||||
|
.tlsVersions(TlsVersion.TLS_1_0)
|
||||||
|
.tlsVersions(TlsVersion.TLS_1_1)
|
||||||
|
.tlsVersions(TlsVersion.TLS_1_2)
|
||||||
|
.build()
|
||||||
|
val specs: MutableList<ConnectionSpec> = ArrayList()
|
||||||
|
specs.add(cs)
|
||||||
|
specs.add(ConnectionSpec.COMPATIBLE_TLS)
|
||||||
|
specs.add(ConnectionSpec.CLEARTEXT)
|
||||||
|
connectionSpecs(specs)
|
||||||
|
}
|
||||||
|
} catch (exc: Exception) {
|
||||||
|
Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkDevModePassword() {
|
||||||
|
devMode = try {
|
||||||
|
Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.devModePassword) == "ok here you go it's enabled now" || BuildConfig.DEBUG
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
21
app/src/main/java/pl/szczodrzynski/edziennik/Binding.java
Normal file
21
app/src/main/java/pl/szczodrzynski/edziennik/Binding.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-11.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik;
|
||||||
|
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.databinding.BindingAdapter;
|
||||||
|
|
||||||
|
public class Binding {
|
||||||
|
@BindingAdapter("strikeThrough")
|
||||||
|
public static void strikeThrough(TextView textView, Boolean strikeThrough) {
|
||||||
|
if (strikeThrough) {
|
||||||
|
textView.setPaintFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
} else {
|
||||||
|
textView.setPaintFlags(textView.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,20 +4,41 @@ import android.Manifest
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.graphics.PorterDuffColorFilter
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.text.*
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import android.text.style.StrikethroughSpan
|
||||||
|
import android.text.style.StyleSpan
|
||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.CompoundButton
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.*
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||||
import pl.szczodrzynski.navlib.R
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
import pl.szczodrzynski.navlib.getColorFromAttr
|
||||||
import pl.szczodrzynski.navlib.getColorFromRes
|
import pl.szczodrzynski.navlib.getColorFromRes
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -84,6 +105,15 @@ fun String.swapFirstLastName(): String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun String.getFirstLastName(): Pair<String, String>? {
|
||||||
|
return this.split(" ").let {
|
||||||
|
if (it.size >= 2) Pair(it[0], it[1])
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.getLastFirstName() = this.getFirstLastName()
|
||||||
|
|
||||||
fun changeStringCase(s: String): String {
|
fun changeStringCase(s: String): String {
|
||||||
val delimiters = " '-/"
|
val delimiters = " '-/"
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
@ -142,8 +172,9 @@ fun colorFromName(context: Context, name: String?): Int {
|
|||||||
return context.getColorFromRes(color)
|
return context.getColorFromRes(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutableList<out Profile>.filterOutArchived() {
|
fun MutableList<Profile>.filterOutArchived(): MutableList<Profile> {
|
||||||
this.removeAll { it.archived }
|
this.removeAll { it.archived }
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.isStoragePermissionGranted(): Boolean {
|
fun Activity.isStoragePermissionGranted(): Boolean {
|
||||||
@ -172,6 +203,7 @@ const val DAY = 24L*HOUR
|
|||||||
const val WEEK = 7L*DAY
|
const val WEEK = 7L*DAY
|
||||||
const val MONTH = 30L*DAY
|
const val MONTH = 30L*DAY
|
||||||
const val YEAR = 365L*DAY
|
const val YEAR = 365L*DAY
|
||||||
|
const val MS = 1000L
|
||||||
|
|
||||||
fun <T> LongSparseArray<T>.values(): List<T> {
|
fun <T> LongSparseArray<T>.values(): List<T> {
|
||||||
val result = mutableListOf<T>()
|
val result = mutableListOf<T>()
|
||||||
@ -326,4 +358,251 @@ fun String.crc32(): Long {
|
|||||||
return crc.value
|
return crc.value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Long.formatDate(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this)
|
fun Long.formatDate(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this)
|
||||||
|
|
||||||
|
fun CharSequence?.asColoredSpannable(colorInt: Int): Spannable {
|
||||||
|
val spannable = SpannableString(this)
|
||||||
|
spannable.setSpan(ForegroundColorSpan(colorInt), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
return spannable
|
||||||
|
}
|
||||||
|
fun CharSequence?.asStrikethroughSpannable(): Spannable {
|
||||||
|
val spannable = SpannableString(this)
|
||||||
|
spannable.setSpan(StrikethroughSpan(), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
return spannable
|
||||||
|
}
|
||||||
|
fun CharSequence?.asItalicSpannable(): Spannable {
|
||||||
|
val spannable = SpannableString(this)
|
||||||
|
spannable.setSpan(StyleSpan(Typeface.ITALIC), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
return spannable
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new read-only list only of those given elements, that are not empty.
|
||||||
|
* Applies for CharSequence and descendants.
|
||||||
|
*/
|
||||||
|
fun <T : CharSequence> listOfNotEmpty(vararg elements: T): List<T> = elements.filterNot { it.isEmpty() }
|
||||||
|
|
||||||
|
fun List<CharSequence?>.concat(delimiter: String? = null): CharSequence {
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.size == 1) {
|
||||||
|
return this[0] ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var spanned = false
|
||||||
|
for (piece in this) {
|
||||||
|
if (piece is Spanned) {
|
||||||
|
spanned = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var first = true
|
||||||
|
if (spanned) {
|
||||||
|
val ssb = SpannableStringBuilder()
|
||||||
|
for (piece in this) {
|
||||||
|
if (piece == null)
|
||||||
|
continue
|
||||||
|
if (!first && delimiter != null)
|
||||||
|
ssb.append(delimiter)
|
||||||
|
first = false
|
||||||
|
ssb.append(piece)
|
||||||
|
}
|
||||||
|
return SpannedString(ssb)
|
||||||
|
} else {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
for (piece in this) {
|
||||||
|
if (piece == null)
|
||||||
|
continue
|
||||||
|
if (!first && delimiter != null)
|
||||||
|
sb.append(delimiter)
|
||||||
|
first = false
|
||||||
|
sb.append(piece)
|
||||||
|
}
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TextView.setText(@StringRes resid: Int, vararg formatArgs: Any) {
|
||||||
|
text = context.getString(resid, *formatArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JsonObject(vararg properties: Pair<String, Any?>): JsonObject {
|
||||||
|
return JsonObject().apply {
|
||||||
|
for (property in properties) {
|
||||||
|
when (property.second) {
|
||||||
|
is JsonElement -> add(property.first, property.second as JsonElement?)
|
||||||
|
is String -> addProperty(property.first, property.second as String?)
|
||||||
|
is Char -> addProperty(property.first, property.second as Char?)
|
||||||
|
is Number -> addProperty(property.first, property.second as Number?)
|
||||||
|
is Boolean -> addProperty(property.first, property.second as Boolean?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JsonArray?.isNullOrEmpty(): Boolean = (this?.size() ?: 0) == 0
|
||||||
|
fun JsonArray.isEmpty(): Boolean = this.size() == 0
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
inline fun <T : View> T.onClick(crossinline onClickListener: (v: T) -> Unit) {
|
||||||
|
setOnClickListener { v: View ->
|
||||||
|
onClickListener(v as T)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
inline fun <T : CompoundButton> T.onChange(crossinline onChangeListener: (v: T, isChecked: Boolean) -> Unit) {
|
||||||
|
setOnCheckedChangeListener { buttonView, isChecked ->
|
||||||
|
onChangeListener(buttonView as T, isChecked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
|
||||||
|
observe(lifecycleOwner, object : Observer<T> {
|
||||||
|
override fun onChanged(t: T?) {
|
||||||
|
observer.onChanged(t)
|
||||||
|
removeObserver(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a value in dp to pixels.
|
||||||
|
*/
|
||||||
|
val Int.dp: Int
|
||||||
|
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
||||||
|
/**
|
||||||
|
* Convert a value in pixels to dp.
|
||||||
|
*/
|
||||||
|
val Int.px: Int
|
||||||
|
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
fun @receiver:AttrRes Int.resolveAttr(context: Context?): Int {
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
context?.theme?.resolveAttribute(this, typedValue, true)
|
||||||
|
return typedValue.data
|
||||||
|
}
|
||||||
|
@ColorInt
|
||||||
|
fun @receiver:ColorRes Int.resolveColor(context: Context): Int {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
context.resources.getColor(this, context.theme)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.resources.getColor(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun @receiver:DrawableRes Int.resolveDrawable(context: Context): Drawable {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
context.resources.getDrawable(this, context.theme)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.resources.getDrawable(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun View.findParentById(targetId: Int): View? {
|
||||||
|
if (id == targetId) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
val viewParent = this.parent ?: return null
|
||||||
|
if (viewParent is View) {
|
||||||
|
return viewParent.findParentById(targetId)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: () -> Unit) = launch {
|
||||||
|
delay(delayMillis)
|
||||||
|
if (repeatMillis > 0) {
|
||||||
|
while (true) {
|
||||||
|
action()
|
||||||
|
delay(repeatMillis)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun Time?.compareTo(other: Time?): Int {
|
||||||
|
if (this == null && other == null)
|
||||||
|
return 0
|
||||||
|
if (this == null)
|
||||||
|
return -1
|
||||||
|
if (other == null)
|
||||||
|
return 1
|
||||||
|
return this.compareTo(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun StringBuilder.plusAssign(str: String?) {
|
||||||
|
this.append(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.timeTill(time: Int, delimiter: String = " "): String {
|
||||||
|
val parts = mutableListOf<Pair<Int, Int>>()
|
||||||
|
|
||||||
|
val hours = time / 3600
|
||||||
|
val minutes = (time - hours*3600) / 60
|
||||||
|
val seconds = time - minutes*60 - hours*3600
|
||||||
|
|
||||||
|
var prefixAdded = false
|
||||||
|
if (hours > 0) {
|
||||||
|
if (!prefixAdded) parts += R.plurals.time_till_text to hours; prefixAdded = true
|
||||||
|
parts += R.plurals.time_till_hours to hours
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
if (!prefixAdded) parts += R.plurals.time_till_text to minutes; prefixAdded = true
|
||||||
|
parts += R.plurals.time_till_minutes to minutes
|
||||||
|
}
|
||||||
|
if (hours == 0 && minutes < 10) {
|
||||||
|
if (!prefixAdded) parts += R.plurals.time_till_text to seconds; prefixAdded = true
|
||||||
|
parts += R.plurals.time_till_seconds to seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.joinToString(delimiter) { resources.getQuantityString(it.first, it.second, it.second) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.timeLeft(time: Int, delimiter: String = " "): String {
|
||||||
|
val parts = mutableListOf<Pair<Int, Int>>()
|
||||||
|
|
||||||
|
val hours = time / 3600
|
||||||
|
val minutes = (time - hours*3600) / 60
|
||||||
|
val seconds = time - minutes*60 - hours*3600
|
||||||
|
|
||||||
|
var prefixAdded = false
|
||||||
|
if (hours > 0) {
|
||||||
|
if (!prefixAdded) parts += R.plurals.time_left_text to hours
|
||||||
|
prefixAdded = true
|
||||||
|
parts += R.plurals.time_left_hours to hours
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
if (!prefixAdded) parts += R.plurals.time_left_text to minutes
|
||||||
|
prefixAdded = true
|
||||||
|
parts += R.plurals.time_left_minutes to minutes
|
||||||
|
}
|
||||||
|
if (hours == 0 && minutes < 10) {
|
||||||
|
if (!prefixAdded) parts += R.plurals.time_left_text to seconds
|
||||||
|
prefixAdded = true
|
||||||
|
parts += R.plurals.time_left_seconds to seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.joinToString(delimiter) { resources.getQuantityString(it.first, it.second, it.second) }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> Any?.instanceOfOrNull(): T? {
|
||||||
|
return when (this) {
|
||||||
|
is T -> this
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Drawable.setTintColor(color: Int): Drawable {
|
||||||
|
colorFilter = PorterDuffColorFilter(
|
||||||
|
color,
|
||||||
|
PorterDuff.Mode.SRC_ATOP
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
@ -38,31 +38,33 @@ import pl.droidsonroids.gif.GifDrawable
|
|||||||
import pl.szczodrzynski.edziennik.App.APP_URL
|
import pl.szczodrzynski.edziennik.App.APP_URL
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.*
|
import pl.szczodrzynski.edziennik.api.v2.events.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata.*
|
||||||
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
||||||
import pl.szczodrzynski.edziennik.network.ServerRequest
|
import pl.szczodrzynski.edziennik.network.ServerRequest
|
||||||
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
||||||
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog
|
||||||
|
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog
|
||||||
|
import pl.szczodrzynski.edziennik.ui.dialogs.sync.SyncViewListDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment
|
import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment
|
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment
|
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.behaviour.BehaviourFragment
|
import pl.szczodrzynski.edziennik.ui.modules.behaviour.BehaviourFragment
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
|
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
|
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesFragment
|
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesDetailsFragment
|
import pl.szczodrzynski.edziennik.ui.modules.messages.MessageFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
|
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
|
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
|
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment
|
||||||
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
|
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
@ -120,9 +122,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val list: MutableList<NavTarget> = mutableListOf()
|
val list: MutableList<NavTarget> = mutableListOf()
|
||||||
|
|
||||||
// home item
|
// home item
|
||||||
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragment::class)
|
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragmentV2::class)
|
||||||
.withTitle(R.string.app_name)
|
.withTitle(R.string.app_name)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_home)
|
.withIcon(CommunityMaterial.Icon2.cmd_home_outline)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
.isStatic(true)
|
.isStatic(true)
|
||||||
.withPopToHome(false)
|
.withPopToHome(false)
|
||||||
@ -133,50 +135,50 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_AGENDA, R.string.menu_agenda, AgendaFragment::class)
|
list += NavTarget(DRAWER_ITEM_AGENDA, R.string.menu_agenda, AgendaFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_calendar)
|
.withIcon(CommunityMaterial.Icon.cmd_calendar_outline)
|
||||||
.withBadgeTypeId(TYPE_EVENT)
|
.withBadgeTypeId(TYPE_EVENT)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesFragment::class)
|
list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_numeric_5_box)
|
.withIcon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline)
|
||||||
.withBadgeTypeId(TYPE_GRADE)
|
.withBadgeTypeId(TYPE_GRADE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_MESSAGES, R.string.menu_messages, MessagesFragment::class)
|
list += NavTarget(DRAWER_ITEM_MESSAGES, R.string.menu_messages, MessagesFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_email)
|
.withIcon(CommunityMaterial.Icon.cmd_email_outline)
|
||||||
.withBadgeTypeId(TYPE_MESSAGE)
|
.withBadgeTypeId(TYPE_MESSAGE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_HOMEWORK, R.string.menu_homework, HomeworkFragment::class)
|
list += NavTarget(DRAWER_ITEM_HOMEWORK, R.string.menu_homework, HomeworkFragment::class)
|
||||||
.withIcon(SzkolnyFont.Icon.szf_file_document_edit)
|
.withIcon(SzkolnyFont.Icon.szf_notebook_outline)
|
||||||
.withBadgeTypeId(TYPE_HOMEWORK)
|
.withBadgeTypeId(TYPE_HOMEWORK)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_BEHAVIOUR, R.string.menu_notices, BehaviourFragment::class)
|
list += NavTarget(DRAWER_ITEM_BEHAVIOUR, R.string.menu_notices, BehaviourFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_message_alert)
|
.withIcon(CommunityMaterial.Icon.cmd_emoticon_outline)
|
||||||
.withBadgeTypeId(TYPE_NOTICE)
|
.withBadgeTypeId(TYPE_NOTICE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_ATTENDANCE, R.string.menu_attendance, AttendanceFragment::class)
|
list += NavTarget(DRAWER_ITEM_ATTENDANCE, R.string.menu_attendance, AttendanceFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_calendar_remove)
|
.withIcon(CommunityMaterial.Icon.cmd_calendar_remove_outline)
|
||||||
.withBadgeTypeId(TYPE_ATTENDANCE)
|
.withBadgeTypeId(TYPE_ATTENDANCE)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_ANNOUNCEMENTS, R.string.menu_announcements, AnnouncementsFragment::class)
|
list += NavTarget(DRAWER_ITEM_ANNOUNCEMENTS, R.string.menu_announcements, AnnouncementsFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_bulletin_board)
|
.withIcon(CommunityMaterial.Icon.cmd_bullhorn_outline)
|
||||||
.withBadgeTypeId(TYPE_ANNOUNCEMENT)
|
.withBadgeTypeId(TYPE_ANNOUNCEMENT)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
|
|
||||||
|
|
||||||
// static drawer items
|
// static drawer items
|
||||||
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsFragment::class)
|
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_bell_ring)
|
.withIcon(CommunityMaterial.Icon.cmd_bell_ring_outline)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
.isStatic(true)
|
.isStatic(true)
|
||||||
.isBelowSeparator(true)
|
.isBelowSeparator(true)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_ITEM_SETTINGS, R.string.menu_settings, SettingsNewFragment::class)
|
list += NavTarget(DRAWER_ITEM_SETTINGS, R.string.menu_settings, SettingsNewFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_settings)
|
.withIcon(CommunityMaterial.Icon2.cmd_settings_outline)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
.isStatic(true)
|
.isStatic(true)
|
||||||
.isBelowSeparator(true)
|
.isBelowSeparator(true)
|
||||||
@ -195,7 +197,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.isInProfileList(false)
|
.isInProfileList(false)
|
||||||
|
|
||||||
list += NavTarget(DRAWER_PROFILE_SYNC_ALL, R.string.menu_sync_all, null)
|
list += NavTarget(DRAWER_PROFILE_SYNC_ALL, R.string.menu_sync_all, null)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_sync)
|
.withIcon(CommunityMaterial.Icon.cmd_download_outline)
|
||||||
.isInProfileList(true)
|
.isInProfileList(true)
|
||||||
|
|
||||||
|
|
||||||
@ -203,7 +205,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
list += NavTarget(TARGET_GRADES_EDITOR, R.string.menu_grades_editor, GradesEditorFragment::class)
|
list += NavTarget(TARGET_GRADES_EDITOR, R.string.menu_grades_editor, GradesEditorFragment::class)
|
||||||
list += NavTarget(TARGET_HELP, R.string.menu_help, HelpFragment::class)
|
list += NavTarget(TARGET_HELP, R.string.menu_help, HelpFragment::class)
|
||||||
list += NavTarget(TARGET_FEEDBACK, R.string.menu_feedback, FeedbackFragment::class)
|
list += NavTarget(TARGET_FEEDBACK, R.string.menu_feedback, FeedbackFragment::class)
|
||||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessagesDetailsFragment::class)
|
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class)
|
||||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||||
|
|
||||||
list
|
list
|
||||||
@ -214,6 +216,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val navView: NavView by lazy { b.navView }
|
val navView: NavView by lazy { b.navView }
|
||||||
val drawer: NavDrawer by lazy { navView.drawer }
|
val drawer: NavDrawer by lazy { navView.drawer }
|
||||||
val bottomSheet: NavBottomSheet by lazy { navView.bottomSheet }
|
val bottomSheet: NavBottomSheet by lazy { navView.bottomSheet }
|
||||||
|
val errorSnackbar: ErrorSnackbar by lazy { ErrorSnackbar(this) }
|
||||||
|
|
||||||
val swipeRefreshLayout: SwipeRefreshLayoutNoTouch by lazy { b.swipeRefreshLayout }
|
val swipeRefreshLayout: SwipeRefreshLayoutNoTouch by lazy { b.swipeRefreshLayout }
|
||||||
|
|
||||||
@ -240,12 +243,14 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
setTheme(Themes.appTheme)
|
setTheme(Themes.appTheme)
|
||||||
|
|
||||||
app.appConfig.language?.let {
|
app.config.ui.language?.let {
|
||||||
setLanguage(it)
|
setLanguage(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(b.root)
|
setContentView(b.root)
|
||||||
|
|
||||||
|
errorSnackbar.setCoordinator(b.navView.coordinator, b.navView.bottomBar)
|
||||||
|
|
||||||
navLoading = true
|
navLoading = true
|
||||||
|
|
||||||
b.navView.apply {
|
b.navView.apply {
|
||||||
@ -301,10 +306,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawer.apply {
|
drawer.apply {
|
||||||
setAccountHeaderBackground(app.appConfig.headerBackground)
|
setAccountHeaderBackground(app.config.ui.headerBackground)
|
||||||
|
|
||||||
drawerProfileListEmptyListener = {
|
drawerProfileListEmptyListener = {
|
||||||
app.appConfig.loginFinished = false
|
app.config.loginFinished = false
|
||||||
app.saveConfig("loginFinished")
|
app.saveConfig("loginFinished")
|
||||||
profileListEmptyListener()
|
profileListEmptyListener()
|
||||||
}
|
}
|
||||||
@ -329,7 +334,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
drawerProfileSettingClickListener = this@MainActivity.profileSettingClickListener
|
drawerProfileSettingClickListener = this@MainActivity.profileSettingClickListener
|
||||||
|
|
||||||
miniDrawerVisibleLandscape = null
|
miniDrawerVisibleLandscape = null
|
||||||
miniDrawerVisiblePortrait = app.appConfig.miniDrawerVisible
|
miniDrawerVisiblePortrait = app.config.ui.miniMenuVisible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +350,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (!profileListEmpty) {
|
if (!profileListEmpty) {
|
||||||
handleIntent(intent?.extras)
|
handleIntent(intent?.extras)
|
||||||
}
|
}
|
||||||
app.db.profileDao().getAllFull().observe(this, Observer { profiles ->
|
app.db.profileDao().allFull.observe(this, Observer { profiles ->
|
||||||
// TODO fix weird -1 profiles ???
|
// TODO fix weird -1 profiles ???
|
||||||
profiles.removeAll { it.id < 0 }
|
profiles.removeAll { it.id < 0 }
|
||||||
drawer.setProfileList(profiles)
|
drawer.setProfileList(profiles)
|
||||||
@ -362,7 +367,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (app.profile != null)
|
if (app.profile != null)
|
||||||
setDrawerItems()
|
setDrawerItems()
|
||||||
|
|
||||||
app.db.metadataDao().getUnreadCounts().observe(this, Observer { unreadCounters ->
|
app.db.metadataDao().unreadCounts.observe(this, Observer { unreadCounters ->
|
||||||
unreadCounters.map {
|
unreadCounters.map {
|
||||||
it.type = it.thingType
|
it.type = it.thingType
|
||||||
}
|
}
|
||||||
@ -371,27 +376,34 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
b.swipeRefreshLayout.isEnabled = true
|
b.swipeRefreshLayout.isEnabled = true
|
||||||
b.swipeRefreshLayout.setOnRefreshListener { this.syncCurrentFeature() }
|
b.swipeRefreshLayout.setOnRefreshListener { this.syncCurrentFeature() }
|
||||||
|
b.swipeRefreshLayout.setColorSchemeResources(
|
||||||
|
R.color.md_blue_500,
|
||||||
|
R.color.md_amber_500,
|
||||||
|
R.color.md_green_500
|
||||||
|
)
|
||||||
|
|
||||||
isStoragePermissionGranted()
|
isStoragePermissionGranted()
|
||||||
|
|
||||||
SyncWorker.scheduleNext(app)
|
SyncWorker.scheduleNext(app)
|
||||||
|
|
||||||
// APP BACKGROUND
|
// APP BACKGROUND
|
||||||
if (app.appConfig.appBackground != null) {
|
if (app.config.ui.appBackground != null) {
|
||||||
try {
|
try {
|
||||||
var bg = app.appConfig.appBackground
|
app.config.ui.appBackground?.let {
|
||||||
val bgDir = File(Environment.getExternalStoragePublicDirectory("Szkolny.eu"), "bg")
|
var bg = it
|
||||||
if (bgDir.exists()) {
|
val bgDir = File(Environment.getExternalStoragePublicDirectory("Szkolny.eu"), "bg")
|
||||||
val files = bgDir.listFiles()
|
if (bgDir.exists()) {
|
||||||
val r = Random()
|
val files = bgDir.listFiles()
|
||||||
val i = r.nextInt(files.size)
|
val r = Random()
|
||||||
bg = files[i].toString()
|
val i = r.nextInt(files.size)
|
||||||
}
|
bg = files[i].toString()
|
||||||
val linearLayout = b.root
|
}
|
||||||
if (bg.endsWith(".gif")) {
|
val linearLayout = b.root
|
||||||
linearLayout.background = GifDrawable(bg)
|
if (bg.endsWith(".gif")) {
|
||||||
} else {
|
linearLayout.background = GifDrawable(bg)
|
||||||
linearLayout.background = BitmapDrawable.createFromPath(bg)
|
} else {
|
||||||
|
linearLayout.background = BitmapDrawable.createFromPath(bg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@ -399,7 +411,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WHAT'S NEW DIALOG
|
// WHAT'S NEW DIALOG
|
||||||
if (app.appConfig.lastAppVersion != BuildConfig.VERSION_CODE) {
|
if (app.config.appVersion < BuildConfig.VERSION_CODE) {
|
||||||
ServerRequest(app, app.requestScheme + APP_URL + "main.php?just_updated", "MainActivity/JU")
|
ServerRequest(app, app.requestScheme + APP_URL + "main.php?just_updated", "MainActivity/JU")
|
||||||
.run { e, result ->
|
.run { e, result ->
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
@ -410,21 +422,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (app.appConfig.lastAppVersion < 170) {
|
if (app.config.appVersion < 170) {
|
||||||
//Intent intent = new Intent(this, ChangelogIntroActivity.class);
|
//Intent intent = new Intent(this, ChangelogIntroActivity.class);
|
||||||
//startActivity(intent);
|
//startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
app.appConfig.lastAppVersion = BuildConfig.VERSION_CODE
|
app.config.appVersion = BuildConfig.VERSION_CODE
|
||||||
app.saveConfig("lastAppVersion")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RATE SNACKBAR
|
// RATE SNACKBAR
|
||||||
if (app.appConfig.appRateSnackbarTime != 0L && app.appConfig.appRateSnackbarTime <= System.currentTimeMillis()) {
|
if (app.config.appRateSnackbarTime != 0L && app.config.appRateSnackbarTime <= System.currentTimeMillis()) {
|
||||||
navView.coordinator.postDelayed({
|
navView.coordinator.postDelayed({
|
||||||
CafeBar.builder(this)
|
CafeBar.builder(this)
|
||||||
.content(R.string.rate_snackbar_text)
|
.content(R.string.rate_snackbar_text)
|
||||||
.icon(IconicsDrawable(this).icon(CommunityMaterial.Icon2.cmd_star).size(IconicsSize.dp(20)).color(IconicsColor.colorInt(Themes.getPrimaryTextColor(this))))
|
.icon(IconicsDrawable(this).icon(CommunityMaterial.Icon2.cmd_star_outline).size(IconicsSize.dp(20)).color(IconicsColor.colorInt(Themes.getPrimaryTextColor(this))))
|
||||||
.positiveText(R.string.rate_snackbar_positive)
|
.positiveText(R.string.rate_snackbar_positive)
|
||||||
.positiveColor(-0xb350b0)
|
.positiveColor(-0xb350b0)
|
||||||
.negativeText(R.string.rate_snackbar_negative)
|
.negativeText(R.string.rate_snackbar_negative)
|
||||||
@ -434,20 +445,17 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.onPositive { cafeBar ->
|
.onPositive { cafeBar ->
|
||||||
Utils.openGooglePlay(this)
|
Utils.openGooglePlay(this)
|
||||||
cafeBar.dismiss()
|
cafeBar.dismiss()
|
||||||
app.appConfig.appRateSnackbarTime = 0
|
app.config.appRateSnackbarTime = 0
|
||||||
app.saveConfig("appRateSnackbarTime")
|
|
||||||
}
|
}
|
||||||
.onNegative { cafeBar ->
|
.onNegative { cafeBar ->
|
||||||
Toast.makeText(this, "Szkoda, opinie innych pomagają mi rozwijać aplikację.", Toast.LENGTH_LONG).show()
|
Toast.makeText(this, "Szkoda, opinie innych pomagają mi rozwijać aplikację.", Toast.LENGTH_LONG).show()
|
||||||
cafeBar.dismiss()
|
cafeBar.dismiss()
|
||||||
app.appConfig.appRateSnackbarTime = 0
|
app.config.appRateSnackbarTime = 0
|
||||||
app.saveConfig("appRateSnackbarTime")
|
|
||||||
}
|
}
|
||||||
.onNeutral { cafeBar ->
|
.onNeutral { cafeBar ->
|
||||||
Toast.makeText(this, "OK", Toast.LENGTH_LONG).show()
|
Toast.makeText(this, "OK", Toast.LENGTH_LONG).show()
|
||||||
cafeBar.dismiss()
|
cafeBar.dismiss()
|
||||||
app.appConfig.appRateSnackbarTime = System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000
|
app.config.appRateSnackbarTime = System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000
|
||||||
app.saveConfig("appRateSnackbarTime")
|
|
||||||
}
|
}
|
||||||
.autoDismiss(false)
|
.autoDismiss(false)
|
||||||
.swipeToDismiss(true)
|
.swipeToDismiss(true)
|
||||||
@ -461,25 +469,25 @@ class MainActivity : AppCompatActivity() {
|
|||||||
bottomSheet.appendItems(
|
bottomSheet.appendItems(
|
||||||
BottomSheetPrimaryItem(false)
|
BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_sync)
|
.withTitle(R.string.menu_sync)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_sync)
|
.withIcon(CommunityMaterial.Icon.cmd_download_outline)
|
||||||
.withOnClickListener(View.OnClickListener {
|
.withOnClickListener(View.OnClickListener {
|
||||||
bottomSheet.close()
|
bottomSheet.close()
|
||||||
app.apiEdziennik.guiSyncFeature(app, this, App.profileId, R.string.sync_dialog_title, R.string.sync_dialog_text, R.string.sync_done, fragmentToFeature(navTargetId))
|
SyncViewListDialog(this, navTargetId)
|
||||||
}),
|
}),
|
||||||
BottomSheetSeparatorItem(false),
|
BottomSheetSeparatorItem(false),
|
||||||
BottomSheetPrimaryItem(false)
|
BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_settings)
|
.withTitle(R.string.menu_settings)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_settings)
|
.withIcon(CommunityMaterial.Icon2.cmd_settings_outline)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_SETTINGS) }),
|
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_SETTINGS) }),
|
||||||
BottomSheetPrimaryItem(false)
|
BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_feedback)
|
.withTitle(R.string.menu_feedback)
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_help_circle)
|
.withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
||||||
)
|
)
|
||||||
if (App.devMode) {
|
if (App.devMode) {
|
||||||
bottomSheet += BottomSheetPrimaryItem(false)
|
bottomSheet += BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_debug)
|
.withTitle(R.string.menu_debug)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_android_debug_bridge)
|
.withIcon(CommunityMaterial.Icon.cmd_android_studio)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) })
|
.withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_DEBUG) })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,9 +535,14 @@ class MainActivity : AppCompatActivity() {
|
|||||||
DRAWER_ITEM_MESSAGES -> MessagesFragment.pageSelection
|
DRAWER_ITEM_MESSAGES -> MessagesFragment.pageSelection
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
val arguments = when (navTargetId) {
|
||||||
|
DRAWER_ITEM_TIMETABLE -> JsonObject("weekStart" to TimetableFragment.pageSelection?.weekStart?.stringY_m_d)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
EdziennikTask.syncProfile(
|
EdziennikTask.syncProfile(
|
||||||
App.profileId,
|
App.profileId,
|
||||||
listOf(navTargetId to fragmentParam)
|
listOf(navTargetId to fragmentParam),
|
||||||
|
arguments
|
||||||
).enqueue(this)
|
).enqueue(this)
|
||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
@ -573,7 +586,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onSyncErrorEvent(event: ApiTaskErrorEvent) {
|
fun onSyncErrorEvent(event: ApiTaskErrorEvent) {
|
||||||
|
navView.toolbar.apply {
|
||||||
|
subtitleFormat = R.string.toolbar_subtitle
|
||||||
|
subtitleFormatWithUnread = R.plurals.toolbar_subtitle_with_unread
|
||||||
|
subtitle = "Gotowe"
|
||||||
|
}
|
||||||
|
errorSnackbar.addError(event.error).show()
|
||||||
}
|
}
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
|
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
|
||||||
@ -605,22 +623,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
private fun fragmentToFeature(currentFragment: Int): Int {
|
|
||||||
return when (currentFragment) {
|
|
||||||
DRAWER_ITEM_TIMETABLE -> FEATURE_TIMETABLE
|
|
||||||
DRAWER_ITEM_AGENDA -> FEATURE_AGENDA
|
|
||||||
DRAWER_ITEM_GRADES -> FEATURE_GRADES
|
|
||||||
DRAWER_ITEM_HOMEWORK -> FEATURE_HOMEWORK
|
|
||||||
DRAWER_ITEM_BEHAVIOUR -> FEATURE_NOTICES
|
|
||||||
DRAWER_ITEM_ATTENDANCE -> FEATURE_ATTENDANCE
|
|
||||||
DRAWER_ITEM_MESSAGES -> when (MessagesFragment.pageSelection) {
|
|
||||||
1 -> FEATURE_MESSAGES_OUTBOX
|
|
||||||
else -> FEATURE_MESSAGES_INBOX
|
|
||||||
}
|
|
||||||
DRAWER_ITEM_ANNOUNCEMENTS -> FEATURE_ANNOUNCEMENTS
|
|
||||||
else -> FEATURE_ALL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun fragmentToSyncName(currentFragment: Int): Int {
|
private fun fragmentToSyncName(currentFragment: Int): Int {
|
||||||
return when (currentFragment) {
|
return when (currentFragment) {
|
||||||
DRAWER_ITEM_TIMETABLE -> R.string.sync_feature_timetable
|
DRAWER_ITEM_TIMETABLE -> R.string.sync_feature_timetable
|
||||||
@ -684,29 +687,33 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (navLoading) {
|
if (navLoading) {
|
||||||
navLoading = false
|
|
||||||
b.fragment.removeAllViews()
|
b.fragment.removeAllViews()
|
||||||
if (intentTargetId == -1)
|
if (intentTargetId == -1)
|
||||||
intentTargetId = HOME_ID
|
intentTargetId = HOME_ID
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
app.profile == null -> {
|
app.profile == null || app.profile.id == -1 -> {
|
||||||
if (intentProfileId == -1)
|
if (intentProfileId == -1)
|
||||||
intentProfileId = app.appSharedPrefs.getInt("current_profile_id", 1)
|
intentProfileId = app.appSharedPrefs.getInt("current_profile_id", 1)
|
||||||
loadProfile(intentProfileId, intentTargetId)
|
loadProfile(intentProfileId, intentTargetId, extras)
|
||||||
}
|
}
|
||||||
intentProfileId != -1 -> {
|
intentProfileId != -1 -> {
|
||||||
loadProfile(intentProfileId, intentTargetId)
|
if (app.profile.id != intentProfileId)
|
||||||
|
loadProfile(intentProfileId, intentTargetId, extras)
|
||||||
|
else
|
||||||
|
loadTarget(intentTargetId, extras)
|
||||||
}
|
}
|
||||||
intentTargetId != -1 -> {
|
intentTargetId != -1 -> {
|
||||||
drawer.currentProfile = app.profile.id
|
drawer.currentProfile = app.profile.id
|
||||||
loadTarget(intentTargetId, extras)
|
if (navTargetId != intentTargetId || navLoading)
|
||||||
|
loadTarget(intentTargetId, extras)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
drawer.currentProfile = app.profile.id
|
drawer.currentProfile = app.profile.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
navLoading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recreate() {
|
override fun recreate() {
|
||||||
@ -754,7 +761,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!app.appConfig.loginFinished)
|
if (!app.config.loginFinished)
|
||||||
finish()
|
finish()
|
||||||
else {
|
else {
|
||||||
handleIntent(data?.extras)
|
handleIntent(data?.extras)
|
||||||
@ -791,13 +798,16 @@ class MainActivity : AppCompatActivity() {
|
|||||||
this.runOnUiThread {
|
this.runOnUiThread {
|
||||||
if (app.profile == null) {
|
if (app.profile == null) {
|
||||||
LoginActivity.firstCompleted = false
|
LoginActivity.firstCompleted = false
|
||||||
if (app.appConfig.loginFinished) {
|
if (app.config.loginFinished) {
|
||||||
// this shouldn't run
|
// this shouldn't run
|
||||||
profileListEmptyListener()
|
profileListEmptyListener()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setDrawerItems()
|
setDrawerItems()
|
||||||
drawer.currentProfile = app.profile.id
|
// 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)
|
loadTarget(drawerSelection, arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -964,7 +974,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val item = DrawerPrimaryItem()
|
val item = DrawerPrimaryItem()
|
||||||
.withIdentifier(target.id.toLong())
|
.withIdentifier(target.id.toLong())
|
||||||
.withName(target.name)
|
.withName(target.name)
|
||||||
.withHiddenInMiniDrawer(!app.appConfig.miniDrawerButtonIds.contains(target.id))
|
.withHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id))
|
||||||
.also { if (target.description != null) it.withDescription(target.description!!) }
|
.also { if (target.description != null) it.withDescription(target.description!!) }
|
||||||
.also { if (target.icon != null) it.withIcon(target.icon!!) }
|
.also { if (target.icon != null) it.withIcon(target.icon!!) }
|
||||||
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
|
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
|
||||||
@ -1042,7 +1052,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
loadTarget(DRAWER_ITEM_SETTINGS, null)
|
loadTarget(DRAWER_ITEM_SETTINGS, null)
|
||||||
} else if (item.itemId == 2) {
|
} else if (item.itemId == 2) {
|
||||||
app.apiEdziennik.guiRemoveProfile(this@MainActivity, profileId, profile.name?.getText(this).toString())
|
ProfileRemoveDialog(this, profileId, profile.name?.getText(this)?.toString() ?: "?")
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,8 @@ public class Notifier {
|
|||||||
|
|
||||||
public boolean shouldBeQuiet() {
|
public boolean shouldBeQuiet() {
|
||||||
long now = Time.getNow().getInMillis();
|
long now = Time.getNow().getInMillis();
|
||||||
long start = app.appConfig.quietHoursStart;
|
long start = app.config.getSync().getQuietHoursStart();
|
||||||
long end = app.appConfig.quietHoursEnd;
|
long end = app.config.getSync().getQuietHoursEnd();
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
end += 1000 * 60 * 60 * 24;
|
end += 1000 * 60 * 60 * 24;
|
||||||
//Log.d(TAG, "Night passing");
|
//Log.d(TAG, "Night passing");
|
||||||
@ -104,7 +104,7 @@ public class Notifier {
|
|||||||
//Log.d(TAG, "Now is smaller");
|
//Log.d(TAG, "Now is smaller");
|
||||||
}
|
}
|
||||||
//Log.d(TAG, "Start is "+start+", now is "+now+", end is "+end);
|
//Log.d(TAG, "Start is "+start+", now is "+now+", end is "+end);
|
||||||
return app.appConfig.quietHoursStart > 0 && now >= start && now <= end;
|
return start > 0 && now >= start && now <= end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNotificationDefaults() {
|
public int getNotificationDefaults() {
|
||||||
@ -311,13 +311,14 @@ public class Notifier {
|
|||||||
\____/| .__/ \__,_|\__,_|\__\___||___/
|
\____/| .__/ \__,_|\__,_|\__\___||___/
|
||||||
| |
|
| |
|
||||||
|*/
|
|*/
|
||||||
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename) {
|
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename, boolean updateDirect) {
|
||||||
if (!app.appConfig.notifyAboutUpdates)
|
if (!app.config.getSync().getNotifyAboutUpdates())
|
||||||
return;
|
return;
|
||||||
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
||||||
.putExtra("update_version", updateVersion)
|
.putExtra("update_version", updateVersion)
|
||||||
.putExtra("update_url", updateUrl)
|
.putExtra("update_url", updateUrl)
|
||||||
.putExtra("update_filename", updateFilename);
|
.putExtra("update_filename", updateFilename)
|
||||||
|
.putExtra("update_direct", updateDirect);
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
@ -339,7 +340,7 @@ public class Notifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notificationUpdatesHide() {
|
public void notificationUpdatesHide() {
|
||||||
if (!app.appConfig.notifyAboutUpdates)
|
if (!app.config.getSync().getNotifyAboutUpdates())
|
||||||
return;
|
return;
|
||||||
notificationManager.cancel(ID_UPDATES);
|
notificationManager.cancel(ID_UPDATES);
|
||||||
}
|
}
|
||||||
|
@ -1,450 +0,0 @@
|
|||||||
package pl.szczodrzynski.edziennik;
|
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.appwidget.AppWidgetManager;
|
|
||||||
import android.appwidget.AppWidgetProvider;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.RemoteViews;
|
|
||||||
|
|
||||||
import com.mikepenz.iconics.IconicsColor;
|
|
||||||
import com.mikepenz.iconics.IconicsDrawable;
|
|
||||||
import com.mikepenz.iconics.IconicsSize;
|
|
||||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week;
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.WidgetConfig;
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.timetable.LessonDetailsActivity;
|
|
||||||
import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService;
|
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.ExtensionsKt.filterOutArchived;
|
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK;
|
|
||||||
import static pl.szczodrzynski.edziennik.utils.Utils.bs;
|
|
||||||
|
|
||||||
|
|
||||||
public class WidgetTimetable extends AppWidgetProvider {
|
|
||||||
|
|
||||||
|
|
||||||
public static final String ACTION_SYNC_DATA = "ACTION_SYNC_DATA";
|
|
||||||
private static final String TAG = "WidgetTimetable";
|
|
||||||
private static int modeInt = 0;
|
|
||||||
|
|
||||||
public WidgetTimetable() {
|
|
||||||
// Start the worker thread
|
|
||||||
//HandlerThread sWorkerThread = new HandlerThread("WidgetTimetable-worker");
|
|
||||||
//sWorkerThread.start();
|
|
||||||
//Handler sWorkerQueue = new Handler(sWorkerThread.getLooper());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SparseArray<List<ItemWidgetTimetableModel>> timetables = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (ACTION_SYNC_DATA.equals(intent.getAction())) {
|
|
||||||
EdziennikTask.Companion.sync().enqueue(context);
|
|
||||||
}
|
|
||||||
super.onReceive(context, intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PendingIntent getPendingSelfIntent(Context context, String action) {
|
|
||||||
Intent intent = new Intent(context, WidgetTimetable.class);
|
|
||||||
intent.setAction(action);
|
|
||||||
return getPendingSelfIntent(context, intent);
|
|
||||||
}
|
|
||||||
public static PendingIntent getPendingSelfIntent(Context context, Intent intent) {
|
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap drawableToBitmap (Drawable drawable) {
|
|
||||||
|
|
||||||
if (drawable instanceof BitmapDrawable) {
|
|
||||||
return ((BitmapDrawable)drawable).getBitmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
|
||||||
Canvas canvas = new Canvas(bitmap);
|
|
||||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
|
||||||
drawable.draw(canvas);
|
|
||||||
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
|
||||||
ComponentName thisWidget = new ComponentName(context, WidgetTimetable.class);
|
|
||||||
|
|
||||||
timetables = new SparseArray<>();
|
|
||||||
//timetables.clear();
|
|
||||||
|
|
||||||
App app = (App)context.getApplicationContext();
|
|
||||||
|
|
||||||
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
|
||||||
// There may be multiple widgets active, so update all of them
|
|
||||||
for (int appWidgetId : allWidgetIds) {
|
|
||||||
|
|
||||||
//d(TAG, "thr "+Thread.currentThread().getName());
|
|
||||||
|
|
||||||
WidgetConfig widgetConfig = app.appConfig.widgetTimetableConfigs.get(appWidgetId);
|
|
||||||
if (widgetConfig == null) {
|
|
||||||
widgetConfig = new WidgetConfig(app.profileFirstId());
|
|
||||||
app.appConfig.widgetTimetableConfigs.put(appWidgetId, widgetConfig);
|
|
||||||
app.appConfig.savePending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteViews views;
|
|
||||||
if (widgetConfig.bigStyle) {
|
|
||||||
views = new RemoteViews(context.getPackageName(), widgetConfig.darkTheme ? R.layout.widget_timetable_dark_big : R.layout.widget_timetable_big);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
views = new RemoteViews(context.getPackageName(), widgetConfig.darkTheme ? R.layout.widget_timetable_dark : R.layout.widget_timetable);
|
|
||||||
}
|
|
||||||
|
|
||||||
PorterDuff.Mode mode = PorterDuff.Mode.DST_IN;
|
|
||||||
/*if (widgetConfig.darkTheme) {
|
|
||||||
switch (modeInt) {
|
|
||||||
case 0:
|
|
||||||
mode = PorterDuff.Mode.ADD;
|
|
||||||
d(TAG, "ADD");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
mode = PorterDuff.Mode.DST_ATOP;
|
|
||||||
d(TAG, "DST_ATOP");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mode = PorterDuff.Mode.DST_IN;
|
|
||||||
d(TAG, "DST_IN");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
mode = PorterDuff.Mode.DST_OUT;
|
|
||||||
d(TAG, "DST_OUT");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
mode = PorterDuff.Mode.DST_OVER;
|
|
||||||
d(TAG, "DST_OVER");
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
mode = PorterDuff.Mode.LIGHTEN;
|
|
||||||
d(TAG, "LIGHTEN");
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
mode = PorterDuff.Mode.MULTIPLY;
|
|
||||||
d(TAG, "MULTIPLY");
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
mode = PorterDuff.Mode.OVERLAY;
|
|
||||||
d(TAG, "OVERLAY");
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
mode = PorterDuff.Mode.SCREEN;
|
|
||||||
d(TAG, "SCREEN");
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
mode = PorterDuff.Mode.SRC_ATOP;
|
|
||||||
d(TAG, "SRC_ATOP");
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
mode = PorterDuff.Mode.SRC_IN;
|
|
||||||
d(TAG, "SRC_IN");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
mode = PorterDuff.Mode.SRC_OUT;
|
|
||||||
d(TAG, "SRC_OUT");
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
mode = PorterDuff.Mode.SRC_OVER;
|
|
||||||
d(TAG, "SRC_OVER");
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
mode = PorterDuff.Mode.XOR;
|
|
||||||
d(TAG, "XOR");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
modeInt = 0;
|
|
||||||
mode = PorterDuff.Mode.ADD;
|
|
||||||
d(TAG, "ADD");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
|
||||||
// this code seems to crash the launcher on >= P
|
|
||||||
float transparency = widgetConfig.opacity; //0...1
|
|
||||||
long colorFilter = 0x01000000L * (long) (255f * transparency);
|
|
||||||
try {
|
|
||||||
final Method[] declaredMethods = Class.forName("android.widget.RemoteViews").getDeclaredMethods();
|
|
||||||
final int len = declaredMethods.length;
|
|
||||||
if (len > 0) {
|
|
||||||
for (int m = 0; m < len; m++) {
|
|
||||||
final Method method = declaredMethods[m];
|
|
||||||
if (method.getName().equals("setDrawableParameters")) {
|
|
||||||
method.setAccessible(true);
|
|
||||||
method.invoke(views, R.id.widgetTimetableListView, true, -1, (int) colorFilter, mode, -1);
|
|
||||||
method.invoke(views, R.id.widgetTimetableHeader, true, -1, (int) colorFilter, mode, -1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent refreshIntent = new Intent(context, WidgetTimetable.class);
|
|
||||||
refreshIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
|
||||||
refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
|
|
||||||
PendingIntent pendingRefreshIntent = PendingIntent.getBroadcast(context,
|
|
||||||
0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, pendingRefreshIntent);
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetTimetableSync, WidgetTimetable.getPendingSelfIntent(context, ACTION_SYNC_DATA));
|
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.widgetTimetableRefresh, new IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh)
|
|
||||||
.color(IconicsColor.colorInt(Color.WHITE))
|
|
||||||
.size(IconicsSize.dp(widgetConfig.bigStyle ? 24 : 16)).toBitmap());
|
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.widgetTimetableSync, new IconicsDrawable(context, CommunityMaterial.Icon2.cmd_sync)
|
|
||||||
.color(IconicsColor.colorInt(Color.WHITE))
|
|
||||||
.size(IconicsSize.dp(widgetConfig.bigStyle ? 24 : 16)).toBitmap());
|
|
||||||
|
|
||||||
boolean unified = widgetConfig.profileId == -1;
|
|
||||||
|
|
||||||
List<Profile> profileList = new ArrayList<>();
|
|
||||||
if (unified) {
|
|
||||||
profileList = app.db.profileDao().getAllNow();
|
|
||||||
filterOutArchived(profileList);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Profile profile = app.db.profileDao().getFullByIdNow(widgetConfig.profileId);
|
|
||||||
if (profile != null) {
|
|
||||||
profileList.add(profile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//d(TAG, "Profiles: "+ Arrays.toString(profileList.toArray()));
|
|
||||||
|
|
||||||
if (profileList == null || profileList.size() == 0) {
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE);
|
|
||||||
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_profile_doesnt_exist));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE);
|
|
||||||
//Register profile;
|
|
||||||
|
|
||||||
long bellSyncDiffMillis = 0;
|
|
||||||
if (app.appConfig.bellSyncDiff != null) {
|
|
||||||
bellSyncDiffMillis = app.appConfig.bellSyncDiff.hour * 60 * 60 * 1000 + app.appConfig.bellSyncDiff.minute * 60 * 1000 + app.appConfig.bellSyncDiff.second * 1000;
|
|
||||||
bellSyncDiffMillis *= app.appConfig.bellSyncMultiplier;
|
|
||||||
bellSyncDiffMillis *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ItemWidgetTimetableModel> lessonList = new ArrayList<>();
|
|
||||||
|
|
||||||
Time syncedNow = Time.fromMillis(Time.getNow().getInMillis() + bellSyncDiffMillis);
|
|
||||||
|
|
||||||
Date today = Date.getToday();
|
|
||||||
|
|
||||||
int openProfileId = -1;
|
|
||||||
Date displayingDate = null;
|
|
||||||
int displayingWeekDay = 0;
|
|
||||||
if (unified) {
|
|
||||||
views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.widget_timetable_title_unified));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
views.setTextViewText(R.id.widgetTimetableSubtitle, profileList.get(0).getName());
|
|
||||||
openProfileId = profileList.get(0).getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<LessonFull> lessons = app.db.lessonDao().getAllWeekNow(unified ? -1 : openProfileId, today.clone().stepForward(0, 0, -today.getWeekDay()), today);
|
|
||||||
|
|
||||||
int scrollPos = 0;
|
|
||||||
|
|
||||||
for (Profile profile: profileList) {
|
|
||||||
Date profileDisplayingDate = HomeFragment.findDateWithLessons(profile.getId(), lessons, syncedNow, 1);
|
|
||||||
int profileDisplayingWeekDay = profileDisplayingDate.getWeekDay();
|
|
||||||
int dayDiff = Date.diffDays(profileDisplayingDate, Date.getToday());
|
|
||||||
|
|
||||||
//d(TAG, "For profile "+profile.name+" displayingDate is "+profileDisplayingDate.getStringY_m_d());
|
|
||||||
if (displayingDate == null || profileDisplayingDate.getValue() < displayingDate.getValue()) {
|
|
||||||
displayingDate = profileDisplayingDate;
|
|
||||||
displayingWeekDay = profileDisplayingWeekDay;
|
|
||||||
//d(TAG, "Setting as global dd");
|
|
||||||
if (dayDiff == 0) {
|
|
||||||
views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.day_today_format, Week.getFullDayName(displayingWeekDay)));
|
|
||||||
} else if (dayDiff == 1) {
|
|
||||||
views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.day_tomorrow_format, Week.getFullDayName(displayingWeekDay)));
|
|
||||||
} else {
|
|
||||||
views.setTextViewText(R.id.widgetTimetableTitle, Week.getFullDayName(displayingWeekDay) + " " + profileDisplayingDate.getStringDm());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Profile profile: profileList) {
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
List<EventFull> events = app.db.eventDao().getAllByDateNow(profile.getId(), displayingDate);
|
|
||||||
if (events == null)
|
|
||||||
events = new ArrayList<>();
|
|
||||||
|
|
||||||
if (unified) {
|
|
||||||
ItemWidgetTimetableModel separator = new ItemWidgetTimetableModel();
|
|
||||||
separator.profileId = profile.getId();
|
|
||||||
separator.bigStyle = widgetConfig.bigStyle;
|
|
||||||
separator.darkTheme = widgetConfig.darkTheme;
|
|
||||||
separator.separatorProfileName = profile.getName();
|
|
||||||
lessonList.add(separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (LessonFull lesson : lessons) {
|
|
||||||
//d(TAG, "Profile "+profile.id+" Lesson profileId "+lesson.profileId+" weekDay "+lesson.weekDay+", "+lesson);
|
|
||||||
if (profile.getId() != lesson.profileId || displayingWeekDay != lesson.weekDay)
|
|
||||||
continue;
|
|
||||||
//d(TAG, "Not skipped");
|
|
||||||
ItemWidgetTimetableModel model = new ItemWidgetTimetableModel();
|
|
||||||
|
|
||||||
model.bigStyle = widgetConfig.bigStyle;
|
|
||||||
model.darkTheme = widgetConfig.darkTheme;
|
|
||||||
|
|
||||||
model.profileId = profile.getId();
|
|
||||||
|
|
||||||
model.lessonDate = displayingDate;
|
|
||||||
model.startTime = lesson.startTime;
|
|
||||||
model.endTime = lesson.endTime;
|
|
||||||
|
|
||||||
model.lessonPassed = (syncedNow.getValue() > lesson.endTime.getValue()) && displayingWeekDay == Week.getTodayWeekDay();
|
|
||||||
model.lessonCurrent = (Time.inRange(lesson.startTime, lesson.endTime, syncedNow)) && displayingWeekDay == Week.getTodayWeekDay();
|
|
||||||
|
|
||||||
if (model.lessonCurrent) {
|
|
||||||
scrollPos = pos;
|
|
||||||
} else if (model.lessonPassed) {
|
|
||||||
scrollPos = pos + 1;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
model.subjectName = bs(lesson.subjectLongName);
|
|
||||||
model.classroomName = lesson.classroomName;
|
|
||||||
|
|
||||||
model.bellSyncDiffMillis = bellSyncDiffMillis;
|
|
||||||
|
|
||||||
if (lesson.changeId != 0) {
|
|
||||||
if (lesson.changeType == LessonChange.TYPE_CHANGE) {
|
|
||||||
model.lessonChange = true;
|
|
||||||
if (lesson.changedClassroomName()) {
|
|
||||||
model.newClassroomName = lesson.changeClassroomName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lesson.changedSubjectLongName()) {
|
|
||||||
model.newSubjectName = lesson.changeSubjectLongName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lesson.changeType == LessonChange.TYPE_CANCELLED) {
|
|
||||||
model.lessonCancelled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (EventFull event : events) {
|
|
||||||
if (event.startTime == null)
|
|
||||||
continue;
|
|
||||||
if (event.eventDate.getValue() == displayingDate.getValue()
|
|
||||||
&& event.startTime.getValue() == lesson.startTime.getValue()) {
|
|
||||||
model.eventColors.add(event.type == TYPE_HOMEWORK ? ItemWidgetTimetableModel.EVENT_COLOR_HOMEWORK : event.getColor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lessonList.add(model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lessonList.size() == 0) {
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE);
|
|
||||||
views.setRemoteAdapter(R.id.widgetTimetableListView, new Intent());
|
|
||||||
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons));
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE);
|
|
||||||
|
|
||||||
timetables.put(appWidgetId, lessonList);
|
|
||||||
//WidgetTimetableListProvider.widgetsLessons.put(appWidgetId, lessons);
|
|
||||||
//views.setRemoteAdapter(R.id.widgetTimetableListView, new Intent());
|
|
||||||
Intent listIntent = new Intent(context, WidgetTimetableService.class);
|
|
||||||
listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
|
||||||
listIntent.setData(Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME)));
|
|
||||||
views.setRemoteAdapter(R.id.widgetTimetableListView, listIntent);
|
|
||||||
|
|
||||||
// template to handle the click listener for each item
|
|
||||||
Intent intentTemplate = new Intent(context, LessonDetailsActivity.class);
|
|
||||||
// Old activities shouldn't be in the history stack
|
|
||||||
intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
||||||
PendingIntent pendingIntentTimetable = PendingIntent.getActivity(context,
|
|
||||||
0,
|
|
||||||
intentTemplate,
|
|
||||||
0);
|
|
||||||
views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable);
|
|
||||||
|
|
||||||
Intent openIntent = new Intent(context, MainActivity.class);
|
|
||||||
openIntent.setAction("android.intent.action.MAIN");
|
|
||||||
if (!unified) {
|
|
||||||
openIntent.putExtra("profileId", openProfileId);
|
|
||||||
openIntent.putExtra("timetableDate", displayingDate.getValue());
|
|
||||||
}
|
|
||||||
openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE);
|
|
||||||
PendingIntent pendingOpenIntent = PendingIntent.getActivity(context,
|
|
||||||
appWidgetId, openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent);
|
|
||||||
|
|
||||||
if (!unified)
|
|
||||||
views.setScrollPosition(R.id.widgetTimetableListView, scrollPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
|
||||||
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetTimetableListView);
|
|
||||||
}
|
|
||||||
//modeInt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnabled(Context context) {
|
|
||||||
// Enter relevant functionality for when the first widget is created
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeleted(Context context, int[] appWidgetIds) {
|
|
||||||
App app = (App) context.getApplicationContext();
|
|
||||||
for (int appWidgetId: appWidgetIds) {
|
|
||||||
app.appConfig.widgetTimetableConfigs.remove(appWidgetId);
|
|
||||||
}
|
|
||||||
app.saveConfig("widgetTimetableConfigs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
371
app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.kt
Normal file
371
app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.kt
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
package pl.szczodrzynski.edziennik
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.appwidget.AppWidgetProvider
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.SparseArray
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.RemoteViews
|
||||||
|
import com.mikepenz.iconics.IconicsDrawable
|
||||||
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||||
|
import com.mikepenz.iconics.utils.colorInt
|
||||||
|
import com.mikepenz.iconics.utils.sizeDp
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
import pl.szczodrzynski.edziennik.widgets.WidgetConfig
|
||||||
|
import pl.szczodrzynski.edziennik.widgets.timetable.LessonDialogActivity
|
||||||
|
import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService
|
||||||
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
|
|
||||||
|
class WidgetTimetable : AppWidgetProvider() {
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (ACTION_SYNC_DATA == intent.action) {
|
||||||
|
EdziennikTask.sync().enqueue(context)
|
||||||
|
}
|
||||||
|
super.onReceive(context, intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||||
|
val thisWidget = ComponentName(context, WidgetTimetable::class.java)
|
||||||
|
|
||||||
|
timetables = SparseArray()
|
||||||
|
//timetables.clear();
|
||||||
|
|
||||||
|
val app = context.applicationContext as App
|
||||||
|
|
||||||
|
var bellSyncDiffMillis: Long = 0
|
||||||
|
app.config.timetable.bellSyncDiff?.let {
|
||||||
|
bellSyncDiffMillis = (it.hour * 60 * 60 * 1000 + it.minute * 60 * 1000 + it.second * 1000).toLong()
|
||||||
|
bellSyncDiffMillis *= app.config.timetable.bellSyncMultiplier.toLong()
|
||||||
|
bellSyncDiffMillis *= -1
|
||||||
|
}
|
||||||
|
|
||||||
|
val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget)
|
||||||
|
|
||||||
|
allWidgetIds?.forEach { appWidgetId ->
|
||||||
|
var widgetConfig = app.appConfig.widgetTimetableConfigs[appWidgetId]
|
||||||
|
if (widgetConfig == null) {
|
||||||
|
widgetConfig = WidgetConfig(app.profileFirstId())
|
||||||
|
app.appConfig.widgetTimetableConfigs[appWidgetId] = widgetConfig
|
||||||
|
app.appConfig.savePending = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val views = if (widgetConfig.bigStyle) {
|
||||||
|
RemoteViews(context.packageName, if (widgetConfig.darkTheme) R.layout.widget_timetable_dark_big else R.layout.widget_timetable_big)
|
||||||
|
} else {
|
||||||
|
RemoteViews(context.packageName, if (widgetConfig.darkTheme) R.layout.widget_timetable_dark else R.layout.widget_timetable)
|
||||||
|
}
|
||||||
|
|
||||||
|
val refreshIntent = Intent(app, WidgetTimetable::class.java)
|
||||||
|
refreshIntent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||||
|
refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
|
||||||
|
val pendingRefreshIntent = PendingIntent.getBroadcast(context,
|
||||||
|
0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, pendingRefreshIntent)
|
||||||
|
|
||||||
|
views.setOnClickPendingIntent(R.id.widgetTimetableSync, getPendingSelfIntent(context, ACTION_SYNC_DATA))
|
||||||
|
|
||||||
|
views.setImageViewBitmap(R.id.widgetTimetableRefresh, IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh)
|
||||||
|
.colorInt(Color.WHITE)
|
||||||
|
.sizeDp(if (widgetConfig.bigStyle) 24 else 16).toBitmap())
|
||||||
|
|
||||||
|
views.setImageViewBitmap(R.id.widgetTimetableSync, IconicsDrawable(context, CommunityMaterial.Icon.cmd_download_outline)
|
||||||
|
.colorInt(Color.WHITE)
|
||||||
|
.sizeDp(if (widgetConfig.bigStyle) 24 else 16).toBitmap())
|
||||||
|
|
||||||
|
prepareAppWidget(app, appWidgetId, views, widgetConfig, bellSyncDiffMillis)
|
||||||
|
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
|
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetTimetableListView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareAppWidget(
|
||||||
|
app: App,
|
||||||
|
appWidgetId: Int,
|
||||||
|
views: RemoteViews,
|
||||||
|
widgetConfig: WidgetConfig,
|
||||||
|
bellSyncDiffMillis: Long
|
||||||
|
) {
|
||||||
|
// get the current bell-synced time
|
||||||
|
val now = Time.fromMillis(Time.getNow().inMillis + bellSyncDiffMillis)
|
||||||
|
|
||||||
|
// set the widget transparency
|
||||||
|
val mode = PorterDuff.Mode.DST_IN
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||||
|
// this code seems to crash the launcher on >= P
|
||||||
|
val transparency = widgetConfig.opacity //0...1
|
||||||
|
val colorFilter = 0x01000000L * (255f * transparency).toLong()
|
||||||
|
try {
|
||||||
|
val declaredMethods = Class.forName("android.widget.RemoteViews").declaredMethods
|
||||||
|
val len = declaredMethods.size
|
||||||
|
if (len > 0) {
|
||||||
|
for (m in 0 until len) {
|
||||||
|
val method = declaredMethods[m]
|
||||||
|
if (method.name == "setDrawableParameters") {
|
||||||
|
method.isAccessible = true
|
||||||
|
method.invoke(views, R.id.widgetTimetableListView, true, -1, colorFilter.toInt(), mode, -1)
|
||||||
|
method.invoke(views, R.id.widgetTimetableHeader, true, -1, colorFilter.toInt(), mode, -1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: ClassNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: InvocationTargetException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IllegalAccessException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val unified = widgetConfig.profileId == -1
|
||||||
|
|
||||||
|
// get all profiles or one profile with the specified id
|
||||||
|
val profileList = if (unified)
|
||||||
|
app.db.profileDao().allNow.filterOutArchived()
|
||||||
|
else
|
||||||
|
listOfNotNull(app.db.profileDao().getByIdNow(widgetConfig.profileId))
|
||||||
|
|
||||||
|
// no profile was found
|
||||||
|
if (profileList.isEmpty()) {
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE)
|
||||||
|
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_profile_doesnt_exist))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE)
|
||||||
|
|
||||||
|
// set lesson search bounds
|
||||||
|
val today = Date.getToday()
|
||||||
|
val searchEnd = today.clone().stepForward(0, 0, 7)
|
||||||
|
|
||||||
|
var scrollPos = 0
|
||||||
|
|
||||||
|
var profileId: Int? = null
|
||||||
|
var displayingDate: Date? = null
|
||||||
|
|
||||||
|
val models = mutableListOf<ItemWidgetTimetableModel>()
|
||||||
|
|
||||||
|
// get all lessons within the search bounds
|
||||||
|
val lessonList = app.db.timetableDao().getBetweenDatesNow(today, searchEnd)
|
||||||
|
|
||||||
|
for (profile in profileList) {
|
||||||
|
|
||||||
|
// add a profile separator with its name
|
||||||
|
if (unified) {
|
||||||
|
val separator = ItemWidgetTimetableModel()
|
||||||
|
separator.profileId = profile.id
|
||||||
|
separator.bigStyle = widgetConfig.bigStyle
|
||||||
|
separator.darkTheme = widgetConfig.darkTheme
|
||||||
|
separator.separatorProfileName = profile.name
|
||||||
|
models.add(separator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for lessons to display
|
||||||
|
val timetableDate = Date.getToday()
|
||||||
|
var checkedDays = 0
|
||||||
|
var lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
|
||||||
|
while ((lessons.isEmpty() || lessons.none {
|
||||||
|
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
|
||||||
|
}) && checkedDays < 7) {
|
||||||
|
timetableDate.stepForward(0, 0, 1)
|
||||||
|
lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
|
||||||
|
checkedDays++
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the displayingDate to show in the header
|
||||||
|
if (!unified) {
|
||||||
|
if (lessons.isNotEmpty())
|
||||||
|
displayingDate = timetableDate
|
||||||
|
profileId = profile.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all events for the current date
|
||||||
|
val events = app.db.eventDao().getAllByDateNow(profile.id, timetableDate)?.filterNotNull() ?: emptyList()
|
||||||
|
|
||||||
|
lessons.forEachIndexed { pos, lesson ->
|
||||||
|
val model = ItemWidgetTimetableModel()
|
||||||
|
|
||||||
|
model.bigStyle = widgetConfig.bigStyle
|
||||||
|
model.darkTheme = widgetConfig.darkTheme
|
||||||
|
|
||||||
|
model.profileId = profile.id
|
||||||
|
|
||||||
|
model.lessonId = lesson.id
|
||||||
|
model.lessonDate = timetableDate
|
||||||
|
model.startTime = lesson.displayStartTime
|
||||||
|
model.endTime = lesson.displayEndTime
|
||||||
|
|
||||||
|
// check if the lesson has already passed or it's currently in progress
|
||||||
|
if (lesson.displayDate == today) {
|
||||||
|
lesson.displayEndTime?.let { endTime ->
|
||||||
|
model.lessonPassed = now > endTime
|
||||||
|
lesson.displayStartTime?.let { startTime ->
|
||||||
|
model.lessonCurrent = now in startTime..endTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set where should the list view scroll to
|
||||||
|
if (model.lessonCurrent) {
|
||||||
|
scrollPos = pos
|
||||||
|
} else if (model.lessonPassed) {
|
||||||
|
scrollPos = pos + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the subject and classroom name
|
||||||
|
model.subjectName = lesson.displaySubjectName
|
||||||
|
model.classroomName = lesson.displayClassroom
|
||||||
|
|
||||||
|
// set the bell sync to calculate progress in ListProvider
|
||||||
|
model.bellSyncDiffMillis = bellSyncDiffMillis
|
||||||
|
|
||||||
|
// make the model aware of the lesson type
|
||||||
|
when (lesson.type) {
|
||||||
|
Lesson.TYPE_CANCELLED -> {
|
||||||
|
model.lessonCancelled = true
|
||||||
|
}
|
||||||
|
Lesson.TYPE_CHANGE,
|
||||||
|
Lesson.TYPE_SHIFTED_SOURCE,
|
||||||
|
Lesson.TYPE_SHIFTED_TARGET -> {
|
||||||
|
model.lessonChange = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add every event on this lesson
|
||||||
|
for (event in events) {
|
||||||
|
if (event.startTime != null && event.startTime != lesson.displayStartTime)
|
||||||
|
continue
|
||||||
|
model.eventColors.add(if (event.type == TYPE_HOMEWORK) ItemWidgetTimetableModel.EVENT_COLOR_HOMEWORK else event.getColor())
|
||||||
|
}
|
||||||
|
|
||||||
|
models += model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unified) {
|
||||||
|
// set the title for an unified widget
|
||||||
|
views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.widget_timetable_title_unified))
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableSubtitle, View.GONE)
|
||||||
|
} else {
|
||||||
|
// set the title to present the widget's profile
|
||||||
|
views.setTextViewText(R.id.widgetTimetableTitle, profileList[0].name)
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableTitle, View.VISIBLE)
|
||||||
|
// make the subtitle show current date for these lessons
|
||||||
|
displayingDate?.let {
|
||||||
|
when (Date.diffDays(it, Date.getToday())) {
|
||||||
|
0 -> views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.day_today_format, Week.getFullDayName(it.weekDay)))
|
||||||
|
1 -> views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.day_tomorrow_format, Week.getFullDayName(it.weekDay)))
|
||||||
|
else -> views.setTextViewText(R.id.widgetTimetableSubtitle, Week.getFullDayName(it.weekDay) + " " + it.formattedString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// intent running when the header is clicked
|
||||||
|
val openIntent = Intent(app, MainActivity::class.java)
|
||||||
|
openIntent.action = "android.intent.action.MAIN"
|
||||||
|
if (!unified) {
|
||||||
|
// per-profile widget should redirect to it + correct day
|
||||||
|
profileId?.let {
|
||||||
|
openIntent.putExtra("profileId", it)
|
||||||
|
}
|
||||||
|
displayingDate?.let {
|
||||||
|
openIntent.putExtra("timetableDate", it.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE)
|
||||||
|
val pendingOpenIntent = PendingIntent.getActivity(app, appWidgetId, openIntent, 0)
|
||||||
|
views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent)
|
||||||
|
|
||||||
|
if (lessonList.isEmpty()) {
|
||||||
|
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE)
|
||||||
|
views.setRemoteAdapter(R.id.widgetTimetableListView, Intent())
|
||||||
|
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
timetables!!.put(appWidgetId, models)
|
||||||
|
|
||||||
|
// apply the list service to the list view
|
||||||
|
val listIntent = Intent(app, WidgetTimetableService::class.java)
|
||||||
|
listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||||
|
listIntent.data = Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME))
|
||||||
|
views.setRemoteAdapter(R.id.widgetTimetableListView, listIntent)
|
||||||
|
|
||||||
|
// create an intent used to display the lesson details dialog
|
||||||
|
val intentTemplate = Intent(app, LessonDialogActivity::class.java)
|
||||||
|
intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||||
|
val pendingIntentTimetable = PendingIntent.getActivity(app, appWidgetId, intentTemplate, 0)
|
||||||
|
views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable)
|
||||||
|
|
||||||
|
if (!unified)
|
||||||
|
views.setScrollPosition(R.id.widgetTimetableListView, scrollPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEnabled(context: Context) {
|
||||||
|
// Enter relevant functionality for when the first widget is created
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
||||||
|
val app = context.applicationContext as App
|
||||||
|
for (appWidgetId in appWidgetIds) {
|
||||||
|
app.appConfig.widgetTimetableConfigs.remove(appWidgetId)
|
||||||
|
}
|
||||||
|
app.saveConfig("widgetTimetableConfigs")
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
|
||||||
|
val ACTION_SYNC_DATA = "ACTION_SYNC_DATA"
|
||||||
|
private val TAG = "WidgetTimetable"
|
||||||
|
private val modeInt = 0
|
||||||
|
|
||||||
|
var timetables: SparseArray<List<ItemWidgetTimetableModel>>? = null
|
||||||
|
|
||||||
|
fun getPendingSelfIntent(context: Context, action: String): PendingIntent {
|
||||||
|
val intent = Intent(context, WidgetTimetable::class.java)
|
||||||
|
intent.action = action
|
||||||
|
return getPendingSelfIntent(context, intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPendingSelfIntent(context: Context, intent: Intent): PendingIntent {
|
||||||
|
return PendingIntent.getBroadcast(context, 0, intent, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawableToBitmap(drawable: Drawable): Bitmap {
|
||||||
|
|
||||||
|
if (drawable is BitmapDrawable) {
|
||||||
|
return drawable.bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(bitmap)
|
||||||
|
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||||
|
drawable.draw(canvas)
|
||||||
|
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -60,6 +60,9 @@ class ApiService : Service() {
|
|||||||
|
|
||||||
private val notification by lazy { EdziennikNotification(this) }
|
private val notification by lazy { EdziennikNotification(this) }
|
||||||
|
|
||||||
|
private var lastEventTime = System.currentTimeMillis()
|
||||||
|
private var taskCancelTries = 0
|
||||||
|
|
||||||
/* ______ _ _ _ _ _____ _ _ _ _
|
/* ______ _ _ _ _ _____ _ _ _ _
|
||||||
| ____| | | (_) (_) | / ____| | | | | | |
|
| ____| | | (_) (_) | / ____| | | | | | |
|
||||||
| |__ __| |_____ ___ _ __ _ __ _| | __ | | __ _| | | |__ __ _ ___| | __
|
| |__ __| |_____ ___ _ __ _ __ _| | __ | | __ _| | | |__ __ _ ___| | __
|
||||||
@ -68,22 +71,17 @@ class ApiService : Service() {
|
|||||||
|______\__,_/___|_|\___|_| |_|_| |_|_|_|\_\ \_____\__,_|_|_|_.__/ \__,_|\___|_|\*/
|
|______\__,_/___|_|\___|_| |_|_| |_|_|_|\_\ \_____\__,_|_|_|_.__/ \__,_|\___|_|\*/
|
||||||
private val taskCallback = object : EdziennikCallback {
|
private val taskCallback = object : EdziennikCallback {
|
||||||
override fun onCompleted() {
|
override fun onCompleted() {
|
||||||
|
lastEventTime = System.currentTimeMillis()
|
||||||
d(TAG, "Task $taskRunningId (profile $taskProfileId) - $taskProgressText - finished")
|
d(TAG, "Task $taskRunningId (profile $taskProfileId) - $taskProgressText - finished")
|
||||||
//if (!taskCancelled) {
|
EventBus.getDefault().post(ApiTaskFinishedEvent(taskProfileId))
|
||||||
EventBus.getDefault().post(ApiTaskFinishedEvent(taskProfileId))
|
clearTask()
|
||||||
//}
|
|
||||||
taskIsRunning = false
|
|
||||||
taskRunningId = -1
|
|
||||||
taskRunning = null
|
|
||||||
taskProfileId = -1
|
|
||||||
taskProgress = -1f
|
|
||||||
taskProgressText = null
|
|
||||||
|
|
||||||
notification.setIdle().post()
|
notification.setIdle().post()
|
||||||
runTask()
|
runTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(apiError: ApiError) {
|
override fun onError(apiError: ApiError) {
|
||||||
|
lastEventTime = System.currentTimeMillis()
|
||||||
d(TAG, "Task $taskRunningId threw an error - $apiError")
|
d(TAG, "Task $taskRunningId threw an error - $apiError")
|
||||||
apiError.profileId = taskProfileId
|
apiError.profileId = taskProfileId
|
||||||
EventBus.getDefault().post(ApiTaskErrorEvent(apiError))
|
EventBus.getDefault().post(ApiTaskErrorEvent(apiError))
|
||||||
@ -92,9 +90,7 @@ class ApiService : Service() {
|
|||||||
if (apiError.isCritical) {
|
if (apiError.isCritical) {
|
||||||
taskRunning?.cancel()
|
taskRunning?.cancel()
|
||||||
notification.setCriticalError().post()
|
notification.setCriticalError().post()
|
||||||
taskRunning = null
|
clearTask()
|
||||||
taskIsRunning = false
|
|
||||||
taskRunningId = -1
|
|
||||||
runTask()
|
runTask()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -103,6 +99,7 @@ class ApiService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
override fun onProgress(step: Float) {
|
||||||
|
lastEventTime = System.currentTimeMillis()
|
||||||
if (step <= 0)
|
if (step <= 0)
|
||||||
return
|
return
|
||||||
if (taskProgress < 0)
|
if (taskProgress < 0)
|
||||||
@ -115,6 +112,7 @@ class ApiService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartProgress(stringRes: Int) {
|
override fun onStartProgress(stringRes: Int) {
|
||||||
|
lastEventTime = System.currentTimeMillis()
|
||||||
taskProgressText = getString(stringRes)
|
taskProgressText = getString(stringRes)
|
||||||
d(TAG, "Task $taskRunningId progress: $taskProgressText")
|
d(TAG, "Task $taskRunningId progress: $taskProgressText")
|
||||||
EventBus.getDefault().post(ApiTaskProgressEvent(taskProfileId, taskProgress, taskProgressText))
|
EventBus.getDefault().post(ApiTaskProgressEvent(taskProfileId, taskProgress, taskProgressText))
|
||||||
@ -129,6 +127,7 @@ class ApiService : Service() {
|
|||||||
| | (_| \__ \ < | __/> < __/ (__| |_| | |_| | (_) | | | |
|
| | (_| \__ \ < | __/> < __/ (__| |_| | |_| | (_) | | | |
|
||||||
|_|\__,_|___/_|\_\ \___/_/\_\___|\___|\__,_|\__|_|\___/|_| |*/
|
|_|\__,_|___/_|\_\ \___/_/\_\___|\___|\__,_|\__|_|\___/|_| |*/
|
||||||
private fun runTask() {
|
private fun runTask() {
|
||||||
|
checkIfTaskFrozen()
|
||||||
if (taskIsRunning)
|
if (taskIsRunning)
|
||||||
return
|
return
|
||||||
if (taskCancelled || serviceClosed || (taskQueue.isEmpty() && finishingTaskQueue.isEmpty())) {
|
if (taskCancelled || serviceClosed || (taskQueue.isEmpty() && finishingTaskQueue.isEmpty())) {
|
||||||
@ -137,6 +136,8 @@ class ApiService : Service() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastEventTime = System.currentTimeMillis()
|
||||||
|
|
||||||
val task = if (taskQueue.isEmpty()) finishingTaskQueue.removeAt(0) else taskQueue.removeAt(0)
|
val task = if (taskQueue.isEmpty()) finishingTaskQueue.removeAt(0) else taskQueue.removeAt(0)
|
||||||
task.taskId = ++taskMaximumId
|
task.taskId = ++taskMaximumId
|
||||||
task.prepare(app)
|
task.prepare(app)
|
||||||
@ -166,6 +167,48 @@ class ApiService : Service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a task is inactive for more than 30 seconds.
|
||||||
|
* If the user tries to cancel a task with no success at least three times,
|
||||||
|
* consider it frozen as well.
|
||||||
|
*
|
||||||
|
* This usually means it is broken and won't become active again.
|
||||||
|
* This method cancels the task and removes any pointers to it.
|
||||||
|
*/
|
||||||
|
private fun checkIfTaskFrozen(): Boolean {
|
||||||
|
if (System.currentTimeMillis() - lastEventTime > 30*1000
|
||||||
|
|| taskCancelTries >= 3) {
|
||||||
|
val time = System.currentTimeMillis() - lastEventTime
|
||||||
|
d(TAG, "!!! Task $taskRunningId froze for $time ms. $taskRunning")
|
||||||
|
clearTask()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the service if the current task is frozen/broken.
|
||||||
|
*/
|
||||||
|
private fun stopIfTaskFrozen() {
|
||||||
|
if (checkIfTaskFrozen()) {
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove any task descriptors or pointers from the service.
|
||||||
|
*/
|
||||||
|
private fun clearTask() {
|
||||||
|
taskIsRunning = false
|
||||||
|
taskRunningId = -1
|
||||||
|
taskRunning = null
|
||||||
|
taskProfileId = -1
|
||||||
|
taskProgress = -1f
|
||||||
|
taskProgressText = null
|
||||||
|
taskCancelled = false
|
||||||
|
taskCancelTries = 0
|
||||||
|
}
|
||||||
|
|
||||||
private fun allCompleted() {
|
private fun allCompleted() {
|
||||||
EventBus.getDefault().post(ApiTaskAllFinishedEvent())
|
EventBus.getDefault().post(ApiTaskAllFinishedEvent())
|
||||||
stopSelf()
|
stopSelf()
|
||||||
@ -211,8 +254,10 @@ class ApiService : Service() {
|
|||||||
EventBus.getDefault().removeStickyEvent(request)
|
EventBus.getDefault().removeStickyEvent(request)
|
||||||
d(TAG, request.toString())
|
d(TAG, request.toString())
|
||||||
|
|
||||||
|
taskCancelTries++
|
||||||
taskCancelled = true
|
taskCancelled = true
|
||||||
taskRunning?.cancel()
|
taskRunning?.cancel()
|
||||||
|
stopIfTaskFrozen()
|
||||||
}
|
}
|
||||||
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
|
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
|
||||||
fun onServiceCloseRequest(request: ServiceCloseRequest) {
|
fun onServiceCloseRequest(request: ServiceCloseRequest) {
|
||||||
|
@ -14,6 +14,14 @@ val SYSTEM_USER_AGENT = System.getProperty("http.agent") ?: "Dalvik/2.1.0 Androi
|
|||||||
|
|
||||||
val SERVER_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME} $SYSTEM_USER_AGENT"
|
val SERVER_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME} $SYSTEM_USER_AGENT"
|
||||||
|
|
||||||
|
const val FAKE_LIBRUS_API = "http://librus.szkolny.eu/api"
|
||||||
|
const val FAKE_LIBRUS_PORTAL = "http://librus.szkolny.eu"
|
||||||
|
const val FAKE_LIBRUS_AUTHORIZE = "http://librus.szkolny.eu/authorize.php"
|
||||||
|
const val FAKE_LIBRUS_LOGIN = "http://librus.szkolny.eu/login_action.php"
|
||||||
|
const val FAKE_LIBRUS_TOKEN = "http://librus.szkolny.eu/access_token.php"
|
||||||
|
const val FAKE_LIBRUS_ACCOUNT = "/synergia_accounts_fresh.php?login="
|
||||||
|
const val FAKE_LIBRUS_ACCOUNTS = "/synergia_accounts.php"
|
||||||
|
|
||||||
val LIBRUS_USER_AGENT = "$SYSTEM_USER_AGENT LibrusMobileApp"
|
val LIBRUS_USER_AGENT = "$SYSTEM_USER_AGENT LibrusMobileApp"
|
||||||
const val SYNERGIA_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/62.0"
|
const val SYNERGIA_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/62.0"
|
||||||
const val LIBRUS_CLIENT_ID = "wmSyUMo8llDAs4y9tJVYY92oyZ6h4lAt7KCuy0Gv"
|
const val LIBRUS_CLIENT_ID = "wmSyUMo8llDAs4y9tJVYY92oyZ6h4lAt7KCuy0Gv"
|
||||||
@ -56,6 +64,7 @@ const val IDZIENNIK_WEB_TIMETABLE = "mod_panelRodzica/plan/WS_Plan.asmx/pobierzP
|
|||||||
const val IDZIENNIK_WEB_GRADES = "mod_panelRodzica/oceny/WS_ocenyUcznia.asmx/pobierzOcenyUcznia"
|
const val IDZIENNIK_WEB_GRADES = "mod_panelRodzica/oceny/WS_ocenyUcznia.asmx/pobierzOcenyUcznia"
|
||||||
const val IDZIENNIK_WEB_MISSING_GRADES = "mod_panelRodzica/brak_ocen/WS_BrakOcenUcznia.asmx/pobierzBrakujaceOcenyUcznia"
|
const val IDZIENNIK_WEB_MISSING_GRADES = "mod_panelRodzica/brak_ocen/WS_BrakOcenUcznia.asmx/pobierzBrakujaceOcenyUcznia"
|
||||||
const val IDZIENNIK_WEB_EXAMS = "mod_panelRodzica/sprawdziany/mod_sprawdzianyPanel.asmx/pobierzListe"
|
const val IDZIENNIK_WEB_EXAMS = "mod_panelRodzica/sprawdziany/mod_sprawdzianyPanel.asmx/pobierzListe"
|
||||||
|
const val IDZIENNIK_WEB_HOMEWORK = "mod_panelRodzica/pracaDomowa/WS_pracaDomowa.asmx/pobierzPraceDomowe"
|
||||||
const val IDZIENNIK_WEB_NOTICES = "mod_panelRodzica/uwagi/WS_uwagiUcznia.asmx/pobierzUwagiUcznia"
|
const val IDZIENNIK_WEB_NOTICES = "mod_panelRodzica/uwagi/WS_uwagiUcznia.asmx/pobierzUwagiUcznia"
|
||||||
const val IDZIENNIK_WEB_ATTENDANCE = "mod_panelRodzica/obecnosci/WS_obecnosciUcznia.asmx/pobierzObecnosciUcznia"
|
const val IDZIENNIK_WEB_ATTENDANCE = "mod_panelRodzica/obecnosci/WS_obecnosciUcznia.asmx/pobierzObecnosciUcznia"
|
||||||
const val IDZIENNIK_WEB_ANNOUNCEMENTS = "mod_panelRodzica/tabOgl/WS_tablicaOgloszen.asmx/GetOgloszenia"
|
const val IDZIENNIK_WEB_ANNOUNCEMENTS = "mod_panelRodzica/tabOgl/WS_tablicaOgloszen.asmx/GetOgloszenia"
|
||||||
|
@ -45,8 +45,8 @@ class DataNotifications(val data: Data) {
|
|||||||
return@run
|
return@run
|
||||||
}
|
}
|
||||||
|
|
||||||
for (change in app.db.lessonChangeDao().getNotNotifiedNow(profileId)) {
|
for (lesson in app.db.timetableDao().getNotNotifiedNow(profileId)) {
|
||||||
val text = app.getString(R.string.notification_lesson_change_format, change.changeTypeStr(app), if (change.lessonDate == null) "" else change.lessonDate!!.formattedString, change.subjectLongName)
|
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(
|
data.notifications += Notification(
|
||||||
title = app.getNotificationTitle(TYPE_TIMETABLE_LESSON_CHANGE),
|
title = app.getNotificationTitle(TYPE_TIMETABLE_LESSON_CHANGE),
|
||||||
text = text,
|
text = text,
|
||||||
@ -54,8 +54,8 @@ class DataNotifications(val data: Data) {
|
|||||||
profileId = profileId,
|
profileId = profileId,
|
||||||
profileName = profileName,
|
profileName = profileName,
|
||||||
viewId = DRAWER_ITEM_TIMETABLE,
|
viewId = DRAWER_ITEM_TIMETABLE,
|
||||||
addedDate = change.addedDate
|
addedDate = lesson.addedDate
|
||||||
).addExtra("timetableDate", change.lessonDate?.value?.toLong())
|
).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
for (event in app.db.eventDao().getNotNotifiedNow(profileId)) {
|
for (event in app.db.eventDao().getNotNotifiedNow(profileId)) {
|
||||||
@ -186,10 +186,10 @@ class DataNotifications(val data: Data) {
|
|||||||
val luckyNumbers = app.db.luckyNumberDao().getNotNotifiedNow(profileId)
|
val luckyNumbers = app.db.luckyNumberDao().getNotNotifiedNow(profileId)
|
||||||
luckyNumbers?.removeAll { it.date < today }
|
luckyNumbers?.removeAll { it.date < today }
|
||||||
luckyNumbers?.forEach { luckyNumber ->
|
luckyNumbers?.forEach { luckyNumber ->
|
||||||
val text = when {
|
val text = when (luckyNumber.date.value) {
|
||||||
luckyNumber.date.value == todayValue -> // LN for today
|
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)
|
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)
|
||||||
luckyNumber.date.value == todayValue + 1 -> // LN for tomorrow
|
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)
|
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
|
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)
|
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)
|
||||||
@ -207,4 +207,4 @@ class DataNotifications(val data: Data) {
|
|||||||
|
|
||||||
data.db.metadataDao().setAllNotified(profileId, true)
|
data.db.metadataDao().setAllNotified(profileId, true)
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -39,13 +39,16 @@ const val ERROR_REQUEST_HTTP_404 = 54
|
|||||||
const val ERROR_REQUEST_HTTP_405 = 55
|
const val ERROR_REQUEST_HTTP_405 = 55
|
||||||
const val ERROR_REQUEST_HTTP_410 = 56
|
const val ERROR_REQUEST_HTTP_410 = 56
|
||||||
const val ERROR_REQUEST_HTTP_500 = 57
|
const val ERROR_REQUEST_HTTP_500 = 57
|
||||||
|
const val ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND = 60
|
||||||
|
const val ERROR_REQUEST_FAILURE_TIMEOUT = 61
|
||||||
|
const val ERROR_REQUEST_FAILURE_NO_INTERNET = 62
|
||||||
const val ERROR_RESPONSE_EMPTY = 100
|
const val ERROR_RESPONSE_EMPTY = 100
|
||||||
const val ERROR_LOGIN_DATA_MISSING = 101
|
const val ERROR_LOGIN_DATA_MISSING = 101
|
||||||
const val ERROR_LOGIN_DATA_INVALID = 102
|
|
||||||
const val ERROR_PROFILE_MISSING = 105
|
const val ERROR_PROFILE_MISSING = 105
|
||||||
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
|
||||||
|
const val ERROR_FILE_DOWNLOAD = 113
|
||||||
|
|
||||||
const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
|
const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
|
||||||
|
|
||||||
@ -99,6 +102,13 @@ const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID = 172
|
|||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED = 173
|
const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED = 173
|
||||||
const val ERROR_LIBRUS_SYNERGIA_OTHER = 174
|
const val ERROR_LIBRUS_SYNERGIA_OTHER = 174
|
||||||
const val ERROR_LIBRUS_SYNERGIA_MAINTENANCE = 175
|
const val ERROR_LIBRUS_SYNERGIA_MAINTENANCE = 175
|
||||||
|
const val ERROR_LIBRUS_MESSAGES_MAINTENANCE = 176
|
||||||
|
const val ERROR_LIBRUS_MESSAGES_ERROR = 177
|
||||||
|
const val ERROR_LIBRUS_MESSAGES_OTHER = 178
|
||||||
|
const val ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN = 179
|
||||||
|
const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN = 180
|
||||||
|
const val ERROR_LIBRUS_API_MAINTENANCE = 181
|
||||||
|
const val ERROR_LIBRUS_PORTAL_MAINTENANCE = 182
|
||||||
|
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
||||||
@ -109,7 +119,7 @@ const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS = 206
|
|||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OTHER = 210
|
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OTHER = 210
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED = 211
|
const val ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED = 211
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY = 212
|
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY = 212
|
||||||
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE = 212
|
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
|
||||||
@ -158,8 +168,12 @@ const val EXCEPTION_LIBRUS_API_REQUEST = 904
|
|||||||
const val EXCEPTION_LIBRUS_SYNERGIA_REQUEST = 905
|
const val EXCEPTION_LIBRUS_SYNERGIA_REQUEST = 905
|
||||||
const val EXCEPTION_MOBIDZIENNIK_WEB_REQUEST = 906
|
const val EXCEPTION_MOBIDZIENNIK_WEB_REQUEST = 906
|
||||||
const val EXCEPTION_VULCAN_API_REQUEST = 907
|
const val EXCEPTION_VULCAN_API_REQUEST = 907
|
||||||
|
const val EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST = 908
|
||||||
|
const val EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST = 909
|
||||||
const val EXCEPTION_NOTIFY_AND_SYNC = 910
|
const val EXCEPTION_NOTIFY_AND_SYNC = 910
|
||||||
const val EXCEPTION_LIBRUS_MESSAGES_REQUEST = 911
|
const val EXCEPTION_LIBRUS_MESSAGES_REQUEST = 911
|
||||||
const val EXCEPTION_IDZIENNIK_WEB_REQUEST = 912
|
const val EXCEPTION_IDZIENNIK_WEB_REQUEST = 912
|
||||||
const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
|
const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
|
||||||
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
||||||
|
|
||||||
|
const val LOGIN_NO_ARGUMENTS = 1201
|
||||||
|
@ -7,39 +7,36 @@ package pl.szczodrzynski.edziennik.api.v2
|
|||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
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_ANNOUNCEMENTS
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE
|
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_GRADES
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOME
|
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_HOMEWORK
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||||
|
|
||||||
const val FEATURE_ALL = 0
|
internal const val FEATURE_TIMETABLE = 1
|
||||||
const val FEATURE_TIMETABLE = 1
|
internal const val FEATURE_AGENDA = 2
|
||||||
const val FEATURE_AGENDA = 2
|
internal const val FEATURE_GRADES = 3
|
||||||
const val FEATURE_GRADES = 3
|
internal const val FEATURE_HOMEWORK = 4
|
||||||
const val FEATURE_HOMEWORK = 4
|
internal const val FEATURE_BEHAVIOUR = 5
|
||||||
const val FEATURE_BEHAVIOUR = 5
|
internal const val FEATURE_ATTENDANCE = 6
|
||||||
const val FEATURE_ATTENDANCE = 6
|
internal const val FEATURE_MESSAGES_INBOX = 7
|
||||||
const val FEATURE_MESSAGES_INBOX = 7
|
internal const val FEATURE_MESSAGES_SENT = 8
|
||||||
const val FEATURE_MESSAGES_SENT = 8
|
internal const val FEATURE_ANNOUNCEMENTS = 9
|
||||||
const val FEATURE_ANNOUNCEMENTS = 9
|
|
||||||
|
|
||||||
const val FEATURE_ALWAYS_NEEDED = 100
|
internal const val FEATURE_ALWAYS_NEEDED = 100
|
||||||
const val FEATURE_STUDENT_INFO = 101
|
internal const val FEATURE_STUDENT_INFO = 101
|
||||||
const val FEATURE_STUDENT_NUMBER = 109
|
internal const val FEATURE_STUDENT_NUMBER = 109
|
||||||
const val FEATURE_SCHOOL_INFO = 102
|
internal const val FEATURE_SCHOOL_INFO = 102
|
||||||
const val FEATURE_CLASS_INFO = 103
|
internal const val FEATURE_CLASS_INFO = 103
|
||||||
const val FEATURE_TEAM_INFO = 104
|
internal const val FEATURE_TEAM_INFO = 104
|
||||||
const val FEATURE_LUCKY_NUMBER = 105
|
internal const val FEATURE_LUCKY_NUMBER = 105
|
||||||
const val FEATURE_TEACHERS = 106
|
internal const val FEATURE_TEACHERS = 106
|
||||||
const val FEATURE_SUBJECTS = 107
|
internal const val FEATURE_SUBJECTS = 107
|
||||||
const val FEATURE_CLASSROOMS = 108
|
internal const val FEATURE_CLASSROOMS = 108
|
||||||
const val FEATURE_PUSH_CONFIG = 120
|
internal const val FEATURE_PUSH_CONFIG = 120
|
||||||
|
|
||||||
const val FEATURE_MESSAGE_GET = 201
|
|
||||||
|
|
||||||
object Features {
|
object Features {
|
||||||
private fun getAllNecessary(): List<Int> = listOf(
|
private fun getAllNecessary(): List<Int> = listOf(
|
||||||
|
@ -66,13 +66,13 @@ val librusLoginMethods = listOf(
|
|||||||
},
|
},
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_SYNERGIA, LibrusLoginSynergia::class.java)
|
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_SYNERGIA, LibrusLoginSynergia::class.java)
|
||||||
.withIsPossible { _, _ -> true }
|
.withIsPossible { _, loginStore -> !loginStore.hasLoginData("fakeLogin") }
|
||||||
.withRequiredLoginMethod { profile, _ ->
|
.withRequiredLoginMethod { profile, _ ->
|
||||||
if (profile?.hasStudentData("accountPassword") == false) LOGIN_METHOD_LIBRUS_API else LOGIN_METHOD_NOT_NEEDED
|
if (profile?.hasStudentData("accountPassword") == false) LOGIN_METHOD_LIBRUS_API else LOGIN_METHOD_NOT_NEEDED
|
||||||
},
|
},
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_MESSAGES, LibrusLoginMessages::class.java)
|
LoginMethod(LOGIN_TYPE_LIBRUS, LOGIN_METHOD_LIBRUS_MESSAGES, LibrusLoginMessages::class.java)
|
||||||
.withIsPossible { _, _ -> true }
|
.withIsPossible { _, loginStore -> !loginStore.hasLoginData("fakeLogin") }
|
||||||
.withRequiredLoginMethod { profile, _ ->
|
.withRequiredLoginMethod { profile, _ ->
|
||||||
if (profile?.hasStudentData("accountPassword") == false) LOGIN_METHOD_LIBRUS_SYNERGIA else LOGIN_METHOD_NOT_NEEDED
|
if (profile?.hasStudentData("accountPassword") == false) LOGIN_METHOD_LIBRUS_SYNERGIA else LOGIN_METHOD_NOT_NEEDED
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ object Regexes {
|
|||||||
"""Liczona do średniej:.*?<strong>nie<br/?></strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
"""Liczona do średniej:.*?<strong>nie<br/?></strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
val MOBIDZIENNIK_GRADES_DETAILS by lazy {
|
val MOBIDZIENNIK_GRADES_DETAILS by lazy {
|
||||||
"""<strong.*?>(.+?)</strong>.*?<sup>.+?</sup>.*?<small>\((.+?)\)</small>.*?<span>.*?Wartość oceny:.*?<strong>([0-9.]+)</strong>.*?Wpisał\(a\):.*?<strong>(.+?)</strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
"""<strong.*?>(.+?)</strong>.*?<sup>.+?</sup>.*?(?:<small>\((.+?)\)</small>.*?)?<span>.*?Wartość oceny:.*?<strong>([0-9.]+)</strong>.*?Wpisał\(a\):.*?<strong>(.+?)</strong>.*?(?:Komentarz:.*?<strong>(.+?)</strong>)?</span>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val MOBIDZIENNIK_EVENT_TYPE by lazy {
|
val MOBIDZIENNIK_EVENT_TYPE by lazy {
|
||||||
@ -37,6 +37,16 @@ object Regexes {
|
|||||||
"""events: (.+),$""".toRegex(RegexOption.MULTILINE)
|
"""events: (.+),$""".toRegex(RegexOption.MULTILINE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val MOBIDZIENNIK_MESSAGE_READ_DATE by lazy {
|
||||||
|
"""czas przeczytania:.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
|
}
|
||||||
|
val MOBIDZIENNIK_MESSAGE_SENT_READ_DATE by lazy {
|
||||||
|
""".+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
|
}
|
||||||
|
val MOBIDZIENNIK_MESSAGE_ATTACHMENT by lazy {
|
||||||
|
"""href="https://.+?\.mobidziennik.pl/.+?&(?:amp;)?zalacznik=([0-9]+)"(?:.+?<small.+?\(([0-9.]+)\s(M|K|G|)B\))*""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
||||||
@ -60,4 +70,16 @@ object Regexes {
|
|||||||
val IDZIENNIK_LOGIN_FIRST_STUDENT by lazy {
|
val IDZIENNIK_LOGIN_FIRST_STUDENT by lazy {
|
||||||
"""<option.*?value="([0-9]+)"\sdata-id-ucznia="([A-z0-9]+?)".*?>(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)</option>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
"""<option.*?value="([0-9]+)"\sdata-id-ucznia="([A-z0-9]+?)".*?>(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)</option>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val VULCAN_SHITFT_ANNOTATION by lazy {
|
||||||
|
"""\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val LIBRUS_ATTACHMENT_KEY by lazy {
|
||||||
|
"""singleUseKey=([0-9A-f_]+)""".toRegex()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
|||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
|
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.AppError.CODE_APP_SERVER_ERROR
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
||||||
import pl.szczodrzynski.edziennik.data.api.AppError.CODE_APP_SERVER_ERROR
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
@ -176,4 +176,4 @@ class ServerSync(val data: Data, val onSuccess: () -> Unit) {
|
|||||||
|
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-24
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.events
|
||||||
|
|
||||||
|
data class AttachmentGetEvent(val profileId: Int, val messageId: Long, val attachmentId: Long,
|
||||||
|
var eventType: Int = TYPE_PROGRESS, val fileName: String? = null,
|
||||||
|
val bytesWritten: Long = 0) {
|
||||||
|
companion object {
|
||||||
|
const val TYPE_PROGRESS = 0
|
||||||
|
const val TYPE_FINISHED = 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.events
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
|
|
||||||
|
data class MessageGetEvent(val message: MessageFull)
|
@ -1,5 +1,6 @@
|
|||||||
package pl.szczodrzynski.edziennik.api.v2.events.task
|
package pl.szczodrzynski.edziennik.api.v2.events.task
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
@ -11,6 +12,8 @@ import pl.szczodrzynski.edziennik.api.v2.mobidziennik.Mobidziennik
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.template.Template
|
import pl.szczodrzynski.edziennik.api.v2.template.Template
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.Vulcan
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.Vulcan
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
|
|
||||||
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 {
|
||||||
@ -18,10 +21,11 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
|||||||
|
|
||||||
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
|
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
|
||||||
fun sync() = EdziennikTask(-1, SyncRequest())
|
fun sync() = EdziennikTask(-1, SyncRequest())
|
||||||
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds))
|
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, arguments))
|
||||||
fun syncProfileList(profileList: List<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList))
|
fun syncProfileList(profileList: List<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList))
|
||||||
fun messageGet(profileId: Int, messageId: Int) = EdziennikTask(profileId, MessageGetRequest(messageId))
|
fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message))
|
||||||
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
|
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
|
||||||
|
fun attachmentGet(profileId: Int, message: Message, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(message, attachmentId, attachmentName))
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var loginStore: LoginStore
|
private lateinit var loginStore: LoginStore
|
||||||
@ -33,12 +37,11 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
|||||||
loginStore = request.loginStore
|
loginStore = request.loginStore
|
||||||
// save the profile ID and name as the current task's
|
// save the profile ID and name as the current task's
|
||||||
taskName = app.getString(R.string.edziennik_notification_api_first_login_title)
|
taskName = app.getString(R.string.edziennik_notification_api_first_login_title)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// get the requested profile and login store
|
// get the requested profile and login store
|
||||||
val profile = app.db.profileDao().getByIdNow(profileId)
|
val profile = app.db.profileDao().getByIdNow(profileId)
|
||||||
this.profile = profile
|
this.profile = profile
|
||||||
if (profile == null || !profile.syncEnabled) {
|
if (profile == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return
|
val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return
|
||||||
@ -50,7 +53,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
|||||||
|
|
||||||
private var edziennikInterface: EdziennikInterface? = null
|
private var edziennikInterface: EdziennikInterface? = null
|
||||||
|
|
||||||
fun run(app: App, taskCallback: EdziennikCallback) {
|
internal fun run(app: App, taskCallback: EdziennikCallback) {
|
||||||
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)
|
||||||
@ -65,11 +68,14 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
|||||||
|
|
||||||
when (request) {
|
when (request) {
|
||||||
is SyncProfileRequest -> edziennikInterface?.sync(
|
is SyncProfileRequest -> edziennikInterface?.sync(
|
||||||
featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) } ?: Features.getAllIds(),
|
featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) }
|
||||||
viewId = request.viewIds?.get(0)?.first)
|
?: Features.getAllIds(),
|
||||||
is MessageGetRequest -> edziennikInterface?.getMessage(request.messageId)
|
viewId = request.viewIds?.get(0)?.first,
|
||||||
|
arguments = request.arguments)
|
||||||
|
is MessageGetRequest -> edziennikInterface?.getMessage(request.message)
|
||||||
is FirstLoginRequest -> edziennikInterface?.firstLogin()
|
is FirstLoginRequest -> edziennikInterface?.firstLogin()
|
||||||
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
|
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
|
||||||
|
is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.message, request.attachmentId, request.attachmentName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,8 +89,9 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
|||||||
|
|
||||||
data class FirstLoginRequest(val loginStore: LoginStore)
|
data class FirstLoginRequest(val loginStore: LoginStore)
|
||||||
class SyncRequest
|
class SyncRequest
|
||||||
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null)
|
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null, val arguments: JsonObject? = null)
|
||||||
data class SyncProfileListRequest(val profileList: List<Int>)
|
data class SyncProfileListRequest(val profileList: List<Int>)
|
||||||
data class MessageGetRequest(val messageId: Int)
|
data class MessageGetRequest(val message: MessageFull)
|
||||||
class AnnouncementsReadRequest
|
class AnnouncementsReadRequest
|
||||||
}
|
data class AttachmentGetRequest(val message: Message, val attachmentId: Long, val attachmentName: String)
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.MainActivity
|
|||||||
import pl.szczodrzynski.edziennik.Notifier.ID_NOTIFICATIONS
|
import pl.szczodrzynski.edziennik.Notifier.ID_NOTIFICATIONS
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.notification.getNotificationTitle
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Notification
|
import pl.szczodrzynski.edziennik.utils.models.Notification
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@ -33,9 +34,9 @@ class NotifyTask : IApiTask(-1) {
|
|||||||
val pendingIntent = PendingIntent.getActivity(app, notification.id, intent, 0)
|
val pendingIntent = PendingIntent.getActivity(app, notification.id, intent, 0)
|
||||||
val notificationBuilder = NotificationCompat.Builder(app, app.notifier.notificationGroup)
|
val notificationBuilder = NotificationCompat.Builder(app, app.notifier.notificationGroup)
|
||||||
// title, text, type, date
|
// title, text, type, date
|
||||||
.setContentTitle(notification.title)
|
.setContentTitle(notification.profileName)
|
||||||
.setContentText(notification.text)
|
.setContentText(notification.text)
|
||||||
.setSubText(Notification.stringType(app, notification.type))
|
.setSubText(app.getNotificationTitle(notification.type))
|
||||||
.setWhen(notification.addedDate)
|
.setWhen(notification.addedDate)
|
||||||
.setTicker(app.getString(R.string.notification_ticker_format, Notification.stringType(app, notification.type)))
|
.setTicker(app.getString(R.string.notification_ticker_format, Notification.stringType(app, notification.type)))
|
||||||
// icon, color, lights, priority
|
// icon, color, lights, priority
|
||||||
|
@ -138,10 +138,12 @@ class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(
|
|||||||
val teacher = teacherList.singleOrNull { it.fullName == "$firstName $lastName" }
|
val teacher = teacherList.singleOrNull { it.fullName == "$firstName $lastName" }
|
||||||
return validateTeacher(teacher, firstName, lastName)
|
return validateTeacher(teacher, firstName, lastName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTeacher(firstNameChar: Char, lastName: String): Teacher {
|
fun getTeacher(firstNameChar: Char, lastName: String): Teacher {
|
||||||
val teacher = teacherList.singleOrNull { it.shortName == "$firstNameChar.$lastName" }
|
val teacher = teacherList.singleOrNull { it.shortName == "$firstNameChar.$lastName" }
|
||||||
return validateTeacher(teacher, firstNameChar.toString(), lastName)
|
return validateTeacher(teacher, firstNameChar.toString(), lastName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTeacherByLastFirst(nameLastFirst: String): Teacher {
|
fun getTeacherByLastFirst(nameLastFirst: String): Teacher {
|
||||||
val nameParts = nameLastFirst.split(" ")
|
val nameParts = nameLastFirst.split(" ")
|
||||||
return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[1], nameParts[0])
|
return if (nameParts.size == 1) getTeacher(nameParts[0], "") else getTeacher(nameParts[1], nameParts[0])
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.idziennik
|
package pl.szczodrzynski.edziennik.api.v2.idziennik
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikData
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikData
|
||||||
@ -15,6 +16,8 @@ import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.prepare
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
@ -48,7 +51,8 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||||
|
data.arguments = arguments
|
||||||
data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId)
|
data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId)
|
||||||
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
@ -59,7 +63,7 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(messageId: Int) {
|
override fun getMessage(message: MessageFull) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +71,10 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun firstLogin() {
|
override fun firstLogin() {
|
||||||
IdziennikFirstLogin(data) {
|
IdziennikFirstLogin(data) {
|
||||||
completed()
|
completed()
|
||||||
|
@ -11,6 +11,7 @@ const val ENDPOINT_IDZIENNIK_WEB_TIMETABLE = 1030
|
|||||||
const val ENDPOINT_IDZIENNIK_WEB_GRADES = 1040
|
const val ENDPOINT_IDZIENNIK_WEB_GRADES = 1040
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES = 1050
|
const val ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES = 1050
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_EXAMS = 1060
|
const val ENDPOINT_IDZIENNIK_WEB_EXAMS = 1060
|
||||||
|
const val ENDPOINT_IDZIENNIK_WEB_HOMEWORK = 1061
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_NOTICES = 1070
|
const val ENDPOINT_IDZIENNIK_WEB_NOTICES = 1070
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS = 1080
|
const val ENDPOINT_IDZIENNIK_WEB_ANNOUNCEMENTS = 1080
|
||||||
const val ENDPOINT_IDZIENNIK_WEB_ATTENDANCE = 1090
|
const val ENDPOINT_IDZIENNIK_WEB_ATTENDANCE = 1090
|
||||||
@ -34,6 +35,10 @@ val IdziennikFeatures = listOf(
|
|||||||
ENDPOINT_IDZIENNIK_WEB_EXAMS to LOGIN_METHOD_IDZIENNIK_WEB
|
ENDPOINT_IDZIENNIK_WEB_EXAMS to LOGIN_METHOD_IDZIENNIK_WEB
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
||||||
|
|
||||||
|
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_HOMEWORK, listOf(
|
||||||
|
ENDPOINT_IDZIENNIK_WEB_HOMEWORK to LOGIN_METHOD_IDZIENNIK_WEB
|
||||||
|
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_BEHAVIOUR, listOf(
|
Feature(LOGIN_TYPE_IDZIENNIK, FEATURE_BEHAVIOUR, listOf(
|
||||||
ENDPOINT_IDZIENNIK_WEB_NOTICES to LOGIN_METHOD_IDZIENNIK_WEB
|
ENDPOINT_IDZIENNIK_WEB_NOTICES to LOGIN_METHOD_IDZIENNIK_WEB
|
||||||
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
), listOf(LOGIN_METHOD_IDZIENNIK_WEB)),
|
||||||
|
@ -55,6 +55,10 @@ class IdziennikData(val data: DataIdziennik, val onSuccess: () -> Unit) {
|
|||||||
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
||||||
IdziennikWebExams(data, onSuccess)
|
IdziennikWebExams(data, onSuccess)
|
||||||
}
|
}
|
||||||
|
ENDPOINT_IDZIENNIK_WEB_HOMEWORK -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
||||||
|
IdziennikWebHomework(data, onSuccess)
|
||||||
|
}
|
||||||
ENDPOINT_IDZIENNIK_WEB_NOTICES -> {
|
ENDPOINT_IDZIENNIK_WEB_NOTICES -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
data.startProgress(R.string.edziennik_progress_endpoint_notices)
|
||||||
IdziennikWebNotices(data, onSuccess)
|
IdziennikWebNotices(data, onSuccess)
|
||||||
|
@ -94,6 +94,7 @@ open class IdziennikWeb(open val data: DataIdziennik) {
|
|||||||
is Long -> json.addProperty(name, value)
|
is Long -> json.addProperty(name, value)
|
||||||
is Float -> json.addProperty(name, value)
|
is Float -> json.addProperty(name, value)
|
||||||
is Char -> json.addProperty(name, value)
|
is Char -> json.addProperty(name, value)
|
||||||
|
is Boolean -> json.addProperty(name, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setJsonBody(json)
|
setJsonBody(json)
|
||||||
|
@ -75,7 +75,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
|||||||
/*messageId*/ messageId
|
/*messageId*/ messageId
|
||||||
)
|
)
|
||||||
|
|
||||||
data.messageList.add(message)
|
data.messageIgnoreList.add(message)
|
||||||
data.messageRecipientList.add(messageRecipient)
|
data.messageRecipientList.add(messageRecipient)
|
||||||
data.messageMetadataList.add(Metadata(
|
data.messageMetadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
|
@ -74,7 +74,7 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
|
|||||||
data.messageRecipientIgnoreList.add(messageRecipient)
|
data.messageRecipientIgnoreList.add(messageRecipient)
|
||||||
}
|
}
|
||||||
|
|
||||||
data.messageList.add(message)
|
data.messageIgnoreList.add(message)
|
||||||
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
|
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,21 +5,21 @@
|
|||||||
package pl.szczodrzynski.edziennik.api.v2.idziennik.data.web
|
package pl.szczodrzynski.edziennik.api.v2.idziennik.data.web
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
import pl.szczodrzynski.edziennik.api.v2.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
||||||
import pl.szczodrzynski.edziennik.api.v2.IDZIENNIK_WEB_EXAMS
|
import pl.szczodrzynski.edziennik.api.v2.IDZIENNIK_WEB_EXAMS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.DataIdziennik
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.DataIdziennik
|
||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_EXAMS
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_EXAMS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.Lesson
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class IdziennikWebExams(override val data: DataIdziennik,
|
class IdziennikWebExams(override val data: DataIdziennik,
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "IdziennikWebExams"
|
private const val TAG = "IdziennikWebExams"
|
||||||
}
|
}
|
||||||
@ -34,14 +34,15 @@ class IdziennikWebExams(override val data: DataIdziennik,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getExams() {
|
private fun getExams() {
|
||||||
val param = JsonObject()
|
val param = JsonObject().apply {
|
||||||
param.addProperty("strona", 1)
|
addProperty("strona", 1)
|
||||||
param.addProperty("iloscNaStrone", "99")
|
addProperty("iloscNaStrone", "99")
|
||||||
param.addProperty("iloscRekordow", -1)
|
addProperty("iloscRekordow", -1)
|
||||||
param.addProperty("kolumnaSort", "ss.Nazwa,sp.Data_sprawdzianu")
|
addProperty("kolumnaSort", "ss.Nazwa,sp.Data_sprawdzianu")
|
||||||
param.addProperty("kierunekSort", 0)
|
addProperty("kierunekSort", 0)
|
||||||
param.addProperty("maxIloscZaznaczonych", 0)
|
addProperty("maxIloscZaznaczonych", 0)
|
||||||
param.addProperty("panelFiltrow", 0)
|
addProperty("panelFiltrow", 0)
|
||||||
|
}
|
||||||
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_EXAMS, mapOf(
|
webApiGet(TAG, IDZIENNIK_WEB_EXAMS, mapOf(
|
||||||
"idP" to data.registerId,
|
"idP" to data.registerId,
|
||||||
@ -55,28 +56,34 @@ class IdziennikWebExams(override val data: DataIdziennik,
|
|||||||
return@webApiGet
|
return@webApiGet
|
||||||
}
|
}
|
||||||
|
|
||||||
for (jExamEl in json.getAsJsonArray("ListK")) {
|
json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { exam ->
|
||||||
val jExam = jExamEl.asJsonObject
|
val id = exam.getLong("_recordId") ?: return@forEach
|
||||||
// jExam
|
val examDate = Date.fromY_m_d(exam.getString("data") ?: return@forEach)
|
||||||
val eventId = jExam.get("_recordId").asLong
|
val subjectName = exam.getString("przedmiot") ?: return@forEach
|
||||||
val rSubject = data.getSubject(jExam.get("przedmiot").asString, -1, "")
|
val subjectId = data.getSubject(subjectName, null, subjectName).id
|
||||||
val rTeacher = data.getTeacherByLastFirst(jExam.get("wpisal").asString)
|
val teacherName = exam.getString("wpisal") ?: return@forEach
|
||||||
val examDate = Date.fromY_m_d(jExam.get("data").asString)
|
val teacherId = data.getTeacherByLastFirst(teacherName).id
|
||||||
val lessonObject = Lesson.getByWeekDayAndSubject(data.lessonList, examDate.weekDay, rSubject.id)
|
val topic = exam.getString("zakres") ?: ""
|
||||||
val examTime = lessonObject?.startTime
|
|
||||||
|
val lessonList = data.db.timetableDao().getForDateNow(profileId, examDate)
|
||||||
|
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
|
||||||
|
|
||||||
|
val eventType = when (exam.getString("rodzaj")) {
|
||||||
|
"sprawdzian/praca klasowa" -> Event.TYPE_EXAM
|
||||||
|
else -> Event.TYPE_SHORT_QUIZ
|
||||||
|
}
|
||||||
|
|
||||||
val eventType = if (jExam.get("rodzaj").asString == "sprawdzian/praca klasowa") Event.TYPE_EXAM else Event.TYPE_SHORT_QUIZ
|
|
||||||
val eventObject = Event(
|
val eventObject = Event(
|
||||||
profileId,
|
profileId,
|
||||||
eventId,
|
id,
|
||||||
examDate,
|
examDate,
|
||||||
examTime,
|
startTime,
|
||||||
jExam.get("zakres").asString,
|
topic,
|
||||||
-1,
|
-1,
|
||||||
eventType,
|
eventType,
|
||||||
false,
|
false,
|
||||||
rTeacher.id,
|
teacherId,
|
||||||
rSubject.id,
|
subjectId,
|
||||||
data.teamClass?.id ?: -1
|
data.teamClass?.id ?: -1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -106,9 +113,11 @@ class IdziennikWebExams(override val data: DataIdziennik,
|
|||||||
examsNextMonthChecked = true
|
examsNextMonthChecked = true
|
||||||
getExams()
|
getExams()
|
||||||
} else {
|
} else {
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-25
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.idziennik.data.web
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.*
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.IDZIENNIK_WEB_HOMEWORK
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.DataIdziennik
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_HOMEWORK
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
|
class IdziennikWebHomework(override val data: DataIdziennik,
|
||||||
|
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "IdziennikWebHomework"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val param = JsonObject().apply {
|
||||||
|
addProperty("strona", 1)
|
||||||
|
addProperty("iloscNaStrone", 997)
|
||||||
|
addProperty("iloscRekordow", -1)
|
||||||
|
addProperty("kolumnaSort", "DataZadania")
|
||||||
|
addProperty("kierunekSort", 0)
|
||||||
|
addProperty("maxIloscZaznaczonych", 0)
|
||||||
|
addProperty("panelFiltrow", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
webApiGet(TAG, IDZIENNIK_WEB_HOMEWORK, mapOf(
|
||||||
|
"idP" to data.registerId,
|
||||||
|
"data" to Date.getToday().stringY_m_d,
|
||||||
|
"wszystkie" to true,
|
||||||
|
"param" to param
|
||||||
|
)) { result ->
|
||||||
|
val json = result.getJsonObject("d") ?: run {
|
||||||
|
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
||||||
|
.withApiResponse(result))
|
||||||
|
return@webApiGet
|
||||||
|
}
|
||||||
|
|
||||||
|
json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { homework ->
|
||||||
|
val id = homework.getLong("_recordId") ?: return@forEach
|
||||||
|
val eventDate = Date.fromY_m_d(homework.getString("dataO") ?: return@forEach)
|
||||||
|
val subjectName = homework.getString("przed") ?: return@forEach
|
||||||
|
val subjectId = data.getSubject(subjectName, null, subjectName).id
|
||||||
|
val teacherName = homework.getString("usr") ?: return@forEach
|
||||||
|
val teacherId = data.getTeacherByLastFirst(teacherName).id
|
||||||
|
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
|
||||||
|
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime
|
||||||
|
val topic = homework.getString("tytul") ?: ""
|
||||||
|
|
||||||
|
val seen = when (profile?.empty) {
|
||||||
|
true -> true
|
||||||
|
else -> eventDate < Date.getToday()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val eventObject = Event(
|
||||||
|
profileId,
|
||||||
|
id,
|
||||||
|
eventDate,
|
||||||
|
startTime,
|
||||||
|
topic,
|
||||||
|
-1,
|
||||||
|
Event.TYPE_HOMEWORK,
|
||||||
|
false,
|
||||||
|
teacherId,
|
||||||
|
subjectId,
|
||||||
|
data.teamClass?.id ?: -1
|
||||||
|
)
|
||||||
|
|
||||||
|
data.eventList.add(eventObject)
|
||||||
|
data.metadataList.add(Metadata(
|
||||||
|
profileId,
|
||||||
|
Metadata.TYPE_HOMEWORK,
|
||||||
|
eventObject.id,
|
||||||
|
seen,
|
||||||
|
seen,
|
||||||
|
System.currentTimeMillis()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||||
|
|
||||||
|
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_HOMEWORK, SYNC_ALWAYS)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,21 +10,24 @@ import pl.szczodrzynski.edziennik.api.v2.idziennik.DataIdziennik
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES
|
||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.asJsonObjectList
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.getJsonArray
|
||||||
import pl.szczodrzynski.edziennik.getJsonObject
|
import pl.szczodrzynski.edziennik.getJsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.getWordGradeValue
|
import pl.szczodrzynski.edziennik.utils.Utils.getWordGradeValue
|
||||||
|
|
||||||
class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "IdziennikWebProposedGrades"
|
private const val TAG = "IdziennikWebProposedGrades"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init { data.profile?.also { profile ->
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_MISSING_GRADES, mapOf(
|
webApiGet(TAG, IDZIENNIK_WEB_MISSING_GRADES, mapOf(
|
||||||
"idPozDziennika" to data.registerId
|
"idPozDziennika" to data.registerId
|
||||||
)) { result ->
|
)) { result ->
|
||||||
@ -34,17 +37,17 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
|||||||
return@webApiGet
|
return@webApiGet
|
||||||
}
|
}
|
||||||
|
|
||||||
val jSubjects = json.getAsJsonArray("Przedmioty")
|
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { subject ->
|
||||||
for (jSubjectEl in jSubjects) {
|
val subjectName = subject.getString("Przedmiot") ?: return@forEach
|
||||||
val jSubject = jSubjectEl.getAsJsonObject()
|
val subjectObject = data.getSubject(subjectName, null, subjectName)
|
||||||
// jSubject
|
|
||||||
val rSubject = data.getSubject(jSubject.get("Przedmiot").getAsString(), -1, jSubject.get("Przedmiot").getAsString())
|
val semester1Proposed = subject.getString("OcenaSem1") ?: ""
|
||||||
val semester1Proposed = jSubject.get("OcenaSem1").getAsString()
|
|
||||||
val semester2Proposed = jSubject.get("OcenaSem2").getAsString()
|
|
||||||
val semester1Value = getWordGradeValue(semester1Proposed)
|
val semester1Value = getWordGradeValue(semester1Proposed)
|
||||||
|
val semester1Id = subjectObject.id * (-100) - 1
|
||||||
|
|
||||||
|
val semester2Proposed = subject.getString("OcenaSem2") ?: ""
|
||||||
val semester2Value = getWordGradeValue(semester2Proposed)
|
val semester2Value = getWordGradeValue(semester2Proposed)
|
||||||
val semester1Id = rSubject.id * -100 - 1
|
val semester2Id = subjectObject.id * (-100) - 2
|
||||||
val semester2Id = rSubject.id * -100 - 2
|
|
||||||
|
|
||||||
if (semester1Proposed != "") {
|
if (semester1Proposed != "") {
|
||||||
val gradeObject = Grade(
|
val gradeObject = Grade(
|
||||||
@ -58,17 +61,18 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
|||||||
0f,
|
0f,
|
||||||
1,
|
1,
|
||||||
-1,
|
-1,
|
||||||
rSubject.id)
|
subjectObject.id
|
||||||
|
).apply {
|
||||||
gradeObject.type = TYPE_SEMESTER1_PROPOSED
|
type = TYPE_SEMESTER1_PROPOSED
|
||||||
|
}
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
data.gradeList.add(gradeObject)
|
||||||
data.metadataList.add(Metadata(
|
data.metadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_GRADE,
|
Metadata.TYPE_GRADE,
|
||||||
gradeObject.id,
|
gradeObject.id,
|
||||||
profile?.empty ?: false,
|
profile.empty,
|
||||||
profile?.empty ?: false,
|
profile.empty,
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -85,17 +89,18 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
|||||||
0f,
|
0f,
|
||||||
2,
|
2,
|
||||||
-1,
|
-1,
|
||||||
rSubject.id)
|
subjectObject.id
|
||||||
|
).apply {
|
||||||
gradeObject.type = TYPE_YEAR_PROPOSED
|
type = TYPE_YEAR_PROPOSED
|
||||||
|
}
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
data.gradeList.add(gradeObject)
|
||||||
data.metadataList.add(Metadata(
|
data.metadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_GRADE,
|
Metadata.TYPE_GRADE,
|
||||||
gradeObject.id,
|
gradeObject.id,
|
||||||
profile?.empty ?: false,
|
profile.empty,
|
||||||
profile?.empty ?: false,
|
profile.empty,
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -104,5 +109,5 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
|||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-10-27.
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-22
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.idziennik.data.web
|
package pl.szczodrzynski.edziennik.api.v2.idziennik.data.web
|
||||||
@ -12,33 +12,38 @@ import pl.szczodrzynski.edziennik.api.v2.idziennik.DataIdziennik
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_TIMETABLE
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.ENDPOINT_IDZIENNIK_WEB_TIMETABLE
|
||||||
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.Lesson
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CANCELLED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CHANGE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
|
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
|
||||||
class IdziennikWebTimetable(override val data: DataIdziennik,
|
class IdziennikWebTimetable(override val data: DataIdziennik,
|
||||||
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
val onSuccess: () -> Unit) : IdziennikWeb(data) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "IdziennikWebTimetable"
|
private const val TAG = "IdziennikWebTimetable"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init { data.profile?.also { profile ->
|
||||||
val weekStart = Week.getWeekStart()
|
val currentWeekStart = Week.getWeekStart()
|
||||||
|
|
||||||
if (Date.getToday().weekDay > 4) {
|
if (Date.getToday().weekDay > 4) {
|
||||||
weekStart.stepForward(0, 0, 7)
|
currentWeekStart.stepForward(0, 0, 7)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
||||||
|
|
||||||
|
val weekStart = Date.fromY_m_d(getDate)
|
||||||
|
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
||||||
|
|
||||||
webApiGet(TAG, IDZIENNIK_WEB_TIMETABLE, mapOf(
|
webApiGet(TAG, IDZIENNIK_WEB_TIMETABLE, mapOf(
|
||||||
"idPozDziennika" to data.registerId,
|
"idPozDziennika" to data.registerId,
|
||||||
"pidRokSzkolny" to data.schoolYearId,
|
"pidRokSzkolny" to data.schoolYearId,
|
||||||
"data" to weekStart.stringY_m_d+"T10:00:00.000Z"
|
"data" to "${weekStart.stringY_m_d}T10:00:00.000Z"
|
||||||
)) { result ->
|
)) { result ->
|
||||||
val json = result.getJsonObject("d") ?: run {
|
val json = result.getJsonObject("d") ?: run {
|
||||||
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
|
||||||
@ -56,73 +61,132 @@ class IdziennikWebTimetable(override val data: DataIdziennik,
|
|||||||
data.lessonRanges[lessonRange.lessonNumber] = lessonRange
|
data.lessonRanges[lessonRange.lessonNumber] = lessonRange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val dates = mutableSetOf<Int>()
|
||||||
|
val lessons = mutableListOf<Lesson>()
|
||||||
|
|
||||||
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { lesson ->
|
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { lesson ->
|
||||||
val subject = data.getSubject(
|
val subject = data.getSubject(
|
||||||
lesson.getString("Nazwa") ?: return@forEach,
|
lesson.getString("Nazwa") ?: return@forEach,
|
||||||
lesson.getLong("Id"),
|
lesson.getLong("Id"),
|
||||||
lesson.getString("Skrot") ?: ""
|
lesson.getString("Skrot") ?: ""
|
||||||
)
|
)
|
||||||
val teacher = data.getTeacherByFDotLast(lesson.getString("Nauczyciel") ?: return@forEach)
|
val teacher = data.getTeacherByFDotLast(lesson.getString("Nauczyciel")
|
||||||
val weekDay = lesson.getInt("DzienTygodnia")?.minus(1) ?: return@forEach
|
?: return@forEach)
|
||||||
val lessonRange = data.lessonRanges[lesson.getInt("Godzina")?.plus(1) ?: return@forEach]
|
|
||||||
|
|
||||||
val lessonObject = Lesson(
|
val newSubjectName = lesson.getString("PrzedmiotZastepujacy")
|
||||||
profileId,
|
val newSubject = when (newSubjectName.isNullOrBlank()) {
|
||||||
weekDay,
|
true -> null
|
||||||
lessonRange.startTime,
|
else -> data.getSubject(newSubjectName, null, newSubjectName)
|
||||||
lessonRange.endTime
|
|
||||||
).apply {
|
|
||||||
subjectId = subject.id
|
|
||||||
teacherId = teacher.id
|
|
||||||
teamId = data.teamClass?.id ?: -1
|
|
||||||
classroomName = lesson.getString("NazwaSali") ?: ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.lessonList.add(lessonObject)
|
val newTeacherName = lesson.getString("NauZastepujacy")
|
||||||
|
val newTeacher = when (newTeacherName.isNullOrBlank()) {
|
||||||
|
true -> null
|
||||||
|
else -> data.getTeacherByFDotLast(newTeacherName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val weekDay = lesson.getInt("DzienTygodnia")?.minus(1) ?: return@forEach
|
||||||
|
val lessonRange = data.lessonRanges[lesson.getInt("Godzina")?.plus(1)
|
||||||
|
?: return@forEach]
|
||||||
|
val lessonDate = weekStart.clone().stepForward(0, 0, weekDay)
|
||||||
|
val classroom = lesson.getString("NazwaSali")
|
||||||
|
|
||||||
val type = lesson.getInt("TypZastepstwa") ?: -1
|
val type = lesson.getInt("TypZastepstwa") ?: -1
|
||||||
if (type != -1) {
|
|
||||||
// we have a lesson change to process
|
|
||||||
val lessonChangeObject = LessonChange(
|
|
||||||
profileId,
|
|
||||||
weekStart.clone().stepForward(0, 0, weekDay),
|
|
||||||
lessonObject.startTime,
|
|
||||||
lessonObject.endTime
|
|
||||||
)
|
|
||||||
|
|
||||||
lessonChangeObject.teamId = lessonObject.teamId
|
val lessonObject = Lesson(profileId, -1)
|
||||||
lessonChangeObject.teacherId = lessonObject.teacherId
|
|
||||||
lessonChangeObject.subjectId = lessonObject.subjectId
|
when (type) {
|
||||||
lessonChangeObject.classroomName = lessonObject.classroomName
|
1, 2, 3, 4, 5 -> {
|
||||||
when (type) {
|
lessonObject.apply {
|
||||||
0 -> lessonChangeObject.type = TYPE_CANCELLED
|
this.type = Lesson.TYPE_CHANGE
|
||||||
1, 2, 3, 4, 5 -> {
|
|
||||||
lessonChangeObject.type = TYPE_CHANGE
|
this.date = lessonDate
|
||||||
val newTeacher = lesson.getString("NauZastepujacy")
|
this.lessonNumber = lessonRange.lessonNumber
|
||||||
val newSubject = lesson.getString("PrzedmiotZastepujacy")
|
this.startTime = lessonRange.startTime
|
||||||
if (newTeacher != null) {
|
this.endTime = lessonRange.endTime
|
||||||
lessonChangeObject.teacherId = data.getTeacherByFDotLast(newTeacher).id
|
this.subjectId = newSubject?.id
|
||||||
}
|
this.teacherId = newTeacher?.id
|
||||||
if (newSubject != null) {
|
this.teamId = data.teamClass?.id
|
||||||
lessonChangeObject.subjectId = data.getSubject(newSubject, null, "").id
|
this.classroom = classroom
|
||||||
}
|
|
||||||
|
this.oldDate = lessonDate
|
||||||
|
this.oldLessonNumber = lessonRange.lessonNumber
|
||||||
|
this.oldStartTime = lessonRange.startTime
|
||||||
|
this.oldEndTime = lessonRange.endTime
|
||||||
|
this.oldSubjectId = subject.id
|
||||||
|
this.oldTeacherId = teacher.id
|
||||||
|
this.oldTeamId = data.teamClass?.id
|
||||||
|
this.oldClassroom = classroom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0 -> {
|
||||||
|
lessonObject.apply {
|
||||||
|
this.type = Lesson.TYPE_CANCELLED
|
||||||
|
|
||||||
data.lessonChangeList.add(lessonChangeObject)
|
this.oldDate = lessonDate
|
||||||
|
this.oldLessonNumber = lessonRange.lessonNumber
|
||||||
|
this.oldStartTime = lessonRange.startTime
|
||||||
|
this.oldEndTime = lessonRange.endTime
|
||||||
|
this.oldSubjectId = subject.id
|
||||||
|
this.oldTeacherId = teacher.id
|
||||||
|
this.oldTeamId = data.teamClass?.id
|
||||||
|
this.oldClassroom = classroom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
lessonObject.apply {
|
||||||
|
this.type = Lesson.TYPE_NORMAL
|
||||||
|
|
||||||
|
this.date = lessonDate
|
||||||
|
this.lessonNumber = lessonRange.lessonNumber
|
||||||
|
this.startTime = lessonRange.startTime
|
||||||
|
this.endTime = lessonRange.endTime
|
||||||
|
this.subjectId = subject.id
|
||||||
|
this.teacherId = teacher.id
|
||||||
|
this.teamId = data.teamClass?.id
|
||||||
|
this.classroom = classroom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lessonObject.id = lessonObject.buildId()
|
||||||
|
|
||||||
|
dates.add(lessonDate.value)
|
||||||
|
lessons.add(lessonObject)
|
||||||
|
|
||||||
|
val seen = profile.empty || lessonDate < Date.getToday()
|
||||||
|
|
||||||
|
if (lessonObject.type != Lesson.TYPE_NORMAL && lessonDate >= Date.getToday()) {
|
||||||
data.metadataList.add(Metadata(
|
data.metadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_LESSON_CHANGE,
|
Metadata.TYPE_LESSON_CHANGE,
|
||||||
lessonChangeObject.id,
|
lessonObject.id,
|
||||||
profile?.empty ?: false,
|
seen,
|
||||||
profile?.empty ?: false,
|
seen,
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val date: Date = weekStart.clone()
|
||||||
|
while (date <= weekEnd) {
|
||||||
|
if (!dates.contains(date.value)) {
|
||||||
|
lessons.add(Lesson(profileId, date.value.toLong()).apply {
|
||||||
|
this.type = Lesson.TYPE_NO_LESSONS
|
||||||
|
this.date = date.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
date.stepForward(0, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
||||||
|
|
||||||
|
data.lessonNewList.addAll(lessons)
|
||||||
|
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,15 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.interfaces
|
package pl.szczodrzynski.edziennik.api.v2.interfaces
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
|
|
||||||
interface EdziennikInterface {
|
interface EdziennikInterface {
|
||||||
fun sync(featureIds: List<Int>, viewId: Int? = null)
|
fun sync(featureIds: List<Int>, viewId: Int? = null, arguments: JsonObject? = null)
|
||||||
fun getMessage(messageId: Int)
|
fun getMessage(message: MessageFull)
|
||||||
fun markAllAnnouncementsAsRead()
|
fun markAllAnnouncementsAsRead()
|
||||||
|
fun getAttachment(message: Message, attachmentId: Long, attachmentName: String)
|
||||||
fun firstLogin()
|
fun firstLogin()
|
||||||
fun cancel()
|
fun cancel()
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,21 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.librus
|
package pl.szczodrzynski.edziennik.api.v2.librus
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusData
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusData
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.messages.LibrusMessagesGetAttachment
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.messages.LibrusMessagesGetMessage
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.synergia.LibrusSynergiaMarkAllAnnouncementsAsRead
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.synergia.LibrusSynergiaMarkAllAnnouncementsAsRead
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.firstlogin.LibrusFirstLogin
|
import pl.szczodrzynski.edziennik.api.v2.librus.firstlogin.LibrusFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLogin
|
import pl.szczodrzynski.edziennik.api.v2.librus.login.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginApi
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginSynergia
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
@ -49,7 +52,8 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||||
|
data.arguments = arguments
|
||||||
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
|
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
|
||||||
login()
|
login()
|
||||||
}
|
}
|
||||||
@ -76,15 +80,41 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(messageId: Int) {
|
override fun getMessage(message: MessageFull) {
|
||||||
|
LibrusLoginPortal(data) {
|
||||||
|
LibrusLoginApi(data) {
|
||||||
|
LibrusLoginSynergia(data) {
|
||||||
|
LibrusLoginMessages(data) {
|
||||||
|
LibrusMessagesGetMessage(data, message) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {
|
override fun markAllAnnouncementsAsRead() {
|
||||||
LibrusLoginApi(data) {
|
LibrusLoginPortal(data) {
|
||||||
LibrusLoginSynergia(data) {
|
LibrusLoginApi(data) {
|
||||||
LibrusSynergiaMarkAllAnnouncementsAsRead(data) {
|
LibrusLoginSynergia(data) {
|
||||||
completed()
|
LibrusSynergiaMarkAllAnnouncementsAsRead(data) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||||
|
LibrusLoginPortal(data) {
|
||||||
|
LibrusLoginApi(data) {
|
||||||
|
LibrusLoginSynergia(data) {
|
||||||
|
LibrusLoginMessages(data) {
|
||||||
|
LibrusMessagesGetAttachment(data, message, attachmentId, attachmentName) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +203,10 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
login()
|
login()
|
||||||
}
|
}
|
||||||
// TODO PORTAL CAPTCHA
|
// TODO PORTAL CAPTCHA
|
||||||
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC,
|
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC -> {
|
||||||
|
loginStore.putLoginData("timetableNotPublic", true)
|
||||||
|
data()
|
||||||
|
}
|
||||||
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
|
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
|
||||||
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
|
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
|
||||||
data()
|
data()
|
||||||
|
@ -24,6 +24,7 @@ const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GC = 1023
|
|||||||
const val ENDPOINT_LIBRUS_API_TEXT_GC = 1024
|
const val ENDPOINT_LIBRUS_API_TEXT_GC = 1024
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC = 1025
|
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC = 1025
|
||||||
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GC = 1026
|
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GC = 1026
|
||||||
|
const val ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS = 1030
|
||||||
const val ENDPOINT_LIBRUS_API_NORMAL_GRADES = 1031
|
const val ENDPOINT_LIBRUS_API_NORMAL_GRADES = 1031
|
||||||
const val ENDPOINT_LIBRUS_API_POINT_GRADES = 1032
|
const val ENDPOINT_LIBRUS_API_POINT_GRADES = 1032
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES = 1033
|
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES = 1033
|
||||||
@ -59,7 +60,7 @@ val LibrusFeatures = listOf(
|
|||||||
Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf(
|
Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf(
|
||||||
ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API
|
ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API
|
||||||
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
|
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
|
||||||
data.app.appConfig.fcmTokens[LOGIN_TYPE_LIBRUS]?.second?.contains(data.profileId) == false
|
!data.app.config.sync.tokenLibrusList.contains(data.profileId)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ val LibrusFeatures = listOf(
|
|||||||
ENDPOINT_LIBRUS_API_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GC to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_BEHAVIOUR_GC to LOGIN_METHOD_LIBRUS_API,
|
||||||
|
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_POINT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_POINT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LOGIN_METHOD_LIBRUS_API,
|
||||||
|
@ -28,10 +28,17 @@ open class LibrusApi(open val data: DataLibrus) {
|
|||||||
|
|
||||||
fun apiGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject) -> Unit) {
|
fun apiGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject) -> Unit) {
|
||||||
|
|
||||||
d(tag, "Request: Librus/Api - $LIBRUS_API_URL/$endpoint")
|
d(tag, "Request: Librus/Api - ${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
val callback = object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
|
if (response?.code() == HTTP_UNAVAILABLE) {
|
||||||
|
data.error(ApiError(tag, ERROR_LIBRUS_API_MAINTENANCE)
|
||||||
|
.withApiResponse(json)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (json == null && response?.parserErrorBody == null) {
|
if (json == null && response?.parserErrorBody == null) {
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
.withResponse(response))
|
.withResponse(response))
|
||||||
@ -90,7 +97,7 @@ open class LibrusApi(open val data: DataLibrus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Request.builder()
|
Request.builder()
|
||||||
.url("$LIBRUS_API_URL/$endpoint")
|
.url("${if (data.fakeLogin) FAKE_LIBRUS_API else LIBRUS_API_URL}/$endpoint")
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
.userAgent(LIBRUS_USER_AGENT)
|
||||||
.addHeader("Authorization", "Bearer ${data.apiAccessToken}")
|
.addHeader("Authorization", "Bearer ${data.apiAccessToken}")
|
||||||
.apply {
|
.apply {
|
||||||
@ -104,6 +111,7 @@ open class LibrusApi(open val data: DataLibrus) {
|
|||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
.allowErrorCode(HTTP_FORBIDDEN)
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
|
.allowErrorCode(HTTP_UNAVAILABLE)
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
|
@ -76,12 +76,19 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
LibrusApiClassrooms(data, onSuccess)
|
LibrusApiClassrooms(data, onSuccess)
|
||||||
}
|
}
|
||||||
// TODO push config
|
// TODO push config
|
||||||
// TODO timetable
|
ENDPOINT_LIBRUS_API_TIMETABLES -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||||
|
LibrusApiTimetables(data, onSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
|
ENDPOINT_LIBRUS_API_NORMAL_GRADES -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
||||||
LibrusApiGrades(data, onSuccess)
|
LibrusApiGrades(data, onSuccess)
|
||||||
}
|
}
|
||||||
|
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
|
||||||
|
LibrusApiGradeComments(data, onSuccess)
|
||||||
|
}
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GC -> {
|
ENDPOINT_LIBRUS_API_NORMAL_GC -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||||
LibrusApiGradeCategories(data, onSuccess)
|
LibrusApiGradeCategories(data, onSuccess)
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.librus.data
|
package pl.szczodrzynski.edziennik.api.v2.librus.data
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
import im.wangchao.mhttp.body.MediaTypeUtils
|
import im.wangchao.mhttp.body.MediaTypeUtils
|
||||||
|
import im.wangchao.mhttp.callback.FileCallbackHandler
|
||||||
|
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
@ -15,8 +18,8 @@ import org.jsoup.parser.Parser
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.get
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import java.io.File
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
import javax.xml.transform.OutputKeys
|
import javax.xml.transform.OutputKeys
|
||||||
@ -43,19 +46,19 @@ open class LibrusMessages(open val data: DataLibrus) {
|
|||||||
val callback = object : TextCallbackHandler() {
|
val callback = object : TextCallbackHandler() {
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
override fun onSuccess(text: String?, response: Response?) {
|
||||||
if (text.isNullOrEmpty()) {
|
if (text.isNullOrEmpty()) {
|
||||||
data.error(ApiError(LibrusSynergia.TAG, ERROR_RESPONSE_EMPTY)
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
.withResponse(response))
|
.withResponse(response))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Finish error handling
|
when {
|
||||||
|
text.contains("<message>Niepoprawny login i/lub hasło.</message>") -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
|
||||||
if ("error" in text) {
|
text.contains("stop.png") -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
||||||
when ("<type>(.*)</type>".toRegex().find(text)?.get(1)) {
|
text.contains("eAccessDeny") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||||
"eAccessDeny" -> data.error(ApiError(tag, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED)
|
text.contains("OffLine") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
|
||||||
.withResponse(response)
|
text.contains("<status>error</status>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
|
||||||
.withApiResponse(text))
|
text.contains("<type>eVarWhitThisNameNotExists</type>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||||
}
|
text.contains("<error>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -132,4 +135,95 @@ open class LibrusMessages(open val data: DataLibrus) {
|
|||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sandboxGet(tag: String, action: String, parameters: Map<String, Any>? = null,
|
||||||
|
onSuccess: (json: JsonObject) -> Unit) {
|
||||||
|
|
||||||
|
d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
|
||||||
|
|
||||||
|
val callback = object : JsonCallbackHandler() {
|
||||||
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
|
if (json == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
onSuccess(json)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(e)
|
||||||
|
.withApiResponse(json))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url("$LIBRUS_SANDBOX_URL$action")
|
||||||
|
.userAgent(SYNERGIA_USER_AGENT)
|
||||||
|
.apply {
|
||||||
|
parameters?.forEach { (k, v) ->
|
||||||
|
addParameter(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.post()
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sandboxGetFile(tag: String, action: String, targetFile: File, onSuccess: (file: File) -> Unit,
|
||||||
|
onProgress: (written: Long, total: Long) -> Unit) {
|
||||||
|
|
||||||
|
d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action")
|
||||||
|
|
||||||
|
val callback = object : FileCallbackHandler(targetFile) {
|
||||||
|
override fun onSuccess(file: File?, response: Response?) {
|
||||||
|
if (file == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
onSuccess(file)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
|
||||||
|
try {
|
||||||
|
onProgress(bytesWritten, bytesTotal)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST)
|
||||||
|
.withThrowable(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url("$LIBRUS_SANDBOX_URL$action")
|
||||||
|
.userAgent(SYNERGIA_USER_AGENT)
|
||||||
|
.post()
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ open class LibrusPortal(open val data: DataLibrus) {
|
|||||||
|
|
||||||
fun portalGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject, response: Response?) -> Unit) {
|
fun portalGet(tag: String, endpoint: String, method: Int = GET, payload: JsonObject? = null, onSuccess: (json: JsonObject, response: Response?) -> Unit) {
|
||||||
|
|
||||||
d(tag, "Request: Librus/Portal - $LIBRUS_PORTAL_URL$endpoint")
|
d(tag, "Request: Librus/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_PORTAL else LIBRUS_PORTAL_URL}$endpoint")
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
val callback = object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
@ -81,7 +81,7 @@ open class LibrusPortal(open val data: DataLibrus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Request.builder()
|
Request.builder()
|
||||||
.url(LIBRUS_PORTAL_URL + endpoint)
|
.url((if (data.fakeLogin) FAKE_LIBRUS_PORTAL else LIBRUS_PORTAL_URL) + endpoint)
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
.userAgent(LIBRUS_USER_AGENT)
|
||||||
.addHeader("Authorization", "Bearer ${data.portalAccessToken}")
|
.addHeader("Authorization", "Bearer ${data.portalAccessToken}")
|
||||||
.apply {
|
.apply {
|
||||||
|
@ -14,7 +14,7 @@ import pl.szczodrzynski.edziennik.utils.Utils.d
|
|||||||
|
|
||||||
open class LibrusSynergia(open val data: DataLibrus) {
|
open class LibrusSynergia(open val data: DataLibrus) {
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "LibrusSynergia"
|
private const val TAG = "LibrusSynergia"
|
||||||
}
|
}
|
||||||
|
|
||||||
val profileId
|
val profileId
|
||||||
|
@ -36,14 +36,14 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
|||||||
val lessonNo = attendance.getInt("LessonNo") ?: return@forEach
|
val lessonNo = attendance.getInt("LessonNo") ?: return@forEach
|
||||||
val startTime = data.lessonRanges.get(lessonNo).startTime
|
val startTime = data.lessonRanges.get(lessonNo).startTime
|
||||||
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
|
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
|
||||||
val subjectId = data.lessonList.singleOrNull {
|
|
||||||
it.weekDay == lessonDate.weekDay && it.startTime.value == startTime.value
|
|
||||||
}?.subjectId ?: -1
|
|
||||||
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)
|
||||||
val topic = typeObject?.name ?: ""
|
val topic = typeObject?.name ?: ""
|
||||||
|
|
||||||
|
val lessonList = data.db.timetableDao().getForDateNow(profileId, lessonDate)
|
||||||
|
val subjectId = lessonList.firstOrNull { it.startTime == startTime }?.subjectId ?: -1
|
||||||
|
|
||||||
val attendanceObject = Attendance(
|
val attendanceObject = Attendance(
|
||||||
profileId,
|
profileId,
|
||||||
id,
|
id,
|
||||||
|
@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.*
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_EVENTS
|
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_EVENTS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
@ -69,6 +70,8 @@ class LibrusApiEvents(override val data: DataLibrus,
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_EVENTS, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_LIBRUS_API_EVENTS, SYNC_ALWAYS)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-20
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.librus.data.api
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
|
import pl.szczodrzynski.edziennik.asJsonObjectList
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
||||||
|
import pl.szczodrzynski.edziennik.getJsonArray
|
||||||
|
import pl.szczodrzynski.edziennik.getLong
|
||||||
|
import pl.szczodrzynski.edziennik.getString
|
||||||
|
|
||||||
|
class LibrusApiGradeComments(override val data: DataLibrus,
|
||||||
|
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "LibrusApiGradeComments"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
apiGet(TAG, "Grades/Comments") { json ->
|
||||||
|
|
||||||
|
json.getJsonArray("Comments")?.asJsonObjectList()?.forEach { comment ->
|
||||||
|
val id = comment.getLong("Id") ?: return@forEach
|
||||||
|
val text = comment.getString("Text")
|
||||||
|
|
||||||
|
val gradeCategoryObject = GradeCategory(
|
||||||
|
profileId,
|
||||||
|
id,
|
||||||
|
-1f,
|
||||||
|
-1,
|
||||||
|
text
|
||||||
|
).apply {
|
||||||
|
type = GradeCategory.TYPE_COMMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
data.gradeCategories.put(id, gradeCategoryObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS, SYNC_ALWAYS)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
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
|
||||||
@ -42,12 +43,21 @@ class LibrusApiGrades(override val data: DataLibrus,
|
|||||||
weight = 0f
|
weight = 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val description = grade.getJsonArray("Comments")?.asJsonObjectList()?.let { comments ->
|
||||||
|
if (comments.isNotEmpty()) {
|
||||||
|
data.gradeCategories.singleOrNull {
|
||||||
|
it.type == GradeCategory.TYPE_COMMENT
|
||||||
|
&& it.categoryId == comments[0].asJsonObject.getLong("Id")
|
||||||
|
}?.text
|
||||||
|
} else null
|
||||||
|
} ?: ""
|
||||||
|
|
||||||
val gradeObject = Grade(
|
val gradeObject = Grade(
|
||||||
profileId,
|
profileId,
|
||||||
id,
|
id,
|
||||||
categoryName,
|
categoryName,
|
||||||
color,
|
color,
|
||||||
"",
|
description,
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
weight,
|
weight,
|
||||||
|
@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.*
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_HOMEWORK
|
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_HOMEWORK
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
@ -55,6 +56,8 @@ class LibrusApiHomework(override val data: DataLibrus,
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_HOMEWORK, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_LIBRUS_API_HOMEWORK, SYNC_ALWAYS)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.librus.data.api
|
||||||
|
|
||||||
|
import androidx.core.util.isEmpty
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.*
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_TIMETABLES
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
|
||||||
|
class LibrusApiTimetables(override val data: DataLibrus,
|
||||||
|
val onSuccess: () -> Unit) : LibrusApi(data) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "LibrusApiTimetables"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (data.classrooms.isEmpty()) {
|
||||||
|
data.db.classroomDao().getAllNow(profileId).toSparseArray(data.classrooms) { it.id }
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentWeekStart = Week.getWeekStart()
|
||||||
|
|
||||||
|
if (Date.getToday().weekDay > 4) {
|
||||||
|
currentWeekStart.stepForward(0, 0, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
||||||
|
|
||||||
|
val weekStart = Date.fromY_m_d(getDate)
|
||||||
|
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
||||||
|
|
||||||
|
apiGet(TAG, "Timetables?weekStart=${weekStart.stringY_m_d}") { json ->
|
||||||
|
val days = json.getJsonObject("Timetable")
|
||||||
|
|
||||||
|
days?.entrySet()?.forEach { (dateString, dayEl) ->
|
||||||
|
val day = dayEl?.asJsonArray
|
||||||
|
|
||||||
|
val lessonDate = dateString?.let { Date.fromY_m_d(it) } ?: return@forEach
|
||||||
|
|
||||||
|
var lessonsFound = false
|
||||||
|
day?.forEach { lessonRangeEl ->
|
||||||
|
val lessonRange = lessonRangeEl?.asJsonArray?.asJsonObjectList()
|
||||||
|
if (lessonRange?.isNullOrEmpty() == false)
|
||||||
|
lessonsFound = true
|
||||||
|
lessonRange?.forEach { lesson ->
|
||||||
|
parseLesson(lessonDate, lesson)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day.isNullOrEmpty() || !lessonsFound) {
|
||||||
|
data.lessonNewList.add(Lesson(profileId, lessonDate.value.toLong()).apply {
|
||||||
|
type = Lesson.TYPE_NO_LESSONS
|
||||||
|
date = lessonDate
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||||
|
data.setSyncNext(ENDPOINT_LIBRUS_API_TIMETABLES, SYNC_ALWAYS)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseLesson(lessonDate: Date, lesson: JsonObject) { data.profile?.also { profile ->
|
||||||
|
val isSubstitution = lesson.getBoolean("IsSubstitutionClass") ?: false
|
||||||
|
val isCancelled = lesson.getBoolean("IsCanceled") ?: false
|
||||||
|
|
||||||
|
val lessonNo = lesson.getInt("LessonNo") ?: return
|
||||||
|
val startTime = lesson.getString("HourFrom")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
val endTime = lesson.getString("HourTo")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
val subjectId = lesson.getJsonObject("Subject")?.getLong("Id")
|
||||||
|
val teacherId = lesson.getJsonObject("Teacher")?.getLong("Id")
|
||||||
|
val classroomId = lesson.getJsonObject("Classroom")?.getLong("Id") ?: -1
|
||||||
|
val virtualClassId = lesson.getJsonObject("VirtualClass")?.getLong("Id")
|
||||||
|
val teamId = lesson.getJsonObject("Class")?.getLong("Id") ?: virtualClassId
|
||||||
|
|
||||||
|
val lessonObject = Lesson(profileId, -1)
|
||||||
|
|
||||||
|
if (isSubstitution && isCancelled) {
|
||||||
|
// shifted lesson - source
|
||||||
|
val newDate = lesson.getString("NewDate")?.let { Date.fromY_m_d(it) } ?: return
|
||||||
|
val newLessonNo = lesson.getInt("NewLessonNo") ?: return
|
||||||
|
val newStartTime = lesson.getString("NewHourFrom")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
val newEndTime = lesson.getString("NewHourTo")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
val newSubjectId = lesson.getJsonObject("NewSubject")?.getLong("Id")
|
||||||
|
val newTeacherId = lesson.getJsonObject("NewTeacher")?.getLong("Id")
|
||||||
|
val newClassroomId = lesson.getJsonObject("NewClassroom")?.getLong("Id") ?: -1
|
||||||
|
val newVirtualClassId = lesson.getJsonObject("NewVirtualClass")?.getLong("Id")
|
||||||
|
val newTeamId = lesson.getJsonObject("NewClass")?.getLong("Id") ?: newVirtualClassId
|
||||||
|
|
||||||
|
lessonObject.let {
|
||||||
|
it.type = Lesson.TYPE_SHIFTED_SOURCE
|
||||||
|
it.oldDate = lessonDate
|
||||||
|
it.oldLessonNumber = lessonNo
|
||||||
|
it.oldStartTime = startTime
|
||||||
|
it.oldEndTime = endTime
|
||||||
|
it.oldSubjectId = subjectId
|
||||||
|
it.oldTeacherId = teacherId
|
||||||
|
it.oldTeamId = teamId
|
||||||
|
it.oldClassroom = data.classrooms[classroomId]?.name
|
||||||
|
|
||||||
|
it.date = newDate
|
||||||
|
it.lessonNumber = newLessonNo
|
||||||
|
it.startTime = newStartTime
|
||||||
|
it.endTime = newEndTime
|
||||||
|
it.subjectId = newSubjectId
|
||||||
|
it.teacherId = newTeacherId
|
||||||
|
it.teamId = newTeamId
|
||||||
|
it.classroom = data.classrooms[newClassroomId]?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isSubstitution) {
|
||||||
|
// lesson change OR shifted lesson - target
|
||||||
|
val oldDate = lesson.getString("OrgDate")?.let { Date.fromY_m_d(it) } ?: return
|
||||||
|
val oldLessonNo = lesson.getInt("OrgLessonNo") ?: return
|
||||||
|
val oldStartTime = lesson.getString("OrgHourFrom")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
val oldEndTime = lesson.getString("OrgHourTo")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
val oldSubjectId = lesson.getJsonObject("OrgSubject")?.getLong("Id")
|
||||||
|
val oldTeacherId = lesson.getJsonObject("OrgTeacher")?.getLong("Id")
|
||||||
|
val oldClassroomId = lesson.getJsonObject("OrgClassroom")?.getLong("Id") ?: -1
|
||||||
|
val oldVirtualClassId = lesson.getJsonObject("OrgVirtualClass")?.getLong("Id")
|
||||||
|
val oldTeamId = lesson.getJsonObject("OrgClass")?.getLong("Id") ?: oldVirtualClassId
|
||||||
|
|
||||||
|
lessonObject.let {
|
||||||
|
it.type = if (lessonDate == oldDate && lessonNo == oldLessonNo) Lesson.TYPE_CHANGE else Lesson.TYPE_SHIFTED_TARGET
|
||||||
|
it.oldDate = oldDate
|
||||||
|
it.oldLessonNumber = oldLessonNo
|
||||||
|
it.oldStartTime = oldStartTime
|
||||||
|
it.oldEndTime = oldEndTime
|
||||||
|
it.oldSubjectId = oldSubjectId
|
||||||
|
it.oldTeacherId = oldTeacherId
|
||||||
|
it.oldTeamId = oldTeamId
|
||||||
|
it.oldClassroom = data.classrooms[oldClassroomId]?.name
|
||||||
|
|
||||||
|
it.date = lessonDate
|
||||||
|
it.lessonNumber = lessonNo
|
||||||
|
it.startTime = startTime
|
||||||
|
it.endTime = endTime
|
||||||
|
it.subjectId = subjectId
|
||||||
|
it.teacherId = teacherId
|
||||||
|
it.teamId = teamId
|
||||||
|
it.classroom = data.classrooms[classroomId]?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isCancelled) {
|
||||||
|
lessonObject.let {
|
||||||
|
it.type = Lesson.TYPE_CANCELLED
|
||||||
|
it.oldDate = lessonDate
|
||||||
|
it.oldLessonNumber = lessonNo
|
||||||
|
it.oldStartTime = startTime
|
||||||
|
it.oldEndTime = endTime
|
||||||
|
it.oldSubjectId = subjectId
|
||||||
|
it.oldTeacherId = teacherId
|
||||||
|
it.oldTeamId = teamId
|
||||||
|
it.oldClassroom = data.classrooms[classroomId]?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lessonObject.let {
|
||||||
|
it.type = Lesson.TYPE_NORMAL
|
||||||
|
it.date = lessonDate
|
||||||
|
it.lessonNumber = lessonNo
|
||||||
|
it.startTime = startTime
|
||||||
|
it.endTime = endTime
|
||||||
|
it.subjectId = subjectId
|
||||||
|
it.teacherId = teacherId
|
||||||
|
it.teamId = teamId
|
||||||
|
it.classroom = data.classrooms[classroomId]?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lessonObject.id = lessonObject.buildId()
|
||||||
|
|
||||||
|
val seen = profile.empty || lessonDate < Date.getToday()
|
||||||
|
|
||||||
|
if (lessonObject.type != Lesson.TYPE_NORMAL) {
|
||||||
|
data.metadataList.add(
|
||||||
|
Metadata(
|
||||||
|
profileId,
|
||||||
|
Metadata.TYPE_LESSON_CHANGE,
|
||||||
|
lessonObject.id,
|
||||||
|
seen,
|
||||||
|
seen,
|
||||||
|
System.currentTimeMillis()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
data.lessonNewList.add(lessonObject)
|
||||||
|
}}
|
||||||
|
}
|
@ -22,8 +22,8 @@ class LibrusApiUsers(override val data: DataLibrus,
|
|||||||
|
|
||||||
users?.forEach { user ->
|
users?.forEach { user ->
|
||||||
val id = user.getLong("Id") ?: return@forEach
|
val id = user.getLong("Id") ?: return@forEach
|
||||||
val firstName = user.getString("FirstName")?.fixWhiteSpaces() ?: ""
|
val firstName = user.getString("FirstName")?.fixName() ?: ""
|
||||||
val lastName = user.getString("LastName")?.fixWhiteSpaces() ?: ""
|
val lastName = user.getString("LastName")?.fixName() ?: ""
|
||||||
|
|
||||||
data.teacherList.put(id, Teacher(profileId, id, firstName, lastName))
|
data.teacherList.put(id, Teacher(profileId, id, firstName, lastName))
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-24
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.librus.data.messages
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.ERROR_FILE_DOWNLOAD
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.EXCEPTION_LIBRUS_MESSAGES_REQUEST
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent.Companion.TYPE_FINISHED
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent.Companion.TYPE_PROGRESS
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusMessages
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.get
|
||||||
|
import pl.szczodrzynski.edziennik.getString
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
class LibrusMessagesGetAttachment(
|
||||||
|
override val data: DataLibrus, val message: Message, val attachmentId: Long,
|
||||||
|
val attachmentName: String, val onSuccess: () -> Unit) : LibrusMessages(data), CoroutineScope {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "LibrusMessagesGetAttachment"
|
||||||
|
}
|
||||||
|
|
||||||
|
private var job = Job()
|
||||||
|
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Default
|
||||||
|
|
||||||
|
private var getAttachmentCheckKeyTries = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
messagesGet(TAG, "GetFileDownloadLink", parameters = mapOf(
|
||||||
|
"fileId" to attachmentId,
|
||||||
|
"msgId" to message.id,
|
||||||
|
"archive" to 0
|
||||||
|
)) { doc ->
|
||||||
|
val downloadLink = doc.select("response GetFileDownloadLink downloadLink").text()
|
||||||
|
val keyMatcher = Regexes.LIBRUS_ATTACHMENT_KEY.find(downloadLink)
|
||||||
|
|
||||||
|
if (keyMatcher != null) {
|
||||||
|
getAttachmentCheckKeyTries = 0
|
||||||
|
|
||||||
|
val attachmentKey = keyMatcher[1]
|
||||||
|
getAttachmentCheckKey(attachmentKey) {
|
||||||
|
downloadAttachment(attachmentKey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
|
||||||
|
.withApiResponse(doc.toString()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAttachmentCheckKey(attachmentKey: String, callback: () -> Unit) {
|
||||||
|
sandboxGet(TAG, "CSCheckKey",
|
||||||
|
parameters = mapOf("singleUseKey" to attachmentKey)) { json ->
|
||||||
|
|
||||||
|
when (json.getString("status")) {
|
||||||
|
"not_downloaded_yet" -> {
|
||||||
|
if (getAttachmentCheckKeyTries++ > 5) {
|
||||||
|
data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
|
||||||
|
.withApiResponse(json))
|
||||||
|
return@sandboxGet
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
delay(2000)
|
||||||
|
getAttachmentCheckKey(attachmentKey, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"ready" -> {
|
||||||
|
launch { callback() }
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
data.error(ApiError(TAG, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
|
||||||
|
.withApiResponse(json))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun downloadAttachment(attachmentKey: String) {
|
||||||
|
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
||||||
|
|
||||||
|
sandboxGetFile(TAG, "CSDownload&singleUseKey=$attachmentKey", targetFile, { file ->
|
||||||
|
|
||||||
|
val event = AttachmentGetEvent(
|
||||||
|
profileId,
|
||||||
|
message.id,
|
||||||
|
attachmentId,
|
||||||
|
TYPE_FINISHED,
|
||||||
|
file.absolutePath
|
||||||
|
)
|
||||||
|
|
||||||
|
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
|
||||||
|
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||||
|
|
||||||
|
EventBus.getDefault().post(event)
|
||||||
|
|
||||||
|
onSuccess()
|
||||||
|
|
||||||
|
}) { written, _ ->
|
||||||
|
val event = AttachmentGetEvent(
|
||||||
|
profileId,
|
||||||
|
message.id,
|
||||||
|
attachmentId,
|
||||||
|
TYPE_PROGRESS,
|
||||||
|
bytesWritten = written
|
||||||
|
)
|
||||||
|
|
||||||
|
EventBus.getDefault().post(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_MESSAGES_SENT
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusMessages
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusMessages
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||||
@ -20,7 +21,7 @@ import pl.szczodrzynski.edziennik.singleOrNull
|
|||||||
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
|
||||||
|
|
||||||
class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int = Message.TYPE_RECEIVED,
|
class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int = TYPE_RECEIVED,
|
||||||
archived: Boolean = false, val onSuccess: () -> Unit) : LibrusMessages(data) {
|
archived: Boolean = false, val onSuccess: () -> Unit) : LibrusMessages(data) {
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "LibrusMessagesGetList"
|
const val TAG = "LibrusMessagesGetList"
|
||||||
@ -28,7 +29,7 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val endpoint = when (type) {
|
val endpoint = when (type) {
|
||||||
Message.TYPE_RECEIVED -> "Inbox/action/GetList"
|
TYPE_RECEIVED -> "Inbox/action/GetList"
|
||||||
Message.TYPE_SENT -> "Outbox/action/GetList"
|
Message.TYPE_SENT -> "Outbox/action/GetList"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
@ -46,34 +47,38 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
|
|||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
val sentDate = Date.fromIso(element.select("sendDate").text().trim())
|
val sentDate = Date.fromIso(element.select("sendDate").text().trim())
|
||||||
var senderId: Long = -1
|
|
||||||
var receiverId: Long = -1
|
|
||||||
|
|
||||||
when (type) {
|
val recipientFirstName = element.select(when (type) {
|
||||||
Message.TYPE_RECEIVED -> {
|
TYPE_RECEIVED -> "senderFirstName"
|
||||||
val senderFirstName = element.select("senderFirstName").text().trim()
|
else -> "receiverFirstName"
|
||||||
val senderLastName = element.select("senderLastName").text().trim()
|
}).text().trim()
|
||||||
senderId = data.teacherList.singleOrNull {
|
|
||||||
it.name == senderFirstName && it.surname == senderLastName
|
|
||||||
}?.id ?: -1
|
|
||||||
}
|
|
||||||
|
|
||||||
Message.TYPE_SENT -> {
|
val recipientLastName = element.select(when (type) {
|
||||||
val receiverFirstName = element.select("receiverFirstName").text().trim()
|
TYPE_RECEIVED -> "senderLastName"
|
||||||
val receiverLastName = element.select("receiverLastName").text().trim()
|
else -> "receiverLastName"
|
||||||
receiverId = data.teacherList.singleOrNull {
|
}).text().trim()
|
||||||
it.name == receiverFirstName && it.surname == receiverLastName
|
|
||||||
}?.id ?: {
|
val recipientId = data.teacherList.singleOrNull {
|
||||||
val teacherObject = Teacher(
|
it.name == recipientFirstName && it.surname == recipientLastName
|
||||||
profileId,
|
}?.id ?: {
|
||||||
-1 * Utils.crc16("$receiverFirstName $receiverLastName".toByteArray()).toLong(),
|
val teacherObject = Teacher(
|
||||||
receiverFirstName,
|
profileId,
|
||||||
receiverLastName
|
-1 * Utils.crc16("$recipientFirstName $recipientLastName".toByteArray()).toLong(),
|
||||||
)
|
recipientFirstName,
|
||||||
data.teacherList.put(teacherObject.id, teacherObject)
|
recipientLastName
|
||||||
teacherObject.id
|
)
|
||||||
}.invoke()
|
data.teacherList.put(teacherObject.id, teacherObject)
|
||||||
}
|
teacherObject.id
|
||||||
|
}.invoke()
|
||||||
|
|
||||||
|
val senderId = when (type) {
|
||||||
|
TYPE_RECEIVED -> recipientId
|
||||||
|
else -> -1
|
||||||
|
}
|
||||||
|
|
||||||
|
val receiverId = when (type) {
|
||||||
|
TYPE_RECEIVED -> -1
|
||||||
|
else -> recipientId
|
||||||
}
|
}
|
||||||
|
|
||||||
val notified = when (type) {
|
val notified = when (type) {
|
||||||
@ -99,7 +104,7 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
|
|||||||
id
|
id
|
||||||
)
|
)
|
||||||
|
|
||||||
data.messageList.add(messageObject)
|
data.messageIgnoreList.add(messageObject)
|
||||||
data.messageRecipientList.add(messageRecipientObject)
|
data.messageRecipientList.add(messageRecipientObject)
|
||||||
data.metadataList.add(Metadata(
|
data.metadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
@ -112,7 +117,7 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (type) {
|
when (type) {
|
||||||
Message.TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
|
TYPE_RECEIVED -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_RECEIVED, SYNC_ALWAYS)
|
||||||
Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)
|
Message.TYPE_SENT -> data.setSyncNext(ENDPOINT_LIBRUS_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)
|
||||||
}
|
}
|
||||||
onSuccess()
|
onSuccess()
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.librus.data.messages
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.MessageGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusMessages
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.fixName
|
||||||
|
import pl.szczodrzynski.edziennik.singleOrNull
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
class LibrusMessagesGetMessage(
|
||||||
|
override val data: DataLibrus,
|
||||||
|
private val messageObject: MessageFull,
|
||||||
|
val onSuccess: () -> Unit
|
||||||
|
) : LibrusMessages(data) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "LibrusMessagesGetMessage"
|
||||||
|
}
|
||||||
|
|
||||||
|
init { data.profile?.also { profile ->
|
||||||
|
messagesGet(TAG, "GetMessage", parameters = mapOf(
|
||||||
|
"messageId" to messageObject.id,
|
||||||
|
"archive" to 0
|
||||||
|
)) { doc ->
|
||||||
|
val message = doc.select("response GetMessage data").first()
|
||||||
|
|
||||||
|
val body = Base64.decode(message.select("Message").text(), Base64.DEFAULT)
|
||||||
|
.toString(Charset.defaultCharset())
|
||||||
|
.replace("\n", "<br>")
|
||||||
|
.replace("<!\\[CDATA\\[", "")
|
||||||
|
.replace("]]>", "")
|
||||||
|
|
||||||
|
messageObject.apply {
|
||||||
|
this.body = body
|
||||||
|
|
||||||
|
clearAttachments()
|
||||||
|
message.select("attachments ArrayItem").forEach {
|
||||||
|
val attachmentId = it.select("id").text().toLong()
|
||||||
|
val attachmentName = it.select("filename").text()
|
||||||
|
addAttachment(attachmentId, attachmentName, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val messageRecipientList = mutableListOf<MessageRecipientFull>()
|
||||||
|
|
||||||
|
when (messageObject.type) {
|
||||||
|
TYPE_RECEIVED -> {
|
||||||
|
val senderLoginId = message.select("senderId").text()
|
||||||
|
data.teacherList.singleOrNull { it.id == messageObject.senderId }?.loginId = senderLoginId
|
||||||
|
|
||||||
|
val readDateText = message.select("readDate").text()
|
||||||
|
val readDate = when (readDateText.isNotEmpty()) {
|
||||||
|
true -> Date.fromIso(readDateText)
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val messageRecipientObject = MessageRecipientFull(
|
||||||
|
profileId,
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
readDate,
|
||||||
|
messageObject.id
|
||||||
|
)
|
||||||
|
|
||||||
|
messageRecipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong
|
||||||
|
|
||||||
|
messageRecipientList.add(messageRecipientObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_SENT -> {
|
||||||
|
|
||||||
|
message.select("receivers ArrayItem").forEach { receiver ->
|
||||||
|
val receiverFirstName = receiver.select("firstName").text().fixName()
|
||||||
|
val receiverLastName = receiver.select("lastName").text().fixName()
|
||||||
|
val receiverLoginId = receiver.select("receiverId").text()
|
||||||
|
|
||||||
|
val teacher = data.teacherList.singleOrNull { it.name == receiverFirstName && it.surname == receiverLastName }
|
||||||
|
val receiverId = teacher?.id ?: -1
|
||||||
|
teacher?.loginId = receiverLoginId
|
||||||
|
|
||||||
|
val readDateText = message.select("readed").text()
|
||||||
|
val readDate = when (readDateText.isNotEmpty()) {
|
||||||
|
true -> Date.fromIso(readDateText)
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val messageRecipientObject = MessageRecipientFull(
|
||||||
|
profileId,
|
||||||
|
receiverId,
|
||||||
|
-1,
|
||||||
|
readDate,
|
||||||
|
messageObject.id
|
||||||
|
)
|
||||||
|
|
||||||
|
messageRecipientObject.fullName = "$receiverFirstName $receiverLastName"
|
||||||
|
|
||||||
|
messageRecipientList.add(messageRecipientObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!messageObject.seen) {
|
||||||
|
data.messageMetadataList.add(Metadata(
|
||||||
|
messageObject.profileId,
|
||||||
|
Metadata.TYPE_MESSAGE,
|
||||||
|
messageObject.id,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
messageObject.addedDate
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
messageObject.recipients = messageRecipientList
|
||||||
|
data.messageRecipientList.addAll(messageRecipientList)
|
||||||
|
data.messageList.add(messageObject)
|
||||||
|
|
||||||
|
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
} ?: onSuccess()}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.api.v2.POST
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK
|
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusSynergia
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusSynergia
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.get
|
import pl.szczodrzynski.edziennik.get
|
||||||
@ -55,19 +56,18 @@ class LibrusSynergiaHomework(override val data: DataLibrus, val onSuccess: () ->
|
|||||||
val id = "/podglad/([0-9]+)'".toRegex().find(
|
val id = "/podglad/([0-9]+)'".toRegex().find(
|
||||||
elements[9].select("input").attr("onclick")
|
elements[9].select("input").attr("onclick")
|
||||||
)?.get(1)?.toLong() ?: return@forEachIndexed
|
)?.get(1)?.toLong() ?: return@forEachIndexed
|
||||||
val startTime = data.lessonList.singleOrNull {
|
|
||||||
it.weekDay == eventDate.weekDay && it.subjectId == subjectId
|
val lessons = data.db.timetableDao().getForDateNow(profileId, eventDate)
|
||||||
}?.startTime
|
val startTime = lessons.firstOrNull { it.subjectId == subjectId }?.startTime
|
||||||
|
|
||||||
val moreInfo = graphElements[2 * i + 1].select("td[title]")
|
val moreInfo = graphElements[2 * i + 1].select("td[title]")
|
||||||
.attr("title").trim()
|
.attr("title").trim()
|
||||||
val description = "Treść: (.*)".toRegex(RegexOption.DOT_MATCHES_ALL).find(moreInfo)
|
val description = "Treść: (.*)".toRegex(RegexOption.DOT_MATCHES_ALL).find(moreInfo)
|
||||||
?.get(1)?.replace("<br.*/>".toRegex(), "\n")?.trim()
|
?.get(1)?.replace("<br.*/>".toRegex(), "\n")?.trim()
|
||||||
|
|
||||||
val notified = when (profile?.empty) {
|
val seen = when (profile?.empty) {
|
||||||
true -> true
|
true -> true
|
||||||
false -> Date.getToday() < eventDate
|
else -> eventDate < Date.getToday()
|
||||||
else -> false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val eventObject = Event(
|
val eventObject = Event(
|
||||||
@ -89,13 +89,15 @@ class LibrusSynergiaHomework(override val data: DataLibrus, val onSuccess: () ->
|
|||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_HOMEWORK,
|
Metadata.TYPE_HOMEWORK,
|
||||||
id,
|
id,
|
||||||
notified,
|
seen,
|
||||||
notified,
|
seen,
|
||||||
addedDate
|
addedDate
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||||
|
|
||||||
// because this requires a synergia login (2 more requests) sync this every two hours or if explicit :D
|
// because this requires a synergia login (2 more requests) sync this every two hours or if explicit :D
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK, 2 * HOUR, DRAWER_ITEM_HOMEWORK)
|
data.setSyncNext(ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK, 2 * HOUR, DRAWER_ITEM_HOMEWORK)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
|
@ -3,6 +3,7 @@ package pl.szczodrzynski.edziennik.api.v2.librus.firstlogin
|
|||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.ERROR_NO_STUDENTS_IN_ACCOUNT
|
import pl.szczodrzynski.edziennik.api.v2.ERROR_NO_STUDENTS_IN_ACCOUNT
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.FAKE_LIBRUS_ACCOUNTS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LIBRUS_ACCOUNTS_URL
|
import pl.szczodrzynski.edziennik.api.v2.LIBRUS_ACCOUNTS_URL
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_MODE_LIBRUS_EMAIL
|
import pl.szczodrzynski.edziennik.api.v2.LOGIN_MODE_LIBRUS_EMAIL
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.FirstLoginFinishedEvent
|
import pl.szczodrzynski.edziennik.api.v2.events.FirstLoginFinishedEvent
|
||||||
@ -12,8 +13,8 @@ import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusPortal
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginApi
|
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginApi
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginPortal
|
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginPortal
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.api.AppError.CODE_LIBRUS_DISCONNECTED
|
import pl.szczodrzynski.edziennik.api.v2.models.AppError.CODE_LIBRUS_DISCONNECTED
|
||||||
import pl.szczodrzynski.edziennik.data.api.AppError.CODE_SYNERGIA_NOT_ACTIVATED
|
import pl.szczodrzynski.edziennik.api.v2.models.AppError.CODE_SYNERGIA_NOT_ACTIVATED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
|
|
||||||
class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
|
class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
@ -29,7 +30,7 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) {
|
if (data.loginStore.mode == LOGIN_MODE_LIBRUS_EMAIL) {
|
||||||
// email login: use Portal for account list
|
// email login: use Portal for account list
|
||||||
LibrusLoginPortal(data) {
|
LibrusLoginPortal(data) {
|
||||||
portal.portalGet(TAG, LIBRUS_ACCOUNTS_URL) { json, response ->
|
portal.portalGet(TAG, if (data.fakeLogin) FAKE_LIBRUS_ACCOUNTS else LIBRUS_ACCOUNTS_URL) { json, response ->
|
||||||
val accounts = json.getJsonArray("accounts")
|
val accounts = json.getJsonArray("accounts")
|
||||||
|
|
||||||
if (accounts == null || accounts.size() < 1) {
|
if (accounts == null || accounts.size() < 1) {
|
||||||
@ -88,4 +89,4 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,7 @@ import pl.szczodrzynski.edziennik.getInt
|
|||||||
import pl.szczodrzynski.edziennik.getString
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.net.HttpURLConnection.HTTP_BAD_REQUEST
|
import java.net.HttpURLConnection.*
|
||||||
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
|
|
||||||
|
|
||||||
class LibrusLoginApi {
|
class LibrusLoginApi {
|
||||||
companion object {
|
companion object {
|
||||||
@ -117,6 +116,13 @@ class LibrusLoginApi {
|
|||||||
|
|
||||||
private val tokenCallback = object : JsonCallbackHandler() {
|
private val tokenCallback = object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
|
if (response?.code() == HTTP_UNAVAILABLE) {
|
||||||
|
data.error(ApiError(TAG, ERROR_LIBRUS_API_MAINTENANCE)
|
||||||
|
.withApiResponse(json)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
.withResponse(response))
|
.withResponse(response))
|
||||||
@ -176,6 +182,7 @@ class LibrusLoginApi {
|
|||||||
.post()
|
.post()
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
|
.allowErrorCode(HTTP_UNAVAILABLE)
|
||||||
.callback(tokenCallback)
|
.callback(tokenCallback)
|
||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
|
@ -6,20 +6,57 @@ package pl.szczodrzynski.edziennik.api.v2.librus.login
|
|||||||
|
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
|
import im.wangchao.mhttp.body.MediaTypeUtils
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import java.io.StringWriter
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
import javax.xml.transform.OutputKeys
|
||||||
|
import javax.xml.transform.TransformerFactory
|
||||||
|
import javax.xml.transform.dom.DOMSource
|
||||||
|
import javax.xml.transform.stream.StreamResult
|
||||||
|
|
||||||
class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "LoginLibrusMessages"
|
private const val TAG = "LoginLibrusMessages"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val callback by lazy { object : TextCallbackHandler() {
|
||||||
|
override fun onSuccess(text: String?, response: Response?) {
|
||||||
|
val location = response?.headers()?.get("Location")
|
||||||
|
when {
|
||||||
|
location?.contains("MultiDomainLogon") == true -> loginWithSynergia(location)
|
||||||
|
location?.contains("AutoLogon") == true -> {
|
||||||
|
saveSessionId(response, text)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
text?.contains("<status>ok</status>") == true -> {
|
||||||
|
saveSessionId(response, text)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
text?.contains("<message>Niepoprawny login i/lub hasło.</message>") == true -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
|
||||||
|
text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
||||||
|
text?.contains("eAccessDeny") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||||
|
text?.contains("OffLine") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
|
||||||
|
text?.contains("<status>error</status>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
|
||||||
|
text?.contains("<type>eVarWhitThisNameNotExists</type>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||||
|
text?.contains("<error>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
init { run {
|
init { run {
|
||||||
if (data.profile == null) {
|
if (data.profile == null) {
|
||||||
data.error(ApiError(TAG, ERROR_PROFILE_MISSING))
|
data.error(ApiError(TAG, ERROR_PROFILE_MISSING))
|
||||||
@ -41,7 +78,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) {
|
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) {
|
||||||
loginWithSynergia()
|
loginWithSynergia()
|
||||||
}
|
}
|
||||||
else if (data.apiLogin != null && data.apiPassword != null && false) {
|
else if (data.apiLogin != null && data.apiPassword != null) {
|
||||||
loginWithCredentials()
|
loginWithCredentials()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -54,7 +91,44 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
* XML (Flash messages website) login method. Uses a Synergia login and password.
|
* XML (Flash messages website) login method. Uses a Synergia login and password.
|
||||||
*/
|
*/
|
||||||
private fun loginWithCredentials() {
|
private fun loginWithCredentials() {
|
||||||
|
d(TAG, "Request: Librus/Login/Messages - $LIBRUS_MESSAGES_URL/Login")
|
||||||
|
|
||||||
|
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||||
|
val doc = docBuilder.newDocument()
|
||||||
|
val serviceElement = doc.createElement("service")
|
||||||
|
val headerElement = doc.createElement("header")
|
||||||
|
val dataElement = doc.createElement("data")
|
||||||
|
val loginElement = doc.createElement("login")
|
||||||
|
loginElement.appendChild(doc.createTextNode(data.apiLogin))
|
||||||
|
dataElement.appendChild(loginElement)
|
||||||
|
val passwordElement = doc.createElement("password")
|
||||||
|
passwordElement.appendChild(doc.createTextNode(data.apiPassword))
|
||||||
|
dataElement.appendChild(passwordElement)
|
||||||
|
val keyStrokeElement = doc.createElement("KeyStroke")
|
||||||
|
val keysElement = doc.createElement("Keys")
|
||||||
|
val upElement = doc.createElement("Up")
|
||||||
|
keysElement.appendChild(upElement)
|
||||||
|
val downElement = doc.createElement("Down")
|
||||||
|
keysElement.appendChild(downElement)
|
||||||
|
keyStrokeElement.appendChild(keysElement)
|
||||||
|
dataElement.appendChild(keyStrokeElement)
|
||||||
|
serviceElement.appendChild(headerElement)
|
||||||
|
serviceElement.appendChild(dataElement)
|
||||||
|
doc.appendChild(serviceElement)
|
||||||
|
val transformer = TransformerFactory.newInstance().newTransformer()
|
||||||
|
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
|
||||||
|
val stringWriter = StringWriter()
|
||||||
|
transformer.transform(DOMSource(doc), StreamResult(stringWriter))
|
||||||
|
val requestXml = stringWriter.toString()
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url("$LIBRUS_MESSAGES_URL/Login")
|
||||||
|
.userAgent(SYNERGIA_USER_AGENT)
|
||||||
|
.setTextBody(requestXml, MediaTypeUtils.APPLICATION_XML)
|
||||||
|
.post()
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,37 +137,6 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
private fun loginWithSynergia(url: String = "https://synergia.librus.pl/wiadomosci2") {
|
private fun loginWithSynergia(url: String = "https://synergia.librus.pl/wiadomosci2") {
|
||||||
d(TAG, "Request: Librus/Login/Messages - $url")
|
d(TAG, "Request: Librus/Login/Messages - $url")
|
||||||
|
|
||||||
val callback = object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
val location = response?.headers()?.get("Location")
|
|
||||||
when {
|
|
||||||
location?.contains("MultiDomainLogon") == true -> loginWithSynergia(location)
|
|
||||||
location?.contains("AutoLogon") == true -> {
|
|
||||||
var sessionId = data.app.cookieJar.getCookie("wiadomosci.librus.pl", "DZIENNIKSID")
|
|
||||||
sessionId = sessionId?.replace("-MAINT", "")
|
|
||||||
if (sessionId == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(text))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data.messagesSessionId = sessionId
|
|
||||||
data.messagesSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
text?.contains("eAccessDeny") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
|
||||||
text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Request.builder()
|
Request.builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.userAgent(SYNERGIA_USER_AGENT)
|
.userAgent(SYNERGIA_USER_AGENT)
|
||||||
@ -103,4 +146,18 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveSessionId(response: Response?, text: String?) {
|
||||||
|
var sessionId = data.app.cookieJar.getCookie("wiadomosci.librus.pl", "DZIENNIKSID")
|
||||||
|
sessionId = sessionId?.replace("-MAINT", "") // dunno what's this
|
||||||
|
sessionId = sessionId?.replace("MAINT", "") // dunno what's this
|
||||||
|
if (sessionId == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID)
|
||||||
|
.withResponse(response)
|
||||||
|
.withApiResponse(text))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.messagesSessionId = sessionId
|
||||||
|
data.messagesSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,14 +7,15 @@ import im.wangchao.mhttp.Response
|
|||||||
import im.wangchao.mhttp.body.MediaTypeUtils
|
import im.wangchao.mhttp.body.MediaTypeUtils
|
||||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.getInt
|
||||||
|
import pl.szczodrzynski.edziennik.getString
|
||||||
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
|
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
@ -42,7 +43,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data.app.cookieJar.clearForDomain("portal.librus.pl")
|
data.app.cookieJar.clearForDomain("portal.librus.pl")
|
||||||
authorize(LIBRUS_AUTHORIZE_URL)
|
authorize(if (data.fakeLogin) FAKE_LIBRUS_AUTHORIZE else LIBRUS_AUTHORIZE_URL)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@ -86,10 +87,10 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun login(csrfToken: String) {
|
private fun login(csrfToken: String) {
|
||||||
d(TAG, "Request: Librus/Login/Portal - $LIBRUS_LOGIN_URL")
|
d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL}")
|
||||||
|
|
||||||
Request.builder()
|
Request.builder()
|
||||||
.url(LIBRUS_LOGIN_URL)
|
.url(if (data.fakeLogin) FAKE_LIBRUS_LOGIN else LIBRUS_LOGIN_URL)
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
.userAgent(LIBRUS_USER_AGENT)
|
||||||
.addParameter("email", data.portalEmail)
|
.addParameter("email", data.portalEmail)
|
||||||
.addParameter("password", data.portalPassword)
|
.addParameter("password", data.portalPassword)
|
||||||
@ -98,6 +99,14 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
.post()
|
.post()
|
||||||
.callback(object : JsonCallbackHandler() {
|
.callback(object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response) {
|
override fun onSuccess(json: JsonObject?, response: Response) {
|
||||||
|
val location = response.headers()?.get("Location")
|
||||||
|
if (location == "http://localhost/bar?command=close") {
|
||||||
|
data.error(ApiError(TAG, ERROR_LIBRUS_PORTAL_MAINTENANCE)
|
||||||
|
.withApiResponse(json)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
|
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED)
|
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED)
|
||||||
@ -119,7 +128,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
|
|
||||||
override fun onFailure(response: Response, throwable: Throwable) {
|
override fun onFailure(response: Response, throwable: Throwable) {
|
||||||
if (response.code() == 403 || response.code() == 401) {
|
if (response.code() == 403 || response.code() == 401) {
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_DATA_INVALID)
|
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN)
|
||||||
.withResponse(response)
|
.withResponse(response)
|
||||||
.withThrowable(throwable))
|
.withThrowable(throwable))
|
||||||
return
|
return
|
||||||
@ -135,7 +144,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
|
|
||||||
private var refreshTokenFailed = false
|
private var refreshTokenFailed = false
|
||||||
private fun accessToken(code: String?, refreshToken: String?) {
|
private fun accessToken(code: String?, refreshToken: String?) {
|
||||||
d(TAG, "Request: Librus/Login/Portal - $LIBRUS_TOKEN_URL")
|
d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_TOKEN else LIBRUS_TOKEN_URL}")
|
||||||
|
|
||||||
val onSuccess = { json: JsonObject, response: Response? ->
|
val onSuccess = { json: JsonObject, response: Response? ->
|
||||||
data.portalAccessToken = json.getString("access_token")
|
data.portalAccessToken = json.getString("access_token")
|
||||||
@ -204,7 +213,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Request.builder()
|
Request.builder()
|
||||||
.url(LIBRUS_TOKEN_URL)
|
.url(if (data.fakeLogin) FAKE_LIBRUS_TOKEN else LIBRUS_TOKEN_URL)
|
||||||
.userAgent(LIBRUS_USER_AGENT)
|
.userAgent(LIBRUS_USER_AGENT)
|
||||||
.addParams(params)
|
.addParams(params)
|
||||||
.post()
|
.post()
|
||||||
|
@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.api.v2.librus.login
|
|||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
@ -16,7 +15,6 @@ import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.getString
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
|
|
||||||
@ -86,6 +84,13 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
|
|||||||
val callback = object : TextCallbackHandler() {
|
val callback = object : TextCallbackHandler() {
|
||||||
override fun onSuccess(json: String?, response: Response?) {
|
override fun onSuccess(json: String?, response: Response?) {
|
||||||
val location = response?.headers()?.get("Location")
|
val location = response?.headers()?.get("Location")
|
||||||
|
if (location?.endsWith("przerwa_techniczna") == true) {
|
||||||
|
data.error(ApiError(TAG, ERROR_LIBRUS_SYNERGIA_MAINTENANCE)
|
||||||
|
.withApiResponse(json)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (location?.endsWith("centrum_powiadomien") == true) {
|
if (location?.endsWith("centrum_powiadomien") == true) {
|
||||||
val sessionId = data.app.cookieJar.getCookie("synergia.librus.pl", "DZIENNIKSID")
|
val sessionId = data.app.cookieJar.getCookie("synergia.librus.pl", "DZIENNIKSID")
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
|
@ -43,7 +43,7 @@ class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () ->
|
|||||||
val accountLogin = data.apiLogin ?: return false
|
val accountLogin = data.apiLogin ?: return false
|
||||||
data.portalAccessToken ?: return false
|
data.portalAccessToken ?: return false
|
||||||
|
|
||||||
d(TAG, "Request: Librus/SynergiaTokenExtractor - $LIBRUS_ACCOUNT_URL$accountLogin")
|
d(TAG, "Request: Librus/SynergiaTokenExtractor - ${if (data.fakeLogin) FAKE_LIBRUS_ACCOUNT else LIBRUS_ACCOUNT_URL}$accountLogin")
|
||||||
|
|
||||||
val onSuccess = { json: JsonObject, response: Response? ->
|
val onSuccess = { json: JsonObject, response: Response? ->
|
||||||
// synergiaAccount is executed when a synergia token needs a refresh
|
// synergiaAccount is executed when a synergia token needs a refresh
|
||||||
@ -67,7 +67,7 @@ class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
portalGet(TAG, LIBRUS_ACCOUNT_URL+accountLogin, onSuccess = onSuccess)
|
portalGet(TAG, (if (data.fakeLogin) FAKE_LIBRUS_ACCOUNT else LIBRUS_ACCOUNT_URL)+accountLogin, onSuccess = onSuccess)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,17 +4,23 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.mobidziennik
|
package pl.szczodrzynski.edziennik.api.v2.mobidziennik
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikData
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikData
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikWebGetAttachment
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikWebGetMessage
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.firstlogin.MobidziennikFirstLogin
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.firstlogin.MobidziennikFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLogin
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLogin
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLoginWeb
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennikLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennikLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.prepare
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
@ -48,7 +54,8 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||||
|
data.arguments = arguments
|
||||||
data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, featureIds, viewId)
|
data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, featureIds, viewId)
|
||||||
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
@ -59,14 +66,26 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(messageId: Int) {
|
override fun getMessage(message: MessageFull) {
|
||||||
|
MobidziennikLoginWeb(data) {
|
||||||
|
MobidziennikWebGetMessage(data, message) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {
|
override fun markAllAnnouncementsAsRead() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||||
|
MobidziennikLoginWeb(data) {
|
||||||
|
MobidziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun firstLogin() {
|
override fun firstLogin() {
|
||||||
MobidziennikFirstLogin(data) {
|
MobidziennikFirstLogin(data) {
|
||||||
completed()
|
completed()
|
||||||
|
@ -21,10 +21,10 @@ const val ENDPOINT_MOBIDZIENNIK_API2_MAIN = 3000
|
|||||||
|
|
||||||
val MobidziennikFeatures = listOf(
|
val MobidziennikFeatures = listOf(
|
||||||
// always synced
|
// always synced
|
||||||
/*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ALWAYS_NEEDED, listOf(
|
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ALWAYS_NEEDED, listOf(
|
||||||
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
|
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
|
||||||
ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL to LOGIN_METHOD_MOBIDZIENNIK_WEB
|
ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL to LOGIN_METHOD_MOBIDZIENNIK_WEB
|
||||||
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),*/
|
), 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(
|
||||||
|
@ -6,12 +6,14 @@ package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data
|
|||||||
|
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
|
import im.wangchao.mhttp.callback.FileCallbackHandler
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
open class MobidziennikWeb(open val data: DataMobidziennik) {
|
open class MobidziennikWeb(open val data: DataMobidziennik) {
|
||||||
companion object {
|
companion object {
|
||||||
@ -93,4 +95,77 @@ open class MobidziennikWeb(open val data: DataMobidziennik) {
|
|||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun webGetFile(tag: String, action: String, targetFile: File, onSuccess: (file: File) -> Unit,
|
||||||
|
onProgress: (written: Long, total: Long) -> Unit) {
|
||||||
|
val url = "https://${data.loginServerName}.mobidziennik.pl$action"
|
||||||
|
|
||||||
|
d(tag, "Request: Mobidziennik/Web - $url")
|
||||||
|
|
||||||
|
if (data.webSessionKey == null) {
|
||||||
|
data.error(TAG, ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (data.webSessionValue == null) {
|
||||||
|
data.error(TAG, ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (data.webServerId == null) {
|
||||||
|
data.error(TAG, ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val callback = object : FileCallbackHandler(targetFile) {
|
||||||
|
override fun onSuccess(file: File?, response: Response?) {
|
||||||
|
if (file == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
onSuccess(file)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
data.error(ApiError(tag, EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
|
||||||
|
try {
|
||||||
|
onProgress(bytesWritten, bytesTotal)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
data.error(ApiError(tag, EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST)
|
||||||
|
.withThrowable(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.app.cookieJar.saveFromResponse(null, listOf(
|
||||||
|
Cookie.Builder()
|
||||||
|
.name(data.webSessionKey!!)
|
||||||
|
.value(data.webSessionValue!!)
|
||||||
|
.domain("${data.loginServerName}.mobidziennik.pl")
|
||||||
|
.secure().httpOnly().build(),
|
||||||
|
Cookie.Builder()
|
||||||
|
.name("SERVERID")
|
||||||
|
.value(data.webServerId!!)
|
||||||
|
.domain("${data.loginServerName}.mobidziennik.pl")
|
||||||
|
.secure().httpOnly().build()
|
||||||
|
))
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url(url)
|
||||||
|
.userAgent(MOBIDZIENNIK_USER_AGENT)
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.api
|
|||||||
import androidx.core.util.contains
|
import androidx.core.util.contains
|
||||||
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
@ -74,5 +75,7 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.api
|
|||||||
|
|
||||||
import androidx.core.util.contains
|
import androidx.core.util.contains
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
@ -53,5 +54,7 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.api
|
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.api
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.App.profileId
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||||
import pl.szczodrzynski.edziennik.getById
|
import pl.szczodrzynski.edziennik.getById
|
||||||
@ -25,7 +24,7 @@ class MobidziennikApiTeams(val data: DataMobidziennik, tableTeams: List<String>?
|
|||||||
val teacherId = cols[4].toLongOrNull() ?: -1
|
val teacherId = cols[4].toLongOrNull() ?: -1
|
||||||
|
|
||||||
val teamObject = Team(
|
val teamObject = Team(
|
||||||
profileId,
|
data.profileId,
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
|
@ -5,15 +5,103 @@
|
|||||||
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.api
|
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.api
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.Lesson
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
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.Time
|
||||||
|
|
||||||
class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
|
class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
|
||||||
init {
|
init { data.profile?.also { profile ->
|
||||||
for (lessonStr in rows) {
|
val lessons = rows.filterNot { it.isEmpty() }.map { it.split("|") }
|
||||||
|
|
||||||
|
val dataStart = Date.getToday()
|
||||||
|
val dataEnd = dataStart.clone().stepForward(0, 0, 7 + (6 - dataStart.weekDay))
|
||||||
|
|
||||||
|
data.toRemove.add(DataRemoveModel.Timetable.between(dataStart.clone(), dataEnd))
|
||||||
|
|
||||||
|
val dataDays = mutableListOf<Int>()
|
||||||
|
while (dataStart <= dataEnd) {
|
||||||
|
dataDays += dataStart.value
|
||||||
|
dataStart.stepForward(0, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (lesson in lessons) {
|
||||||
|
val date = Date.fromYmd(lesson[2])
|
||||||
|
val startTime = Time.fromYmdHm(lesson[3])
|
||||||
|
val endTime = Time.fromYmdHm(lesson[4])
|
||||||
|
|
||||||
|
dataDays.remove(date.value)
|
||||||
|
|
||||||
|
val subjectId = data.subjectList.singleOrNull { it.longName == lesson[5] }?.id ?: -1
|
||||||
|
val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == (lesson[7]+" "+lesson[6]).fixName() }?.id ?: -1
|
||||||
|
val teamId = data.teamList.singleOrNull { it.name == lesson[8]+lesson[9] }?.id ?: -1
|
||||||
|
val classroom = lesson[11]
|
||||||
|
|
||||||
|
Lesson(data.profileId, -1).also {
|
||||||
|
when (lesson[1]) {
|
||||||
|
"plan_lekcji", "lekcja" -> {
|
||||||
|
it.type = Lesson.TYPE_NORMAL
|
||||||
|
it.date = date
|
||||||
|
it.startTime = startTime
|
||||||
|
it.endTime = endTime
|
||||||
|
it.subjectId = subjectId
|
||||||
|
it.teacherId = teacherId
|
||||||
|
it.teamId = teamId
|
||||||
|
it.classroom = classroom
|
||||||
|
}
|
||||||
|
"lekcja_odwolana" -> {
|
||||||
|
it.type = Lesson.TYPE_CANCELLED
|
||||||
|
it.date = date
|
||||||
|
it.startTime = startTime
|
||||||
|
it.endTime = endTime
|
||||||
|
it.oldSubjectId = subjectId
|
||||||
|
//it.oldTeacherId = teacherId
|
||||||
|
it.oldTeamId = teamId
|
||||||
|
//it.oldClassroom = classroom
|
||||||
|
}
|
||||||
|
"zastepstwo" -> {
|
||||||
|
it.type = Lesson.TYPE_CHANGE
|
||||||
|
it.date = date
|
||||||
|
it.startTime = startTime
|
||||||
|
it.endTime = endTime
|
||||||
|
it.subjectId = subjectId
|
||||||
|
it.teacherId = teacherId
|
||||||
|
it.teamId = teamId
|
||||||
|
it.classroom = classroom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it.id = it.buildId()
|
||||||
|
|
||||||
|
val seen = profile.empty || date < Date.getToday()
|
||||||
|
|
||||||
|
if (it.type != Lesson.TYPE_NORMAL) {
|
||||||
|
data.metadataList.add(
|
||||||
|
Metadata(
|
||||||
|
data.profileId,
|
||||||
|
Metadata.TYPE_LESSON_CHANGE,
|
||||||
|
it.id,
|
||||||
|
seen,
|
||||||
|
seen,
|
||||||
|
System.currentTimeMillis()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
data.lessonNewList += it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (day in dataDays) {
|
||||||
|
val lessonDate = Date.fromValue(day)
|
||||||
|
data.lessonNewList += Lesson(data.profileId, lessonDate.value.toLong()).apply {
|
||||||
|
type = Lesson.TYPE_NO_LESSONS
|
||||||
|
date = lessonDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for (lessonStr in rows) {
|
||||||
if (lessonStr.isNotEmpty()) {
|
if (lessonStr.isNotEmpty()) {
|
||||||
val lesson = lessonStr.split("|")
|
val lesson = lessonStr.split("|")
|
||||||
|
|
||||||
@ -76,9 +164,9 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
|
|||||||
if (originalLesson == null) {
|
if (originalLesson == null) {
|
||||||
// original lesson doesn't exist, save a new addition
|
// original lesson doesn't exist, save a new addition
|
||||||
// TODO
|
// TODO
|
||||||
/*if (!RegisterLessonChange.existsAddition(app.profile, registerLessonChange)) {
|
*//*if (!RegisterLessonChange.existsAddition(app.profile, registerLessonChange)) {
|
||||||
app.profile.timetable.addLessonAddition(registerLessonChange);
|
app.profile.timetable.addLessonAddition(registerLessonChange);
|
||||||
}*/
|
}*//*
|
||||||
} else {
|
} else {
|
||||||
// original lesson exists, so we need to compare them
|
// original lesson exists, so we need to compare them
|
||||||
if (!lessonChange.matches(originalLesson)) {
|
if (!lessonChange.matches(originalLesson)) {
|
||||||
@ -108,6 +196,6 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-28.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class MobidziennikWebGetAttachment(
|
||||||
|
override val data: DataMobidziennik, val message: Message, val attachmentId: Long,
|
||||||
|
val attachmentName: String, val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MobidziennikWebGetAttachment"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
||||||
|
|
||||||
|
val typeUrl = if (message.type == Message.TYPE_SENT)
|
||||||
|
"wiadwyslana"
|
||||||
|
else
|
||||||
|
"wiadodebrana"
|
||||||
|
|
||||||
|
webGetFile(TAG, "/dziennik/$typeUrl/?id=${message.id}&zalacznik=$attachmentId", targetFile, { file ->
|
||||||
|
|
||||||
|
val event = AttachmentGetEvent(
|
||||||
|
profileId,
|
||||||
|
message.id,
|
||||||
|
attachmentId,
|
||||||
|
AttachmentGetEvent.TYPE_FINISHED,
|
||||||
|
file.absolutePath
|
||||||
|
)
|
||||||
|
|
||||||
|
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
|
||||||
|
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||||
|
|
||||||
|
EventBus.getDefault().post(event)
|
||||||
|
|
||||||
|
onSuccess()
|
||||||
|
|
||||||
|
}) { written, _ ->
|
||||||
|
// TODO make use of bytesTotal
|
||||||
|
val event = AttachmentGetEvent(
|
||||||
|
profileId,
|
||||||
|
message.id,
|
||||||
|
attachmentId,
|
||||||
|
AttachmentGetEvent.TYPE_PROGRESS,
|
||||||
|
bytesWritten = written
|
||||||
|
)
|
||||||
|
|
||||||
|
EventBus.getDefault().post(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.events.MessageGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.get
|
||||||
|
import pl.szczodrzynski.edziennik.singleOrNull
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.monthFromName
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
|
class MobidziennikWebGetMessage(
|
||||||
|
override val data: DataMobidziennik,
|
||||||
|
private val message: MessageFull,
|
||||||
|
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MobidziennikWebGetMessage"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val typeUrl = if (message.type == Message.TYPE_SENT)
|
||||||
|
"wiadwyslana"
|
||||||
|
else
|
||||||
|
"wiadodebrana"
|
||||||
|
webGet(TAG, "/dziennik/$typeUrl/?id=${message.id}") { text ->
|
||||||
|
MobidziennikLuckyNumberExtractor(data, text)
|
||||||
|
|
||||||
|
val messageRecipientList = mutableListOf<MessageRecipientFull>()
|
||||||
|
|
||||||
|
val doc = Jsoup.parse(text)
|
||||||
|
|
||||||
|
val content = doc.select("#content").first()
|
||||||
|
|
||||||
|
val body = content.select(".wiadomosc_tresc").first()
|
||||||
|
|
||||||
|
if (message.type == TYPE_RECEIVED) {
|
||||||
|
var readDate = System.currentTimeMillis()
|
||||||
|
Regexes.MOBIDZIENNIK_MESSAGE_READ_DATE.find(body.html())?.let {
|
||||||
|
val date = Date(
|
||||||
|
it[3].toIntOrNull() ?: 2019,
|
||||||
|
monthFromName(it[2]),
|
||||||
|
it[1].toIntOrNull() ?: 1
|
||||||
|
)
|
||||||
|
val time = Time.fromH_m_s(
|
||||||
|
it[4] // TODO blank string safety
|
||||||
|
)
|
||||||
|
readDate = date.combineWith(time)
|
||||||
|
}
|
||||||
|
|
||||||
|
val recipient = MessageRecipientFull(
|
||||||
|
profileId,
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
readDate,
|
||||||
|
message.id
|
||||||
|
)
|
||||||
|
|
||||||
|
recipient.fullName = profile?.accountNameLong ?: profile?.studentNameLong
|
||||||
|
|
||||||
|
messageRecipientList.add(recipient)
|
||||||
|
} else {
|
||||||
|
message.senderId = -1
|
||||||
|
message.senderReplyId = -1
|
||||||
|
|
||||||
|
content.select("table.spis tr:has(td)")?.forEach { recipientEl ->
|
||||||
|
val senderEl = recipientEl.select("td:eq(0)").first()
|
||||||
|
val senderName = senderEl.text()
|
||||||
|
|
||||||
|
val teacher = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }
|
||||||
|
val receiverId = teacher?.id ?: -1
|
||||||
|
|
||||||
|
var readDate = 0L
|
||||||
|
val isReadEl = recipientEl.select("td:eq(2)").first()
|
||||||
|
if (isReadEl.ownText() != "NIE") {
|
||||||
|
val readDateEl = recipientEl.select("td:eq(3) small").first()
|
||||||
|
Regexes.MOBIDZIENNIK_MESSAGE_SENT_READ_DATE.find(readDateEl.ownText())?.let {
|
||||||
|
val date = Date(
|
||||||
|
it[3].toIntOrNull() ?: 2019,
|
||||||
|
monthFromName(it[2]),
|
||||||
|
it[1].toIntOrNull() ?: 1
|
||||||
|
)
|
||||||
|
val time = Time.fromH_m_s(
|
||||||
|
it[4] // TODO blank string safety
|
||||||
|
)
|
||||||
|
readDate = date.combineWith(time)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val recipient = MessageRecipientFull(
|
||||||
|
profileId,
|
||||||
|
receiverId,
|
||||||
|
-1,
|
||||||
|
readDate,
|
||||||
|
message.id
|
||||||
|
)
|
||||||
|
|
||||||
|
recipient.fullName = teacher?.fullName ?: "?"
|
||||||
|
|
||||||
|
messageRecipientList.add(recipient)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this line removes the sender and read date details
|
||||||
|
body.select("div").remove()
|
||||||
|
|
||||||
|
// this needs to be at the end
|
||||||
|
message.apply {
|
||||||
|
this.body = body.html()
|
||||||
|
|
||||||
|
clearAttachments()
|
||||||
|
content.select("ul li").map { it.select("a").first() }.forEach {
|
||||||
|
val attachmentName = it.ownText()
|
||||||
|
Regexes.MOBIDZIENNIK_MESSAGE_ATTACHMENT.find(it.outerHtml())?.let { match ->
|
||||||
|
val attachmentId = match[1].toLong()
|
||||||
|
var size = match[2].toFloatOrNull() ?: -1f
|
||||||
|
when (match[3]) {
|
||||||
|
"K" -> size *= 1024f
|
||||||
|
"M" -> size *= 1024f * 1024f
|
||||||
|
"G" -> size *= 1024f * 1024f * 1024f
|
||||||
|
}
|
||||||
|
message.addAttachment(attachmentId, attachmentName, size.toLong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message.seen) { // TODO discover why this monstrosity instead of MetadataDao.setSeen
|
||||||
|
data.messageMetadataList.add(Metadata(
|
||||||
|
message.profileId,
|
||||||
|
Metadata.TYPE_MESSAGE,
|
||||||
|
message.id,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
message.addedDate
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
message.recipients = messageRecipientList
|
||||||
|
data.messageRecipientList.addAll(messageRecipientList)
|
||||||
|
data.messageList.add(message)
|
||||||
|
|
||||||
|
EventBus.getDefault().postSticky(MessageGetEvent(message))
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -96,13 +96,17 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
|
|||||||
if (Regexes.MOBIDZIENNIK_GRADES_COUNT_TO_AVG.containsMatchIn(html)) {
|
if (Regexes.MOBIDZIENNIK_GRADES_COUNT_TO_AVG.containsMatchIn(html)) {
|
||||||
Regexes.MOBIDZIENNIK_GRADES_DETAILS.find(html)?.let { match ->
|
Regexes.MOBIDZIENNIK_GRADES_DETAILS.find(html)?.let { match ->
|
||||||
val gradeName = match[1]
|
val gradeName = match[1]
|
||||||
val gradeDescription = match[2]
|
var gradeDescription = match[2]
|
||||||
val gradeValue = match[3].toFloatOrNull() ?: 0.0f
|
val gradeValue = match[3].toFloatOrNull() ?: 0.0f
|
||||||
val teacherName = match[4].fixWhiteSpaces()
|
val teacherName = match[4].fixWhiteSpaces()
|
||||||
|
|
||||||
val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1
|
val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1
|
||||||
val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1
|
val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1
|
||||||
|
|
||||||
|
if (match[5].isNotEmpty()) {
|
||||||
|
gradeDescription += "\n"+match[5].replace("<br>", "\n")
|
||||||
|
}
|
||||||
|
|
||||||
val gradeObject = Grade(
|
val gradeObject = Grade(
|
||||||
profileId,
|
profileId,
|
||||||
gradeId,
|
gradeId,
|
||||||
|
@ -8,9 +8,7 @@ import org.jsoup.Jsoup
|
|||||||
import pl.szczodrzynski.edziennik.DAY
|
import pl.szczodrzynski.edziennik.DAY
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||||
@ -79,7 +77,7 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
|
|||||||
-1
|
-1
|
||||||
)
|
)
|
||||||
|
|
||||||
data.messageList.add(message)
|
data.messageIgnoreList.add(message)
|
||||||
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate))
|
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
|||||||
if (hasAttachments)
|
if (hasAttachments)
|
||||||
message.setHasAttachments()
|
message.setHasAttachments()
|
||||||
|
|
||||||
data.messageList.add(message)
|
data.messageIgnoreList.add(message)
|
||||||
data.messageMetadataList.add(
|
data.messageMetadataList.add(
|
||||||
Metadata(
|
Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
|
@ -91,7 +91,7 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
|
|||||||
.addParameter("ip", data.app.deviceId)
|
.addParameter("ip", data.app.deviceId)
|
||||||
.addParameter("login", data.loginUsername)
|
.addParameter("login", data.loginUsername)
|
||||||
.addParameter("haslo", data.loginPassword)
|
.addParameter("haslo", data.loginPassword)
|
||||||
.addParameter("token", data.app.appConfig.fcmTokens[LOGIN_TYPE_MOBIDZIENNIK]?.first)
|
.addParameter("token", data.app.config.sync.tokenMobidziennik)
|
||||||
.post()
|
.post()
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
.build()
|
.build()
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.models
|
package pl.szczodrzynski.edziennik.api.v2.models
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
import pl.szczodrzynski.edziennik.data.api.AppError
|
|
||||||
|
|
||||||
class ApiError(val tag: String, val errorCode: Int) {
|
class ApiError(val tag: String, val errorCode: Int) {
|
||||||
var profileId: Int? = null
|
var profileId: Int? = null
|
||||||
@ -52,9 +52,18 @@ class ApiError(val tag: String, val errorCode: Int) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getStringReason(context: Context): String {
|
||||||
|
return context.resources.getIdentifier("error_${errorCode}_reason", "string", context.packageName).let {
|
||||||
|
if (it != 0)
|
||||||
|
context.getString(it)
|
||||||
|
else
|
||||||
|
"?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "ApiError(tag='$tag', errorCode=$errorCode, profileId=$profileId, throwable=$throwable, apiResponse=$apiResponse, request=$request, response=$response, isCritical=$isCritical)"
|
return "ApiError(tag='$tag', errorCode=$errorCode, profileId=$profileId, throwable=$throwable, apiResponse=$apiResponse, request=$request, response=$response, isCritical=$isCritical)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api;
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-26
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.models;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
@ -10,7 +10,7 @@ import pl.szczodrzynski.edziennik.api.v2.DataNotifications
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.EXCEPTION_NOTIFY_AND_SYNC
|
import pl.szczodrzynski.edziennik.api.v2.EXCEPTION_NOTIFY_AND_SYNC
|
||||||
import pl.szczodrzynski.edziennik.api.v2.ServerSync
|
import pl.szczodrzynski.edziennik.api.v2.ServerSync
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EndpointCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EndpointCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.AppError.*
|
import pl.szczodrzynski.edziennik.api.v2.models.AppError.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement
|
import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
||||||
@ -60,6 +60,8 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
val profileId
|
val profileId
|
||||||
get() = profile?.id ?: -1
|
get() = profile?.id ?: -1
|
||||||
|
|
||||||
|
var arguments: JsonObject? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A callback passed to all [Feature]s and [LoginMethod]s
|
* A callback passed to all [Feature]s and [LoginMethod]s
|
||||||
*/
|
*/
|
||||||
@ -133,23 +135,20 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
mTeamClass = value
|
mTeamClass = value
|
||||||
}
|
}
|
||||||
|
|
||||||
var lessonsToRemove: DataRemoveModel? = null
|
var toRemove = mutableListOf<DataRemoveModel>()
|
||||||
|
|
||||||
val lessonList = mutableListOf<Lesson>()
|
val lessonList = mutableListOf<Lesson>()
|
||||||
val lessonChangeList = mutableListOf<LessonChange>()
|
val lessonChangeList = mutableListOf<LessonChange>()
|
||||||
|
val lessonNewList = mutableListOf<pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson>()
|
||||||
|
|
||||||
var gradesToRemove: DataRemoveModel? = null
|
|
||||||
val gradeList = mutableListOf<Grade>()
|
val gradeList = mutableListOf<Grade>()
|
||||||
|
|
||||||
var eventsToRemove: DataRemoveModel? = null
|
|
||||||
val eventList = mutableListOf<Event>()
|
val eventList = mutableListOf<Event>()
|
||||||
|
|
||||||
var noticesToRemove: DataRemoveModel? = null
|
|
||||||
val noticeList = mutableListOf<Notice>()
|
val noticeList = mutableListOf<Notice>()
|
||||||
|
|
||||||
var attendancesToRemove: DataRemoveModel? = null
|
|
||||||
val attendanceList = mutableListOf<Attendance>()
|
val attendanceList = mutableListOf<Attendance>()
|
||||||
|
|
||||||
var announcementsToRemove: DataRemoveModel? = null
|
|
||||||
val announcementList = mutableListOf<Announcement>()
|
val announcementList = mutableListOf<Announcement>()
|
||||||
|
|
||||||
val luckyNumberList = mutableListOf<LuckyNumber>()
|
val luckyNumberList = mutableListOf<LuckyNumber>()
|
||||||
@ -157,6 +156,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
val teacherAbsenceList = mutableListOf<TeacherAbsence>()
|
val teacherAbsenceList = mutableListOf<TeacherAbsence>()
|
||||||
|
|
||||||
val messageList = mutableListOf<Message>()
|
val messageList = mutableListOf<Message>()
|
||||||
|
val messageIgnoreList = mutableListOf<Message>()
|
||||||
val messageRecipientList = mutableListOf<MessageRecipient>()
|
val messageRecipientList = mutableListOf<MessageRecipient>()
|
||||||
val messageRecipientIgnoreList = mutableListOf<MessageRecipient>()
|
val messageRecipientIgnoreList = mutableListOf<MessageRecipient>()
|
||||||
|
|
||||||
@ -166,6 +166,9 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
val db: AppDb by lazy { app.db }
|
val db: AppDb by lazy { app.db }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
if (App.devMode) {
|
||||||
|
fakeLogin = loginStore.hasLoginData("fakeLogin")
|
||||||
|
}
|
||||||
clear()
|
clear()
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
endpointTimers = db.endpointTimerDao().getAllNow(profile.id).toMutableList()
|
endpointTimers = db.endpointTimerDao().getAllNow(profile.id).toMutableList()
|
||||||
@ -180,6 +183,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
fun clear() {
|
fun clear() {
|
||||||
loginMethods.clear()
|
loginMethods.clear()
|
||||||
|
|
||||||
|
toRemove.clear()
|
||||||
endpointTimers.clear()
|
endpointTimers.clear()
|
||||||
teacherList.clear()
|
teacherList.clear()
|
||||||
subjectList.clear()
|
subjectList.clear()
|
||||||
@ -195,13 +199,14 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
|
|
||||||
lessonList.clear()
|
lessonList.clear()
|
||||||
lessonChangeList.clear()
|
lessonChangeList.clear()
|
||||||
|
lessonNewList.clear()
|
||||||
gradeList.clear()
|
gradeList.clear()
|
||||||
noticeList.clear()
|
noticeList.clear()
|
||||||
attendanceList.clear()
|
attendanceList.clear()
|
||||||
announcementList.clear()
|
announcementList.clear()
|
||||||
luckyNumberList.clear()
|
luckyNumberList.clear()
|
||||||
teacherAbsenceList.clear()
|
teacherAbsenceList.clear()
|
||||||
messageList.clear()
|
messageIgnoreList.clear()
|
||||||
messageRecipientList.clear()
|
messageRecipientList.clear()
|
||||||
messageRecipientIgnoreList.clear()
|
messageRecipientIgnoreList.clear()
|
||||||
metadataList.clear()
|
metadataList.clear()
|
||||||
@ -248,6 +253,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
app.profile.loginStoreData = loginStore.data
|
app.profile.loginStoreData = loginStore.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always present and not empty, during every sync
|
||||||
db.endpointTimerDao().addAll(endpointTimers)
|
db.endpointTimerDao().addAll(endpointTimers)
|
||||||
db.teacherDao().clear(profileId)
|
db.teacherDao().clear(profileId)
|
||||||
db.teacherDao().addAll(teacherList.values())
|
db.teacherDao().addAll(teacherList.values())
|
||||||
@ -260,6 +266,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
db.gradeCategoryDao().clear(profileId)
|
db.gradeCategoryDao().clear(profileId)
|
||||||
db.gradeCategoryDao().addAll(gradeCategories.values())
|
db.gradeCategoryDao().addAll(gradeCategories.values())
|
||||||
|
|
||||||
|
// may be empty - extracted from DB on demand, by an endpoint
|
||||||
if (classrooms.size > 0)
|
if (classrooms.size > 0)
|
||||||
db.classroomDao().addAll(classrooms.values())
|
db.classroomDao().addAll(classrooms.values())
|
||||||
if (attendanceTypes.size > 0)
|
if (attendanceTypes.size > 0)
|
||||||
@ -271,22 +278,34 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
if (teacherAbsenceTypes.size > 0)
|
if (teacherAbsenceTypes.size > 0)
|
||||||
db.teacherAbsenceTypeDao().addAll(teacherAbsenceTypes.values())
|
db.teacherAbsenceTypeDao().addAll(teacherAbsenceTypes.values())
|
||||||
|
|
||||||
gradesToRemove?.let { it ->
|
// clear DB with DataRemoveModels added by endpoints
|
||||||
it.removeAll?.let { _ -> db.gradeDao().clear(profileId) }
|
for (model in toRemove) {
|
||||||
it.removeSemester?.let { semester -> db.gradeDao().clearForSemester(profileId, semester) }
|
when (model) {
|
||||||
|
is DataRemoveModel.Timetable -> model.commit(profileId, db.timetableDao())
|
||||||
|
is DataRemoveModel.Grades -> model.commit(profileId, db.gradeDao())
|
||||||
|
is DataRemoveModel.Events -> model.commit(profileId, db.eventDao())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (metadataList.isNotEmpty())
|
||||||
|
db.metadataDao().addAllIgnore(metadataList)
|
||||||
|
if (messageMetadataList.isNotEmpty())
|
||||||
|
db.metadataDao().setSeen(messageMetadataList)
|
||||||
|
|
||||||
|
// not extracted from DB - always new data
|
||||||
if (lessonList.isNotEmpty()) {
|
if (lessonList.isNotEmpty()) {
|
||||||
db.lessonDao().clear(profile.id)
|
db.lessonDao().clear(profile.id)
|
||||||
db.lessonDao().addAll(lessonList)
|
db.lessonDao().addAll(lessonList)
|
||||||
}
|
}
|
||||||
if (lessonChangeList.isNotEmpty())
|
if (lessonChangeList.isNotEmpty())
|
||||||
db.lessonChangeDao().addAll(lessonChangeList)
|
db.lessonChangeDao().addAll(lessonChangeList)
|
||||||
|
if (lessonNewList.isNotEmpty()) {
|
||||||
|
db.timetableDao() += lessonNewList
|
||||||
|
}
|
||||||
if (gradeList.isNotEmpty()) {
|
if (gradeList.isNotEmpty()) {
|
||||||
db.gradeDao().addAll(gradeList)
|
db.gradeDao().addAll(gradeList)
|
||||||
}
|
}
|
||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
db.eventDao().removeFuture(profile.id, Date.getToday())
|
|
||||||
db.eventDao().addAll(eventList)
|
db.eventDao().addAll(eventList)
|
||||||
}
|
}
|
||||||
if (noticeList.isNotEmpty()) {
|
if (noticeList.isNotEmpty()) {
|
||||||
@ -303,15 +322,13 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
db.teacherAbsenceDao().addAll(teacherAbsenceList)
|
db.teacherAbsenceDao().addAll(teacherAbsenceList)
|
||||||
|
|
||||||
if (messageList.isNotEmpty())
|
if (messageList.isNotEmpty())
|
||||||
db.messageDao().addAllIgnore(messageList)
|
db.messageDao().addAll(messageList)
|
||||||
|
if (messageIgnoreList.isNotEmpty())
|
||||||
|
db.messageDao().addAllIgnore(messageIgnoreList)
|
||||||
if (messageRecipientList.isNotEmpty())
|
if (messageRecipientList.isNotEmpty())
|
||||||
db.messageRecipientDao().addAll(messageRecipientList)
|
db.messageRecipientDao().addAll(messageRecipientList)
|
||||||
if (messageRecipientIgnoreList.isNotEmpty())
|
if (messageRecipientIgnoreList.isNotEmpty())
|
||||||
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
|
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
|
||||||
if (metadataList.isNotEmpty())
|
|
||||||
db.metadataDao().addAllIgnore(metadataList)
|
|
||||||
if (messageMetadataList.isNotEmpty())
|
|
||||||
db.metadataDao().setSeen(messageMetadataList)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyAndSyncEvents(onSuccess: () -> Unit) {
|
fun notifyAndSyncEvents(onSuccess: () -> Unit) {
|
||||||
@ -358,7 +375,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun shouldSyncLuckyNumber(): Boolean {
|
fun shouldSyncLuckyNumber(): Boolean {
|
||||||
return (db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday()) ?: -1) == -1
|
return (db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday().value) ?: -1) == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) {
|
fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) {
|
||||||
|
@ -4,28 +4,52 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.models
|
package pl.szczodrzynski.edziennik.api.v2.models
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.events.EventDao
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeDao
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.TimetableDao
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class DataRemoveModel {
|
open class DataRemoveModel {
|
||||||
var removeAll: Boolean? = null
|
class Timetable(private val dateFrom: Date?, private val dateTo: Date?) : DataRemoveModel() {
|
||||||
var removeSemester: Int? = null
|
companion object {
|
||||||
var removeDateFrom: Date? = null
|
fun from(dateFrom: Date) = Timetable(dateFrom, null)
|
||||||
var removeDateTo: Date? = null
|
fun to(dateTo: Date) = Timetable(null, dateTo)
|
||||||
|
fun between(dateFrom: Date, dateTo: Date) = Timetable(dateFrom, dateTo)
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
fun commit(profileId: Int, dao: TimetableDao) {
|
||||||
this.removeAll = true
|
if (dateFrom != null && dateTo != null) {
|
||||||
|
dao.clearBetweenDates(profileId, dateFrom, dateTo)
|
||||||
|
} else {
|
||||||
|
dateFrom?.let { dateFrom -> dao.clearFromDate(profileId, dateFrom) }
|
||||||
|
dateTo?.let { dateTo -> dao.clearToDate(profileId, dateTo) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(semester: Int) {
|
class Grades(private val all: Boolean, private val semester: Int?) : DataRemoveModel() {
|
||||||
this.removeSemester = semester
|
companion object {
|
||||||
|
fun all() = Grades(true, null)
|
||||||
|
fun semester(semester: Int) = Grades(false, semester)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun commit(profileId: Int, dao: GradeDao) {
|
||||||
|
if (all) {
|
||||||
|
dao.clear(profileId)
|
||||||
|
}
|
||||||
|
semester?.let { dao.clearForSemester(profileId, it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(dateFrom: Date?, dateTo: Date) {
|
class Events(private val type: Int?, private val exceptType: Int?) : DataRemoveModel() {
|
||||||
this.removeDateFrom = dateFrom
|
companion object {
|
||||||
this.removeDateTo = dateTo
|
fun futureExceptType(exceptType: Int) = Events(null, exceptType)
|
||||||
}
|
fun futureWithType(type: Int) = Events(type, null)
|
||||||
|
}
|
||||||
|
|
||||||
constructor(dateFrom: Date) {
|
fun commit(profileId: Int, dao: EventDao) {
|
||||||
this.removeDateFrom = dateFrom
|
type?.let { dao.removeFutureWithType(profileId, Date.getToday(), it) }
|
||||||
|
exceptType?.let { dao.removeFutureExceptType(profileId, Date.getToday(), it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.template
|
package pl.szczodrzynski.edziennik.api.v2.template
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
@ -15,6 +16,8 @@ import pl.szczodrzynski.edziennik.api.v2.template.firstlogin.TemplateFirstLogin
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.template.login.TemplateLogin
|
import pl.szczodrzynski.edziennik.api.v2.template.login.TemplateLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.templateLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.templateLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
@ -48,7 +51,8 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||||
|
data.arguments = arguments
|
||||||
data.prepare(templateLoginMethods, TemplateFeatures, featureIds, viewId)
|
data.prepare(templateLoginMethods, TemplateFeatures, featureIds, viewId)
|
||||||
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
@ -59,7 +63,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(messageId: Int) {
|
override fun getMessage(message: MessageFull) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +71,10 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun firstLogin() {
|
override fun firstLogin() {
|
||||||
TemplateFirstLogin(data) {
|
TemplateFirstLogin(data) {
|
||||||
completed()
|
completed()
|
||||||
|
@ -7,15 +7,14 @@ package pl.szczodrzynski.edziennik.api.v2.vulcan
|
|||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_VULCAN_API
|
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_VULCAN_API
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
||||||
import pl.szczodrzynski.edziennik.currentTimeUnix
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||||
|
|
||||||
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
||||||
|
|
||||||
fun isApiLoginValid() = apiCertificateExpiryTime-30 > currentTimeUnix()
|
fun isApiLoginValid() = /*apiCertificateExpiryTime-30 > currentTimeUnix()
|
||||||
&& apiCertificateKey.isNotNullNorEmpty()
|
&&*/ apiCertificateKey.isNotNullNorEmpty()
|
||||||
&& apiCertificatePrivate.isNotNullNorEmpty()
|
&& apiCertificatePrivate.isNotNullNorEmpty()
|
||||||
&& symbol.isNotNullNorEmpty()
|
&& symbol.isNotNullNorEmpty()
|
||||||
|
|
||||||
@ -165,6 +164,8 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
|||||||
"GD1" -> "https://uonetplus-komunikacja.edu.gdansk.pl"
|
"GD1" -> "https://uonetplus-komunikacja.edu.gdansk.pl"
|
||||||
"KA1" -> "https://uonetplus-komunikacja.mcuw.katowice.eu"
|
"KA1" -> "https://uonetplus-komunikacja.mcuw.katowice.eu"
|
||||||
"KA2" -> "https://uonetplus-komunikacja-test.mcuw.katowice.eu"
|
"KA2" -> "https://uonetplus-komunikacja-test.mcuw.katowice.eu"
|
||||||
|
"LU1" -> "https://uonetplus-komunikacja.edu.lublin.eu"
|
||||||
|
"LU2" -> "https://test-uonetplus-komunikacja.edu.lublin.eu"
|
||||||
"P03" -> "https://efeb-komunikacja-pro-efebmobile.pro.vulcan.pl"
|
"P03" -> "https://efeb-komunikacja-pro-efebmobile.pro.vulcan.pl"
|
||||||
"P01" -> "http://efeb-komunikacja.pro-hudson.win.vulcan.pl"
|
"P01" -> "http://efeb-komunikacja.pro-hudson.win.vulcan.pl"
|
||||||
"P02" -> "http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl"
|
"P02" -> "http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl"
|
||||||
@ -173,7 +174,7 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
|||||||
"SZ9" -> "http://vulcan.szkolny.eu"
|
"SZ9" -> "http://vulcan.szkolny.eu"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
return if (url != null) "$url/$symbol" else null
|
return if (url != null) "$url/$symbol" else loginStore.getLoginData("apiUrl", null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fullApiUrl: String?
|
val fullApiUrl: String?
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.vulcan
|
package pl.szczodrzynski.edziennik.api.v2.vulcan
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
@ -11,10 +12,14 @@ import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
|||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.prepare
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanData
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanData
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.api.VulcanApiMessagesChangeStatus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.firstlogin.VulcanFirstLogin
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.firstlogin.VulcanFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.login.VulcanLogin
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.login.VulcanLogin
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.login.VulcanLoginApi
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcanLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.vulcanLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
@ -48,7 +53,8 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||||
|
data.arguments = arguments
|
||||||
data.prepare(vulcanLoginMethods, VulcanFeatures, featureIds, viewId)
|
data.prepare(vulcanLoginMethods, VulcanFeatures, featureIds, viewId)
|
||||||
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
@ -59,14 +65,22 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(messageId: Int) {
|
override fun getMessage(message: MessageFull) {
|
||||||
|
VulcanLoginApi(data) {
|
||||||
|
VulcanApiMessagesChangeStatus(data, message) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {
|
override fun markAllAnnouncementsAsRead() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun firstLogin() {
|
override fun firstLogin() {
|
||||||
VulcanFirstLogin(data) {
|
VulcanFirstLogin(data) {
|
||||||
completed()
|
completed()
|
||||||
|
@ -64,6 +64,10 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
|||||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
||||||
VulcanApiAttendance(data, onSuccess)
|
VulcanApiAttendance(data, onSuccess)
|
||||||
}
|
}
|
||||||
|
ENDPOINT_VULCAN_API_TIMETABLE -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||||
|
VulcanApiTimetable(data, onSuccess)
|
||||||
|
}
|
||||||
ENDPOINT_VULCAN_API_MESSAGES_INBOX -> {
|
ENDPOINT_VULCAN_API_MESSAGES_INBOX -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
||||||
VulcanApiMessagesInbox(data, onSuccess)
|
VulcanApiMessagesInbox(data, onSuccess)
|
||||||
|
@ -55,7 +55,7 @@ class VulcanApiAttendance(override val data: DataVulcan, val onSuccess: () -> Un
|
|||||||
lessonSemester,
|
lessonSemester,
|
||||||
attendance.getString("PrzedmiotNazwa") + attendanceCategory.name.let { " - $it" },
|
attendance.getString("PrzedmiotNazwa") + attendanceCategory.name.let { " - $it" },
|
||||||
lessonDate,
|
lessonDate,
|
||||||
data.lessonRanges.get(attendance.getInt("IdPoraLekcji") ?: 0)?.startTime,
|
data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime,
|
||||||
type)
|
type)
|
||||||
|
|
||||||
data.attendanceList.add(attendanceObject)
|
data.attendanceList.add(attendanceObject)
|
||||||
|
@ -35,7 +35,7 @@ class VulcanApiDictionaries(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
elements?.getJsonArray("KategorieUwag")?.forEach { saveNoticeType(it.asJsonObject) }
|
elements?.getJsonArray("KategorieUwag")?.forEach { saveNoticeType(it.asJsonObject) }
|
||||||
elements?.getJsonArray("KategorieFrekwencji")?.forEach { saveAttendanceType(it.asJsonObject) }
|
elements?.getJsonArray("KategorieFrekwencji")?.forEach { saveAttendanceType(it.asJsonObject) }
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_API_DICTIONARIES, 4*DAY)
|
data.setSyncNext(ENDPOINT_VULCAN_API_DICTIONARIES, 4 * DAY)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ class VulcanApiDictionaries(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun saveLessonRange(lessonRange: JsonObject) {
|
private fun saveLessonRange(lessonRange: JsonObject) {
|
||||||
val lessonNumber = lessonRange.getInt("Id") ?: return
|
val lessonNumber = lessonRange.getInt("Numer") ?: return
|
||||||
val startTime = lessonRange.getString("PoczatekTekst")?.let { Time.fromH_m(it) } ?: return
|
val startTime = lessonRange.getString("PoczatekTekst")?.let { Time.fromH_m(it) } ?: return
|
||||||
val endTime = lessonRange.getString("KoniecTekst")?.let { Time.fromH_m(it) } ?: return
|
val endTime = lessonRange.getString("KoniecTekst")?.let { Time.fromH_m(it) } ?: return
|
||||||
|
|
||||||
@ -126,8 +126,7 @@ class VulcanApiDictionaries(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
Attendance.TYPE_ABSENT_EXCUSED
|
Attendance.TYPE_ABSENT_EXCUSED
|
||||||
else
|
else
|
||||||
Attendance.TYPE_ABSENT
|
Attendance.TYPE_ABSENT
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val belated = attendanceType.getBoolean("Spoznienie") ?: false
|
val belated = attendanceType.getBoolean("Spoznienie") ?: false
|
||||||
val released = attendanceType.getBoolean("Zwolnienie") ?: false
|
val released = attendanceType.getBoolean("Zwolnienie") ?: false
|
||||||
val present = attendanceType.getBoolean("Obecnosc") ?: true
|
val present = attendanceType.getBoolean("Obecnosc") ?: true
|
||||||
|
@ -6,6 +6,7 @@ package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
|
|||||||
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_EVENTS
|
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_EVENTS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_HOMEWORK
|
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_HOMEWORK
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_EVENTS
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_EVENTS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_HOMEWORK
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_HOMEWORK
|
||||||
@ -52,10 +53,11 @@ class VulcanApiEvents(override val data: DataVulcan, private val isHomework: Boo
|
|||||||
val eventDate = Date.fromY_m_d(event.getString("DataTekst") ?: return@forEach)
|
val eventDate = Date.fromY_m_d(event.getString("DataTekst") ?: return@forEach)
|
||||||
val subjectId = event.getLong("IdPrzedmiot") ?: -1
|
val subjectId = event.getLong("IdPrzedmiot") ?: -1
|
||||||
val teacherId = event.getLong("IdPracownik") ?: -1
|
val teacherId = event.getLong("IdPracownik") ?: -1
|
||||||
val startTime = data.lessonList.singleOrNull {
|
|
||||||
it.weekDay == eventDate.weekDay && it.subjectId == subjectId
|
|
||||||
}?.startTime
|
|
||||||
val topic = event.getString("Opis") ?: ""
|
val topic = event.getString("Opis") ?: ""
|
||||||
|
|
||||||
|
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
|
||||||
|
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
|
||||||
|
|
||||||
val type = when (isHomework) {
|
val type = when (isHomework) {
|
||||||
true -> Event.TYPE_HOMEWORK
|
true -> Event.TYPE_HOMEWORK
|
||||||
else -> when (event.getBoolean("Rodzaj")) {
|
else -> when (event.getBoolean("Rodzaj")) {
|
||||||
@ -91,8 +93,14 @@ class VulcanApiEvents(override val data: DataVulcan, private val isHomework: Boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (isHomework) {
|
when (isHomework) {
|
||||||
true -> data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS)
|
true -> {
|
||||||
false -> data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS)
|
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
|
||||||
|
data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS)
|
||||||
|
}
|
||||||
|
false -> {
|
||||||
|
data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
|
||||||
|
data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-12
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
|
||||||
|
class VulcanApiMessagesChangeStatus(
|
||||||
|
override val data: DataVulcan,
|
||||||
|
private val messageObject: MessageFull,
|
||||||
|
val onSuccess: () -> Unit
|
||||||
|
) : VulcanApi(data) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "VulcanApiMessagesChangeStatus"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
data.profile?.also { profile ->
|
||||||
|
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS, parameters = mapOf(
|
||||||
|
"WiadomoscId" to messageObject.id,
|
||||||
|
"FolderWiadomosci" to "Odebrane",
|
||||||
|
"Status" to "Widoczna",
|
||||||
|
"LoginId" to data.studentLoginId,
|
||||||
|
"IdUczen" to data.studentId
|
||||||
|
)) { _, _ ->
|
||||||
|
|
||||||
|
if (!messageObject.seen) {
|
||||||
|
data.messageMetadataList.add(Metadata(
|
||||||
|
profileId,
|
||||||
|
Metadata.TYPE_MESSAGE,
|
||||||
|
messageObject.id,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
messageObject.addedDate
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messageObject.type != TYPE_SENT) {
|
||||||
|
val messageRecipientObject = MessageRecipient(
|
||||||
|
profileId,
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
messageObject.id
|
||||||
|
)
|
||||||
|
|
||||||
|
data.messageRecipientList.add(messageRecipientObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,8 @@ import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
|
class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
|
||||||
@ -43,7 +45,22 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
|
|
||||||
val senderLoginId = message.getString("NadawcaId") ?: return@forEach
|
val senderLoginId = message.getString("NadawcaId") ?: return@forEach
|
||||||
val senderId = data.teacherList
|
val senderId = data.teacherList
|
||||||
.singleOrNull { it.loginId == senderLoginId }?.id ?: return@forEach
|
.singleOrNull { it.loginId == senderLoginId }?.id ?: {
|
||||||
|
|
||||||
|
val senderName = message.getString("Nadawca") ?: ""
|
||||||
|
|
||||||
|
senderName.getLastFirstName()?.let { (senderLastName, senderFirstName) ->
|
||||||
|
val teacherObject = Teacher(
|
||||||
|
profileId,
|
||||||
|
-1 * Utils.crc16(senderName.toByteArray()).toLong(),
|
||||||
|
senderFirstName,
|
||||||
|
senderLastName,
|
||||||
|
senderLoginId
|
||||||
|
)
|
||||||
|
data.teacherList.put(teacherObject.id, teacherObject)
|
||||||
|
teacherObject.id
|
||||||
|
}
|
||||||
|
}.invoke() ?: -1
|
||||||
|
|
||||||
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 }
|
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 }
|
||||||
?: -1
|
?: -1
|
||||||
@ -68,7 +85,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
id
|
id
|
||||||
)
|
)
|
||||||
|
|
||||||
data.messageList.add(messageObject)
|
data.messageIgnoreList.add(messageObject)
|
||||||
data.messageRecipientList.add(messageRecipientObject)
|
data.messageRecipientList.add(messageRecipientObject)
|
||||||
data.metadataList.add(Metadata(
|
data.metadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
|
@ -14,6 +14,8 @@ import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
|
||||||
class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
|
class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
|
||||||
@ -23,11 +25,11 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
data.profile?.also { profile ->
|
data.profile?.also { profile ->
|
||||||
val startDate: String = when (profile.empty) {
|
val startDate: Long = when (profile.empty) {
|
||||||
true -> profile.getSemesterStart(profile.currentSemester).stringY_m_d
|
true -> profile.getSemesterStart(profile.currentSemester).inUnix
|
||||||
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
|
else -> Date.getToday().stepForward(0, -1, 0).inUnix
|
||||||
}
|
}
|
||||||
val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d
|
val endDate: Long = profile.getSemesterEnd(profile.currentSemester).inUnix
|
||||||
|
|
||||||
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_SENT, parameters = mapOf(
|
apiGet(TAG, VULCAN_API_ENDPOINT_MESSAGES_SENT, parameters = mapOf(
|
||||||
"DataPoczatkowa" to startDate,
|
"DataPoczatkowa" to startDate,
|
||||||
@ -43,23 +45,27 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
val unreadBy = message.getInt("Nieprzeczytane") ?: 0
|
val unreadBy = message.getInt("Nieprzeczytane") ?: 0
|
||||||
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } ?: -1
|
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } ?: -1
|
||||||
|
|
||||||
val messageObject = Message(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
subject,
|
|
||||||
body,
|
|
||||||
TYPE_SENT,
|
|
||||||
-1,
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
|
|
||||||
message.getJsonArray("Adresaci")?.asJsonObjectList()
|
message.getJsonArray("Adresaci")?.asJsonObjectList()
|
||||||
?.forEachIndexed { _, recipient ->
|
?.onEach { receiver ->
|
||||||
|
|
||||||
val recipientLoginId = recipient.getString("LoginId")
|
val receiverLoginId = receiver.getString("LoginId")
|
||||||
?: return@forEachIndexed
|
?: return@onEach
|
||||||
val recipientId = data.teacherList.singleOrNull { it.loginId == recipientLoginId }?.id
|
val receiverId = data.teacherList.singleOrNull { it.loginId == receiverLoginId }?.id
|
||||||
?: return@forEachIndexed
|
?: {
|
||||||
|
val receiverName = receiver.getString("Nazwa") ?: ""
|
||||||
|
|
||||||
|
receiverName.getLastFirstName()?.let { (receiverLastName, receiverFirstName) ->
|
||||||
|
val teacherObject = Teacher(
|
||||||
|
profileId,
|
||||||
|
-1 * Utils.crc16(receiverName.toByteArray()).toLong(),
|
||||||
|
receiverFirstName,
|
||||||
|
receiverLastName,
|
||||||
|
receiverLoginId
|
||||||
|
)
|
||||||
|
data.teacherList.put(teacherObject.id, teacherObject)
|
||||||
|
teacherObject.id
|
||||||
|
}
|
||||||
|
}.invoke() ?: -1
|
||||||
|
|
||||||
val readDate: Long = when (readBy) {
|
val readDate: Long = when (readBy) {
|
||||||
0 -> 0
|
0 -> 0
|
||||||
@ -71,7 +77,7 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
|
|
||||||
val messageRecipientObject = MessageRecipient(
|
val messageRecipientObject = MessageRecipient(
|
||||||
profileId,
|
profileId,
|
||||||
recipientId,
|
receiverId,
|
||||||
-1,
|
-1,
|
||||||
readDate,
|
readDate,
|
||||||
id
|
id
|
||||||
@ -80,7 +86,17 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
|||||||
data.messageRecipientList.add(messageRecipientObject)
|
data.messageRecipientList.add(messageRecipientObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
data.messageList.add(messageObject)
|
val messageObject = Message(
|
||||||
|
profileId,
|
||||||
|
id,
|
||||||
|
subject,
|
||||||
|
body,
|
||||||
|
TYPE_SENT,
|
||||||
|
-1,
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
|
||||||
|
data.messageIgnoreList.add(messageObject)
|
||||||
data.metadataList.add(Metadata(
|
data.metadataList.add(Metadata(
|
||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_MESSAGE,
|
Metadata.TYPE_MESSAGE,
|
||||||
|
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-11-13
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
|
||||||
|
|
||||||
|
import androidx.core.util.set
|
||||||
|
import pl.szczodrzynski.edziennik.*
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_TIMETABLE
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.ENDPOINT_VULCAN_API_TIMETABLE
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.crc16
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
|
||||||
|
class VulcanApiTimetable(override val data: DataVulcan, val onSuccess: () -> Unit) : VulcanApi(data) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "VulcanApiTimetable"
|
||||||
|
}
|
||||||
|
|
||||||
|
init { data.profile?.also { profile ->
|
||||||
|
val currentWeekStart = Week.getWeekStart()
|
||||||
|
|
||||||
|
if (Date.getToday().weekDay > 4) {
|
||||||
|
currentWeekStart.stepForward(0, 0, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
||||||
|
|
||||||
|
val weekStart = Date.fromY_m_d(getDate)
|
||||||
|
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
||||||
|
|
||||||
|
apiGet(TAG, VULCAN_API_ENDPOINT_TIMETABLE, parameters = mapOf(
|
||||||
|
"DataPoczatkowa" to weekStart.stringY_m_d,
|
||||||
|
"DataKoncowa" to weekEnd.stringY_m_d,
|
||||||
|
"IdUczen" to data.studentId,
|
||||||
|
"IdOddzial" to data.studentClassId,
|
||||||
|
"IdOkresKlasyfikacyjny" to data.studentSemesterId
|
||||||
|
)) { json, _ ->
|
||||||
|
val dates = mutableSetOf<Int>()
|
||||||
|
val lessons = mutableListOf<Lesson>()
|
||||||
|
|
||||||
|
json.getJsonArray("Data")?.asJsonObjectList()?.forEach { lesson ->
|
||||||
|
if (lesson.getBoolean("PlanUcznia") != true)
|
||||||
|
return@forEach
|
||||||
|
val lessonDate = Date.fromY_m_d(lesson.getString("DzienTekst"))
|
||||||
|
val lessonNumber = lesson.getInt("NumerLekcji")
|
||||||
|
val lessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }
|
||||||
|
val startTime = lessonRange?.startTime
|
||||||
|
val endTime = lessonRange?.endTime
|
||||||
|
val teacherId = lesson.getLong("IdPracownik")
|
||||||
|
val classroom = lesson.getString("Sala")
|
||||||
|
|
||||||
|
val oldTeacherId = lesson.getLong("IdPracownikOld")
|
||||||
|
|
||||||
|
val changeAnnotation = lesson.getString("AdnotacjaOZmianie") ?: ""
|
||||||
|
val type = when {
|
||||||
|
changeAnnotation.startsWith("(przeniesiona z") -> Lesson.TYPE_SHIFTED_TARGET
|
||||||
|
changeAnnotation.startsWith("(przeniesiona na") -> Lesson.TYPE_SHIFTED_SOURCE
|
||||||
|
changeAnnotation.startsWith("(zastępstwo") -> Lesson.TYPE_CHANGE
|
||||||
|
lesson.getBoolean("PrzekreslonaNazwa") == true -> Lesson.TYPE_CANCELLED
|
||||||
|
else -> Lesson.TYPE_NORMAL
|
||||||
|
}
|
||||||
|
|
||||||
|
val teamId = lesson.getString("PodzialSkrot")?.let { teamName ->
|
||||||
|
val name = "${data.teamClass?.name} $teamName"
|
||||||
|
val id = name.crc16().toLong()
|
||||||
|
var team = data.teamList.singleOrNull { it.name == name }
|
||||||
|
if (team == null) {
|
||||||
|
team = Team(
|
||||||
|
profileId,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
Team.TYPE_VIRTUAL,
|
||||||
|
"${data.schoolName}:$name",
|
||||||
|
teacherId ?: oldTeacherId ?: -1
|
||||||
|
)
|
||||||
|
data.teamList[id] = team
|
||||||
|
}
|
||||||
|
team.id
|
||||||
|
} ?: data.studentClassId.toLong()
|
||||||
|
|
||||||
|
val subjectId = lesson.getLong("IdPrzedmiot")?.let {
|
||||||
|
when (it) {
|
||||||
|
0L -> {
|
||||||
|
val subjectName = lesson.getString("PrzedmiotNazwa") ?: ""
|
||||||
|
|
||||||
|
data.subjectList.singleOrNull { subject -> subject.longName == subjectName }?.id
|
||||||
|
?: {
|
||||||
|
/**
|
||||||
|
* CREATE A NEW SUBJECT IF IT DOESN'T EXIST
|
||||||
|
*/
|
||||||
|
|
||||||
|
val subjectObject = Subject(
|
||||||
|
profileId,
|
||||||
|
-1 * crc16(subjectName.toByteArray()).toLong(),
|
||||||
|
subjectName,
|
||||||
|
subjectName
|
||||||
|
)
|
||||||
|
data.subjectList.put(subjectObject.id, subjectObject)
|
||||||
|
subjectObject.id
|
||||||
|
}.invoke()
|
||||||
|
}
|
||||||
|
else -> it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val lessonObject = Lesson(profileId, -1).apply {
|
||||||
|
this.type = type
|
||||||
|
|
||||||
|
when (type) {
|
||||||
|
Lesson.TYPE_NORMAL, Lesson.TYPE_CHANGE, Lesson.TYPE_SHIFTED_TARGET -> {
|
||||||
|
this.date = lessonDate
|
||||||
|
this.lessonNumber = lessonNumber
|
||||||
|
this.startTime = startTime
|
||||||
|
this.endTime = endTime
|
||||||
|
this.subjectId = subjectId
|
||||||
|
this.teacherId = teacherId
|
||||||
|
this.teamId = teamId
|
||||||
|
this.classroom = classroom
|
||||||
|
|
||||||
|
this.oldTeacherId = oldTeacherId
|
||||||
|
}
|
||||||
|
|
||||||
|
Lesson.TYPE_CANCELLED, Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||||
|
this.oldDate = lessonDate
|
||||||
|
this.oldLessonNumber = lessonNumber
|
||||||
|
this.oldStartTime = startTime
|
||||||
|
this.oldEndTime = endTime
|
||||||
|
this.oldSubjectId = subjectId
|
||||||
|
this.oldTeacherId = teacherId
|
||||||
|
this.oldTeamId = teamId
|
||||||
|
this.oldClassroom = classroom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Lesson.TYPE_SHIFTED_SOURCE || type == Lesson.TYPE_SHIFTED_TARGET) {
|
||||||
|
val shift = Regexes.VULCAN_SHITFT_ANNOTATION.find(changeAnnotation)
|
||||||
|
val oldLessonNumber = shift?.get(2)?.toInt()
|
||||||
|
val oldLessonDate = shift?.get(3)?.let { Date.fromd_m_Y(it) }
|
||||||
|
|
||||||
|
val oldLessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == oldLessonNumber }
|
||||||
|
val oldStartTime = oldLessonRange?.startTime
|
||||||
|
val oldEndTime = oldLessonRange?.endTime
|
||||||
|
|
||||||
|
when (type) {
|
||||||
|
Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||||
|
this.lessonNumber = oldLessonNumber
|
||||||
|
this.date = oldLessonDate
|
||||||
|
this.startTime = oldStartTime
|
||||||
|
this.endTime = oldEndTime
|
||||||
|
}
|
||||||
|
|
||||||
|
Lesson.TYPE_SHIFTED_TARGET -> {
|
||||||
|
this.oldLessonNumber = oldLessonNumber
|
||||||
|
this.oldDate = oldLessonDate
|
||||||
|
this.oldStartTime = oldStartTime
|
||||||
|
this.oldEndTime = oldEndTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.id = buildId()
|
||||||
|
}
|
||||||
|
|
||||||
|
val seen = profile.empty || lessonDate < Date.getToday()
|
||||||
|
|
||||||
|
if (type != Lesson.TYPE_NORMAL) {
|
||||||
|
data.metadataList.add(Metadata(
|
||||||
|
profileId,
|
||||||
|
Metadata.TYPE_LESSON_CHANGE,
|
||||||
|
lessonObject.id,
|
||||||
|
seen,
|
||||||
|
seen,
|
||||||
|
System.currentTimeMillis()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
dates.add(lessonDate.value)
|
||||||
|
lessons.add(lessonObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
val date: Date = weekStart.clone()
|
||||||
|
while (date <= weekEnd) {
|
||||||
|
if (!dates.contains(date.value)) {
|
||||||
|
lessons.add(Lesson(profileId, date.value.toLong()).apply {
|
||||||
|
this.type = Lesson.TYPE_NO_LESSONS
|
||||||
|
this.date = date.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
date.stepForward(0, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
||||||
|
|
||||||
|
data.lessonNewList.addAll(lessons)
|
||||||
|
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||||
|
|
||||||
|
data.setSyncNext(ENDPOINT_VULCAN_API_TIMETABLE, SYNC_ALWAYS)
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
@ -38,10 +38,12 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
|
|||||||
if (data.apiToken?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD,
|
if (data.apiToken?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD,
|
||||||
data.apiCertificatePfx ?: ""
|
data.apiCertificatePfx ?: ""
|
||||||
)
|
)
|
||||||
onSuccess()
|
data.loginStore.removeLoginData("certificatePfx")
|
||||||
return@run
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
} finally {
|
||||||
|
onSuccess()
|
||||||
|
return@run
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.symbol.isNotNullNorEmpty() && data.apiToken.isNotNullNorEmpty() && data.apiPin.isNotNullNorEmpty()) {
|
if (data.symbol.isNotNullNorEmpty() && data.apiToken.isNotNullNorEmpty() && data.apiPin.isNotNullNorEmpty()) {
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
interface AbstractConfig {
|
||||||
|
fun set(key: String, value: String?)
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.BuildConfig
|
||||||
|
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.ConfigMigration
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
||||||
|
companion object {
|
||||||
|
const val DATA_VERSION = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
private val job = Job()
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Default
|
||||||
|
|
||||||
|
val values: HashMap<String, String?> = hashMapOf()
|
||||||
|
|
||||||
|
val ui by lazy { ConfigUI(this) }
|
||||||
|
val sync by lazy { ConfigSync(this) }
|
||||||
|
val timetable by lazy { ConfigTimetable(this) }
|
||||||
|
val grades by lazy { ConfigGrades(this) }
|
||||||
|
|
||||||
|
private var mDataVersion: Int? = null
|
||||||
|
var dataVersion: Int
|
||||||
|
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
||||||
|
set(value) { set("dataVersion", value); mDataVersion = value }
|
||||||
|
|
||||||
|
private var mAppVersion: Int? = null
|
||||||
|
var appVersion: Int
|
||||||
|
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE }
|
||||||
|
set(value) { set("appVersion", value); mAppVersion = value }
|
||||||
|
|
||||||
|
private var mLoginFinished: Boolean? = null
|
||||||
|
var loginFinished: Boolean
|
||||||
|
get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false }
|
||||||
|
set(value) { set("loginFinished", value); mLoginFinished = value }
|
||||||
|
|
||||||
|
private var mDevModePassword: String? = null
|
||||||
|
var devModePassword: String?
|
||||||
|
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }
|
||||||
|
set(value) { set("devModePassword", value); mDevModePassword = value }
|
||||||
|
|
||||||
|
private var mAppInstalledTime: Long? = null
|
||||||
|
var appInstalledTime: Long
|
||||||
|
get() { mAppInstalledTime = mAppInstalledTime ?: values.get("appInstalledTime", 0L); return mAppInstalledTime ?: 0L }
|
||||||
|
set(value) { set("appInstalledTime", value); mAppInstalledTime = value }
|
||||||
|
|
||||||
|
private var mAppRateSnackbarTime: Long? = null
|
||||||
|
var appRateSnackbarTime: Long
|
||||||
|
get() { mAppRateSnackbarTime = mAppRateSnackbarTime ?: values.get("appRateSnackbarTime", 0L); return mAppRateSnackbarTime ?: 0L }
|
||||||
|
set(value) { set("appRateSnackbarTime", value); mAppRateSnackbarTime = value }
|
||||||
|
|
||||||
|
private var rawEntries: List<ConfigEntry> = db.configDao().getAllNow()
|
||||||
|
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
|
||||||
|
init {
|
||||||
|
rawEntries.toHashMap(-1, values)
|
||||||
|
}
|
||||||
|
fun migrate(app: App) {
|
||||||
|
if (dataVersion < DATA_VERSION)
|
||||||
|
ConfigMigration(app, this)
|
||||||
|
}
|
||||||
|
fun getFor(profileId: Int): ProfileConfig {
|
||||||
|
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, rawEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setProfile(profileId: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun set(key: String, value: String?) {
|
||||||
|
values[key] = value
|
||||||
|
launch {
|
||||||
|
db.configDao().add(ConfigEntry(-1, key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
|
||||||
|
class ConfigGrades(private val config: Config) {
|
||||||
|
companion object {
|
||||||
|
const val ORDER_BY_DATE_DESC = 0
|
||||||
|
const val ORDER_BY_SUBJECT_ASC = 1
|
||||||
|
const val ORDER_BY_DATE_ASC = 2
|
||||||
|
const val ORDER_BY_SUBJECT_DESC = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mOrderBy: Int? = null
|
||||||
|
var orderBy: Int
|
||||||
|
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: 0 }
|
||||||
|
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
|
||||||
|
class ConfigSync(private val config: Config) {
|
||||||
|
private var mSyncEnabled: Boolean? = null
|
||||||
|
var enabled: Boolean
|
||||||
|
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
||||||
|
set(value) { config.set("syncEnabled", value); mSyncEnabled = value }
|
||||||
|
|
||||||
|
private var mSyncOnlyWifi: Boolean? = null
|
||||||
|
var onlyWifi: Boolean
|
||||||
|
get() { mSyncOnlyWifi = mSyncOnlyWifi ?: config.values.get("syncOnlyWifi", false); return mSyncOnlyWifi ?: notifyAboutUpdates }
|
||||||
|
set(value) { config.set("syncOnlyWifi", value); mSyncOnlyWifi = value }
|
||||||
|
|
||||||
|
private var mSyncInterval: Int? = null
|
||||||
|
var interval: Int
|
||||||
|
get() { mSyncInterval = mSyncInterval ?: config.values.get("syncInterval", 60*60); return mSyncInterval ?: 60*60 }
|
||||||
|
set(value) { config.set("syncInterval", value); mSyncInterval = value }
|
||||||
|
|
||||||
|
private var mNotifyAboutUpdates: Boolean? = null
|
||||||
|
var notifyAboutUpdates: Boolean
|
||||||
|
get() { mNotifyAboutUpdates = mNotifyAboutUpdates ?: config.values.get("notifyAboutUpdates", true); return mNotifyAboutUpdates ?: true }
|
||||||
|
set(value) { config.set("notifyAboutUpdates", value); mNotifyAboutUpdates = value }
|
||||||
|
|
||||||
|
/* ____ _ _ _
|
||||||
|
/ __ \ (_) | | | |
|
||||||
|
| | | |_ _ _ ___| |_ | |__ ___ _ _ _ __ ___
|
||||||
|
| | | | | | | |/ _ \ __| | '_ \ / _ \| | | | '__/ __|
|
||||||
|
| |__| | |_| | | __/ |_ | | | | (_) | |_| | | \__ \
|
||||||
|
\___\_\\__,_|_|\___|\__| |_| |_|\___/ \__,_|_| |__*/
|
||||||
|
private var mQuietHoursStart: Long? = null
|
||||||
|
var quietHoursStart: Long
|
||||||
|
get() { mQuietHoursStart = mQuietHoursStart ?: config.values.get("quietHoursStart", 0L); return mQuietHoursStart ?: 0L }
|
||||||
|
set(value) { config.set("quietHoursStart", value); mQuietHoursStart = value }
|
||||||
|
|
||||||
|
private var mQuietHoursEnd: Long? = null
|
||||||
|
var quietHoursEnd: Long
|
||||||
|
get() { mQuietHoursEnd = mQuietHoursEnd ?: config.values.get("quietHoursEnd", 0L); return mQuietHoursEnd ?: 0L }
|
||||||
|
set(value) { config.set("quietHoursEnd", value); mQuietHoursEnd = value }
|
||||||
|
|
||||||
|
private var mQuietDuringLessons: Boolean? = null
|
||||||
|
var quietDuringLessons: Boolean
|
||||||
|
get() { mQuietDuringLessons = mQuietDuringLessons ?: config.values.get("quietDuringLessons", false); return mQuietDuringLessons ?: false }
|
||||||
|
set(value) { config.set("quietDuringLessons", value); mQuietDuringLessons = value }
|
||||||
|
|
||||||
|
/* ______ _____ __ __ _______ _
|
||||||
|
| ____/ ____| \/ | |__ __| | |
|
||||||
|
| |__ | | | \ / | | | ___ | | _____ _ __ ___
|
||||||
|
| __|| | | |\/| | | |/ _ \| |/ / _ \ '_ \/ __|
|
||||||
|
| | | |____| | | | | | (_) | < __/ | | \__ \
|
||||||
|
|_| \_____|_| |_| |_|\___/|_|\_\___|_| |_|__*/
|
||||||
|
private var mTokenApp: String? = null
|
||||||
|
var tokenApp: String?
|
||||||
|
get() { mTokenApp = mTokenApp ?: config.values.get("tokenApp", null as String?); return mTokenApp }
|
||||||
|
set(value) { config.set("tokenApp", value); mTokenApp = value }
|
||||||
|
private var mTokenMobidziennik: String? = null
|
||||||
|
var tokenMobidziennik: String?
|
||||||
|
get() { mTokenMobidziennik = mTokenMobidziennik ?: config.values.get("tokenMobidziennik", null as String?); return mTokenMobidziennik }
|
||||||
|
set(value) { config.set("tokenMobidziennik", value); mTokenMobidziennik = value }
|
||||||
|
private var mTokenLibrus: String? = null
|
||||||
|
var tokenLibrus: String?
|
||||||
|
get() { mTokenLibrus = mTokenLibrus ?: config.values.get("tokenLibrus", null as String?); return mTokenLibrus }
|
||||||
|
set(value) { config.set("tokenLibrus", value); mTokenLibrus = value }
|
||||||
|
private var mTokenVulcan: String? = null
|
||||||
|
var tokenVulcan: String?
|
||||||
|
get() { mTokenVulcan = mTokenVulcan ?: config.values.get("tokenVulcan", null as String?); return mTokenVulcan }
|
||||||
|
set(value) { config.set("tokenVulcan", value); mTokenVulcan = value }
|
||||||
|
|
||||||
|
private var mTokenMobidziennikList: List<Int>? = null
|
||||||
|
var tokenMobidziennikList: List<Int>
|
||||||
|
get() { mTokenMobidziennikList = mTokenMobidziennikList ?: config.values.getIntList("tokenMobidziennikList", listOf()); return mTokenMobidziennikList ?: listOf() }
|
||||||
|
set(value) { config.set("tokenMobidziennikList", value); mTokenMobidziennikList = value }
|
||||||
|
private var mTokenLibrusList: List<Int>? = null
|
||||||
|
var tokenLibrusList: List<Int>
|
||||||
|
get() { mTokenLibrusList = mTokenLibrusList ?: config.values.getIntList("tokenLibrusList", listOf()); return mTokenLibrusList ?: listOf() }
|
||||||
|
set(value) { config.set("tokenLibrusList", value); mTokenLibrusList = value }
|
||||||
|
private var mTokenVulcanList: List<Int>? = null
|
||||||
|
var tokenVulcanList: List<Int>
|
||||||
|
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
|
||||||
|
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
|
class ConfigTimetable(private val config: Config) {
|
||||||
|
private var mBellSyncMultiplier: Int? = null
|
||||||
|
var bellSyncMultiplier: Int
|
||||||
|
get() { mBellSyncMultiplier = mBellSyncMultiplier ?: config.values.get("bellSyncMultiplier", 0); return mBellSyncMultiplier ?: 0 }
|
||||||
|
set(value) { config.set("bellSyncMultiplier", value); mBellSyncMultiplier = value }
|
||||||
|
|
||||||
|
private var mBellSyncDiff: Time? = null
|
||||||
|
var bellSyncDiff: Time?
|
||||||
|
get() { mBellSyncDiff = mBellSyncDiff ?: config.values.get("bellSyncDiff", null as Time?); return mBellSyncDiff }
|
||||||
|
set(value) { config.set("bellSyncDiff", value); mBellSyncDiff = value }
|
||||||
|
|
||||||
|
private var mCountInSeconds: Boolean? = null
|
||||||
|
var countInSeconds: Boolean
|
||||||
|
get() { mCountInSeconds = mCountInSeconds ?: config.values.get("countInSeconds", false); return mCountInSeconds ?: false }
|
||||||
|
set(value) { config.set("countInSeconds", value); mCountInSeconds = value }
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel
|
||||||
|
|
||||||
|
class ConfigUI(private val config: Config) {
|
||||||
|
private var mTheme: Int? = null
|
||||||
|
var theme: Int
|
||||||
|
get() { mTheme = mTheme ?: config.values.get("theme", 1); return mTheme ?: 1 }
|
||||||
|
set(value) { config.set("theme", value); mTheme = value }
|
||||||
|
|
||||||
|
private var mLanguage: String? = null
|
||||||
|
var language: String?
|
||||||
|
get() { mLanguage = mLanguage ?: config.values.get("language", null as String?); return mLanguage }
|
||||||
|
set(value) { config.set("language", value); mLanguage = value }
|
||||||
|
|
||||||
|
private var mHeaderBackground: String? = null
|
||||||
|
var headerBackground: String?
|
||||||
|
get() { mHeaderBackground = mHeaderBackground ?: config.values.get("headerBackground", null as String?); return mHeaderBackground }
|
||||||
|
set(value) { config.set("headerBg", value); mHeaderBackground = value }
|
||||||
|
|
||||||
|
private var mAppBackground: String? = null
|
||||||
|
var appBackground: String?
|
||||||
|
get() { mAppBackground = mAppBackground ?: config.values.get("appBackground", null as String?); return mAppBackground }
|
||||||
|
set(value) { config.set("appBg", value); mAppBackground = value }
|
||||||
|
|
||||||
|
private var mMiniMenuVisible: Boolean? = null
|
||||||
|
var miniMenuVisible: Boolean
|
||||||
|
get() { mMiniMenuVisible = mMiniMenuVisible ?: config.values.get("miniMenuVisible", false); return mMiniMenuVisible ?: false }
|
||||||
|
set(value) { config.set("miniMenuVisible", value); mMiniMenuVisible = value }
|
||||||
|
|
||||||
|
private var mMiniMenuButtons: List<Int>? = null
|
||||||
|
var miniMenuButtons: List<Int>
|
||||||
|
get() { mMiniMenuButtons = mMiniMenuButtons ?: config.values.getIntList("miniMenuButtons", listOf()); return mMiniMenuButtons ?: listOf() }
|
||||||
|
set(value) { config.set("miniMenuButtons", value); mMiniMenuButtons = value }
|
||||||
|
|
||||||
|
private var mAgendaViewType: Int? = null
|
||||||
|
var agendaViewType: Int
|
||||||
|
get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: 0 }
|
||||||
|
set(value) { config.set("agendaViewType", value); mAgendaViewType = value }
|
||||||
|
|
||||||
|
private var mHomeCards: List<HomeCardModel>? = null
|
||||||
|
var homeCards: List<HomeCardModel>
|
||||||
|
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
|
||||||
|
set(value) { config.set("homeCards", value); mHomeCards = value }
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEntry>) : CoroutineScope, AbstractConfig {
|
||||||
|
companion object {
|
||||||
|
const val DATA_VERSION = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
private val job = Job()
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Default
|
||||||
|
|
||||||
|
val values: HashMap<String, String?> = hashMapOf()
|
||||||
|
|
||||||
|
val grades by lazy { ProfileConfigGrades(this) }
|
||||||
|
/*
|
||||||
|
val sync by lazy { ConfigSync(this) }
|
||||||
|
val timetable by lazy { ConfigTimetable(this) }
|
||||||
|
val grades by lazy { ConfigGrades(this) }*/
|
||||||
|
|
||||||
|
private var mDataVersion: Int? = null
|
||||||
|
var dataVersion: Int
|
||||||
|
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
||||||
|
set(value) { set("dataVersion", value); mDataVersion = value }
|
||||||
|
|
||||||
|
init {
|
||||||
|
rawEntries.toHashMap(profileId, values)
|
||||||
|
/*if (dataVersion < DATA_VERSION)
|
||||||
|
ProfileConfigMigration(this)*/
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun set(key: String, value: String?) {
|
||||||
|
values[key] = value
|
||||||
|
launch {
|
||||||
|
db.configDao().add(ConfigEntry(profileId, key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.get
|
||||||
|
import pl.szczodrzynski.edziennik.config.utils.set
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.COLOR_MODE_WEIGHTED
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile.Companion.YEAR_ALL_GRADES
|
||||||
|
|
||||||
|
class ProfileConfigGrades(private val config: ProfileConfig) {
|
||||||
|
private var mColorMode: Int? = null
|
||||||
|
var colorMode: Int
|
||||||
|
get() { mColorMode = mColorMode ?: config.values.get("gradesColorMode", COLOR_MODE_WEIGHTED); return mColorMode ?: COLOR_MODE_WEIGHTED }
|
||||||
|
set(value) { config.set("gradesColorMode", value); mColorMode = value }
|
||||||
|
|
||||||
|
private var mYearAverageMode: Int? = null
|
||||||
|
var yearAverageMode: Int
|
||||||
|
get() { mYearAverageMode = mYearAverageMode ?: config.values.get("yearAverageMode", YEAR_ALL_GRADES); return mYearAverageMode ?: YEAR_ALL_GRADES }
|
||||||
|
set(value) { config.set("yearAverageMode", value); mYearAverageMode = value }
|
||||||
|
|
||||||
|
private var mCountZeroToAvg: Boolean? = null
|
||||||
|
var countZeroToAvg: Boolean
|
||||||
|
get() { mCountZeroToAvg = mCountZeroToAvg ?: config.values.get("countZeroToAvg", true); return mCountZeroToAvg ?: true }
|
||||||
|
set(value) { config.set("countZeroToAvg", value); mCountZeroToAvg = value }
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user