Compare commits

...

11 Commits

35 changed files with 383 additions and 240 deletions

View File

@ -128,6 +128,7 @@ dependencies {
implementation "com.mikepenz:iconics-core:${versions.iconics}" implementation "com.mikepenz:iconics-core:${versions.iconics}"
implementation "com.mikepenz:iconics-views:${versions.iconics}" implementation "com.mikepenz:iconics-views:${versions.iconics}"
implementation "com.mikepenz:community-material-typeface:${versions.font_cmd}@aar" implementation "com.mikepenz:community-material-typeface:${versions.font_cmd}@aar"
implementation "com.mikepenz:materialize:1.2.1"
implementation "com.github.kuba2k2:NavLib:${versions.navlib}" implementation "com.github.kuba2k2:NavLib:${versions.navlib}"

View File

@ -31,6 +31,12 @@
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider -keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider -keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider
-keepnames class androidx.appcompat.view.menu.MenuBuilder { setHeaderTitleInt(java.lang.CharSequence); }
-keepclassmembernames class androidx.appcompat.view.menu.StandardMenuPopup { private *; }
-keepnames class androidx.appcompat.view.menu.MenuPopupHelper { showPopup(int, int, boolean, boolean); }
-keepclassmembernames class com.mikepenz.materialdrawer.widget.MiniDrawerSliderView { private *; }
-keep class .R -keep class .R
-keep class **.R$* { -keep class **.R$* {
<fields>; <fields>;

View File

@ -1,12 +1,13 @@
<h3>Wersja 4.0-beta.14, 2020-03-24</h3> <h3>Wersja 4.0-rc.1, 2020-03-26</h3>
<ul> <ul>
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkość oraz poprawność pobieranych danych.</li>
<li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli &#x1F44F;</li> <li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli &#x1F44F;</li>
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkość oraz poprawność pobieranych danych</li>
<li>Udoskonalony wygląd Szkolnego - sprawi, że korzystanie z aplikacji będzie jeszcze przyjemniejsze</li> <li>Udoskonalony wygląd Szkolnego - sprawi, że korzystanie z aplikacji będzie jeszcze przyjemniejsze</li>
<li>Nowa <b>Strona główna</b> - ładniejszy wygląd oraz możliwość przestawiania kart na każdym profilu</li> <li>Nowa <b>Strona główna</b> - ładniejszy wygląd oraz możliwość przestawiania kart na każdym profilu</li>
<li>Nowy <b>Plan lekcji</b> - z doskonałą obsługą lekcji przesuniętych oraz dwóch lekcji o tej samej godzinie</li> <li>Nowy <b>Plan lekcji</b> - z doskonałą obsługą lekcji przesuniętych oraz dwóch lekcji o tej samej godzinie</li>
<li>Nowe <b>Oceny</b> - z możliwością zmiany wartości plusów oraz minusów oraz wyłączenia niektórych ocen ze średniej</li> <li>Nowe <b>Oceny</b> - z możliwością zmiany wartości plusów oraz minusów oraz wyłączenia niektórych ocen ze średniej</li>
<li>Opcja wyłączenia wybranych powiadomień z aplikacji</li> <li>Opcja wyłączenia wybranych powiadomień z aplikacji</li>
<li>Znaczki nieprzeczytanych informacji na obrazkach profili.</li>
<br> <br>
<br> <br>
<li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li> <li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li>
@ -21,18 +22,8 @@
<li>Poprawiliśmy synchronizację w tle na niektórych telefonach</li> <li>Poprawiliśmy synchronizację w tle na niektórych telefonach</li>
<li>Usunąłem denerwujący brak zaznaczenia w lewym menu</li> <li>Usunąłem denerwujący brak zaznaczenia w lewym menu</li>
<li>Znaczna ilość błędów z poprzednich wersji już nie występuje</li> <li>Znaczna ilość błędów z poprzednich wersji już nie występuje</li>
<li><strike>Występują natomiast nowe błędy, dlatego proszę o ich zgłaszanie :)</strike></li>
</ul> </ul>
<br> <br>
<br> <br>
<br>
<b>Uwaga.</b> Ponieważ to wersja <i>beta</i>, niektóre funkcje mogą nie działać prawidłowo.<br>
Staramy się usuwać takie przypadki, jednak na chwilę obecną mogą występować błędy w:
<ul>
<li>Wysyłanie wiadomości może nie działać w pełni prawidłowo - proszę o zgłaszanie wszystkich błędów na naszym serwerze Discord</li>
</ul>
<br>
<br>
<br>
Dzięki za korzystanie ze Szkolnego!<br> Dzięki za korzystanie ze Szkolnego!<br>
<i>&copy; Kuba Szczodrzyński, Kacper Ziubryniewicz 2020</i> <i>&copy; Kuba Szczodrzyński, Kacper Ziubryniewicz 2020</i>

View File

@ -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] = {
0xc4, 0x97, 0xfb, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 0x53, 0xfb, 0x18, 0x06, 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);

View File

@ -28,9 +28,6 @@ import com.hypertrack.hyperlog.HyperLog
import com.mikepenz.iconics.Iconics import com.mikepenz.iconics.Iconics
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
import im.wangchao.mhttp.MHttp import im.wangchao.mhttp.MHttp
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar
import im.wangchao.mhttp.internal.cookie.cache.SetCookieCache
import im.wangchao.mhttp.internal.cookie.persistence.SharedPrefsCookiePersistor
import kotlinx.coroutines.* import kotlinx.coroutines.*
import me.leolin.shortcutbadger.ShortcutBadger import me.leolin.shortcutbadger.ShortcutBadger
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -41,6 +38,7 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.network.NetworkUtils import pl.szczodrzynski.edziennik.network.NetworkUtils
import pl.szczodrzynski.edziennik.network.cookie.DumbCookieJar
import pl.szczodrzynski.edziennik.sync.SyncWorker import pl.szczodrzynski.edziennik.sync.SyncWorker
import pl.szczodrzynski.edziennik.sync.UpdateWorker import pl.szczodrzynski.edziennik.sync.UpdateWorker
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity
@ -125,7 +123,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
.followSslRedirects(false) .followSslRedirects(false)
.build() .build()
} }
val cookieJar by lazy { PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(this)) } val cookieJar by lazy { DumbCookieJar(this) }
/* _____ _ _ /* _____ _ _
/ ____(_) | | / ____(_) | |

View File

@ -31,8 +31,8 @@ import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
import com.mikepenz.materialdrawer.model.DividerDrawerItem import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.ProfileDrawerItem import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem import com.mikepenz.materialdrawer.model.interfaces.*
import com.mikepenz.materialdrawer.model.interfaces.IProfile import com.mikepenz.materialdrawer.model.utils.withIsHiddenInMiniDrawer
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
@ -90,7 +90,6 @@ import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import pl.szczodrzynski.navlib.drawer.NavDrawer import pl.szczodrzynski.navlib.drawer.NavDrawer
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
import pl.szczodrzynski.navlib.drawer.items.withAppTitle
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
@ -361,7 +360,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
false false
} }
drawerProfileLongClickListener = { _, profile, _, view -> drawerProfileLongClickListener = { _, profile, _, view ->
if (profile is ProfileDrawerItem) { if (view != null && profile is ProfileDrawerItem) {
showProfileContextMenu(profile, view) showProfileContextMenu(profile, view)
true true
} }
@ -915,7 +914,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
bottomSheet.removeAllContextual() bottomSheet.removeAllContextual()
bottomSheet.toggleGroupEnabled = false bottomSheet.toggleGroupEnabled = false
drawer.close() drawer.close()
drawer.setSelection(target.id, fireOnClick = false) if (drawer.getSelection() != target.id)
drawer.setSelection(target.id, fireOnClick = false)
navView.toolbar.setTitle(target.title ?: target.name) navView.toolbar.setTitle(target.title ?: target.name)
navView.bottomBar.fabEnable = false navView.bottomBar.fabEnable = false
navView.bottomBar.fabExtended = false navView.bottomBar.fabExtended = false
@ -1063,7 +1063,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
val item = DrawerPrimaryItem() val item = DrawerPrimaryItem()
.withIdentifier(target.id.toLong()) .withIdentifier(target.id.toLong())
.withName(target.name) .withName(target.name)
.withHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id)) .withIsHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id))
.also { if (target.description != null) it.withDescription(target.description!!) } .also { if (target.description != null) it.withDescription(target.description!!) }
.also { if (target.icon != null) it.withIcon(target.icon!!) } .also { if (target.icon != null) it.withIcon(target.icon!!) }
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) } .also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
@ -1127,7 +1127,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
drawer.addProfileSettings(*drawerProfiles.toTypedArray()) drawer.addProfileSettings(*drawerProfiles.toTypedArray())
} }
private fun showProfileContextMenu(profile: IProfile<*>, view: View) { private fun showProfileContextMenu(profile: IProfile, view: View) {
val profileId = profile.identifier.toInt() val profileId = profile.identifier.toInt()
val popupMenu = PopupMenu(this, view) val popupMenu = PopupMenu(this, view)
popupMenu.menu.add(0, 1, 1, R.string.profile_menu_open_settings) popupMenu.menu.add(0, 1, 1, R.string.profile_menu_open_settings)
@ -1140,7 +1140,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
} }
loadTarget(DRAWER_ITEM_SETTINGS, null) loadTarget(DRAWER_ITEM_SETTINGS, null)
} else if (item.itemId == 2) { } else if (item.itemId == 2) {
ProfileRemoveDialog(this, profileId, profile.name?.getText(this)?.toString() ?: "?") ProfileRemoveDialog(this, profileId, profile.name?.getText(this) ?: "?")
} }
true true
} }

View File

@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
import im.wangchao.mhttp.Request import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
@ -43,8 +42,8 @@ open class EdudziennikWeb(open val data: DataEdudziennik, open val lastSync: Lon
if (semester == null && url.contains("start")) { if (semester == null && url.contains("start")) {
profile?.also { profile -> profile?.also { profile ->
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com") val cookies = data.app.cookieJar.getAll("dziennikel.appspot.com")
val semesterCookie = cookies.firstOrNull { it.name() == "semester" }?.value()?.toIntOrNull() val semesterCookie = cookies["semester"]?.toIntOrNull()
semesterCookie?.let { data.currentSemester = it } semesterCookie?.let { data.currentSemester = it }
@ -75,13 +74,7 @@ open class EdudziennikWeb(open val data: DataEdudziennik, open val lastSync: Lon
} }
} }
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("dziennikel.appspot.com", "sessionid", data.webSessionId)
Cookie.Builder()
.name("sessionid")
.value(data.webSessionId!!)
.domain("dziennikel.appspot.com")
.secure().httpOnly().build()
))
Request.builder() Request.builder()
.url(url) .url(url)

View File

@ -24,7 +24,7 @@ class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit)
onSuccess() onSuccess()
} }
else { else {
data.app.cookieJar.clearForDomain("dziennikel.appspot.com") data.app.cookieJar.clear("dziennikel.appspot.com")
if (data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) { if (data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
loginWithCredentials() loginWithCredentials()
} }
@ -59,8 +59,8 @@ class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit)
} }
} }
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com") val cookies = data.app.cookieJar.getAll("dziennikel.appspot.com")
val sessionId = cookies.firstOrNull { it.name() == "sessionid" }?.value() val sessionId = cookies["sessionid"]
if (sessionId == null) { if (sessionId == null) {
data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID) data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID)

View File

@ -5,7 +5,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik
import androidx.core.util.set import androidx.core.util.set
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_API import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_API
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_WEB import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_IDZIENNIK_WEB
@ -24,18 +23,8 @@ class DataIdziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(
loginMethods.clear() loginMethods.clear()
if (isWebLoginValid()) { if (isWebLoginValid()) {
loginMethods += LOGIN_METHOD_IDZIENNIK_WEB loginMethods += LOGIN_METHOD_IDZIENNIK_WEB
app.cookieJar.saveFromResponse(null, listOf( app.cookieJar.set("iuczniowie.progman.pl", "ASP.NET_SessionId_iDziennik", webSessionId)
Cookie.Builder() app.cookieJar.set("iuczniowie.progman.pl", ".ASPXAUTH", webAuth)
.name("ASP.NET_SessionId_iDziennik")
.value(webSessionId!!)
.domain("iuczniowie.progman.pl")
.secure().httpOnly().build(),
Cookie.Builder()
.name(".ASPXAUTH")
.value(webAuth!!)
.domain("iuczniowie.progman.pl")
.secure().httpOnly().build()
))
} }
if (isApiLoginValid()) if (isApiLoginValid())
loginMethods += LOGIN_METHOD_IDZIENNIK_API loginMethods += LOGIN_METHOD_IDZIENNIK_API

View File

@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login
import im.wangchao.mhttp.Request import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
@ -24,22 +23,12 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
init { run { init { run {
if (data.isWebLoginValid()) { if (data.isWebLoginValid()) {
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("iuczniowie.progman.pl", "ASP.NET_SessionId_iDziennik", data.webSessionId)
Cookie.Builder() data.app.cookieJar.set("iuczniowie.progman.pl", ".ASPXAUTH", data.webAuth)
.name("ASP.NET_SessionId_iDziennik")
.value(data.webSessionId!!)
.domain("iuczniowie.progman.pl")
.secure().httpOnly().build(),
Cookie.Builder()
.name(".ASPXAUTH")
.value(data.webAuth!!)
.domain("iuczniowie.progman.pl")
.secure().httpOnly().build()
))
onSuccess() onSuccess()
} }
else { else {
data.app.cookieJar.clearForDomain("iuczniowie.progman.pl") data.app.cookieJar.clear("iuczniowie.progman.pl")
if (data.webSchoolName != null && data.webUsername != null && data.webPassword != null) { if (data.webSchoolName != null && data.webUsername != null && data.webPassword != null) {
loginWithCredentials() loginWithCredentials()
} }
@ -62,11 +51,11 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
// login succeeded: there is a start page // login succeeded: there is a start page
if (text.contains("czyWyswietlicDostepMobilny")) { if (text.contains("czyWyswietlicDostepMobilny")) {
val cookies = data.app.cookieJar.getForDomain("iuczniowie.progman.pl") val cookies = data.app.cookieJar.getAll("iuczniowie.progman.pl")
run { run {
data.webSessionId = cookies.singleOrNull { it.name() == "ASP.NET_SessionId_iDziennik" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION data.webSessionId = cookies["ASP.NET_SessionId_iDziennik"] ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION
data.webAuth = cookies.singleOrNull { it.name() == ".ASPXAUTH" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH data.webAuth = cookies[".ASPXAUTH"] ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH
data.apiBearer = cookies.singleOrNull { it.name() == "Bearer" }?.value() ?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER data.apiBearer = cookies["Bearer"]?: return@run ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER
data.loginExpiryTime = response.getUnixDate() + 30 * MINUTE /* after about 40 minutes the login didn't work already */ data.loginExpiryTime = response.getUnixDate() + 30 * MINUTE /* after about 40 minutes the login didn't work already */
data.apiExpiryTime = response.getUnixDate() + 12 * HOUR /* actually it expires after 24 hours but I'm not sure when does the token refresh. */ data.apiExpiryTime = response.getUnixDate() + 12 * HOUR /* actually it expires after 24 hours but I'm not sure when does the token refresh. */

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus package pl.szczodrzynski.edziennik.data.api.edziennik.librus
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
@ -31,23 +30,11 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
loginMethods += LOGIN_METHOD_LIBRUS_API loginMethods += LOGIN_METHOD_LIBRUS_API
if (isSynergiaLoginValid()) { if (isSynergiaLoginValid()) {
loginMethods += LOGIN_METHOD_LIBRUS_SYNERGIA loginMethods += LOGIN_METHOD_LIBRUS_SYNERGIA
app.cookieJar.saveFromResponse(null, listOf( app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", synergiaSessionId)
Cookie.Builder()
.name("DZIENNIKSID")
.value(synergiaSessionId!!)
.domain("synergia.librus.pl")
.secure().httpOnly().build()
))
} }
if (isMessagesLoginValid()) { if (isMessagesLoginValid()) {
loginMethods += LOGIN_METHOD_LIBRUS_MESSAGES loginMethods += LOGIN_METHOD_LIBRUS_MESSAGES
app.cookieJar.saveFromResponse(null, listOf( app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", messagesSessionId)
Cookie.Builder()
.name("DZIENNIKSID")
.value(messagesSessionId!!)
.domain("wiadomosci.librus.pl")
.secure().httpOnly().build()
))
} }
} }

View File

@ -64,7 +64,7 @@ val LibrusFeatures = listOf(
Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf( Feature(LOGIN_TYPE_LIBRUS, FEATURE_PUSH_CONFIG, listOf(
ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_PUSH_CONFIG to LOGIN_METHOD_LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data -> ), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
!data.app.config.sync.tokenLibrusList.contains(data.profileId) (data as DataLibrus).isPremium && !data.app.config.sync.tokenLibrusList.contains(data.profileId)
}, },
@ -116,11 +116,11 @@ val LibrusFeatures = listOf(
* Homework - using API. * Homework - using API.
* Sync only if account has premium access. * Sync only if account has premium access.
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf( /*Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
ENDPOINT_LIBRUS_API_HOMEWORK to LOGIN_METHOD_LIBRUS_API ENDPOINT_LIBRUS_API_HOMEWORK to LOGIN_METHOD_LIBRUS_API
), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data -> ), listOf(LOGIN_METHOD_LIBRUS_API)).withShouldSync { data ->
(data as DataLibrus).isPremium (data as DataLibrus).isPremium
}, },*/
/** /**
* Behaviour - using API. * Behaviour - using API.
*/ */
@ -227,9 +227,9 @@ val LibrusFeatures = listOf(
*/ */
Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf( Feature(LOGIN_TYPE_LIBRUS, FEATURE_HOMEWORK, listOf(
ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LOGIN_METHOD_LIBRUS_SYNERGIA ENDPOINT_LIBRUS_SYNERGIA_HOMEWORK to LOGIN_METHOD_LIBRUS_SYNERGIA
), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA)).withShouldSync { data -> ), listOf(LOGIN_METHOD_LIBRUS_SYNERGIA))/*.withShouldSync { data ->
!(data as DataLibrus).isPremium !(data as DataLibrus).isPremium
}, }*/,
/** /**
* Messages inbox - using messages website. * Messages inbox - using messages website.

View File

@ -12,7 +12,6 @@ import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.FileCallbackHandler import im.wangchao.mhttp.callback.FileCallbackHandler
import im.wangchao.mhttp.callback.JsonCallbackHandler import im.wangchao.mhttp.callback.JsonCallbackHandler
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import okhttp3.Cookie
import org.json.JSONObject import org.json.JSONObject
import org.json.XML import org.json.XML
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -89,14 +88,7 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
} }
} }
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
Cookie.Builder()
.name("DZIENNIKSID")
.value(data.messagesSessionId!!)
.domain("wiadomosci.librus.pl")
.secure().httpOnly().build()
))
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder() val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
val doc = docBuilder.newDocument() val doc = docBuilder.newDocument()
@ -180,14 +172,7 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
} }
} }
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
Cookie.Builder()
.name("DZIENNIKSID")
.value(data.messagesSessionId!!)
.domain("wiadomosci.librus.pl")
.secure().httpOnly().build()
))
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder() val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
val doc = docBuilder.newDocument() val doc = docBuilder.newDocument()

View File

@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiAttendances(override val data: DataLibrus, class LibrusApiAttendances(override val data: DataLibrus,
override val lastSync: Long?, override val lastSync: Long?,
@ -45,7 +46,7 @@ class LibrusApiAttendances(override val data: DataLibrus,
val typeObject = data.attendanceTypes[type] ?: null val typeObject = data.attendanceTypes[type] ?: null
val topic = typeObject?.name ?: "" val topic = typeObject?.name ?: ""
val startTime = data.lessonRanges.get(lessonNo).startTime val startTime = data.lessonRanges.get(lessonNo)?.startTime
val lesson = if (lessonId != -1L) val lesson = if (lessonId != -1L)
data.librusLessons.singleOrNull { it.lessonId == lessonId } data.librusLessons.singleOrNull { it.lessonId == lessonId }
@ -59,7 +60,7 @@ class LibrusApiAttendances(override val data: DataLibrus,
semester, semester,
topic, topic,
lessonDate, lessonDate,
startTime, startTime ?: Time(0, 0, 0),
typeObject?.type ?: Attendance.TYPE_CUSTOM typeObject?.type ?: Attendance.TYPE_CUSTOM
) )

View File

@ -4,15 +4,12 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
import pl.szczodrzynski.edziennik.DAY import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LUCKY_NUMBER import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_LUCKY_NUMBER
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.getInt
import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
@ -41,9 +38,10 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
luckyNumber luckyNumber
) )
//if (luckyNumberDate > Date.getToday()) { if (luckyNumberDate >= Date.getToday())
nextSync = luckyNumberDate.combineWith(Time(15, 0, 0)) nextSync = luckyNumberDate.combineWith(Time(15, 0, 0))
//} else
nextSync = System.currentTimeMillis() + 6*HOUR*1000
data.luckyNumberList.add(luckyNumberObject) data.luckyNumberList.add(luckyNumberObject)
data.metadataList.add( data.metadataList.add(

View File

@ -21,6 +21,14 @@ class LibrusApiPushConfig(override val data: DataLibrus,
} }
init { data.app.config.sync.tokenLibrus?.also { tokenLibrus -> init { data.app.config.sync.tokenLibrus?.also { tokenLibrus ->
if(tokenLibrus.isEmpty()) {
data.setSyncNext(ENDPOINT_LIBRUS_API_PUSH_CONFIG, SYNC_ALWAYS)
data.app.config.sync.tokenLibrusList =
data.app.config.sync.tokenLibrusList + profileId
onSuccess(ENDPOINT_LIBRUS_API_PUSH_CONFIG)
return@also
}
apiGet(TAG, "ChangeRegister", payload = JsonObject( apiGet(TAG, "ChangeRegister", payload = JsonObject(
"provider" to "FCM", "provider" to "FCM",
"device" to tokenLibrus, "device" to tokenLibrus,

View File

@ -8,7 +8,6 @@ import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.body.MediaTypeUtils import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
@ -64,21 +63,15 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
if (data.isMessagesLoginValid()) { if (data.isMessagesLoginValid()) {
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("wiadomosci.librus.pl", "DZIENNIKSID", data.messagesSessionId)
Cookie.Builder()
.name("DZIENNIKSID")
.value(data.messagesSessionId!!)
.domain("wiadomosci.librus.pl")
.secure().httpOnly().build()
))
onSuccess() onSuccess()
} }
else { else {
data.app.cookieJar.clearForDomain("wiadomosci.librus.pl") data.app.cookieJar.clear("wiadomosci.librus.pl")
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) { if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) {
loginWithSynergia() loginWithSynergia()
} }
else if (data.apiLogin != null && data.apiPassword != null) { else if (data.apiLogin != null && data.apiPassword != null && false) {
loginWithCredentials() loginWithCredentials()
} }
else { else {
@ -148,7 +141,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
private fun saveSessionId(response: Response?, text: String?) { private fun saveSessionId(response: Response?, text: String?) {
var sessionId = data.app.cookieJar.getCookie("wiadomosci.librus.pl", "DZIENNIKSID") var sessionId = data.app.cookieJar.get("wiadomosci.librus.pl", "DZIENNIKSID")
sessionId = sessionId?.replace("-MAINT", "") // dunno what's this sessionId = sessionId?.replace("-MAINT", "") // dunno what's this
sessionId = sessionId?.replace("MAINT", "") // dunno what's this sessionId = sessionId?.replace("MAINT", "") // dunno what's this
if (sessionId == null) { if (sessionId == null) {

View File

@ -37,19 +37,19 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
} }
else if (data.portalRefreshToken != null) { else if (data.portalRefreshToken != null) {
if (data.fakeLogin) { if (data.fakeLogin) {
data.app.cookieJar.clearForDomain("librus.szkolny.eu") data.app.cookieJar.clear("librus.szkolny.eu")
} }
else { else {
data.app.cookieJar.clearForDomain("portal.librus.pl") data.app.cookieJar.clear("portal.librus.pl")
} }
accessToken(null, data.portalRefreshToken) accessToken(null, data.portalRefreshToken)
} }
else { else {
if (data.fakeLogin) { if (data.fakeLogin) {
data.app.cookieJar.clearForDomain("librus.szkolny.eu") data.app.cookieJar.clear("librus.szkolny.eu")
} }
else { else {
data.app.cookieJar.clearForDomain("portal.librus.pl") data.app.cookieJar.clear("portal.librus.pl")
} }
authorize(if (data.fakeLogin) FAKE_LIBRUS_AUTHORIZE else LIBRUS_AUTHORIZE_URL) authorize(if (data.fakeLogin) FAKE_LIBRUS_AUTHORIZE else LIBRUS_AUTHORIZE_URL)
} }

View File

@ -8,7 +8,6 @@ import com.google.gson.JsonObject
import im.wangchao.mhttp.Request import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
@ -30,17 +29,11 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
} }
if (data.isSynergiaLoginValid()) { if (data.isSynergiaLoginValid()) {
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("synergia.librus.pl", "DZIENNIKSID", data.synergiaSessionId)
Cookie.Builder()
.name("DZIENNIKSID")
.value(data.synergiaSessionId!!)
.domain("synergia.librus.pl")
.secure().httpOnly().build()
))
onSuccess() onSuccess()
} }
else { else {
data.app.cookieJar.clearForDomain("synergia.librus.pl") data.app.cookieJar.clear("synergia.librus.pl")
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_API)) { if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_API)) {
loginWithApi() loginWithApi()
} }
@ -92,7 +85,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
} }
if (location?.endsWith("centrum_powiadomien") == true) { if (location?.endsWith("centrum_powiadomien") == true) {
val sessionId = data.app.cookieJar.getCookie("synergia.librus.pl", "DZIENNIKSID") val sessionId = data.app.cookieJar.get("synergia.librus.pl", "DZIENNIKSID")
if (sessionId == null) { if (sessionId == null) {
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID) data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID)
.withResponse(response) .withResponse(response)
@ -117,7 +110,7 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
} }
} }
data.app.cookieJar.clearForDomain("synergia.librus.pl") data.app.cookieJar.clear("synergia.librus.pl")
Request.builder() Request.builder()
.url(LIBRUS_SYNERGIA_TOKEN_LOGIN_URL.replace("TOKEN", token) + "/uczen/widok/centrum_powiadomien") .url(LIBRUS_SYNERGIA_TOKEN_LOGIN_URL.replace("TOKEN", token) + "/uczen/widok/centrum_powiadomien")
.userAgent(LIBRUS_USER_AGENT) .userAgent(LIBRUS_USER_AGENT)

View File

@ -8,7 +8,6 @@ import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.FileCallbackHandler import im.wangchao.mhttp.callback.FileCallbackHandler
import im.wangchao.mhttp.callback.TextCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
@ -105,18 +104,8 @@ open class MobidziennikWeb(open val data: DataMobidziennik, open val lastSync: L
} }
} }
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", data.webSessionKey, data.webSessionValue)
Cookie.Builder() data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", "SERVERID", data.webServerId)
.name(data.webSessionKey!!)
.value(data.webSessionValue!!)
.domain("${data.loginServerName}.mobidziennik.pl")
.secure().httpOnly().build(),
Cookie.Builder()
.name("SERVERID")
.value(data.webServerId!!)
.domain("${data.loginServerName}.mobidziennik.pl")
.secure().httpOnly().build()
))
Request.builder() Request.builder()
.url(url) .url(url)
@ -187,18 +176,8 @@ open class MobidziennikWeb(open val data: DataMobidziennik, open val lastSync: L
} }
} }
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", data.webSessionKey, data.webSessionValue)
Cookie.Builder() data.app.cookieJar.set("${data.loginServerName}.mobidziennik.pl", "SERVERID", data.webServerId)
.name(data.webSessionKey!!)
.value(data.webSessionValue!!)
.domain("${data.loginServerName}.mobidziennik.pl")
.secure().httpOnly().build(),
Cookie.Builder()
.name("SERVERID")
.value(data.webServerId!!)
.domain("${data.loginServerName}.mobidziennik.pl")
.secure().httpOnly().build()
))
Request.builder() Request.builder()
.url(url) .url(url)

View File

@ -26,7 +26,7 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
} }
else { else {
if (data.loginServerName.isNotNullNorEmpty() && data.loginUsername.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) { if (data.loginServerName.isNotNullNorEmpty() && data.loginUsername.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
data.app.cookieJar.clearForDomain(data.loginServerName + ".mobidziennik.pl") data.app.cookieJar.clear("${data.loginServerName}.mobidziennik.pl")
loginWithCredentials() loginWithCredentials()
} }
else { else {
@ -58,10 +58,10 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
} }
} }
val cookies = data.app.cookieJar.getForDomain("${data.loginServerName}.mobidziennik.pl") val cookies = data.app.cookieJar.getAll("${data.loginServerName}.mobidziennik.pl")
val cookie = cookies.singleOrNull { it.name().length > 32 } val cookie = cookies.entries.firstOrNull { it.key.length > 32 }
val sessionKey = cookie?.name() val sessionKey = cookie?.key
val sessionId = cookie?.value() val sessionId = cookie?.value
if (sessionId == null) { if (sessionId == null) {
data.error(ApiError(TAG, ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID) data.error(ApiError(TAG, ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID)
.withResponse(response) .withResponse(response)
@ -71,7 +71,7 @@ class MobidziennikLoginWeb(val data: DataMobidziennik, val onSuccess: () -> Unit
data.webSessionKey = sessionKey data.webSessionKey = sessionKey
data.webSessionValue = sessionId data.webSessionValue = sessionId
data.webServerId = data.app.cookieJar.getCookie("${data.loginServerName}.mobidziennik.pl", "SERVERID") data.webServerId = data.app.cookieJar.get("${data.loginServerName}.mobidziennik.pl", "SERVERID")
data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */ data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */
onSuccess() onSuccess()
} }

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.template package pl.szczodrzynski.edziennik.data.api.edziennik.template
import okhttp3.Cookie
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_TEMPLATE_API import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_TEMPLATE_API
@ -28,13 +27,7 @@ class DataTemplate(app: App, profile: Profile?, loginStore: LoginStore) : Data(a
loginMethods.clear() loginMethods.clear()
if (isWebLoginValid()) { if (isWebLoginValid()) {
loginMethods += LOGIN_METHOD_TEMPLATE_WEB loginMethods += LOGIN_METHOD_TEMPLATE_WEB
app.cookieJar.saveFromResponse(null, listOf( app.cookieJar.set("eregister.example.com", "AuthCookie", webCookie)
Cookie.Builder()
.name("AuthCookie")
.value(webCookie!!)
.domain("eregister.example.com")
.secure().httpOnly().build()
))
} }
if (isApiLoginValid()) if (isApiLoginValid())
loginMethods += LOGIN_METHOD_TEMPLATE_API loginMethods += LOGIN_METHOD_TEMPLATE_API

View File

@ -4,12 +4,11 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.template.login package pl.szczodrzynski.edziennik.data.api.edziennik.template.login
import okhttp3.Cookie import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_DATA_MISSING import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_DATA_MISSING
import pl.szczodrzynski.edziennik.data.api.ERROR_PROFILE_MISSING import pl.szczodrzynski.edziennik.data.api.ERROR_PROFILE_MISSING
import pl.szczodrzynski.edziennik.data.api.edziennik.template.DataTemplate import pl.szczodrzynski.edziennik.data.api.edziennik.template.DataTemplate
import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.currentTimeUnix
class TemplateLoginWeb(val data: DataTemplate, val onSuccess: () -> Unit) { class TemplateLoginWeb(val data: DataTemplate, val onSuccess: () -> Unit) {
companion object { companion object {
@ -23,17 +22,11 @@ class TemplateLoginWeb(val data: DataTemplate, val onSuccess: () -> Unit) {
} }
if (data.isWebLoginValid()) { if (data.isWebLoginValid()) {
data.app.cookieJar.saveFromResponse(null, listOf( data.app.cookieJar.set("eregister.example.com", "AuthCookie", data.webCookie)
Cookie.Builder()
.name("AuthCookie")
.value(data.webCookie!!)
.domain("eregister.example.com")
.secure().httpOnly().build()
))
onSuccess() onSuccess()
} }
else { else {
data.app.cookieJar.clearForDomain("eregister.example.com") data.app.cookieJar.clear("eregister.example.com")
if (/*data.webLogin != null && data.webPassword != null && */true) { if (/*data.webLogin != null && data.webPassword != null && */true) {
loginWithCredentials() loginWithCredentials()
} }

View File

@ -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.MTIzNDU2Nzg5MDurcz1Rjg===.$param2".sha256() return "$param1.MTIzNDU2Nzg5MD86J6EdtN===.$param2".sha256()
} }
} }

View File

@ -9,8 +9,8 @@ import android.app.PendingIntent
import android.app.PendingIntent.CanceledException import android.app.PendingIntent.CanceledException
import android.content.Intent import android.content.Intent
import android.util.Log import android.util.Log
import com.google.firebase.iid.zzaq import com.google.firebase.iid.zzad
import com.google.firebase.iid.zzv import com.google.firebase.iid.zzaz
import com.google.firebase.messaging.zzc import com.google.firebase.messaging.zzc
import com.google.gson.JsonObject import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
@ -36,7 +36,7 @@ open class FirebaseService : zzc() {
// apparently this gets the correct intent from some // apparently this gets the correct intent from some
// kind of queue inside Firebase's InstanceID Receiver // kind of queue inside Firebase's InstanceID Receiver
final override fun zza(intent: Intent?) = zzaq.zza()?.zzb() final override fun zza(intent: Intent?) = zzaz.zza()?.zzb()
final override fun zzb(intent: Intent?): Boolean { final override fun zzb(intent: Intent?): Boolean {
val action = intent?.action val action = intent?.action
if (action == "com.google.firebase.messaging.NOTIFICATION_OPEN") { if (action == "com.google.firebase.messaging.NOTIFICATION_OPEN") {
@ -80,7 +80,7 @@ open class FirebaseService : zzc() {
val ackBundle = Bundle( val ackBundle = Bundle(
"google.message_id" to messageId "google.message_id" to messageId
) )
zzv.zza(this).zza(2, ackBundle) zzad.zza(this).zza(2, ackBundle)
} }
// check for duplicate message // check for duplicate message
// and add it to queue // and add it to queue

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-3-24.
*/
package pl.szczodrzynski.edziennik.network.cookie
import okhttp3.Cookie
class DumbCookie(var cookie: Cookie) {
constructor(domain: String, name: String, value: String, expiresAt: Long? = null) : this(
Cookie.Builder()
.name(name)
.value(value)
.also { if (expiresAt != null) it.expiresAt(expiresAt) }
.domain(domain)
.build()
)
init {
cookie = Cookie.Builder()
.name(cookie.name())
.value(cookie.value())
.expiresAt(cookie.expiresAt())
.domain(cookie.domain())
.build()
}
fun domainMatches(host: String): Boolean {
val domain = cookie.domain()
return host == domain || host.endsWith(".$domain")
}
override fun equals(other: Any?): Boolean {
if (other !is DumbCookie) return false
if (this.cookie === other.cookie) return true
return cookie.name() == other.cookie.name()
&& cookie.domain() == other.cookie.domain()
}
override fun hashCode(): Int {
var hash = 17
hash = 31 * hash + cookie.name().hashCode()
hash = 31 * hash + cookie.domain().hashCode()
return hash
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-3-24.
*/
package pl.szczodrzynski.edziennik.network.cookie
import android.content.Context
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
/**
* A simple cookie jar that does not care about the [Cookie.secure], [Cookie.hostOnly],
* [Cookie.httpOnly] and [Cookie.path] attributes.
*/
class DumbCookieJar(
/**
* A context to create the shared prefs file.
*/
context: Context,
/**
* Whether to persist session cookies as well, when [Cookie.persistent] is false.
*/
private val persistAll: Boolean = false
) : CookieJar {
private val prefs = context.getSharedPreferences("cookies", Context.MODE_PRIVATE)
private val sessionCookies = mutableSetOf<DumbCookie>()
private val savedCookies = mutableSetOf<DumbCookie>()
private fun save(dc: DumbCookie) {
sessionCookies.remove(dc)
sessionCookies.add(dc)
if (dc.cookie.persistent() || persistAll) {
savedCookies.remove(dc)
savedCookies.add(dc)
}
}
private fun delete(vararg toRemove: DumbCookie) {
sessionCookies.removeAll(toRemove)
savedCookies.removeAll(toRemove)
}
override fun saveFromResponse(url: HttpUrl?, cookies: List<Cookie>) {
for (cookie in cookies) {
val dc = DumbCookie(cookie)
save(dc)
}
}
override fun loadForRequest(url: HttpUrl): List<Cookie> {
return sessionCookies.filter {
it.cookie.matches(url)
}.map { it.cookie }
}
fun get(domain: String, name: String): String? {
return sessionCookies.firstOrNull {
it.domainMatches(domain) && it.cookie.name() == name
}?.cookie?.value()
}
fun set(domain: String, name: String, value: String?, isSession: Boolean) = set(
domain, name, value,
if (isSession) null
else System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L
)
/**
* Add a cookie to the cache.
* By default a session cookie is added. If [expiresAt] is set, the cookie is
* additionally persisted.
*/
fun set(domain: String, name: String?, value: String?, expiresAt: Long? = null) {
name ?: return
if (value == null) {
remove(domain, name)
return
}
val dc = DumbCookie(domain, name, value, expiresAt)
save(dc)
}
fun getAll(domain: String): Map<String, String> {
return sessionCookies.filter {
it.domainMatches(domain)
}.map { it.cookie.name() to it.cookie.value() }.toMap()
}
fun remove(domain: String, name: String) {
val toRemove = sessionCookies.filter {
it.domainMatches(domain) && it.cookie.name() == name
}
delete(*toRemove.toTypedArray())
}
fun clear(domain: String) {
val toRemove = sessionCookies.filter {
it.domainMatches(domain)
}
delete(*toRemove.toTypedArray())
}
}

View File

@ -241,7 +241,7 @@ class EventManualDialog(
with (b.dateDropdown) { with (b.dateDropdown) {
db = app.db db = app.db
profileId = profileId profileId = this@EventManualDialog.profileId
showWeekDays = false showWeekDays = false
showDays = true showDays = true
showOtherDate = true showOtherDate = true
@ -269,7 +269,7 @@ class EventManualDialog(
with (b.timeDropdown) { with (b.timeDropdown) {
db = app.db db = app.db
profileId = profileId profileId = this@EventManualDialog.profileId
showAllDay = true showAllDay = true
showCustomTime = true showCustomTime = true
lessonsDate = b.dateDropdown.getSelected() as? Date ?: Date.getToday() lessonsDate = b.dateDropdown.getSelected() as? Date ?: Date.getToday()
@ -289,7 +289,7 @@ class EventManualDialog(
with (b.teamDropdown) { with (b.teamDropdown) {
db = app.db db = app.db
profileId = profileId profileId = this@EventManualDialog.profileId
showNoTeam = true showNoTeam = true
loadItems() loadItems()
selectTeamClass() selectTeamClass()
@ -299,7 +299,7 @@ class EventManualDialog(
with (b.subjectDropdown) { with (b.subjectDropdown) {
db = app.db db = app.db
profileId = profileId profileId = this@EventManualDialog.profileId
showNoSubject = true showNoSubject = true
showCustomSubject = false showCustomSubject = false
loadItems() loadItems()
@ -309,7 +309,7 @@ class EventManualDialog(
with (b.teacherDropdown) { with (b.teacherDropdown) {
db = app.db db = app.db
profileId = profileId profileId = this@EventManualDialog.profileId
showNoTeacher = true showNoTeacher = true
loadItems() loadItems()
selectDefault(editingEvent?.teacherId) selectDefault(editingEvent?.teacherId)

View File

@ -438,7 +438,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
if (b.textLayout.counterMaxLength != -1 && b.text.length() > b.textLayout.counterMaxLength) if (b.textLayout.counterMaxLength != -1 && b.text.length() > b.textLayout.counterMaxLength)
return return
var textHtml = if (app.profile.loginStoreType != LoginStore.LOGIN_TYPE_VULCAN && app.profile.loginStoreType != LoginStore.LOGIN_TYPE_IDZIENNIK) { var textHtml = if (app.profile.loginStoreType != LoginStore.LOGIN_TYPE_VULCAN) {
HtmlCompat.toHtml(SpannableString(text), HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL) HtmlCompat.toHtml(SpannableString(text), HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL)
.replace("\n", "") .replace("\n", "")
.replace(" dir=\"ltr\"", "") .replace(" dir=\"ltr\"", "")

View File

@ -6,12 +6,11 @@ package pl.szczodrzynski.edziennik.utils.html
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.os.Build
import android.text.Html
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
import android.text.style.BulletSpan import android.text.style.BulletSpan
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.text.HtmlCompat
import pl.szczodrzynski.edziennik.dp import pl.szczodrzynski.edziennik.dp
import pl.szczodrzynski.edziennik.resolveAttr import pl.szczodrzynski.edziennik.resolveAttr
import pl.szczodrzynski.navlib.blendColors import pl.szczodrzynski.navlib.blendColors
@ -59,16 +58,12 @@ object BetterHtml {
}*/ }*/
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
val htmlSpannable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val htmlSpannable = HtmlCompat.fromHtml(
Html.fromHtml( text,
text, HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM or HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_LIST or HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_DIV,
Html.FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM or Html.FROM_HTML_SEPARATOR_LINE_BREAK_LIST or Html.FROM_HTML_SEPARATOR_LINE_BREAK_DIV, null,
null, LiTagHandler()
LiTagHandler() )
)
} else {
Html.fromHtml(text, null, LiTagHandler())
}
val spannableBuilder = SpannableStringBuilder(htmlSpannable) val spannableBuilder = SpannableStringBuilder(htmlSpannable)
val bulletSpans = spannableBuilder.getSpans(0, spannableBuilder.length, BulletSpan::class.java) val bulletSpans = spannableBuilder.getSpans(0, spannableBuilder.length, BulletSpan::class.java)

View File

@ -1,6 +1,6 @@
<androidx.constraintlayout.widget.ConstraintLayout <merge xmlns:android="http://schemas.android.com/apk/res/android"
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/material_drawer_account_header" android:id="@+id/material_drawer_account_header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/material_drawer_account_header_height" android:layout_height="@dimen/material_drawer_account_header_height"
@ -35,10 +35,27 @@
android:elevation="2dp" android:elevation="2dp"
android:focusable="true" android:focusable="true"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:biv_selectorOnPress="#80ffffff" app:materialDrawerSelectorOnPress="#80ffffff"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" /> app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/material_drawer_account_header_current_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
android:fontFamily="sans-serif"
android:gravity="center"
android:lines="1"
android:minWidth="20dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_badge_text"
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_current"
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_current"
tools:text="99" />
<com.mikepenz.materialdrawer.view.BezelImageView <com.mikepenz.materialdrawer.view.BezelImageView
android:id="@+id/material_drawer_account_header_small_first" android:id="@+id/material_drawer_account_header_small_first"
style="@style/BezelImageView" style="@style/BezelImageView"
@ -50,12 +67,29 @@
android:clickable="true" android:clickable="true"
android:elevation="2dp" android:elevation="2dp"
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter"
android:visibility="visible" android:visibility="visible"
android:scaleType="centerCrop" app:materialDrawerSelectorOnPress="#80ffffff"
app:biv_selectorOnPress="#80ffffff"
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_second" app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_second"
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" /> app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/material_drawer_account_header_small_first_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
android:fontFamily="sans-serif"
android:gravity="center"
android:lines="1"
android:minWidth="20dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_badge_small_text"
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_small_first"
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_small_first"
tools:text="99" />
<com.mikepenz.materialdrawer.view.BezelImageView <com.mikepenz.materialdrawer.view.BezelImageView
android:id="@+id/material_drawer_account_header_small_second" android:id="@+id/material_drawer_account_header_small_second"
style="@style/BezelImageView" style="@style/BezelImageView"
@ -67,12 +101,29 @@
android:clickable="true" android:clickable="true"
android:elevation="2dp" android:elevation="2dp"
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter"
android:visibility="visible" android:visibility="visible"
android:scaleType="centerCrop" app:materialDrawerSelectorOnPress="#80ffffff"
app:biv_selectorOnPress="#80ffffff"
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_third" app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_third"
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" /> app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/material_drawer_account_header_small_second_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
android:fontFamily="sans-serif"
android:gravity="center"
android:lines="1"
android:minWidth="20dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_badge_small_text"
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_small_second"
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_small_second"
tools:text="99" />
<com.mikepenz.materialdrawer.view.BezelImageView <com.mikepenz.materialdrawer.view.BezelImageView
android:id="@+id/material_drawer_account_header_small_third" android:id="@+id/material_drawer_account_header_small_third"
style="@style/BezelImageView" style="@style/BezelImageView"
@ -84,12 +135,29 @@
android:clickable="true" android:clickable="true"
android:elevation="2dp" android:elevation="2dp"
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter"
android:visibility="visible" android:visibility="visible"
android:scaleType="centerCrop" app:materialDrawerSelectorOnPress="#80ffffff"
app:biv_selectorOnPress="#80ffffff"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" /> app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/material_drawer_account_header_small_third_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
android:fontFamily="sans-serif"
android:gravity="center"
android:lines="1"
android:minWidth="20dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_badge_small_text"
app:layout_constraintBottom_toBottomOf="@id/material_drawer_account_header_small_third"
app:layout_constraintStart_toStartOf="@id/material_drawer_account_header_small_third"
tools:text="99" />
<androidx.constraintlayout.widget.Guideline <androidx.constraintlayout.widget.Guideline
android:id="@+id/material_drawer_text_guideline" android:id="@+id/material_drawer_text_guideline"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -138,4 +206,4 @@
android:layout_marginBottom="@dimen/material_drawer_account_header_dropdown_margin_bottom" android:layout_marginBottom="@dimen/material_drawer_account_header_dropdown_margin_bottom"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </merge>

View File

@ -4,6 +4,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/material_drawer_item_profile" android:layout_height="@dimen/material_drawer_item_profile"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingStart="@dimen/material_drawer_vertical_padding" android:paddingStart="@dimen/material_drawer_vertical_padding"
android:paddingLeft="@dimen/material_drawer_vertical_padding" android:paddingLeft="@dimen/material_drawer_vertical_padding"
@ -44,7 +46,7 @@
android:textDirection="anyRtl" android:textDirection="anyRtl"
android:textSize="@dimen/material_drawer_item_profile_text" android:textSize="@dimen/material_drawer_item_profile_text"
app:layout_constraintBottom_toTopOf="@id/material_drawer_email" app:layout_constraintBottom_toTopOf="@id/material_drawer_email"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/material_drawer_badge_container"
app:layout_constraintStart_toEndOf="@id/material_drawer_profileIcon" app:layout_constraintStart_toEndOf="@id/material_drawer_profileIcon"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
@ -69,9 +71,37 @@
android:textDirection="anyRtl" android:textDirection="anyRtl"
android:textSize="@dimen/material_drawer_item_profile_description" android:textSize="@dimen/material_drawer_item_profile_description"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/material_drawer_badge_container"
app:layout_constraintStart_toEndOf="@id/material_drawer_profileIcon" app:layout_constraintStart_toEndOf="@id/material_drawer_profileIcon"
app:layout_constraintTop_toBottomOf="@id/material_drawer_name" app:layout_constraintTop_toBottomOf="@id/material_drawer_name"
tools:text="Some drawer text" /> tools:text="Some drawer text" />
</androidx.constraintlayout.widget.ConstraintLayout> <LinearLayout
android:id="@+id/material_drawer_badge_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"
android:gravity="center"
android:paddingStart="@dimen/material_drawer_padding"
android:paddingLeft="@dimen/material_drawer_padding"
android:paddingEnd="0dp"
android:paddingRight="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/material_drawer_badge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:gravity="center"
android:lines="1"
android:minWidth="20dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_primary_text"
tools:text="99" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -197,14 +197,14 @@
<string name="error_62_reason">Brak internetu</string> <string name="error_62_reason">Brak internetu</string>
<string name="error_63_reason">Brak internetu: połączenie SSL nie powiodło się</string> <string name="error_63_reason">Brak internetu: połączenie SSL nie powiodło się</string>
<string name="error_100_reason">Brak odpowiedzi serwera. Dziennik może być przeciążony lub mieć przerwę techniczną.</string> <string name="error_100_reason">Brak odpowiedzi serwera. Dziennik może być przeciążony lub mieć przerwę techniczną.</string>
<string name="error_101_reason">Dane logowania niekompletne</string> <string name="error_101_reason">Dane logowania niekompletne. Skontaktuj się z twórcą aplikacji.</string>
<string name="error_102_reason">Nieprawidłowe dane logowania</string> <string name="error_102_reason">Nieprawidłowe dane logowania</string>
<string name="error_105_reason">Profil nie został ustawiony</string> <string name="error_105_reason">Profil nie został ustawiony</string>
<string name="error_106_reason">Profil jest archiwalny - synchronizacja profilu z poprzedniego roku szkolnego nie jest możliwa</string> <string name="error_106_reason">Profil jest archiwalny - synchronizacja profilu z poprzedniego roku szkolnego nie jest możliwa</string>
<string name="error_110_reason">Nieprawidłowy sposób logowania</string> <string name="error_110_reason">Nieprawidłowy sposób logowania. Skontaktuj się z twórcą aplikacji.</string>
<string name="error_111_reason">Nie można wywołać metody logowania</string> <string name="error_111_reason">Nie można wywołać metody logowania. Skontaktuj się z twórcą aplikacji.</string>
<string name="error_112_reason">Nie zaimplementowano</string> <string name="error_112_reason">Nie zaimplementowano</string>
<string name="error_113_reason">Wystąpił błąd podczas pobierania pliku</string> <string name="error_113_reason">Wystąpił błąd podczas pobierania pliku. Dziennik może być przeciążony lub mieć przerwę techniczną.</string>
<string name="error_115_reason">Brak uczniów przypisanych do konta</string> <string name="error_115_reason">Brak uczniów przypisanych do konta</string>

View File

@ -5,8 +5,8 @@ buildscript {
kotlin_version = '1.3.61' kotlin_version = '1.3.61'
release = [ release = [
versionName: "4.0-beta.14", versionName: "4.0-rc.1",
versionCode: 4000014 versionCode: 4000019
] ]
setup = [ setup = [
@ -17,6 +17,8 @@ buildscript {
] ]
versions = [ versions = [
gradleAndroid : "4.0.0-beta03",
kotlin : ext.kotlin_version, kotlin : ext.kotlin_version,
ktx : "1.2.0", ktx : "1.2.0",
@ -32,24 +34,24 @@ buildscript {
navigationFragment: "1.0.0", navigationFragment: "1.0.0",
legacy : "1.0.0", legacy : "1.0.0",
room : "2.2.4", room : "2.2.5",
lifecycle : "2.2.0", lifecycle : "2.2.0",
work : "2.3.2", work : "2.3.4",
firebase : '17.2.2', firebase : '17.2.2',
firebasemessaging: "20.1.0", firebasemessaging: "20.1.3",
play_services : "17.0.0", play_services : "17.0.0",
materialdialogs : "0.9.6.0", materialdialogs : "0.9.6.0",
materialdrawer : "cad66092a6", materialdrawer : "817e45765c367034b03046aaea6e95eeabcb40e9",
iconics : "4.0.1", iconics : "4.0.1",
font_cmd : "3.5.95.1-kotlin", font_cmd : "3.5.95.1-kotlin",
navlib : "5c8b13c0d9db0d9e822fdae82c8afca6c01ab41e", navlib : "28cdab341470dffa5f331379fe9702482681d7de",
gifdrawable : "1.2.15", gifdrawable : "1.2.15",
retrofit : '2.6.2' retrofit : "2.6.4"
] ]
} }
@ -61,11 +63,11 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.0.0-beta01' classpath "com.android.tools.build:gradle:${versions.gradleAndroid}"
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.3' classpath 'com.google.gms:google-services:4.3.3'
classpath 'io.fabric.tools:gradle:1.28.1' classpath 'io.fabric.tools:gradle:1.28.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip