feat: show timestamp on the last message of each author run

A small time label now sits in the bubble's bottom-end corner of the last
message of a group (and singles), so temporal context is always visible
without repeating it on every bubble. Hidden while the tap-to-expand
detail row is open, which already includes the time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129yvP2hmVeDFfuKKy94tqX
This commit is contained in:
Claude
2026-07-11 03:45:21 +00:00
parent 34bf660455
commit 5a2587c085
3 changed files with 17 additions and 0 deletions
@@ -265,6 +265,12 @@ fun NormalChatNote(
} else {
null
},
timeRow =
if (!innerQuote && groupPosition.isLastOfGroup) {
{ ChatTimeAgo(note) }
} else {
null
},
drawAuthorLine = {
DrawAuthorInfo(
note,
@@ -27,6 +27,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
@@ -87,6 +88,9 @@ fun ChatBubbleLayout(
onAuthorClick: () -> Unit,
actionMenu: @Composable (onDismiss: () -> Unit) -> Unit,
reactionsRow: (@Composable () -> Unit)? = null,
// Small always-visible timestamp in the bubble's bottom-end corner; skipped
// while the tap-to-expand detail row (which includes the time) is open.
timeRow: (@Composable () -> Unit)? = null,
detailRow: @Composable () -> Unit,
drawAuthorLine: @Composable () -> Unit,
inner: @Composable (MutableState<Color>) -> Unit,
@@ -193,6 +197,10 @@ fun ChatBubbleLayout(
if (showDetails.value) {
detailRow()
} else if (timeRow != null) {
Box(modifier = Modifier.align(Alignment.End)) {
timeRow()
}
}
}
}
@@ -56,6 +56,9 @@ enum class ChatGroupPosition {
val isFirstOfGroup: Boolean
get() = this == SINGLE || this == TOP
val isLastOfGroup: Boolean
get() = this == SINGLE || this == BOTTOM
val isConnectedAbove: Boolean
get() = this == MIDDLE || this == BOTTOM
}