1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 01:39:09 -05:00

Fix messages after 20.09 update (#916)

This commit is contained in:
Mikołaj Pich 2020-08-29 23:53:55 +02:00 committed by GitHub
parent 36984e08b5
commit 7e2de594a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 2057 additions and 71 deletions

View File

@ -126,7 +126,7 @@ configurations.all {
} }
dependencies { dependencies {
implementation "io.github.wulkanowy:sdk:b919b96" implementation "io.github.wulkanowy:sdk:cbcc640"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
package io.github.wulkanowy.data.db.migrations
import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import kotlin.random.Random
class Migration27Test : AbstractMigrationTest() {
@Test
fun userWithoutCorrespondingUnit() {
with(helper.createDatabase(dbName, 26)) {
createStudent(this, 321, 123, "Jan Student")
createUnit(this, 9999, "Unit Jan")
close()
}
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() }
assertEquals(1, students.size)
with(students[0]) {
assertEquals(321, id)
assertEquals(123, userLoginId)
assertEquals("Student Jan", userName)
}
}
@Test
fun userWithCorrespondingUnit() {
with(helper.createDatabase(dbName, 26)) {
createStudent(this, 1, 2, "Jan Kowalski Student")
createUnit(this, 2, "Unit Jan")
close()
}
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() }
assertEquals(1, students.size)
with(students[0]) {
assertEquals(1, id)
assertEquals(2, userLoginId)
assertEquals("Unit Jan", userName)
}
}
@Test
fun studentAccountAndParentAccountWithCorrespondingUnits() {
with(helper.createDatabase(dbName, 26)) {
createStudent(this, 1, 222, "Jan Student")
createStudent(this, 2, 333, "Jan Parent")
createUnit(this, 222, "Unit Jan")
createUnit(this, 333, "Unit Tomasz")
close()
}
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() }
assertEquals(2, students.size)
with(students[0]) {
assertEquals(1, id)
assertEquals(222, userLoginId)
assertEquals("Unit Jan", userName)
}
with(students[1]) {
assertEquals(2, id)
assertEquals(333, userLoginId)
assertEquals("Unit Tomasz", userName)
}
}
private fun createStudent(db: SupportSQLiteDatabase, id: Long, userLoginId: Int, studentName: String) {
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
put("id", id)
put("scrapper_base_url", "https://fakelog.cf")
put("mobile_base_url", "")
put("login_mode", "SCRAPPER")
put("login_type", "STANDARD")
put("certificate_key", "")
put("private_key", "")
put("is_parent", false)
put("email", "jan@fakelog.cf")
put("password", "******")
put("symbol", "Default")
put("school_short", "")
put("class_name", "")
put("student_id", Random.nextInt())
put("class_id", Random.nextInt())
put("school_id", "123")
put("school_name", "Wulkan first class school")
put("is_current", false)
put("registration_date", "0")
put("user_login_id", userLoginId)
put("student_name", studentName)
})
}
private fun createUnit(db: SupportSQLiteDatabase, senderId: Int, senderName: String) {
db.insert("ReportingUnits", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
put("student_id", Random.nextInt())
put("real_id", Random.nextInt())
put("short", "SHORT")
put("roles", "[0]")
put("sender_id", senderId)
put("sender_name", senderName)
})
}
}

View File

@ -13,6 +13,7 @@ fun getStudent(): Student {
scrapperBaseUrl = "fakelog.cf", scrapperBaseUrl = "fakelog.cf",
loginType = "AUTO", loginType = "AUTO",
isCurrent = true, isCurrent = true,
userName = "",
studentName = "", studentName = "",
schoolShortName = "", schoolShortName = "",
schoolName = "", schoolName = "",

View File

@ -215,6 +215,7 @@ class GradeRepositoryTest {
studentId = 0, studentId = 0,
studentName = "", studentName = "",
symbol = "", symbol = "",
userLoginId = 0 userLoginId = 0,
userName = ""
) )
} }

View File

@ -41,7 +41,7 @@ class LuckyNumberLocalTest {
val number = LuckyNumber(1, LocalDate.of(2019, 1, 20), 14) val number = LuckyNumber(1, LocalDate.of(2019, 1, 20), 14)
runBlocking { luckyNumberLocal.saveLuckyNumber(number) } runBlocking { luckyNumberLocal.saveLuckyNumber(number) }
val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", 1, false, now()) val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", "", 1, false, now())
val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)).first() } val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)).first() }
assertEquals(1, luckyNumber?.studentId) assertEquals(1, luckyNumber?.studentId)

View File

@ -43,7 +43,7 @@ class RecipientLocalTest {
) )
runBlocking { recipientLocal.saveRecipients(list) } runBlocking { recipientLocal.saveRecipients(list) }
val student = Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", 1, true, LocalDateTime.now()) val student = Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", "", 1, true, LocalDateTime.now())
val recipients = runBlocking { val recipients = runBlocking {
recipientLocal.getRecipients( recipientLocal.getRecipients(
student = student, student = student,

View File

@ -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.Migration24
import io.github.wulkanowy.data.db.migrations.Migration25 import io.github.wulkanowy.data.db.migrations.Migration25
import io.github.wulkanowy.data.db.migrations.Migration26 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.Migration3
import io.github.wulkanowy.data.db.migrations.Migration4 import io.github.wulkanowy.data.db.migrations.Migration4
import io.github.wulkanowy.data.db.migrations.Migration5 import io.github.wulkanowy.data.db.migrations.Migration5
@ -111,7 +112,7 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
companion object { companion object {
const val VERSION_SCHEMA = 26 const val VERSION_SCHEMA = 27
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> { fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
return arrayOf( return arrayOf(
@ -139,7 +140,8 @@ abstract class AppDatabase : RoomDatabase() {
Migration23(), Migration23(),
Migration24(), Migration24(),
Migration25(), Migration25(),
Migration26() Migration26(),
Migration27(),
) )
} }

View File

@ -14,9 +14,6 @@ interface MessagesDao : BaseDao<Message> {
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId") @Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment> 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>> 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>>
} }

View File

@ -29,8 +29,6 @@ data class Message(
val subject: String, val subject: String,
var content: String,
val date: LocalDateTime, val date: LocalDateTime,
@ColumnInfo(name = "folder_id") @ColumnInfo(name = "folder_id")
@ -55,4 +53,6 @@ data class Message(
@ColumnInfo(name = "is_notified") @ColumnInfo(name = "is_notified")
var isNotified: Boolean = true var isNotified: Boolean = true
var content: String = ""
} }

View File

@ -43,6 +43,9 @@ data class Student(
@ColumnInfo(name = "user_login_id") @ColumnInfo(name = "user_login_id")
val userLoginId: Int, val userLoginId: Int,
@ColumnInfo(name = "user_name")
val userName: String,
@ColumnInfo(name = "student_name") @ColumnInfo(name = "student_name")
val studentName: String, val studentName: String,

View File

@ -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
}
}

View File

@ -14,6 +14,7 @@ fun List<SdkStudent>.mapToEntities(password: String = "") = map {
symbol = it.symbol, symbol = it.symbol,
studentId = it.studentId, studentId = it.studentId,
userLoginId = it.userLoginId, userLoginId = it.userLoginId,
userName = it.userName,
studentName = it.studentName + " " + it.studentSurname, studentName = it.studentName + " " + it.studentSurname,
schoolSymbol = it.schoolSymbol, schoolSymbol = it.schoolSymbol,
schoolShortName = it.schoolShortName, schoolShortName = it.schoolShortName,

View File

@ -38,9 +38,6 @@ class MessageLocal @Inject constructor(
} }
fun getMessages(student: Student, folder: MessageFolder): Flow<List<Message>> { fun getMessages(student: Student, folder: MessageFolder): Flow<List<Message>> {
return when (folder) { return messagesDb.loadAll(student.id.toInt(), folder.id)
TRASHED -> messagesDb.loadDeleted(student.id.toInt())
else -> messagesDb.loadAll(student.id.toInt(), folder.id)
}
} }
} }

View File

@ -18,24 +18,25 @@ import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
class MessageRemote @Inject constructor(private val sdk: Sdk) { class MessageRemote @Inject constructor(private val sdk: Sdk) {
suspend fun getMessages(student: Student, semester: Semester, folder: MessageFolder): List<Message> { 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( Message(
studentId = student.id.toInt(), studentId = student.id.toInt(),
realId = it.id ?: 0, realId = it.id ?: 0,
messageId = it.messageId ?: 0, messageId = it.messageId ?: 0,
sender = it.sender.orEmpty(), sender = it.sender?.name.orEmpty(),
senderId = it.senderId ?: 0, senderId = it.sender?.loginId ?: 0,
recipient = it.recipient.orEmpty(), recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
subject = it.subject.trim(), subject = it.subject.trim(),
date = it.date ?: now(), date = it.date ?: now(),
content = it.content.orEmpty(),
folderId = it.folderId, folderId = it.folderId,
unread = it.unread ?: false, unread = it.unread ?: false,
unreadBy = it.unreadBy ?: 0, unreadBy = it.unreadBy ?: 0,
readBy = it.readBy ?: 0, readBy = it.readBy ?: 0,
removed = it.removed, removed = it.removed,
hasAttachments = it.hasAttachments 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 { 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)
} }
} }

View File

@ -64,9 +64,11 @@ class MessageRepository @Inject constructor(
suspend fun deleteMessage(student: Student, message: Message) { suspend fun deleteMessage(student: Student, message: Message) {
val isDeleted = remote.deleteMessage(student, message) val isDeleted = remote.deleteMessage(student, message)
if (!message.removed) local.updateMessages(listOf(message.copy(removed = isDeleted).apply { if (message.folderId != MessageFolder.TRASHED.id) {
id = message.id if (isDeleted) local.updateMessages(listOf(message.copy(folderId = MessageFolder.TRASHED.id).apply {
content = message.content id = message.id
})) else local.deleteMessages(listOf(message)) content = message.content
}))
} else local.deleteMessages(listOf(message))
} }
} }

View File

@ -40,6 +40,6 @@ class ContributorPresenter @Inject constructor(
} }
Status.ERROR -> errorHandler.dispatch(it.error!!) Status.ERROR -> errorHandler.dispatch(it.error!!)
} }
} }.launch()
} }
} }

View File

@ -9,7 +9,6 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageAttachment import io.github.wulkanowy.data.db.entities.MessageAttachment
import io.github.wulkanowy.data.db.entities.MessageWithAttachment 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.ItemMessageAttachmentBinding
import io.github.wulkanowy.databinding.ItemMessageDividerBinding import io.github.wulkanowy.databinding.ItemMessageDividerBinding
import io.github.wulkanowy.databinding.ItemMessagePreviewBinding 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) } 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")) messagePreviewDate.text = root.context.getString(R.string.message_date, message.date.toFormattedString("yyyy-MM-dd HH:mm:ss"))
messagePreviewContent.text = message.content messagePreviewContent.text = message.content
messagePreviewAuthor.text = if (message.folderId == MessageFolder.SENT.id) "${root.context.getString(R.string.message_to)} ${message.recipient}" messagePreviewFromSender.text = message.sender
else "${root.context.getString(R.string.message_from)} ${message.sender}" messagePreviewToRecipient.text = message.recipient
} }
} }

View File

@ -5,6 +5,7 @@ import android.os.Build
import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageAttachment 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.message.MessageRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
@ -207,7 +208,7 @@ class MessagePreviewPresenter @Inject constructor(
view?.apply { view?.apply {
showOptions(message != null) showOptions(message != null)
message?.let { message?.let {
when (it.removed) { when (it.folderId == MessageFolder.TRASHED.id) {
true -> setDeletedOptionsLabels() true -> setDeletedOptionsLabels()
false -> setNotDeletedOptionsLabels() false -> setNotDeletedOptionsLabels()
} }

View File

@ -19,22 +19,17 @@ class MessageTabAdapter @Inject constructor() :
var onClickListener: (Message, position: Int) -> Unit = { _, _ -> } var onClickListener: (Message, position: Int) -> Unit = { _, _ -> }
var onChangesDetectedListener = {}
private var items = mutableListOf<Message>() private var items = mutableListOf<Message>()
fun setDataItems(data: List<Message>) { fun setDataItems(data: List<Message>) {
if (items.size != data.size) onChangesDetectedListener()
val diffResult = DiffUtil.calculateDiff(MessageTabDiffUtil(items, data)) val diffResult = DiffUtil.calculateDiff(MessageTabDiffUtil(items, data))
items = data.toMutableList() items = data.toMutableList()
diffResult.dispatchUpdatesTo(this) 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 getItemCount() = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(

View File

@ -63,7 +63,10 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
} }
override fun initView() { override fun initView() {
tabAdapter.onClickListener = presenter::onMessageItemSelected with(tabAdapter) {
onClickListener = presenter::onMessageItemSelected
onChangesDetectedListener = ::resetListPosition
}
with(binding.messageTabRecycler) { with(binding.messageTabRecycler) {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
@ -97,10 +100,6 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
tabAdapter.setDataItems(data) tabAdapter.setDataItems(data)
} }
override fun updateItem(item: Message, position: Int) {
tabAdapter.updateItem(position, item)
}
override fun showProgress(show: Boolean) { override fun showProgress(show: Boolean) {
binding.messageTabProgress.visibility = if (show) VISIBLE else GONE binding.messageTabProgress.visibility = if (show) VISIBLE else GONE
} }

View File

@ -81,13 +81,7 @@ class MessageTabPresenter @Inject constructor(
fun onMessageItemSelected(message: Message, position: Int) { fun onMessageItemSelected(message: Message, position: Int) {
Timber.i("Select message ${message.id} item (position: $position)") Timber.i("Select message ${message.id} item (position: $position)")
view?.run { view?.openMessage(message)
openMessage(message)
if (message.unread) {
message.unread = false
updateItem(message, position)
}
}
} }
private fun loadData(forceRefresh: Boolean) { private fun loadData(forceRefresh: Boolean) {
@ -154,6 +148,7 @@ class MessageTabPresenter @Inject constructor(
.collect { .collect {
Timber.d("Applying filter. Full list: ${messages.size}, filtered: ${it.size}") Timber.d("Applying filter. Full list: ${messages.size}, filtered: ${it.size}")
updateData(it) updateData(it)
view?.resetListPosition()
} }
} }
} }
@ -176,7 +171,6 @@ class MessageTabPresenter @Inject constructor(
showContent(data.isNotEmpty()) showContent(data.isNotEmpty())
showErrorView(false) showErrorView(false)
updateData(data) updateData(data)
resetListPosition()
} }
} }

View File

@ -13,8 +13,6 @@ interface MessageTabView : BaseView {
fun updateData(data: List<Message>) fun updateData(data: List<Message>)
fun updateItem(item: Message, position: Int)
fun showProgress(show: Boolean) fun showProgress(show: Boolean)
fun enableSwipe(enable: Boolean) fun enableSwipe(enable: Boolean)

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?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" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/messagePreviewContentContainer" android:id="@+id/messagePreviewContentContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -9,37 +10,84 @@
<TextView <TextView
android:id="@+id/messagePreviewSubject" android:id="@+id/messagePreviewSubject"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:lineSpacingMultiplier="1.2" android:lineSpacingMultiplier="1.2"
android:textSize="22sp" android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/lorem" /> tools:text="@tools:sample/lorem" />
<TextView <TextView
android:id="@+id/messagePreviewAuthor" android:id="@+id/messagePreviewFromLabel"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="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:textColor="?android:textColorSecondary"
android:textSize="15sp" 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 <TextView
android:id="@+id/messagePreviewDate" android:id="@+id/messagePreviewDate"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="15dp" android:layout_marginTop="4dp"
android:textColor="?android:textColorSecondary" android:textColor="?android:textColorSecondary"
android:textSize="15sp" android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/messagePreviewToLabel"
tools:text="@tools:sample/date/ddmmyy" /> tools:text="@tools:sample/date/ddmmyy" />
<TextView <TextView
android:id="@+id/messagePreviewContent" android:id="@+id/messagePreviewContent"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:autoLink="web" android:autoLink="web"
android:lineSpacingMultiplier="1.2" android:lineSpacingMultiplier="1.2"
android:textIsSelectable="true" 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" /> tools:text="@tools:sample/lorem/random" />
</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -45,7 +45,8 @@ fun getStudentEntity(mode: Sdk.Mode = Sdk.Mode.API): Student {
studentId = 0, studentId = 0,
studentName = "", studentName = "",
symbol = "", symbol = "",
userLoginId = 0 userLoginId = 0,
userName = "",
) )
} }
@ -86,7 +87,6 @@ fun getMessageEntity(
senderId = 1, senderId = 1,
recipient = "", recipient = "",
subject = "", subject = "",
content = content,
date = now(), date = now(),
folderId = 1, folderId = 1,
unread = unread, unread = unread,
@ -94,4 +94,6 @@ fun getMessageEntity(
readBy = 1, readBy = 1,
removed = false, removed = false,
hasAttachments = false hasAttachments = false
) ).apply {
this.content = content
}

View File

@ -8,6 +8,7 @@ import io.mockk.MockKAnnotations
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.just import io.mockk.just
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
@ -35,6 +36,7 @@ class MessageRepositoryTest {
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
every { student.userName } returns "Jan"
repo = MessageRepository(local, remote) repo = MessageRepository(local, remote)
} }
@ -63,7 +65,7 @@ class MessageRepositoryTest {
@Test @Test
fun `get message when content in db is empty`() { fun `get message when content in db is empty`() {
val testMessage = getMessageEntity(123, "", true) val testMessage = getMessageEntity(123, "", true)
val testMessageWithContent = testMessage.copy(content = "Test") val testMessageWithContent = testMessage.copy().apply { content = "Test" }
val mWa = MessageWithAttachment(testMessage, emptyList()) val mWa = MessageWithAttachment(testMessage, emptyList())
val mWaWithContent = MessageWithAttachment(testMessageWithContent, emptyList()) val mWaWithContent = MessageWithAttachment(testMessageWithContent, emptyList())

View File

@ -39,7 +39,7 @@ class GradeAverageProviderTest {
private lateinit var gradeAverageProvider: GradeAverageProvider private lateinit var gradeAverageProvider: GradeAverageProvider
private val student = Student("", "", "", "SCRAPPER", "", "", false, "", "", "", 101, 0, "", "", "", "", "", 1, true, LocalDateTime.now()) private val student = Student("", "", "", "SCRAPPER", "", "", false, "", "", "", 101, 0, "", "", "", "", "", "", 1, true, LocalDateTime.now())
private val semesters = mutableListOf( private val semesters = mutableListOf(
createSemesterEntity(10, 21, of(2019, 1, 31), of(2019, 6, 23)), createSemesterEntity(10, 21, of(2019, 1, 31), of(2019, 6, 23)),

View File

@ -99,7 +99,7 @@ class LoginFormPresenterTest {
@Test @Test
fun loginTest() { fun loginTest() {
val studentTest = Student(email = "test@", password = "123", scrapperBaseUrl = "https://fakelog.cf/", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, classId = 1, isCurrent = false, symbol = "", registrationDate = now(), className = "", mobileBaseUrl = "", privateKey = "", certificateKey = "", loginMode = "", userLoginId = 0, schoolShortName = "", isParent = false) val studentTest = Student(email = "test@", password = "123", scrapperBaseUrl = "https://fakelog.cf/", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, classId = 1, isCurrent = false, symbol = "", registrationDate = now(), className = "", mobileBaseUrl = "", privateKey = "", certificateKey = "", loginMode = "", userLoginId = 0, schoolShortName = "", isParent = false, userName = "")
coEvery { repository.getStudentsScrapper(any(), any(), any(), any()) } returns listOf(StudentWithSemesters(studentTest, emptyList())) coEvery { repository.getStudentsScrapper(any(), any(), any(), any()) } returns listOf(StudentWithSemesters(studentTest, emptyList()))
every { loginFormView.formUsernameValue } returns "@" every { loginFormView.formUsernameValue } returns "@"

View File

@ -38,7 +38,7 @@ class LoginStudentSelectPresenterTest {
private lateinit var presenter: LoginStudentSelectPresenter private lateinit var presenter: LoginStudentSelectPresenter
private val testStudent by lazy { Student(email = "test", password = "test123", scrapperBaseUrl = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", classId = 1, studentName = "", registrationDate = now(), className = "", loginMode = "", certificateKey = "", privateKey = "", mobileBaseUrl = "", schoolShortName = "", userLoginId = 1, isParent = false) } private val testStudent by lazy { Student(email = "test", password = "test123", scrapperBaseUrl = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", classId = 1, studentName = "", registrationDate = now(), className = "", loginMode = "", certificateKey = "", privateKey = "", mobileBaseUrl = "", schoolShortName = "", userLoginId = 1, isParent = false, userName = "") }
private val testException by lazy { RuntimeException("Problem") } private val testException by lazy { RuntimeException("Problem") }