Compare commits
No commits in common. "v4.5-beta.2" and "v4.4.1" have entirely different histories.
v4.5-beta.
...
v4.4.1
16
.idea/codeStyles/Project.xml
generated
|
@ -1,10 +1,6 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
|
||||||
<indentOptions>
|
<indentOptions>
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
</indentOptions>
|
</indentOptions>
|
||||||
|
@ -15,6 +11,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>xmlns:android</NAME>
|
<NAME>xmlns:android</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -25,6 +22,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>xmlns:.*</NAME>
|
<NAME>xmlns:.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -36,6 +34,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>.*:id</NAME>
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -46,6 +45,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>.*:name</NAME>
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -56,6 +56,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>name</NAME>
|
<NAME>name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>style</NAME>
|
<NAME>style</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -76,6 +78,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>.*</NAME>
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -87,6 +90,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>.*</NAME>
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -98,6 +102,7 @@
|
||||||
<match>
|
<match>
|
||||||
<AND>
|
<AND>
|
||||||
<NAME>.*</NAME>
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
</AND>
|
</AND>
|
||||||
</match>
|
</match>
|
||||||
|
@ -107,8 +112,5 @@
|
||||||
</rules>
|
</rules>
|
||||||
</arrangement>
|
</arrangement>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
|
@ -1,5 +0,0 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
15
.idea/compiler.xml
generated
|
@ -4,14 +4,13 @@
|
||||||
<bytecodeTargetLevel target="1.7">
|
<bytecodeTargetLevel target="1.7">
|
||||||
<module name="annotation" target="1.7" />
|
<module name="annotation" target="1.7" />
|
||||||
<module name="codegen" target="1.7" />
|
<module name="codegen" target="1.7" />
|
||||||
<module name="Szkolny.eu.agendacalendarview" target="11" />
|
<module name="Szkolny.eu.agendacalendarview" target="1.8" />
|
||||||
<module name="Szkolny.eu.app" target="11" />
|
<module name="Szkolny.eu.app" target="1.8" />
|
||||||
<module name="Szkolny.eu.cafebar" target="11" />
|
<module name="Szkolny.eu.cafebar" target="1.8" />
|
||||||
<module name="Szkolny.eu.material-about-library" target="11" />
|
<module name="Szkolny.eu.material-about-library" target="1.8" />
|
||||||
<module name="Szkolny.eu.mhttp" target="11" />
|
<module name="Szkolny.eu.mhttp" target="1.8" />
|
||||||
<module name="Szkolny.eu.nachos" target="11" />
|
<module name="Szkolny.eu.nachos" target="1.8" />
|
||||||
<module name="Szkolny.eu.szkolny-font" target="11" />
|
<module name="Szkolny.eu.szkolny-font" target="1.8" />
|
||||||
<module name="Szkolny.eu.wear" target="11" />
|
|
||||||
</bytecodeTargetLevel>
|
</bytecodeTargetLevel>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
2
.idea/discord.xml
generated
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DiscordProjectSettings">
|
<component name="DiscordProjectSettings">
|
||||||
<option name="show" value="PROJECT_FILES" />
|
<option name="show" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectNotificationSettings">
|
<component name="ProjectNotificationSettings">
|
||||||
<option name="askShowProject" value="false" />
|
<option name="askShowProject" value="false" />
|
||||||
|
|
1
.idea/runConfigurations.xml
generated
|
@ -3,7 +3,6 @@
|
||||||
<component name="RunConfigurationProducerService">
|
<component name="RunConfigurationProducerService">
|
||||||
<option name="ignoredProducers">
|
<option name="ignoredProducers">
|
||||||
<set>
|
<set>
|
||||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
|
|
|
@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
apply plugin: 'kotlin-android-extensions'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
apply plugin: 'com.google.firebase.crashlytics'
|
apply plugin: 'io.fabric'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
@ -54,11 +54,10 @@ android {
|
||||||
lintOptions {
|
lintOptions {
|
||||||
checkReleaseBuilds false
|
checkReleaseBuilds false
|
||||||
}
|
}
|
||||||
buildFeatures {
|
dataBinding {
|
||||||
dataBinding = true
|
enabled = true
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
coreLibraryDesugaringEnabled true
|
|
||||||
sourceCompatibility '1.8'
|
sourceCompatibility '1.8'
|
||||||
targetCompatibility '1.8'
|
targetCompatibility '1.8'
|
||||||
}
|
}
|
||||||
|
@ -76,7 +75,6 @@ android {
|
||||||
version "3.10.2"
|
version "3.10.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ndkVersion '21.3.6528147'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*task finalizeBundleDebug(type: Copy) {
|
/*task finalizeBundleDebug(type: Copy) {
|
||||||
|
@ -106,8 +104,6 @@ tasks.whenTaskAdded { task ->
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
|
|
||||||
|
|
||||||
kapt "androidx.room:room-compiler:${versions.room}"
|
kapt "androidx.room:room-compiler:${versions.room}"
|
||||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.5"
|
debugImplementation "com.amitshekhar.android:debug-db:1.0.5"
|
||||||
|
|
||||||
|
@ -118,7 +114,7 @@ dependencies {
|
||||||
implementation "androidx.core:core-ktx:${versions.ktx}"
|
implementation "androidx.core:core-ktx:${versions.ktx}"
|
||||||
implementation "androidx.gridlayout:gridlayout:${versions.gridLayout}"
|
implementation "androidx.gridlayout:gridlayout:${versions.gridLayout}"
|
||||||
implementation "androidx.legacy:legacy-support-v4:${versions.legacy}"
|
implementation "androidx.legacy:legacy-support-v4:${versions.legacy}"
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:${versions.lifecycle}"
|
implementation "androidx.lifecycle:lifecycle-livedata:${versions.lifecycle}"
|
||||||
implementation "androidx.recyclerview:recyclerview:${versions.recyclerView}"
|
implementation "androidx.recyclerview:recyclerview:${versions.recyclerView}"
|
||||||
implementation "androidx.room:room-runtime:${versions.room}"
|
implementation "androidx.room:room-runtime:${versions.room}"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
|
||||||
|
@ -141,7 +137,7 @@ dependencies {
|
||||||
|
|
||||||
implementation "cat.ereza:customactivityoncrash:2.2.0"
|
implementation "cat.ereza:customactivityoncrash:2.2.0"
|
||||||
implementation "com.applandeo:material-calendar-view:1.5.0"
|
implementation "com.applandeo:material-calendar-view:1.5.0"
|
||||||
implementation 'com.google.firebase:firebase-crashlytics:17.3.1'
|
implementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||||
implementation "com.evernote:android-job:1.2.6"
|
implementation "com.evernote:android-job:1.2.6"
|
||||||
implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2"
|
implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2"
|
||||||
|
@ -161,7 +157,7 @@ dependencies {
|
||||||
implementation "me.grantland:autofittextview:0.2.1"
|
implementation "me.grantland:autofittextview:0.2.1"
|
||||||
implementation "me.leolin:ShortcutBadger:1.1.22@aar"
|
implementation "me.leolin:ShortcutBadger:1.1.22@aar"
|
||||||
implementation "org.greenrobot:eventbus:3.1.1"
|
implementation "org.greenrobot:eventbus:3.1.1"
|
||||||
implementation "org.jsoup:jsoup:1.12.1"
|
implementation "org.jsoup:jsoup:1.10.1"
|
||||||
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15"
|
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15"
|
||||||
//implementation "se.emilsjolander:stickylistheaders:2.7.0"
|
//implementation "se.emilsjolander:stickylistheaders:2.7.0"
|
||||||
implementation 'com.github.edisonw:StickyListHeaders:master-SNAPSHOT@aar'
|
implementation 'com.github.edisonw:StickyListHeaders:master-SNAPSHOT@aar'
|
||||||
|
@ -184,7 +180,6 @@ dependencies {
|
||||||
//implementation "org.redundent:kotlin-xml-builder:1.5.3"
|
//implementation "org.redundent:kotlin-xml-builder:1.5.3"
|
||||||
|
|
||||||
implementation "io.github.wulkanowy:signer-android:0.1.1"
|
implementation "io.github.wulkanowy:signer-android:0.1.1"
|
||||||
implementation 'com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31'
|
|
||||||
|
|
||||||
implementation "androidx.work:work-runtime-ktx:${versions.work}"
|
implementation "androidx.work:work-runtime-ktx:${versions.work}"
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,6 @@
|
||||||
|
|
||||||
-keep class pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing { public final byte[] pleaseStopRightNow(java.lang.String, long); }
|
-keep class pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing { public final byte[] pleaseStopRightNow(java.lang.String, long); }
|
||||||
|
|
||||||
-keepclassmembers class pl.szczodrzynski.edziennik.data.api.szkolny.request.** { *; }
|
-keepclassmembernames class pl.szczodrzynski.edziennik.data.api.szkolny.request.** { *; }
|
||||||
-keepclassmembers class pl.szczodrzynski.edziennik.data.api.szkolny.response.** { *; }
|
-keepclassmembernames class pl.szczodrzynski.edziennik.data.api.szkolny.response.** { *; }
|
||||||
-keepclassmembernames class pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo.Platform { *; }
|
-keepclassmembernames class pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo.Platform { *; }
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<h3>Wersja 4.5-beta.2, 2021-02-21</h3>
|
<h3>Wersja 4.4.1, 2020-09-03</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Vulcan: aplikacja Szkolny.eu zaktualizowana w związku z wygaszeniem aplikacji Dzienniczek+.</li>
|
<li>Poprawione komunikaty o aktualizacjach aplikacji.</li>
|
||||||
|
<li>Mobidziennik: poprawione wyświetlanie przedmiotu w planie lekcji.</li>
|
||||||
|
<li>Mobidziennik: naprawiony moduł frekwencji.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
Dzięki za korzystanie ze Szkolnego!<br>
|
Dzięki za korzystanie ze Szkolnego!<br>
|
||||||
<i>© Kuba Szczodrzyński, Kacper Ziubryniewicz 2021</i>
|
<i>© Kuba Szczodrzyński, Kacper Ziubryniewicz 2020</i>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
/*secret password - removed for source code publication*/
|
/*secret password - removed for source code publication*/
|
||||||
static toys AES_IV[16] = {
|
static toys AES_IV[16] = {
|
||||||
0x42, 0xf5, 0x8e, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
0x72, 0x4b, 0x61, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
val profileId
|
val profileId
|
||||||
get() = profile.id
|
get() = profile.id
|
||||||
|
|
||||||
var debugMode = false
|
|
||||||
var devMode = false
|
var devMode = false
|
||||||
|
var debugMode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
|
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
|
||||||
|
@ -107,7 +107,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
builder.installHttpsSupport(this)
|
builder.installHttpsSupport(this)
|
||||||
|
|
||||||
if (devMode || BuildConfig.DEBUG) {
|
if (debugMode || BuildConfig.DEBUG) {
|
||||||
HyperLog.initialize(this)
|
HyperLog.initialize(this)
|
||||||
HyperLog.setLogLevel(Log.VERBOSE)
|
HyperLog.setLogLevel(Log.VERBOSE)
|
||||||
HyperLog.setLogFormat(DebugLogFormat(this))
|
HyperLog.setLogFormat(DebugLogFormat(this))
|
||||||
|
@ -162,7 +162,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
Iconics.registerFont(SzkolnyFont)
|
Iconics.registerFont(SzkolnyFont)
|
||||||
App.db = AppDb(this)
|
App.db = AppDb(this)
|
||||||
Themes.themeInt = config.ui.theme
|
Themes.themeInt = config.ui.theme
|
||||||
devMode = config.debugMode
|
debugMode = config.debugMode
|
||||||
MHttp.instance().customOkHttpClient(http)
|
MHttp.instance().customOkHttpClient(http)
|
||||||
|
|
||||||
if (!profileLoadById(config.lastProfileId)) {
|
if (!profileLoadById(config.lastProfileId)) {
|
||||||
|
@ -173,9 +173,9 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
setLanguage(it)
|
setLanguage(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
debugMode = BuildConfig.DEBUG
|
devMode = BuildConfig.DEBUG
|
||||||
if (BuildConfig.DEBUG)
|
if (BuildConfig.DEBUG)
|
||||||
devMode = true
|
debugMode = true
|
||||||
|
|
||||||
Signing.getCert(this)
|
Signing.getCert(this)
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
|
|
||||||
if (config.devModePassword != null)
|
if (config.devModePassword != null)
|
||||||
checkDevModePassword()
|
checkDevModePassword()
|
||||||
devMode = debugMode || config.debugMode
|
debugMode = devMode || config.debugMode
|
||||||
|
|
||||||
if (config.sync.enabled)
|
if (config.sync.enabled)
|
||||||
SyncWorker.scheduleNext(this@App, false)
|
SyncWorker.scheduleNext(this@App, false)
|
||||||
|
@ -294,19 +294,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
"Vulcan"
|
"Vulcan"
|
||||||
)
|
)
|
||||||
|
|
||||||
val pushVulcanHebeApp = FirebaseApp.initializeApp(
|
|
||||||
this@App,
|
|
||||||
FirebaseOptions.Builder()
|
|
||||||
.setProjectId("dzienniczekplus")
|
|
||||||
.setStorageBucket("dzienniczekplus.appspot.com")
|
|
||||||
.setDatabaseUrl("https://dzienniczekplus.firebaseio.com")
|
|
||||||
.setGcmSenderId("987828170337")
|
|
||||||
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
|
||||||
.setApplicationId("1:987828170337:android:7e16404b9e5deaaa")
|
|
||||||
.build(),
|
|
||||||
"VulcanHebe"
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
|
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
|
||||||
val token = instanceIdResult.token
|
val token = instanceIdResult.token
|
||||||
|
@ -337,14 +324,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
config.sync.tokenVulcanList = listOf()
|
config.sync.tokenVulcanList = listOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FirebaseInstanceId.getInstance(pushVulcanHebeApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
||||||
val token = instanceIdResult.token
|
|
||||||
d("Firebase", "Got VulcanHebe token: $token")
|
|
||||||
if (token != config.sync.tokenVulcanHebe) {
|
|
||||||
config.sync.tokenVulcanHebe = token
|
|
||||||
config.sync.tokenVulcanHebeList = listOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
|
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
|
@ -96,30 +96,30 @@ fun List<Teacher>.byNameFDotSpaceLast(nameFDotSpaceLast: String) = firstOrNull {
|
||||||
|
|
||||||
fun JsonObject?.get(key: String): JsonElement? = this?.get(key)
|
fun JsonObject?.get(key: String): JsonElement? = this?.get(key)
|
||||||
|
|
||||||
fun JsonObject?.getBoolean(key: String): Boolean? = get(key)?.let { if (!it.isJsonPrimitive) null else it.asBoolean }
|
fun JsonObject?.getBoolean(key: String): Boolean? = get(key)?.let { if (it.isJsonNull) null else it.asBoolean }
|
||||||
fun JsonObject?.getString(key: String): String? = get(key)?.let { if (!it.isJsonPrimitive) null else it.asString }
|
fun JsonObject?.getString(key: String): String? = get(key)?.let { if (it.isJsonNull) null else it.asString }
|
||||||
fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (!it.isJsonPrimitive) null else it.asInt }
|
fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) null else it.asInt }
|
||||||
fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (!it.isJsonPrimitive) null else it.asLong }
|
fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong }
|
||||||
fun JsonObject?.getFloat(key: String): Float? = get(key)?.let { if(!it.isJsonPrimitive) null else it.asFloat }
|
fun JsonObject?.getFloat(key: String): Float? = get(key)?.let { if(it.isJsonNull) null else it.asFloat }
|
||||||
fun JsonObject?.getChar(key: String): Char? = get(key)?.let { if(!it.isJsonPrimitive) null else it.asCharacter }
|
fun JsonObject?.getChar(key: String): Char? = get(key)?.let { if(it.isJsonNull) null else it.asCharacter }
|
||||||
fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonObject) it.asJsonObject else null }
|
fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonObject) it.asJsonObject else null }
|
||||||
fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonArray) it.asJsonArray else null }
|
fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonArray) it.asJsonArray else null }
|
||||||
|
|
||||||
fun JsonObject?.getBoolean(key: String, defaultValue: Boolean): Boolean = get(key)?.let { if (!it.isJsonPrimitive) defaultValue else it.asBoolean } ?: defaultValue
|
fun JsonObject?.getBoolean(key: String, defaultValue: Boolean): Boolean = get(key)?.let { if (it.isJsonNull) defaultValue else it.asBoolean } ?: defaultValue
|
||||||
fun JsonObject?.getString(key: String, defaultValue: String): String = get(key)?.let { if (!it.isJsonPrimitive) defaultValue else it.asString } ?: defaultValue
|
fun JsonObject?.getString(key: String, defaultValue: String): String = get(key)?.let { if (it.isJsonNull) defaultValue else it.asString } ?: defaultValue
|
||||||
fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (!it.isJsonPrimitive) defaultValue else it.asInt } ?: defaultValue
|
fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (it.isJsonNull) defaultValue else it.asInt } ?: defaultValue
|
||||||
fun JsonObject?.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (!it.isJsonPrimitive) defaultValue else it.asLong } ?: defaultValue
|
fun JsonObject?.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: defaultValue
|
||||||
fun JsonObject?.getFloat(key: String, defaultValue: Float): Float = get(key)?.let { if(!it.isJsonPrimitive) defaultValue else it.asFloat } ?: defaultValue
|
fun JsonObject?.getFloat(key: String, defaultValue: Float): Float = get(key)?.let { if(it.isJsonNull) defaultValue else it.asFloat } ?: defaultValue
|
||||||
fun JsonObject?.getChar(key: String, defaultValue: Char): Char = get(key)?.let { if(!it.isJsonPrimitive) defaultValue else it.asCharacter } ?: defaultValue
|
fun JsonObject?.getChar(key: String, defaultValue: Char): Char = get(key)?.let { if(it.isJsonNull) defaultValue else it.asCharacter } ?: defaultValue
|
||||||
fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonObject) it.asJsonObject else defaultValue } ?: defaultValue
|
fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonObject) it.asJsonObject else defaultValue } ?: defaultValue
|
||||||
fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonArray) it.asJsonArray else defaultValue } ?: defaultValue
|
fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonArray) it.asJsonArray else defaultValue } ?: defaultValue
|
||||||
|
|
||||||
fun JsonArray.getBoolean(key: Int): Boolean? = if (key >= size()) null else get(key)?.let { if (!it.isJsonPrimitive) null else it.asBoolean }
|
fun JsonArray.getBoolean(key: Int): Boolean? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asBoolean }
|
||||||
fun JsonArray.getString(key: Int): String? = if (key >= size()) null else get(key)?.let { if (!it.isJsonPrimitive) null else it.asString }
|
fun JsonArray.getString(key: Int): String? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asString }
|
||||||
fun JsonArray.getInt(key: Int): Int? = if (key >= size()) null else get(key)?.let { if (!it.isJsonPrimitive) null else it.asInt }
|
fun JsonArray.getInt(key: Int): Int? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asInt }
|
||||||
fun JsonArray.getLong(key: Int): Long? = if (key >= size()) null else get(key)?.let { if (!it.isJsonPrimitive) null else it.asLong }
|
fun JsonArray.getLong(key: Int): Long? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asLong }
|
||||||
fun JsonArray.getFloat(key: Int): Float? = if (key >= size()) null else get(key)?.let { if(!it.isJsonPrimitive) null else it.asFloat }
|
fun JsonArray.getFloat(key: Int): Float? = if (key >= size()) null else get(key)?.let { if(it.isJsonNull) null else it.asFloat }
|
||||||
fun JsonArray.getChar(key: Int): Char? = if (key >= size()) null else get(key)?.let { if(!it.isJsonPrimitive) null else it.asCharacter }
|
fun JsonArray.getChar(key: Int): Char? = if (key >= size()) null else get(key)?.let { if(it.isJsonNull) null else it.asCharacter }
|
||||||
fun JsonArray.getJsonObject(key: Int): JsonObject? = if (key >= size()) null else get(key)?.let { if (it.isJsonObject) it.asJsonObject else null }
|
fun JsonArray.getJsonObject(key: Int): JsonObject? = if (key >= size()) null else get(key)?.let { if (it.isJsonObject) it.asJsonObject else null }
|
||||||
fun JsonArray.getJsonArray(key: Int): JsonArray? = if (key >= size()) null else get(key)?.let { if (it.isJsonArray) it.asJsonArray else null }
|
fun JsonArray.getJsonArray(key: Int): JsonArray? = if (key >= size()) null else get(key)?.let { if (it.isJsonArray) it.asJsonArray else null }
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ fun colorFromCssName(name: String): Int {
|
||||||
"orange" -> 0xffffa500
|
"orange" -> 0xffffa500
|
||||||
"black" -> 0xff000000
|
"black" -> 0xff000000
|
||||||
"white" -> 0xffffffff
|
"white" -> 0xffffffff
|
||||||
else -> -1L
|
else -> -1
|
||||||
}.toInt()
|
}.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,7 +1172,7 @@ fun Iterable<Float>.averageOrNull() = this.average().let { if (it.isNaN()) null
|
||||||
fun String.copyToClipboard(context: Context) {
|
fun String.copyToClipboard(context: Context) {
|
||||||
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
val clipData = ClipData.newPlainText("Tekst", this)
|
val clipData = ClipData.newPlainText("Tekst", this)
|
||||||
clipboard.setPrimaryClip(clipData)
|
clipboard.primaryClip = clipData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TextView.getTextPosition(range: IntRange): Rect {
|
fun TextView.getTextPosition(range: IntRange): Rect {
|
||||||
|
|
|
@ -232,7 +232,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES)
|
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES)
|
||||||
list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class)
|
list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class)
|
||||||
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
|
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
|
||||||
if (App.devMode) {
|
if (App.debugMode) {
|
||||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||||
list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class)
|
list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_flask_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_flask_outline)
|
||||||
|
@ -566,7 +566,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||||
.withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline)
|
.withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline)
|
||||||
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
.withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) })
|
||||||
)
|
)
|
||||||
if (App.devMode) {
|
if (App.debugMode) {
|
||||||
bottomSheet += BottomSheetPrimaryItem(false)
|
bottomSheet += BottomSheetPrimaryItem(false)
|
||||||
.withTitle(R.string.menu_debug)
|
.withTitle(R.string.menu_debug)
|
||||||
.withIcon(CommunityMaterial.Icon.cmd_android_studio)
|
.withIcon(CommunityMaterial.Icon.cmd_android_studio)
|
||||||
|
@ -647,7 +647,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||||
|
|
||||||
app.profile.registerName?.let { registerName ->
|
app.profile.registerName?.let { registerName ->
|
||||||
var status = app.config.sync.registerAvailability[registerName]
|
var status = app.config.sync.registerAvailability[registerName]
|
||||||
if (status == null || status.nextCheckAt < currentTimeUnix()) {
|
if (status == null || status.nextCheck < currentTimeUnix()) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val api = SzkolnyApi(app)
|
val api = SzkolnyApi(app)
|
||||||
api.runCatching(this@MainActivity) {
|
api.runCatching(this@MainActivity) {
|
||||||
|
|
|
@ -99,10 +99,6 @@ class ConfigSync(private val config: Config) {
|
||||||
var tokenVulcan: String?
|
var tokenVulcan: String?
|
||||||
get() { mTokenVulcan = mTokenVulcan ?: config.values.get("tokenVulcan", null as String?); return mTokenVulcan }
|
get() { mTokenVulcan = mTokenVulcan ?: config.values.get("tokenVulcan", null as String?); return mTokenVulcan }
|
||||||
set(value) { config.set("tokenVulcan", value); mTokenVulcan = value }
|
set(value) { config.set("tokenVulcan", value); mTokenVulcan = value }
|
||||||
private var mTokenVulcanHebe: String? = null
|
|
||||||
var tokenVulcanHebe: String?
|
|
||||||
get() { mTokenVulcanHebe = mTokenVulcanHebe ?: config.values.get("tokenVulcanHebe", null as String?); return mTokenVulcanHebe }
|
|
||||||
set(value) { config.set("tokenVulcanHebe", value); mTokenVulcanHebe = value }
|
|
||||||
|
|
||||||
private var mTokenMobidziennikList: List<Int>? = null
|
private var mTokenMobidziennikList: List<Int>? = null
|
||||||
var tokenMobidziennikList: List<Int>
|
var tokenMobidziennikList: List<Int>
|
||||||
|
@ -116,10 +112,6 @@ class ConfigSync(private val config: Config) {
|
||||||
var tokenVulcanList: List<Int>
|
var tokenVulcanList: List<Int>
|
||||||
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
|
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
|
||||||
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
|
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
|
||||||
private var mTokenVulcanHebeList: List<Int>? = null
|
|
||||||
var tokenVulcanHebeList: List<Int>
|
|
||||||
get() { mTokenVulcanHebeList = mTokenVulcanHebeList ?: config.values.getIntList("tokenVulcanHebeList", listOf()); return mTokenVulcanHebeList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenVulcanHebeList", value); mTokenVulcanHebeList = value }
|
|
||||||
|
|
||||||
private var mRegisterAvailability: Map<String, RegisterAvailabilityStatus>? = null
|
private var mRegisterAvailability: Map<String, RegisterAvailabilityStatus>? = null
|
||||||
var registerAvailability: Map<String, RegisterAvailabilityStatus>
|
var registerAvailability: Map<String, RegisterAvailabilityStatus>
|
||||||
|
|
|
@ -49,9 +49,4 @@ class ProfileConfigGrades(private val config: ProfileConfig) {
|
||||||
var dontCountGrades: List<String>
|
var dontCountGrades: List<String>
|
||||||
get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() }
|
get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() }
|
||||||
set(value) { config.set("dontCountGrades", value); mDontCountGrades = value }
|
set(value) { config.set("dontCountGrades", value); mDontCountGrades = value }
|
||||||
|
|
||||||
private var mHideSticksFromOld: Boolean? = null
|
|
||||||
var hideSticksFromOld: Boolean
|
|
||||||
get() { mHideSticksFromOld = mHideSticksFromOld ?: config.values.get("hideSticksFromOld", false); return mHideSticksFromOld ?: false }
|
|
||||||
set(value) { config.set("hideSticksFromOld", value); mHideSticksFromOld = value }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,16 +95,7 @@ const val VULCAN_API_APP_NAME = "VULCAN-Android-ModulUcznia"
|
||||||
const val VULCAN_API_APP_VERSION = "20.5.1.470"
|
const val VULCAN_API_APP_VERSION = "20.5.1.470"
|
||||||
const val VULCAN_API_PASSWORD = "CE75EA598C7743AD9B0B7328DED85B06"
|
const val VULCAN_API_PASSWORD = "CE75EA598C7743AD9B0B7328DED85B06"
|
||||||
const val VULCAN_API_PASSWORD_FAKELOG = "012345678901234567890123456789AB"
|
const val VULCAN_API_PASSWORD_FAKELOG = "012345678901234567890123456789AB"
|
||||||
const val VULCAN_HEBE_USER_AGENT = "Dart/2.10 (dart:io)"
|
val VULCAN_API_DEVICE_NAME = "Szkolny.eu ${Build.MODEL}"
|
||||||
const val VULCAN_HEBE_APP_NAME = "DzienniczekPlus 2.0"
|
|
||||||
const val VULCAN_HEBE_APP_VERSION = "21.02.09 (G)"
|
|
||||||
private const val VULCAN_API_DEVICE_NAME_PREFIX = "Szkolny.eu "
|
|
||||||
private const val VULCAN_API_DEVICE_NAME_SUFFIX = " - nie usuwać"
|
|
||||||
val VULCAN_API_DEVICE_NAME by lazy {
|
|
||||||
val base = "$VULCAN_API_DEVICE_NAME_PREFIX${Build.MODEL}"
|
|
||||||
val baseMaxLength = 50 - VULCAN_API_DEVICE_NAME_SUFFIX.length
|
|
||||||
base.take(baseMaxLength) + VULCAN_API_DEVICE_NAME_SUFFIX
|
|
||||||
}
|
|
||||||
|
|
||||||
const val VULCAN_API_ENDPOINT_CERTIFICATE = "mobile-api/Uczen.v3.UczenStart/Certyfikat"
|
const val VULCAN_API_ENDPOINT_CERTIFICATE = "mobile-api/Uczen.v3.UczenStart/Certyfikat"
|
||||||
const val VULCAN_API_ENDPOINT_STUDENT_LIST = "mobile-api/Uczen.v3.UczenStart/ListaUczniow"
|
const val VULCAN_API_ENDPOINT_STUDENT_LIST = "mobile-api/Uczen.v3.UczenStart/ListaUczniow"
|
||||||
|
@ -125,21 +116,9 @@ const val VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/
|
||||||
const val VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/ZadaniaDomoweZalacznik"
|
const val VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/ZadaniaDomoweZalacznik"
|
||||||
const val VULCAN_WEB_ENDPOINT_LUCKY_NUMBER = "Start.mvc/GetKidsLuckyNumbers"
|
const val VULCAN_WEB_ENDPOINT_LUCKY_NUMBER = "Start.mvc/GetKidsLuckyNumbers"
|
||||||
const val VULCAN_WEB_ENDPOINT_REGISTER_DEVICE = "RejestracjaUrzadzeniaToken.mvc/Get"
|
const val VULCAN_WEB_ENDPOINT_REGISTER_DEVICE = "RejestracjaUrzadzeniaToken.mvc/Get"
|
||||||
const val VULCAN_HEBE_ENDPOINT_REGISTER_NEW = "api/mobile/register/new"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_MAIN = "api/mobile/register/hebe"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_TIMETABLE = "api/mobile/schedule"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_TIMETABLE_CHANGES = "api/mobile/schedule/changes"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_ADDRESSBOOK = "api/mobile/addressbook"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_EXAMS = "api/mobile/exam"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_GRADES = "api/mobile/grade"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_HOMEWORK = "api/mobile/homework"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_ATTENDANCE = "api/mobile/lesson"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_MESSAGES = "api/mobile/message"
|
|
||||||
const val VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS = "api/mobile/message/status"
|
|
||||||
|
|
||||||
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
||||||
|
|
||||||
const val PODLASIE_API_VERSION = "1.0.62"
|
const val PODLASIE_API_VERSION = "1.0.31"
|
||||||
const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api"
|
const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api"
|
||||||
const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia"
|
const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia"
|
||||||
const val PODLASIE_API_LOGOUT_DEVICES_ENDPOINT = "/wyczyscUrzadzenia"
|
|
||||||
|
|
|
@ -170,7 +170,6 @@ const val ERROR_VULCAN_WEB_LOGGED_OUT = 350
|
||||||
const val ERROR_VULCAN_WEB_CERTIFICATE_POST_FAILED = 351
|
const val ERROR_VULCAN_WEB_CERTIFICATE_POST_FAILED = 351
|
||||||
const val ERROR_VULCAN_WEB_GRADUATE_ACCOUNT = 352
|
const val ERROR_VULCAN_WEB_GRADUATE_ACCOUNT = 352
|
||||||
const val ERROR_VULCAN_WEB_NO_SCHOOLS = 353
|
const val ERROR_VULCAN_WEB_NO_SCHOOLS = 353
|
||||||
const val ERROR_VULCAN_HEBE_OTHER = 354
|
|
||||||
|
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN = 401
|
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN = 401
|
||||||
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME = 402
|
const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME = 402
|
||||||
|
@ -230,6 +229,5 @@ const val ERROR_ONEDRIVE_DOWNLOAD = 930
|
||||||
const val EXCEPTION_VULCAN_WEB_LOGIN = 931
|
const val EXCEPTION_VULCAN_WEB_LOGIN = 931
|
||||||
const val EXCEPTION_VULCAN_WEB_REQUEST = 932
|
const val EXCEPTION_VULCAN_WEB_REQUEST = 932
|
||||||
const val EXCEPTION_PODLASIE_API_REQUEST = 940
|
const val EXCEPTION_PODLASIE_API_REQUEST = 940
|
||||||
const val EXCEPTION_VULCAN_HEBE_REQUEST = 950
|
|
||||||
|
|
||||||
const val LOGIN_NO_ARGUMENTS = 1201
|
const val LOGIN_NO_ARGUMENTS = 1201
|
||||||
|
|
|
@ -17,7 +17,6 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLogi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
||||||
|
|
||||||
|
@ -99,13 +98,11 @@ val mobidziennikLoginMethods = listOf(
|
||||||
const val LOGIN_TYPE_VULCAN = 4
|
const val LOGIN_TYPE_VULCAN = 4
|
||||||
const val LOGIN_MODE_VULCAN_API = 0
|
const val LOGIN_MODE_VULCAN_API = 0
|
||||||
const val LOGIN_MODE_VULCAN_WEB = 1
|
const val LOGIN_MODE_VULCAN_WEB = 1
|
||||||
const val LOGIN_MODE_VULCAN_HEBE = 2
|
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_MAIN = 100
|
const val LOGIN_METHOD_VULCAN_WEB_MAIN = 100
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_NEW = 200
|
const val LOGIN_METHOD_VULCAN_WEB_NEW = 200
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_OLD = 300
|
const val LOGIN_METHOD_VULCAN_WEB_OLD = 300
|
||||||
const val LOGIN_METHOD_VULCAN_WEB_MESSAGES = 400
|
const val LOGIN_METHOD_VULCAN_WEB_MESSAGES = 400
|
||||||
const val LOGIN_METHOD_VULCAN_API = 500
|
const val LOGIN_METHOD_VULCAN_API = 500
|
||||||
const val LOGIN_METHOD_VULCAN_HEBE = 600
|
|
||||||
val vulcanLoginMethods = listOf(
|
val vulcanLoginMethods = listOf(
|
||||||
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_MAIN, VulcanLoginWebMain::class.java)
|
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_WEB_MAIN, VulcanLoginWebMain::class.java)
|
||||||
.withIsPossible { _, loginStore -> loginStore.hasLoginData("webHost") }
|
.withIsPossible { _, loginStore -> loginStore.hasLoginData("webHost") }
|
||||||
|
@ -120,17 +117,7 @@ val vulcanLoginMethods = listOf(
|
||||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },*/
|
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_VULCAN_WEB_MAIN },*/
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_API, VulcanLoginApi::class.java)
|
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_API, VulcanLoginApi::class.java)
|
||||||
.withIsPossible { _, loginStore ->
|
.withIsPossible { _, _ -> true }
|
||||||
loginStore.mode != LOGIN_MODE_VULCAN_HEBE
|
|
||||||
}
|
|
||||||
.withRequiredLoginMethod { _, loginStore ->
|
|
||||||
if (loginStore.mode == LOGIN_MODE_VULCAN_WEB) LOGIN_METHOD_VULCAN_WEB_MAIN else LOGIN_METHOD_NOT_NEEDED
|
|
||||||
},
|
|
||||||
|
|
||||||
LoginMethod(LOGIN_TYPE_VULCAN, LOGIN_METHOD_VULCAN_HEBE, VulcanLoginHebe::class.java)
|
|
||||||
.withIsPossible { _, loginStore ->
|
|
||||||
loginStore.mode != LOGIN_MODE_VULCAN_API
|
|
||||||
}
|
|
||||||
.withRequiredLoginMethod { _, loginStore ->
|
.withRequiredLoginMethod { _, loginStore ->
|
||||||
if (loginStore.mode == LOGIN_MODE_VULCAN_WEB) LOGIN_METHOD_VULCAN_WEB_MAIN else LOGIN_METHOD_NOT_NEEDED
|
if (loginStore.mode == LOGIN_MODE_VULCAN_WEB) LOGIN_METHOD_VULCAN_WEB_MAIN else LOGIN_METHOD_NOT_NEEDED
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,6 @@ object Regexes {
|
||||||
"""color: (\w+);?""".toRegex()
|
"""color: (\w+);?""".toRegex()
|
||||||
}
|
}
|
||||||
|
|
||||||
val NOT_DIGITS by lazy {
|
|
||||||
"""[^0-9]""".toRegex()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
|
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
|
||||||
|
|
|
@ -93,7 +93,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||||
|
|
||||||
profile.registerName?.let { registerName ->
|
profile.registerName?.let { registerName ->
|
||||||
var status = app.config.sync.registerAvailability[registerName]
|
var status = app.config.sync.registerAvailability[registerName]
|
||||||
if (status == null || status.nextCheckAt < currentTimeUnix()) {
|
if (status == null || status.nextCheck < currentTimeUnix()) {
|
||||||
val api = SzkolnyApi(app)
|
val api = SzkolnyApi(app)
|
||||||
api.runCatching({
|
api.runCatching({
|
||||||
val availability = getRegisterAvailability()
|
val availability = getRegisterAvailability()
|
||||||
|
|
|
@ -56,21 +56,20 @@ class MobidziennikWebGetRecipientList(override val data: DataMobidziennik,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processRecipient(listType: Int, listName: String, recipient: JsonObject) {
|
private fun processRecipient(listType: Int, listName: String, recipient: JsonObject) {
|
||||||
val id = recipient.getString("id") ?: return
|
val id = recipient.getLong("id") ?: -1
|
||||||
val idLong = id.replace(Regexes.NOT_DIGITS, "").toLongOrNull() ?: return
|
|
||||||
// get teacher by ID or create it
|
// get teacher by ID or create it
|
||||||
val teacher = data.teacherList[idLong] ?: Teacher(data.profileId, idLong).apply {
|
val teacher = data.teacherList[id] ?: Teacher(data.profileId, id).apply {
|
||||||
val fullName = recipient.getString("nazwa")?.fixName()
|
val fullName = recipient.getString("nazwa")?.fixName()
|
||||||
name = fullName ?: ""
|
name = fullName ?: ""
|
||||||
fullName?.splitName()?.let {
|
fullName?.splitName()?.let {
|
||||||
name = it.second
|
name = it.second
|
||||||
surname = it.first
|
surname = it.first
|
||||||
}
|
}
|
||||||
data.teacherList[idLong] = this
|
data.teacherList[id] = this
|
||||||
}
|
}
|
||||||
|
|
||||||
teacher.apply {
|
teacher.apply {
|
||||||
loginId = id
|
loginId = id.toString()
|
||||||
when (listType) {
|
when (listType) {
|
||||||
1 -> setTeacherType(Teacher.TYPE_PRINCIPAL)
|
1 -> setTeacherType(Teacher.TYPE_PRINCIPAL)
|
||||||
2 -> setTeacherType(Teacher.TYPE_TEACHER)
|
2 -> setTeacherType(Teacher.TYPE_TEACHER)
|
||||||
|
|
|
@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE
|
||||||
import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_LOGOUT_DEVICES_ENDPOINT
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT
|
import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
|
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieApi
|
||||||
|
@ -23,23 +22,10 @@ class PodlasieFirstLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
|
||||||
private val api = PodlasieApi(data, null)
|
private val api = PodlasieApi(data, null)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
PodlasieLoginApi(data) {
|
|
||||||
doLogin()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doLogin() {
|
|
||||||
val loginStoreId = data.loginStore.id
|
val loginStoreId = data.loginStore.id
|
||||||
val loginStoreType = LOGIN_TYPE_PODLASIE
|
val loginStoreType = LOGIN_TYPE_PODLASIE
|
||||||
|
|
||||||
if (data.loginStore.getLoginData("logoutDevices", false)) {
|
PodlasieLoginApi(data) {
|
||||||
data.loginStore.removeLoginData("logoutDevices")
|
|
||||||
api.apiGet(TAG, PODLASIE_API_LOGOUT_DEVICES_ENDPOINT) {
|
|
||||||
doLogin()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json ->
|
api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json ->
|
||||||
val uuid = json.getString("Uuid")
|
val uuid = json.getString("Uuid")
|
||||||
val login = json.getString("Login")
|
val login = json.getString("Login")
|
||||||
|
@ -82,3 +68,4 @@ class PodlasieFirstLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan
|
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.currentTimeUnix
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_WEB_MAIN
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_MODE_VULCAN_API
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
import pl.szczodrzynski.edziennik.data.api.models.Data
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
||||||
|
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
import pl.szczodrzynski.edziennik.values
|
||||||
|
|
||||||
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
||||||
|
|
||||||
|
@ -26,27 +26,17 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||||
&& apiFingerprint[symbol].isNotNullNorEmpty()
|
&& apiFingerprint[symbol].isNotNullNorEmpty()
|
||||||
&& apiPrivateKey[symbol].isNotNullNorEmpty()
|
&& apiPrivateKey[symbol].isNotNullNorEmpty()
|
||||||
&& symbol.isNotNullNorEmpty()
|
&& symbol.isNotNullNorEmpty()
|
||||||
fun isHebeLoginValid() = hebePublicKey.isNotNullNorEmpty()
|
|
||||||
&& hebePrivateKey.isNotNullNorEmpty()
|
|
||||||
&& symbol.isNotNullNorEmpty()
|
|
||||||
|
|
||||||
override fun satisfyLoginMethods() {
|
override fun satisfyLoginMethods() {
|
||||||
loginMethods.clear()
|
loginMethods.clear()
|
||||||
if (isWebMainLoginValid()) {
|
|
||||||
loginMethods += LOGIN_METHOD_VULCAN_WEB_MAIN
|
|
||||||
}
|
|
||||||
if (isApiLoginValid()) {
|
if (isApiLoginValid()) {
|
||||||
loginMethods += LOGIN_METHOD_VULCAN_API
|
loginMethods += LOGIN_METHOD_VULCAN_API
|
||||||
}
|
}
|
||||||
if (isHebeLoginValid()) {
|
|
||||||
loginMethods += LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// during the first sync `profile.studentClassName` is already set
|
// during the first sync `profile.studentClassName` is already set
|
||||||
if (loginStore.mode == LOGIN_MODE_VULCAN_API
|
if (teamList.values().none { it.type == Team.TYPE_CLASS }) {
|
||||||
&& teamList.values().none { it.type == Team.TYPE_CLASS }) {
|
|
||||||
profile?.studentClassName?.also { name ->
|
profile?.studentClassName?.also { name ->
|
||||||
val id = Utils.crc16(name.toByteArray()).toLong()
|
val id = Utils.crc16(name.toByteArray()).toLong()
|
||||||
|
|
||||||
|
@ -65,17 +55,6 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||||
|
|
||||||
override fun generateUserCode() = "$schoolCode:$studentId"
|
override fun generateUserCode() = "$schoolCode:$studentId"
|
||||||
|
|
||||||
fun buildDeviceId(): String {
|
|
||||||
val deviceId = app.deviceId.padStart(16, '0')
|
|
||||||
val loginStoreId = loginStore.id.toString(16).padStart(4, '0')
|
|
||||||
val symbol = symbol?.crc16()?.toString(16)?.take(2) ?: "00"
|
|
||||||
return deviceId.substring(0..7) +
|
|
||||||
"-" + deviceId.substring(8..11) +
|
|
||||||
"-" + deviceId.substring(12..15) +
|
|
||||||
"-" + loginStoreId +
|
|
||||||
"-" + symbol + "6f72616e7a"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A UONET+ client symbol.
|
* A UONET+ client symbol.
|
||||||
*
|
*
|
||||||
|
@ -160,16 +139,6 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||||
get() { mStudentSemesterId = mStudentSemesterId ?: profile?.getStudentData("studentSemesterId", 0); return mStudentSemesterId ?: 0 }
|
get() { mStudentSemesterId = mStudentSemesterId ?: profile?.getStudentData("studentSemesterId", 0); return mStudentSemesterId ?: 0 }
|
||||||
set(value) { profile?.putStudentData("studentSemesterId", value) ?: return; mStudentSemesterId = value }
|
set(value) { profile?.putStudentData("studentSemesterId", value) ?: return; mStudentSemesterId = value }
|
||||||
|
|
||||||
private var mStudentUnitId: Int? = null
|
|
||||||
var studentUnitId: Int
|
|
||||||
get() { mStudentUnitId = mStudentUnitId ?: profile?.getStudentData("studentUnitId", 0); return mStudentUnitId ?: 0 }
|
|
||||||
set(value) { profile?.putStudentData("studentUnitId", value) ?: return; mStudentUnitId = value }
|
|
||||||
|
|
||||||
private var mStudentConstituentId: Int? = null
|
|
||||||
var studentConstituentId: Int
|
|
||||||
get() { mStudentConstituentId = mStudentConstituentId ?: profile?.getStudentData("studentConstituentId", 0); return mStudentConstituentId ?: 0 }
|
|
||||||
set(value) { profile?.putStudentData("studentConstituentId", value) ?: return; mStudentConstituentId = value }
|
|
||||||
|
|
||||||
private var mSemester1Id: Int? = null
|
private var mSemester1Id: Int? = null
|
||||||
var semester1Id: Int
|
var semester1Id: Int
|
||||||
get() { mSemester1Id = mSemester1Id ?: profile?.getStudentData("semester1Id", 0); return mSemester1Id ?: 0 }
|
get() { mSemester1Id = mSemester1Id ?: profile?.getStudentData("semester1Id", 0); return mSemester1Id ?: 0 }
|
||||||
|
@ -234,32 +203,6 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||||
get() { mApiPrivateKey = mApiPrivateKey ?: loginStore.getLoginData("apiPrivateKey", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiPrivateKey ?: mapOf() }
|
get() { mApiPrivateKey = mApiPrivateKey ?: loginStore.getLoginData("apiPrivateKey", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiPrivateKey ?: mapOf() }
|
||||||
set(value) { loginStore.putLoginData("apiPrivateKey", app.gson.toJson(value)); mApiPrivateKey = value }
|
set(value) { loginStore.putLoginData("apiPrivateKey", app.gson.toJson(value)); mApiPrivateKey = value }
|
||||||
|
|
||||||
/* _ _ _ _____ _____
|
|
||||||
| | | | | | /\ | __ \_ _|
|
|
||||||
| |__| | ___| |__ ___ / \ | |__) || |
|
|
||||||
| __ |/ _ \ '_ \ / _ \ / /\ \ | ___/ | |
|
|
||||||
| | | | __/ |_) | __/ / ____ \| | _| |_
|
|
||||||
|_| |_|\___|_.__/ \___| /_/ \_\_| |____*/
|
|
||||||
private var mHebePublicKey: String? = null
|
|
||||||
var hebePublicKey: String?
|
|
||||||
get() { mHebePublicKey = mHebePublicKey ?: loginStore.getLoginData("hebePublicKey", null); return mHebePublicKey }
|
|
||||||
set(value) { loginStore.putLoginData("hebePublicKey", value); mHebePublicKey = value }
|
|
||||||
|
|
||||||
private var mHebePrivateKey: String? = null
|
|
||||||
var hebePrivateKey: String?
|
|
||||||
get() { mHebePrivateKey = mHebePrivateKey ?: loginStore.getLoginData("hebePrivateKey", null); return mHebePrivateKey }
|
|
||||||
set(value) { loginStore.putLoginData("hebePrivateKey", value); mHebePrivateKey = value }
|
|
||||||
|
|
||||||
private var mHebePublicHash: String? = null
|
|
||||||
var hebePublicHash: String?
|
|
||||||
get() { mHebePublicHash = mHebePublicHash ?: loginStore.getLoginData("hebePublicHash", null); return mHebePublicHash }
|
|
||||||
set(value) { loginStore.putLoginData("hebePublicHash", value); mHebePublicHash = value }
|
|
||||||
|
|
||||||
private var mHebeContext: String? = null
|
|
||||||
var hebeContext: String?
|
|
||||||
get() { mHebeContext = mHebeContext ?: profile?.getStudentData("hebeContext", null); return mHebeContext }
|
|
||||||
set(value) { profile?.putStudentData("hebeContext", value) ?: return; mHebeContext = value }
|
|
||||||
|
|
||||||
val apiUrl: String?
|
val apiUrl: String?
|
||||||
get() {
|
get() {
|
||||||
val url = when (apiToken[symbol]?.substring(0, 3)) {
|
val url = when (apiToken[symbol]?.substring(0, 3)) {
|
||||||
|
@ -276,7 +219,6 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||||
"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"
|
||||||
"P90" -> "http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl"
|
"P90" -> "http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl"
|
||||||
"KO1" -> "https://uonetplus-komunikacja.eduportal.koszalin.pl"
|
|
||||||
"FK1", "FS1" -> "http://api.fakelog.cf"
|
"FK1", "FS1" -> "http://api.fakelog.cf"
|
||||||
"SZ9" -> "http://hack.szkolny.eu"
|
"SZ9" -> "http://hack.szkolny.eu"
|
||||||
else -> null
|
else -> null
|
||||||
|
@ -284,7 +226,7 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||||
return if (url != null) "$url/$symbol/" else loginStore.getLoginData("apiUrl", null)
|
return if (url != null) "$url/$symbol/" else loginStore.getLoginData("apiUrl", null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fullApiUrl: String
|
val fullApiUrl: String?
|
||||||
get() {
|
get() {
|
||||||
return "$apiUrl$schoolSymbol/"
|
return "$apiUrl$schoolSymbol/"
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanData
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiAttachments
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiAttachments
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiMessagesChangeStatus
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiMessagesChangeStatus
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiSendMessage
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiSendMessage
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.VulcanHebeMessagesChangeStatus
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin.VulcanFirstLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin.VulcanFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||||
|
@ -92,20 +91,6 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(message: MessageFull) {
|
override fun getMessage(message: MessageFull) {
|
||||||
if (loginStore.mode != LOGIN_MODE_VULCAN_API) {
|
|
||||||
login(LOGIN_METHOD_VULCAN_HEBE) {
|
|
||||||
if (message.seen) {
|
|
||||||
EventBus.getDefault().postSticky(MessageGetEvent(message))
|
|
||||||
completed()
|
|
||||||
return@login
|
|
||||||
}
|
|
||||||
VulcanHebeMessagesChangeStatus(data, message) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
login(LOGIN_METHOD_VULCAN_API) {
|
login(LOGIN_METHOD_VULCAN_API) {
|
||||||
if (message.attachmentIds != null) {
|
if (message.attachmentIds != null) {
|
||||||
VulcanApiMessagesChangeStatus(data, message) {
|
VulcanApiMessagesChangeStatus(data, message) {
|
||||||
|
|
|
@ -20,46 +20,25 @@ const val ENDPOINT_VULCAN_API_ATTENDANCE = 1080
|
||||||
const val ENDPOINT_VULCAN_API_MESSAGES_INBOX = 1090
|
const val ENDPOINT_VULCAN_API_MESSAGES_INBOX = 1090
|
||||||
const val ENDPOINT_VULCAN_API_MESSAGES_SENT = 1100
|
const val ENDPOINT_VULCAN_API_MESSAGES_SENT = 1100
|
||||||
const val ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS = 2010
|
const val ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS = 2010
|
||||||
const val ENDPOINT_VULCAN_HEBE_MAIN = 3000
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_ADDRESSBOOK = 3010
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_TIMETABLE = 3020
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_EXAMS = 3030
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_GRADES = 3040
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_HOMEWORK = 3060
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_ATTENDANCE = 3080
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX = 3090
|
|
||||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_SENT = 3100
|
|
||||||
|
|
||||||
val VulcanFeatures = listOf(
|
val VulcanFeatures = listOf(
|
||||||
// timetable
|
// timetable
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_TIMETABLE, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_TIMETABLE, listOf(
|
||||||
ENDPOINT_VULCAN_API_TIMETABLE to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_TIMETABLE to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API)),
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_TIMETABLE, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_TIMETABLE to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
// agenda
|
// agenda
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_AGENDA, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_AGENDA, listOf(
|
||||||
ENDPOINT_VULCAN_API_EVENTS to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_EVENTS to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API)),
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_AGENDA, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_EXAMS to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
// grades
|
// grades
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_GRADES, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_GRADES, listOf(
|
||||||
ENDPOINT_VULCAN_API_GRADES to LOGIN_METHOD_VULCAN_API,
|
ENDPOINT_VULCAN_API_GRADES to LOGIN_METHOD_VULCAN_API,
|
||||||
ENDPOINT_VULCAN_API_GRADES_SUMMARY to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_GRADES_SUMMARY to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API)),
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_GRADES, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_GRADES to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
// homework
|
// homework
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_HOMEWORK, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_HOMEWORK, listOf(
|
||||||
ENDPOINT_VULCAN_API_HOMEWORK to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_HOMEWORK to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API)),
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_HOMEWORK, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_HOMEWORK to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
// behaviour
|
// behaviour
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_BEHAVIOUR, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_BEHAVIOUR, listOf(
|
||||||
ENDPOINT_VULCAN_API_NOTICES to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_NOTICES to LOGIN_METHOD_VULCAN_API
|
||||||
|
@ -68,9 +47,6 @@ val VulcanFeatures = listOf(
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_ATTENDANCE, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_ATTENDANCE, listOf(
|
||||||
ENDPOINT_VULCAN_API_ATTENDANCE to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_ATTENDANCE to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API)),
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_ATTENDANCE, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_ATTENDANCE to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
// messages
|
// messages
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_INBOX, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_INBOX, listOf(
|
||||||
ENDPOINT_VULCAN_API_MESSAGES_INBOX to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_MESSAGES_INBOX to LOGIN_METHOD_VULCAN_API
|
||||||
|
@ -78,12 +54,6 @@ val VulcanFeatures = listOf(
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_SENT, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_SENT, listOf(
|
||||||
ENDPOINT_VULCAN_API_MESSAGES_SENT to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_MESSAGES_SENT to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API)),
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_INBOX, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_MESSAGES_SENT, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_MESSAGES_SENT to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE)),
|
|
||||||
|
|
||||||
// push config
|
// push config
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_PUSH_CONFIG, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_PUSH_CONFIG, listOf(
|
||||||
|
@ -102,11 +72,7 @@ val VulcanFeatures = listOf(
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
|
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
|
||||||
ENDPOINT_VULCAN_API_UPDATE_SEMESTER to LOGIN_METHOD_VULCAN_API,
|
ENDPOINT_VULCAN_API_UPDATE_SEMESTER to LOGIN_METHOD_VULCAN_API,
|
||||||
ENDPOINT_VULCAN_API_DICTIONARIES to LOGIN_METHOD_VULCAN_API
|
ENDPOINT_VULCAN_API_DICTIONARIES to LOGIN_METHOD_VULCAN_API
|
||||||
), listOf(LOGIN_METHOD_VULCAN_API)),
|
), listOf(LOGIN_METHOD_VULCAN_API))
|
||||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_MAIN to LOGIN_METHOD_VULCAN_HEBE,
|
|
||||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
), listOf(LOGIN_METHOD_VULCAN_HEBE))
|
|
||||||
/*Feature(LOGIN_TYPE_VULCAN, FEATURE_STUDENT_INFO, listOf(
|
/*Feature(LOGIN_TYPE_VULCAN, FEATURE_STUDENT_INFO, listOf(
|
||||||
ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB
|
ENDPOINT_VULCAN_API to LOGIN_METHOD_VULCAN_WEB
|
||||||
), listOf(LOGIN_METHOD_VULCAN_WEB)),
|
), listOf(LOGIN_METHOD_VULCAN_WEB)),
|
||||||
|
|
|
@ -7,9 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.*
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.*
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web.VulcanWebLuckyNumber
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web.VulcanWebLuckyNumber
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
|
||||||
class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
|
@ -17,30 +15,8 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
private const val TAG = "VulcanData"
|
private const val TAG = "VulcanData"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var firstSemesterSync = false
|
|
||||||
private val firstSemesterSyncExclude = listOf(
|
|
||||||
ENDPOINT_VULCAN_HEBE_MAIN,
|
|
||||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK,
|
|
||||||
ENDPOINT_VULCAN_HEBE_TIMETABLE,
|
|
||||||
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX,
|
|
||||||
ENDPOINT_VULCAN_HEBE_MESSAGES_SENT
|
|
||||||
)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (data.studentSemesterNumber == 2 && data.profile?.empty != false) {
|
nextEndpoint(onSuccess)
|
||||||
firstSemesterSync = true
|
|
||||||
// set to sync 1st semester first
|
|
||||||
data.studentSemesterId = data.semester1Id
|
|
||||||
data.studentSemesterNumber = 1
|
|
||||||
}
|
|
||||||
nextEndpoint {
|
|
||||||
if (firstSemesterSync) {
|
|
||||||
// at the end, set back 2nd semester
|
|
||||||
data.studentSemesterId = data.semester2Id
|
|
||||||
data.studentSemesterNumber = 2
|
|
||||||
}
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun nextEndpoint(onSuccess: () -> Unit) {
|
private fun nextEndpoint(onSuccess: () -> Unit) {
|
||||||
|
@ -54,21 +30,7 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
}
|
}
|
||||||
val id = data.targetEndpointIds.firstKey()
|
val id = data.targetEndpointIds.firstKey()
|
||||||
val lastSync = data.targetEndpointIds.remove(id)
|
val lastSync = data.targetEndpointIds.remove(id)
|
||||||
useEndpoint(id, lastSync) {
|
useEndpoint(id, lastSync) { endpointId ->
|
||||||
if (firstSemesterSync && id !in firstSemesterSyncExclude) {
|
|
||||||
// sync 2nd semester after every endpoint
|
|
||||||
data.studentSemesterId = data.semester2Id
|
|
||||||
data.studentSemesterNumber = 2
|
|
||||||
useEndpoint(id, lastSync) {
|
|
||||||
// set 1st semester back for the next endpoint
|
|
||||||
data.studentSemesterId = data.semester1Id
|
|
||||||
data.studentSemesterNumber = 1
|
|
||||||
// progress further
|
|
||||||
data.progress(data.progressStep)
|
|
||||||
nextEndpoint(onSuccess)
|
|
||||||
}
|
|
||||||
return@useEndpoint
|
|
||||||
}
|
|
||||||
data.progress(data.progressStep)
|
data.progress(data.progressStep)
|
||||||
nextEndpoint(onSuccess)
|
nextEndpoint(onSuccess)
|
||||||
}
|
}
|
||||||
|
@ -129,51 +91,6 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
||||||
VulcanWebLuckyNumber(data, lastSync, onSuccess)
|
VulcanWebLuckyNumber(data, lastSync, onSuccess)
|
||||||
}
|
}
|
||||||
ENDPOINT_VULCAN_HEBE_MAIN -> {
|
|
||||||
if (data.profile == null) {
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_MAIN)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
|
|
||||||
VulcanHebeMain(data, lastSync).getStudents(
|
|
||||||
profile = data.profile,
|
|
||||||
profileList = null
|
|
||||||
) {
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_MAIN)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
|
||||||
VulcanHebeAddressbook(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_TIMETABLE -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
|
||||||
VulcanHebeTimetable(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_EXAMS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
|
||||||
VulcanHebeExams(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_GRADES -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
|
||||||
VulcanHebeGrades(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_HOMEWORK -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_homework)
|
|
||||||
VulcanHebeHomework(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
|
||||||
VulcanHebeMessages(data, lastSync, onSuccess).getMessages(Message.TYPE_RECEIVED)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_MESSAGES_SENT -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
|
|
||||||
VulcanHebeMessages(data, lastSync, onSuccess).getMessages(Message.TYPE_SENT)
|
|
||||||
}
|
|
||||||
ENDPOINT_VULCAN_HEBE_ATTENDANCE -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
|
||||||
VulcanHebeAttendance(data, lastSync, onSuccess)
|
|
||||||
}
|
|
||||||
else -> onSuccess(endpointId)
|
else -> onSuccess(endpointId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,360 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data
|
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.core.util.set
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonElement
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import im.wangchao.mhttp.Request
|
|
||||||
import im.wangchao.mhttp.Response
|
|
||||||
import im.wangchao.mhttp.body.MediaTypeUtils
|
|
||||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
|
||||||
import io.github.wulkanowy.signer.hebe.getSignatureHeaders
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.HebeFilterType
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Subject
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.URLEncoder
|
|
||||||
import java.time.Instant
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.ZoneId
|
|
||||||
import java.time.ZonedDateTime
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebe"
|
|
||||||
}
|
|
||||||
|
|
||||||
val profileId
|
|
||||||
get() = data.profile?.id ?: -1
|
|
||||||
|
|
||||||
val profile
|
|
||||||
get() = data.profile
|
|
||||||
|
|
||||||
fun getDateTime(json: JsonObject?, key: String, default: Long = System.currentTimeMillis()): Long {
|
|
||||||
val date = json.getJsonObject(key)
|
|
||||||
return date.getLong("Timestamp") ?: return default
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDate(json: JsonObject?, key: String): Date? {
|
|
||||||
val date = json.getJsonObject(key)
|
|
||||||
return date.getString("Date")?.let { Date.fromY_m_d(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeacherId(json: JsonObject?, key: String): Long? {
|
|
||||||
val teacher = json.getJsonObject(key)
|
|
||||||
val teacherId = teacher.getLong("Id") ?: return null
|
|
||||||
if (data.teacherList[teacherId] == null) {
|
|
||||||
data.teacherList[teacherId] = Teacher(
|
|
||||||
data.profileId,
|
|
||||||
teacherId,
|
|
||||||
teacher.getString("Name") ?: "",
|
|
||||||
teacher.getString("Surname") ?: ""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return teacherId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSubjectId(json: JsonObject?, key: String): Long? {
|
|
||||||
val subject = json.getJsonObject(key)
|
|
||||||
val subjectId = subject.getLong("Id") ?: return null
|
|
||||||
if (data.subjectList[subjectId] == null) {
|
|
||||||
data.subjectList[subjectId] = Subject(
|
|
||||||
data.profileId,
|
|
||||||
subjectId,
|
|
||||||
subject.getString("Name") ?: "",
|
|
||||||
subject.getString("Kod") ?: ""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return subjectId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeamId(json: JsonObject?, key: String): Long? {
|
|
||||||
val team = json.getJsonObject(key)
|
|
||||||
val teamId = team.getLong("Id") ?: return null
|
|
||||||
if (data.teamList[teamId] == null) {
|
|
||||||
var name = team.getString("Shortcut")
|
|
||||||
?: team.getString("Name")
|
|
||||||
?: ""
|
|
||||||
name = "${profile?.studentClassName ?: ""} $name"
|
|
||||||
data.teamList[teamId] = Team(
|
|
||||||
data.profileId,
|
|
||||||
teamId,
|
|
||||||
name,
|
|
||||||
Team.TYPE_VIRTUAL,
|
|
||||||
"${data.schoolCode}:$name",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return teamId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getClassId(json: JsonObject?, key: String): Long? {
|
|
||||||
val team = json.getJsonObject(key)
|
|
||||||
val teamId = team.getLong("Id") ?: return null
|
|
||||||
if (data.teamList[teamId] == null) {
|
|
||||||
val name = data.profile?.studentClassName
|
|
||||||
?: team.getString("Name")
|
|
||||||
?: ""
|
|
||||||
data.teamList[teamId] = Team(
|
|
||||||
data.profileId,
|
|
||||||
teamId,
|
|
||||||
name,
|
|
||||||
Team.TYPE_CLASS,
|
|
||||||
"${data.schoolCode}:$name",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return teamId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLessonRange(json: JsonObject?, key: String): LessonRange? {
|
|
||||||
val timeslot = json.getJsonObject(key)
|
|
||||||
val position = timeslot.getInt("Position") ?: return null
|
|
||||||
val start = timeslot.getString("Start") ?: return null
|
|
||||||
val end = timeslot.getString("End") ?: return null
|
|
||||||
val lessonRange = LessonRange(
|
|
||||||
data.profileId,
|
|
||||||
position,
|
|
||||||
Time.fromH_m(start),
|
|
||||||
Time.fromH_m(end)
|
|
||||||
)
|
|
||||||
data.lessonRanges[position] = lessonRange
|
|
||||||
return lessonRange
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSemester(json: JsonObject?): Int {
|
|
||||||
val periodId = json.getInt("PeriodId") ?: return 1
|
|
||||||
return if (periodId == data.semester1Id)
|
|
||||||
1
|
|
||||||
else
|
|
||||||
2
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> apiRequest(
|
|
||||||
tag: String,
|
|
||||||
endpoint: String,
|
|
||||||
method: Int = GET,
|
|
||||||
payload: JsonElement? = null,
|
|
||||||
baseUrl: Boolean = false,
|
|
||||||
firebaseToken: String? = null,
|
|
||||||
crossinline onSuccess: (json: T, response: Response?) -> Unit
|
|
||||||
) {
|
|
||||||
val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint"
|
|
||||||
|
|
||||||
d(tag, "Request: Vulcan/Hebe - $url")
|
|
||||||
|
|
||||||
val privateKey = data.hebePrivateKey
|
|
||||||
val publicHash = data.hebePublicHash
|
|
||||||
|
|
||||||
if (privateKey == null || publicHash == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val timestamp = ZonedDateTime.now(ZoneId.of("GMT"))
|
|
||||||
val timestampMillis = timestamp.toInstant().toEpochMilli()
|
|
||||||
val timestampIso = timestamp.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"))
|
|
||||||
|
|
||||||
val finalPayload = if (payload != null) {
|
|
||||||
JsonObject(
|
|
||||||
"AppName" to VULCAN_HEBE_APP_NAME,
|
|
||||||
"AppVersion" to VULCAN_HEBE_APP_VERSION,
|
|
||||||
"CertificateId" to publicHash,
|
|
||||||
"Envelope" to payload,
|
|
||||||
"FirebaseToken" to (firebaseToken ?: data.app.config.sync.tokenVulcanHebe),
|
|
||||||
"API" to 1,
|
|
||||||
"RequestId" to UUID.randomUUID().toString(),
|
|
||||||
"Timestamp" to timestampMillis,
|
|
||||||
"TimestampFormatted" to timestampIso
|
|
||||||
)
|
|
||||||
} else null
|
|
||||||
val jsonString = finalPayload?.toString()
|
|
||||||
|
|
||||||
val headers = getSignatureHeaders(
|
|
||||||
publicHash,
|
|
||||||
privateKey,
|
|
||||||
jsonString,
|
|
||||||
endpoint,
|
|
||||||
timestamp
|
|
||||||
)
|
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
|
||||||
if (json == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val status = json.getJsonObject("Status")
|
|
||||||
if (status?.getInt("Code") != 0) {
|
|
||||||
data.error(ApiError(tag, ERROR_VULCAN_HEBE_OTHER)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(json.toString()))
|
|
||||||
}
|
|
||||||
|
|
||||||
val envelope = when (T::class.java) {
|
|
||||||
JsonObject::class.java -> json.getJsonObject("Envelope") as T
|
|
||||||
JsonArray::class.java -> json.getJsonArray("Envelope") as T
|
|
||||||
java.lang.Boolean::class.java -> json.getBoolean("Envelope") as T
|
|
||||||
else -> {
|
|
||||||
data.error(ApiError(tag, ERROR_RESPONSE_EMPTY)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(json)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
onSuccess(envelope, response)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
data.error(ApiError(tag, EXCEPTION_VULCAN_HEBE_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(url)
|
|
||||||
.userAgent(VULCAN_HEBE_USER_AGENT)
|
|
||||||
.addHeader("vOS", "Android")
|
|
||||||
.addHeader("vDeviceModel", Build.MODEL)
|
|
||||||
.addHeader("vAPI", "1")
|
|
||||||
.apply {
|
|
||||||
if (data.hebeContext != null)
|
|
||||||
addHeader("vContext", data.hebeContext)
|
|
||||||
headers.forEach {
|
|
||||||
addHeader(it.key, it.value)
|
|
||||||
}
|
|
||||||
when (method) {
|
|
||||||
GET -> get()
|
|
||||||
POST -> {
|
|
||||||
post()
|
|
||||||
setTextBody(jsonString, MediaTypeUtils.APPLICATION_JSON)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
|
|
||||||
.allowErrorCode(HttpURLConnection.HTTP_UNAVAILABLE)
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> apiGet(
|
|
||||||
tag: String,
|
|
||||||
endpoint: String,
|
|
||||||
query: Map<String, String> = mapOf(),
|
|
||||||
baseUrl: Boolean = false,
|
|
||||||
firebaseToken: String? = null,
|
|
||||||
crossinline onSuccess: (json: T, response: Response?) -> Unit
|
|
||||||
) {
|
|
||||||
val queryPath = query.map {
|
|
||||||
it.key + "=" + URLEncoder.encode(it.value, "UTF-8").replace("+", "%20")
|
|
||||||
}.join("&")
|
|
||||||
apiRequest(
|
|
||||||
tag,
|
|
||||||
if (query.isNotEmpty()) "$endpoint?$queryPath" else endpoint,
|
|
||||||
baseUrl = baseUrl,
|
|
||||||
firebaseToken = firebaseToken,
|
|
||||||
onSuccess = onSuccess
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> apiPost(
|
|
||||||
tag: String,
|
|
||||||
endpoint: String,
|
|
||||||
payload: JsonElement,
|
|
||||||
baseUrl: Boolean = false,
|
|
||||||
firebaseToken: String? = null,
|
|
||||||
crossinline onSuccess: (json: T, response: Response?) -> Unit
|
|
||||||
) {
|
|
||||||
apiRequest(
|
|
||||||
tag,
|
|
||||||
endpoint,
|
|
||||||
method = POST,
|
|
||||||
payload,
|
|
||||||
baseUrl = baseUrl,
|
|
||||||
firebaseToken = firebaseToken,
|
|
||||||
onSuccess = onSuccess
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun apiGetList(
|
|
||||||
tag: String,
|
|
||||||
endpoint: String,
|
|
||||||
filterType: HebeFilterType? = null,
|
|
||||||
dateFrom: Date? = null,
|
|
||||||
dateTo: Date? = null,
|
|
||||||
lastSync: Long? = null,
|
|
||||||
folder: Int? = null,
|
|
||||||
params: Map<String, String> = mapOf(),
|
|
||||||
includeFilterType: Boolean = true,
|
|
||||||
onSuccess: (data: List<JsonObject>, response: Response?) -> Unit
|
|
||||||
) {
|
|
||||||
val url = if (includeFilterType && filterType != null)
|
|
||||||
"$endpoint/${filterType.endpoint}"
|
|
||||||
else endpoint
|
|
||||||
|
|
||||||
val query = params.toMutableMap()
|
|
||||||
|
|
||||||
when (filterType) {
|
|
||||||
HebeFilterType.BY_PUPIL -> {
|
|
||||||
query["unitId"] = data.studentUnitId.toString()
|
|
||||||
query["pupilId"] = data.studentId.toString()
|
|
||||||
query["periodId"] = data.studentSemesterId.toString()
|
|
||||||
}
|
|
||||||
HebeFilterType.BY_PERSON -> {
|
|
||||||
query["loginId"] = data.studentLoginId.toString()
|
|
||||||
}
|
|
||||||
HebeFilterType.BY_PERIOD -> {
|
|
||||||
query["periodId"] = data.studentSemesterId.toString()
|
|
||||||
query["pupilId"] = data.studentId.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dateFrom != null)
|
|
||||||
query["dateFrom"] = dateFrom.stringY_m_d
|
|
||||||
if (dateTo != null)
|
|
||||||
query["dateTo"] = dateTo.stringY_m_d
|
|
||||||
|
|
||||||
if (folder != null)
|
|
||||||
query["folder"] = folder.toString()
|
|
||||||
|
|
||||||
query["lastId"] = "-2147483648" // don't ask, it's just Vulcan
|
|
||||||
query["pageSize"] = "500"
|
|
||||||
query["lastSyncDate"] = LocalDateTime
|
|
||||||
.ofInstant(Instant.ofEpochMilli(lastSync ?: 0), ZoneId.systemDefault())
|
|
||||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
|
||||||
|
|
||||||
apiGet(tag, url, query) { json: JsonArray, response ->
|
|
||||||
onSuccess(json.map { it.asJsonObject }, response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
enum class HebeFilterType(val endpoint: String) {
|
|
||||||
BY_PUPIL("byPupil"),
|
|
||||||
BY_PERSON("byPerson"),
|
|
||||||
BY_PERIOD("byPeriod")
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import androidx.core.util.set
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_ADDRESSBOOK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_ADDRESSBOOK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_EDUCATOR
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_OTHER
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_PARENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_PARENTS_COUNCIL
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_STUDENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_TEACHER
|
|
||||||
import kotlin.text.replace
|
|
||||||
|
|
||||||
class VulcanHebeAddressbook(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeAddressbook"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.removeUnitName(unitName: String?): String {
|
|
||||||
return (unitName ?: data.schoolShort)?.let {
|
|
||||||
this.replace("($it)", "").trim()
|
|
||||||
} ?: this
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_ADDRESSBOOK,
|
|
||||||
HebeFilterType.BY_PERSON,
|
|
||||||
lastSync = lastSync,
|
|
||||||
includeFilterType = false
|
|
||||||
) { list, _ ->
|
|
||||||
list.forEach { person ->
|
|
||||||
val id = person.getString("Id") ?: return@forEach
|
|
||||||
val loginId = person.getString("LoginId") ?: return@forEach
|
|
||||||
|
|
||||||
val idType = id.split("-")
|
|
||||||
.getOrNull(0)
|
|
||||||
val idLong = id.split("-")
|
|
||||||
.getOrNull(1)
|
|
||||||
?.toLongOrNull()
|
|
||||||
?: return@forEach
|
|
||||||
|
|
||||||
val typeBase = when (idType) {
|
|
||||||
"e" -> TYPE_TEACHER
|
|
||||||
"c" -> TYPE_PARENT
|
|
||||||
"p" -> TYPE_STUDENT
|
|
||||||
else -> TYPE_OTHER
|
|
||||||
}
|
|
||||||
|
|
||||||
val name = person.getString("Name") ?: ""
|
|
||||||
val surname = person.getString("Surname") ?: ""
|
|
||||||
val namePrefix = "$surname $name - "
|
|
||||||
|
|
||||||
val teacher = data.teacherList[idLong] ?: Teacher(
|
|
||||||
data.profileId,
|
|
||||||
idLong,
|
|
||||||
name,
|
|
||||||
surname,
|
|
||||||
loginId
|
|
||||||
).also {
|
|
||||||
data.teacherList[idLong] = it
|
|
||||||
}
|
|
||||||
|
|
||||||
person.getJsonArray("Roles")?.asJsonObjectList()?.onEach { role ->
|
|
||||||
var roleText: String? = null
|
|
||||||
val unitName = role.getString("ConstituentUnitSymbol")
|
|
||||||
|
|
||||||
val personType = when (role.getInt("RoleOrder")) {
|
|
||||||
0 -> { /* Wychowawca */
|
|
||||||
roleText = role.getString("ClassSymbol")
|
|
||||||
?.removeUnitName(unitName)
|
|
||||||
TYPE_EDUCATOR
|
|
||||||
}
|
|
||||||
1 -> TYPE_TEACHER /* Nauczyciel */
|
|
||||||
2 -> return@onEach /* Pracownik */
|
|
||||||
3 -> { /* Rada rodziców */
|
|
||||||
roleText = role.getString("Address")
|
|
||||||
?.removeUnitName(unitName)
|
|
||||||
?.removePrefix(namePrefix)
|
|
||||||
?.trim()
|
|
||||||
TYPE_PARENTS_COUNCIL
|
|
||||||
}
|
|
||||||
5 -> {
|
|
||||||
roleText = role.getString("RoleName")
|
|
||||||
?.plus(" - ")
|
|
||||||
?.plus(
|
|
||||||
role.getString("Address")
|
|
||||||
?.removeUnitName(unitName)
|
|
||||||
?.removePrefix(namePrefix)
|
|
||||||
?.trim()
|
|
||||||
)
|
|
||||||
TYPE_STUDENT
|
|
||||||
}
|
|
||||||
else -> TYPE_OTHER
|
|
||||||
}
|
|
||||||
|
|
||||||
teacher.setTeacherType(personType)
|
|
||||||
teacher.typeDescription = roleText
|
|
||||||
}
|
|
||||||
|
|
||||||
if (teacher.type == 0)
|
|
||||||
teacher.setTeacherType(typeBase)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK, 2 * DAY)
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2021-2-21
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_ATTENDANCE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_ATTENDANCE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
|
|
||||||
class VulcanHebeAttendance(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeAttendance"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
val semesterNumber = data.studentSemesterNumber
|
|
||||||
val startDate = profile?.getSemesterStart(semesterNumber)
|
|
||||||
val endDate = profile?.getSemesterEnd(semesterNumber)
|
|
||||||
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_ATTENDANCE,
|
|
||||||
HebeFilterType.BY_PUPIL,
|
|
||||||
dateFrom = startDate,
|
|
||||||
dateTo = endDate,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { list, _ ->
|
|
||||||
list.forEach { attendance ->
|
|
||||||
val id = attendance.getLong("AuxPresenceId") ?: return@forEach
|
|
||||||
val type = attendance.getJsonObject("PresenceType") ?: return@forEach
|
|
||||||
val baseType = getBaseType(type)
|
|
||||||
val typeName = type.getString("Name") ?: return@forEach
|
|
||||||
val typeCategoryId = type.getLong("CategoryId") ?: return@forEach
|
|
||||||
val typeSymbol = type.getString("Symbol") ?: return@forEach
|
|
||||||
val typeShort = when (typeCategoryId.toInt()) {
|
|
||||||
6, 8 -> typeSymbol
|
|
||||||
else -> data.app.attendanceManager.getTypeShort(baseType)
|
|
||||||
}
|
|
||||||
val typeColor = when (typeCategoryId.toInt()) {
|
|
||||||
1 -> 0xffffffff // obecność
|
|
||||||
2 -> 0xffffa687 // nieobecność
|
|
||||||
3 -> 0xfffcc150 // nieobecność usprawiedliwiona
|
|
||||||
4 -> 0xffede049 // spóźnienie
|
|
||||||
5 -> 0xffbbdd5f // spóźnienie usprawiedliwione
|
|
||||||
6 -> 0xffa9c9fd // nieobecny z przyczyn szkolnych
|
|
||||||
7 -> 0xffddbbe5 // zwolniony
|
|
||||||
8 -> 0xffffffff // usunięty wpis
|
|
||||||
else -> null
|
|
||||||
}?.toInt()
|
|
||||||
val date = getDate(attendance, "Day") ?: return@forEach
|
|
||||||
val lessonRange = getLessonRange(attendance, "TimeSlot")
|
|
||||||
val startTime = lessonRange?.startTime
|
|
||||||
val semester = profile?.dateToSemester(date) ?: return@forEach
|
|
||||||
val teacherId = attendance.getJsonObject("TeacherPrimary")?.getLong("Id") ?: -1
|
|
||||||
val subjectId = attendance.getJsonObject("Subject")?.getLong("Id") ?: -1
|
|
||||||
val addedDate = getDateTime(attendance, "DateModify")
|
|
||||||
val lessonNumber = lessonRange?.lessonNumber
|
|
||||||
val isCounted = attendance.getBoolean("CalculatePresence")
|
|
||||||
?: (baseType != Attendance.TYPE_RELEASED)
|
|
||||||
|
|
||||||
val attendanceObject = Attendance(
|
|
||||||
profileId = profileId,
|
|
||||||
id = id,
|
|
||||||
baseType = baseType,
|
|
||||||
typeName = typeName,
|
|
||||||
typeShort = typeShort,
|
|
||||||
typeSymbol = typeSymbol,
|
|
||||||
typeColor = typeColor,
|
|
||||||
date = date,
|
|
||||||
startTime = startTime,
|
|
||||||
semester = semester,
|
|
||||||
teacherId = teacherId,
|
|
||||||
subjectId = subjectId,
|
|
||||||
addedDate = addedDate
|
|
||||||
).also {
|
|
||||||
it.lessonNumber = lessonNumber
|
|
||||||
it.isCounted = isCounted
|
|
||||||
}
|
|
||||||
|
|
||||||
data.attendanceList.add(attendanceObject)
|
|
||||||
if (baseType != Attendance.TYPE_PRESENT) {
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_ATTENDANCE,
|
|
||||||
attendanceObject.id,
|
|
||||||
profile?.empty ?: true
|
|
||||||
|| baseType == Attendance.TYPE_PRESENT_CUSTOM
|
|
||||||
|| baseType == Attendance.TYPE_UNKNOWN,
|
|
||||||
profile?.empty ?: true
|
|
||||||
|| baseType == Attendance.TYPE_PRESENT_CUSTOM
|
|
||||||
|| baseType == Attendance.TYPE_UNKNOWN
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_ATTENDANCE, SYNC_ALWAYS)
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_ATTENDANCE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBaseType(attendanceType: JsonObject): Int {
|
|
||||||
val absent = attendanceType.getBoolean("Absence") ?: false
|
|
||||||
val excused = attendanceType.getBoolean("AbsenceJustified") ?: false
|
|
||||||
return if (absent) {
|
|
||||||
if (excused)
|
|
||||||
Attendance.TYPE_ABSENT_EXCUSED
|
|
||||||
else
|
|
||||||
Attendance.TYPE_ABSENT
|
|
||||||
} else {
|
|
||||||
val belated = attendanceType.getBoolean("Late") ?: false
|
|
||||||
val released = attendanceType.getBoolean("LegalAbsence") ?: false
|
|
||||||
val present = attendanceType.getBoolean("Presence") ?: true
|
|
||||||
if (belated)
|
|
||||||
if (excused)
|
|
||||||
Attendance.TYPE_BELATED_EXCUSED
|
|
||||||
else
|
|
||||||
Attendance.TYPE_BELATED
|
|
||||||
else if (released)
|
|
||||||
Attendance.TYPE_RELEASED
|
|
||||||
else if (present)
|
|
||||||
if (attendanceType.getInt("CategoryId") != 1)
|
|
||||||
Attendance.TYPE_PRESENT_CUSTOM
|
|
||||||
else
|
|
||||||
Attendance.TYPE_PRESENT
|
|
||||||
else
|
|
||||||
Attendance.TYPE_UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_EXAMS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_EXAMS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
|
|
||||||
class VulcanHebeExams(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeExams"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_EXAMS,
|
|
||||||
HebeFilterType.BY_PUPIL,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { list, _ ->
|
|
||||||
list.forEach { exam ->
|
|
||||||
val id = exam.getLong("Id") ?: return@forEach
|
|
||||||
val eventDate = getDate(exam, "Deadline") ?: return@forEach
|
|
||||||
val subjectId = getSubjectId(exam, "Subject") ?: -1
|
|
||||||
val teacherId = getTeacherId(exam, "Creator") ?: -1
|
|
||||||
val teamId = getTeamId(exam, "Distribution")
|
|
||||||
?: getClassId(exam, "Class")
|
|
||||||
?: data.teamClass?.id
|
|
||||||
?: -1
|
|
||||||
val topic = exam.getString("Content")?.trim() ?: ""
|
|
||||||
|
|
||||||
val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
|
|
||||||
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
|
|
||||||
|
|
||||||
val type = when (exam.getString("Type")) {
|
|
||||||
"Praca klasowa",
|
|
||||||
"Sprawdzian" -> Event.TYPE_EXAM
|
|
||||||
"Kartkówka" -> Event.TYPE_SHORT_QUIZ
|
|
||||||
else -> Event.TYPE_DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
val eventObject = Event(
|
|
||||||
profileId = profileId,
|
|
||||||
id = id,
|
|
||||||
date = eventDate,
|
|
||||||
time = startTime,
|
|
||||||
topic = topic,
|
|
||||||
color = null,
|
|
||||||
type = type,
|
|
||||||
teacherId = teacherId,
|
|
||||||
subjectId = subjectId,
|
|
||||||
teamId = teamId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_EVENT,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: true,
|
|
||||||
profile?.empty ?: true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_EXAMS, SYNC_ALWAYS)
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_EXAMS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,121 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_GRADES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Grade
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import java.text.DecimalFormat
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
class VulcanHebeGrades(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeGrades"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_GRADES,
|
|
||||||
HebeFilterType.BY_PUPIL,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { list, _ ->
|
|
||||||
list.forEach { grade ->
|
|
||||||
val id = grade.getLong("Id") ?: return@forEach
|
|
||||||
|
|
||||||
val column = grade.getJsonObject("Column")
|
|
||||||
val category = column.getJsonObject("Category")
|
|
||||||
val categoryText = category.getString("Name")
|
|
||||||
|
|
||||||
val teacherId = getTeacherId(grade, "Creator") ?: -1
|
|
||||||
val subjectId = getSubjectId(column, "Subject") ?: -1
|
|
||||||
|
|
||||||
val description = column.getString("Name")
|
|
||||||
val comment = grade.getString("Comment")
|
|
||||||
var value = grade.getFloat("Value")
|
|
||||||
var weight = column.getFloat("Weight") ?: 0.0f
|
|
||||||
val numerator = grade.getFloat("Numerator ")
|
|
||||||
val denominator = grade.getFloat("Denominator")
|
|
||||||
val addedDate = getDateTime(grade, "DateModify")
|
|
||||||
|
|
||||||
var finalDescription = ""
|
|
||||||
|
|
||||||
var name = when (numerator != null && denominator != null) {
|
|
||||||
true -> {
|
|
||||||
value = numerator / denominator
|
|
||||||
finalDescription += DecimalFormat("#.##").format(numerator) +
|
|
||||||
"/" + DecimalFormat("#.##").format(denominator)
|
|
||||||
weight = 0.0f
|
|
||||||
(value * 100).roundToInt().toString() + "%"
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
if (value == null) weight = 0.0f
|
|
||||||
|
|
||||||
grade.getString("Content") ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comment?.also {
|
|
||||||
if (name == "") name = it
|
|
||||||
else finalDescription = (if (finalDescription == "") "" else " ") + it
|
|
||||||
}
|
|
||||||
|
|
||||||
description?.also {
|
|
||||||
finalDescription = (if (finalDescription == "") "" else " - ") + it
|
|
||||||
}
|
|
||||||
|
|
||||||
val columnColor = column.getInt("Color") ?: 0
|
|
||||||
val color = if (columnColor == 0)
|
|
||||||
when (name) {
|
|
||||||
"1-", "1", "1+" -> 0xffd65757
|
|
||||||
"2-", "2", "2+" -> 0xff9071b3
|
|
||||||
"3-", "3", "3+" -> 0xffd2ab24
|
|
||||||
"4-", "4", "4+" -> 0xff50b6d6
|
|
||||||
"5-", "5", "5+" -> 0xff2cbd92
|
|
||||||
"6-", "6", "6+" -> 0xff91b43c
|
|
||||||
else -> 0xff3D5F9C
|
|
||||||
}.toInt()
|
|
||||||
else
|
|
||||||
columnColor
|
|
||||||
|
|
||||||
val gradeObject = Grade(
|
|
||||||
profileId = profileId,
|
|
||||||
id = id,
|
|
||||||
name = name,
|
|
||||||
type = Grade.TYPE_NORMAL,
|
|
||||||
value = value ?: 0.0f,
|
|
||||||
weight = weight,
|
|
||||||
color = color,
|
|
||||||
category = categoryText,
|
|
||||||
description = finalDescription,
|
|
||||||
comment = null,
|
|
||||||
semester = getSemester(column),
|
|
||||||
teacherId = teacherId,
|
|
||||||
subjectId = subjectId,
|
|
||||||
addedDate = addedDate
|
|
||||||
)
|
|
||||||
|
|
||||||
data.gradeList.add(gradeObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_GRADE,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: true,
|
|
||||||
profile?.empty ?: true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_GRADES, SYNC_ALWAYS)
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_GRADES)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_HOMEWORK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.getLong
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
|
|
||||||
class VulcanHebeHomework(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeHomework"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_HOMEWORK,
|
|
||||||
HebeFilterType.BY_PUPIL,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { list, _ ->
|
|
||||||
list.forEach { exam ->
|
|
||||||
val id = exam.getLong("IdHomework") ?: return@forEach
|
|
||||||
val eventDate = getDate(exam, "Deadline") ?: return@forEach
|
|
||||||
val subjectId = getSubjectId(exam, "Subject") ?: -1
|
|
||||||
val teacherId = getTeacherId(exam, "Creator") ?: -1
|
|
||||||
val teamId = data.teamClass?.id ?: -1
|
|
||||||
val topic = exam.getString("Content")?.trim() ?: ""
|
|
||||||
|
|
||||||
val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
|
|
||||||
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
|
|
||||||
|
|
||||||
val eventObject = Event(
|
|
||||||
profileId = profileId,
|
|
||||||
id = id,
|
|
||||||
date = eventDate,
|
|
||||||
time = startTime,
|
|
||||||
topic = topic,
|
|
||||||
color = null,
|
|
||||||
type = Event.TYPE_HOMEWORK,
|
|
||||||
teacherId = teacherId,
|
|
||||||
subjectId = subjectId,
|
|
||||||
teamId = teamId
|
|
||||||
)
|
|
||||||
|
|
||||||
data.eventList.add(eventObject)
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_HOMEWORK,
|
|
||||||
id,
|
|
||||||
profile?.empty ?: true,
|
|
||||||
profile?.empty ?: true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_HOMEWORK, SYNC_ALWAYS)
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_HOMEWORK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_VULCAN
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MAIN
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_MAIN
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class VulcanHebeMain(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long? = null
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeMain"
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getStudents(
|
|
||||||
profile: Profile?,
|
|
||||||
profileList: MutableList<Profile>?,
|
|
||||||
loginStoreId: Int? = null,
|
|
||||||
firstProfileId: Int? = null,
|
|
||||||
onEmpty: (() -> Unit)? = null,
|
|
||||||
onSuccess: () -> Unit
|
|
||||||
) {
|
|
||||||
if (profile == null && (profileList == null || loginStoreId == null || firstProfileId == null))
|
|
||||||
throw IllegalArgumentException()
|
|
||||||
|
|
||||||
apiGet(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_MAIN,
|
|
||||||
query = mapOf("lastSyncDate" to "null"),
|
|
||||||
baseUrl = profile == null
|
|
||||||
) { students: JsonArray, _ ->
|
|
||||||
if (students.isEmpty()) {
|
|
||||||
if (onEmpty != null)
|
|
||||||
onEmpty()
|
|
||||||
else
|
|
||||||
onSuccess()
|
|
||||||
return@apiGet
|
|
||||||
}
|
|
||||||
|
|
||||||
// safe to assume this will be non-null when creating a profile
|
|
||||||
var profileId = firstProfileId ?: loginStoreId ?: 1
|
|
||||||
|
|
||||||
students.forEach { studentEl ->
|
|
||||||
val student = studentEl.asJsonObject
|
|
||||||
|
|
||||||
val pupil = student.getJsonObject("Pupil")
|
|
||||||
val studentId = pupil.getInt("Id") ?: return@forEach
|
|
||||||
|
|
||||||
// check the student ID in case of not first login
|
|
||||||
if (profile != null && data.studentId != studentId)
|
|
||||||
return@forEach
|
|
||||||
|
|
||||||
val unit = student.getJsonObject("Unit")
|
|
||||||
val constituentUnit = student.getJsonObject("ConstituentUnit")
|
|
||||||
val login = student.getJsonObject("Login")
|
|
||||||
val periods = student.getJsonArray("Periods")?.map {
|
|
||||||
it.asJsonObject
|
|
||||||
} ?: listOf()
|
|
||||||
|
|
||||||
val period = periods.firstOrNull {
|
|
||||||
it.getBoolean("Current", false)
|
|
||||||
} ?: return@forEach
|
|
||||||
|
|
||||||
val periodLevel = period.getInt("Level") ?: return@forEach
|
|
||||||
val semester1 = periods.firstOrNull {
|
|
||||||
it.getInt("Level") == periodLevel && it.getInt("Number") == 1
|
|
||||||
}
|
|
||||||
val semester2 = periods.firstOrNull {
|
|
||||||
it.getInt("Level") == periodLevel && it.getInt("Number") == 2
|
|
||||||
}
|
|
||||||
|
|
||||||
val schoolSymbol = unit.getString("Symbol") ?: return@forEach
|
|
||||||
val schoolShort = constituentUnit.getString("Short") ?: return@forEach
|
|
||||||
val schoolCode = "${data.symbol}_$schoolSymbol"
|
|
||||||
|
|
||||||
val studentUnitId = unit.getInt("Id") ?: return@forEach
|
|
||||||
val studentConstituentId = constituentUnit.getInt("Id") ?: return@forEach
|
|
||||||
val studentLoginId = login.getInt("Id") ?: return@forEach
|
|
||||||
//val studentClassId = student.getInt("IdOddzial") ?: return@forEach
|
|
||||||
val studentClassName = student.getString("ClassDisplay") ?: return@forEach
|
|
||||||
val studentFirstName = pupil.getString("FirstName") ?: ""
|
|
||||||
val studentLastName = pupil.getString("Surname") ?: ""
|
|
||||||
val studentNameLong = "$studentFirstName $studentLastName".fixName()
|
|
||||||
val studentNameShort = "$studentFirstName ${studentLastName[0]}.".fixName()
|
|
||||||
val userLogin = login.getString("Value") ?: ""
|
|
||||||
|
|
||||||
val studentSemesterId = period.getInt("Id") ?: return@forEach
|
|
||||||
val studentSemesterNumber = period.getInt("Number") ?: return@forEach
|
|
||||||
|
|
||||||
val hebeContext = student.getString("Context")
|
|
||||||
|
|
||||||
val isParent = login.getString("LoginRole").equals("opiekun", ignoreCase = true)
|
|
||||||
val accountName = if (isParent)
|
|
||||||
login.getString("DisplayName")?.fixName()
|
|
||||||
else null
|
|
||||||
|
|
||||||
val dateSemester1Start = semester1
|
|
||||||
?.getJsonObject("Start")
|
|
||||||
?.getString("Date")
|
|
||||||
?.let { Date.fromY_m_d(it) }
|
|
||||||
val dateSemester2Start = semester2
|
|
||||||
?.getJsonObject("Start")
|
|
||||||
?.getString("Date")
|
|
||||||
?.let { Date.fromY_m_d(it) }
|
|
||||||
val dateYearEnd = semester2
|
|
||||||
?.getJsonObject("End")
|
|
||||||
?.getString("Date")
|
|
||||||
?.let { Date.fromY_m_d(it) }
|
|
||||||
|
|
||||||
val newProfile = profile ?: Profile(
|
|
||||||
profileId++,
|
|
||||||
loginStoreId!!,
|
|
||||||
LOGIN_TYPE_VULCAN,
|
|
||||||
studentNameLong,
|
|
||||||
userLogin,
|
|
||||||
studentNameLong,
|
|
||||||
studentNameShort,
|
|
||||||
accountName
|
|
||||||
)
|
|
||||||
|
|
||||||
newProfile.apply {
|
|
||||||
this.studentClassName = studentClassName
|
|
||||||
studentData["symbol"] = data.symbol
|
|
||||||
|
|
||||||
studentData["studentId"] = studentId
|
|
||||||
studentData["studentUnitId"] = studentUnitId
|
|
||||||
studentData["studentConstituentId"] = studentConstituentId
|
|
||||||
studentData["studentLoginId"] = studentLoginId
|
|
||||||
studentData["studentSemesterId"] = studentSemesterId
|
|
||||||
studentData["studentSemesterNumber"] = studentSemesterNumber
|
|
||||||
studentData["semester1Id"] = semester1?.getInt("Id") ?: 0
|
|
||||||
studentData["semester2Id"] = semester2?.getInt("Id") ?: 0
|
|
||||||
studentData["schoolSymbol"] = schoolSymbol
|
|
||||||
studentData["schoolShort"] = schoolShort
|
|
||||||
studentData["schoolName"] = schoolCode
|
|
||||||
studentData["hebeContext"] = hebeContext
|
|
||||||
}
|
|
||||||
dateSemester1Start?.let {
|
|
||||||
newProfile.dateSemester1Start = it
|
|
||||||
newProfile.studentSchoolYearStart = it.year
|
|
||||||
}
|
|
||||||
dateSemester2Start?.let { newProfile.dateSemester2Start = it }
|
|
||||||
dateYearEnd?.let { newProfile.dateYearEnd = it }
|
|
||||||
|
|
||||||
if (profile != null)
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_MAIN, 1 * DAY)
|
|
||||||
|
|
||||||
profileList?.add(newProfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import androidx.core.util.set
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_MESSAGES_SENT
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
|
|
||||||
import pl.szczodrzynski.navlib.crc16
|
|
||||||
import kotlin.text.replace
|
|
||||||
|
|
||||||
class VulcanHebeMessages(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeMessagesInbox"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getPersonId(json: JsonObject): Long {
|
|
||||||
val senderLoginId = json.getInt("LoginId") ?: return -1
|
|
||||||
/*if (senderLoginId == data.studentLoginId)
|
|
||||||
return -1*/
|
|
||||||
|
|
||||||
val senderName = json.getString("Address") ?: return -1
|
|
||||||
val senderNameSplit = senderName.splitName()
|
|
||||||
val senderLoginIdStr = senderLoginId.toString()
|
|
||||||
val teacher = data.teacherList.singleOrNull { it.loginId == senderLoginIdStr }
|
|
||||||
?: Teacher(
|
|
||||||
profileId,
|
|
||||||
-1 * crc16(senderName).toLong(),
|
|
||||||
senderNameSplit?.second ?: "",
|
|
||||||
senderNameSplit?.first ?: "",
|
|
||||||
senderLoginIdStr
|
|
||||||
).also {
|
|
||||||
it.setTeacherType(Teacher.TYPE_OTHER)
|
|
||||||
data.teacherList[it.id] = it
|
|
||||||
}
|
|
||||||
return teacher.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMessages(messageType: Int) {
|
|
||||||
val folder = when (messageType) {
|
|
||||||
TYPE_RECEIVED -> 1
|
|
||||||
TYPE_SENT -> 2
|
|
||||||
TYPE_DELETED -> 3
|
|
||||||
else -> 1
|
|
||||||
}
|
|
||||||
val endpointId = when (messageType) {
|
|
||||||
TYPE_RECEIVED -> ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX
|
|
||||||
TYPE_SENT -> ENDPOINT_VULCAN_HEBE_MESSAGES_SENT
|
|
||||||
else -> ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX
|
|
||||||
}
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_MESSAGES,
|
|
||||||
HebeFilterType.BY_PERSON,
|
|
||||||
folder = folder,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { list, _ ->
|
|
||||||
list.forEach { message ->
|
|
||||||
val id = message.getLong("Id") ?: return@forEach
|
|
||||||
val subject = message.getString("Subject") ?: return@forEach
|
|
||||||
val body = message.getString("Content") ?: return@forEach
|
|
||||||
|
|
||||||
val sender = message.getJsonObject("Sender") ?: return@forEach
|
|
||||||
|
|
||||||
val sentDate = getDateTime(message, "DateSent")
|
|
||||||
val readDate = getDateTime(message, "DateRead", default = 0)
|
|
||||||
|
|
||||||
val messageObject = Message(
|
|
||||||
profileId = profileId,
|
|
||||||
id = id,
|
|
||||||
type = messageType,
|
|
||||||
subject = subject,
|
|
||||||
body = body.replace("\n", "<br>"),
|
|
||||||
senderId = if (messageType == TYPE_RECEIVED) getPersonId(sender) else null,
|
|
||||||
addedDate = sentDate
|
|
||||||
)
|
|
||||||
|
|
||||||
val receivers = message.getJsonArray("Receiver")
|
|
||||||
?.asJsonObjectList()
|
|
||||||
?: return@forEach
|
|
||||||
val receiverReadDate =
|
|
||||||
if (receivers.size == 1) readDate
|
|
||||||
else -1
|
|
||||||
|
|
||||||
for (receiver in receivers) {
|
|
||||||
val messageRecipientObject = MessageRecipient(
|
|
||||||
profileId,
|
|
||||||
if (messageType == TYPE_SENT) getPersonId(receiver) else -1,
|
|
||||||
-1,
|
|
||||||
receiverReadDate,
|
|
||||||
id
|
|
||||||
)
|
|
||||||
data.messageRecipientList.add(messageRecipientObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.messageList.add(messageObject)
|
|
||||||
data.setSeenMetadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_MESSAGE,
|
|
||||||
id,
|
|
||||||
readDate > 0 || messageType == TYPE_SENT,
|
|
||||||
readDate > 0 || messageType == TYPE_SENT
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(
|
|
||||||
endpointId,
|
|
||||||
if (messageType == TYPE_RECEIVED) SYNC_ALWAYS else 1 * DAY,
|
|
||||||
if (messageType == TYPE_RECEIVED) null else DRAWER_ITEM_MESSAGES
|
|
||||||
)
|
|
||||||
onSuccess(endpointId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import pl.szczodrzynski.edziennik.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
|
||||||
|
|
||||||
class VulcanHebeMessagesChangeStatus(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
private val messageObject: MessageFull,
|
|
||||||
val onSuccess: () -> Unit
|
|
||||||
) : VulcanHebe(data, null) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeMessagesChangeStatus"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiPost(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS,
|
|
||||||
payload = JsonObject(
|
|
||||||
"MessageId" to messageObject.id,
|
|
||||||
"LoginId" to data.studentLoginId,
|
|
||||||
"Status" to 1
|
|
||||||
)
|
|
||||||
) { _: Boolean, _ ->
|
|
||||||
|
|
||||||
if (!messageObject.seen) {
|
|
||||||
data.setSeenMetadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_MESSAGE,
|
|
||||||
messageObject.id,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
messageObject.seen = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messageObject.type != Message.TYPE_SENT) {
|
|
||||||
val messageRecipientObject = MessageRecipient(
|
|
||||||
profileId,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
messageObject.id
|
|
||||||
)
|
|
||||||
data.messageRecipientList.add(messageRecipientObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,247 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_TIMETABLE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_TIMETABLE_CHANGES
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_TIMETABLE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_CANCELLED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_CHANGE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_NORMAL
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_SHIFTED_SOURCE
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_SHIFTED_TARGET
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
|
||||||
|
|
||||||
class VulcanHebeTimetable(
|
|
||||||
override val data: DataVulcan,
|
|
||||||
override val lastSync: Long?,
|
|
||||||
val onSuccess: (endpointId: Int) -> Unit
|
|
||||||
) : VulcanHebe(data, lastSync) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "VulcanHebeTimetable"
|
|
||||||
}
|
|
||||||
|
|
||||||
private val lessonList = mutableListOf<Lesson>()
|
|
||||||
private val lessonDates = mutableSetOf<Int>()
|
|
||||||
|
|
||||||
init {
|
|
||||||
val previousWeekStart = Week.getWeekStart().stepForward(0, 0, -7)
|
|
||||||
if (Date.getToday().weekDay > 4) {
|
|
||||||
previousWeekStart.stepForward(0, 0, 7)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dateFrom = data.arguments
|
|
||||||
?.getString("weekStart")
|
|
||||||
?.let { Date.fromY_m_d(it) }
|
|
||||||
?: previousWeekStart
|
|
||||||
val dateTo = dateFrom.clone().stepForward(0, 0, 13)
|
|
||||||
|
|
||||||
val lastSync = null
|
|
||||||
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_TIMETABLE,
|
|
||||||
HebeFilterType.BY_PUPIL,
|
|
||||||
dateFrom = dateFrom,
|
|
||||||
dateTo = dateTo,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { lessons, _ ->
|
|
||||||
apiGetList(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_TIMETABLE_CHANGES,
|
|
||||||
HebeFilterType.BY_PUPIL,
|
|
||||||
dateFrom = dateFrom,
|
|
||||||
dateTo = dateTo,
|
|
||||||
lastSync = lastSync
|
|
||||||
) { changes, _ ->
|
|
||||||
processData(lessons, changes)
|
|
||||||
|
|
||||||
// cancel lesson changes when caused by a shift
|
|
||||||
for (lesson in lessonList) {
|
|
||||||
if (lesson.type != TYPE_SHIFTED_TARGET)
|
|
||||||
continue
|
|
||||||
lessonList.firstOrNull {
|
|
||||||
it.oldDate == lesson.date
|
|
||||||
&& it.oldLessonNumber == lesson.lessonNumber
|
|
||||||
&& it.type == TYPE_CHANGE
|
|
||||||
}?.let {
|
|
||||||
it.type = TYPE_CANCELLED
|
|
||||||
it.date = null
|
|
||||||
it.lessonNumber = null
|
|
||||||
it.startTime = null
|
|
||||||
it.endTime = null
|
|
||||||
it.subjectId = null
|
|
||||||
it.teacherId = null
|
|
||||||
it.teamId = null
|
|
||||||
it.classroom = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add TYPE_NO_LESSONS to empty dates
|
|
||||||
val date: Date = dateFrom.clone()
|
|
||||||
while (date <= dateTo) {
|
|
||||||
if (!lessonDates.contains(date.value)) {
|
|
||||||
lessonList.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 ${dateFrom.stringY_m_d} and ${dateTo.stringY_m_d}"
|
|
||||||
)
|
|
||||||
|
|
||||||
data.lessonList.addAll(lessonList)
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_TIMETABLE, SYNC_ALWAYS)
|
|
||||||
onSuccess(ENDPOINT_VULCAN_HEBE_TIMETABLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildLesson(changes: List<JsonObject>, json: JsonObject): Pair<Lesson, Lesson?>? {
|
|
||||||
val lesson = Lesson(profileId, -1)
|
|
||||||
var lessonShift: Lesson? = null
|
|
||||||
|
|
||||||
val lessonDate = getDate(json, "Date") ?: return null
|
|
||||||
val lessonRange = getLessonRange(json, "TimeSlot")
|
|
||||||
val startTime = lessonRange?.startTime
|
|
||||||
val endTime = lessonRange?.endTime
|
|
||||||
val teacherId = getTeacherId(json, "TeacherPrimary")
|
|
||||||
val classroom = json.getJsonObject("Room").getString("Code")
|
|
||||||
val subjectId = getSubjectId(json, "Subject")
|
|
||||||
|
|
||||||
val teamId = getTeamId(json, "Distribution")
|
|
||||||
?: getClassId(json, "Clazz")
|
|
||||||
?: data.teamClass?.id
|
|
||||||
?: -1
|
|
||||||
|
|
||||||
val change = json.getJsonObject("Change")
|
|
||||||
val changeId = change.getInt("Id")
|
|
||||||
val type = when (change.getInt("Type")) {
|
|
||||||
1 -> TYPE_CANCELLED
|
|
||||||
2 -> TYPE_CHANGE
|
|
||||||
3 -> TYPE_SHIFTED_SOURCE
|
|
||||||
4 -> TYPE_CANCELLED // TODO: 2021-02-21 add showing cancellation reason
|
|
||||||
else -> TYPE_NORMAL
|
|
||||||
}
|
|
||||||
|
|
||||||
lesson.type = type
|
|
||||||
if (type == TYPE_NORMAL) {
|
|
||||||
lesson.date = lessonDate
|
|
||||||
lesson.lessonNumber = lessonRange?.lessonNumber
|
|
||||||
lesson.startTime = startTime
|
|
||||||
lesson.endTime = endTime
|
|
||||||
lesson.subjectId = subjectId
|
|
||||||
lesson.teacherId = teacherId
|
|
||||||
lesson.teamId = teamId
|
|
||||||
lesson.classroom = classroom
|
|
||||||
} else {
|
|
||||||
lesson.oldDate = lessonDate
|
|
||||||
lesson.oldLessonNumber = lessonRange?.lessonNumber
|
|
||||||
lesson.oldStartTime = startTime
|
|
||||||
lesson.oldEndTime = endTime
|
|
||||||
lesson.oldSubjectId = subjectId
|
|
||||||
lesson.oldTeacherId = teacherId
|
|
||||||
lesson.oldTeamId = teamId
|
|
||||||
lesson.oldClassroom = classroom
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == TYPE_CHANGE || type == TYPE_SHIFTED_SOURCE) {
|
|
||||||
val changeJson = changes.firstOrNull {
|
|
||||||
it.getInt("Id") == changeId
|
|
||||||
} ?: return lesson to null
|
|
||||||
|
|
||||||
val changeLessonDate = getDate(changeJson, "LessonDate") ?: return lesson to null
|
|
||||||
val changeLessonRange = getLessonRange(changeJson, "TimeSlot") ?: lessonRange
|
|
||||||
val changeStartTime = changeLessonRange?.startTime
|
|
||||||
val changeEndTime = changeLessonRange?.endTime
|
|
||||||
val changeTeacherId = getTeacherId(changeJson, "TeacherPrimary") ?: teacherId
|
|
||||||
val changeClassroom = changeJson.getJsonObject("Room").getString("Code") ?: classroom
|
|
||||||
val changeSubjectId = getSubjectId(changeJson, "Subject") ?: subjectId
|
|
||||||
|
|
||||||
val changeTeamId = getTeamId(json, "Distribution")
|
|
||||||
?: getClassId(json, "Clazz")
|
|
||||||
?: teamId
|
|
||||||
|
|
||||||
if (type != TYPE_CHANGE) {
|
|
||||||
/* lesson shifted */
|
|
||||||
lessonShift = Lesson(profileId, -1)
|
|
||||||
lessonShift.type = TYPE_SHIFTED_TARGET
|
|
||||||
|
|
||||||
// update source lesson with the target lesson date
|
|
||||||
lesson.date = changeLessonDate
|
|
||||||
lesson.lessonNumber = changeLessonRange?.lessonNumber
|
|
||||||
lesson.startTime = changeStartTime
|
|
||||||
lesson.endTime = changeEndTime
|
|
||||||
// update target lesson with the source lesson date
|
|
||||||
lessonShift.oldDate = lessonDate
|
|
||||||
lessonShift.oldLessonNumber = lessonRange?.lessonNumber
|
|
||||||
lessonShift.oldStartTime = startTime
|
|
||||||
lessonShift.oldEndTime = endTime
|
|
||||||
}
|
|
||||||
|
|
||||||
(if (type == TYPE_CHANGE) lesson else lessonShift)
|
|
||||||
?.apply {
|
|
||||||
this.date = changeLessonDate
|
|
||||||
this.lessonNumber = changeLessonRange?.lessonNumber
|
|
||||||
this.startTime = changeStartTime
|
|
||||||
this.endTime = changeEndTime
|
|
||||||
this.subjectId = changeSubjectId
|
|
||||||
this.teacherId = changeTeacherId
|
|
||||||
this.teamId = changeTeamId
|
|
||||||
this.classroom = changeClassroom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lesson to lessonShift
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processData(lessons: List<JsonObject>, changes: List<JsonObject>) {
|
|
||||||
lessons.forEach { lessonJson ->
|
|
||||||
if (lessonJson.getBoolean("Visible") != true)
|
|
||||||
return@forEach
|
|
||||||
|
|
||||||
val lessonPair = buildLesson(changes, lessonJson) ?: return@forEach
|
|
||||||
val (lessonObject, lessonShift) = lessonPair
|
|
||||||
|
|
||||||
when {
|
|
||||||
lessonShift != null -> lessonShift
|
|
||||||
lessonObject.type != TYPE_NORMAL -> lessonObject
|
|
||||||
else -> null
|
|
||||||
}?.let { lesson ->
|
|
||||||
val lessonDate = lesson.displayDate ?: return@let
|
|
||||||
val seen = profile?.empty ?: true || lessonDate < Date.getToday()
|
|
||||||
data.metadataList.add(
|
|
||||||
Metadata(
|
|
||||||
profileId,
|
|
||||||
Metadata.TYPE_LESSON_CHANGE,
|
|
||||||
lesson.id,
|
|
||||||
seen,
|
|
||||||
seen
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
lessonObject.id = lessonObject.buildId()
|
|
||||||
lessonShift?.id = lessonShift?.buildId() ?: -1
|
|
||||||
|
|
||||||
lessonList.add(lessonObject)
|
|
||||||
lessonShift?.let { lessonList.add(it) }
|
|
||||||
|
|
||||||
lessonObject.displayDate?.let { lessonDates.add(it.value) }
|
|
||||||
lessonShift?.displayDate?.let { lessonDates.add(it.value) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,12 +9,9 @@ import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanWebMain
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanWebMain
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.VulcanHebeMain
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.CufsCertificate
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.CufsCertificate
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
|
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
|
@ -28,7 +25,6 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
|
|
||||||
private val api = VulcanApi(data, null)
|
private val api = VulcanApi(data, null)
|
||||||
private val web = VulcanWebMain(data, null)
|
private val web = VulcanWebMain(data, null)
|
||||||
private val hebe = VulcanHebe(data, null)
|
|
||||||
private val profileList = mutableListOf<Profile>()
|
private val profileList = mutableListOf<Profile>()
|
||||||
private val loginStoreId = data.loginStore.id
|
private val loginStoreId = data.loginStore.id
|
||||||
private var firstProfileId = loginStoreId
|
private var firstProfileId = loginStoreId
|
||||||
|
@ -54,14 +50,8 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
checkSymbol(certificate)
|
checkSymbol(certificate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (data.loginStore.mode == LOGIN_MODE_VULCAN_API) {
|
|
||||||
registerDevice {
|
|
||||||
EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
registerDeviceHebe {
|
registerDevice {
|
||||||
EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
|
EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -113,7 +103,7 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
data.apiPin = data.apiPin.toMutableMap().also {
|
data.apiPin = data.apiPin.toMutableMap().also {
|
||||||
it[symbol] = json.getString("PIN")
|
it[symbol] = json.getString("PIN")
|
||||||
}
|
}
|
||||||
registerDeviceHebe(onSuccess)
|
registerDevice(onSuccess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,21 +197,4 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerDeviceHebe(onSuccess: () -> Unit) {
|
|
||||||
VulcanLoginHebe(data) {
|
|
||||||
VulcanHebeMain(data).getStudents(
|
|
||||||
profile = null,
|
|
||||||
profileList,
|
|
||||||
loginStoreId,
|
|
||||||
firstProfileId,
|
|
||||||
onEmpty = {
|
|
||||||
EventBus.getDefault()
|
|
||||||
.postSticky(FirstLoginFinishedEvent(listOf(), data.loginStore))
|
|
||||||
onSuccess()
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_HEBE
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_WEB_MAIN
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_WEB_MAIN
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
@ -55,10 +54,6 @@ class VulcanLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
data.startProgress(R.string.edziennik_progress_login_vulcan_api)
|
data.startProgress(R.string.edziennik_progress_login_vulcan_api)
|
||||||
VulcanLoginApi(data) { onSuccess(loginMethodId) }
|
VulcanLoginApi(data) { onSuccess(loginMethodId) }
|
||||||
}
|
}
|
||||||
LOGIN_METHOD_VULCAN_HEBE -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_login_vulcan_api)
|
|
||||||
VulcanLoginHebe(data) { onSuccess(loginMethodId) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,6 +191,18 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val deviceId = data.app.deviceId.padStart(16, '0')
|
||||||
|
val loginStoreId = data.loginStore.id.toString(16).padStart(4, '0')
|
||||||
|
val symbol = data.symbol?.crc16()?.toString(16)?.take(2) ?: "00"
|
||||||
|
val uuid =
|
||||||
|
deviceId.substring(0..7) +
|
||||||
|
"-" + deviceId.substring(8..11) +
|
||||||
|
"-" + deviceId.substring(12..15) +
|
||||||
|
"-" + loginStoreId +
|
||||||
|
"-" + symbol + "6f72616e7a"
|
||||||
|
|
||||||
|
val deviceNameSuffix = " - nie usuwać"
|
||||||
|
|
||||||
val szkolnyApi = SzkolnyApi(data.app)
|
val szkolnyApi = SzkolnyApi(data.app)
|
||||||
val firebaseToken = szkolnyApi.runCatching({
|
val firebaseToken = szkolnyApi.runCatching({
|
||||||
getFirebaseToken("vulcan")
|
getFirebaseToken("vulcan")
|
||||||
|
@ -204,8 +216,8 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
.addHeader("RequestMobileType", "RegisterDevice")
|
.addHeader("RequestMobileType", "RegisterDevice")
|
||||||
.addParameter("PIN", data.apiPin[data.symbol])
|
.addParameter("PIN", data.apiPin[data.symbol])
|
||||||
.addParameter("TokenKey", data.apiToken[data.symbol])
|
.addParameter("TokenKey", data.apiToken[data.symbol])
|
||||||
.addParameter("DeviceId", data.buildDeviceId())
|
.addParameter("DeviceId", uuid)
|
||||||
.addParameter("DeviceName", VULCAN_API_DEVICE_NAME)
|
.addParameter("DeviceName", VULCAN_API_DEVICE_NAME.take(50 - deviceNameSuffix.length) + deviceNameSuffix)
|
||||||
.addParameter("DeviceNameUser", "")
|
.addParameter("DeviceNameUser", "")
|
||||||
.addParameter("DeviceDescription", "")
|
.addParameter("DeviceDescription", "")
|
||||||
.addParameter("DeviceSystemType", "Android")
|
.addParameter("DeviceSystemType", "Android")
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import io.github.wulkanowy.signer.hebe.generateKeyPair
|
|
||||||
import pl.szczodrzynski.edziennik.JsonObject
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_DATA_MISSING
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_API_DEVICE_NAME
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_REGISTER_NEW
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
|
||||||
|
|
||||||
class VulcanLoginHebe(val data: DataVulcan, val onSuccess: () -> Unit) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "VulcanLoginHebe"
|
|
||||||
}
|
|
||||||
|
|
||||||
init { run {
|
|
||||||
// i'm sure this does something useful
|
|
||||||
// not quite sure what, though
|
|
||||||
if (data.studentSemesterNumber == 1 && data.semester1Id == 0)
|
|
||||||
data.semester1Id = data.studentSemesterNumber
|
|
||||||
if (data.studentSemesterNumber == 2 && data.semester2Id == 0)
|
|
||||||
data.semester2Id = data.studentSemesterNumber
|
|
||||||
|
|
||||||
copyFromLoginStore()
|
|
||||||
|
|
||||||
if (data.profile != null && data.isApiLoginValid()) {
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (data.symbol.isNotNullNorEmpty() && data.apiToken[data.symbol].isNotNullNorEmpty() && data.apiPin[data.symbol].isNotNullNorEmpty()) {
|
|
||||||
loginWithToken()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
private fun copyFromLoginStore() {
|
|
||||||
data.loginStore.data.apply {
|
|
||||||
// map form inputs to the symbol
|
|
||||||
if (has("symbol")) {
|
|
||||||
data.symbol = getString("symbol")
|
|
||||||
remove("symbol")
|
|
||||||
}
|
|
||||||
if (has("deviceToken")) {
|
|
||||||
data.apiToken = data.apiToken.toMutableMap().also {
|
|
||||||
it[data.symbol] = getString("deviceToken")
|
|
||||||
}
|
|
||||||
remove("deviceToken")
|
|
||||||
}
|
|
||||||
if (has("devicePin")) {
|
|
||||||
data.apiPin = data.apiPin.toMutableMap().also {
|
|
||||||
it[data.symbol] = getString("devicePin")
|
|
||||||
}
|
|
||||||
remove("devicePin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loginWithToken() {
|
|
||||||
val szkolnyApi = SzkolnyApi(data.app)
|
|
||||||
val hebe = VulcanHebe(data, null)
|
|
||||||
|
|
||||||
if (data.hebePublicKey == null || data.hebePrivateKey == null || data.hebePublicHash == null) {
|
|
||||||
val (publicPem, privatePem, publicHash) = generateKeyPair()
|
|
||||||
data.hebePublicKey = publicPem
|
|
||||||
data.hebePrivateKey = privatePem
|
|
||||||
data.hebePublicHash = publicHash
|
|
||||||
}
|
|
||||||
|
|
||||||
val firebaseToken = szkolnyApi.runCatching({
|
|
||||||
getFirebaseToken("vulcan")
|
|
||||||
}, onError = {
|
|
||||||
// screw errors
|
|
||||||
}) ?: data.app.config.sync.tokenVulcan
|
|
||||||
|
|
||||||
hebe.apiPost(
|
|
||||||
TAG,
|
|
||||||
VULCAN_HEBE_ENDPOINT_REGISTER_NEW,
|
|
||||||
payload = JsonObject(
|
|
||||||
"OS" to "Android",
|
|
||||||
"PIN" to data.apiPin[data.symbol],
|
|
||||||
"Certificate" to data.hebePublicKey,
|
|
||||||
"CertificateType" to "RSA_PEM",
|
|
||||||
"DeviceModel" to VULCAN_API_DEVICE_NAME,
|
|
||||||
"SecurityToken" to data.apiToken[data.symbol],
|
|
||||||
"SelfIdentifier" to data.buildDeviceId(),
|
|
||||||
"CertificateThumbprint" to data.hebePublicHash
|
|
||||||
),
|
|
||||||
baseUrl = true,
|
|
||||||
firebaseToken = firebaseToken
|
|
||||||
) { _: JsonObject, _ ->
|
|
||||||
data.apiToken = data.apiToken.toMutableMap().also {
|
|
||||||
it[data.symbol] = it[data.symbol]?.substring(0, 3)
|
|
||||||
}
|
|
||||||
data.loginStore.removeLoginData("apiPin")
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -89,7 +89,7 @@ class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val fsLogin = FSLogin(data.app.http, debug = App.devMode)
|
val fsLogin = FSLogin(data.app.http, debug = App.debugMode)
|
||||||
fsLogin.performLogin(
|
fsLogin.performLogin(
|
||||||
realm = realm,
|
realm = realm,
|
||||||
username = data.webUsername ?: data.webEmail ?: return false,
|
username = data.webUsername ?: data.webEmail ?: return false,
|
||||||
|
|
|
@ -136,7 +136,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
||||||
val db: AppDb by lazy { app.db }
|
val db: AppDb by lazy { app.db }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (App.debugMode) {
|
if (App.devMode) {
|
||||||
fakeLogin = loginStore.hasLoginData("fakeLogin")
|
fakeLogin = loginStore.hasLoginData("fakeLogin")
|
||||||
}
|
}
|
||||||
clear()
|
clear()
|
||||||
|
|
|
@ -46,6 +46,6 @@ object Signing {
|
||||||
|
|
||||||
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
|
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
|
||||||
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
|
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
|
||||||
return "$param1.MTIzNDU2Nzg5MDL9U0lwJn===.$param2".sha256()
|
return "$param1.MTIzNDU2Nzg5MDv1BTei5k===.$param2".sha256()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ import pl.szczodrzynski.edziennik.currentTimeUnix
|
||||||
data class RegisterAvailabilityStatus(
|
data class RegisterAvailabilityStatus(
|
||||||
val available: Boolean,
|
val available: Boolean,
|
||||||
val name: String?,
|
val name: String?,
|
||||||
val userMessage: Message?,
|
val message: Message?,
|
||||||
val nextCheckAt: Long = currentTimeUnix() + 7 * DAY,
|
val nextCheck: Long = currentTimeUnix() + 7 * DAY,
|
||||||
val minVersionCode: Int = BuildConfig.VERSION_CODE
|
val minVersionCode: Int = BuildConfig.VERSION_CODE
|
||||||
) {
|
) {
|
||||||
data class Message(
|
data class Message(
|
||||||
|
|
|
@ -47,14 +47,14 @@ class RegisterUnavailableDialog(
|
||||||
onShowListener?.invoke(TAG)
|
onShowListener?.invoke(TAG)
|
||||||
app = activity.applicationContext as App
|
app = activity.applicationContext as App
|
||||||
|
|
||||||
if (!status.available && status.userMessage != null) {
|
if (!status.available && status.message != null) {
|
||||||
val b = DialogRegisterUnavailableBinding.inflate(LayoutInflater.from(activity), null, false)
|
val b = DialogRegisterUnavailableBinding.inflate(LayoutInflater.from(activity), null, false)
|
||||||
b.message = status.userMessage
|
b.message = status.message
|
||||||
if (status.userMessage.image != null)
|
if (status.message.image != null)
|
||||||
b.image.load(status.userMessage.image)
|
b.image.load(status.message.image)
|
||||||
if (status.userMessage.url != null) {
|
if (status.message.url != null) {
|
||||||
b.readMore.onClick {
|
b.readMore.onClick {
|
||||||
Utils.openUrl(activity, status.userMessage.url)
|
Utils.openUrl(activity, status.message.url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.text.movementMethod = LinkMovementMethod.getInstance()
|
b.text.movementMethod = LinkMovementMethod.getInstance()
|
||||||
|
@ -67,7 +67,6 @@ class RegisterUnavailableDialog(
|
||||||
onDismissListener?.invoke(TAG)
|
onDismissListener?.invoke(TAG)
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
return@run
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val update = app.config.update
|
val update = app.config.update
|
||||||
|
|
|
@ -193,7 +193,7 @@ class EventDetailsDialog(
|
||||||
b.goToTimetableButton.attachToastHint(R.string.hint_go_to_timetable)
|
b.goToTimetableButton.attachToastHint(R.string.hint_go_to_timetable)
|
||||||
|
|
||||||
// RE-DOWNLOAD
|
// RE-DOWNLOAD
|
||||||
b.downloadButton.isVisible = App.devMode
|
b.downloadButton.isVisible = App.debugMode
|
||||||
b.downloadButton.onClick {
|
b.downloadButton.onClick {
|
||||||
EdziennikTask.eventGet(event.profileId, event).enqueue(activity)
|
EdziennikTask.eventGet(event.profileId, event).enqueue(activity)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class GradeDetailsDialog(
|
||||||
b.grade = grade
|
b.grade = grade
|
||||||
b.weightText = manager.getWeightString(app, grade)
|
b.weightText = manager.getWeightString(app, grade)
|
||||||
b.commentVisible = false
|
b.commentVisible = false
|
||||||
b.devMode = App.devMode
|
b.devMode = App.debugMode
|
||||||
b.gradeName.setTextColor(if (ColorUtils.calculateLuminance(gradeColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
|
b.gradeName.setTextColor(if (ColorUtils.calculateLuminance(gradeColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
|
||||||
b.gradeName.background.setTintColor(gradeColor)
|
b.gradeName.background.setTintColor(gradeColor)
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class LessonDetailsDialog(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App.devMode)
|
if (App.debugMode)
|
||||||
b.lessonId.visibility = View.VISIBLE
|
b.lessonId.visibility = View.VISIBLE
|
||||||
|
|
||||||
update()
|
update()
|
||||||
|
|
|
@ -55,7 +55,7 @@ class AttendanceDetailsDialog(
|
||||||
|
|
||||||
val attendanceColor = manager.getAttendanceColor(attendance)
|
val attendanceColor = manager.getAttendanceColor(attendance)
|
||||||
b.attendance = attendance
|
b.attendance = attendance
|
||||||
b.devMode = App.devMode
|
b.devMode = App.debugMode
|
||||||
b.attendanceName.setTextColor(if (ColorUtils.calculateLuminance(attendanceColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
|
b.attendanceName.setTextColor(if (ColorUtils.calculateLuminance(attendanceColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt())
|
||||||
b.attendanceName.background.setTintColor(attendanceColor)
|
b.attendanceName.background.setTintColor(attendanceColor)
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ class CrashActivity : AppCompatActivity(), CoroutineScope {
|
||||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
|
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
|
||||||
clipboard?.apply {
|
clipboard?.apply {
|
||||||
val clip = ClipData.newPlainText(getString(R.string.customactivityoncrash_error_activity_error_details_clipboard_label), errorInformation)
|
val clip = ClipData.newPlainText(getString(R.string.customactivityoncrash_error_activity_error_details_clipboard_label), errorInformation)
|
||||||
setPrimaryClip(clip)
|
primaryClip = clip
|
||||||
Toast.makeText(this@CrashActivity, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@CrashActivity, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ErrorDetailsDialog(
|
||||||
listOf(
|
listOf(
|
||||||
it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)),
|
it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)),
|
||||||
activity.getString(R.string.error_unknown_format, it.errorCode, it.tag),
|
activity.getString(R.string.error_unknown_format, it.errorCode, it.tag),
|
||||||
if (App.devMode)
|
if (App.debugMode)
|
||||||
it.throwable?.stackTraceString ?: it.throwable?.localizedMessage
|
it.throwable?.stackTraceString ?: it.throwable?.localizedMessage
|
||||||
else
|
else
|
||||||
it.throwable?.localizedMessage
|
it.throwable?.localizedMessage
|
||||||
|
|
|
@ -71,14 +71,9 @@ class GradesListFragment : Fragment(), CoroutineScope {
|
||||||
val adapter = GradesAdapter(activity)
|
val adapter = GradesAdapter(activity)
|
||||||
var firstRun = true
|
var firstRun = true
|
||||||
|
|
||||||
app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { grades -> this@GradesListFragment.launch {
|
app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { items -> this@GradesListFragment.launch {
|
||||||
if (!isAdded) return@launch
|
if (!isAdded) return@launch
|
||||||
|
|
||||||
val items = when {
|
|
||||||
app.config.forProfile().grades.hideSticksFromOld && App.devMode -> grades.filter { it.value != 1.0f }
|
|
||||||
else -> grades
|
|
||||||
}
|
|
||||||
|
|
||||||
// load & configure the adapter
|
// load & configure the adapter
|
||||||
adapter.items = withContext(Dispatchers.Default) { processGrades(items) }
|
adapter.items = withContext(Dispatchers.Default) { processGrades(items) }
|
||||||
if (items.isNotNullNorEmpty() && b.list.adapter == null) {
|
if (items.isNotNullNorEmpty() && b.list.adapter == null) {
|
||||||
|
|
|
@ -152,14 +152,13 @@ class HomeFragment : Fragment(), CoroutineScope {
|
||||||
|
|
||||||
val items = mutableListOf<HomeCard>()
|
val items = mutableListOf<HomeCard>()
|
||||||
cards.mapNotNullTo(items) {
|
cards.mapNotNullTo(items) {
|
||||||
@Suppress("USELESS_CAST")
|
|
||||||
when (it.cardId) {
|
when (it.cardId) {
|
||||||
HomeCard.CARD_LUCKY_NUMBER -> HomeLuckyNumberCard(it.cardId, app, activity, this, app.profile)
|
HomeCard.CARD_LUCKY_NUMBER -> HomeLuckyNumberCard(it.cardId, app, activity, this, app.profile)
|
||||||
HomeCard.CARD_TIMETABLE -> HomeTimetableCard(it.cardId, app, activity, this, app.profile)
|
HomeCard.CARD_TIMETABLE -> HomeTimetableCard(it.cardId, app, activity, this, app.profile)
|
||||||
HomeCard.CARD_GRADES -> HomeGradesCard(it.cardId, app, activity, this, app.profile)
|
HomeCard.CARD_GRADES -> HomeGradesCard(it.cardId, app, activity, this, app.profile)
|
||||||
HomeCard.CARD_EVENTS -> HomeEventsCard(it.cardId, app, activity, this, app.profile)
|
HomeCard.CARD_EVENTS -> HomeEventsCard(it.cardId, app, activity, this, app.profile)
|
||||||
else -> null
|
else -> null
|
||||||
} as HomeCard?
|
}
|
||||||
}
|
}
|
||||||
//if (App.devMode)
|
//if (App.devMode)
|
||||||
// items += HomeDebugCard(100, app, activity, this, app.profile)
|
// items += HomeDebugCard(100, app, activity, this, app.profile)
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.modules.home.cards
|
package pl.szczodrzynski.edziennik.ui.modules.home.cards
|
||||||
|
|
||||||
|
import android.text.Html
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.core.text.HtmlCompat
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.plusAssign
|
import androidx.core.view.plusAssign
|
||||||
import androidx.core.view.setMargins
|
import androidx.core.view.setMargins
|
||||||
|
@ -58,13 +58,13 @@ class HomeAvailabilityCard(
|
||||||
|
|
||||||
var onInfoClick = { _: View -> }
|
var onInfoClick = { _: View -> }
|
||||||
|
|
||||||
if (status != null && !status.available && status.userMessage != null) {
|
if (status != null && !status.available && status.message != null) {
|
||||||
b.homeAvailabilityTitle.text = HtmlCompat.fromHtml(status.userMessage.title, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
b.homeAvailabilityTitle.text = Html.fromHtml(status.message.title)
|
||||||
b.homeAvailabilityText.text = HtmlCompat.fromHtml(status.userMessage.contentShort, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
b.homeAvailabilityText.text = Html.fromHtml(status.message.contentShort)
|
||||||
b.homeAvailabilityUpdate.isVisible = false
|
b.homeAvailabilityUpdate.isVisible = false
|
||||||
b.homeAvailabilityIcon.setImageResource(R.drawable.ic_sync)
|
b.homeAvailabilityIcon.setImageResource(R.drawable.ic_sync)
|
||||||
if (status.userMessage.icon != null)
|
if (status.message.icon != null)
|
||||||
b.homeAvailabilityIcon.load(status.userMessage.icon)
|
b.homeAvailabilityIcon.load(status.message.icon)
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
RegisterUnavailableDialog(activity, status)
|
RegisterUnavailableDialog(activity, status)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import kotlin.coroutines.CoroutineContext
|
||||||
class LoginActivity : AppCompatActivity(), CoroutineScope {
|
class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "LoginActivity"
|
private const val TAG = "LoginActivity"
|
||||||
|
var thisOneIsTricky = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private val app: App by lazy { applicationContext as App }
|
private val app: App by lazy { applicationContext as App }
|
||||||
|
@ -41,8 +42,6 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||||
val profiles = mutableListOf<LoginSummaryAdapter.Item>()
|
val profiles = mutableListOf<LoginSummaryAdapter.Item>()
|
||||||
val loginStores = mutableListOf<LoginStore>()
|
val loginStores = mutableListOf<LoginStore>()
|
||||||
|
|
||||||
fun getRootView() = b.root
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
val destination = nav.currentDestination ?: run {
|
val destination = nav.currentDestination ?: run {
|
||||||
nav.navigateUp()
|
nav.navigateUp()
|
||||||
|
@ -56,11 +55,6 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||||
return
|
return
|
||||||
if (destination.id == R.id.loginFinishFragment)
|
if (destination.id == R.id.loginFinishFragment)
|
||||||
return
|
return
|
||||||
// eggs
|
|
||||||
if (destination.id == R.id.loginPrizeFragment) {
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (destination.id == R.id.loginChooserFragment && loginStores.isEmpty()) {
|
if (destination.id == R.id.loginChooserFragment && loginStores.isEmpty()) {
|
||||||
setResult(Activity.RESULT_CANCELED)
|
setResult(Activity.RESULT_CANCELED)
|
||||||
finish()
|
finish()
|
||||||
|
@ -85,6 +79,8 @@ class LoginActivity : AppCompatActivity(), CoroutineScope {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setTheme(R.style.AppTheme_Light)
|
setTheme(R.style.AppTheme_Light)
|
||||||
|
|
||||||
|
thisOneIsTricky = -1
|
||||||
|
|
||||||
navOptions = NavOptions.Builder()
|
navOptions = NavOptions.Builder()
|
||||||
.setEnterAnim(R.anim.slide_in_right)
|
.setEnterAnim(R.anim.slide_in_right)
|
||||||
.setExitAnim(R.anim.slide_out_left)
|
.setExitAnim(R.anim.slide_out_left)
|
||||||
|
|
|
@ -60,8 +60,7 @@ class LoginChooserAdapter(
|
||||||
|
|
||||||
private val onClickListener = View.OnClickListener { view ->
|
private val onClickListener = View.OnClickListener { view ->
|
||||||
val model = view.getTag(R.string.tag_key_model)
|
val model = view.getTag(R.string.tag_key_model)
|
||||||
if (model is LoginInfo.Register
|
if (model is LoginInfo.Register && model.loginModes.size == 1) {
|
||||||
&& model.loginModes.count { App.devMode || !it.isDevOnly } == 1) {
|
|
||||||
onModeClick?.invoke(model, model.loginModes.first())
|
onModeClick?.invoke(model, model.loginModes.first())
|
||||||
return@OnClickListener
|
return@OnClickListener
|
||||||
}
|
}
|
||||||
|
@ -86,9 +85,7 @@ class LoginChooserAdapter(
|
||||||
|
|
||||||
if (model.state == STATE_CLOSED) {
|
if (model.state == STATE_CLOSED) {
|
||||||
|
|
||||||
val subItems = model.items.filter {
|
val subItems = model.items
|
||||||
App.devMode || !it.isDevOnly
|
|
||||||
}
|
|
||||||
|
|
||||||
model.state = STATE_OPENED
|
model.state = STATE_OPENED
|
||||||
items.addAll(position + 1, subItems)
|
items.addAll(position + 1, subItems)
|
||||||
|
|
|
@ -4,22 +4,15 @@
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
package pl.szczodrzynski.edziennik.ui.modules.login
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator
|
|
||||||
import android.view.animation.Animation
|
|
||||||
import android.view.animation.RotateAnimation
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
|
@ -33,8 +26,6 @@ import kotlin.coroutines.CoroutineContext
|
||||||
class LoginChooserFragment : Fragment(), CoroutineScope {
|
class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "LoginChooserFragment"
|
private const val TAG = "LoginChooserFragment"
|
||||||
// eggs
|
|
||||||
var isRotated = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
|
@ -56,33 +47,31 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||||
return b.root
|
return b.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
if (!isAdded) return
|
if (!isAdded) return
|
||||||
|
|
||||||
val adapter = LoginChooserAdapter(activity, this::onLoginModeClicked)
|
val adapter = LoginChooserAdapter(activity) { loginType, loginMode ->
|
||||||
|
launch {
|
||||||
|
if (!checkAvailability(loginType.loginType))
|
||||||
|
return@launch
|
||||||
|
|
||||||
|
if (loginMode.isPlatformSelection) {
|
||||||
|
nav.navigate(R.id.loginPlatformListFragment, Bundle(
|
||||||
|
"loginType" to loginType.loginType,
|
||||||
|
"loginMode" to loginMode.loginMode
|
||||||
|
), activity.navOptions)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navigate(R.id.loginFormFragment, Bundle(
|
||||||
|
"loginType" to loginType.loginType,
|
||||||
|
"loginMode" to loginMode.loginMode
|
||||||
|
), activity.navOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LoginInfo.chooserList = LoginInfo.chooserList
|
LoginInfo.chooserList = LoginInfo.chooserList
|
||||||
?: LoginInfo.list.toMutableList()
|
?: LoginInfo.list.toMutableList<Any>()
|
||||||
|
|
||||||
// eggs
|
|
||||||
if (isRotated) {
|
|
||||||
isRotated = false
|
|
||||||
LoginFormFragment.wantEggs = false
|
|
||||||
LoginInfo.chooserList = LoginInfo.list.toMutableList()
|
|
||||||
val anim = RotateAnimation(
|
|
||||||
180f,
|
|
||||||
0f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f
|
|
||||||
)
|
|
||||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
|
||||||
anim.duration = 500
|
|
||||||
anim.fillAfter = true
|
|
||||||
activity.getRootView().startAnimation(anim)
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.items = LoginInfo.chooserList!!
|
adapter.items = LoginInfo.chooserList!!
|
||||||
b.list.adapter = adapter
|
b.list.adapter = adapter
|
||||||
|
@ -96,81 +85,6 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||||
startActivity(Intent(activity, FeedbackActivity::class.java))
|
startActivity(Intent(activity, FeedbackActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
// eggs
|
|
||||||
b.footnoteText.onClick {
|
|
||||||
if (!LoginFormFragment.wantEggs || isRotated)
|
|
||||||
return@onClick
|
|
||||||
|
|
||||||
val text = b.subtitleText.text.toString()
|
|
||||||
if (text.endsWith(".."))
|
|
||||||
b.subtitleText.text = text.substring(0, text.length - 2)
|
|
||||||
else
|
|
||||||
b.subtitleText.text = "$text..."
|
|
||||||
}
|
|
||||||
var clickCount = 0
|
|
||||||
val color = R.color.md_blue_500.resolveColor(app)
|
|
||||||
val hsv = FloatArray(3)
|
|
||||||
Color.colorToHSV(color, hsv)
|
|
||||||
val hueOriginal = hsv[0]
|
|
||||||
b.subtitleText.onClick {
|
|
||||||
if (isRotated)
|
|
||||||
return@onClick
|
|
||||||
val text = b.subtitleText.text.toString()
|
|
||||||
if (text.endsWith("..") && !text.endsWith("...")) {
|
|
||||||
clickCount++
|
|
||||||
}
|
|
||||||
if (clickCount == 5) {
|
|
||||||
val anim = ValueAnimator.ofFloat(0f, 1f)
|
|
||||||
anim.duration = 5000
|
|
||||||
anim.addUpdateListener {
|
|
||||||
hsv[0] = hueOriginal + it.animatedFraction * 3f * 360f
|
|
||||||
hsv[0] = hsv[0] % 360f
|
|
||||||
b.topLogo.drawable.setTintColor(Color.HSVToColor(Color.alpha(color), hsv))
|
|
||||||
}
|
|
||||||
anim.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.topLogo.onClick {
|
|
||||||
if (clickCount != 5 || isRotated) {
|
|
||||||
clickCount = 0
|
|
||||||
return@onClick
|
|
||||||
}
|
|
||||||
isRotated = true
|
|
||||||
val anim = RotateAnimation(
|
|
||||||
0f,
|
|
||||||
180f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f
|
|
||||||
)
|
|
||||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
|
||||||
anim.duration = 2000
|
|
||||||
anim.fillAfter = true
|
|
||||||
activity.getRootView().startAnimation(anim)
|
|
||||||
|
|
||||||
b.list.smoothScrollToPosition(0)
|
|
||||||
adapter.items.add(
|
|
||||||
LoginInfo.Register(
|
|
||||||
loginType = 74,
|
|
||||||
internalName = "eggs",
|
|
||||||
registerName = R.string.eggs,
|
|
||||||
registerLogo = R.drawable.face_1,
|
|
||||||
loginModes = listOf(
|
|
||||||
LoginInfo.Mode(
|
|
||||||
loginMode = 0,
|
|
||||||
name = 0,
|
|
||||||
icon = 0,
|
|
||||||
guideText = 0,
|
|
||||||
credentials = listOf(),
|
|
||||||
errorCodes = mapOf()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
adapter.notifyItemInserted(adapter.items.size - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
when {
|
||||||
activity.loginStores.isNotEmpty() -> {
|
activity.loginStores.isNotEmpty() -> {
|
||||||
// we are navigated here from LoginSummary
|
// we are navigated here from LoginSummary
|
||||||
|
@ -192,50 +106,6 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoginModeClicked(
|
|
||||||
loginType: LoginInfo.Register,
|
|
||||||
loginMode: LoginInfo.Mode
|
|
||||||
) {
|
|
||||||
if (loginType.internalName == "eggs") {
|
|
||||||
nav.navigate(R.id.loginEggsFragment, null, activity.navOptions)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
launch {
|
|
||||||
if (!checkAvailability(loginType.loginType))
|
|
||||||
return@launch
|
|
||||||
|
|
||||||
if (loginMode.isTesting || loginMode.isDevOnly) {
|
|
||||||
MaterialAlertDialogBuilder(activity)
|
|
||||||
.setTitle(R.string.login_chooser_testing_title)
|
|
||||||
.setMessage(R.string.login_chooser_testing_text)
|
|
||||||
.setPositiveButton(R.string.ok) { _, _ ->
|
|
||||||
navigateToLoginMode(loginType, loginMode)
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.show()
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
navigateToLoginMode(loginType, loginMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun navigateToLoginMode(loginType: LoginInfo.Register, loginMode: LoginInfo.Mode) {
|
|
||||||
if (loginMode.isPlatformSelection) {
|
|
||||||
nav.navigate(R.id.loginPlatformListFragment, Bundle(
|
|
||||||
"loginType" to loginType.loginType,
|
|
||||||
"loginMode" to loginMode.loginMode
|
|
||||||
), activity.navOptions)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nav.navigate(R.id.loginFormFragment, Bundle(
|
|
||||||
"loginType" to loginType.loginType,
|
|
||||||
"loginMode" to loginMode.loginMode
|
|
||||||
), activity.navOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun checkAvailability(loginType: Int): Boolean {
|
private suspend fun checkAvailability(loginType: Int): Boolean {
|
||||||
when (loginType) {
|
when (loginType) {
|
||||||
LOGIN_TYPE_LIBRUS -> "librus"
|
LOGIN_TYPE_LIBRUS -> "librus"
|
||||||
|
@ -247,7 +117,7 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||||
else -> null
|
else -> null
|
||||||
}?.let { registerName ->
|
}?.let { registerName ->
|
||||||
var status = app.config.sync.registerAvailability[registerName]
|
var status = app.config.sync.registerAvailability[registerName]
|
||||||
if (status == null || status.nextCheckAt < currentTimeUnix()) {
|
if (status == null || status.nextCheck < currentTimeUnix()) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val api = SzkolnyApi(app)
|
val api = SzkolnyApi(app)
|
||||||
api.runCatching(activity) {
|
api.runCatching(activity) {
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2020-10-18.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator
|
|
||||||
import android.view.animation.Animation
|
|
||||||
import android.view.animation.RotateAnimation
|
|
||||||
import android.webkit.JavascriptInterface
|
|
||||||
import android.webkit.WebView
|
|
||||||
import android.webkit.WebViewClient
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.md5
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class LoginEggsFragment : Fragment(), CoroutineScope {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LoginEggsFragment"
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var app: App
|
|
||||||
private lateinit var activity: LoginActivity
|
|
||||||
private lateinit var view: ViewGroup
|
|
||||||
private lateinit var webView: WebView
|
|
||||||
private val nav by lazy { activity.nav }
|
|
||||||
|
|
||||||
private val job: Job = Job()
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Main
|
|
||||||
|
|
||||||
// local/private variables go here
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
activity = (getActivity() as LoginActivity?) ?: return null
|
|
||||||
context ?: return null
|
|
||||||
app = activity.application as App
|
|
||||||
webView = WebView(activity)
|
|
||||||
view = FrameLayout(activity)
|
|
||||||
view.addView(webView)
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface")
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
if (!isAdded) return
|
|
||||||
|
|
||||||
if (!LoginChooserFragment.isRotated) {
|
|
||||||
nav.navigateUp()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val anim = RotateAnimation(
|
|
||||||
180f,
|
|
||||||
0f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f
|
|
||||||
)
|
|
||||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
|
||||||
anim.duration = 10
|
|
||||||
anim.fillAfter = true
|
|
||||||
activity.getRootView().startAnimation(anim)
|
|
||||||
|
|
||||||
webView.apply {
|
|
||||||
settings.apply {
|
|
||||||
javaScriptEnabled = true
|
|
||||||
}
|
|
||||||
addJavascriptInterface(object : Any() {
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
@JavascriptInterface
|
|
||||||
fun getPrize() {
|
|
||||||
val anim = RotateAnimation(
|
|
||||||
0f,
|
|
||||||
180f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f,
|
|
||||||
Animation.RELATIVE_TO_SELF,
|
|
||||||
0.5f
|
|
||||||
)
|
|
||||||
anim.interpolator = AccelerateDecelerateInterpolator()
|
|
||||||
anim.duration = 10
|
|
||||||
anim.fillAfter = true
|
|
||||||
activity.getRootView().startAnimation(anim)
|
|
||||||
nav.navigate(R.id.loginPrizeFragment, null, activity.navOptions)
|
|
||||||
}
|
|
||||||
}, "EggInterface")
|
|
||||||
loadUrl("https://szkolny.eu/game/runner.html")
|
|
||||||
webViewClient = object : WebViewClient() {
|
|
||||||
override fun onPageFinished(view: WebView?, url: String?) {
|
|
||||||
super.onPageFinished(view, url)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
val deviceId = app.deviceId.md5()
|
|
||||||
val version = BuildConfig.VERSION_NAME
|
|
||||||
val js = """initPage("$deviceId", true, "$version");"""
|
|
||||||
webView.evaluateJavascript(js) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,9 +22,8 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.databinding.LoginFormCheckboxItemBinding
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.LoginFormFieldItemBinding
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.LoginFormFragmentBinding
|
import pl.szczodrzynski.edziennik.databinding.LoginFormFragmentBinding
|
||||||
|
import pl.szczodrzynski.edziennik.databinding.LoginFormItemBinding
|
||||||
import pl.szczodrzynski.navlib.colorAttr
|
import pl.szczodrzynski.navlib.colorAttr
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
@ -32,8 +31,6 @@ import kotlin.coroutines.CoroutineContext
|
||||||
class LoginFormFragment : Fragment(), CoroutineScope {
|
class LoginFormFragment : Fragment(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "LoginFormFragment"
|
private const val TAG = "LoginFormFragment"
|
||||||
// eggs
|
|
||||||
var wantEggs = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
|
@ -78,14 +75,13 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
||||||
b.subTitle.text = platformName ?: app.getString(mode.name)
|
b.subTitle.text = platformName ?: app.getString(mode.name)
|
||||||
b.text.text = platformGuideText ?: app.getString(mode.guideText)
|
b.text.text = platformGuideText ?: app.getString(mode.guideText)
|
||||||
|
|
||||||
val credentials = mutableMapOf<LoginInfo.BaseCredential, Any>()
|
val credentials = mutableMapOf<LoginInfo.Credential, LoginFormItemBinding>()
|
||||||
|
|
||||||
for (credential in mode.credentials) {
|
for (credential in mode.credentials) {
|
||||||
if (platformFormFields?.contains(credential.keyName) == false)
|
if (platformFormFields?.contains(credential.keyName) == false)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (credential is LoginInfo.FormField) {
|
val b = LoginFormItemBinding.inflate(layoutInflater)
|
||||||
val b = LoginFormFieldItemBinding.inflate(layoutInflater)
|
|
||||||
b.textLayout.hint = app.getString(credential.name)
|
b.textLayout.hint = app.getString(credential.name)
|
||||||
if (credential.hideText) {
|
if (credential.hideText) {
|
||||||
b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD
|
b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||||
|
@ -107,37 +103,13 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
||||||
this.b.formContainer.addView(b.root)
|
this.b.formContainer.addView(b.root)
|
||||||
credentials[credential] = b
|
credentials[credential] = b
|
||||||
}
|
}
|
||||||
if (credential is LoginInfo.FormCheckbox) {
|
|
||||||
val b = LoginFormCheckboxItemBinding.inflate(layoutInflater)
|
|
||||||
b.checkbox.text = app.getString(credential.name)
|
|
||||||
b.checkbox.onChange { _, isChecked ->
|
|
||||||
b.errorText.text = null
|
|
||||||
|
|
||||||
// eggs
|
|
||||||
if (register.internalName == "podlasie") {
|
|
||||||
wantEggs = !isChecked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (arguments?.containsKey(credential.keyName) == true) {
|
|
||||||
b.checkbox.isChecked = arguments?.getBoolean(credential.keyName) == true
|
|
||||||
}
|
|
||||||
|
|
||||||
this.b.formContainer.addView(b.root)
|
|
||||||
credentials[credential] = b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
activity.lastError?.let { error ->
|
activity.lastError?.let { error ->
|
||||||
activity.lastError = null
|
activity.lastError = null
|
||||||
startCoroutineTimer(delayMillis = 200L) {
|
startCoroutineTimer(delayMillis = 200L) {
|
||||||
for (credential in credentials) {
|
for (credential in credentials) {
|
||||||
credential.key.errorCodes[error.errorCode]?.let {
|
credential.key.errorCodes[error.errorCode]?.let {
|
||||||
(credential.value as? LoginFormFieldItemBinding)?.let { b ->
|
credential.value.textLayout.error = app.getString(it)
|
||||||
b.textLayout.error = app.getString(it)
|
|
||||||
}
|
|
||||||
(credential.value as? LoginFormCheckboxItemBinding)?.let { b ->
|
|
||||||
b.errorText.text = app.getString(it)
|
|
||||||
}
|
|
||||||
return@startCoroutineTimer
|
return@startCoroutineTimer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +127,7 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
||||||
"loginMode" to loginMode
|
"loginMode" to loginMode
|
||||||
)
|
)
|
||||||
|
|
||||||
if (App.debugMode && b.fakeLogin.isChecked) {
|
if (App.devMode && b.fakeLogin.isChecked) {
|
||||||
payload.putBoolean("fakeLogin", true)
|
payload.putBoolean("fakeLogin", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,14 +137,13 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
||||||
|
|
||||||
var hasErrors = false
|
var hasErrors = false
|
||||||
credentials.forEach { (credential, b) ->
|
credentials.forEach { (credential, b) ->
|
||||||
if (credential is LoginInfo.FormField && b is LoginFormFieldItemBinding) {
|
|
||||||
var text = b.textEdit.text?.toString() ?: return@forEach
|
var text = b.textEdit.text?.toString() ?: return@forEach
|
||||||
if (!credential.hideText)
|
if (!credential.hideText)
|
||||||
text = text.trim()
|
text = text.trim()
|
||||||
|
|
||||||
if (credential.caseMode == LoginInfo.FormField.CaseMode.UPPER_CASE)
|
if (credential.caseMode == LoginInfo.Credential.CaseMode.UPPER_CASE)
|
||||||
text = text.toUpperCase(Locale.getDefault())
|
text = text.toUpperCase(Locale.getDefault())
|
||||||
if (credential.caseMode == LoginInfo.FormField.CaseMode.LOWER_CASE)
|
if (credential.caseMode == LoginInfo.Credential.CaseMode.LOWER_CASE)
|
||||||
text = text.toLowerCase(Locale.getDefault())
|
text = text.toLowerCase(Locale.getDefault())
|
||||||
|
|
||||||
credential.stripTextRegex?.let {
|
credential.stripTextRegex?.let {
|
||||||
|
@ -196,12 +167,6 @@ class LoginFormFragment : Fragment(), CoroutineScope {
|
||||||
payload.putString(credential.keyName, text)
|
payload.putString(credential.keyName, text)
|
||||||
arguments?.putString(credential.keyName, text)
|
arguments?.putString(credential.keyName, text)
|
||||||
}
|
}
|
||||||
if (credential is LoginInfo.FormCheckbox && b is LoginFormCheckboxItemBinding) {
|
|
||||||
val checked = b.checkbox.isChecked
|
|
||||||
payload.putBoolean(credential.keyName, checked)
|
|
||||||
arguments?.putBoolean(credential.keyName, checked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasErrors)
|
if (hasErrors)
|
||||||
return@onClick
|
return@onClick
|
||||||
|
|
|
@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
||||||
|
|
||||||
object LoginInfo {
|
object LoginInfo {
|
||||||
|
|
||||||
private fun getEmailCredential(keyName: String) = FormField(
|
private fun getEmailCredential(keyName: String) = Credential(
|
||||||
keyName = keyName,
|
keyName = keyName,
|
||||||
name = R.string.login_hint_email,
|
name = R.string.login_hint_email,
|
||||||
icon = CommunityMaterial.Icon.cmd_at,
|
icon = CommunityMaterial.Icon.cmd_at,
|
||||||
|
@ -24,9 +24,9 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+",
|
validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
)
|
)
|
||||||
private fun getPasswordCredential(keyName: String) = FormField(
|
private fun getPasswordCredential(keyName: String) = Credential(
|
||||||
keyName = keyName,
|
keyName = keyName,
|
||||||
name = R.string.login_hint_password,
|
name = R.string.login_hint_password,
|
||||||
icon = CommunityMaterial.Icon2.cmd_lock_outline,
|
icon = CommunityMaterial.Icon2.cmd_lock_outline,
|
||||||
|
@ -94,7 +94,7 @@ object LoginInfo {
|
||||||
hintText = R.string.login_mode_librus_jst_hint,
|
hintText = R.string.login_mode_librus_jst_hint,
|
||||||
guideText = R.string.login_mode_librus_jst_guide,
|
guideText = R.string.login_mode_librus_jst_guide,
|
||||||
credentials = listOf(
|
credentials = listOf(
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "accountCode",
|
keyName = "accountCode",
|
||||||
name = R.string.login_hint_token,
|
name = R.string.login_hint_token,
|
||||||
icon = CommunityMaterial.Icon.cmd_code_braces,
|
icon = CommunityMaterial.Icon.cmd_code_braces,
|
||||||
|
@ -103,9 +103,9 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[A-Z0-9_]+",
|
validationRegex = "[A-Z0-9_]+",
|
||||||
caseMode = FormField.CaseMode.UPPER_CASE
|
caseMode = Credential.CaseMode.UPPER_CASE
|
||||||
),
|
),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "accountPin",
|
keyName = "accountPin",
|
||||||
name = R.string.login_hint_pin,
|
name = R.string.login_hint_pin,
|
||||||
icon = CommunityMaterial.Icon2.cmd_lock,
|
icon = CommunityMaterial.Icon2.cmd_lock,
|
||||||
|
@ -114,7 +114,7 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[a-z0-9_]+",
|
validationRegex = "[a-z0-9_]+",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
errorCodes = mapOf(
|
errorCodes = mapOf(
|
||||||
|
@ -138,7 +138,7 @@ object LoginInfo {
|
||||||
guideText = R.string.login_mode_vulcan_api_guide,
|
guideText = R.string.login_mode_vulcan_api_guide,
|
||||||
isRecommended = true,
|
isRecommended = true,
|
||||||
credentials = listOf(
|
credentials = listOf(
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "deviceToken",
|
keyName = "deviceToken",
|
||||||
name = R.string.login_hint_token,
|
name = R.string.login_hint_token,
|
||||||
icon = CommunityMaterial.Icon.cmd_code_braces,
|
icon = CommunityMaterial.Icon.cmd_code_braces,
|
||||||
|
@ -149,9 +149,9 @@ object LoginInfo {
|
||||||
),
|
),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[A-Z0-9]{5,12}",
|
validationRegex = "[A-Z0-9]{5,12}",
|
||||||
caseMode = FormField.CaseMode.UPPER_CASE
|
caseMode = Credential.CaseMode.UPPER_CASE
|
||||||
),
|
),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "symbol",
|
keyName = "symbol",
|
||||||
name = R.string.login_hint_symbol,
|
name = R.string.login_hint_symbol,
|
||||||
icon = CommunityMaterial.Icon2.cmd_school,
|
icon = CommunityMaterial.Icon2.cmd_school,
|
||||||
|
@ -162,9 +162,9 @@ object LoginInfo {
|
||||||
),
|
),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[a-z0-9_-]+",
|
validationRegex = "[a-z0-9_-]+",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
),
|
),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "devicePin",
|
keyName = "devicePin",
|
||||||
name = R.string.login_hint_pin,
|
name = R.string.login_hint_pin,
|
||||||
icon = CommunityMaterial.Icon2.cmd_lock,
|
icon = CommunityMaterial.Icon2.cmd_lock,
|
||||||
|
@ -175,76 +175,24 @@ object LoginInfo {
|
||||||
),
|
),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[0-9]+",
|
validationRegex = "[0-9]+",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
errorCodes = mapOf(
|
errorCodes = mapOf(
|
||||||
ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token
|
ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token
|
||||||
)
|
)
|
||||||
),
|
)/*,
|
||||||
Mode(
|
|
||||||
loginMode = LOGIN_MODE_VULCAN_HEBE,
|
|
||||||
name = R.string.login_mode_vulcan_api,
|
|
||||||
icon = R.drawable.login_mode_vulcan_hebe,
|
|
||||||
hintText = R.string.login_mode_vulcan_api_hint,
|
|
||||||
guideText = R.string.login_mode_vulcan_api_guide,
|
|
||||||
isTesting = true,
|
|
||||||
credentials = listOf(
|
|
||||||
FormField(
|
|
||||||
keyName = "deviceToken",
|
|
||||||
name = R.string.login_hint_token,
|
|
||||||
icon = CommunityMaterial.Icon.cmd_code_braces,
|
|
||||||
emptyText = R.string.login_error_no_token,
|
|
||||||
invalidText = R.string.login_error_incorrect_token,
|
|
||||||
errorCodes = mapOf(
|
|
||||||
ERROR_LOGIN_VULCAN_INVALID_TOKEN to R.string.login_error_incorrect_token
|
|
||||||
),
|
|
||||||
isRequired = true,
|
|
||||||
validationRegex = "[A-Z0-9]{5,12}",
|
|
||||||
caseMode = FormField.CaseMode.UPPER_CASE
|
|
||||||
),
|
|
||||||
FormField(
|
|
||||||
keyName = "symbol",
|
|
||||||
name = R.string.login_hint_symbol,
|
|
||||||
icon = CommunityMaterial.Icon2.cmd_school,
|
|
||||||
emptyText = R.string.login_error_no_symbol,
|
|
||||||
invalidText = R.string.login_error_incorrect_symbol,
|
|
||||||
errorCodes = mapOf(
|
|
||||||
ERROR_LOGIN_VULCAN_INVALID_SYMBOL to R.string.login_error_incorrect_symbol
|
|
||||||
),
|
|
||||||
isRequired = true,
|
|
||||||
validationRegex = "[a-z0-9_-]+",
|
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
|
||||||
),
|
|
||||||
FormField(
|
|
||||||
keyName = "devicePin",
|
|
||||||
name = R.string.login_hint_pin,
|
|
||||||
icon = CommunityMaterial.Icon2.cmd_lock,
|
|
||||||
emptyText = R.string.login_error_no_pin,
|
|
||||||
invalidText = R.string.login_error_incorrect_pin,
|
|
||||||
errorCodes = mapOf(
|
|
||||||
ERROR_LOGIN_VULCAN_INVALID_PIN to R.string.login_error_incorrect_pin
|
|
||||||
),
|
|
||||||
isRequired = true,
|
|
||||||
validationRegex = "[0-9]+",
|
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
|
||||||
)
|
|
||||||
),
|
|
||||||
errorCodes = mapOf(
|
|
||||||
ERROR_LOGIN_VULCAN_EXPIRED_TOKEN to R.string.login_error_expired_token
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Mode(
|
Mode(
|
||||||
loginMode = LOGIN_MODE_VULCAN_WEB,
|
loginMode = LOGIN_MODE_VULCAN_WEB,
|
||||||
name = R.string.login_mode_vulcan_web,
|
name = R.string.login_mode_vulcan_web,
|
||||||
icon = R.drawable.login_mode_vulcan_web,
|
icon = R.drawable.login_mode_vulcan_web,
|
||||||
hintText = R.string.login_mode_vulcan_web_hint,
|
hintText = R.string.login_mode_vulcan_web_hint,
|
||||||
guideText = R.string.login_mode_vulcan_web_guide,
|
guideText = R.string.login_mode_vulcan_web_guide,
|
||||||
isDevOnly = true,
|
isTesting = true,
|
||||||
isPlatformSelection = true,
|
isPlatformSelection = true,
|
||||||
credentials = listOf(
|
credentials = listOf(
|
||||||
getEmailCredential("webEmail"),
|
getEmailCredential("webEmail"),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "webUsername",
|
keyName = "webUsername",
|
||||||
name = R.string.login_hint_username,
|
name = R.string.login_hint_username,
|
||||||
icon = CommunityMaterial.Icon.cmd_account_outline,
|
icon = CommunityMaterial.Icon.cmd_account_outline,
|
||||||
|
@ -253,12 +201,12 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[A-Z]{7}[0-9]+",
|
validationRegex = "[A-Z]{7}[0-9]+",
|
||||||
caseMode = FormField.CaseMode.UPPER_CASE
|
caseMode = Credential.CaseMode.UPPER_CASE
|
||||||
),
|
),
|
||||||
getPasswordCredential("webPassword")
|
getPasswordCredential("webPassword")
|
||||||
),
|
),
|
||||||
errorCodes = mapOf()
|
errorCodes = mapOf()
|
||||||
)
|
)*/
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Register(
|
Register(
|
||||||
|
@ -274,7 +222,7 @@ object LoginInfo {
|
||||||
hintText = R.string.login_mode_mobidziennik_web_hint,
|
hintText = R.string.login_mode_mobidziennik_web_hint,
|
||||||
guideText = R.string.login_mode_mobidziennik_web_guide,
|
guideText = R.string.login_mode_mobidziennik_web_guide,
|
||||||
credentials = listOf(
|
credentials = listOf(
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "username",
|
keyName = "username",
|
||||||
name = R.string.login_hint_login_email,
|
name = R.string.login_hint_login_email,
|
||||||
icon = CommunityMaterial.Icon.cmd_account_outline,
|
icon = CommunityMaterial.Icon.cmd_account_outline,
|
||||||
|
@ -283,9 +231,9 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "^[a-z0-9_\\-@+.]+$",
|
validationRegex = "^[a-z0-9_\\-@+.]+$",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
),
|
),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "password",
|
keyName = "password",
|
||||||
name = R.string.login_hint_password,
|
name = R.string.login_hint_password,
|
||||||
icon = CommunityMaterial.Icon2.cmd_lock_outline,
|
icon = CommunityMaterial.Icon2.cmd_lock_outline,
|
||||||
|
@ -298,7 +246,7 @@ object LoginInfo {
|
||||||
validationRegex = ".*",
|
validationRegex = ".*",
|
||||||
hideText = true
|
hideText = true
|
||||||
),
|
),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "serverName",
|
keyName = "serverName",
|
||||||
name = R.string.login_hint_address,
|
name = R.string.login_hint_address,
|
||||||
icon = CommunityMaterial.Icon2.cmd_web,
|
icon = CommunityMaterial.Icon2.cmd_web,
|
||||||
|
@ -309,7 +257,7 @@ object LoginInfo {
|
||||||
),
|
),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "^[a-z0-9_\\-]+\$",
|
validationRegex = "^[a-z0-9_\\-]+\$",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
errorCodes = mapOf(
|
errorCodes = mapOf(
|
||||||
|
@ -332,7 +280,7 @@ object LoginInfo {
|
||||||
hintText = R.string.login_mode_idziennik_web_hint,
|
hintText = R.string.login_mode_idziennik_web_hint,
|
||||||
guideText = R.string.login_mode_idziennik_web_guide,
|
guideText = R.string.login_mode_idziennik_web_guide,
|
||||||
credentials = listOf(
|
credentials = listOf(
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "schoolName",
|
keyName = "schoolName",
|
||||||
name = R.string.login_hint_school_name,
|
name = R.string.login_hint_school_name,
|
||||||
icon = CommunityMaterial.Icon2.cmd_school,
|
icon = CommunityMaterial.Icon2.cmd_school,
|
||||||
|
@ -343,9 +291,9 @@ object LoginInfo {
|
||||||
),
|
),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "^[a-z0-9_\\-.]+$",
|
validationRegex = "^[a-z0-9_\\-.]+$",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
),
|
),
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "username",
|
keyName = "username",
|
||||||
name = R.string.login_hint_username,
|
name = R.string.login_hint_username,
|
||||||
icon = CommunityMaterial.Icon.cmd_account_outline,
|
icon = CommunityMaterial.Icon.cmd_account_outline,
|
||||||
|
@ -354,7 +302,7 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "^[a-z0-9_\\-.]+$",
|
validationRegex = "^[a-z0-9_\\-.]+$",
|
||||||
caseMode = FormField.CaseMode.LOWER_CASE
|
caseMode = Credential.CaseMode.LOWER_CASE
|
||||||
),
|
),
|
||||||
getPasswordCredential("password")
|
getPasswordCredential("password")
|
||||||
),
|
),
|
||||||
|
@ -398,7 +346,7 @@ object LoginInfo {
|
||||||
icon = R.drawable.login_mode_podlasie_api,
|
icon = R.drawable.login_mode_podlasie_api,
|
||||||
guideText = R.string.login_mode_podlasie_api_guide,
|
guideText = R.string.login_mode_podlasie_api_guide,
|
||||||
credentials = listOf(
|
credentials = listOf(
|
||||||
FormField(
|
Credential(
|
||||||
keyName = "apiToken",
|
keyName = "apiToken",
|
||||||
name = R.string.login_hint_token,
|
name = R.string.login_hint_token,
|
||||||
icon = CommunityMaterial.Icon2.cmd_lock_outline,
|
icon = CommunityMaterial.Icon2.cmd_lock_outline,
|
||||||
|
@ -407,15 +355,7 @@ object LoginInfo {
|
||||||
errorCodes = mapOf(),
|
errorCodes = mapOf(),
|
||||||
isRequired = true,
|
isRequired = true,
|
||||||
validationRegex = "[a-zA-Z0-9]{10}",
|
validationRegex = "[a-zA-Z0-9]{10}",
|
||||||
caseMode = FormField.CaseMode.UNCHANGED
|
caseMode = Credential.CaseMode.UNCHANGED
|
||||||
),
|
|
||||||
FormCheckbox(
|
|
||||||
keyName = "logoutDevices",
|
|
||||||
name = R.string.login_podlasie_logout_devices,
|
|
||||||
checked = false,
|
|
||||||
errorCodes = mapOf(
|
|
||||||
ERROR_LOGIN_PODLASIE_API_DEVICE_LIMIT to R.string.error_602_reason
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
errorCodes = mapOf()
|
errorCodes = mapOf()
|
||||||
|
@ -450,10 +390,9 @@ object LoginInfo {
|
||||||
|
|
||||||
val isRecommended: Boolean = false,
|
val isRecommended: Boolean = false,
|
||||||
val isTesting: Boolean = false,
|
val isTesting: Boolean = false,
|
||||||
val isDevOnly: Boolean = false,
|
|
||||||
val isPlatformSelection: Boolean = false,
|
val isPlatformSelection: Boolean = false,
|
||||||
|
|
||||||
val credentials: List<BaseCredential>,
|
val credentials: List<Credential>,
|
||||||
val errorCodes: Map<Int, Int>
|
val errorCodes: Map<Int, Int>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -470,18 +409,11 @@ object LoginInfo {
|
||||||
val apiData: JsonObject
|
val apiData: JsonObject
|
||||||
)
|
)
|
||||||
|
|
||||||
open class BaseCredential(
|
data class Credential(
|
||||||
open val keyName: String,
|
val keyName: String,
|
||||||
@StringRes
|
|
||||||
open val name: Int,
|
|
||||||
open val errorCodes: Map<Int, Int>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class FormField(
|
|
||||||
override val keyName: String,
|
|
||||||
|
|
||||||
@StringRes
|
@StringRes
|
||||||
override val name: Int,
|
val name: Int,
|
||||||
val icon: IIcon,
|
val icon: IIcon,
|
||||||
@StringRes
|
@StringRes
|
||||||
val placeholder: Int? = null,
|
val placeholder: Int? = null,
|
||||||
|
@ -489,7 +421,7 @@ object LoginInfo {
|
||||||
val emptyText: Int,
|
val emptyText: Int,
|
||||||
@StringRes
|
@StringRes
|
||||||
val invalidText: Int,
|
val invalidText: Int,
|
||||||
override val errorCodes: Map<Int, Int>,
|
val errorCodes: Map<Int, Int>,
|
||||||
@StringRes
|
@StringRes
|
||||||
val hintText: Int? = null,
|
val hintText: Int? = null,
|
||||||
|
|
||||||
|
@ -498,18 +430,10 @@ object LoginInfo {
|
||||||
val caseMode: CaseMode = CaseMode.UNCHANGED,
|
val caseMode: CaseMode = CaseMode.UNCHANGED,
|
||||||
val hideText: Boolean = false,
|
val hideText: Boolean = false,
|
||||||
val stripTextRegex: String? = null
|
val stripTextRegex: String? = null
|
||||||
) : BaseCredential(keyName, name, errorCodes) {
|
) {
|
||||||
enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE }
|
enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE }
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FormCheckbox(
|
|
||||||
override val keyName: String,
|
|
||||||
@StringRes
|
|
||||||
override val name: Int,
|
|
||||||
val checked: Boolean = false,
|
|
||||||
override val errorCodes: Map<Int, Int> = mapOf()
|
|
||||||
) : BaseCredential(keyName, name, errorCodes)
|
|
||||||
|
|
||||||
var chooserList: MutableList<Any>? = null
|
var chooserList: MutableList<Any>? = null
|
||||||
var platformList: MutableMap<Int, List<Platform>> = mutableMapOf()
|
var platformList: MutableMap<Int, List<Platform>> = mutableMapOf()
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var timeoutJob: Job
|
private lateinit var timeoutJob: Job
|
||||||
private lateinit var adapter: LoginPlatformAdapter
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
if (!isAdded) return
|
if (!isAdded) return
|
||||||
|
@ -58,7 +57,12 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope {
|
||||||
val loginMode = arguments?.getInt("loginMode") ?: return
|
val loginMode = arguments?.getInt("loginMode") ?: return
|
||||||
val mode = register.loginModes.firstOrNull { it.loginMode == loginMode } ?: return
|
val mode = register.loginModes.firstOrNull { it.loginMode == loginMode } ?: return
|
||||||
|
|
||||||
adapter = LoginPlatformAdapter(activity) { platform ->
|
timeoutJob = startCoroutineTimer(5000L) {
|
||||||
|
b.timeoutText.isVisible = true
|
||||||
|
timeoutJob.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
val adapter = LoginPlatformAdapter(activity) { platform ->
|
||||||
nav.navigate(R.id.loginFormFragment, Bundle(
|
nav.navigate(R.id.loginFormFragment, Bundle(
|
||||||
"loginType" to platform.loginType,
|
"loginType" to platform.loginType,
|
||||||
"loginMode" to platform.loginMode,
|
"loginMode" to platform.loginMode,
|
||||||
|
@ -69,30 +73,7 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope {
|
||||||
), activity.navOptions)
|
), activity.navOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPlatforms(register, mode)
|
|
||||||
b.reloadButton.isVisible = App.devMode
|
|
||||||
b.reloadButton.onClick {
|
|
||||||
LoginInfo.platformList.remove(mode.name)
|
|
||||||
loadPlatforms(register, mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.list.apply {
|
|
||||||
setHasFixedSize(true)
|
|
||||||
layoutManager = LinearLayoutManager(context)
|
|
||||||
addItemDecoration(SimpleDividerItemDecoration(context))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadPlatforms(register: LoginInfo.Register, mode: LoginInfo.Mode) {
|
|
||||||
launch {
|
launch {
|
||||||
timeoutJob = startCoroutineTimer(5000L) {
|
|
||||||
b.timeoutText.isVisible = true
|
|
||||||
timeoutJob.cancel()
|
|
||||||
}
|
|
||||||
b.loadingLayout.isVisible = true
|
|
||||||
b.list.isVisible = false
|
|
||||||
b.reloadButton.isEnabled = false
|
|
||||||
|
|
||||||
val platforms = LoginInfo.platformList[mode.name]
|
val platforms = LoginInfo.platformList[mode.name]
|
||||||
?: run {
|
?: run {
|
||||||
api.runCatching(activity) {
|
api.runCatching(activity) {
|
||||||
|
@ -106,11 +87,14 @@ class LoginPlatformListFragment : Fragment(), CoroutineScope {
|
||||||
|
|
||||||
adapter.items = platforms
|
adapter.items = platforms
|
||||||
b.list.adapter = adapter
|
b.list.adapter = adapter
|
||||||
|
b.list.apply {
|
||||||
|
setHasFixedSize(true)
|
||||||
|
layoutManager = LinearLayoutManager(context)
|
||||||
|
addItemDecoration(SimpleDividerItemDecoration(context))
|
||||||
|
}
|
||||||
timeoutJob.cancel()
|
timeoutJob.cancel()
|
||||||
b.loadingLayout.isVisible = false
|
b.loadingLayout.isVisible = false
|
||||||
b.list.isVisible = true
|
b.list.isVisible = true
|
||||||
b.reloadButton.isEnabled = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2020-10-18.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Process
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import coil.api.load
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.LoginPrizeFragmentBinding
|
|
||||||
import pl.szczodrzynski.edziennik.onClick
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import kotlin.system.exitProcess
|
|
||||||
|
|
||||||
class LoginPrizeFragment : Fragment(), CoroutineScope {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "LoginPrizeFragment"
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var app: App
|
|
||||||
private lateinit var activity: LoginActivity
|
|
||||||
private lateinit var b: LoginPrizeFragmentBinding
|
|
||||||
private val nav by lazy { activity.nav }
|
|
||||||
|
|
||||||
private val job: Job = Job()
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Main
|
|
||||||
|
|
||||||
// local/private variables go here
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
activity = (getActivity() as LoginActivity?) ?: return null
|
|
||||||
context ?: return null
|
|
||||||
app = activity.application as App
|
|
||||||
b = LoginPrizeFragmentBinding.inflate(inflater)
|
|
||||||
return b.root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
b.button.load("https://szkolny.eu/game/button.png")
|
|
||||||
b.button.onClick {
|
|
||||||
MaterialAlertDialogBuilder(activity)
|
|
||||||
.setTitle(R.string.are_you_sure)
|
|
||||||
.setMessage(R.string.dev_mode_enable_warning)
|
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
|
||||||
app.config.debugMode = true
|
|
||||||
App.devMode = true
|
|
||||||
MaterialAlertDialogBuilder(activity)
|
|
||||||
.setTitle("Restart")
|
|
||||||
.setMessage("Wymagany restart aplikacji")
|
|
||||||
.setPositiveButton(R.string.ok) { _, _ ->
|
|
||||||
Process.killProcess(Process.myPid())
|
|
||||||
Runtime.getRuntime().exit(0)
|
|
||||||
exitProcess(0)
|
|
||||||
}
|
|
||||||
.setCancelable(false)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.no) { _, _ ->
|
|
||||||
app.config.debugMode = false
|
|
||||||
App.devMode = false
|
|
||||||
activity.finish()
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,10 +10,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.LoginChooserModeItemBinding
|
import pl.szczodrzynski.edziennik.databinding.LoginChooserModeItemBinding
|
||||||
import pl.szczodrzynski.edziennik.resolveColor
|
|
||||||
import pl.szczodrzynski.edziennik.setTintColor
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginChooserAdapter
|
import pl.szczodrzynski.edziennik.ui.modules.login.LoginChooserAdapter
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
|
import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
|
||||||
|
@ -37,19 +34,6 @@ class ModeViewHolder(
|
||||||
b.description.isVisible = true
|
b.description.isVisible = true
|
||||||
b.description.setText(item.hintText)
|
b.description.setText(item.hintText)
|
||||||
}
|
}
|
||||||
|
b.hint.isVisible = false
|
||||||
b.badge.isVisible = item.isRecommended || item.isDevOnly || item.isTesting
|
|
||||||
if (item.isRecommended) {
|
|
||||||
b.badge.setText(R.string.login_chooser_mode_recommended)
|
|
||||||
b.badge.background.setTintColor(R.color.md_blue_300.resolveColor(app))
|
|
||||||
}
|
|
||||||
if (item.isTesting) {
|
|
||||||
b.badge.setText(R.string.login_chooser_mode_testing)
|
|
||||||
b.badge.background.setTintColor(R.color.md_yellow_300.resolveColor(app))
|
|
||||||
}
|
|
||||||
if (item.isDevOnly) {
|
|
||||||
b.badge.setText(R.string.login_chooser_mode_dev_only)
|
|
||||||
b.badge.background.setTintColor(R.color.md_red_300.resolveColor(app))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ class MessageFragment : Fragment(), CoroutineScope {
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
b.downloadButton.isVisible = App.devMode
|
b.downloadButton.isVisible = App.debugMode
|
||||||
b.downloadButton.onClick {
|
b.downloadButton.onClick {
|
||||||
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||||
}
|
}
|
||||||
|
|
|
@ -581,7 +581,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||||
syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled());
|
syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled());
|
||||||
syncCardIntervalItem.setOnClickAction(() -> {
|
syncCardIntervalItem.setOnClickAction(() -> {
|
||||||
List<CharSequence> intervalNames = new ArrayList<>();
|
List<CharSequence> intervalNames = new ArrayList<>();
|
||||||
if (App.Companion.getDebugMode() && false) {
|
if (App.Companion.getDevMode() && false) {
|
||||||
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_seconds, 30));
|
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_seconds, 30));
|
||||||
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_minutes, 2));
|
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_minutes, 2));
|
||||||
}
|
}
|
||||||
|
@ -593,7 +593,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||||
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 3));
|
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 3));
|
||||||
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 4));
|
intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 4));
|
||||||
List<Integer> intervals = new ArrayList<>();
|
List<Integer> intervals = new ArrayList<>();
|
||||||
if (App.Companion.getDebugMode() && false) {
|
if (App.Companion.getDevMode() && false) {
|
||||||
intervals.add(30);
|
intervals.add(30);
|
||||||
intervals.add(2 * 60);
|
intervals.add(2 * 60);
|
||||||
}
|
}
|
||||||
|
@ -1059,24 +1059,6 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App.Companion.getDevMode()) {
|
|
||||||
items.add(
|
|
||||||
new MaterialAboutSwitchItem(
|
|
||||||
getString(R.string.settings_register_hide_sticks_from_old),
|
|
||||||
null,
|
|
||||||
new IconicsDrawable(activity)
|
|
||||||
.icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline)
|
|
||||||
.size(IconicsSize.dp(iconSizeDp))
|
|
||||||
.color(IconicsColor.colorInt(iconColor))
|
|
||||||
)
|
|
||||||
.setChecked(app.getConfig().forProfile().getGrades().getHideSticksFromOld())
|
|
||||||
.setOnChangeAction((isChecked, tag) -> {
|
|
||||||
app.getConfig().forProfile().getGrades().setHideSticksFromOld(isChecked);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@ -1263,7 +1245,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||||
})
|
})
|
||||||
.build());*/
|
.build());*/
|
||||||
|
|
||||||
if (App.Companion.getDevMode()) {
|
if (App.Companion.getDebugMode()) {
|
||||||
items.add(new MaterialAboutActionItem.Builder()
|
items.add(new MaterialAboutActionItem.Builder()
|
||||||
.text(R.string.settings_about_crash_text)
|
.text(R.string.settings_about_crash_text)
|
||||||
.subText(R.string.settings_about_crash_subtext)
|
.subText(R.string.settings_about_crash_subtext)
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class Utils {
|
||||||
public static List<String> debugLog = new ArrayList<>();
|
public static List<String> debugLog = new ArrayList<>();
|
||||||
|
|
||||||
public static void d(String TAG, String message) {
|
public static void d(String TAG, String message) {
|
||||||
if (App.Companion.getDevMode()) {
|
if (App.Companion.getDebugMode()) {
|
||||||
HyperLog.d("Szkolny/"+TAG, message);
|
HyperLog.d("Szkolny/"+TAG, message);
|
||||||
//debugLog.add(TAG+": "+message);
|
//debugLog.add(TAG+": "+message);
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 2 KiB |
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="androidx.core.text.HtmlCompat" />
|
<import type="android.text.Html" />
|
||||||
<variable
|
<variable
|
||||||
name="message"
|
name="message"
|
||||||
type="pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus.Message" />
|
type="pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus.Message" />
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@{HtmlCompat.fromHtml(message.title, HtmlCompat.FROM_HTML_MODE_LEGACY)}"
|
android:text="@{Html.fromHtml(message.title)}"
|
||||||
android:textAppearance="@style/NavView.TextView.Title"
|
android:textAppearance="@style/NavView.TextView.Title"
|
||||||
tools:text="Dziennik nie działa" />
|
tools:text="Dziennik nie działa" />
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="@{HtmlCompat.fromHtml(message.contentLong, HtmlCompat.FROM_HTML_MODE_LEGACY)}"
|
android:text="@{Html.fromHtml(message.contentLong)}"
|
||||||
tools:text="Dziennik się zepsuł i nie działa, szkoda\n\n\nwiele linijek ma ten tekst" />
|
tools:text="Dziennik się zepsuł i nie działa, szkoda\n\n\nwiele linijek ma ten tekst" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
android:textSize="24sp" />
|
android:textSize="24sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/subtitleText"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
|
@ -48,14 +47,13 @@
|
||||||
tools:listitem="@layout/login_chooser_item" />
|
tools:listitem="@layout/login_chooser_item" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footnoteText"
|
|
||||||
style="@style/TextAppearance.AppCompat.Small"
|
style="@style/TextAppearance.AppCompat.Small"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginVertical="8dp"
|
android:layout_marginVertical="8dp"
|
||||||
android:text="@string/login_copyright_notice"
|
android:text="@string/login_copyright_notice"
|
||||||
android:gravity="center" />
|
android:textAlignment="center" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -36,19 +36,6 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<com.mikepenz.iconics.view.IconicsTextView
|
|
||||||
android:id="@+id/badge"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/bg_rounded_8dp"
|
|
||||||
android:minHeight="0dp"
|
|
||||||
android:paddingHorizontal="4dp"
|
|
||||||
android:paddingVertical="2dp"
|
|
||||||
android:textColor="@color/md_black_1000"
|
|
||||||
android:textSize="12sp"
|
|
||||||
tools:backgroundTint="@color/md_blue_300"
|
|
||||||
tools:text="{cmd-alert-circle-outline} Zalecane" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -56,6 +43,13 @@
|
||||||
android:textAppearance="@style/NavView.TextView.Medium"
|
android:textAppearance="@style/NavView.TextView.Medium"
|
||||||
tools:text="Zaloguj używając e-maila" />
|
tools:text="Zaloguj używając e-maila" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/hint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="(zalecane)" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/description"
|
android:id="@+id/description"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kuba Szczodrzyński 2020-10-16.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingVertical="4dp">
|
|
||||||
|
|
||||||
<com.google.android.material.checkbox.MaterialCheckBox
|
|
||||||
android:id="@+id/checkbox"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="0dp"
|
|
||||||
tools:text="Text" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/errorText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="32dp"
|
|
||||||
android:textColor="?colorError"
|
|
||||||
tools:text="Error text" />
|
|
||||||
</LinearLayout>
|
|
||||||
</layout>
|
|
|
@ -78,15 +78,6 @@
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/reloadButton"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/refresh"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kuba Szczodrzyński 2020-10-18.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/black">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_margin="48dp"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:scaleType="fitXY"
|
|
||||||
tools:src="@tools:sample/avatars" />
|
|
||||||
</FrameLayout>
|
|
||||||
</layout>
|
|
|
@ -18,24 +18,6 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_loginChooserFragment_to_loginFormFragment"
|
android:id="@+id/action_loginChooserFragment_to_loginFormFragment"
|
||||||
app:destination="@id/loginFormFragment" />
|
app:destination="@id/loginFormFragment" />
|
||||||
<!-- eggs -->
|
|
||||||
<action
|
|
||||||
android:id="@+id/action_loginChooserFragment_to_loginEggsFragment"
|
|
||||||
app:destination="@id/loginEggsFragment" />
|
|
||||||
</fragment>
|
|
||||||
<!-- eggs -->
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/loginEggsFragment"
|
|
||||||
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginEggsFragment"
|
|
||||||
android:label="LoginEggsFragment">
|
|
||||||
<action
|
|
||||||
android:id="@+id/action_loginEggsFragment_to_loginPrizeFragment"
|
|
||||||
app:destination="@id/loginPrizeFragment" />
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/loginPrizeFragment"
|
|
||||||
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginPrizeFragment"
|
|
||||||
android:label="LoginPrizeFragment">
|
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/loginPlatformListFragment"
|
android:id="@+id/loginPlatformListFragment"
|
||||||
|
|
|
@ -854,7 +854,7 @@
|
||||||
<string name="settings_about_licenses_text">Open-Source-Lizenzen</string>
|
<string name="settings_about_licenses_text">Open-Source-Lizenzen</string>
|
||||||
<string name="settings_about_privacy_policy_text">Datenschutzrichtlinie</string>
|
<string name="settings_about_privacy_policy_text">Datenschutzrichtlinie</string>
|
||||||
<string name="settings_about_register_title_text">E-Klassenbuch</string>
|
<string name="settings_about_register_title_text">E-Klassenbuch</string>
|
||||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - Februar 2021</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2020</string>
|
||||||
<string name="settings_about_update_subtext">Klicken Sie hier, um nach Aktualisierungen zu suchen</string>
|
<string name="settings_about_update_subtext">Klicken Sie hier, um nach Aktualisierungen zu suchen</string>
|
||||||
<string name="settings_about_update_text">Aktualisierung</string>
|
<string name="settings_about_update_text">Aktualisierung</string>
|
||||||
<string name="settings_about_version_text">Version</string>
|
<string name="settings_about_version_text">Version</string>
|
||||||
|
|
|
@ -856,7 +856,7 @@
|
||||||
<string name="settings_about_licenses_text">Open-source licenses</string>
|
<string name="settings_about_licenses_text">Open-source licenses</string>
|
||||||
<string name="settings_about_privacy_policy_text">Privacy policy</string>
|
<string name="settings_about_privacy_policy_text">Privacy policy</string>
|
||||||
<string name="settings_about_register_title_text">E-register</string>
|
<string name="settings_about_register_title_text">E-register</string>
|
||||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - February 2021</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2020</string>
|
||||||
<string name="settings_about_update_subtext">Click to check for updates</string>
|
<string name="settings_about_update_subtext">Click to check for updates</string>
|
||||||
<string name="settings_about_update_text">Update</string>
|
<string name="settings_about_update_text">Update</string>
|
||||||
<string name="settings_about_version_text">Version</string>
|
<string name="settings_about_version_text">Version</string>
|
||||||
|
@ -1233,5 +1233,4 @@
|
||||||
<string name="permissions_attachment">In order to download the file, you have to grant file storage permission for the application.\n\nClick OK to grant the permission.</string>
|
<string name="permissions_attachment">In order to download the file, you have to grant file storage permission for the application.\n\nClick OK to grant the permission.</string>
|
||||||
<string name="permissions_denied">You denied the required permissions for the application.\n\nIn order to grant the permission, open the Permissions screen for Szkolny.eu in phone settings.\n\nClick OK to open app settings now.</string>
|
<string name="permissions_denied">You denied the required permissions for the application.\n\nIn order to grant the permission, open the Permissions screen for Szkolny.eu in phone settings.\n\nClick OK to open app settings now.</string>
|
||||||
<string name="permissions_required">Required permissions</string>
|
<string name="permissions_required">Required permissions</string>
|
||||||
<string name="settings_register_hide_sticks_from_old">Your mother won\'t see your F grades</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -919,7 +919,7 @@
|
||||||
<string name="settings_about_licenses_text">Licencje open-source</string>
|
<string name="settings_about_licenses_text">Licencje open-source</string>
|
||||||
<string name="settings_about_privacy_policy_text">Polityka prywatności</string>
|
<string name="settings_about_privacy_policy_text">Polityka prywatności</string>
|
||||||
<string name="settings_about_register_title_text">E-dziennik</string>
|
<string name="settings_about_register_title_text">E-dziennik</string>
|
||||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nwrzesień 2018 - luty 2021</string>
|
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nwrzesień 2018 - 2020</string>
|
||||||
<string name="settings_about_update_subtext">Kliknij, aby sprawdzić aktualizacje</string>
|
<string name="settings_about_update_subtext">Kliknij, aby sprawdzić aktualizacje</string>
|
||||||
<string name="settings_about_update_text">Aktualizacja</string>
|
<string name="settings_about_update_text">Aktualizacja</string>
|
||||||
<string name="settings_about_version_text">Wersja</string>
|
<string name="settings_about_version_text">Wersja</string>
|
||||||
|
@ -1368,7 +1368,7 @@
|
||||||
<string name="home_archive_close_no_target_title">Brak aktualnego profilu</string>
|
<string name="home_archive_close_no_target_title">Brak aktualnego profilu</string>
|
||||||
<string name="home_archive_close_no_target_text">Uczeń %s nie posiada profilu na tym koncie w aktualnym roku szkolnym. Prawdopodobnie ten profil został usunięty lub uczeń nie uczęszcza już do tej klasy.\n\nAby przejść do aktualnego profilu, wybierz ucznia z listy lub zaloguj się na jego konto przyciskiem Dodaj ucznia.</string>
|
<string name="home_archive_close_no_target_text">Uczeń %s nie posiada profilu na tym koncie w aktualnym roku szkolnym. Prawdopodobnie ten profil został usunięty lub uczeń nie uczęszcza już do tej klasy.\n\nAby przejść do aktualnego profilu, wybierz ucznia z listy lub zaloguj się na jego konto przyciskiem Dodaj ucznia.</string>
|
||||||
<string name="login_copyright_notice">Znaki towarowe zamieszczone w tej aplikacji należą do ich prawowitych właścicieli i są używane wyłącznie w celach informacyjnych.</string>
|
<string name="login_copyright_notice">Znaki towarowe zamieszczone w tej aplikacji należą do ich prawowitych właścicieli i są używane wyłącznie w celach informacyjnych.</string>
|
||||||
<string name="update_available_title">Dostępna aktualizacja aplikacji</string>
|
<string name="update_available_title">Dostępna aktualiacja aplikacji</string>
|
||||||
<string name="update_available_format">Używasz starej wersji aplikacji Szkolny.eu (%s). Aby móc korzystać z aplikacji oraz zapewnić najlepsze działanie, zaktualizuj aplikację do wersji %s.\n\nDziennik zmian:\n%s</string>
|
<string name="update_available_format">Używasz starej wersji aplikacji Szkolny.eu (%s). Aby móc korzystać z aplikacji oraz zapewnić najlepsze działanie, zaktualizuj aplikację do wersji %s.\n\nDziennik zmian:\n%s</string>
|
||||||
<string name="update_available_fallback">Posiadasz nieaktualną wersję aplikacji Szkolny.eu. Aby móc dalej synchronizować dane, musisz zaktualizować aplikację.</string>
|
<string name="update_available_fallback">Posiadasz nieaktualną wersję aplikacji Szkolny.eu. Aby móc dalej synchronizować dane, musisz zaktualizować aplikację.</string>
|
||||||
<string name="update_available_button">Aktualizuj</string>
|
<string name="update_available_button">Aktualizuj</string>
|
||||||
|
@ -1378,12 +1378,4 @@
|
||||||
<string name="home_availability_info">Zobacz więcej</string>
|
<string name="home_availability_info">Zobacz więcej</string>
|
||||||
<string name="home_availability_update">Aktualizuj</string>
|
<string name="home_availability_update">Aktualizuj</string>
|
||||||
<string name="register_unavailable_read_more">Dowiedz się więcej</string>
|
<string name="register_unavailable_read_more">Dowiedz się więcej</string>
|
||||||
<string name="settings_register_hide_sticks_from_old">Stara nie zobaczy pał</string>
|
|
||||||
<string name="login_podlasie_logout_devices">Wyloguj z pozostałych urządzeń</string>
|
|
||||||
<string name="login_chooser_testing_title">Wersja testowa</string>
|
|
||||||
<string name="login_chooser_testing_text">Wybrany sposób logowania jest jeszcze w fazie testów i może nie działać poprawnie.\n\nJeśli masz problemy z aplikacją, wybierz zalecany sposób logowania.</string>
|
|
||||||
<string name="login_chooser_mode_recommended">{cmd-information-outline} Zalecane</string>
|
|
||||||
<string name="login_chooser_mode_testing">{cmd-alert-circle-outline} Wersja testowa</string>
|
|
||||||
<string name="login_chooser_mode_dev_only">{cmd-android-studio} Wersja deweloperska</string>
|
|
||||||
<string name="eggs">\???</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
42
build.gradle
|
@ -2,43 +2,43 @@
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
kotlin_version = '1.4.30'
|
kotlin_version = '1.3.61'
|
||||||
|
|
||||||
release = [
|
release = [
|
||||||
versionName: "4.5-beta.2",
|
versionName: "4.4.1",
|
||||||
versionCode: 4050002
|
versionCode: 4040199
|
||||||
]
|
]
|
||||||
|
|
||||||
setup = [
|
setup = [
|
||||||
compileSdk: 30,
|
compileSdk: 28,
|
||||||
buildTools: "28.0.3",
|
buildTools: "28.0.3",
|
||||||
minSdk : 16,
|
minSdk : 16,
|
||||||
targetSdk : 30
|
targetSdk : 28
|
||||||
]
|
]
|
||||||
|
|
||||||
versions = [
|
versions = [
|
||||||
gradleAndroid : '4.2.0-beta04',
|
gradleAndroid : '4.1.0-rc01',
|
||||||
|
|
||||||
kotlin : ext.kotlin_version,
|
kotlin : ext.kotlin_version,
|
||||||
ktx : "1.3.2",
|
ktx : "1.2.0",
|
||||||
|
|
||||||
androidX : '1.0.0',
|
androidX : '1.0.0',
|
||||||
annotation : '1.1.0',
|
annotation : '1.1.0',
|
||||||
recyclerView : '1.2.0-beta01',
|
recyclerView : '1.2.0-alpha01',
|
||||||
material : '1.3.0',
|
material : '1.2.0-alpha05',
|
||||||
appcompat : '1.3.0-beta01',
|
appcompat : '1.2.0-alpha02',
|
||||||
constraintLayout : '2.1.0-alpha2',
|
constraintLayout : '2.0.0-beta4',
|
||||||
cardview : '1.0.0',
|
cardview : '1.0.0',
|
||||||
gridLayout : '1.0.0',
|
gridLayout : '1.0.0',
|
||||||
navigation : "2.0.0",
|
navigation : "2.0.0",
|
||||||
navigationFragment: "1.0.0",
|
navigationFragment: "1.0.0",
|
||||||
legacy : "1.0.0",
|
legacy : "1.0.0",
|
||||||
|
|
||||||
room : "2.2.6",
|
room : "2.2.5",
|
||||||
lifecycle : "2.3.0",
|
lifecycle : "2.2.0",
|
||||||
work : "2.5.0",
|
work : "2.3.4",
|
||||||
|
|
||||||
firebase : '18.0.2',
|
firebase : '17.2.2',
|
||||||
firebasemessaging: "20.1.3",
|
firebasemessaging: "20.1.3",
|
||||||
play_services : "17.0.0",
|
play_services : "17.0.0",
|
||||||
|
|
||||||
|
@ -53,11 +53,12 @@ buildscript {
|
||||||
|
|
||||||
retrofit : "2.6.4"
|
retrofit : "2.6.4"
|
||||||
]
|
]
|
||||||
versions.kotlin = '1.4.0'
|
|
||||||
versions.kotlin = '1.4.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://maven.fabric.io/public'
|
||||||
|
}
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
@ -65,8 +66,11 @@ buildscript {
|
||||||
classpath "com.android.tools.build:gradle:${versions.gradleAndroid}"
|
classpath "com.android.tools.build:gradle:${versions.gradleAndroid}"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||||
classpath 'me.tatarka:gradle-retrolambda:3.7.0'
|
classpath 'me.tatarka:gradle-retrolambda:3.7.0'
|
||||||
classpath 'com.google.gms:google-services:4.3.5'
|
classpath 'com.google.gms:google-services:4.3.3'
|
||||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.0'
|
classpath 'io.fabric.tools:gradle:1.28.1'
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
org.gradle.jvmargs=-Xmx1536m
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
|
android.enableR8=true
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
|
6
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
#Wed Feb 17 14:04:38 CET 2021
|
#Mon Aug 24 17:15:24 CEST 2020
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
include ':wear'
|
|
||||||
include ':wear'
|
|
||||||
include ':codegen'
|
include ':codegen'
|
||||||
include ':annotation'
|
include ':annotation'
|
||||||
rootProject.name='Szkolny.eu'
|
rootProject.name='Szkolny.eu'
|
||||||
|
|
1
wear/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/build
|
|
|
@ -1,53 +1,37 @@
|
||||||
/*
|
apply plugin: 'com.android.application'
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id 'com.android.application'
|
|
||||||
id 'kotlin-android'
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 28
|
||||||
buildToolsVersion "29.0.3"
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "pl.szczodrzynski.edziennik"
|
applicationId "pl.szczodrzynski.edziennik"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 29
|
targetSdkVersion 28
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility = '1.8'
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility = '1.8'
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '1.8'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}"
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation 'androidx.core:core-ktx:1.3.1'
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
|
||||||
testImplementation 'junit:junit:4.13'
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
|
||||||
|
|
||||||
implementation 'androidx.wear:wear:1.0.0'
|
implementation 'com.google.android.support:wearable:2.4.0'
|
||||||
implementation 'com.google.android.support:wearable:2.7.0'
|
implementation 'com.google.android.gms:play-services-wearable:16.0.1'
|
||||||
compileOnly 'com.google.android.wearable:wearable:2.7.0'
|
implementation 'androidx.percentlayout:percentlayout:1.0.0-beta01'
|
||||||
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01'
|
||||||
implementation "com.google.android.gms:play-services-wearable:${versions.play_services}"
|
implementation 'androidx.recyclerview:recyclerview:1.0.0-beta01'
|
||||||
|
implementation 'androidx.wear:wear:1.0.0-beta01'
|
||||||
|
compileOnly 'com.google.android.wearable:wearable:2.4.0'
|
||||||
}
|
}
|
||||||
|
|
21
wear/proguard-rules.pro
vendored
|
@ -1,21 +0,0 @@
|
||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik
|
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("pl.szczodrzynski.edziennik", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +1,44 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
-->
|
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="pl.szczodrzynski.edziennik">
|
package="pl.szczodrzynski.edziennik">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.type.watch" />
|
<uses-feature android:name="android.hardware.type.watch" />
|
||||||
|
|
||||||
|
<!-- Required to act as a custom watch face. -->
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required for complications to receive complication data and open the provider chooser. -->
|
||||||
|
<uses-permission android:name="com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Szkolnyeu">
|
android:theme="@android:style/Theme.DeviceDefault">
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.wearable.standalone"
|
||||||
|
android:value="false" />
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.version"
|
||||||
|
android:value="@integer/google_play_services_version" />
|
||||||
|
|
||||||
<uses-library
|
<uses-library
|
||||||
android:name="com.google.android.wearable"
|
android:name="com.google.android.wearable"
|
||||||
android:required="true" />
|
android:required="true" />
|
||||||
|
|
||||||
<!--
|
|
||||||
Set to true if your app is Standalone, that is, it does not require the handheld
|
|
||||||
app to run.
|
|
||||||
-->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.android.wearable.standalone"
|
|
||||||
android:value="true" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppThemeDark">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name="android.support.wearable.activity.ConfirmationActivity">
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
153
wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.java
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
package pl.szczodrzynski.edziennik;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import androidx.wear.widget.drawer.WearableDrawerLayout;
|
||||||
|
import androidx.wear.widget.drawer.WearableDrawerView;
|
||||||
|
import androidx.wear.widget.drawer.WearableNavigationDrawerView;
|
||||||
|
import android.support.wearable.activity.WearableActivity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.android.gms.wearable.CapabilityClient;
|
||||||
|
import com.google.android.gms.wearable.CapabilityInfo;
|
||||||
|
import com.google.android.gms.wearable.DataEvent;
|
||||||
|
import com.google.android.gms.wearable.DataItem;
|
||||||
|
import com.google.android.gms.wearable.Node;
|
||||||
|
import com.google.android.gms.wearable.PutDataMapRequest;
|
||||||
|
import com.google.android.gms.wearable.PutDataRequest;
|
||||||
|
import com.google.android.gms.wearable.Wearable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class MainActivity extends WearableActivity {
|
||||||
|
|
||||||
|
private static final String TAG = "MainActivity";
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
private WearableDrawerLayout wearableDrawerLayout;
|
||||||
|
private WearableNavigationDrawerView mWearableNavigationDrawer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
// Enables Always-on
|
||||||
|
setAmbientEnabled();
|
||||||
|
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
|
||||||
|
wearableDrawerLayout = findViewById(R.id.drawer_layout);
|
||||||
|
wearableDrawerLayout.setDrawerStateCallback(new WearableDrawerLayout.DrawerStateCallback() {
|
||||||
|
@Override
|
||||||
|
public void onDrawerOpened(WearableDrawerLayout layout, WearableDrawerView drawerView) {
|
||||||
|
super.onDrawerOpened(layout, drawerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawerClosed(WearableDrawerLayout layout, WearableDrawerView drawerView) {
|
||||||
|
super.onDrawerClosed(layout, drawerView);
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mWearableNavigationDrawer = (WearableNavigationDrawerView) findViewById(R.id.top_navigation_drawer);
|
||||||
|
WearableNavigationDrawerView.WearableNavigationDrawerAdapter navigationDrawerAdapter = new NavigationDrawerAdapter(this);
|
||||||
|
mWearableNavigationDrawer.setAdapter(navigationDrawerAdapter);
|
||||||
|
mWearableNavigationDrawer.addOnItemSelectedListener(new WearableNavigationDrawerView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(int i) {
|
||||||
|
//Toast.makeText(MainActivity.this, "Selected item "+i, Toast.LENGTH_SHORT).show();
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Peeks navigation drawer on the top.
|
||||||
|
mWearableNavigationDrawer.getController().peekDrawer();
|
||||||
|
|
||||||
|
Wearable.getMessageClient(this).addListener(messageEvent -> {
|
||||||
|
Log.d(TAG, messageEvent.getPath()+" :: "+ Arrays.toString(messageEvent.getData()));
|
||||||
|
});
|
||||||
|
|
||||||
|
Task<CapabilityInfo> capabilityInfoTask =
|
||||||
|
Wearable.getCapabilityClient(this)
|
||||||
|
.getCapability("edziennik_phone_app", CapabilityClient.FILTER_REACHABLE);
|
||||||
|
capabilityInfoTask.addOnCompleteListener((task) -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
CapabilityInfo capabilityInfo = task.getResult();
|
||||||
|
assert capabilityInfo != null;
|
||||||
|
Set<Node> nodes;
|
||||||
|
nodes = capabilityInfo.getNodes();
|
||||||
|
Log.d(TAG, "Nodes "+nodes);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Capability request failed to return any results.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Wearable.getDataClient(this).addListener(dataEventBuffer -> {
|
||||||
|
Log.d(TAG, "onDataChanged(): " + dataEventBuffer);
|
||||||
|
|
||||||
|
for (DataEvent event : dataEventBuffer) {
|
||||||
|
if (event.getType() == DataEvent.TYPE_CHANGED) {
|
||||||
|
String path = event.getDataItem().getUri().getPath();
|
||||||
|
Log.d(TAG, "Data "+path+ " :: "+Arrays.toString(event.getDataItem().getData()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.test).setOnClickListener((v -> {
|
||||||
|
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/ping");
|
||||||
|
putDataMapRequest.getDataMap().putLong("millis", System.currentTimeMillis());
|
||||||
|
|
||||||
|
PutDataRequest request = putDataMapRequest.asPutDataRequest();
|
||||||
|
request.setData("Hello".getBytes());
|
||||||
|
request.setUrgent();
|
||||||
|
|
||||||
|
Log.d(TAG, "Generating DataItem: " + request);
|
||||||
|
|
||||||
|
Task<DataItem> dataItemTask =
|
||||||
|
Wearable.getDataClient(getApplicationContext()).putDataItem(request);
|
||||||
|
dataItemTask.addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
|
||||||
|
Log.d(TAG, "success");
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Capability request failed to return any results.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Block on a task and get the result synchronously (because this is on a background
|
||||||
|
// thread).
|
||||||
|
//DataItem dataItem = dataItemTask.getResult();
|
||||||
|
|
||||||
|
//Log.d(TAG, "DataItem saved: " + dataItem);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class NavigationDrawerAdapter extends WearableNavigationDrawerView.WearableNavigationDrawerAdapter {
|
||||||
|
public NavigationDrawerAdapter(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getItemText(int i) {
|
||||||
|
return "Item "+i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Drawable getItemDrawable(int i) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.support.wearable.activity.WearableActivity
|
|
||||||
import com.google.android.gms.wearable.*
|
|
||||||
|
|
||||||
class MainActivity : WearableActivity(), DataClient.OnDataChangedListener {
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
|
|
||||||
// Enables Always-on
|
|
||||||
setAmbientEnabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDataChanged(dataEvents: DataEventBuffer) {
|
|
||||||
dataEvents.forEach { event ->
|
|
||||||
if (event.type == DataEvent.TYPE_CHANGED) {
|
|
||||||
event.dataItem.also { item ->
|
|
||||||
if (item?.uri?.path?.compareTo("/test") == 0) {
|
|
||||||
DataMapItem.fromDataItem(item).dataMap.apply {
|
|
||||||
getInt("test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (event.type == DataEvent.TYPE_DELETED) {
|
|
||||||
// DataItem deleted
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
Wearable.getDataClient(this).addListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
Wearable.getDataClient(this).removeListener(this)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
-->
|
|
||||||
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="85.84757"
|
|
||||||
android:endY="92.4963"
|
|
||||||
android:startX="42.9492"
|
|
||||||
android:startY="49.59793"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
|
|
@ -1,174 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
-->
|
|
||||||
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M9,0L9,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,0L19,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,0L29,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
|
|
@ -1,29 +1,47 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
<androidx.wear.widget.drawer.WearableDrawerLayout
|
||||||
-->
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
|
||||||
<androidx.wear.widget.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
android:id="@+id/drawer_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:background="@color/white"
|
|
||||||
android:padding="@dimen/box_inset_layout_padding"
|
|
||||||
tools:context=".MainActivity"
|
|
||||||
tools:deviceIds="wear">
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:padding="@dimen/inner_frame_layout_padding"
|
|
||||||
app:boxedEdges="all"
|
|
||||||
tools:ignore="MissingPrefix">
|
|
||||||
|
|
||||||
<TextView
|
<ScrollView
|
||||||
android:id="@+id/text"
|
android:id="@+id/content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:nestedScrollingEnabled="true">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/test"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/hello_world" />
|
android:text="Send"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</androidx.wear.widget.BoxInsetLayout>
|
|
||||||
|
<androidx.wear.widget.drawer.WearableNavigationDrawerView
|
||||||
|
android:id="@+id/top_navigation_drawer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
app:navigationStyle="multiPage"/>
|
||||||
|
</androidx.wear.widget.drawer.WearableDrawerLayout>
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
-->
|
|
||||||
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kacper Ziubryniewicz 2020-9-17
|
|
||||||
-->
|
|
||||||
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 7.3 KiB |