From 867c8920a822c3c6485131b89ad516445870a6f0 Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Sun, 24 Nov 2019 20:54:15 +0100 Subject: [PATCH] [APIv2/Messages] Add downloading attachments. --- .../szczodrzynski/edziennik/api/v2/Errors.kt | 1 + .../szczodrzynski/edziennik/api/v2/Regexes.kt | 6 + .../api/v2/events/AttachmentGetEvent.kt | 14 ++ .../api/v2/events/task/EdziennikTask.kt | 9 +- .../edziennik/api/v2/idziennik/Idziennik.kt | 4 + .../api/v2/interfaces/EdziennikInterface.kt | 1 + .../edziennik/api/v2/librus/Librus.kt | 42 ++++-- .../api/v2/librus/data/LibrusMessages.kt | 95 ++++++++++++++ .../messages/LibrusMessagesGetAttachment.kt | 123 ++++++++++++++++++ .../api/v2/mobidziennik/Mobidziennik.kt | 4 + .../edziennik/api/v2/template/Template.kt | 4 + .../edziennik/api/v2/vulcan/Vulcan.kt | 4 + .../ui/modules/messages/MessageFragment.kt | 83 ++++++++++-- app/src/main/res/values/strings.xml | 2 +- 14 files changed, 361 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/AttachmentGetEvent.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/messages/LibrusMessagesGetAttachment.kt diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt index 79523069..c6a2a35a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt @@ -48,6 +48,7 @@ const val ERROR_PROFILE_MISSING = 105 const val ERROR_INVALID_LOGIN_MODE = 110 const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111 const val ERROR_NOT_IMPLEMENTED = 112 +const val ERROR_FILE_DOWNLOAD = 113 const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Regexes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Regexes.kt index 3bc7f005..b6039a46 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Regexes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Regexes.kt @@ -76,4 +76,10 @@ object Regexes { val VULCAN_SHITFT_ANNOTATION by lazy { """\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex() } + + + + val LIBRUS_ATTACHMENT_KEY by lazy { + """singleUseKey=([0-9A-f_]+)""".toRegex() + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/AttachmentGetEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/AttachmentGetEvent.kt new file mode 100644 index 00000000..cc17291b --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/AttachmentGetEvent.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2019-11-24 + */ + +package pl.szczodrzynski.edziennik.api.v2.events + +data class AttachmentGetEvent(val profileId: Int, val messageId: Long, val attachmentId: Long, + var eventType: Int = TYPE_PROGRESS, val fileName: String? = null, + val bytesWritten: Long = 0) { + companion object { + const val TYPE_PROGRESS = 0 + const val TYPE_FINISHED = 1 + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/task/EdziennikTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/task/EdziennikTask.kt index fa2d513f..9fd44537 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/task/EdziennikTask.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/events/task/EdziennikTask.kt @@ -24,6 +24,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa fun syncProfileList(profileList: List) = EdziennikTask(-1, SyncProfileListRequest(profileList)) fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message)) fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest()) + fun attachmentGet(profileId: Int, messageId: Long, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(messageId, attachmentId, attachmentName)) } private lateinit var loginStore: LoginStore @@ -35,8 +36,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa loginStore = request.loginStore // save the profile ID and name as the current task's taskName = app.getString(R.string.edziennik_notification_api_first_login_title) - } - else { + } else { // get the requested profile and login store val profile = app.db.profileDao().getByIdNow(profileId) this.profile = profile @@ -67,12 +67,14 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa when (request) { is SyncProfileRequest -> edziennikInterface?.sync( - featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) } ?: Features.getAllIds(), + featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) } + ?: Features.getAllIds(), viewId = request.viewIds?.get(0)?.first, arguments = request.arguments) is MessageGetRequest -> edziennikInterface?.getMessage(request.message) is FirstLoginRequest -> edziennikInterface?.firstLogin() is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead() + is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.messageId, request.attachmentId, request.attachmentName) } } @@ -90,4 +92,5 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa data class SyncProfileListRequest(val profileList: List) data class MessageGetRequest(val message: MessageFull) class AnnouncementsReadRequest + data class AttachmentGetRequest(val messageId: Long, val attachmentId: Long, val attachmentName: String) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/idziennik/Idziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/idziennik/Idziennik.kt index 610ae53e..53361e28 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/idziennik/Idziennik.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/idziennik/Idziennik.kt @@ -70,6 +70,10 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, } + override fun getAttachment(messageId: Long, attachmentId: Long, attachmentName: String) { + + } + override fun firstLogin() { IdziennikFirstLogin(data) { completed() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/interfaces/EdziennikInterface.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/interfaces/EdziennikInterface.kt index 855767f1..3f8a0373 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/interfaces/EdziennikInterface.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/interfaces/EdziennikInterface.kt @@ -11,6 +11,7 @@ interface EdziennikInterface { fun sync(featureIds: List, viewId: Int? = null, arguments: JsonObject? = null) fun getMessage(message: MessageFull) fun markAllAnnouncementsAsRead() + fun getAttachment(messageId: Long, attachmentId: Long, attachmentName: String) fun firstLogin() fun cancel() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/Librus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/Librus.kt index 626a4a33..8f281480 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/Librus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/Librus.kt @@ -10,13 +10,11 @@ import pl.szczodrzynski.edziennik.api.v2.* import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusData +import pl.szczodrzynski.edziennik.api.v2.librus.data.messages.LibrusMessagesGetAttachment import pl.szczodrzynski.edziennik.api.v2.librus.data.messages.LibrusMessagesGetMessage import pl.szczodrzynski.edziennik.api.v2.librus.data.synergia.LibrusSynergiaMarkAllAnnouncementsAsRead import pl.szczodrzynski.edziennik.api.v2.librus.firstlogin.LibrusFirstLogin -import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLogin -import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginApi -import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginMessages -import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLoginSynergia +import pl.szczodrzynski.edziennik.api.v2.librus.login.* import pl.szczodrzynski.edziennik.api.v2.models.ApiError import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull @@ -82,11 +80,13 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va } override fun getMessage(message: MessageFull) { - LibrusLoginApi(data) { - LibrusLoginSynergia(data) { - LibrusLoginMessages(data) { - LibrusMessagesGetMessage(data, message) { - completed() + LibrusLoginPortal(data) { + LibrusLoginApi(data) { + LibrusLoginSynergia(data) { + LibrusLoginMessages(data) { + LibrusMessagesGetMessage(data, message) { + completed() + } } } } @@ -94,10 +94,26 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va } override fun markAllAnnouncementsAsRead() { - LibrusLoginApi(data) { - LibrusLoginSynergia(data) { - LibrusSynergiaMarkAllAnnouncementsAsRead(data) { - completed() + LibrusLoginPortal(data) { + LibrusLoginApi(data) { + LibrusLoginSynergia(data) { + LibrusSynergiaMarkAllAnnouncementsAsRead(data) { + completed() + } + } + } + } + } + + override fun getAttachment(messageId: Long, attachmentId: Long, attachmentName: String) { + LibrusLoginPortal(data) { + LibrusLoginApi(data) { + LibrusLoginSynergia(data) { + LibrusLoginMessages(data) { + LibrusMessagesGetAttachment(data, messageId, attachmentId, attachmentName) { + completed() + } + } } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusMessages.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusMessages.kt index 7de22502..60bb1b67 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusMessages.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusMessages.kt @@ -4,9 +4,12 @@ package pl.szczodrzynski.edziennik.api.v2.librus.data +import com.google.gson.JsonObject import im.wangchao.mhttp.Request import im.wangchao.mhttp.Response import im.wangchao.mhttp.body.MediaTypeUtils +import im.wangchao.mhttp.callback.FileCallbackHandler +import im.wangchao.mhttp.callback.JsonCallbackHandler import im.wangchao.mhttp.callback.TextCallbackHandler import okhttp3.Cookie import org.jsoup.Jsoup @@ -16,6 +19,7 @@ import pl.szczodrzynski.edziennik.api.v2.* import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus import pl.szczodrzynski.edziennik.api.v2.models.ApiError import pl.szczodrzynski.edziennik.utils.Utils.d +import java.io.File import java.io.StringWriter import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.OutputKeys @@ -131,4 +135,95 @@ open class LibrusMessages(open val data: DataLibrus) { .build() .enqueue() } + + fun sandboxGet(tag: String, action: String, parameters: Map? = null, + onSuccess: (json: JsonObject) -> Unit) { + + d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action") + + val callback = object : JsonCallbackHandler() { + override fun onSuccess(json: JsonObject?, response: Response?) { + if (json == null) { + data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY) + .withResponse(response)) + return + } + + try { + onSuccess(json) + } catch (e: Exception) { + data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST) + .withResponse(response) + .withThrowable(e) + .withApiResponse(json)) + } + } + + override fun onFailure(response: Response?, throwable: Throwable?) { + data.error(ApiError(tag, ERROR_REQUEST_FAILURE) + .withResponse(response) + .withThrowable(throwable)) + } + } + + Request.builder() + .url("$LIBRUS_SANDBOX_URL$action") + .userAgent(SYNERGIA_USER_AGENT) + .apply { + parameters?.forEach { (k, v) -> + addParameter(k, v) + } + } + .post() + .callback(callback) + .build() + .enqueue() + } + + fun sandboxGetFile(tag: String, action: String, targetFile: File, onSuccess: (file: File) -> Unit, + onProgress: (written: Long, total: Long) -> Unit) { + + d(tag, "Request: Librus/Messages - $LIBRUS_SANDBOX_URL$action") + + val callback = object : FileCallbackHandler(targetFile) { + override fun onSuccess(file: File?, response: Response?) { + if (file == null) { + data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD) + .withResponse(response)) + return + } + + try { + onSuccess(file) + } catch (e: Exception) { + data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST) + .withResponse(response) + .withThrowable(e)) + } + } + + override fun onProgress(bytesWritten: Long, bytesTotal: Long) { + try { + onProgress(bytesWritten, bytesTotal) + } catch (e: Exception) { + data.error(ApiError(tag, EXCEPTION_LIBRUS_MESSAGES_REQUEST) + .withThrowable(e)) + } + } + + override fun onFailure(response: Response?, throwable: Throwable?) { + data.error(ApiError(tag, ERROR_REQUEST_FAILURE) + .withResponse(response) + .withThrowable(throwable)) + } + } + + Request.builder() + .url("$LIBRUS_SANDBOX_URL$action") + .userAgent(SYNERGIA_USER_AGENT) + .post() + .callback(callback) + .build() + .enqueue() + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/messages/LibrusMessagesGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/messages/LibrusMessagesGetAttachment.kt new file mode 100644 index 00000000..c1a54773 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/messages/LibrusMessagesGetAttachment.kt @@ -0,0 +1,123 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2019-11-24 + */ + +package pl.szczodrzynski.edziennik.api.v2.librus.data.messages + +import kotlinx.coroutines.* +import org.greenrobot.eventbus.EventBus +import pl.szczodrzynski.edziennik.api.v2.ERROR_FILE_DOWNLOAD +import pl.szczodrzynski.edziennik.api.v2.EXCEPTION_LIBRUS_MESSAGES_REQUEST +import pl.szczodrzynski.edziennik.api.v2.Regexes +import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent +import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent.Companion.TYPE_FINISHED +import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent.Companion.TYPE_PROGRESS +import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus +import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusMessages +import pl.szczodrzynski.edziennik.api.v2.models.ApiError +import pl.szczodrzynski.edziennik.get +import pl.szczodrzynski.edziennik.getString +import pl.szczodrzynski.edziennik.utils.Utils +import java.io.File +import kotlin.coroutines.CoroutineContext + + +class LibrusMessagesGetAttachment(override val data: DataLibrus, val messageId: Long, val attachmentId: Long, + val attachmentName: String, val onSuccess: () -> Unit) : LibrusMessages(data), CoroutineScope { + companion object { + const val TAG = "LibrusMessagesGetAttachment" + } + + private var job = Job() + + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Default + + private var getAttachmentCheckKeyTries = 0 + + init { + messagesGet(TAG, "GetFileDownloadLink", parameters = mapOf( + "fileId" to attachmentId, + "msgId" to messageId, + "archive" to 0 + )) { doc -> + val downloadLink = doc.select("response GetFileDownloadLink downloadLink").text() + val keyMatcher = Regexes.LIBRUS_ATTACHMENT_KEY.find(downloadLink) + + if (keyMatcher != null) { + getAttachmentCheckKeyTries = 0 + + val attachmentKey = keyMatcher[1] + getAttachmentCheckKey(attachmentKey) { + downloadAttachment(attachmentKey) + } + } else { + data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD) + .withApiResponse(doc.toString())) + } + + onSuccess() + } + } + + private fun getAttachmentCheckKey(attachmentKey: String, callback: () -> Unit) { + sandboxGet(TAG, "CSCheckKey", + parameters = mapOf("singleUseKey" to attachmentKey)) { json -> + + when (json.getString("status")) { + "not_downloaded_yet" -> { + if (getAttachmentCheckKeyTries++ > 5) { + data.error(ApiError(TAG, ERROR_FILE_DOWNLOAD) + .withApiResponse(json)) + return@sandboxGet + } + launch { + delay(2000) + getAttachmentCheckKey(attachmentKey, callback) + } + } + + "ready" -> { + launch { callback() } + } + + else -> { + data.error(ApiError(TAG, EXCEPTION_LIBRUS_MESSAGES_REQUEST) + .withApiResponse(json)) + } + } + } + } + + private fun downloadAttachment(attachmentKey: String) { + val targetFile = File(Utils.getStorageDir(), attachmentName) + + sandboxGetFile(TAG, "CSDownload&singleUseKey=$attachmentKey", + targetFile, { file -> + + val event = AttachmentGetEvent( + profileId, + messageId, + attachmentId, + TYPE_FINISHED, + file.absolutePath + ) + + val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}") + Utils.writeStringToFile(attachmentDataFile, event.fileName) + + EventBus.getDefault().post(event) + + }) { written, _ -> + val event = AttachmentGetEvent( + profileId, + messageId, + attachmentId, + TYPE_PROGRESS, + bytesWritten = written + ) + + EventBus.getDefault().post(event) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/mobidziennik/Mobidziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/mobidziennik/Mobidziennik.kt index 21a136a8..9e04dc72 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/mobidziennik/Mobidziennik.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/mobidziennik/Mobidziennik.kt @@ -76,6 +76,10 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto } + override fun getAttachment(messageId: Long, attachmentId: Long, attachmentName: String) { + + } + override fun firstLogin() { MobidziennikFirstLogin(data) { completed() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/template/Template.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/template/Template.kt index 3b4c750c..508fe8f7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/template/Template.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/template/Template.kt @@ -70,6 +70,10 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore, } + override fun getAttachment(messageId: Long, attachmentId: Long, attachmentName: String) { + + } + override fun firstLogin() { TemplateFirstLogin(data) { completed() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/Vulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/Vulcan.kt index b812fca8..36efeda8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/Vulcan.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/Vulcan.kt @@ -76,6 +76,10 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va } + override fun getAttachment(messageId: Long, attachmentId: Long, attachmentName: String) { + + } + override fun firstLogin() { VulcanFirstLogin(data) { completed() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt index 1f0e4849..75eb21a3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt @@ -31,6 +31,9 @@ import org.greenrobot.eventbus.ThreadMode import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent +import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent.Companion.TYPE_FINISHED +import pl.szczodrzynski.edziennik.api.v2.events.AttachmentGetEvent.Companion.TYPE_PROGRESS import pl.szczodrzynski.edziennik.api.v2.events.MessageGetEvent import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT @@ -225,18 +228,17 @@ class MessageFragment : Fragment(), CoroutineScope { attachmentChip.ellipsize = TextUtils.TruncateAt.MIDDLE // create an icon for the attachment - var icon: IIcon = CommunityMaterial.Icon.cmd_file_outline - when (Utils.getExtensionFromFileName(name)) { - "txt" -> icon = CommunityMaterial.Icon.cmd_file_document_outline - "doc", "docx", "odt", "rtf" -> icon = SzkolnyFont.Icon.szf_file_word_outline - "xls", "xlsx", "ods" -> icon = SzkolnyFont.Icon.szf_file_excel_outline - "ppt", "pptx", "odp" -> icon = SzkolnyFont.Icon.szf_file_powerpoint_outline - "pdf" -> icon = SzkolnyFont.Icon.szf_file_pdf_outline - "mp3", "wav", "aac" -> icon = SzkolnyFont.Icon.szf_file_music_outline - "mp4", "avi", "3gp", "mkv", "flv" -> icon = SzkolnyFont.Icon.szf_file_video_outline - "jpg", "jpeg", "png", "bmp", "gif" -> icon = SzkolnyFont.Icon.szf_file_image_outline - "zip", "rar", "tar", "7z" -> icon = SzkolnyFont.Icon.szf_zip_box_outline - "html", "cpp", "c", "h", "css", "java", "py" -> icon = SzkolnyFont.Icon.szf_file_code_outline + val icon: IIcon = when (Utils.getExtensionFromFileName(name)) { + "doc", "docx", "odt", "rtf" -> SzkolnyFont.Icon.szf_file_word_outline + "xls", "xlsx", "ods" -> SzkolnyFont.Icon.szf_file_excel_outline + "ppt", "pptx", "odp" -> SzkolnyFont.Icon.szf_file_powerpoint_outline + "pdf" -> SzkolnyFont.Icon.szf_file_pdf_outline + "mp3", "wav", "aac" -> SzkolnyFont.Icon.szf_file_music_outline + "mp4", "avi", "3gp", "mkv", "flv" -> SzkolnyFont.Icon.szf_file_video_outline + "jpg", "jpeg", "png", "bmp", "gif" -> SzkolnyFont.Icon.szf_file_image_outline + "zip", "rar", "tar", "7z" -> SzkolnyFont.Icon.szf_zip_box_outline + "html", "cpp", "c", "h", "css", "java", "py" -> SzkolnyFont.Icon.szf_file_code_outline + else -> CommunityMaterial.Icon.cmd_file_document_outline } attachmentChip.chipIcon = IconicsDrawable(activity).color(IconicsColor.colorRes(R.color.colorPrimary)).icon(icon).size(IconicsSize.dp(26)) attachmentChip.closeIcon = IconicsDrawable(activity).icon(CommunityMaterial.Icon.cmd_check).size(IconicsSize.dp(18)).color(IconicsColor.colorInt(Utils.getAttr(activity, android.R.attr.textColorPrimary))) @@ -245,7 +247,7 @@ class MessageFragment : Fragment(), CoroutineScope { attachmentChip.tag = index attachmentChip.setOnClickListener { v -> if (v.tag is Int) { - // TODO downloadAttachment(v.tag as Int) + downloadAttachment(v.tag as Int) } } attachmentLayout.addView(attachmentChip) @@ -269,6 +271,60 @@ class MessageFragment : Fragment(), CoroutineScope { } } + private fun downloadAttachment(index: Int) { + val attachment = attachmentList[index] + + if (attachment.downloaded != null) { + Utils.openFile(activity, File(attachment.downloaded)) + return + } + + attachment.chip.isEnabled = false + attachment.chip.setTextColor(Themes.getSecondaryTextColor(activity)) + attachment.progressBar.visibility = View.VISIBLE + + EdziennikTask.attachmentGet( + App.profileId, + attachment.messageId, + attachment.attachmentId, + attachment.attachmentName + ).enqueue(activity) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onAttachmentGetEvent(event: AttachmentGetEvent) { + attachmentList.firstOrNull { it.profileId == event.profileId + && it.messageId == event.messageId + && it.attachmentId == event.attachmentId }?.let { attachment -> + + when (event.eventType) { + TYPE_FINISHED -> { + // save the downloaded file name + attachment.downloaded = event.fileName + + // set the correct name (and size) + if (attachment.attachmentSize == -1L) + attachment.chip.text = getString(R.string.messages_attachment_no_size_format, attachment.attachmentName) + else + attachment.chip.text = getString(R.string.messages_attachment_format, attachment.attachmentName, readableFileSize(attachment.attachmentSize)) + + // hide the progress bar and show a tick icon + attachment.progressBar.visibility = View.GONE + attachment.chip.isEnabled = true + attachment.chip.setTextColor(Themes.getPrimaryTextColor(activity)) + attachment.chip.isCloseIconVisible = true + + // open the file + Utils.openFile(activity, File(attachment.downloaded)) + } + + TYPE_PROGRESS -> { + attachment.chip.text = getString(R.string.messages_attachment_downloading_format, attachment.attachmentName, event.bytesWritten.toFloat() / 1000000) + } + } + } + } + private fun checkAttachment(attachment: Attachment) { val storageDir = Environment.getExternalStoragePublicDirectory("Szkolny.eu") storageDir.mkdirs() @@ -286,7 +342,6 @@ class MessageFragment : Fragment(), CoroutineScope { e.printStackTrace() //app.apiEdziennik.guiReportException(activity, 355, e) } - } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6521cc66..ffb8d4e4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -449,7 +449,7 @@ Plan lekcji Nie można pobrać załącznika Wystąpił błąd wewnętrzny pobierania załącznika. Może to być spowodowane słabym połączeniem internetowym. - %s (%d%%) + %s (%.2fMB) %s (%s) %s Dodaj załącznik