Verified Commit 9205feb9 authored by Mikolai Gütschow's avatar Mikolai Gütschow
Browse files

insert message at right position in list, move MessageCounter out to ui package

parent a8f61f10
Pipeline #9052 passed with stages
in 9 minutes and 37 seconds
package org.briarproject.briar.desktop.contact
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
......@@ -14,8 +12,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
......@@ -23,8 +19,6 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.briarproject.bramble.api.contact.ContactId
......@@ -34,6 +28,7 @@ import org.briarproject.briar.desktop.theme.selectedCard
import org.briarproject.briar.desktop.theme.surfaceVariant
import org.briarproject.briar.desktop.ui.Constants.HEADER_SIZE
import org.briarproject.briar.desktop.ui.HorizontalDivider
import org.briarproject.briar.desktop.ui.MessageCounter
import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
import org.briarproject.briar.desktop.utils.PreviewUtils.preview
import org.briarproject.briar.desktop.utils.TimeUtils.getFormattedTimestamp
......@@ -125,30 +120,6 @@ fun ContactCard(
HorizontalDivider()
}
@Composable
fun MessageCounter(unread: Int, modifier: Modifier = Modifier) {
val outlineColor = MaterialTheme.colors.outline
val briarSecondary = MaterialTheme.colors.secondary
if (unread > 0) {
Box(
modifier = modifier
.height(20.dp)
.widthIn(min = 20.dp, max = Dp.Infinity)
.border(2.dp, outlineColor, CircleShape)
.background(briarSecondary, CircleShape)
.padding(horizontal = 6.dp)
) {
Text(
modifier = Modifier.align(Alignment.Center),
fontSize = 8.sp,
textAlign = TextAlign.Center,
text = unread.toString(),
maxLines = 1
)
}
}
}
@Composable
fun RealContactInfo(contactItem: ContactItem, modifier: Modifier = Modifier) {
Column(modifier = modifier.padding(start = 12.dp)) {
......
......@@ -37,12 +37,12 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.briarproject.bramble.api.sync.GroupId
import org.briarproject.bramble.api.sync.MessageId
import org.briarproject.briar.desktop.contact.MessageCounter
import org.briarproject.briar.desktop.theme.ChevronDown
import org.briarproject.briar.desktop.theme.ChevronUp
import org.briarproject.briar.desktop.theme.divider
import org.briarproject.briar.desktop.ui.HorizontalDivider
import org.briarproject.briar.desktop.ui.Loader
import org.briarproject.briar.desktop.ui.MessageCounter
import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
import org.briarproject.briar.desktop.utils.PreviewUtils.preview
import org.briarproject.briar.desktop.utils.replaceIfIndexed
......@@ -123,9 +123,9 @@ fun main() = preview(
initialFirstUnreadMessageIndex = initialFirstUnreadIndex,
currentUnreadMessagesInfo = currentUnreadMessagesInfo,
onMessageAddedToBottom = onMessageAddedToBottom,
markMessagesRead = { lst ->
markMessagesRead = { list ->
messages.replaceIfIndexed(
{ idx, it -> idx in lst && !it.isRead },
{ idx, it -> idx in list && !it.isRead },
{ _, it -> it.markRead() }
)
},
......@@ -159,7 +159,6 @@ fun ConversationList(
Box(modifier = Modifier.padding(padding).fillMaxSize()) {
LazyColumn(
state = scrollState,
contentPadding = PaddingValues(top = 8.dp, bottom = 8.dp),
modifier = Modifier.fillMaxSize().padding(end = 12.dp, top = 8.dp, bottom = 8.dp)
) {
itemsIndexed(messages) { idx, m ->
......@@ -255,6 +254,7 @@ fun UnreadMessagesFAB(
fun LazyListState.isScrolledToPenultimate(): Boolean {
val last = layoutInfo.visibleItemsInfo.lastOrNull() ?: return false
// WARNING: this doesn't work when `contentPadding` is used on the LazyList!
return last.index == layoutInfo.totalItemsCount - 1 &&
last.offset == layoutInfo.viewportEndOffset
}
......@@ -41,6 +41,7 @@ import org.briarproject.briar.desktop.conversation.ConversationRequestItem.Reque
import org.briarproject.briar.desktop.threading.BriarExecutors
import org.briarproject.briar.desktop.utils.ImageUtils.loadAvatar
import org.briarproject.briar.desktop.utils.KLoggerUtils.logDuration
import org.briarproject.briar.desktop.utils.addAfterLast
import org.briarproject.briar.desktop.utils.clearAndAddAll
import org.briarproject.briar.desktop.utils.replaceIf
import org.briarproject.briar.desktop.utils.replaceIfIndexed
......@@ -229,8 +230,7 @@ constructor(
var start = LogUtils.now()
val headers = conversationManager.getMessageHeaders(txn, contact.idWrapper.contactId)
LOG.logDuration("Loading message headers", start)
// Sort headers by timestamp in *descending* order
// val sorted = headers.sortedByDescending { it.timestamp }
// Sort headers by timestamp in *ascending* order
val sorted = headers.sortedBy { it.timestamp }
start = LogUtils.now()
val visitor = ConversationVisitor(contact.name, messagingManager, txn)
......@@ -308,11 +308,12 @@ constructor(
}
private fun addMessage(msg: ConversationItem) {
// currently this method adds the message always at the end
// todo: instead we should check where to insert it to maintain the timely order
_messages.add(msg)
val type = if (msg.isIncoming) MessageAddedType.INCOMING else MessageAddedType.OUTGOING
onMessageAddedToBottom.emit(type)
val idx = _messages.addAfterLast(msg) { it.time < msg.time }
if (idx == _messages.lastIndex) {
// only emit the event in case the message was actually added to the bottom
val type = if (msg.isIncoming) MessageAddedType.INCOMING else MessageAddedType.OUTGOING
onMessageAddedToBottom.emit(type)
}
}
private fun markMessages(
......
package org.briarproject.briar.desktop.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.briarproject.briar.desktop.theme.outline
@Composable
fun MessageCounter(unread: Int, modifier: Modifier = Modifier) {
val outlineColor = MaterialTheme.colors.outline
val briarSecondary = MaterialTheme.colors.secondary
if (unread > 0) {
Box(
modifier = modifier
.height(20.dp)
.widthIn(min = 20.dp, max = Dp.Infinity)
.border(2.dp, outlineColor, CircleShape)
.background(briarSecondary, CircleShape)
.padding(horizontal = 6.dp)
) {
Text(
modifier = Modifier.align(Alignment.Center),
fontSize = 8.sp,
textAlign = TextAlign.Center,
text = unread.toString(),
maxLines = 1
)
}
}
}
package org.briarproject.briar.desktop.utils
/**
* Add [element] to the list after the last element that matches the given [predicate].
* If no element matches the [predicate], add [element] to the beginning of the list.
* This method makes most sense for pre-sorted lists.
*/
fun <T> MutableList<T>.addAfterLast(element: T, predicate: (T) -> Boolean): Int {
val idx = indexOfLast(predicate)
if (idx == lastIndex || isEmpty()) {
add(element)
} else {
add(idx + 1, element)
}
return idx + 1
}
fun <T> MutableList<T>.clearAndAddAll(elements: Collection<T>) {
clear()
addAll(elements)
......
package org.briarproject.briar.desktop.utils
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class ListUtilsTest {
@Test
fun addAfterLast() {
val list = mutableListOf(1, 3, 5)
// add to end
var idx = list.addAfterLast(7) { it < 7 }
assertEquals(list.lastIndex, idx)
assertContentEquals(listOf(1, 3, 5, 7), list, "failed to insert at end")
// add to start
idx = list.addAfterLast(0) { it < 0 }
assertEquals(0, idx)
assertContentEquals(listOf(0, 1, 3, 5, 7), list, "failed to insert at start")
// add in-between
idx = list.addAfterLast(4) { it < 4 }
assertEquals(3, idx)
assertContentEquals(listOf(0, 1, 3, 4, 5, 7), list, "failed to insert in-between")
// add to empty list
list.clear()
idx = list.addAfterLast(4) { it < 4 }
assertEquals(0, idx)
assertContentEquals(listOf(4), list, "failed to insert in empty list")
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment