mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-13 14:10:46 +02:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
dc9e6081c5 | |||
26f8c03570 | |||
97e0f36f09 | |||
9b13552b73 | |||
d8559637a5 | |||
00a90a14dc | |||
d56afb034b | |||
0327ba37f1 | |||
12a54e58b5 | |||
238250e8c9 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -86,4 +86,5 @@ app/schemas/
|
|||||||
|
|
||||||
signatures/
|
signatures/
|
||||||
|
|
||||||
app/.cxx
|
app/.cxx
|
||||||
|
/i18n/
|
||||||
|
10
.idea/jarRepositories.xml
generated
10
.idea/jarRepositories.xml
generated
@ -41,5 +41,15 @@
|
|||||||
<option name="name" value="MavenRepo" />
|
<option name="name" value="MavenRepo" />
|
||||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven4" />
|
||||||
|
<option name="name" value="maven4" />
|
||||||
|
<option name="url" value="https://dl.bintray.com/undervoid/Powerpermission" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven4" />
|
||||||
|
<option name="name" value="maven4" />
|
||||||
|
<option name="url" value="https://dl.bintray.com/undervoid/PowerPermission" />
|
||||||
|
</remote-repository>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -198,6 +198,9 @@ dependencies {
|
|||||||
kapt project(":codegen")
|
kapt project(":codegen")
|
||||||
|
|
||||||
implementation 'com.google.android:flexbox:2.0.1'
|
implementation 'com.google.android:flexbox:2.0.1'
|
||||||
|
|
||||||
|
implementation 'com.qifan.powerpermission:powerpermission:1.0.0'
|
||||||
|
implementation 'com.qifan.powerpermission:powerpermission-coroutines:1.0.0'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
|
<!-- PowerPermission uses minSdk 21, it's safe to override as it is used only in >= 23 -->
|
||||||
|
<uses-sdk tools:overrideLibrary="com.qifan.powerpermission.coroutines, com.qifan.powerpermission.core" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
<h3>Wersja 4.0-rc.5, 2020-04-05</h3>
|
<h3>Wersja 4.0, 2020-04-19</h3>
|
||||||
<ul>
|
|
||||||
<li>Możliwość pobierania załączników do zadań domowych (Librus, MobiDziennik, iDziennik).</li>
|
|
||||||
<li>Widok pełnej treści zadań domowych (iDziennik, EduDziennik).</li>
|
|
||||||
<li>Wyszukiwarka wiadomości, pozwalająca na łatwe znalezienie potrzebnej konwersacji.</li>
|
|
||||||
<li>Możliwość usuwania odebranych wiadomości w aplikacji.</li>
|
|
||||||
</ul>
|
|
||||||
<!--<h3>Wersja 4.0-rc.3, 2020-03-29</h3>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli 👏</li>
|
<li><b><u>Wysyłanie wiadomości</u></b> - funkcja, na którą czekał każdy. Od teraz w Szkolnym można wysyłać oraz odpowiadać na wiadomości do nauczycieli 👏</li>
|
||||||
<li><b>Przebudowaliśmy cały moduł synchronizacji</b>, co oznacza większą stabilność aplikacji, szybkość oraz poprawność pobieranych danych</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>Wyszukiwarka wiadomości, pozwalająca na łatwe znalezienie potrzebnej konwersacji.</li>
|
||||||
|
<li>Możliwość pobierania załączników do zadań domowych oraz wiadomości w każdym dzienniku.</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>
|
||||||
@ -17,6 +12,7 @@
|
|||||||
<li>Znaczki nieprzeczytanych informacji na obrazkach profili.</li>
|
<li>Znaczki nieprzeczytanych informacji na obrazkach profili.</li>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
<li>Udoskonalone tłumaczenie na j.angielski (dzięki @Predator)</li>
|
||||||
<li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li>
|
<li>Nowe okienka informacji o wydarzeniach oraz lekcjach</li>
|
||||||
<li>Nowe, przyjemniejsze powiadomienia</li>
|
<li>Nowe, przyjemniejsze powiadomienia</li>
|
||||||
<li>Dużo poprawek w widoku <b>Wiadomości</b> oraz <b>Ogłoszeń</b></li>
|
<li>Dużo poprawek w widoku <b>Wiadomości</b> oraz <b>Ogłoszeń</b></li>
|
||||||
@ -29,7 +25,7 @@
|
|||||||
<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>
|
||||||
</ul>-->
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
Dzięki za korzystanie ze Szkolnego!<br>
|
Dzięki za korzystanie ze Szkolnego!<br>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
/*secret password - removed for source code publication*/
|
/*secret password - removed for source code publication*/
|
||||||
static toys AES_IV[16] = {
|
static toys AES_IV[16] = {
|
||||||
0x7b, 0x51, 0x86, 0xc5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
0x38, 0xd4, 0x73, 0xaf, 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);
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
val gradesManager by lazy { GradesManager(this) }
|
val gradesManager by lazy { GradesManager(this) }
|
||||||
val timetableManager by lazy { TimetableManager(this) }
|
val timetableManager by lazy { TimetableManager(this) }
|
||||||
val eventManager by lazy { EventManager(this) }
|
val eventManager by lazy { EventManager(this) }
|
||||||
|
val permissionManager by lazy { PermissionManager(this) }
|
||||||
|
|
||||||
val db
|
val db
|
||||||
get() = App.db
|
get() = App.db
|
||||||
@ -166,6 +167,10 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
db.profileDao().firstId?.let { profileLoadById(it) }
|
db.profileDao().firstId?.let { profileLoadById(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.ui.language?.let {
|
||||||
|
setLanguage(it)
|
||||||
|
}
|
||||||
|
|
||||||
devMode = BuildConfig.DEBUG
|
devMode = BuildConfig.DEBUG
|
||||||
|
|
||||||
Signing.getCert(this)
|
Signing.getCert(this)
|
||||||
|
@ -454,7 +454,7 @@ operator fun MatchResult.get(group: Int): String {
|
|||||||
return groupValues[group]
|
return groupValues[group]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.setLanguage(language: String) {
|
fun Context.setLanguage(language: String) {
|
||||||
val locale = Locale(language.toLowerCase(Locale.ROOT))
|
val locale = Locale(language.toLowerCase(Locale.ROOT))
|
||||||
val configuration = resources.configuration
|
val configuration = resources.configuration
|
||||||
Locale.setDefault(locale)
|
Locale.setDefault(locale)
|
||||||
@ -463,7 +463,6 @@ fun Activity.setLanguage(language: String) {
|
|||||||
}
|
}
|
||||||
configuration.locale = locale
|
configuration.locale = locale
|
||||||
resources.updateConfiguration(configuration, resources.displayMetrics)
|
resources.updateConfiguration(configuration, resources.displayMetrics)
|
||||||
baseContext.resources.updateConfiguration(configuration, baseContext.resources.displayMetrics)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -226,8 +226,8 @@ 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)
|
||||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
if (App.debugMode) {
|
||||||
if (App.devMode) {
|
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)
|
||||||
.isInDrawer(true)
|
.isInDrawer(true)
|
||||||
@ -414,8 +414,6 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
R.color.md_green_500
|
R.color.md_green_500
|
||||||
)
|
)
|
||||||
|
|
||||||
isStoragePermissionGranted()
|
|
||||||
|
|
||||||
SyncWorker.scheduleNext(app)
|
SyncWorker.scheduleNext(app)
|
||||||
UpdateWorker.scheduleNext(app)
|
UpdateWorker.scheduleNext(app)
|
||||||
|
|
||||||
|
@ -111,5 +111,7 @@ const val VULCAN_API_ENDPOINT_MESSAGES_SENT = "mobile-api/Uczen.v3.Uczen/Wiadomo
|
|||||||
const val VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS = "mobile-api/Uczen.v3.Uczen/ZmienStatusWiadomosci"
|
const val VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS = "mobile-api/Uczen.v3.Uczen/ZmienStatusWiadomosci"
|
||||||
const val VULCAN_API_ENDPOINT_MESSAGES_ADD = "mobile-api/Uczen.v3.Uczen/DodajWiadomosc"
|
const val VULCAN_API_ENDPOINT_MESSAGES_ADD = "mobile-api/Uczen.v3.Uczen/DodajWiadomosc"
|
||||||
const val VULCAN_API_ENDPOINT_PUSH = "mobile-api/Uczen.v3.Uczen/UstawPushToken"
|
const val VULCAN_API_ENDPOINT_PUSH = "mobile-api/Uczen.v3.Uczen/UstawPushToken"
|
||||||
|
const val VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/WiadomosciZalacznik"
|
||||||
|
const val VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS = "mobile-api/Uczen.v3.Uczen/ZadaniaDomoweZalacznik"
|
||||||
|
|
||||||
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
||||||
|
@ -158,6 +158,7 @@ const val ERROR_LOGIN_VULCAN_NO_PUPILS = 331
|
|||||||
const val ERROR_VULCAN_API_MAINTENANCE = 340
|
const val ERROR_VULCAN_API_MAINTENANCE = 340
|
||||||
const val ERROR_VULCAN_API_BAD_REQUEST = 341
|
const val ERROR_VULCAN_API_BAD_REQUEST = 341
|
||||||
const val ERROR_VULCAN_API_OTHER = 342
|
const val ERROR_VULCAN_API_OTHER = 342
|
||||||
|
const val ERROR_VULCAN_ATTACHMENT_DOWNLOAD = 343
|
||||||
|
|
||||||
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
|
||||||
@ -207,5 +208,6 @@ const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
|
|||||||
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
||||||
const val EXCEPTION_EDUDZIENNIK_WEB_REQUEST = 920
|
const val EXCEPTION_EDUDZIENNIK_WEB_REQUEST = 920
|
||||||
const val EXCEPTION_EDUDZIENNIK_FILE_REQUEST = 921
|
const val EXCEPTION_EDUDZIENNIK_FILE_REQUEST = 921
|
||||||
|
const val ERROR_ONEDRIVE_DOWNLOAD = 930
|
||||||
|
|
||||||
const val LOGIN_NO_ARGUMENTS = 1201
|
const val LOGIN_NO_ARGUMENTS = 1201
|
||||||
|
@ -97,7 +97,7 @@ object Regexes {
|
|||||||
"""zadanieFormularz\(([0-9]+),""".toRegex(DOT_MATCHES_ALL)
|
"""zadanieFormularz\(([0-9]+),""".toRegex(DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
val MOBIDZIENNIK_HOMEWORK_ATTACHMENT by lazy {
|
val MOBIDZIENNIK_HOMEWORK_ATTACHMENT by lazy {
|
||||||
"""zalacznik=([0-9]+)'.+?word-break">(.+?)</td>""".toRegex(DOT_MATCHES_ALL)
|
"""zalacznik(_zadania)?=([0-9]+)'.+?word-break">(.+?)</td>""".toRegex(DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-4-7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik.helper
|
||||||
|
|
||||||
|
import im.wangchao.mhttp.Request
|
||||||
|
import im.wangchao.mhttp.Response
|
||||||
|
import im.wangchao.mhttp.callback.FileCallbackHandler
|
||||||
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.ERROR_ONEDRIVE_DOWNLOAD
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.SYSTEM_USER_AGENT
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class OneDriveDownloadAttachment(
|
||||||
|
app: App,
|
||||||
|
fileUrl: String,
|
||||||
|
val onSuccess: (file: File) -> Unit,
|
||||||
|
val onProgress: (written: Long, total: Long) -> Unit,
|
||||||
|
val onError: (apiError: ApiError) -> Unit
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "OneDriveDownloadAttachment"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
Request.builder()
|
||||||
|
.url(fileUrl)
|
||||||
|
.userAgent(SYSTEM_USER_AGENT)
|
||||||
|
.withClient(app.httpLazy)
|
||||||
|
.callback(object : TextCallbackHandler() {
|
||||||
|
override fun onSuccess(text: String, response: Response) {
|
||||||
|
val location = response.headers().get("Location")
|
||||||
|
// https://onedrive.live.com/redir?resid=D75496A2EB87531C!706&authkey=!ABjZeh3pHMqj11Q
|
||||||
|
if (location?.contains("onedrive.live.com/redir?resid=") != true) {
|
||||||
|
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||||
|
.withApiResponse(text)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val url = location
|
||||||
|
.replace("onedrive.live.com/redir?resid=", "storage.live.com/items/")
|
||||||
|
.replace("?", "&")
|
||||||
|
.replaceFirst("&", "?")
|
||||||
|
downloadFile(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response, throwable: Throwable) {
|
||||||
|
onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun downloadFile(url: String) {
|
||||||
|
val targetFile = Utils.getStorageDir()
|
||||||
|
|
||||||
|
val callback = object : FileCallbackHandler(targetFile) {
|
||||||
|
override fun onSuccess(file: File?, response: Response?) {
|
||||||
|
if (file == null) {
|
||||||
|
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||||
|
.withResponse(response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
onSuccess(file)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProgress(bytesWritten: Long, bytesTotal: Long) {
|
||||||
|
try {
|
||||||
|
this@OneDriveDownloadAttachment.onProgress(bytesWritten, bytesTotal)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
onError(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD)
|
||||||
|
.withThrowable(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
onError(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.builder()
|
||||||
|
.url(url)
|
||||||
|
.userAgent(SYSTEM_USER_AGENT)
|
||||||
|
.callback(callback)
|
||||||
|
.build()
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
}
|
@ -54,13 +54,13 @@ class LibrusSandboxDownloadAttachment(override val data: DataLibrus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getAttachmentCheckKey(attachmentKey: String, callback: () -> Unit) {
|
private fun getAttachmentCheckKey(attachmentKey: String, callback: () -> Unit) {
|
||||||
sandboxGet(LibrusMessagesGetAttachment.TAG, "CSCheckKey",
|
sandboxGet(TAG, "CSCheckKey",
|
||||||
parameters = mapOf("singleUseKey" to attachmentKey)) { json ->
|
parameters = mapOf("singleUseKey" to attachmentKey)) { json ->
|
||||||
|
|
||||||
when (json.getString("status")) {
|
when (json.getString("status")) {
|
||||||
"not_downloaded_yet" -> {
|
"not_downloaded_yet" -> {
|
||||||
if (getAttachmentCheckKeyTries++ > 5) {
|
if (getAttachmentCheckKeyTries++ > 5) {
|
||||||
data.error(ApiError(LibrusMessagesGetAttachment.TAG, ERROR_FILE_DOWNLOAD)
|
data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD)
|
||||||
.withApiResponse(json))
|
.withApiResponse(json))
|
||||||
return@sandboxGet
|
return@sandboxGet
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ class LibrusSandboxDownloadAttachment(override val data: DataLibrus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
data.error(ApiError(LibrusMessagesGetAttachment.TAG, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
|
data.error(ApiError(TAG, EXCEPTION_LIBRUS_MESSAGES_REQUEST)
|
||||||
.withApiResponse(json))
|
.withApiResponse(json))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ class LibrusSandboxDownloadAttachment(override val data: DataLibrus,
|
|||||||
private fun downloadAttachment(url: String, method: Int = GET) {
|
private fun downloadAttachment(url: String, method: Int = GET) {
|
||||||
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
||||||
|
|
||||||
sandboxGetFile(LibrusMessagesGetAttachment.TAG, url, targetFile, { file ->
|
sandboxGetFile(TAG, url, targetFile, { file ->
|
||||||
|
|
||||||
val event = AttachmentGetEvent(
|
val event = AttachmentGetEvent(
|
||||||
profileId,
|
profileId,
|
||||||
|
@ -29,14 +29,14 @@ class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
|
|||||||
|
|
||||||
val typeUrl = when (owner) {
|
val typeUrl = when (owner) {
|
||||||
is Message -> if (owner.type == Message.TYPE_SENT)
|
is Message -> if (owner.type == Message.TYPE_SENT)
|
||||||
"dziennik/wiadwyslana?id="
|
"dziennik/wiadwyslana/?id="
|
||||||
else
|
else
|
||||||
"dziennik/wiadodebrana?id="
|
"dziennik/wiadodebrana/?id="
|
||||||
|
|
||||||
is Event -> if (owner.date >= Date.getToday())
|
is Event -> if (owner.date >= Date.getToday())
|
||||||
"mobile/zadaniadomowe?id_zadania="
|
"dziennik/wyslijzadanie/?id_zadania="
|
||||||
else
|
else
|
||||||
"mobile/zadaniadomowearchiwalne?id_zadania="
|
"dziennik/wyslijzadanie/?id_zadania="
|
||||||
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
|
|||||||
else -> -1
|
else -> -1
|
||||||
}
|
}
|
||||||
|
|
||||||
webGetFile(TAG, "/$typeUrl${ownerId}&zalacznik=$attachmentId", targetFile, { file ->
|
webGetFile(TAG, "/$typeUrl${ownerId}&uczen=${data.studentId}&zalacznik=$attachmentId", targetFile, { file ->
|
||||||
|
|
||||||
val event = AttachmentGetEvent(
|
val event = AttachmentGetEvent(
|
||||||
profileId,
|
profileId,
|
||||||
|
@ -39,9 +39,9 @@ class MobidziennikWebGetHomework(override val data: DataMobidziennik,
|
|||||||
|
|
||||||
event.attachmentIds = mutableListOf()
|
event.attachmentIds = mutableListOf()
|
||||||
event.attachmentNames = mutableListOf()
|
event.attachmentNames = mutableListOf()
|
||||||
Regexes.MOBIDZIENNIK_HOMEWORK_ATTACHMENT.findAll(tableRow).onEach {
|
Regexes.MOBIDZIENNIK_HOMEWORK_ATTACHMENT.findAll(tableRow).forEach {
|
||||||
event.attachmentIds?.add(it[1].toLongOrNull() ?: return@onEach)
|
event.attachmentIds?.add(it[2].toLongOrNull() ?: return@forEach)
|
||||||
event.attachmentNames?.add(it[2])
|
event.attachmentNames?.add(it[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
event.homeworkBody = ""
|
event.homeworkBody = ""
|
||||||
|
@ -5,26 +5,31 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan
|
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.helper.OneDriveDownloadAttachment
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanData
|
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.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.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.EventGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.api.prepare
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.prepareFor
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.vulcanLoginMethods
|
|
||||||
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.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
companion object {
|
companion object {
|
||||||
@ -87,8 +92,29 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
override fun getMessage(message: MessageFull) {
|
override fun getMessage(message: MessageFull) {
|
||||||
login(LOGIN_METHOD_VULCAN_API) {
|
login(LOGIN_METHOD_VULCAN_API) {
|
||||||
VulcanApiMessagesChangeStatus(data, message) {
|
if (message.attachmentIds != null) {
|
||||||
completed()
|
VulcanApiMessagesChangeStatus(data, message) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
return@login
|
||||||
|
}
|
||||||
|
val list = data.app.db.messageDao().getAllNow(data.profileId)
|
||||||
|
VulcanApiAttachments(data, list, message, MessageFull::class) { _ ->
|
||||||
|
list.forEach {
|
||||||
|
if (it.attachmentIds == null)
|
||||||
|
it.attachmentIds = mutableListOf()
|
||||||
|
data.messageList.add(it)
|
||||||
|
}
|
||||||
|
data.messageListReplace = true
|
||||||
|
|
||||||
|
if (message.seen) {
|
||||||
|
EventBus.getDefault().postSticky(MessageGetEvent(message))
|
||||||
|
completed()
|
||||||
|
return@VulcanApiAttachments
|
||||||
|
}
|
||||||
|
VulcanApiMessagesChangeStatus(data, message) {
|
||||||
|
completed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,9 +129,66 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {}
|
override fun markAllAnnouncementsAsRead() {}
|
||||||
override fun getAnnouncement(announcement: AnnouncementFull) {}
|
override fun getAnnouncement(announcement: AnnouncementFull) {}
|
||||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {}
|
|
||||||
override fun getRecipientList() {}
|
override fun getRecipientList() {}
|
||||||
override fun getEvent(eventFull: EventFull) {}
|
|
||||||
|
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||||
|
val fileUrl = attachmentName.substringAfter(":")
|
||||||
|
if (attachmentName == fileUrl) {
|
||||||
|
data.error(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
OneDriveDownloadAttachment(
|
||||||
|
app,
|
||||||
|
fileUrl,
|
||||||
|
onSuccess = { file ->
|
||||||
|
val event = AttachmentGetEvent(
|
||||||
|
data.profileId,
|
||||||
|
owner,
|
||||||
|
attachmentId,
|
||||||
|
AttachmentGetEvent.TYPE_FINISHED,
|
||||||
|
file.absolutePath
|
||||||
|
)
|
||||||
|
|
||||||
|
val attachmentDataFile = File(Utils.getStorageDir(), ".${data.profileId}_${event.ownerId}_${event.attachmentId}")
|
||||||
|
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||||
|
|
||||||
|
EventBus.getDefault().postSticky(event)
|
||||||
|
|
||||||
|
completed()
|
||||||
|
},
|
||||||
|
onProgress = { written, total ->
|
||||||
|
val event = AttachmentGetEvent(
|
||||||
|
data.profileId,
|
||||||
|
owner,
|
||||||
|
attachmentId,
|
||||||
|
AttachmentGetEvent.TYPE_PROGRESS,
|
||||||
|
bytesWritten = written
|
||||||
|
)
|
||||||
|
|
||||||
|
EventBus.getDefault().postSticky(event)
|
||||||
|
},
|
||||||
|
onError = { apiError ->
|
||||||
|
data.error(apiError)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getEvent(eventFull: EventFull) {
|
||||||
|
login(LOGIN_METHOD_VULCAN_API) {
|
||||||
|
val list = data.app.db.eventDao().getAllNow(data.profileId).filter { !it.addedManually }
|
||||||
|
VulcanApiAttachments(data, list, eventFull, EventFull::class) { _ ->
|
||||||
|
list.forEach {
|
||||||
|
it.homeworkBody = ""
|
||||||
|
data.eventList.add(it)
|
||||||
|
}
|
||||||
|
data.eventListReplace = true
|
||||||
|
|
||||||
|
EventBus.getDefault().postSticky(EventGetEvent(eventFull))
|
||||||
|
completed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun firstLogin() { VulcanFirstLogin(data) { completed() } }
|
override fun firstLogin() { VulcanFirstLogin(data) { completed() } }
|
||||||
override fun cancel() {
|
override fun cancel() {
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-4-6.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.asJsonObjectList
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||||
|
import pl.szczodrzynski.edziennik.getJsonArray
|
||||||
|
import pl.szczodrzynski.edziennik.getLong
|
||||||
|
import pl.szczodrzynski.edziennik.getString
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
class VulcanApiAttachments(override val data: DataVulcan,
|
||||||
|
val list: List<*>,
|
||||||
|
val owner: Any?,
|
||||||
|
val ownerClass: KClass<*>,
|
||||||
|
val onSuccess: (list: List<*>) -> Unit
|
||||||
|
) : VulcanApi(data, null) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "VulcanApiAttachments"
|
||||||
|
}
|
||||||
|
|
||||||
|
init { run {
|
||||||
|
val endpoint = when (ownerClass) {
|
||||||
|
MessageFull::class -> VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS
|
||||||
|
EventFull::class -> VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS
|
||||||
|
else -> null
|
||||||
|
} ?: return@run
|
||||||
|
|
||||||
|
val idName = when (ownerClass) {
|
||||||
|
MessageFull::class -> "IdWiadomosc"
|
||||||
|
EventFull::class -> "IdZadanieDomowe"
|
||||||
|
else -> null
|
||||||
|
} ?: return@run
|
||||||
|
|
||||||
|
val startDate = profile?.getSemesterStart(profile?.currentSemester ?: 1)?.inUnix ?: 0
|
||||||
|
val endDate = Date.getToday().stepForward(0, 1, 0).inUnix
|
||||||
|
|
||||||
|
apiGet(TAG, endpoint, parameters = mapOf(
|
||||||
|
"DataPoczatkowa" to startDate,
|
||||||
|
"DataKoncowa" to endDate,
|
||||||
|
"LoginId" to data.studentLoginId,
|
||||||
|
"IdUczen" to data.studentId
|
||||||
|
)) { json, _ ->
|
||||||
|
|
||||||
|
json.getJsonArray("Data")?.asJsonObjectList()?.forEach { attachment ->
|
||||||
|
val id = attachment.getLong("Id") ?: return@forEach
|
||||||
|
val itemId = attachment.getLong(idName) ?: return@forEach
|
||||||
|
val url = attachment.getString("Url") ?: return@forEach
|
||||||
|
val fileName = "${attachment.getString("NazwaPliku")}:$url"
|
||||||
|
|
||||||
|
list.forEach {
|
||||||
|
if (it is MessageFull
|
||||||
|
&& it.profileId == profileId
|
||||||
|
&& it.id == itemId
|
||||||
|
&& it.attachmentIds?.contains(id) != true) {
|
||||||
|
if (it.attachmentIds == null)
|
||||||
|
it.attachmentIds = mutableListOf()
|
||||||
|
if (it.attachmentNames == null)
|
||||||
|
it.attachmentNames = mutableListOf()
|
||||||
|
it.attachmentIds?.add(id)
|
||||||
|
it.attachmentNames?.add(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it is EventFull
|
||||||
|
&& it.profileId == profileId
|
||||||
|
&& it.id == itemId
|
||||||
|
&& it.attachmentIds?.contains(id) != true) {
|
||||||
|
if (it.attachmentIds == null)
|
||||||
|
it.attachmentIds = mutableListOf()
|
||||||
|
if (it.attachmentNames == null)
|
||||||
|
it.attachmentNames = mutableListOf()
|
||||||
|
it.attachmentIds?.add(id)
|
||||||
|
it.attachmentNames?.add(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner is MessageFull
|
||||||
|
&& it is MessageFull
|
||||||
|
&& owner.profileId == it.profileId
|
||||||
|
&& owner.id == it.id) {
|
||||||
|
owner.attachmentIds = it.attachmentIds
|
||||||
|
owner.attachmentNames = it.attachmentNames
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner is EventFull
|
||||||
|
&& it is EventFull
|
||||||
|
&& owner.profileId == it.profileId
|
||||||
|
&& owner.id == it.id) {
|
||||||
|
owner.attachmentIds = it.attachmentIds
|
||||||
|
owner.attachmentNames = it.attachmentNames
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (owner is MessageFull) {
|
||||||
|
list.forEach {
|
||||||
|
(it as? MessageFull)?.let { message ->
|
||||||
|
data.messageList.add(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.messageListReplace = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner is EventFull) {
|
||||||
|
list.forEach {
|
||||||
|
(it as? EventFull)?.let { it1 ->
|
||||||
|
it1.homeworkBody = ""
|
||||||
|
data.eventList.add(it1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.eventListReplace = true
|
||||||
|
}*/
|
||||||
|
|
||||||
|
onSuccess(list)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
@ -197,6 +197,13 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
|||||||
|
|
||||||
profile.userCode = generateUserCode()
|
profile.userCode = generateUserCode()
|
||||||
|
|
||||||
|
// update profile subname with class name, school year and account type
|
||||||
|
profile.subname = joinNotNullStrings(
|
||||||
|
" - ",
|
||||||
|
profile.studentClassName,
|
||||||
|
"${profile.studentSchoolYearStart}/${profile.studentSchoolYearStart + 1}"
|
||||||
|
) + " " + app.getString(if (profile.isParent) R.string.login_summary_account_parent else R.string.login_summary_account_child)
|
||||||
|
|
||||||
db.profileDao().add(profile)
|
db.profileDao().add(profile)
|
||||||
db.loginStoreDao().add(loginStore)
|
db.loginStoreDao().add(loginStore)
|
||||||
|
|
||||||
|
@ -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.MTIzNDU2Nzg5MD43hCWBBS===.$param2".sha256()
|
return "$param1.MTIzNDU2Nzg5MDP/4SAI6B===.$param2".sha256()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import com.google.gson.JsonObject
|
|||||||
import pl.droidsonroids.gif.GifDrawable
|
import pl.droidsonroids.gif.GifDrawable
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
|
||||||
|
import pl.szczodrzynski.edziennik.utils.ProfileImageHolder
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.navlib.ImageHolder
|
import pl.szczodrzynski.navlib.ImageHolder
|
||||||
import pl.szczodrzynski.navlib.R
|
import pl.szczodrzynski.navlib.R
|
||||||
@ -128,7 +129,7 @@ open class Profile(
|
|||||||
override fun getImageHolder(context: Context): ImageHolder {
|
override fun getImageHolder(context: Context): ImageHolder {
|
||||||
return if (!image.isNullOrEmpty()) {
|
return if (!image.isNullOrEmpty()) {
|
||||||
try {
|
try {
|
||||||
ImageHolder(image ?: "")
|
ProfileImageHolder(image ?: "")
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
ImageHolder(R.drawable.profile, colorFromName(name))
|
ImageHolder(R.drawable.profile, colorFromName(name))
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,8 @@ class EventDetailsDialog(
|
|||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
fun onEventGetEvent(event: EventGetEvent) {
|
fun onEventGetEvent(event: EventGetEvent) {
|
||||||
EventBus.getDefault().removeStickyEvent(event)
|
EventBus.getDefault().removeStickyEvent(event)
|
||||||
|
if (event.event.homeworkBody == null)
|
||||||
|
event.event.homeworkBody = ""
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,5 +60,9 @@ class LabFragment : Fragment(), CoroutineScope {
|
|||||||
b.rodo.onClick {
|
b.rodo.onClick {
|
||||||
app.db.teacherDao().query(SimpleSQLiteQuery("UPDATE teachers SET teacherSurname = \"\" WHERE profileId = ${App.profileId}"))
|
app.db.teacherDao().query(SimpleSQLiteQuery("UPDATE teachers SET teacherSurname = \"\" WHERE profileId = ${App.profileId}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.removeHomework.onClick {
|
||||||
|
app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,9 @@ class SubjectViewHolder(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove previously added grades from year preview
|
||||||
|
if (b.yearContainer.childCount > 1)
|
||||||
|
b.yearContainer.removeViews(1, b.yearContainer.childCount - 1)
|
||||||
// add the yearly grades to summary container (expanded)
|
// add the yearly grades to summary container (expanded)
|
||||||
item.proposedGrade?.let {
|
item.proposedGrade?.let {
|
||||||
b.yearContainer.addView(GradeView(
|
b.yearContainer.addView(GradeView(
|
||||||
|
@ -85,6 +85,7 @@ class LoginChooserFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.devMode.visibility = if (App.debugMode) View.VISIBLE else View.GONE
|
b.devMode.visibility = if (App.debugMode) View.VISIBLE else View.GONE
|
||||||
|
b.devMode.isChecked = app.config.debugMode
|
||||||
b.devMode.onChange { v, isChecked ->
|
b.devMode.onChange { v, isChecked ->
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
MaterialDialog.Builder(activity)
|
MaterialDialog.Builder(activity)
|
||||||
@ -94,6 +95,7 @@ class LoginChooserFragment : Fragment() {
|
|||||||
.negativeText(R.string.no)
|
.negativeText(R.string.no)
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
app.config.debugMode = true
|
app.config.debugMode = true
|
||||||
|
App.devMode = true
|
||||||
MaterialAlertDialogBuilder(activity)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle("Restart")
|
.setTitle("Restart")
|
||||||
.setMessage("Wymagany restart aplikacji")
|
.setMessage("Wymagany restart aplikacji")
|
||||||
@ -104,12 +106,10 @@ class LoginChooserFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.show()
|
.show()
|
||||||
/*if (b.devModeLayout.getVisibility() !== View.VISIBLE) {
|
|
||||||
Anim.expand(b.devModeTitle, 500, null)
|
|
||||||
Anim.expand(b.devModeLayout, 500, null)
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
.onNegative { _: MaterialDialog?, _: DialogAction? ->
|
.onNegative { _: MaterialDialog?, _: DialogAction? ->
|
||||||
|
app.config.debugMode = false
|
||||||
|
App.devMode = false
|
||||||
b.devMode.isChecked = app.config.debugMode
|
b.devMode.isChecked = app.config.debugMode
|
||||||
b.devMode.jumpDrawablesToCurrentState()
|
b.devMode.jumpDrawablesToCurrentState()
|
||||||
Anim.collapse(b.devMode, 1000, null)
|
Anim.collapse(b.devMode, 1000, null)
|
||||||
@ -117,6 +117,7 @@ class LoginChooserFragment : Fragment() {
|
|||||||
.show()
|
.show()
|
||||||
} else {
|
} else {
|
||||||
app.config.debugMode = false
|
app.config.debugMode = false
|
||||||
|
App.devMode = false
|
||||||
/*if (b.devModeLayout.getVisibility() === View.VISIBLE) {
|
/*if (b.devModeLayout.getVisibility() === View.VISIBLE) {
|
||||||
Anim.collapse(b.devModeTitle, 500, null)
|
Anim.collapse(b.devModeTitle, 500, null)
|
||||||
Anim.collapse(b.devModeLayout, 500, null)
|
Anim.collapse(b.devModeLayout, 500, null)
|
||||||
|
@ -108,6 +108,10 @@ class MessageFragment : Fragment(), CoroutineScope {
|
|||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
b.downloadButton.isVisible = App.debugMode
|
||||||
|
b.downloadButton.onClick {
|
||||||
|
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||||
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
|
|
||||||
@ -182,14 +186,16 @@ class MessageFragment : Fragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val readByAll = checkRecipients()
|
||||||
// if a sent msg is not read by everyone, download it again to check the read status
|
if (app.profile.loginStoreType == LoginStore.LOGIN_TYPE_VULCAN) {
|
||||||
if (!checkRecipients() && app.profile.loginStoreType != LoginStore.LOGIN_TYPE_VULCAN) {
|
// vulcan: change message status or download attachments
|
||||||
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
if (message.type == TYPE_RECEIVED && !message.seen || message.attachmentIds == null) {
|
||||||
return
|
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (!readByAll) {
|
||||||
if(message.type == TYPE_RECEIVED && !message.seen && app.profile.loginStoreType == LoginStore.LOGIN_TYPE_VULCAN) {
|
// if a sent msg is not read by everyone, download it again to check the read status
|
||||||
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog;
|
|||||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog;
|
import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog;
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog;
|
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog;
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.sync.NotificationFilterDialog;
|
import pl.szczodrzynski.edziennik.ui.dialogs.sync.NotificationFilterDialog;
|
||||||
|
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity;
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
import pl.szczodrzynski.edziennik.utils.Utils;
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||||
@ -161,7 +162,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
|
|
||||||
profileCardTitleItem = new MaterialAboutProfileItem(
|
profileCardTitleItem = new MaterialAboutProfileItem(
|
||||||
app.getProfile().getName(),
|
app.getProfile().getName(),
|
||||||
getString(R.string.settings_profile_subtitle_format, app.getProfile().getSubname()),
|
app.getProfile().getSubname(),
|
||||||
getProfileDrawable()
|
getProfileDrawable()
|
||||||
);
|
);
|
||||||
profileCardTitleItem.setOnClickAction(() -> {
|
profileCardTitleItem.setOnClickAction(() -> {
|
||||||
@ -218,6 +219,20 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
})
|
})
|
||||||
);*/
|
);*/
|
||||||
|
|
||||||
|
items.add(
|
||||||
|
new MaterialAboutActionItem(
|
||||||
|
getString(R.string.settings_add_student_text),
|
||||||
|
getString(R.string.settings_add_student_subtext),
|
||||||
|
new IconicsDrawable(activity)
|
||||||
|
.icon(CommunityMaterial.Icon.cmd_account_plus_outline)
|
||||||
|
.size(IconicsSize.dp(iconSizeDp))
|
||||||
|
.color(IconicsColor.colorInt(iconColor))
|
||||||
|
)
|
||||||
|
.setOnClickAction(() -> {
|
||||||
|
startActivity(new Intent(activity, LoginActivity.class));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
new MaterialAboutActionItem(
|
new MaterialAboutActionItem(
|
||||||
getString(R.string.settings_profile_notifications_text),
|
getString(R.string.settings_profile_notifications_text),
|
||||||
@ -232,6 +247,20 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
items.add(
|
||||||
|
new MaterialAboutActionItem(
|
||||||
|
getString(R.string.settings_profile_remove_text),
|
||||||
|
getString(R.string.settings_profile_remove_subtext),
|
||||||
|
new IconicsDrawable(activity)
|
||||||
|
.icon(SzkolnyFont.Icon.szf_delete_empty_outline)
|
||||||
|
.size(IconicsSize.dp(iconSizeDp))
|
||||||
|
.color(IconicsColor.colorInt(iconColor))
|
||||||
|
)
|
||||||
|
.setOnClickAction(() -> {
|
||||||
|
new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
items.add(getMoreItem(() -> addCardItems(CARD_PROFILE, getProfileCard(true))));
|
items.add(getMoreItem(() -> addCardItems(CARD_PROFILE, getProfileCard(true))));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -253,20 +282,6 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
items.add(
|
|
||||||
new MaterialAboutActionItem(
|
|
||||||
getString(R.string.settings_profile_remove_text),
|
|
||||||
getString(R.string.settings_profile_remove_subtext),
|
|
||||||
new IconicsDrawable(activity)
|
|
||||||
.icon(SzkolnyFont.Icon.szf_delete_empty_outline)
|
|
||||||
.size(IconicsSize.dp(iconSizeDp))
|
|
||||||
.color(IconicsColor.colorInt(iconColor))
|
|
||||||
)
|
|
||||||
.setOnClickAction(() -> {
|
|
||||||
new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName());
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@ -58,8 +58,9 @@ class AttachmentAdapter(
|
|||||||
val item = items[position]
|
val item = items[position]
|
||||||
val b = holder.b
|
val b = holder.b
|
||||||
|
|
||||||
|
val fileName = item.name.substringBefore(":http")
|
||||||
// create an icon for the attachment
|
// create an icon for the attachment
|
||||||
val icon: IIcon = when (Utils.getExtensionFromFileName(item.name)) {
|
val icon: IIcon = when (Utils.getExtensionFromFileName(fileName)) {
|
||||||
"doc", "docx", "odt", "rtf" -> SzkolnyFont.Icon.szf_file_word_outline
|
"doc", "docx", "odt", "rtf" -> SzkolnyFont.Icon.szf_file_word_outline
|
||||||
"xls", "xlsx", "ods" -> SzkolnyFont.Icon.szf_file_excel_outline
|
"xls", "xlsx", "ods" -> SzkolnyFont.Icon.szf_file_excel_outline
|
||||||
"ppt", "pptx", "odp" -> SzkolnyFont.Icon.szf_file_powerpoint_outline
|
"ppt", "pptx", "odp" -> SzkolnyFont.Icon.szf_file_powerpoint_outline
|
||||||
@ -73,12 +74,12 @@ class AttachmentAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.chip.text = if (item.isDownloading) {
|
b.chip.text = if (item.isDownloading) {
|
||||||
app.getString(R.string.messages_attachment_downloading_format, item.name, item.downloadProgress)
|
app.getString(R.string.messages_attachment_downloading_format, fileName, item.downloadProgress)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
item.size?.let {
|
item.size?.let {
|
||||||
app.getString(R.string.messages_attachment_format, item.name, Utils.readableFileSize(it))
|
app.getString(R.string.messages_attachment_format, fileName, Utils.readableFileSize(it))
|
||||||
} ?: item.name
|
} ?: fileName
|
||||||
}
|
}
|
||||||
|
|
||||||
b.chip.chipIcon = IconicsDrawable(context)
|
b.chip.chipIcon = IconicsDrawable(context)
|
||||||
|
@ -8,12 +8,14 @@ import android.content.Context
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||||
@ -41,6 +43,8 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun init(arguments: Bundle, owner: Any) {
|
fun init(arguments: Bundle, owner: Any) {
|
||||||
|
val app = context.applicationContext as App
|
||||||
|
val activity = context as? AppCompatActivity ?: return
|
||||||
val list = this as? RecyclerView ?: return
|
val list = this as? RecyclerView ?: return
|
||||||
|
|
||||||
val profileId = arguments.get<Int>("profileId") ?: return
|
val profileId = arguments.get<Int>("profileId") ?: return
|
||||||
@ -49,12 +53,16 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
val attachmentSizes = arguments.getLongArray("attachmentSizes")
|
val attachmentSizes = arguments.getLongArray("attachmentSizes")
|
||||||
|
|
||||||
val adapter = AttachmentAdapter(context, onAttachmentClick = { item ->
|
val adapter = AttachmentAdapter(context, onAttachmentClick = { item ->
|
||||||
downloadAttachment(item)
|
app.permissionManager.requestStoragePermission(activity, R.string.permissions_attachment) {
|
||||||
|
downloadAttachment(item)
|
||||||
|
}
|
||||||
}, onAttachmentLongClick = { chip, item ->
|
}, onAttachmentLongClick = { chip, item ->
|
||||||
val popupMenu = PopupMenu(chip.context, chip)
|
val popupMenu = PopupMenu(chip.context, chip)
|
||||||
popupMenu.menu.add(0, 1, 0, R.string.messages_attachment_download_again)
|
popupMenu.menu.add(0, 1, 0, R.string.messages_attachment_download_again)
|
||||||
popupMenu.setOnMenuItemClickListener {
|
popupMenu.setOnMenuItemClickListener {
|
||||||
downloadAttachment(item, forceDownload = true)
|
app.permissionManager.requestStoragePermission(activity, R.string.permissions_attachment) {
|
||||||
|
downloadAttachment(item, forceDownload = true)
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
popupMenu.show()
|
popupMenu.show()
|
||||||
@ -86,7 +94,20 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
try {
|
try {
|
||||||
val attachmentFileName = Utils.getStringFromFile(attachmentDataFile)
|
val attachmentFileName = Utils.getStringFromFile(attachmentDataFile)
|
||||||
val attachmentFile = File(attachmentFileName)
|
val attachmentFile = File(attachmentFileName)
|
||||||
attachmentFile.exists()
|
// get the correct file name and update
|
||||||
|
if (attachmentFile.exists()) {
|
||||||
|
|
||||||
|
// get the download url before updating file name
|
||||||
|
val fileUrl = item.name.substringAfter(":", missingDelimiterValue = "")
|
||||||
|
// update file name with the downloaded one
|
||||||
|
item.name = attachmentFile.name
|
||||||
|
// save the download url back
|
||||||
|
if (fileUrl != "")
|
||||||
|
item.name += ":$fileUrl"
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else false
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
false
|
false
|
||||||
@ -97,7 +118,8 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
|
|
||||||
private fun downloadAttachment(attachment: AttachmentAdapter.Item, forceDownload: Boolean = false) {
|
private fun downloadAttachment(attachment: AttachmentAdapter.Item, forceDownload: Boolean = false) {
|
||||||
if (!forceDownload && attachment.isDownloaded) {
|
if (!forceDownload && attachment.isDownloaded) {
|
||||||
Utils.openFile(context, File(Utils.getStorageDir(), attachment.name))
|
// open file by name, or first part before ':' (Vulcan OneDrive)
|
||||||
|
Utils.openFile(context, File(Utils.getStorageDir(), attachment.name.substringBefore(":")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,17 +150,19 @@ class AttachmentsView @JvmOverloads constructor(
|
|||||||
when (event.eventType) {
|
when (event.eventType) {
|
||||||
AttachmentGetEvent.TYPE_FINISHED -> {
|
AttachmentGetEvent.TYPE_FINISHED -> {
|
||||||
// save the downloaded file name
|
// save the downloaded file name
|
||||||
attachment.downloadedName = event.fileName
|
|
||||||
attachment.isDownloading = false
|
attachment.isDownloading = false
|
||||||
attachment.isDownloaded = true
|
attachment.isDownloaded = true
|
||||||
|
|
||||||
// update file name for iDziennik which
|
// get the download url before updating file name
|
||||||
// does not provide the name before downloading
|
val fileUrl = attachment.name.substringAfter(":", missingDelimiterValue = "")
|
||||||
if (!attachment.name.contains("."))
|
// update file name with the downloaded one
|
||||||
attachment.name = File(attachment.downloadedName).name
|
attachment.name = File(event.fileName).name
|
||||||
|
// save the download url back
|
||||||
|
if (fileUrl != "")
|
||||||
|
attachment.name += ":$fileUrl"
|
||||||
|
|
||||||
// open the file
|
// open the file
|
||||||
Utils.openFile(context, File(Utils.getStorageDir(), attachment.name))
|
Utils.openFile(context, File(event.fileName))
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachmentGetEvent.TYPE_PROGRESS -> {
|
AttachmentGetEvent.TYPE_PROGRESS -> {
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-4-7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.utils
|
||||||
|
|
||||||
|
import android.widget.ImageView
|
||||||
|
import pl.szczodrzynski.navlib.ImageHolder
|
||||||
|
|
||||||
|
class ProfileImageHolder(url: String) : ImageHolder(url) {
|
||||||
|
|
||||||
|
override fun applyTo(imageView: ImageView, tag: String?): Boolean {
|
||||||
|
return try {
|
||||||
|
super.applyTo(imageView, tag)
|
||||||
|
} catch (_: Exception) { false }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2020-4-7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.utils.managers
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.qifan.powerpermission.coroutines.awaitAskPermissions
|
||||||
|
import com.qifan.powerpermission.data.hasAllGranted
|
||||||
|
import com.qifan.powerpermission.data.hasPermanentDenied
|
||||||
|
import com.qifan.powerpermission.data.hasRational
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.R
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
class PermissionManager(val app: App) : CoroutineScope {
|
||||||
|
|
||||||
|
private val job = Job()
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Main
|
||||||
|
|
||||||
|
private fun isStoragePermissionGranted() = if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
app.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestStoragePermission(
|
||||||
|
activity: AppCompatActivity,
|
||||||
|
@StringRes permissionMessage: Int,
|
||||||
|
onSuccess: suspend CoroutineScope.() -> Unit
|
||||||
|
) {
|
||||||
|
launch {
|
||||||
|
if (isStoragePermissionGranted()) {
|
||||||
|
onSuccess()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
val result = activity.awaitAskPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
when {
|
||||||
|
result.hasAllGranted() -> onSuccess()
|
||||||
|
result.hasRational() -> {
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.permissions_required)
|
||||||
|
.setMessage(permissionMessage)
|
||||||
|
.setPositiveButton(R.string.ok) { _, _ ->
|
||||||
|
requestStoragePermission(activity, permissionMessage, onSuccess)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
result.hasPermanentDenied() -> {
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.permissions_required)
|
||||||
|
.setMessage(R.string.permissions_denied)
|
||||||
|
.setPositiveButton(R.string.ok) { _, _ ->
|
||||||
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||||
|
val uri = Uri.fromParts("package", app.packageName, null)
|
||||||
|
intent.data = uri
|
||||||
|
activity.startActivity(intent)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,13 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Duh rodo button"
|
android:text="Duh rodo button"
|
||||||
android:textAllCaps="false" />
|
android:textAllCaps="false" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/removeHomework"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Remove all homework body (null)"
|
||||||
|
android:textAllCaps="false" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -295,6 +295,39 @@
|
|||||||
android:textAppearance="@style/NavView.TextView.Small" />
|
android:textAppearance="@style/NavView.TextView.Small" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/downloadButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_rounded_ripple"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
|
<com.mikepenz.iconics.view.IconicsImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:padding="4dp"
|
||||||
|
app:iiv_color="?android:textColorSecondary"
|
||||||
|
app:iiv_icon="cmd-download-outline"
|
||||||
|
tools:srcCompat="@android:drawable/ic_menu_delete" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Pobierz ponownie"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Small" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -128,6 +128,7 @@
|
|||||||
<string name="error_340" translatable="false">ERROR_VULCAN_API_MAINTENANCE</string>
|
<string name="error_340" translatable="false">ERROR_VULCAN_API_MAINTENANCE</string>
|
||||||
<string name="error_341" translatable="false">ERROR_VULCAN_API_BAD_REQUEST</string>
|
<string name="error_341" translatable="false">ERROR_VULCAN_API_BAD_REQUEST</string>
|
||||||
<string name="error_342" translatable="false">ERROR_VULCAN_API_OTHER</string>
|
<string name="error_342" translatable="false">ERROR_VULCAN_API_OTHER</string>
|
||||||
|
<string name="error_343" translatable="false">ERROR_VULCAN_ATTACHMENT_DOWNLOAD</string>
|
||||||
|
|
||||||
<string name="error_401" translatable="false">ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN</string>
|
<string name="error_401" translatable="false">ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN</string>
|
||||||
<string name="error_402" translatable="false">ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME</string>
|
<string name="error_402" translatable="false">ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME</string>
|
||||||
@ -177,6 +178,7 @@
|
|||||||
<string name="error_914" translatable="false">EXCEPTION_IDZIENNIK_API_REQUEST</string>
|
<string name="error_914" translatable="false">EXCEPTION_IDZIENNIK_API_REQUEST</string>
|
||||||
<string name="error_920" translatable="false">EXCEPTION_EDUDZIENNIK_WEB_REQUEST</string>
|
<string name="error_920" translatable="false">EXCEPTION_EDUDZIENNIK_WEB_REQUEST</string>
|
||||||
<string name="error_921" translatable="false">EXCEPTION_EDUDZIENNIK_FILE_REQUEST</string>
|
<string name="error_921" translatable="false">EXCEPTION_EDUDZIENNIK_FILE_REQUEST</string>
|
||||||
|
<string name="error_930" translatable="false">ERROR_ONEDRIVE_DOWNLOAD</string>
|
||||||
|
|
||||||
<string name="error_1201" translatable="false">LOGIN_NO_ARGUMENTS</string>
|
<string name="error_1201" translatable="false">LOGIN_NO_ARGUMENTS</string>
|
||||||
|
|
||||||
@ -246,7 +248,7 @@
|
|||||||
<string name="error_157_reason">Brak ID sesji Wiadomości</string>
|
<string name="error_157_reason">Brak ID sesji Wiadomości</string>
|
||||||
<string name="error_158_reason">Odmowa dostępu do Portalu Librus</string>
|
<string name="error_158_reason">Odmowa dostępu do Portalu Librus</string>
|
||||||
<string name="error_159_reason">API Portalu Librus wyłączone</string>
|
<string name="error_159_reason">API Portalu Librus wyłączone</string>
|
||||||
<string name="error_160_reason">Konto Synergia zostało rozłączone</string>
|
<string name="error_160_reason">Konto LIBRUS utraciło połączenie z kontem Synergia. Zaloguj się na stronie portal.librus.pl lub w oficjalnej aplikacji Librus i postępuj zgodnie z instrukcją, aby naprawić konto.</string>
|
||||||
<string name="error_161_reason">Inny błąd Portalu Librus</string>
|
<string name="error_161_reason">Inny błąd Portalu Librus</string>
|
||||||
<string name="error_162_reason">Nie znaleziono konta Synergia. Zaloguj się na stronie portal.librus.pl, a następnie powiąż swoje konto Synergia do konta Librus Portal.</string>
|
<string name="error_162_reason">Nie znaleziono konta Synergia. Zaloguj się na stronie portal.librus.pl, a następnie powiąż swoje konto Synergia do konta Librus Portal.</string>
|
||||||
<string name="error_163_reason">Inny błąd logowania do Portalu Librus</string>
|
<string name="error_163_reason">Inny błąd logowania do Portalu Librus</string>
|
||||||
@ -304,6 +306,7 @@
|
|||||||
<string name="error_340_reason">Vulcan: przerwa techniczna</string>
|
<string name="error_340_reason">Vulcan: przerwa techniczna</string>
|
||||||
<string name="error_341_reason">Vulcan: błąd żądania, zgłoś błąd</string>
|
<string name="error_341_reason">Vulcan: błąd żądania, zgłoś błąd</string>
|
||||||
<string name="error_342_reason">Vulcan: inny błąd, wyślij zgłoszenie</string>
|
<string name="error_342_reason">Vulcan: inny błąd, wyślij zgłoszenie</string>
|
||||||
|
<string name="error_343_reason">Vulcan: nie znaleziono adresu załącznika</string>
|
||||||
|
|
||||||
<string name="error_401_reason">Nieprawidłowe dane logowania</string>
|
<string name="error_401_reason">Nieprawidłowe dane logowania</string>
|
||||||
<string name="error_402_reason">Nieprawidłowa nazwa szkoły</string>
|
<string name="error_402_reason">Nieprawidłowa nazwa szkoły</string>
|
||||||
@ -353,6 +356,7 @@
|
|||||||
<string name="error_914_reason">EXCEPTION_IDZIENNIK_API_REQUEST</string>
|
<string name="error_914_reason">EXCEPTION_IDZIENNIK_API_REQUEST</string>
|
||||||
<string name="error_920_reason">Wystąpił błąd</string>
|
<string name="error_920_reason">Wystąpił błąd</string>
|
||||||
<string name="error_921_reason">Wystąpił błąd podczas pobierania pliku</string>
|
<string name="error_921_reason">Wystąpił błąd podczas pobierania pliku</string>
|
||||||
|
<string name="error_930_reason">Nie udało się pobrać pliku z OneDrive</string>
|
||||||
|
|
||||||
<string name="error_1201_reason">Nie podano parametrów</string>
|
<string name="error_1201_reason">Nie podano parametrów</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,8 +5,8 @@ buildscript {
|
|||||||
kotlin_version = '1.3.61'
|
kotlin_version = '1.3.61'
|
||||||
|
|
||||||
release = [
|
release = [
|
||||||
versionName: "4.0-rc.5",
|
versionName: "4.0",
|
||||||
versionCode: 4000059
|
versionCode: 4000099
|
||||||
]
|
]
|
||||||
|
|
||||||
setup = [
|
setup = [
|
||||||
@ -87,6 +87,7 @@ allprojects {
|
|||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
maven { url "https://kotlin.bintray.com/kotlinx/" }
|
maven { url "https://kotlin.bintray.com/kotlinx/" }
|
||||||
maven { url "https://dl.bintray.com/wulkanowy/wulkanowy" }
|
maven { url "https://dl.bintray.com/wulkanowy/wulkanowy" }
|
||||||
|
maven { url "https://dl.bintray.com/undervoid/PowerPermission" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
import im.wangchao.mhttp.AbsCallbackHandler;
|
||||||
import im.wangchao.mhttp.Accept;
|
import im.wangchao.mhttp.Accept;
|
||||||
@ -69,7 +70,11 @@ public class FileCallbackHandler extends AbsCallbackHandler<File> {
|
|||||||
if (this.file.isDirectory()) {
|
if (this.file.isDirectory()) {
|
||||||
String contentDisposition = response.header("content-disposition");
|
String contentDisposition = response.header("content-disposition");
|
||||||
if (contentDisposition != null) {
|
if (contentDisposition != null) {
|
||||||
String filename = contentDisposition.substring(contentDisposition.indexOf("\"")+1, contentDisposition.lastIndexOf("\""));
|
if (contentDisposition.contains("*=UTF-8")) {
|
||||||
|
contentDisposition = contentDisposition.replace("*=UTF-8''", "\"") + "\"";
|
||||||
|
contentDisposition = URLDecoder.decode(contentDisposition, "UTF-8");
|
||||||
|
}
|
||||||
|
String filename = contentDisposition.substring(contentDisposition.indexOf("\"") + 1, contentDisposition.lastIndexOf("\""));
|
||||||
this.file = new File(file, filename);
|
this.file = new File(file, filename);
|
||||||
file = this.file;
|
file = this.file;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user