feat: show the last message and its time on the home chat list
The row was a centred column with the room's name in it and nothing else. It is now a row: the name and a one-line preview of what was last said in a weighted column on the left, the clock on the right. Both text lines are clipped to one with an ellipsis, the name included, and that is what keeps the clock on the row. A long subject, or a five-member group whose title is five names joined with commas, would otherwise push the timestamp off the edge; a multi-line message would push the next room down the screen. The clipping is on the title's own composable rather than the row, because that is where the three ways of building a title live -- a subject, "Note to Self", or the participant list -- and only one of them being clipped is the shape this would rot into. The clock is absent rather than blank for a room with nothing in it. There is no message time to show, and the room's own creation -- which is what it sorts on in that case -- is not something the user has any reason to read here. The preview line carries "No messages yet" in its place, which is the honest state for a room that exists because it was just made, or because a member joined a working group and is still waiting on the chronicle to fill it in. Everything the row renders was decided in the model, so this commit is the card body and the title clipping and nothing else. Verified: `:composeApp:compileDebugKotlinAndroid` builds, and the full `:composeApp:jvmTest` suite passes at 526 tests, 0 failures -- the 503 that were there before this branch plus its 23. The layout itself has not been run on a device; it is checked by compilation and by the model tests behind it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -42,12 +42,16 @@ data class LocalChatRoom(
|
||||
if (chatRoom.subject != null) {
|
||||
Text(
|
||||
text = chatRoom.subject,
|
||||
color = ProfileColor.fromPublicKey(chatRoom.id)
|
||||
color = ProfileColor.fromPublicKey(chatRoom.id),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
} else {
|
||||
if (localParticipants.size == 1) {
|
||||
Text(
|
||||
text = "Note to Self (${localParticipants.first().profile?.humanReadableNameOrPubkey()})"
|
||||
text = "Note to Self (${localParticipants.first().profile?.humanReadableNameOrPubkey()})",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
} else {
|
||||
// Remove the active user publicKey from participants...
|
||||
@@ -66,6 +70,8 @@ data class LocalChatRoom(
|
||||
append(participantName)
|
||||
}
|
||||
},
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package press.mantra.compose.ui.view.model
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@@ -11,6 +12,7 @@ import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.LoadingIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -27,6 +29,7 @@ import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import press.mantra.compose.database.model.NegentropySynchronizeRequest
|
||||
import press.mantra.compose.database.model.types.SynchronizationFilter
|
||||
import press.mantra.compose.extensions.toChatListTimestampString
|
||||
import press.mantra.compose.nostr.Nip17Filters
|
||||
import press.mantra.compose.nostr.Relays
|
||||
import press.mantra.compose.repository.ChatRepository
|
||||
@@ -186,11 +189,36 @@ class ChatRoomListViewModel(
|
||||
)
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(20.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(20.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
localChatRoom.RenderChatRoomTitleText()
|
||||
// Both lines are clipped to one, so the name
|
||||
// and the preview keep their width whatever
|
||||
// was said -- a long message must not push
|
||||
// the clock off the row.
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
localChatRoom.RenderChatRoomTitleText()
|
||||
localChatRoom.RenderChatRoomLastMessageText()
|
||||
}
|
||||
|
||||
// Absent rather than blank for a room with
|
||||
// nothing in it: there is no time to show,
|
||||
// and the room's own creation -- which is
|
||||
// what it sorts on -- is not one the user
|
||||
// has any reason to read here.
|
||||
localChatRoom.lastChatMessage?.let { lastChatMessage ->
|
||||
Text(
|
||||
text = lastChatMessage.createdAt.toChatListTimestampString(),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user