forked from github/szkolny
Compare commits
7 Commits
v3.9.4-dev
...
v3.9.5-dev
Author | SHA1 | Date | |
---|---|---|---|
16102de619 | |||
472e768369 | |||
131a769c26 | |||
4a0a6c54e4 | |||
c83abe57d5 | |||
c6e2519dcc | |||
74db524db6 |
5
.idea/misc.xml
generated
5
.idea/misc.xml
generated
@ -6,8 +6,9 @@
|
||||
</configurations>
|
||||
</component>
|
||||
<component name="EntryPointsManager">
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
||||
<list size="2">
|
||||
<item index="0" class="java.lang.String" itemvalue="androidx.databinding.BindingAdapter" />
|
||||
<item index="1" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
|
@ -131,7 +131,7 @@ dependencies {
|
||||
implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true}
|
||||
implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update
|
||||
implementation "com.jaredrummler:colorpicker:1.0.2"
|
||||
implementation "com.squareup.okhttp3:okhttp:3.12.0"
|
||||
implementation "com.squareup.okhttp3:okhttp:3.12.2"
|
||||
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update
|
||||
implementation "com.wdullaer:materialdatetimepicker:4.1.2"
|
||||
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
||||
|
@ -39,4 +39,13 @@
|
||||
|
||||
-keep class okhttp3.** { *; }
|
||||
|
||||
-keep class com.google.android.material.tabs.** {*;}
|
||||
-keep class com.google.android.material.tabs.** {*;}
|
||||
|
||||
# ServiceLoader support
|
||||
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
|
||||
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
|
||||
|
||||
# Most of volatile fields are updated with AFU and should not be mangled
|
||||
-keepclassmembernames class kotlinx.** {
|
||||
volatile <fields>;
|
||||
}
|
21
app/src/main/java/pl/szczodrzynski/edziennik/Binding.java
Normal file
21
app/src/main/java/pl/szczodrzynski/edziennik/Binding.java
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-11.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik;
|
||||
|
||||
import android.graphics.Paint;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.databinding.BindingAdapter;
|
||||
|
||||
public class Binding {
|
||||
@BindingAdapter("strikeThrough")
|
||||
public static void strikeThrough(TextView textView, Boolean strikeThrough) {
|
||||
if (strikeThrough) {
|
||||
textView.setPaintFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
} else {
|
||||
textView.setPaintFlags(textView.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,17 +4,23 @@ import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Typeface
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.*
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.StrikethroughSpan
|
||||
import android.text.style.StyleSpan
|
||||
import android.util.LongSparseArray
|
||||
import android.util.SparseArray
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.util.forEach
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
@ -343,6 +349,11 @@ fun CharSequence?.asStrikethroughSpannable(): Spannable {
|
||||
spannable.setSpan(StrikethroughSpan(), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return spannable
|
||||
}
|
||||
fun CharSequence?.asItalicSpannable(): Spannable {
|
||||
val spannable = SpannableString(this)
|
||||
spannable.setSpan(StyleSpan(Typeface.ITALIC), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return spannable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new read-only list only of those given elements, that are not empty.
|
||||
@ -408,4 +419,20 @@ fun JsonObject(vararg properties: Pair<String, Any>): JsonObject {
|
||||
}
|
||||
|
||||
fun JsonArray?.isNullOrEmpty(): Boolean = (this?.size() ?: 0) == 0
|
||||
fun JsonArray.isEmpty(): Boolean = this.size() == 0
|
||||
fun JsonArray.isEmpty(): Boolean = this.size() == 0
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <T : View> T.onClick(crossinline onClickListener: (v: T) -> Unit) {
|
||||
setOnClickListener { v: View ->
|
||||
onClickListener(v as T)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
|
||||
observe(lifecycleOwner, object : Observer<T> {
|
||||
override fun onChanged(t: T?) {
|
||||
observer.onChanged(t)
|
||||
removeObserver(this)
|
||||
}
|
||||
})
|
||||
}
|
@ -57,7 +57,7 @@ import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesDetailsFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessageFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
||||
@ -203,7 +203,7 @@ class MainActivity : AppCompatActivity() {
|
||||
list += NavTarget(TARGET_GRADES_EDITOR, R.string.menu_grades_editor, GradesEditorFragment::class)
|
||||
list += NavTarget(TARGET_HELP, R.string.menu_help, HelpFragment::class)
|
||||
list += NavTarget(TARGET_FEEDBACK, R.string.menu_feedback, FeedbackFragment::class)
|
||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessagesDetailsFragment::class)
|
||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||
|
||||
list
|
||||
@ -345,7 +345,7 @@ class MainActivity : AppCompatActivity() {
|
||||
if (!profileListEmpty) {
|
||||
handleIntent(intent?.extras)
|
||||
}
|
||||
app.db.profileDao().getAllFull().observe(this, Observer { profiles ->
|
||||
app.db.profileDao().allFull.observe(this, Observer { profiles ->
|
||||
// TODO fix weird -1 profiles ???
|
||||
profiles.removeAll { it.id < 0 }
|
||||
drawer.setProfileList(profiles)
|
||||
@ -362,7 +362,7 @@ class MainActivity : AppCompatActivity() {
|
||||
if (app.profile != null)
|
||||
setDrawerItems()
|
||||
|
||||
app.db.metadataDao().getUnreadCounts().observe(this, Observer { unreadCounters ->
|
||||
app.db.metadataDao().unreadCounts.observe(this, Observer { unreadCounters ->
|
||||
unreadCounters.map {
|
||||
it.type = it.thingType
|
||||
}
|
||||
@ -701,7 +701,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
intentTargetId != -1 -> {
|
||||
drawer.currentProfile = app.profile.id
|
||||
loadTarget(intentTargetId, extras)
|
||||
if (navTargetId != intentTargetId)
|
||||
loadTarget(intentTargetId, extras)
|
||||
}
|
||||
else -> {
|
||||
drawer.currentProfile = app.profile.id
|
||||
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.api.v2.events
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
|
||||
data class MessageGetEvent(val message: MessageFull)
|
@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.api.v2.mobidziennik.Mobidziennik
|
||||
import pl.szczodrzynski.edziennik.api.v2.template.Template
|
||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.Vulcan
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
|
||||
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
|
||||
companion object {
|
||||
@ -21,7 +22,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
fun sync() = EdziennikTask(-1, SyncRequest())
|
||||
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, arguments))
|
||||
fun syncProfileList(profileList: List<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList))
|
||||
fun messageGet(profileId: Int, messageId: Int) = EdziennikTask(profileId, MessageGetRequest(messageId))
|
||||
fun messageGet(profileId: Int, message: MessageFull) = EdziennikTask(profileId, MessageGetRequest(message))
|
||||
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
|
||||
}
|
||||
|
||||
@ -39,7 +40,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
// get the requested profile and login store
|
||||
val profile = app.db.profileDao().getByIdNow(profileId)
|
||||
this.profile = profile
|
||||
if (profile == null || !profile.syncEnabled) {
|
||||
if (profile == null) {
|
||||
return
|
||||
}
|
||||
val loginStore = app.db.loginStoreDao().getByIdNow(profile.loginStoreId) ?: return
|
||||
@ -69,7 +70,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
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.messageId)
|
||||
is MessageGetRequest -> edziennikInterface?.getMessage(request.message)
|
||||
is FirstLoginRequest -> edziennikInterface?.firstLogin()
|
||||
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
|
||||
}
|
||||
@ -87,6 +88,6 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
class SyncRequest
|
||||
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null, val arguments: JsonObject? = null)
|
||||
data class SyncProfileListRequest(val profileList: List<Int>)
|
||||
data class MessageGetRequest(val messageId: Int)
|
||||
data class MessageGetRequest(val message: MessageFull)
|
||||
class AnnouncementsReadRequest
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -61,7 +62,7 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMessage(messageId: Int) {
|
||||
override fun getMessage(message: MessageFull) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
|
||||
/*messageId*/ messageId
|
||||
)
|
||||
|
||||
data.messageList.add(message)
|
||||
data.messageIgnoreList.add(message)
|
||||
data.messageRecipientList.add(messageRecipient)
|
||||
data.messageMetadataList.add(Metadata(
|
||||
profileId,
|
||||
|
@ -74,7 +74,7 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
|
||||
data.messageRecipientIgnoreList.add(messageRecipient)
|
||||
}
|
||||
|
||||
data.messageList.add(message)
|
||||
data.messageIgnoreList.add(message)
|
||||
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,11 @@
|
||||
package pl.szczodrzynski.edziennik.api.v2.interfaces
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
|
||||
interface EdziennikInterface {
|
||||
fun sync(featureIds: List<Int>, viewId: Int? = null, arguments: JsonObject? = null)
|
||||
fun getMessage(messageId: Int)
|
||||
fun getMessage(message: MessageFull)
|
||||
fun markAllAnnouncementsAsRead()
|
||||
fun firstLogin()
|
||||
fun cancel()
|
||||
|
@ -10,13 +10,16 @@ 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.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.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -78,8 +81,16 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMessage(messageId: Int) {
|
||||
|
||||
override fun getMessage(message: MessageFull) {
|
||||
LibrusLoginApi(data) {
|
||||
LibrusLoginSynergia(data) {
|
||||
LibrusLoginMessages(data) {
|
||||
LibrusMessagesGetMessage(data, message) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun markAllAnnouncementsAsRead() {
|
||||
|
@ -187,6 +187,6 @@ class LibrusApiTimetables(override val data: DataLibrus,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
data.lessonNewList += lessonObject
|
||||
data.lessonNewList.add(lessonObject)
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ class LibrusApiUsers(override val data: DataLibrus,
|
||||
|
||||
users?.forEach { user ->
|
||||
val id = user.getLong("Id") ?: return@forEach
|
||||
val firstName = user.getString("FirstName")?.fixWhiteSpaces() ?: ""
|
||||
val lastName = user.getString("LastName")?.fixWhiteSpaces() ?: ""
|
||||
val firstName = user.getString("FirstName")?.fixName() ?: ""
|
||||
val lastName = user.getString("LastName")?.fixName() ?: ""
|
||||
|
||||
data.teacherList.put(id, Teacher(profileId, id, firstName, lastName))
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ class LibrusMessagesGetList(override val data: DataLibrus, private val type: Int
|
||||
id
|
||||
)
|
||||
|
||||
data.messageList.add(messageObject)
|
||||
data.messageIgnoreList.add(messageObject)
|
||||
data.messageRecipientList.add(messageRecipientObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-11
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.api.v2.librus.data.messages
|
||||
|
||||
import android.util.Base64
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.api.v2.events.MessageGetEvent
|
||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusMessages
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.fixName
|
||||
import pl.szczodrzynski.edziennik.singleOrNull
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import java.nio.charset.Charset
|
||||
|
||||
class LibrusMessagesGetMessage(
|
||||
override val data: DataLibrus,
|
||||
private val messageObject: MessageFull,
|
||||
val onSuccess: () -> Unit
|
||||
) : LibrusMessages(data) {
|
||||
companion object {
|
||||
const val TAG = "LibrusMessagesGetMessage"
|
||||
}
|
||||
|
||||
init { data.profile?.also { profile ->
|
||||
messagesGet(TAG, "GetMessage", parameters = mapOf(
|
||||
"messageId" to messageObject.id,
|
||||
"archive" to 0
|
||||
)) { doc ->
|
||||
val message = doc.select("response GetMessage data").first()
|
||||
|
||||
val body = Base64.decode(message.select("Message").text(), Base64.DEFAULT)
|
||||
.toString(Charset.defaultCharset())
|
||||
.replace("\n", "<br>")
|
||||
.replace("<!\\[CDATA\\[", "")
|
||||
.replace("]]>", "")
|
||||
|
||||
messageObject.apply {
|
||||
this.body = body
|
||||
|
||||
clearAttachments()
|
||||
message.select("attachments ArrayItem").forEach {
|
||||
val attachmentId = it.select("id").text().toLong()
|
||||
val attachmentName = it.select("filename").text()
|
||||
addAttachment(attachmentId, attachmentName, -1)
|
||||
}
|
||||
}
|
||||
|
||||
val messageRecipientList = mutableListOf<MessageRecipientFull>()
|
||||
|
||||
when (messageObject.type) {
|
||||
TYPE_RECEIVED -> {
|
||||
val senderLoginId = message.select("senderId").text()
|
||||
data.teacherList.singleOrNull { it.id == messageObject.senderId }?.loginId = senderLoginId
|
||||
|
||||
val readDateText = message.select("readDate").text()
|
||||
val readDate = when (readDateText.isNotEmpty()) {
|
||||
true -> Date.fromIso(readDateText)
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val messageRecipientObject = MessageRecipientFull(
|
||||
profileId,
|
||||
-1,
|
||||
-1,
|
||||
readDate,
|
||||
messageObject.id
|
||||
)
|
||||
|
||||
messageRecipientObject.fullName = profile.accountNameLong ?: profile.studentNameLong
|
||||
|
||||
messageRecipientList.add(messageRecipientObject)
|
||||
}
|
||||
|
||||
TYPE_SENT -> {
|
||||
|
||||
message.select("receivers ArrayItem").forEach { receiver ->
|
||||
val receiverFirstName = receiver.select("firstName").text().fixName()
|
||||
val receiverLastName = receiver.select("lastName").text().fixName()
|
||||
val receiverLoginId = receiver.select("receiverId").text()
|
||||
|
||||
val teacher = data.teacherList.singleOrNull { it.name == receiverFirstName && it.surname == receiverLastName }
|
||||
val receiverId = teacher?.id ?: -1
|
||||
teacher?.loginId = receiverLoginId
|
||||
|
||||
val readDateText = message.select("readed").text()
|
||||
val readDate = when (readDateText.isNotEmpty()) {
|
||||
true -> Date.fromIso(readDateText)
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val messageRecipientObject = MessageRecipientFull(
|
||||
profileId,
|
||||
receiverId,
|
||||
-1,
|
||||
readDate,
|
||||
messageObject.id
|
||||
)
|
||||
|
||||
messageRecipientObject.fullName = "$receiverFirstName $receiverLastName"
|
||||
|
||||
messageRecipientList.add(messageRecipientObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!messageObject.seen) {
|
||||
data.messageMetadataList.add(Metadata(
|
||||
messageObject.profileId,
|
||||
Metadata.TYPE_MESSAGE,
|
||||
messageObject.id,
|
||||
true,
|
||||
true,
|
||||
messageObject.addedDate
|
||||
))
|
||||
}
|
||||
|
||||
messageObject.recipients = messageRecipientList
|
||||
data.messageRecipientList.addAll(messageRecipientList)
|
||||
data.messageList.add(messageObject)
|
||||
|
||||
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
|
||||
onSuccess()
|
||||
}
|
||||
} ?: onSuccess()}
|
||||
}
|
@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.api.v2.mobidziennikLoginMethods
|
||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -61,7 +62,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMessage(messageId: Int) {
|
||||
override fun getMessage(message: MessageFull) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,7 @@ import org.jsoup.Jsoup
|
||||
import pl.szczodrzynski.edziennik.DAY
|
||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL
|
||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX
|
||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||
@ -79,7 +77,7 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
|
||||
-1
|
||||
)
|
||||
|
||||
data.messageList.add(message)
|
||||
data.messageIgnoreList.add(message)
|
||||
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate))
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
|
||||
if (hasAttachments)
|
||||
message.setHasAttachments()
|
||||
|
||||
data.messageList.add(message)
|
||||
data.messageIgnoreList.add(message)
|
||||
data.messageMetadataList.add(
|
||||
Metadata(
|
||||
profileId,
|
||||
|
@ -156,6 +156,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
||||
val teacherAbsenceList = mutableListOf<TeacherAbsence>()
|
||||
|
||||
val messageList = mutableListOf<Message>()
|
||||
val messageIgnoreList = mutableListOf<Message>()
|
||||
val messageRecipientList = mutableListOf<MessageRecipient>()
|
||||
val messageRecipientIgnoreList = mutableListOf<MessageRecipient>()
|
||||
|
||||
@ -205,7 +206,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
||||
announcementList.clear()
|
||||
luckyNumberList.clear()
|
||||
teacherAbsenceList.clear()
|
||||
messageList.clear()
|
||||
messageIgnoreList.clear()
|
||||
messageRecipientList.clear()
|
||||
messageRecipientIgnoreList.clear()
|
||||
metadataList.clear()
|
||||
@ -285,6 +286,11 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
||||
}
|
||||
}
|
||||
|
||||
if (metadataList.isNotEmpty())
|
||||
db.metadataDao().addAllIgnore(metadataList)
|
||||
if (messageMetadataList.isNotEmpty())
|
||||
db.metadataDao().setSeen(messageMetadataList)
|
||||
|
||||
// not extracted from DB - always new data
|
||||
if (lessonList.isNotEmpty()) {
|
||||
db.lessonDao().clear(profile.id)
|
||||
@ -316,15 +322,13 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
||||
db.teacherAbsenceDao().addAll(teacherAbsenceList)
|
||||
|
||||
if (messageList.isNotEmpty())
|
||||
db.messageDao().addAllIgnore(messageList)
|
||||
db.messageDao().addAll(messageList)
|
||||
if (messageIgnoreList.isNotEmpty())
|
||||
db.messageDao().addAllIgnore(messageIgnoreList)
|
||||
if (messageRecipientList.isNotEmpty())
|
||||
db.messageRecipientDao().addAll(messageRecipientList)
|
||||
if (messageRecipientIgnoreList.isNotEmpty())
|
||||
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
|
||||
if (metadataList.isNotEmpty())
|
||||
db.metadataDao().addAllIgnore(metadataList)
|
||||
if (messageMetadataList.isNotEmpty())
|
||||
db.metadataDao().setSeen(messageMetadataList)
|
||||
}
|
||||
|
||||
fun notifyAndSyncEvents(onSuccess: () -> Unit) {
|
||||
|
@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.api.v2.template.firstlogin.TemplateFirstLogin
|
||||
import pl.szczodrzynski.edziennik.api.v2.template.login.TemplateLogin
|
||||
import pl.szczodrzynski.edziennik.api.v2.templateLoginMethods
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -61,7 +62,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMessage(messageId: Int) {
|
||||
override fun getMessage(message: MessageFull) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.api.v2.vulcan.firstlogin.VulcanFirstLogin
|
||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.login.VulcanLogin
|
||||
import pl.szczodrzynski.edziennik.api.v2.vulcanLoginMethods
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
@ -61,7 +62,7 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMessage(messageId: Int) {
|
||||
override fun getMessage(message: MessageFull) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
|
||||
id
|
||||
)
|
||||
|
||||
data.messageList.add(messageObject)
|
||||
data.messageIgnoreList.add(messageObject)
|
||||
data.messageRecipientList.add(messageRecipientObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
|
@ -80,7 +80,7 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
||||
data.messageRecipientList.add(messageRecipientObject)
|
||||
}
|
||||
|
||||
data.messageList.add(messageObject)
|
||||
data.messageIgnoreList.add(messageObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_MESSAGE,
|
||||
|
@ -5,6 +5,7 @@ import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||
|
||||
@ -85,6 +86,23 @@ public class Event {
|
||||
this.teamId = teamId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event clone() throws CloneNotSupportedException {
|
||||
return new Event(
|
||||
profileId,
|
||||
id,
|
||||
eventDate.clone(),
|
||||
startTime == null ? null : startTime.clone(),
|
||||
topic,
|
||||
color,
|
||||
type,
|
||||
addedManually,
|
||||
subjectId,
|
||||
teacherId,
|
||||
teamId
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Event{" +
|
||||
|
@ -1,19 +1,19 @@
|
||||
package pl.szczodrzynski.edziennik.data.db.modules.messages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity(tableName = "messages",
|
||||
primaryKeys = {"profileId", "messageId"},
|
||||
indices = {@Index(value = {"profileId"})})
|
||||
public class Message {
|
||||
int profileId;
|
||||
public int profileId;
|
||||
|
||||
@ColumnInfo(name = "messageId")
|
||||
public long id;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package pl.szczodrzynski.edziennik.data.db.modules.messages;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
@ -11,6 +10,8 @@ import androidx.room.RawQuery;
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery;
|
||||
import androidx.sqlite.db.SupportSQLiteQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata;
|
||||
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_DELETED;
|
||||
@ -23,6 +24,9 @@ public abstract class MessageDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
public abstract long add(Message message);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
public abstract void addAll(List<Message> messageList);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
public abstract void addAllIgnore(List<Message> messageList);
|
||||
|
||||
@ -56,6 +60,7 @@ public abstract class MessageDao {
|
||||
"ORDER BY addedDate DESC"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MessageFull getById(int profileId, long messageId) {
|
||||
return getOneNow(new SimpleSQLiteQuery("SELECT \n" +
|
||||
"*, \n" +
|
||||
|
@ -1,13 +1,15 @@
|
||||
package pl.szczodrzynski.edziennik.data.db.modules.messages;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.room.Ignore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.room.Ignore;
|
||||
|
||||
public class MessageFull extends Message {
|
||||
public String senderFullName = null;
|
||||
@Ignore
|
||||
@Nullable
|
||||
public List<MessageRecipientFull> recipients = null;
|
||||
|
||||
public MessageFull addRecipient(MessageRecipientFull recipient) {
|
||||
|
@ -62,6 +62,25 @@ class LessonFull(profileId: Int, id: Long) : Lesson(profileId, id) {
|
||||
return classroom ?: oldClassroom
|
||||
}
|
||||
|
||||
val displayTeamId: Long?
|
||||
get() {
|
||||
if (type == TYPE_SHIFTED_SOURCE)
|
||||
return oldTeamId
|
||||
return teamId ?: oldTeamId
|
||||
}
|
||||
val displaySubjectId: Long?
|
||||
get() {
|
||||
if (type == TYPE_SHIFTED_SOURCE)
|
||||
return oldSubjectId
|
||||
return subjectId ?: oldSubjectId
|
||||
}
|
||||
val displayTeacherId: Long?
|
||||
get() {
|
||||
if (type == TYPE_SHIFTED_SOURCE)
|
||||
return oldTeacherId
|
||||
return teacherId ?: oldTeacherId
|
||||
}
|
||||
|
||||
// metadata
|
||||
var seen: Boolean = false
|
||||
var notified: Boolean = false
|
||||
|
@ -43,7 +43,31 @@ interface TimetableDao {
|
||||
LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId
|
||||
LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId
|
||||
WHERE timetable.profileId = :profileId AND (type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date)
|
||||
ORDER BY type
|
||||
ORDER BY id, type
|
||||
""")
|
||||
fun getForDate(profileId: Int, date: Date) : LiveData<List<LessonFull>>
|
||||
|
||||
@Query("""
|
||||
SELECT
|
||||
timetable.*,
|
||||
subjects.subjectLongName AS subjectName,
|
||||
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName,
|
||||
teams.teamName AS teamName,
|
||||
oldS.subjectLongName AS oldSubjectName,
|
||||
oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName,
|
||||
oldG.teamName AS oldTeamName,
|
||||
metadata.seen, metadata.notified, metadata.addedDate
|
||||
FROM timetable
|
||||
LEFT JOIN subjects USING(profileId, subjectId)
|
||||
LEFT JOIN teachers USING(profileId, teacherId)
|
||||
LEFT JOIN teams USING(profileId, teamId)
|
||||
LEFT JOIN subjects AS oldS ON timetable.profileId = oldS.profileId AND timetable.oldSubjectId = oldS.subjectId
|
||||
LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId
|
||||
LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId
|
||||
LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId
|
||||
WHERE timetable.profileId = :profileId AND ((type != 3 AND date > :today) OR ((type = 3 OR type = 1) AND oldDate > :today)) AND timetable.subjectId = :subjectId
|
||||
ORDER BY id, type
|
||||
LIMIT 1
|
||||
""")
|
||||
fun getNextWithSubject(profileId: Int, today: Date, subjectId: Long) : LiveData<LessonFull>
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class EventAddTypeDialog(
|
||||
val activity: Activity,
|
||||
val profileId: Int,
|
||||
val date: Date? = null,
|
||||
val time: Time? = null
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "EventAddTypeDialog"
|
||||
}
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setItems(R.array.main_menu_add_options) { dialog, which ->
|
||||
dialog.dismiss()
|
||||
EventManualDialog(activity, profileId)
|
||||
.show(
|
||||
activity.application as App,
|
||||
null,
|
||||
date,
|
||||
time,
|
||||
when (which) {
|
||||
1 -> EventManualDialog.DIALOG_HOMEWORK
|
||||
else -> EventManualDialog.DIALOG_EVENT
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
}}
|
||||
}
|
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
||||
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class EventManualV2Dialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
val defaultLesson: LessonFull? = null,
|
||||
val defaultDate: Date? = null,
|
||||
val defaultTime: Time? = null,
|
||||
val defaultType: Int? = null,
|
||||
val editingEvent: Event? = null
|
||||
) : CoroutineScope {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "EventManualDialog"
|
||||
}
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
private lateinit var b: DialogEventManualV2Binding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var event: Event
|
||||
private var defaultLoaded = false
|
||||
|
||||
init { run {
|
||||
job = Job()
|
||||
|
||||
b = DialogEventManualV2Binding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.dialog_event_manual_title)
|
||||
.setView(b.root)
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(R.string.save) { _, _ -> saveEvent() }
|
||||
.show()
|
||||
|
||||
event = editingEvent?.clone() ?: Event().also { event ->
|
||||
event.profileId = profileId
|
||||
/*defaultDate?.let {
|
||||
event.eventDate = it
|
||||
b.date = it
|
||||
}
|
||||
defaultTime?.let {
|
||||
event.startTime = it
|
||||
b.time = it
|
||||
}
|
||||
defaultType?.let {
|
||||
event.type = it
|
||||
}*/
|
||||
}
|
||||
|
||||
loadLists()
|
||||
}}
|
||||
|
||||
private fun loadLists() { launch {
|
||||
val deferred = async(Dispatchers.Default) {
|
||||
// get the team list
|
||||
val teams = app.db.teamDao().getAllNow(profileId)
|
||||
b.teamDropdown.clear()
|
||||
b.teamDropdown += TextInputDropDown.Item(
|
||||
-1,
|
||||
activity.getString(R.string.dialog_event_manual_no_team),
|
||||
""
|
||||
)
|
||||
b.teamDropdown += teams.map { TextInputDropDown.Item(it.id, it.name, tag = it) }
|
||||
|
||||
// get the subject list
|
||||
val subjects = app.db.subjectDao().getAllNow(profileId)
|
||||
b.subjectDropdown.clear()
|
||||
b.subjectDropdown += TextInputDropDown.Item(
|
||||
-1,
|
||||
activity.getString(R.string.dialog_event_manual_no_subject),
|
||||
""
|
||||
)
|
||||
b.subjectDropdown += subjects.map { TextInputDropDown.Item(it.id, it.longName, tag = it) }
|
||||
|
||||
// get the teacher list
|
||||
val teachers = app.db.teacherDao().getAllNow(profileId)
|
||||
b.teacherDropdown.clear()
|
||||
b.teacherDropdown += TextInputDropDown.Item(
|
||||
-1,
|
||||
activity.getString(R.string.dialog_event_manual_no_teacher),
|
||||
""
|
||||
)
|
||||
b.teacherDropdown += teachers.map { TextInputDropDown.Item(it.id, it.fullName, tag = it) }
|
||||
}
|
||||
deferred.await()
|
||||
|
||||
b.teamDropdown.isEnabled = true
|
||||
b.subjectDropdown.isEnabled = true
|
||||
b.teacherDropdown.isEnabled = true
|
||||
|
||||
// copy IDs from event being edited
|
||||
editingEvent?.let {
|
||||
b.teamDropdown.select(it.teamId)
|
||||
b.subjectDropdown.select(it.subjectId)
|
||||
b.teacherDropdown.select(it.teacherId)
|
||||
}
|
||||
|
||||
// copy IDs from the LessonFull
|
||||
defaultLesson?.let {
|
||||
b.teamDropdown.select(it.displayTeamId)
|
||||
b.subjectDropdown.select(it.displaySubjectId)
|
||||
b.teacherDropdown.select(it.displayTeacherId)
|
||||
}
|
||||
|
||||
loadDates()
|
||||
}}
|
||||
|
||||
private fun loadDates() { launch {
|
||||
val date = Date.getToday()
|
||||
val today = date.value
|
||||
var weekDay = date.weekDay
|
||||
|
||||
val deferred = async(Dispatchers.Default) {
|
||||
val dates = mutableListOf<TextInputDropDown.Item>()
|
||||
// item choosing the next lesson of specific subject
|
||||
b.subjectDropdown.selected?.let {
|
||||
if (it.tag is Subject) {
|
||||
dates += TextInputDropDown.Item(
|
||||
-it.id,
|
||||
activity.getString(R.string.dialog_event_manual_date_next_lesson, it.tag.longName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODAY
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_today, date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
|
||||
// TOMORROW
|
||||
if (weekDay < 4) {
|
||||
date.stepForward(0, 0, 1)
|
||||
weekDay++
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_tomorrow, date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
}
|
||||
// REMAINING SCHOOL DAYS OF THE CURRENT WEEK
|
||||
while (weekDay < 4) {
|
||||
date.stepForward(0, 0, 1) // step one day forward
|
||||
weekDay++
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_this_week, Week.getFullDayName(weekDay), date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
}
|
||||
// go to next week Monday
|
||||
date.stepForward(0, 0, -weekDay + 7)
|
||||
weekDay = 0
|
||||
// ALL SCHOOL DAYS OF THE NEXT WEEK
|
||||
while (weekDay < 4) {
|
||||
dates += TextInputDropDown.Item(
|
||||
date.value.toLong(),
|
||||
activity.getString(R.string.dialog_event_manual_date_next_week, Week.getFullDayName(weekDay), date.formattedString),
|
||||
tag = date.clone()
|
||||
)
|
||||
date.stepForward(0, 0, 1) // step one day forward
|
||||
weekDay++
|
||||
}
|
||||
dates += TextInputDropDown.Item(
|
||||
-1L,
|
||||
activity.getString(R.string.dialog_event_manual_date_other)
|
||||
)
|
||||
dates
|
||||
}
|
||||
|
||||
val dates = deferred.await()
|
||||
b.dateDropdown.clear().append(dates)
|
||||
|
||||
editingEvent?.let {
|
||||
b.dateDropdown.select(it.eventDate.value.toLong())
|
||||
}
|
||||
|
||||
defaultLesson?.let {
|
||||
b.dateDropdown.select(it.displayDate?.value?.toLong())
|
||||
}
|
||||
|
||||
if (b.dateDropdown.selected == null) {
|
||||
b.dateDropdown.select(today.toLong())
|
||||
}
|
||||
|
||||
b.dateDropdown.isEnabled = true
|
||||
|
||||
b.dateDropdown.setOnChangeListener { item ->
|
||||
when {
|
||||
// next lesson with specified subject
|
||||
item.id < -1 -> {
|
||||
app.db.timetableDao().getNextWithSubject(profileId, Date.getToday(), -item.id).observeOnce(activity, Observer {
|
||||
val lessonDate = it?.displayDate ?: return@Observer
|
||||
b.dateDropdown.selected = TextInputDropDown.Item(
|
||||
lessonDate.value.toLong(),
|
||||
lessonDate.formattedString,
|
||||
tag = lessonDate
|
||||
)
|
||||
// TODO load correct hour when selecting next lesson
|
||||
b.dateDropdown.updateText()
|
||||
it.let {
|
||||
b.teamDropdown.select(it.displayTeamId)
|
||||
b.subjectDropdown.select(it.displaySubjectId)
|
||||
b.teacherDropdown.select(it.displayTeacherId)
|
||||
}
|
||||
defaultLoaded = false
|
||||
loadHours()
|
||||
})
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// custom date
|
||||
item.id == -1L -> {
|
||||
MaterialDatePicker.Builder
|
||||
.datePicker()
|
||||
.setSelection((b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: Date.getToday()).inMillis)
|
||||
.build()
|
||||
.apply {
|
||||
addOnPositiveButtonClickListener {
|
||||
val dateSelected = Date.fromMillis(it)
|
||||
b.dateDropdown.selected = TextInputDropDown.Item(
|
||||
dateSelected.value.toLong(),
|
||||
dateSelected.formattedString,
|
||||
tag = dateSelected
|
||||
)
|
||||
b.dateDropdown.updateText()
|
||||
loadHours()
|
||||
}
|
||||
show(this@EventManualV2Dialog.activity.supportFragmentManager, "MaterialDatePicker")
|
||||
}
|
||||
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// a specific date
|
||||
else -> {
|
||||
b.dateDropdown.select(item)
|
||||
loadHours()
|
||||
}
|
||||
}
|
||||
return@setOnChangeListener true
|
||||
}
|
||||
|
||||
loadHours()
|
||||
}}
|
||||
|
||||
private fun loadHours() {
|
||||
b.timeDropdown.isEnabled = false
|
||||
// get the selected date
|
||||
val date = b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: return
|
||||
// get all lessons for selected date
|
||||
app.db.timetableDao().getForDate(profileId, date).observeOnce(activity, Observer { lessons ->
|
||||
val hours = mutableListOf<TextInputDropDown.Item>()
|
||||
// add All day time choice
|
||||
hours += TextInputDropDown.Item(
|
||||
0L,
|
||||
activity.getString(R.string.dialog_event_manual_all_day)
|
||||
)
|
||||
lessons.forEach { lesson ->
|
||||
if (lesson.type == Lesson.TYPE_NO_LESSONS) {
|
||||
// indicate there are no lessons this day
|
||||
hours += TextInputDropDown.Item(
|
||||
-2L,
|
||||
activity.getString(R.string.dialog_event_manual_no_lessons)
|
||||
)
|
||||
return@forEach
|
||||
}
|
||||
// create the lesson caption
|
||||
val text = listOfNotEmpty(
|
||||
lesson.displayStartTime?.stringHM ?: "",
|
||||
lesson.displaySubjectName?.let {
|
||||
when {
|
||||
lesson.type == Lesson.TYPE_CANCELLED -> it.asStrikethroughSpannable()
|
||||
lesson.type != Lesson.TYPE_NORMAL -> it.asItalicSpannable()
|
||||
else -> it
|
||||
}
|
||||
} ?: ""
|
||||
)
|
||||
// add an item with LessonFull as the tag
|
||||
hours += TextInputDropDown.Item(
|
||||
lesson.displayStartTime?.value?.toLong() ?: -1,
|
||||
text.concat(" "),
|
||||
tag = lesson
|
||||
)
|
||||
}
|
||||
b.timeDropdown.clear().append(hours)
|
||||
|
||||
if (defaultLoaded) {
|
||||
b.timeDropdown.deselect()
|
||||
// select the TEAM_CLASS if possible
|
||||
b.teamDropdown.items.singleOrNull {
|
||||
it.tag is Team && it.tag.type == Team.TYPE_CLASS
|
||||
}?.let {
|
||||
b.teamDropdown.select(it)
|
||||
} ?: b.teamDropdown.deselect()
|
||||
|
||||
// clear subject, teacher selection
|
||||
b.subjectDropdown.deselect()
|
||||
b.teacherDropdown.deselect()
|
||||
}
|
||||
else {
|
||||
editingEvent?.let {
|
||||
b.timeDropdown.select(it.startTime?.value?.toLong())
|
||||
}
|
||||
|
||||
defaultLesson?.let {
|
||||
b.timeDropdown.select(it.displayStartTime?.value?.toLong())
|
||||
}
|
||||
}
|
||||
defaultLoaded = true
|
||||
b.timeDropdown.isEnabled = true
|
||||
|
||||
// attach a listener to time dropdown
|
||||
b.timeDropdown.setOnChangeListener { item ->
|
||||
when {
|
||||
// custom start hour
|
||||
item.id == -1L -> {
|
||||
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// no lessons this day
|
||||
item.id == -2L -> {
|
||||
b.timeDropdown.deselect()
|
||||
return@setOnChangeListener false
|
||||
}
|
||||
// selected a specific lesson
|
||||
else -> {
|
||||
if (item.tag is LessonFull) {
|
||||
// update team, subject, teacher dropdowns,
|
||||
// using the LessonFull from item tag
|
||||
b.teamDropdown.deselect()
|
||||
b.subjectDropdown.deselect()
|
||||
b.teacherDropdown.deselect()
|
||||
item.tag.displayTeamId?.let {
|
||||
b.teamDropdown.select(it)
|
||||
}
|
||||
item.tag.displaySubjectId?.let {
|
||||
b.subjectDropdown.select(it)
|
||||
}
|
||||
item.tag.displayTeacherId?.let {
|
||||
b.teacherDropdown.select(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return@setOnChangeListener true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun saveEvent() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-11.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.timetable
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonDetailsBinding
|
||||
import pl.szczodrzynski.edziennik.setText
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualV2Dialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
|
||||
class LessonDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val lesson: LessonFull
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "LessonDetailsDialog"
|
||||
}
|
||||
|
||||
private lateinit var b: DialogLessonDetailsBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
b = DialogLessonDetailsBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.add) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
EventManualV2Dialog(activity, lesson.profileId, lesson)
|
||||
/*MaterialAlertDialogBuilder(activity)
|
||||
.setItems(R.array.main_menu_add_options) { dialog2, which ->
|
||||
dialog2.dismiss()
|
||||
EventManualDialog(activity, lesson.profileId)
|
||||
.show(
|
||||
activity.application as App,
|
||||
null,
|
||||
lesson.displayDate,
|
||||
lesson.displayStartTime,
|
||||
when (which) {
|
||||
1 -> EventManualDialog.DIALOG_HOMEWORK
|
||||
else -> EventManualDialog.DIALOG_EVENT
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog2, _ -> dialog2.dismiss() }
|
||||
.show()*/
|
||||
}
|
||||
.show()
|
||||
update()
|
||||
}}
|
||||
|
||||
private fun update() {
|
||||
b.lesson = lesson
|
||||
val lessonDate = lesson.displayDate ?: return
|
||||
b.lessonDate.text = Week.getFullDayName(lessonDate.weekDay) + ", " + lessonDate.formattedString
|
||||
|
||||
if (lesson.type >= Lesson.TYPE_SHIFTED_SOURCE) {
|
||||
b.shiftedLayout.visibility = View.VISIBLE
|
||||
var otherLessonDate: Date? = null
|
||||
when (lesson.type) {
|
||||
Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||
otherLessonDate = lesson.date
|
||||
when {
|
||||
lesson.date != lesson.oldDate -> b.shiftedText.setText(
|
||||
R.string.timetable_lesson_shifted_other_day,
|
||||
lesson.date?.stringY_m_d ?: "?",
|
||||
lesson.startTime?.stringHM ?: "?"
|
||||
)
|
||||
lesson.startTime != lesson.oldStartTime -> b.shiftedText.setText(
|
||||
R.string.timetable_lesson_shifted_same_day,
|
||||
lesson.startTime?.stringHM ?: "?"
|
||||
)
|
||||
else -> b.shiftedText.setText(R.string.timetable_lesson_shifted)
|
||||
}
|
||||
}
|
||||
Lesson.TYPE_SHIFTED_TARGET -> {
|
||||
otherLessonDate = lesson.oldDate
|
||||
when {
|
||||
lesson.date != lesson.oldDate -> b.shiftedText.setText(
|
||||
R.string.timetable_lesson_shifted_from_other_day,
|
||||
lesson.oldDate?.stringY_m_d ?: "?",
|
||||
lesson.oldStartTime?.stringHM ?: "?"
|
||||
)
|
||||
lesson.startTime != lesson.oldStartTime -> b.shiftedText.setText(
|
||||
R.string.timetable_lesson_shifted_from_same_day,
|
||||
lesson.oldStartTime?.stringHM ?: "?"
|
||||
)
|
||||
else -> b.shiftedText.setText(R.string.timetable_lesson_shifted_from)
|
||||
}
|
||||
}
|
||||
}
|
||||
b.shiftedGoTo.setOnClickListener {
|
||||
dialog.dismiss()
|
||||
val dateStr = otherLessonDate?.stringY_m_d ?: return@setOnClickListener
|
||||
val intent = Intent(TimetableFragment.ACTION_SCROLL_TO_DATE).apply {
|
||||
putExtra("date", dateStr)
|
||||
}
|
||||
activity.sendBroadcast(intent)
|
||||
}
|
||||
}
|
||||
else {
|
||||
b.shiftedLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldSubjectId != null && lesson.subjectId != lesson.oldSubjectId) {
|
||||
b.oldSubjectName = lesson.oldSubjectName
|
||||
}
|
||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.subjectId != null) {
|
||||
b.subjectName = lesson.subjectName
|
||||
}
|
||||
|
||||
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldTeacherId != null && lesson.teacherId != lesson.oldTeacherId) {
|
||||
b.oldTeacherName = lesson.oldTeacherName
|
||||
}
|
||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.teacherId != null) {
|
||||
b.teacherName = lesson.teacherName
|
||||
}
|
||||
|
||||
if (lesson.oldClassroom != null && lesson.classroom != lesson.oldClassroom) {
|
||||
b.oldClassroom = lesson.oldClassroom
|
||||
}
|
||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.classroom != null) {
|
||||
b.classroom = lesson.classroom
|
||||
}
|
||||
|
||||
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldTeamId != null && lesson.teamId != lesson.oldTeamId) {
|
||||
b.oldTeamName = lesson.oldTeamName
|
||||
}
|
||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.teamId != null) {
|
||||
b.teamName = lesson.teamName
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.messages
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.text.Html
|
||||
import android.text.TextUtils
|
||||
import android.view.Gravity.CENTER_VERTICAL
|
||||
import android.view.Gravity.END
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ProgressBar
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.mikepenz.iconics.IconicsColor
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.IconicsSize
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.coroutines.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
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.MessageGetEvent
|
||||
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.databinding.MessageFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import pl.szczodrzynski.edziennik.utils.Anim
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.getStringFromFile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.readableFileSize
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.navlib.colorAttr
|
||||
import java.io.File
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.math.min
|
||||
|
||||
class MessageFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "MessageFragment"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: MessageFragmentBinding
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private lateinit var message: MessageFull
|
||||
private var attachmentList = mutableListOf<Attachment>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as MainActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
context!!.theme.applyStyle(Themes.appTheme, true)
|
||||
b = MessageFragmentBinding.inflate(inflater)
|
||||
job = Job()
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
// TODO check if app, activity, b can be null
|
||||
if (app.profile == null || !isAdded)
|
||||
return
|
||||
|
||||
b.closeButton.setImageDrawable(
|
||||
IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_window_close)
|
||||
.colorAttr(activity, android.R.attr.textColorSecondary)
|
||||
.sizeDp(12)
|
||||
)
|
||||
b.closeButton.setOnClickListener { activity.navigateUp() }
|
||||
|
||||
val messageId = arguments?.getLong("messageId")
|
||||
if (messageId == null) {
|
||||
activity.navigateUp()
|
||||
return
|
||||
}
|
||||
|
||||
launch {
|
||||
val deferred = async(Dispatchers.Default) {
|
||||
val msg = app.db.messageDao().getById(App.profileId, messageId)?.also {
|
||||
it.recipients = app.db.messageRecipientDao().getAllByMessageId(it.profileId, it.id)
|
||||
if (it.body != null && !it.seen) {
|
||||
app.db.metadataDao().setSeen(it.profileId, message, true)
|
||||
}
|
||||
}
|
||||
msg
|
||||
}
|
||||
val msg = deferred.await() ?: run {
|
||||
return@launch
|
||||
}
|
||||
message = msg
|
||||
b.subject.text = message.subject
|
||||
checkMessage()
|
||||
}
|
||||
|
||||
// click to expand subject and sender
|
||||
b.subject.onClick {
|
||||
it.maxLines = if (it.maxLines == 30) 2 else 30
|
||||
}
|
||||
b.sender.onClick {
|
||||
it.maxLines = if (it.maxLines == 30) 2 else 30
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onMessageGetEvent(event: MessageGetEvent) {
|
||||
// TODO remove this: message = event.message
|
||||
showMessage()
|
||||
}
|
||||
|
||||
private fun checkMessage() {
|
||||
if (message.body == null) {
|
||||
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||
return
|
||||
}
|
||||
|
||||
var readByAll = true
|
||||
message.recipients?.forEach { recipient ->
|
||||
if (recipient.id == -1L)
|
||||
recipient.fullName = app.profile.accountNameLong ?: app.profile.studentNameLong
|
||||
if (message.type == TYPE_SENT && recipient.readDate < 1)
|
||||
readByAll = false
|
||||
}
|
||||
// if a sent msg is not read by everyone, download it again to check the read status
|
||||
if (!readByAll) {
|
||||
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||
return
|
||||
}
|
||||
|
||||
showMessage()
|
||||
}
|
||||
|
||||
private fun showMessage() {
|
||||
b.body.text = Html.fromHtml(message.body?.replace("\\[META:[A-z0-9]+;[0-9-]+]".toRegex(), ""))
|
||||
b.date.text = getString(R.string.messages_date_time_format, Date.fromMillis(message.addedDate).formattedStringShort, Time.fromMillis(message.addedDate).stringHM)
|
||||
|
||||
val messageInfo = MessagesUtils.getMessageInfo(app, message, 40, 20, 14, 10)
|
||||
b.profileBackground.setImageBitmap(messageInfo.profileImage)
|
||||
b.sender.text = messageInfo.profileName
|
||||
|
||||
b.subject.text = message.subject
|
||||
|
||||
val messageRecipients = StringBuilder("<ul>")
|
||||
message.recipients?.forEach { recipient ->
|
||||
when (recipient.readDate) {
|
||||
-1L -> messageRecipients.append(getString(
|
||||
R.string.messages_recipients_list_unknown_state_format,
|
||||
recipient.fullName
|
||||
))
|
||||
0L -> messageRecipients.append(getString(
|
||||
R.string.messages_recipients_list_unread_format,
|
||||
recipient.fullName
|
||||
))
|
||||
1L -> messageRecipients.append(getString(
|
||||
R.string.messages_recipients_list_read_unknown_date_format,
|
||||
recipient.fullName
|
||||
))
|
||||
else -> messageRecipients.append(getString(
|
||||
R.string.messages_recipients_list_read_format,
|
||||
recipient.fullName,
|
||||
Date.fromMillis(recipient.readDate).formattedString,
|
||||
Time.fromMillis(recipient.readDate).stringHM
|
||||
))
|
||||
}
|
||||
}
|
||||
messageRecipients.append("</ul>")
|
||||
b.recipients.text = Html.fromHtml(messageRecipients.toString())
|
||||
|
||||
showAttachments()
|
||||
|
||||
b.progress.visibility = View.GONE
|
||||
Anim.fadeIn(b.content, 200, null)
|
||||
MessagesFragment.pageSelection = min(message.type, 1)
|
||||
}
|
||||
|
||||
private fun showAttachments() {
|
||||
if (message.attachmentIds != null) {
|
||||
val insertPoint = b.attachments
|
||||
|
||||
val chipLayoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
chipLayoutParams.setMargins(0, Utils.dpToPx(8), 0, Utils.dpToPx(8))
|
||||
|
||||
val progressLayoutParams = FrameLayout.LayoutParams(Utils.dpToPx(18), Utils.dpToPx(18))
|
||||
progressLayoutParams.setMargins(Utils.dpToPx(8), 0, Utils.dpToPx(8), 0)
|
||||
progressLayoutParams.gravity = END or CENTER_VERTICAL
|
||||
|
||||
// CREATE VIEWS AND AN OBJECT FOR EVERY ATTACHMENT
|
||||
|
||||
message.attachmentNames.forEachIndexed { index, name ->
|
||||
val messageId = message.id
|
||||
val id = message.attachmentIds[index]
|
||||
val size = message.attachmentSizes[index]
|
||||
// create the parent
|
||||
val attachmentLayout = FrameLayout(b.root.context)
|
||||
attachmentLayout.setPadding(Utils.dpToPx(16), 0, Utils.dpToPx(16), 0)
|
||||
|
||||
val attachmentChip = Chip(attachmentLayout.context)
|
||||
//attachmentChip.setChipBackgroundColorResource(ThemeUtils.getChipColorRes());
|
||||
attachmentChip.layoutParams = chipLayoutParams
|
||||
attachmentChip.height = Utils.dpToPx(40)
|
||||
|
||||
// show the file size or not
|
||||
if (size == -1L)
|
||||
attachmentChip.text = getString(R.string.messages_attachment_no_size_format, name)
|
||||
else
|
||||
attachmentChip.text = getString(R.string.messages_attachment_format, name, readableFileSize(size))
|
||||
attachmentChip.ellipsize = TextUtils.TruncateAt.MIDDLE
|
||||
|
||||
// create an icon for the attachment
|
||||
var icon: IIcon = CommunityMaterial.Icon.cmd_file
|
||||
when (Utils.getExtensionFromFileName(name)) {
|
||||
"txt" -> icon = CommunityMaterial.Icon.cmd_file_document
|
||||
"doc", "docx", "odt", "rtf" -> icon = CommunityMaterial.Icon.cmd_file_word
|
||||
"xls", "xlsx", "ods" -> icon = CommunityMaterial.Icon.cmd_file_excel
|
||||
"ppt", "pptx", "odp" -> icon = CommunityMaterial.Icon.cmd_file_powerpoint
|
||||
"pdf" -> icon = CommunityMaterial.Icon.cmd_file_pdf
|
||||
"mp3", "wav", "aac" -> icon = CommunityMaterial.Icon.cmd_file_music
|
||||
"mp4", "avi", "3gp", "mkv", "flv" -> icon = CommunityMaterial.Icon.cmd_file_video
|
||||
"jpg", "jpeg", "png", "bmp", "gif" -> icon = CommunityMaterial.Icon.cmd_file_image
|
||||
"zip", "rar", "tar", "7z" -> icon = CommunityMaterial.Icon.cmd_file_lock
|
||||
}
|
||||
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)))
|
||||
attachmentChip.isCloseIconVisible = false
|
||||
// set the object's index in the attachmentList as the tag
|
||||
attachmentChip.tag = index
|
||||
attachmentChip.setOnClickListener { v ->
|
||||
if (v.tag is Int) {
|
||||
// TODO downloadAttachment(v.tag as Int)
|
||||
}
|
||||
}
|
||||
attachmentLayout.addView(attachmentChip)
|
||||
|
||||
val attachmentProgress = ProgressBar(attachmentLayout.context)
|
||||
attachmentProgress.layoutParams = progressLayoutParams
|
||||
attachmentProgress.visibility = View.GONE
|
||||
attachmentLayout.addView(attachmentProgress)
|
||||
|
||||
insertPoint.addView(attachmentLayout)
|
||||
// create an object and add to the list
|
||||
val a = Attachment(App.profileId, messageId, id, name, size, attachmentLayout, attachmentChip, attachmentProgress)
|
||||
attachmentList.add(a)
|
||||
// check if the file is already downloaded. Show the check icon if necessary and set `downloaded` to true.
|
||||
checkAttachment(a)
|
||||
|
||||
}
|
||||
} else {
|
||||
// no attachments found
|
||||
b.attachmentsTitle.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAttachment(attachment: Attachment) {
|
||||
val storageDir = Environment.getExternalStoragePublicDirectory("Szkolny.eu")
|
||||
storageDir.mkdirs()
|
||||
|
||||
val attachmentDataFile = File(storageDir, "." + attachment.profileId + "_" + attachment.messageId + "_" + attachment.attachmentId)
|
||||
if (attachmentDataFile.exists()) {
|
||||
try {
|
||||
val attachmentFileName = getStringFromFile(attachmentDataFile)
|
||||
val attachmentFile = File(attachmentFileName)
|
||||
if (attachmentFile.exists()) {
|
||||
attachment.downloaded = attachmentFileName
|
||||
attachment.chip.isCloseIconVisible = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
//app.apiEdziennik.guiReportException(activity, 355, e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
EventBus.getDefault().register(this)
|
||||
super.onStart()
|
||||
}
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
private class Attachment(
|
||||
var profileId: Int,
|
||||
var messageId: Long,
|
||||
var attachmentId: Long,
|
||||
var attachmentName: String,
|
||||
var attachmentSize: Long,
|
||||
var parent: FrameLayout,
|
||||
var chip: Chip,
|
||||
var progressBar: ProgressBar
|
||||
) {
|
||||
/**
|
||||
* An absolute path of the downloaded file. `null` if not downloaded yet.
|
||||
*/
|
||||
internal var downloaded: String? = null
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package pl.szczodrzynski.edziennik.ui.modules.messages
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.text.InputType
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -10,18 +8,14 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentPagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
||||
import pl.szczodrzynski.edziennik.api.v2.events.ApiTaskErrorEvent
|
||||
import pl.szczodrzynski.edziennik.api.v2.events.ApiTaskFinishedEvent
|
||||
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentMessagesBinding
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
@ -92,7 +86,7 @@ class MessagesFragment : Fragment() {
|
||||
|
||||
b.tabLayout.setupWithViewPager(b.viewPager)
|
||||
|
||||
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getStudentData("accountPassword", null) == null) {
|
||||
/*if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getStudentData("accountPassword", null) == null) {
|
||||
MaterialDialog.Builder(activity)
|
||||
.title("Wiadomości w systemie Synergia")
|
||||
.content("Moduł Wiadomości w aplikacji Szkolny.eu jest przeglądarką zasobów szkolnego konta Synergia. Z tego powodu, musisz wpisać swoje hasło do tego konta, aby móc korzystać z tej funkcji.")
|
||||
@ -115,7 +109,7 @@ class MessagesFragment : Fragment() {
|
||||
.show()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
|
@ -1,5 +1,9 @@
|
||||
package pl.szczodrzynski.edziennik.ui.modules.timetable.v2
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -18,12 +22,14 @@ import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
class TimetableFragment : Fragment() {
|
||||
companion object {
|
||||
private const val TAG = "TimetableFragment"
|
||||
const val ACTION_SCROLL_TO_DATE = "pl.szczodrzynski.edziennik.timetable.SCROLL_TO_DATE"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: FragmentTimetableV2Binding
|
||||
private var fabShown = false
|
||||
private val items = mutableListOf<Date>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as MainActivity?) ?: return null
|
||||
@ -38,6 +44,24 @@ class TimetableFragment : Fragment() {
|
||||
return b.root
|
||||
}
|
||||
|
||||
private val broadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, i: Intent) {
|
||||
if (!isAdded)
|
||||
return
|
||||
val dateStr = i.extras?.getString("date", null) ?: return
|
||||
val date = Date.fromY_m_d(dateStr)
|
||||
b.viewPager.setCurrentItem(items.indexOf(date), true)
|
||||
}
|
||||
}
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
activity.registerReceiver(broadcastReceiver, IntentFilter(ACTION_SCROLL_TO_DATE))
|
||||
}
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
activity.unregisterReceiver(broadcastReceiver)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
// TODO check if app, activity, b can be null
|
||||
if (app.profile == null || !isAdded)
|
||||
@ -51,7 +75,7 @@ class TimetableFragment : Fragment() {
|
||||
b.timetableLayout.visibility = View.VISIBLE
|
||||
b.timetableNotPublicLayout.visibility = View.GONE
|
||||
|
||||
val items = mutableListOf<Date>()
|
||||
items.clear()
|
||||
|
||||
val monthDayCount = listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
|
||||
@ -99,7 +123,7 @@ class TimetableFragment : Fragment() {
|
||||
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, false)
|
||||
|
||||
//activity.navView.bottomBar.fabEnable = true
|
||||
activity.navView.bottomBar.fabExtendedText = getString(R.string.timetable_today)
|
||||
activity.navView.bottomBar.fabExtendedText = getString(pl.szczodrzynski.edziennik.R.string.timetable_today)
|
||||
activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon.cmd_calendar_today
|
||||
activity.navView.setFabOnClickListener(View.OnClickListener {
|
||||
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, true)
|
||||
|
@ -19,6 +19,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2DayBinding
|
||||
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.navlib.getColorFromAttr
|
||||
import java.util.*
|
||||
@ -70,7 +71,8 @@ class TimetableDayFragment(val date: Date) : Fragment() {
|
||||
b.noTimetableLayout.visibility = View.VISIBLE
|
||||
b.noLessonsLayout.visibility = View.GONE
|
||||
val weekStart = date.clone().stepForward(0, 0, -date.weekDay).stringY_m_d
|
||||
b.noTimetableSync.setOnClickListener {
|
||||
b.noTimetableSync.onClick {
|
||||
it.isEnabled = false
|
||||
EdziennikTask.syncProfile(
|
||||
profileId = App.profileId,
|
||||
viewIds = listOf(
|
||||
@ -133,6 +135,8 @@ class TimetableDayFragment(val date: Date) : Fragment() {
|
||||
|
||||
eventView.setOnClickListener {
|
||||
Log.d(TAG, "Clicked ${it.tag}")
|
||||
if (isAdded && it.tag is LessonFull)
|
||||
LessonDetailsDialog(activity, it.tag as LessonFull)
|
||||
}
|
||||
|
||||
|
||||
@ -221,21 +225,17 @@ class TimetableDayFragment(val date: Date) : Fragment() {
|
||||
}
|
||||
Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||
lb.annotationVisible = true
|
||||
if (lesson.date != lesson.oldDate) {
|
||||
lb.annotation.setText(
|
||||
when {
|
||||
lesson.date != lesson.oldDate -> lb.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_other_day,
|
||||
lesson.date?.stringY_m_d ?: "?",
|
||||
lesson.startTime?.stringHM ?: "?"
|
||||
)
|
||||
}
|
||||
else if (lesson.startTime != lesson.oldStartTime) {
|
||||
lb.annotation.setText(
|
||||
lesson.startTime != lesson.oldStartTime -> lb.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_same_day,
|
||||
lesson.startTime?.stringHM ?: "?"
|
||||
)
|
||||
}
|
||||
else {
|
||||
lb.annotation.setText(R.string.timetable_lesson_shifted)
|
||||
else -> lb.annotation.setText(R.string.timetable_lesson_shifted)
|
||||
}
|
||||
|
||||
lb.annotation.background.colorFilter = PorterDuffColorFilter(
|
||||
@ -245,21 +245,17 @@ class TimetableDayFragment(val date: Date) : Fragment() {
|
||||
}
|
||||
Lesson.TYPE_SHIFTED_TARGET -> {
|
||||
lb.annotationVisible = true
|
||||
if (lesson.date != lesson.oldDate) {
|
||||
lb.annotation.setText(
|
||||
when {
|
||||
lesson.date != lesson.oldDate -> lb.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_from_other_day,
|
||||
lesson.oldDate?.stringY_m_d ?: "?",
|
||||
lesson.oldStartTime?.stringHM ?: "?"
|
||||
)
|
||||
}
|
||||
else if (lesson.startTime != lesson.oldStartTime) {
|
||||
lb.annotation.setText(
|
||||
lesson.startTime != lesson.oldStartTime -> lb.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_from_same_day,
|
||||
lesson.oldStartTime?.stringHM ?: "?"
|
||||
)
|
||||
}
|
||||
else {
|
||||
lb.annotation.setText(R.string.timetable_lesson_shifted_from)
|
||||
else -> lb.annotation.setText(R.string.timetable_lesson_shifted_from)
|
||||
}
|
||||
|
||||
lb.annotation.background.colorFilter = PorterDuffColorFilter(
|
||||
|
@ -1,55 +0,0 @@
|
||||
package pl.szczodrzynski.edziennik.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import pl.szczodrzynski.edziennik.R;
|
||||
|
||||
public class TextInputDropDown extends TextInputEditText {
|
||||
public TextInputDropDown(Context context) {
|
||||
super(context);
|
||||
create(context);
|
||||
}
|
||||
|
||||
public TextInputDropDown(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
create(context);
|
||||
}
|
||||
|
||||
public TextInputDropDown(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
create(context);
|
||||
}
|
||||
|
||||
public void create(Context context) {
|
||||
Drawable drawable = context.getResources().getDrawable(R.drawable.dropdown_arrow);
|
||||
Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
|
||||
DrawableCompat.setTint(wrappedDrawable, Themes.INSTANCE.getPrimaryTextColor(context));
|
||||
|
||||
setCompoundDrawablesWithIntrinsicBounds(null, null, wrappedDrawable, null);
|
||||
setFocusableInTouchMode(false);
|
||||
setCursorVisible(false);
|
||||
setLongClickable(false);
|
||||
setMaxLines(1);
|
||||
setInputType(0);
|
||||
setKeyListener(null);
|
||||
setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
v.setFocusableInTouchMode(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public final void setOnClickListener(OnClickListener onClickListener) {
|
||||
super.setOnClickListener(v -> {
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
onClickListener.onClick(v);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package pl.szczodrzynski.edziennik.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
|
||||
class TextInputDropDown : TextInputEditText {
|
||||
constructor(context: Context) : super(context) {
|
||||
create(context)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
create(context)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
create(context)
|
||||
}
|
||||
|
||||
var items = mutableListOf<Item>()
|
||||
private var onChangeListener: ((item: Item) -> Boolean)? = null
|
||||
|
||||
var selected: Item? = null
|
||||
val selectedId
|
||||
get() = selected?.id
|
||||
|
||||
fun updateText() {
|
||||
setText(selected?.displayText ?: selected?.text)
|
||||
}
|
||||
|
||||
fun create(context: Context) {
|
||||
val drawable = context.resources.getDrawable(R.drawable.dropdown_arrow)
|
||||
val wrappedDrawable = DrawableCompat.wrap(drawable)
|
||||
DrawableCompat.setTint(wrappedDrawable, Themes.getPrimaryTextColor(context))
|
||||
|
||||
setCompoundDrawablesWithIntrinsicBounds(null, null, wrappedDrawable, null)
|
||||
isFocusableInTouchMode = false
|
||||
isCursorVisible = false
|
||||
isLongClickable = false
|
||||
maxLines = 1
|
||||
inputType = 0
|
||||
keyListener = null
|
||||
setOnFocusChangeListener { v, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
v.isFocusableInTouchMode = false
|
||||
}
|
||||
}
|
||||
|
||||
setOnClickListener {
|
||||
isFocusableInTouchMode = true
|
||||
requestFocus()
|
||||
val popup = PopupMenu(context, this)
|
||||
|
||||
items.forEachIndexed { index, item ->
|
||||
popup.menu.add(0, item.id.toInt(), index, item.text)
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener { menuItem ->
|
||||
val item = items[menuItem.order]
|
||||
if (onChangeListener?.invoke(item) != false) {
|
||||
select(item)
|
||||
}
|
||||
clearFocus()
|
||||
true
|
||||
}
|
||||
|
||||
popup.setOnDismissListener {
|
||||
clearFocus()
|
||||
}
|
||||
|
||||
popup.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun select(item: Item) {
|
||||
selected = item
|
||||
updateText()
|
||||
}
|
||||
|
||||
fun select(id: Long?) {
|
||||
items.singleOrNull { it.id == id }?.let { select(it) }
|
||||
}
|
||||
|
||||
fun select(tag: Any?) {
|
||||
items.singleOrNull { it.tag == tag }?.let { select(it) }
|
||||
}
|
||||
|
||||
fun select(index: Int) {
|
||||
items.getOrNull(index)?.let { select(it) }
|
||||
}
|
||||
|
||||
fun deselect(): TextInputDropDown {
|
||||
selected = null
|
||||
text = null
|
||||
return this
|
||||
}
|
||||
|
||||
fun clear(): TextInputDropDown {
|
||||
items.clear()
|
||||
return this
|
||||
}
|
||||
|
||||
fun append(items: List<Item>): TextInputDropDown {
|
||||
this.items.addAll(items)
|
||||
return this
|
||||
}
|
||||
|
||||
fun prepend(items: List<Item>): TextInputDropDown{
|
||||
this.items.addAll(0, items)
|
||||
return this
|
||||
}
|
||||
|
||||
operator fun plusAssign(items: Item) {
|
||||
this.items.add(items)
|
||||
}
|
||||
operator fun plusAssign(items: List<Item>) {
|
||||
this.items.addAll(items)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the listener called when other item is selected.
|
||||
*
|
||||
* The listener should return true to allow the item to be selected, false otherwise.
|
||||
*/
|
||||
fun setOnChangeListener(onChangeListener: ((item: Item) -> Boolean)? = null): TextInputDropDown {
|
||||
this.onChangeListener = onChangeListener
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setOnClickListener(onClickListener: OnClickListener?) {
|
||||
super.setOnClickListener { v ->
|
||||
isFocusableInTouchMode = true
|
||||
requestFocus()
|
||||
onClickListener!!.onClick(v)
|
||||
}
|
||||
}
|
||||
|
||||
class Item(val id: Long, val text: CharSequence, val displayText: CharSequence? = null, val tag: Any? = null)
|
||||
}
|
@ -97,7 +97,8 @@
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/dialog_event_manual_share_first_notice"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
102
app/src/main/res/layout/dialog_event_manual_v2.xml
Normal file
102
app/src/main/res/layout/dialog_event_manual_v2.xml
Normal file
@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:padding="24dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/dialog_event_manual_date">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/dateDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="13 listopada"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_time">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/timeDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="8:10 - język polski"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_team">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/teamDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="2b3T"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_subject">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/subjectDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="2b3T"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_teacher">
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/teacherDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="2b3T"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_topic">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/topic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textLongMessage|textMultiLine|textImeMultiLine"
|
||||
android:minLines="2"
|
||||
tools:text="2b3T" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
237
app/src/main/res/layout/dialog_lesson_details.xml
Normal file
237
app/src/main/res/layout/dialog_lesson_details.xml
Normal file
@ -0,0 +1,237 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-11.
|
||||
-->
|
||||
|
||||
<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">
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="pl.szczodrzynski.edziennik.App"/>
|
||||
<variable
|
||||
name="lesson"
|
||||
type="pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull" />
|
||||
<variable name="oldSubjectName" type="String" />
|
||||
<variable name="subjectName" type="String" />
|
||||
<variable name="oldTeacherName" type="String" />
|
||||
<variable name="teacherName" type="String" />
|
||||
<variable name="oldClassroom" type="String" />
|
||||
<variable name="classroom" type="String" />
|
||||
<variable name="oldTeamName" type="String" />
|
||||
<variable name="teamName" type="String" />
|
||||
</data>
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{oldSubjectName}"
|
||||
android:textIsSelectable="true"
|
||||
android:textAppearance="@style/NavView.TextView.Medium"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
android:visibility="@{oldSubjectName == null ? View.GONE : View.VISIBLE}"
|
||||
app:strikeThrough="@{true}"
|
||||
tools:text="pracownia urządzeń techniki komputerowej" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{subjectName}"
|
||||
android:textIsSelectable="true"
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
android:visibility="@{subjectName == null ? View.GONE : View.VISIBLE}"
|
||||
tools:text="pracownia urządzeń techniki komputerowej" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lessonDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textIsSelectable="true"
|
||||
android:textAppearance="@style/NavView.TextView.Subtitle"
|
||||
tools:text="czwartek, 14 listopada 2019"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@string/dialog_lesson_details_number"
|
||||
android:visibility="@{lesson.displayLessonNumber == null ? View.GONE : View.VISIBLE}"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:text="@{lesson.displayLessonNumber.toString()}"
|
||||
android:textSize="36sp"
|
||||
android:visibility="@{lesson.displayLessonNumber == null ? View.GONE : View.VISIBLE}"
|
||||
tools:text="4" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{lesson.displayStartTime.stringHM + ` - ` + lesson.displayEndTime.stringHM}"
|
||||
tools:text="14:55 - 15:40" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/shiftedLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/shiftedText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="italic"
|
||||
tools:text="Lekcja przeniesiona na czwartek, 17 października" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/shiftedGoTo"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Przejdź" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@string/dialog_lesson_details_teacher"
|
||||
android:visibility="@{teacherName != null || oldTeacherName != null ? View.VISIBLE : View.GONE}"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@{oldTeacherName}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{oldTeacherName != null ? View.VISIBLE : View.GONE}"
|
||||
app:strikeThrough="@{true}"
|
||||
tools:text="Janósz Kowalski" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{teacherName}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{teacherName != null ? View.VISIBLE : View.GONE}"
|
||||
tools:text="Janósz Kowalski" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@string/dialog_lesson_details_classroom"
|
||||
android:visibility="@{classroom != null || oldClassroom != null ? View.VISIBLE : View.GONE}"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@{oldClassroom}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{oldClassroom != null ? View.VISIBLE : View.GONE}"
|
||||
app:strikeThrough="@{true}"
|
||||
tools:text="013 informatyczna" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{classroom}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{classroom != null ? View.VISIBLE : View.GONE}"
|
||||
tools:text="013 informatyczna" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@string/dialog_lesson_details_team"
|
||||
android:visibility="@{teamName != null || oldTeamName != null ? View.VISIBLE : View.GONE}"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:text="@{oldTeamName}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{oldTeamName != null ? View.VISIBLE : View.GONE}"
|
||||
app:strikeThrough="@{true}"
|
||||
tools:text="013 informatyczna" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{teamName}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{teamName != null ? View.VISIBLE : View.GONE}"
|
||||
tools:text="013 informatyczna" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
android:visibility="@{App.devMode ? View.VISIBLE : View.GONE}"
|
||||
android:text="@string/dialog_lesson_details_id" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="0dp"
|
||||
android:text="@{Long.toString(lesson.id)}"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="@{App.devMode ? View.VISIBLE : View.GONE}"
|
||||
tools:text="12345" />
|
||||
|
||||
<!--<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/gradeHistoryNest"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="@{historyVisible ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/gradeHistoryList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:listitem="@layout/row_grades_list_item" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>-->
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
353
app/src/main/res/layout/message_fragment.xml
Normal file
353
app/src/main/res/layout/message_fragment.xml
Normal file
@ -0,0 +1,353 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-12.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:orientation="horizontal"
|
||||
android:background="@color/colorSurface_6dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/closeButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="?android:attr/actionBarItemBackground"
|
||||
app:srcCompat="@android:drawable/ic_delete" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subject"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="?selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:padding="16dp"
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
tools:ignore="HardcodedText"
|
||||
tools:text="mobiDziennik - raport dzienny." />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="@drawable/shadow_top" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="visible"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/profileBackground"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:padding="12dp"
|
||||
app:srcCompat="@drawable/bg_circle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profileName"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="20sp"
|
||||
tools:text="JP"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/profileImage"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:padding="12dp"
|
||||
android:visibility="gone"
|
||||
tools:srcCompat="@tools:sample/avatars[0]" />
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sender"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingRight="8dp"
|
||||
android:textAppearance="@style/NavView.TextView.Subtitle"
|
||||
tools:text="Allegro - wysyłamy duużo wiadomości!!! Masz nowe oferty! Możesz kupić nowego laptopa! Ale super! Ehh, to jest nadawca a nie temat więc nwm czemu to tutaj wpisałem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:textAppearance="@style/NavView.TextView.Small"
|
||||
tools:text="14:26" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/body"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:autoLink="all"
|
||||
android:minHeight="250dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="To jest treść wiadomości.\n\nZazwyczaj ma wiele linijek.\n\nTak" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?colorControlHighlight" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="Odbiorcy wiadomości:"
|
||||
android:textAppearance="@style/NavView.TextView.Subtitle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/recipients"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
tools:text=" - Jan Kowalski, przeczytano: nie\n - Adam Dodatkowy, przeczytano: 20 marca, 17:35" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/attachmentsTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="Załączniki:"
|
||||
android:textAppearance="@style/NavView.TextView.Subtitle" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/attachments"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:text="Testowy plik.pdf"
|
||||
android:visibility="visible"
|
||||
app:chipBackgroundColor="@color/mtrl_chip_background_color"
|
||||
app:chipIcon="@drawable/googleg_standard_color_18"
|
||||
app:chipMinHeight="36dp"
|
||||
app:chipSurfaceColor="@color/mtrl_chip_surface_color"
|
||||
app:closeIcon="@drawable/ic_error_outline"
|
||||
app:closeIconVisible="true" />
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:text="Wyniki sprawdzianu z matematyki.pdf"
|
||||
android:visibility="visible"
|
||||
app:chipIcon="@drawable/googleg_standard_color_18"
|
||||
app:chipMinHeight="36dp" />
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
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">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Odpowiedz"
|
||||
android:textAppearance="@style/NavView.TextView.Small" />
|
||||
|
||||
<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-reply"
|
||||
tools:srcCompat="@android:drawable/ic_menu_revert" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
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">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Przekaż dalej"
|
||||
android:textAllCaps="false"
|
||||
android:textAppearance="@style/NavView.TextView.Small" />
|
||||
|
||||
<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-share"
|
||||
tools:srcCompat="@android:drawable/ic_media_ff" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
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">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Usuń"
|
||||
android:textAppearance="@style/NavView.TextView.Small" />
|
||||
|
||||
<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-delete"
|
||||
tools:srcCompat="@android:drawable/ic_menu_delete" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
</layout>
|
@ -1006,4 +1006,20 @@
|
||||
<string name="timetable_no_timetable_text">Nie pobrano planu lekcji na ten tydzień.</string>
|
||||
<string name="timetable_no_timetable_sync">Pobierz plan lekcji</string>
|
||||
<string name="timetable_no_timetable_week">na tydzień %s</string>
|
||||
<string name="dialog_lesson_details_teacher">Nauczyciel</string>
|
||||
<string name="dialog_lesson_details_classroom">Sala lekcyjna</string>
|
||||
<string name="dialog_lesson_details_team">Grupa</string>
|
||||
<string name="dialog_lesson_details_id">ID lekcji</string>
|
||||
<string name="dialog_lesson_details_number">Nr lekcji</string>
|
||||
<string name="dialog_lesson_details_shifted_to">Lekcja przeniesiona na %s</string>
|
||||
<string name="dialog_lesson_details_shifted_from">Lekcja przeniesiona z %s</string>
|
||||
<string name="dialog_event_manual_title">Dodaj wpis do terminarza</string>
|
||||
<string name="dialog_event_manual_time">Lekcja/godzina</string>
|
||||
<string name="dialog_event_manual_date_next_lesson">nast. lekcja %s</string>
|
||||
<string name="dialog_event_manual_date_tomorrow">jutro (%s)</string>
|
||||
<string name="dialog_event_manual_date_this_week">%s (%s)</string>
|
||||
<string name="dialog_event_manual_date_other">-- inna data --</string>
|
||||
<string name="dialog_event_manual_date_today">dzisiaj (%s)</string>
|
||||
<string name="dialog_event_manual_date_next_week">następny %s (%s)</string>
|
||||
<string name="dialog_event_manual_no_lessons">Nie ma lekcji tego dnia</string>
|
||||
</resources>
|
||||
|
18
build.gradle
18
build.gradle
@ -18,22 +18,22 @@ buildscript {
|
||||
|
||||
versions = [
|
||||
kotlin : "1.3.50",
|
||||
ktx : "1.0.2",
|
||||
ktx : "1.1.0",
|
||||
|
||||
androidX : '1.0.0',
|
||||
annotation : '1.1.0',
|
||||
recyclerView : '1.1.0-beta04',
|
||||
material : '1.1.0-alpha09',
|
||||
appcompat : '1.1.0-rc01',
|
||||
constraintLayout : '2.0.0-beta2',
|
||||
recyclerView : '1.1.0-rc01',
|
||||
material : '1.2.0-alpha01',
|
||||
appcompat : '1.1.0',
|
||||
constraintLayout : '2.0.0-beta3',
|
||||
cardview : '1.0.0',
|
||||
gridLayout : '1.0.0',
|
||||
navigation : "2.0.0",
|
||||
navigationFragment: "1.0.0",
|
||||
legacy : "1.0.0",
|
||||
|
||||
room : "2.2.0-beta01",
|
||||
lifecycle : "2.2.0-alpha04",
|
||||
room : "2.2.1",
|
||||
lifecycle : "2.2.0-rc02",
|
||||
work : "2.2.0",
|
||||
|
||||
firebase : '17.2.0',
|
||||
@ -41,11 +41,11 @@ buildscript {
|
||||
play_services : "17.0.0",
|
||||
|
||||
materialdialogs : "0.9.6.0",
|
||||
materialdrawer : "62b24da031",
|
||||
materialdrawer : "cad66092a6",
|
||||
iconics : "4.0.1-b02",
|
||||
font_cmd : "3.5.95.1-kotlin",
|
||||
|
||||
navlib : "e4ad01dc87",
|
||||
navlib : "8ae5e2b87a",
|
||||
|
||||
gifdrawable : "1.2.15"
|
||||
]
|
||||
|
Reference in New Issue
Block a user