forked from github/szkolny
[API] Implement Mobidziennik homework attachment downloading. Modify the interface a bit. Show attachments in UI.
This commit is contained in:
parent
f8adc86a0e
commit
9303483470
@ -165,6 +165,13 @@ fun Bundle?.getString(key: String, defaultValue: String): String {
|
||||
return this?.getString(key, defaultValue) ?: defaultValue
|
||||
}
|
||||
|
||||
fun Bundle?.getIntOrNull(key: String): Int? {
|
||||
return this?.get(key) as? Int
|
||||
}
|
||||
fun <T : Any> Bundle?.get(key: String): T? {
|
||||
return this?.get(key) as? T?
|
||||
}
|
||||
|
||||
/**
|
||||
* ` The quick BROWN_fox Jumps OveR THE LAZy-DOG. `
|
||||
*
|
||||
|
@ -19,7 +19,6 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
@ -37,7 +36,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
fun messageSend(profileId: Int, recipients: List<Teacher>, subject: String, text: String) = EdziennikTask(profileId, MessageSendRequest(recipients, subject, text))
|
||||
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
|
||||
fun announcementGet(profileId: Int, announcement: AnnouncementFull) = EdziennikTask(profileId, AnnouncementGetRequest(announcement))
|
||||
fun attachmentGet(profileId: Int, message: Message, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(message, attachmentId, attachmentName))
|
||||
fun attachmentGet(profileId: Int, owner: Any, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(owner, attachmentId, attachmentName))
|
||||
fun recipientListGet(profileId: Int) = EdziennikTask(profileId, RecipientListGetRequest())
|
||||
fun eventGet(profileId: Int, event: EventFull) = EdziennikTask(profileId, EventGetRequest(event))
|
||||
}
|
||||
@ -94,7 +93,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
is FirstLoginRequest -> edziennikInterface?.firstLogin()
|
||||
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
|
||||
is AnnouncementGetRequest -> edziennikInterface?.getAnnouncement(request.announcement)
|
||||
is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.message, request.attachmentId, request.attachmentName)
|
||||
is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.owner, request.attachmentId, request.attachmentName)
|
||||
is RecipientListGetRequest -> edziennikInterface?.getRecipientList()
|
||||
is EventGetRequest -> edziennikInterface?.getEvent(request.event)
|
||||
}
|
||||
@ -116,7 +115,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
data class MessageSendRequest(val recipients: List<Teacher>, val subject: String, val text: String)
|
||||
class AnnouncementsReadRequest
|
||||
data class AnnouncementGetRequest(val announcement: AnnouncementFull)
|
||||
data class AttachmentGetRequest(val message: Message, val attachmentId: Long, val attachmentName: String)
|
||||
data class AttachmentGetRequest(val owner: Any, val attachmentId: Long, val attachmentName: String)
|
||||
class RecipientListGetRequest
|
||||
data class EventGetRequest(val event: EventFull)
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
@ -95,7 +94,7 @@ class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStor
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {}
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {}
|
||||
override fun getRecipientList() {}
|
||||
override fun getEvent(eventFull: EventFull) {}
|
||||
|
||||
|
@ -18,7 +18,6 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
@ -104,9 +103,9 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
override fun markAllAnnouncementsAsRead() {}
|
||||
override fun getAnnouncement(announcement: AnnouncementFull) {}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||
login(LOGIN_METHOD_IDZIENNIK_WEB) {
|
||||
IdziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
|
||||
IdziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
class IdziennikWebGetAttachment(override val data: DataIdziennik,
|
||||
val message: Message,
|
||||
val owner: Any,
|
||||
val attachmentId: Long,
|
||||
val attachmentName: String,
|
||||
val onSuccess: () -> Unit
|
||||
@ -25,6 +25,8 @@ class IdziennikWebGetAttachment(override val data: DataIdziennik,
|
||||
}
|
||||
|
||||
init {
|
||||
val message = owner as Message
|
||||
|
||||
val messageId = "\\[META:([A-z0-9]+);([0-9-]+)]".toRegex().find(message.body ?: "")?.get(2) ?: -1
|
||||
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
||||
|
||||
@ -34,13 +36,13 @@ class IdziennikWebGetAttachment(override val data: DataIdziennik,
|
||||
), { file ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_FINISHED,
|
||||
file.absolutePath
|
||||
)
|
||||
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
|
||||
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||
|
||||
EventBus.getDefault().post(event)
|
||||
@ -50,7 +52,7 @@ class IdziennikWebGetAttachment(override val data: DataIdziennik,
|
||||
}) { written, _ ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_PROGRESS,
|
||||
bytesWritten = written
|
||||
|
@ -20,7 +20,6 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
@ -119,9 +118,9 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||
login(LOGIN_METHOD_LIBRUS_MESSAGES) {
|
||||
LibrusMessagesGetAttachment(data, message, attachmentId, attachmentName) {
|
||||
LibrusMessagesGetAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import java.io.File
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LibrusMessagesGetAttachment(override val data: DataLibrus,
|
||||
val message: Message,
|
||||
val owner: Any,
|
||||
val attachmentId: Long,
|
||||
val attachmentName: String,
|
||||
val onSuccess: () -> Unit
|
||||
@ -38,6 +38,8 @@ class LibrusMessagesGetAttachment(override val data: DataLibrus,
|
||||
private var getAttachmentCheckKeyTries = 0
|
||||
|
||||
init {
|
||||
val message = owner as Message
|
||||
|
||||
messagesGet(TAG, "GetFileDownloadLink", parameters = mapOf(
|
||||
"fileId" to attachmentId,
|
||||
"msgId" to message.id,
|
||||
@ -95,13 +97,13 @@ class LibrusMessagesGetAttachment(override val data: DataLibrus,
|
||||
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
TYPE_FINISHED,
|
||||
file.absolutePath
|
||||
)
|
||||
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
|
||||
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||
|
||||
EventBus.getDefault().post(event)
|
||||
@ -111,7 +113,7 @@ class LibrusMessagesGetAttachment(override val data: DataLibrus,
|
||||
}) { written, _ ->
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
TYPE_PROGRESS,
|
||||
bytesWritten = written
|
||||
|
@ -15,14 +15,12 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||
companion object {
|
||||
@ -104,9 +102,9 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
||||
override fun markAllAnnouncementsAsRead() {}
|
||||
override fun getAnnouncement(announcement: AnnouncementFull) {}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
|
||||
MobidziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
|
||||
MobidziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
@ -121,13 +119,8 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
||||
}
|
||||
|
||||
override fun getEvent(eventFull: EventFull) {
|
||||
val type = if (eventFull.date >= Date.getToday())
|
||||
MobidziennikWebHomework.TYPE_CURRENT
|
||||
else
|
||||
MobidziennikWebHomework.TYPE_PAST
|
||||
|
||||
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
|
||||
MobidziennikWebHomework(data, 0L, type, eventFull) {
|
||||
MobidziennikWebGetHomework(data, eventFull) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,14 @@ import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import java.io.File
|
||||
|
||||
class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
|
||||
val message: Message,
|
||||
val owner: Any,
|
||||
val attachmentId: Long,
|
||||
val attachmentName: String,
|
||||
val onSuccess: () -> Unit
|
||||
@ -25,22 +27,37 @@ class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
|
||||
init {
|
||||
val targetFile = File(Utils.getStorageDir(), attachmentName)
|
||||
|
||||
val typeUrl = if (message.type == Message.TYPE_SENT)
|
||||
"wiadwyslana"
|
||||
else
|
||||
"wiadodebrana"
|
||||
val typeUrl = when (owner) {
|
||||
is Message -> if (owner.type == Message.TYPE_SENT)
|
||||
"dziennik/wiadwyslana?id="
|
||||
else
|
||||
"dziennik/wiadodebrana?id="
|
||||
|
||||
webGetFile(TAG, "/dziennik/$typeUrl/?id=${message.id}&zalacznik=$attachmentId", targetFile, { file ->
|
||||
is Event -> if (owner.date >= Date.getToday())
|
||||
"mobile/zadaniadomowe?id_zadania="
|
||||
else
|
||||
"mobile/zadaniadomowearchiwalne?id_zadania="
|
||||
|
||||
else -> ""
|
||||
}
|
||||
|
||||
val ownerId = when (owner) {
|
||||
is Message -> owner.id
|
||||
is Event -> owner.id
|
||||
else -> -1
|
||||
}
|
||||
|
||||
webGetFile(TAG, "/$typeUrl${ownerId}&zalacznik=$attachmentId", targetFile, { file ->
|
||||
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_FINISHED,
|
||||
file.absolutePath
|
||||
)
|
||||
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.messageId}_${event.attachmentId}")
|
||||
val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
|
||||
Utils.writeStringToFile(attachmentDataFile, event.fileName)
|
||||
|
||||
EventBus.getDefault().post(event)
|
||||
@ -51,7 +68,7 @@ class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
|
||||
// TODO make use of bytesTotal
|
||||
val event = AttachmentGetEvent(
|
||||
profileId,
|
||||
message.id,
|
||||
owner,
|
||||
attachmentId,
|
||||
AttachmentGetEvent.TYPE_PROGRESS,
|
||||
bytesWritten = written
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-31.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class MobidziennikWebGetHomework(override val data: DataMobidziennik,
|
||||
val event: EventFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : MobidziennikWeb(data, null) {
|
||||
companion object {
|
||||
private const val TAG = "MobidziennikWebHomework"
|
||||
}
|
||||
|
||||
init {
|
||||
val endpoint = if (event.date >= Date.getToday())
|
||||
"zadaniadomowe"
|
||||
else
|
||||
"zadaniadomowearchiwalne"
|
||||
|
||||
webGet(TAG, "/mobile/$endpoint") { text ->
|
||||
MobidziennikLuckyNumberExtractor(data, text)
|
||||
|
||||
Regexes.MOBIDZIENNIK_HOMEWORK_ROW.findAll(text).forEach { homeworkMatch ->
|
||||
val tableRow = homeworkMatch[1].ifBlank { return@forEach }
|
||||
|
||||
val id = Regexes.MOBIDZIENNIK_HOMEWORK_ID.find(tableRow)?.get(1)?.toLongOrNull() ?: return@forEach
|
||||
if (event.id != id)
|
||||
return@forEach
|
||||
|
||||
event.attachmentIds = mutableListOf()
|
||||
event.attachmentNames = mutableListOf()
|
||||
Regexes.MOBIDZIENNIK_HOMEWORK_ATTACHMENT.findAll(tableRow).forEach {
|
||||
event.attachmentIds?.add(it[1].toLongOrNull() ?: return@forEach)
|
||||
event.attachmentNames?.add(it[2])
|
||||
}
|
||||
|
||||
event.homeworkBody = ""
|
||||
}
|
||||
|
||||
data.eventList.add(event)
|
||||
data.eventListReplace = true
|
||||
|
||||
EventBus.getDefault().postSticky(EventGetEvent(event))
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.prepare
|
||||
import pl.szczodrzynski.edziennik.data.api.templateLoginMethods
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
@ -80,7 +79,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
|
||||
}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ 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.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
@ -104,7 +103,7 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
|
||||
override fun markAllAnnouncementsAsRead() {}
|
||||
override fun getAnnouncement(announcement: AnnouncementFull) {}
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {}
|
||||
override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {}
|
||||
override fun getRecipientList() {}
|
||||
override fun getEvent(eventFull: EventFull) {}
|
||||
|
||||
|
@ -4,11 +4,21 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.events
|
||||
|
||||
data class AttachmentGetEvent(val profileId: Int, val messageId: Long, val attachmentId: Long,
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
|
||||
data class AttachmentGetEvent(val profileId: Int, val owner: Any, 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
|
||||
}
|
||||
|
||||
val ownerId
|
||||
get() = when (owner) {
|
||||
is Message -> owner.id
|
||||
is Event -> owner.id
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.interfaces
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
@ -17,7 +16,7 @@ interface EdziennikInterface {
|
||||
fun sendMessage(recipients: List<Teacher>, subject: String, text: String)
|
||||
fun markAllAnnouncementsAsRead()
|
||||
fun getAnnouncement(announcement: AnnouncementFull)
|
||||
fun getAttachment(message: Message, attachmentId: Long, attachmentName: String)
|
||||
fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String)
|
||||
fun getRecipientList()
|
||||
fun getEvent(eventFull: EventFull)
|
||||
fun firstLogin()
|
||||
|
@ -61,6 +61,7 @@ class EventDetailsDialog(
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
onShowListener?.invoke(TAG)
|
||||
EventBus.getDefault().register(this)
|
||||
app = activity.applicationContext as App
|
||||
b = DialogEventDetailsBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
@ -74,6 +75,7 @@ class EventDetailsDialog(
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
EventBus.getDefault().unregister(this@EventDetailsDialog)
|
||||
progressDialog?.dismiss()
|
||||
}
|
||||
.show()
|
||||
@ -197,11 +199,18 @@ class EventDetailsDialog(
|
||||
}
|
||||
|
||||
if (event.homeworkBody == null && !event.addedManually && event.type == Event.TYPE_HOMEWORK) {
|
||||
b.bodyTitle.isVisible = true
|
||||
b.bodyProgressBar.isVisible = true
|
||||
b.body.isVisible = false
|
||||
EdziennikTask.eventGet(event.profileId, event).enqueue(activity)
|
||||
}
|
||||
else if (event.homeworkBody.isNullOrBlank()) {
|
||||
b.bodyTitle.isVisible = false
|
||||
b.bodyProgressBar.isVisible = false
|
||||
b.body.isVisible = false
|
||||
}
|
||||
else {
|
||||
b.bodyTitle.isVisible = true
|
||||
b.bodyProgressBar.isVisible = false
|
||||
b.body.isVisible = true
|
||||
b.body.text = event.homeworkBody
|
||||
@ -209,6 +218,20 @@ class EventDetailsDialog(
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
if (event.attachmentIds.isNullOrEmpty() || event.attachmentNames.isNullOrEmpty()) {
|
||||
b.attachmentsTitle.isVisible = false
|
||||
b.attachmentsFragment.isVisible = false
|
||||
}
|
||||
else {
|
||||
b.attachmentsTitle.isVisible = true
|
||||
b.attachmentsFragment.isVisible = true
|
||||
b.attachmentsFragment.init(Bundle().also {
|
||||
it.putInt("profileId", event.profileId)
|
||||
it.putLongArray("attachmentIds", event.attachmentIds!!.toLongArray())
|
||||
it.putStringArray("attachmentNames", event.attachmentNames!!.toTypedArray())
|
||||
}, owner = event)
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
|
@ -375,7 +375,7 @@ class MessageFragment : Fragment(), CoroutineScope {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onAttachmentGetEvent(event: AttachmentGetEvent) {
|
||||
attachmentList.firstOrNull { it.profileId == event.profileId
|
||||
&& it.messageId == event.messageId
|
||||
&& it.messageId == event.ownerId
|
||||
&& it.attachmentId == event.attachmentId }?.let { attachment ->
|
||||
|
||||
when (event.eventType) {
|
||||
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-4-1.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.views
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.databinding.AttachmentListItemBinding
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import pl.szczodrzynski.edziennik.onLongClick
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.navlib.colorAttr
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class AttachmentAdapter(
|
||||
val context: Context,
|
||||
val onAttachmentClick: (item: Item) -> Unit,
|
||||
val onAttachmentLongClick: ((view: Chip, item: Item) -> Unit)? = null
|
||||
) : RecyclerView.Adapter<AttachmentAdapter.ViewHolder>(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "AttachmentAdapter"
|
||||
}
|
||||
|
||||
private val app = context.applicationContext as App
|
||||
// optional: place the manager here
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
var items = listOf<Item>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
val view = AttachmentListItemBinding.inflate(inflater, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
val b = holder.b
|
||||
|
||||
// create an icon for the attachment
|
||||
val icon: IIcon = when (Utils.getExtensionFromFileName(item.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
|
||||
}
|
||||
|
||||
b.chip.text = if (item.isDownloading) {
|
||||
app.getString(R.string.messages_attachment_downloading_format, item.name, item.downloadProgress)
|
||||
}
|
||||
else {
|
||||
item.size?.let {
|
||||
app.getString(R.string.messages_attachment_format, item.name, Utils.readableFileSize(it))
|
||||
} ?: item.name
|
||||
}
|
||||
|
||||
b.chip.chipIcon = IconicsDrawable(context)
|
||||
.icon(icon)
|
||||
.colorAttr(context, R.attr.colorOnSurface)
|
||||
.sizeDp(24)
|
||||
b.chip.closeIcon = IconicsDrawable(context)
|
||||
.icon(CommunityMaterial.Icon.cmd_check)
|
||||
.colorAttr(context, R.attr.colorOnSurface)
|
||||
.sizeDp(18)
|
||||
|
||||
b.chip.isCloseIconVisible = item.isDownloaded && !item.isDownloading
|
||||
// prevent progress bar flickering
|
||||
if (b.progressBar.isVisible != item.isDownloading)
|
||||
b.progressBar.isVisible = item.isDownloading
|
||||
|
||||
b.chip.onClick { onAttachmentClick(item) }
|
||||
onAttachmentLongClick?.let { listener ->
|
||||
b.chip.onLongClick { listener(it, item); true }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
data class Item(
|
||||
val profileId: Int,
|
||||
val owner: Any,
|
||||
val id: Long,
|
||||
val name: String,
|
||||
var size: Long?
|
||||
) {
|
||||
val ownerId
|
||||
get() = when (owner) {
|
||||
is Message -> owner.id
|
||||
is Event -> owner.id
|
||||
else -> -1
|
||||
}
|
||||
var isDownloaded = false
|
||||
var isDownloading = false
|
||||
var downloadProgress: Float = 0f
|
||||
var downloadedName: String? = null
|
||||
}
|
||||
|
||||
class ViewHolder(val b: AttachmentListItemBinding) : RecyclerView.ViewHolder(b.root)
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-4-1.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.views
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
class AttachmentsView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : RecyclerView(context, attrs, defStyleAttr) {
|
||||
companion object {
|
||||
private const val TAG = "AttachmentsFragment"
|
||||
const val TYPE_MESSAGE = 0
|
||||
const val TYPE_EVENT = 1
|
||||
}
|
||||
|
||||
private val storageDir by lazy {
|
||||
val storageDir = Environment.getExternalStoragePublicDirectory("Szkolny.eu")
|
||||
storageDir.mkdirs()
|
||||
storageDir
|
||||
}
|
||||
|
||||
fun init(arguments: Bundle, owner: Any) {
|
||||
val list = this as? RecyclerView ?: return
|
||||
|
||||
val profileId = arguments.get<Int>("profileId") ?: return
|
||||
val attachmentIds = arguments.getLongArray("attachmentIds") ?: return
|
||||
val attachmentNames = arguments.getStringArray("attachmentNames") ?: return
|
||||
val attachmentSizes = arguments.getLongArray("attachmentSizes")
|
||||
|
||||
val adapter = AttachmentAdapter(context, onAttachmentClick = { item ->
|
||||
downloadAttachment(item)
|
||||
}, onAttachmentLongClick = { chip, item ->
|
||||
val popupMenu = PopupMenu(chip.context, chip)
|
||||
popupMenu.menu.add(0, 1, 0, R.string.messages_attachment_download_again)
|
||||
popupMenu.setOnMenuItemClickListener {
|
||||
downloadAttachment(item, forceDownload = true)
|
||||
true
|
||||
}
|
||||
popupMenu.show()
|
||||
})
|
||||
|
||||
attachmentIds.forEachIndexed { index, id ->
|
||||
val name = attachmentNames[index] ?: return@forEachIndexed
|
||||
val size = attachmentSizes?.getOrNull(index)
|
||||
|
||||
val item = AttachmentAdapter.Item(profileId, owner, id, name, size)
|
||||
adapter.items += item
|
||||
checkAttachment(item = item)
|
||||
}
|
||||
|
||||
// load & configure the adapter
|
||||
if (adapter.items.isNotNullNorEmpty() && list.adapter == null) {
|
||||
list.adapter = adapter
|
||||
list.apply {
|
||||
setHasFixedSize(false)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
addItemDecoration(SimpleDividerItemDecoration(context))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAttachment(item: AttachmentAdapter.Item): Boolean {
|
||||
val attachmentDataFile = File(storageDir, "." + item.profileId + "_" + item.ownerId + "_" + item.id)
|
||||
item.isDownloaded = if (attachmentDataFile.exists()) {
|
||||
try {
|
||||
val attachmentFileName = Utils.getStringFromFile(attachmentDataFile)
|
||||
val attachmentFile = File(attachmentFileName)
|
||||
attachmentFile.exists()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
false
|
||||
}
|
||||
} else false
|
||||
return item.isDownloaded
|
||||
}
|
||||
|
||||
private fun downloadAttachment(attachment: AttachmentAdapter.Item, forceDownload: Boolean = false) {
|
||||
if (!forceDownload && attachment.isDownloaded) {
|
||||
Utils.openFile(context, File(attachment.downloadedName))
|
||||
return
|
||||
}
|
||||
|
||||
attachment.isDownloading = true
|
||||
(adapter as? AttachmentAdapter)?.let {
|
||||
it.notifyItemChanged(it.items.indexOf(attachment))
|
||||
}
|
||||
|
||||
EdziennikTask.attachmentGet(
|
||||
attachment.profileId,
|
||||
attachment.owner,
|
||||
attachment.id,
|
||||
attachment.name
|
||||
).enqueue(context)
|
||||
}
|
||||
|
||||
private val lastUpdate: Long = 0
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onAttachmentGetEvent(event: AttachmentGetEvent) {
|
||||
val attachment = (adapter as? AttachmentAdapter)?.items?.firstOrNull {
|
||||
it.profileId == event.profileId
|
||||
&& it.owner == event.owner
|
||||
&& it.id == event.attachmentId
|
||||
} ?: return
|
||||
|
||||
|
||||
when (event.eventType) {
|
||||
AttachmentGetEvent.TYPE_FINISHED -> {
|
||||
// save the downloaded file name
|
||||
attachment.downloadedName = event.fileName
|
||||
attachment.isDownloading = false
|
||||
attachment.isDownloaded = true
|
||||
|
||||
// open the file
|
||||
Utils.openFile(context, File(attachment.downloadedName))
|
||||
}
|
||||
|
||||
AttachmentGetEvent.TYPE_PROGRESS -> {
|
||||
attachment.downloadProgress = event.bytesWritten.toFloat() / 1000000f
|
||||
}
|
||||
}
|
||||
|
||||
if (event.eventType != AttachmentGetEvent.TYPE_PROGRESS || System.currentTimeMillis() - lastUpdate > 100L) {
|
||||
(adapter as? AttachmentAdapter)?.let {
|
||||
it.notifyItemChanged(it.items.indexOf(attachment))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
EventBus.getDefault().register(this)
|
||||
super.onAttachedToWindow()
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
}
|
36
app/src/main/res/layout/attachment_list_item.xml
Normal file
36
app/src/main/res/layout/attachment_list_item.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2020-4-1.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="8dp">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:ellipsize="middle"
|
||||
app:chipIconSize="24dp"
|
||||
app:chipIconVisible="true"
|
||||
app:closeIconSize="18dp"
|
||||
app:closeIconVisible="false"
|
||||
tools:chipIcon="@android:drawable/ic_menu_delete"
|
||||
tools:closeIcon="@drawable/ic_account_circle"
|
||||
tools:closeIconVisible="true"
|
||||
tools:text="Zadanie z matematyki.pdf" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_marginHorizontal="8dp" />
|
||||
</FrameLayout>
|
||||
</layout>
|
@ -152,12 +152,12 @@
|
||||
tools:text="Rozdział II: Panowanie Piastów i Jagiellonów.Przeniesiony z 11 grudnia." />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bodyTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@string/dialog_event_details_body"
|
||||
android:visibility="@{event.homeworkBody != null ? View.VISIBLE : View.GONE}"/>
|
||||
android:textAppearance="@style/NavView.TextView.Helper" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/bodyProgressBar"
|
||||
@ -175,9 +175,21 @@
|
||||
android:text="@{event.homeworkBody}"
|
||||
android:textAppearance="@style/NavView.TextView.Medium"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{event.homeworkBody != null ? View.VISIBLE : View.GONE}"
|
||||
tools:text="Rozdział II: Panowanie Piastów i Jagiellonów.Przeniesiony z 11 grudnia." />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/attachmentsTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/dialog_event_details_attachments"
|
||||
android:textAppearance="@style/NavView.TextView.Helper" />
|
||||
|
||||
<pl.szczodrzynski.edziennik.ui.modules.views.AttachmentsView
|
||||
android:id="@+id/attachmentsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -1284,4 +1284,5 @@
|
||||
<string name="event_mark_as_done_title">Oznacz jako wykonane</string>
|
||||
<string name="event_mark_as_done_text">Czy chcesz oznaczyć to zadanie jako wykonane?\n\nNie będzie ono się wyświetlać na stronie głównej oraz w aktualnych zadaniach domowych. Będzie wciąż dostępne w Terminarzu.</string>
|
||||
<string name="dialog_event_details_body">Treść</string>
|
||||
<string name="dialog_event_details_attachments">Załączniki</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user