mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 19:53:08 +00:00
feat: geohash composer polish + hide the room's own cell in bubbles
- Center the composer identity avatar vertically instead of bottom-aligning it (the "post as me" picture was sinking to the bottom of the edit row). - Halve the gap between the avatar and the text field (drop the avatar's end padding and nudge the field left into its fixed inset). - Drop the divider line between the feed and the composer — the other chat screens don't use one, and the rounded field is separation enough. - In a location room, suppress the room's own geohash in each message's footer/time row (every message repeats the room cell, so showing it is noise). Done via a new LocalChatSuppressGeohash composition-local, factored into both the footer-has-metadata gate and the footer render; any other geohash still shows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172JoMccseEKenyWan6txWV
This commit is contained in:
+12
-2
@@ -249,8 +249,11 @@ fun NormalChatNote(
|
||||
}
|
||||
|
||||
// The footer shows on the last message of a run (for the time) and on any message
|
||||
// carrying per-message metadata (expiration, geohash, PoW, legacy-DM marker).
|
||||
val footerHasMeta = remember(note.event) { chatFooterHasMeta(note) }
|
||||
// carrying per-message metadata (expiration, geohash, PoW, legacy-DM marker). In a geohash
|
||||
// room every message repeats the room's own cell, so that geohash is suppressed and doesn't,
|
||||
// by itself, force a footer row (see LocalChatSuppressGeohash).
|
||||
val suppressGeohash = LocalChatSuppressGeohash.current
|
||||
val footerHasMeta = remember(note.event, suppressGeohash) { chatFooterHasMeta(note, suppressGeohash) }
|
||||
|
||||
// Only mount the reaction/zap chip row when the message actually has engagement.
|
||||
// The chips overlap the bubble's bottom edge, so the bubble reserves space beneath
|
||||
@@ -458,6 +461,13 @@ val LocalChatDisplayNameResolver = compositionLocalOf<((Note) -> String?)?> { nu
|
||||
*/
|
||||
val LocalChatShowSelfAuthorName = compositionLocalOf { false }
|
||||
|
||||
/**
|
||||
* The geohash of the location room currently open, or null outside one. Every message in that room
|
||||
* repeats the room's own cell in its `g` tag, so the bubble footer suppresses this one geohash —
|
||||
* showing it on every message is redundant noise. Any other geohash still renders.
|
||||
*/
|
||||
val LocalChatSuppressGeohash = compositionLocalOf<String?> { null }
|
||||
|
||||
@Composable
|
||||
fun RenderReplyRow(
|
||||
note: Note,
|
||||
|
||||
+12
-3
@@ -74,11 +74,17 @@ fun ChatTimeAgo(baseNote: Note) {
|
||||
* row) while still surfacing these per-message details that used to live in the
|
||||
* tap-to-expand "complete UI" detail row.
|
||||
*/
|
||||
fun chatFooterHasMeta(note: Note): Boolean {
|
||||
fun chatFooterHasMeta(
|
||||
note: Note,
|
||||
// The location room's own cell, when open. A message whose only metadata is this geohash carries
|
||||
// no footer-worthy detail (the room header already says where we are), so it doesn't force a row.
|
||||
suppressGeohash: String? = null,
|
||||
): Boolean {
|
||||
val event = note.event ?: return false
|
||||
val geo = event.geoHashOrScope()
|
||||
return event is PrivateDmEvent ||
|
||||
event.expiration() != null ||
|
||||
event.geoHashOrScope() != null ||
|
||||
(geo != null && geo != suppressGeohash) ||
|
||||
event.strongPoWOrNull() != null ||
|
||||
note.isPinnedInRelayGroup()
|
||||
}
|
||||
@@ -102,7 +108,10 @@ fun ChatMessageFooter(
|
||||
nav: INav,
|
||||
) {
|
||||
val event = note.event
|
||||
val geo = remember(event) { event?.geoHashOrScope() }
|
||||
val geoRaw = remember(event) { event?.geoHashOrScope() }
|
||||
// Hide the room's own cell (repeated on every message here); keep any other geohash.
|
||||
val suppressGeohash = LocalChatSuppressGeohash.current
|
||||
val geo = if (geoRaw != null && geoRaw != suppressGeohash) geoRaw else null
|
||||
val pow = remember(event) { event?.strongPoWOrNull() }
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
|
||||
+8
-5
@@ -32,6 +32,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
@@ -39,7 +40,6 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
@@ -78,6 +78,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.LocalChatActingI
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.LocalChatDisplayNameResolver
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.LocalChatReactOverride
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.LocalChatShowSelfAuthorName
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.LocalChatSuppressGeohash
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.RefreshingChatroomFeedView
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.dal.ChannelFeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.datasource.ChannelFilterAssemblerSubscription
|
||||
@@ -203,6 +204,7 @@ private fun GeohashChatRoom(
|
||||
Box(Modifier.weight(1f).fillMaxWidth()) {
|
||||
CompositionLocalProvider(
|
||||
LocalChatShowSelfAuthorName provides true,
|
||||
LocalChatSuppressGeohash provides geohash,
|
||||
LocalChatActingIdentities provides myPubKeys,
|
||||
LocalChatReactOverride provides { note, reaction ->
|
||||
identity.react(note, reaction, newMessageModel.geohashPostAsSelf)
|
||||
@@ -233,20 +235,21 @@ private fun GeohashChatRoom(
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
if (newMessageModel.geohashTeleported) {
|
||||
TeleportIndicatorRow()
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.Bottom,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
GeohashIdentityAvatar(
|
||||
model = newMessageModel,
|
||||
accountViewModel = accountViewModel,
|
||||
onRequestPostAsSelf = { showPostAsSelfWarning = true },
|
||||
)
|
||||
Box(Modifier.weight(1f)) {
|
||||
// Nudge the field left into the composer's fixed 10dp inset so the picture sits close
|
||||
// to the field rather than across a wide gap.
|
||||
Box(Modifier.weight(1f).offset(x = (-4).dp)) {
|
||||
EditFieldRow(
|
||||
channelScreenModel = newMessageModel,
|
||||
accountViewModel = accountViewModel,
|
||||
@@ -288,7 +291,7 @@ private fun GeohashIdentityAvatar(
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(start = 8.dp, end = 4.dp, bottom = 4.dp),
|
||||
modifier = Modifier.padding(start = 8.dp, end = 0.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
if (postAsSelf) {
|
||||
|
||||
Reference in New Issue
Block a user