Fix messages after 20.09 update (#916)
This commit is contained in:
@ -69,6 +69,7 @@ import io.github.wulkanowy.data.db.migrations.Migration23
|
||||
import io.github.wulkanowy.data.db.migrations.Migration24
|
||||
import io.github.wulkanowy.data.db.migrations.Migration25
|
||||
import io.github.wulkanowy.data.db.migrations.Migration26
|
||||
import io.github.wulkanowy.data.db.migrations.Migration27
|
||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
@ -111,7 +112,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 26
|
||||
const val VERSION_SCHEMA = 27
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||
return arrayOf(
|
||||
@ -139,7 +140,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration23(),
|
||||
Migration24(),
|
||||
Migration25(),
|
||||
Migration26()
|
||||
Migration26(),
|
||||
Migration27(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,6 @@ interface MessagesDao : BaseDao<Message> {
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
||||
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
|
||||
fun loadAll(studentId: Int, folder: Int): Flow<List<Message>>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
|
||||
fun loadDeleted(studentId: Int): Flow<List<Message>>
|
||||
}
|
||||
|
@ -29,8 +29,6 @@ data class Message(
|
||||
|
||||
val subject: String,
|
||||
|
||||
var content: String,
|
||||
|
||||
val date: LocalDateTime,
|
||||
|
||||
@ColumnInfo(name = "folder_id")
|
||||
@ -55,4 +53,6 @@ data class Message(
|
||||
|
||||
@ColumnInfo(name = "is_notified")
|
||||
var isNotified: Boolean = true
|
||||
|
||||
var content: String = ""
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ data class Student(
|
||||
@ColumnInfo(name = "user_login_id")
|
||||
val userLoginId: Int,
|
||||
|
||||
@ColumnInfo(name = "user_name")
|
||||
val userName: String,
|
||||
|
||||
@ColumnInfo(name = "student_name")
|
||||
val studentName: String,
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration27 : Migration(26, 27) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"")
|
||||
|
||||
val students = getStudentsIdsAndNames(database)
|
||||
val units = getReportingUnits(database)
|
||||
|
||||
students.forEach { (id, userLoginId, studentName) ->
|
||||
val userNameFromUnits = units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second
|
||||
val normalizedStudentName = studentName.split(" ").asReversed().joinToString(" ")
|
||||
|
||||
val userName = userNameFromUnits ?: normalizedStudentName
|
||||
database.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||
val students = mutableListOf<Triple<Long, Int, String>>()
|
||||
val studentsCursor = database.query("SELECT id, user_login_id, student_name FROM Students")
|
||||
if (studentsCursor.moveToFirst()) {
|
||||
do {
|
||||
students.add(Triple(studentsCursor.getLong(0), studentsCursor.getInt(1), studentsCursor.getString(2)))
|
||||
} while (studentsCursor.moveToNext())
|
||||
}
|
||||
return students
|
||||
}
|
||||
|
||||
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
val units = mutableListOf<Pair<Int, String>>()
|
||||
val unitsCursor = database.query("SELECT sender_id, sender_name FROM ReportingUnits")
|
||||
if (unitsCursor.moveToFirst()) {
|
||||
do {
|
||||
units.add(unitsCursor.getInt(0) to unitsCursor.getString(1))
|
||||
} while (unitsCursor.moveToNext())
|
||||
}
|
||||
|
||||
return units
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ fun List<SdkStudent>.mapToEntities(password: String = "") = map {
|
||||
symbol = it.symbol,
|
||||
studentId = it.studentId,
|
||||
userLoginId = it.userLoginId,
|
||||
userName = it.userName,
|
||||
studentName = it.studentName + " " + it.studentSurname,
|
||||
schoolSymbol = it.schoolSymbol,
|
||||
schoolShortName = it.schoolShortName,
|
||||
|
@ -38,9 +38,6 @@ class MessageLocal @Inject constructor(
|
||||
}
|
||||
|
||||
fun getMessages(student: Student, folder: MessageFolder): Flow<List<Message>> {
|
||||
return when (folder) {
|
||||
TRASHED -> messagesDb.loadDeleted(student.id.toInt())
|
||||
else -> messagesDb.loadAll(student.id.toInt(), folder.id)
|
||||
}
|
||||
return messagesDb.loadAll(student.id.toInt(), folder.id)
|
||||
}
|
||||
}
|
||||
|
@ -18,24 +18,25 @@ import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
||||
class MessageRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
suspend fun getMessages(student: Student, semester: Semester, folder: MessageFolder): List<Message> {
|
||||
return sdk.init(student).getMessages(Folder.valueOf(folder.name), semester.start.atStartOfDay(), semester.end.atStartOfDay()).map {
|
||||
return sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).map {
|
||||
Message(
|
||||
studentId = student.id.toInt(),
|
||||
realId = it.id ?: 0,
|
||||
messageId = it.messageId ?: 0,
|
||||
sender = it.sender.orEmpty(),
|
||||
senderId = it.senderId ?: 0,
|
||||
recipient = it.recipient.orEmpty(),
|
||||
sender = it.sender?.name.orEmpty(),
|
||||
senderId = it.sender?.loginId ?: 0,
|
||||
recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
|
||||
subject = it.subject.trim(),
|
||||
date = it.date ?: now(),
|
||||
content = it.content.orEmpty(),
|
||||
folderId = it.folderId,
|
||||
unread = it.unread ?: false,
|
||||
unreadBy = it.unreadBy ?: 0,
|
||||
readBy = it.readBy ?: 0,
|
||||
removed = it.removed,
|
||||
hasAttachments = it.hasAttachments
|
||||
)
|
||||
).apply {
|
||||
content = it.content.orEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,6 +73,6 @@ class MessageRemote @Inject constructor(private val sdk: Sdk) {
|
||||
}
|
||||
|
||||
suspend fun deleteMessage(student: Student, message: Message): Boolean {
|
||||
return sdk.init(student).deleteMessages(listOf(message.messageId to message.folderId))
|
||||
return sdk.init(student).deleteMessages(listOf(message.messageId), message.folderId)
|
||||
}
|
||||
}
|
||||
|
@ -64,9 +64,11 @@ class MessageRepository @Inject constructor(
|
||||
suspend fun deleteMessage(student: Student, message: Message) {
|
||||
val isDeleted = remote.deleteMessage(student, message)
|
||||
|
||||
if (!message.removed) local.updateMessages(listOf(message.copy(removed = isDeleted).apply {
|
||||
id = message.id
|
||||
content = message.content
|
||||
})) else local.deleteMessages(listOf(message))
|
||||
if (message.folderId != MessageFolder.TRASHED.id) {
|
||||
if (isDeleted) local.updateMessages(listOf(message.copy(folderId = MessageFolder.TRASHED.id).apply {
|
||||
id = message.id
|
||||
content = message.content
|
||||
}))
|
||||
} else local.deleteMessages(listOf(message))
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,6 @@ class ContributorPresenter @Inject constructor(
|
||||
}
|
||||
Status.ERROR -> errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
||||
import io.github.wulkanowy.databinding.ItemMessageAttachmentBinding
|
||||
import io.github.wulkanowy.databinding.ItemMessageDividerBinding
|
||||
import io.github.wulkanowy.databinding.ItemMessagePreviewBinding
|
||||
@ -66,8 +65,8 @@ class MessagePreviewAdapter @Inject constructor() :
|
||||
messagePreviewSubject.text = message.subject.ifBlank { root.context.getString(R.string.message_no_subject) }
|
||||
messagePreviewDate.text = root.context.getString(R.string.message_date, message.date.toFormattedString("yyyy-MM-dd HH:mm:ss"))
|
||||
messagePreviewContent.text = message.content
|
||||
messagePreviewAuthor.text = if (message.folderId == MessageFolder.SENT.id) "${root.context.getString(R.string.message_to)} ${message.recipient}"
|
||||
else "${root.context.getString(R.string.message_from)} ${message.sender}"
|
||||
messagePreviewFromSender.text = message.sender
|
||||
messagePreviewToRecipient.text = message.recipient
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import android.os.Build
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
||||
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
@ -207,7 +208,7 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
view?.apply {
|
||||
showOptions(message != null)
|
||||
message?.let {
|
||||
when (it.removed) {
|
||||
when (it.folderId == MessageFolder.TRASHED.id) {
|
||||
true -> setDeletedOptionsLabels()
|
||||
false -> setNotDeletedOptionsLabels()
|
||||
}
|
||||
|
@ -19,22 +19,17 @@ class MessageTabAdapter @Inject constructor() :
|
||||
|
||||
var onClickListener: (Message, position: Int) -> Unit = { _, _ -> }
|
||||
|
||||
var onChangesDetectedListener = {}
|
||||
|
||||
private var items = mutableListOf<Message>()
|
||||
|
||||
fun setDataItems(data: List<Message>) {
|
||||
if (items.size != data.size) onChangesDetectedListener()
|
||||
val diffResult = DiffUtil.calculateDiff(MessageTabDiffUtil(items, data))
|
||||
items = data.toMutableList()
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
fun updateItem(position: Int, item: Message) {
|
||||
val currentItem = items[position]
|
||||
items[position] = item
|
||||
if (item != currentItem) {
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
||||
|
@ -63,7 +63,10 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
tabAdapter.onClickListener = presenter::onMessageItemSelected
|
||||
with(tabAdapter) {
|
||||
onClickListener = presenter::onMessageItemSelected
|
||||
onChangesDetectedListener = ::resetListPosition
|
||||
}
|
||||
|
||||
with(binding.messageTabRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
@ -97,10 +100,6 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
||||
tabAdapter.setDataItems(data)
|
||||
}
|
||||
|
||||
override fun updateItem(item: Message, position: Int) {
|
||||
tabAdapter.updateItem(position, item)
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
binding.messageTabProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
@ -81,13 +81,7 @@ class MessageTabPresenter @Inject constructor(
|
||||
|
||||
fun onMessageItemSelected(message: Message, position: Int) {
|
||||
Timber.i("Select message ${message.id} item (position: $position)")
|
||||
view?.run {
|
||||
openMessage(message)
|
||||
if (message.unread) {
|
||||
message.unread = false
|
||||
updateItem(message, position)
|
||||
}
|
||||
}
|
||||
view?.openMessage(message)
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean) {
|
||||
@ -154,6 +148,7 @@ class MessageTabPresenter @Inject constructor(
|
||||
.collect {
|
||||
Timber.d("Applying filter. Full list: ${messages.size}, filtered: ${it.size}")
|
||||
updateData(it)
|
||||
view?.resetListPosition()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,7 +171,6 @@ class MessageTabPresenter @Inject constructor(
|
||||
showContent(data.isNotEmpty())
|
||||
showErrorView(false)
|
||||
updateData(data)
|
||||
resetListPosition()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,6 @@ interface MessageTabView : BaseView {
|
||||
|
||||
fun updateData(data: List<Message>)
|
||||
|
||||
fun updateItem(item: Message, position: Int)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun enableSwipe(enable: Boolean)
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||
android:id="@+id/messagePreviewContentContainer"
|
||||
android:layout_width="match_parent"
|
||||
@ -9,37 +10,84 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewSubject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:textSize="22sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewAuthor"
|
||||
android:id="@+id/messagePreviewFromLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="@string/message_from"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/messagePreviewSubject" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewFromSender"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="15sp"
|
||||
tools:text="@tools:sample/full_names" />
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/messagePreviewFromLabel"
|
||||
app:layout_constraintTop_toTopOf="@id/messagePreviewFromLabel"
|
||||
tools:text="@tools:sample/full_names[0]" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewToLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/message_to"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/messagePreviewFromLabel" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewToRecipient"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/messagePreviewToLabel"
|
||||
app:layout_constraintTop_toTopOf="@id/messagePreviewToLabel"
|
||||
tools:text="@tools:sample/full_names[1]" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/messagePreviewToLabel"
|
||||
tools:text="@tools:sample/date/ddmmyy" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messagePreviewContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:autoLink="web"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:textIsSelectable="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/messagePreviewDate"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
Reference in New Issue
Block a user