mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 01:25:21 +00:00
slightly increase padding (#295)
* slightly increase padding * better colors * add copy to bottom sheet * increase font size * base font size * anchor chat at the bottom
This commit is contained in:
@@ -7,7 +7,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -37,7 +37,7 @@ fun MessagesList(
|
||||
modifier: Modifier = Modifier,
|
||||
forceScrollToBottom: Boolean = false,
|
||||
onNicknameClick: ((String) -> Unit)? = null,
|
||||
onNicknameLongPress: ((String) -> Unit)? = null
|
||||
onMessageLongPress: ((BitchatMessage) -> Unit)? = null
|
||||
) {
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
@@ -48,15 +48,14 @@ fun MessagesList(
|
||||
LaunchedEffect(messages.size) {
|
||||
if (messages.isNotEmpty()) {
|
||||
val layoutInfo = listState.layoutInfo
|
||||
val lastVisibleIndex = layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: -1
|
||||
val totalItems = layoutInfo.totalItemsCount
|
||||
val firstVisibleIndex = layoutInfo.visibleItemsInfo.firstOrNull()?.index ?: -1
|
||||
|
||||
// Always scroll to bottom on first load, or when user is near the bottom
|
||||
// With reverseLayout=true and reversed data, index 0 is the latest message at the bottom
|
||||
val isFirstLoad = !hasScrolledToInitialPosition
|
||||
val isNearBottom = lastVisibleIndex >= totalItems - 3
|
||||
val isNearLatest = firstVisibleIndex <= 2
|
||||
|
||||
if (isFirstLoad || isNearBottom) {
|
||||
listState.animateScrollToItem(messages.size - 1)
|
||||
if (isFirstLoad || isNearLatest) {
|
||||
listState.animateScrollToItem(0)
|
||||
if (isFirstLoad) {
|
||||
hasScrolledToInitialPosition = true
|
||||
}
|
||||
@@ -67,25 +66,26 @@ fun MessagesList(
|
||||
// Force scroll to bottom when requested (e.g., when user sends a message)
|
||||
LaunchedEffect(forceScrollToBottom) {
|
||||
if (forceScrollToBottom && messages.isNotEmpty()) {
|
||||
listState.animateScrollToItem(messages.size - 1)
|
||||
// With reverseLayout=true and reversed data, latest is at index 0
|
||||
listState.animateScrollToItem(0)
|
||||
}
|
||||
}
|
||||
|
||||
SelectionContainer(modifier = modifier) {
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp)
|
||||
) {
|
||||
items(messages) { message ->
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = modifier,
|
||||
reverseLayout = true
|
||||
) {
|
||||
items(messages.asReversed()) { message ->
|
||||
MessageItem(
|
||||
message = message,
|
||||
currentUserNickname = currentUserNickname,
|
||||
meshService = meshService,
|
||||
onNicknameClick = onNicknameClick,
|
||||
onNicknameLongPress = onNicknameLongPress
|
||||
onMessageLongPress = onMessageLongPress
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ fun MessageItem(
|
||||
currentUserNickname: String,
|
||||
meshService: BluetoothMeshService,
|
||||
onNicknameClick: ((String) -> Unit)? = null,
|
||||
onNicknameLongPress: ((String) -> Unit)? = null
|
||||
onMessageLongPress: ((BitchatMessage) -> Unit)? = null
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val timeFormatter = remember { SimpleDateFormat("HH:mm:ss", Locale.getDefault()) }
|
||||
@@ -119,7 +119,7 @@ fun MessageItem(
|
||||
colorScheme = colorScheme,
|
||||
timeFormatter = timeFormatter,
|
||||
onNicknameClick = onNicknameClick,
|
||||
onNicknameLongPress = onNicknameLongPress,
|
||||
onMessageLongPress = onMessageLongPress,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
|
||||
@@ -164,7 +164,7 @@ private fun MessageTextWithClickableNicknames(
|
||||
colorScheme: ColorScheme,
|
||||
timeFormatter: SimpleDateFormat,
|
||||
onNicknameClick: ((String) -> Unit)?,
|
||||
onNicknameLongPress: ((String) -> Unit)?,
|
||||
onMessageLongPress: ((BitchatMessage) -> Unit)?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val annotatedText = formatMessageAsAnnotatedString(
|
||||
@@ -180,8 +180,8 @@ private fun MessageTextWithClickableNicknames(
|
||||
message.sender == currentUserNickname ||
|
||||
message.sender.startsWith("$currentUserNickname#")
|
||||
|
||||
if (!isSelf && (onNicknameClick != null || onNicknameLongPress != null)) {
|
||||
// Use Text with combinedClickable for nickname interactions
|
||||
if (!isSelf && (onNicknameClick != null || onMessageLongPress != null)) {
|
||||
// Use Text with combinedClickable for nickname interactions and message long press
|
||||
Text(
|
||||
text = annotatedText,
|
||||
modifier = modifier.combinedClickable(
|
||||
@@ -198,16 +198,8 @@ private fun MessageTextWithClickableNicknames(
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
// Handle long press for the first nickname
|
||||
val nicknameAnnotations = annotatedText.getStringAnnotations(
|
||||
tag = "nickname_click",
|
||||
start = 0,
|
||||
end = annotatedText.length
|
||||
)
|
||||
if (nicknameAnnotations.isNotEmpty()) {
|
||||
val nickname = nicknameAnnotations.first().item
|
||||
onNicknameLongPress?.invoke(nickname)
|
||||
}
|
||||
// Always use message long press - contains all necessary information
|
||||
onMessageLongPress?.invoke(message)
|
||||
}
|
||||
),
|
||||
fontFamily = FontFamily.Monospace,
|
||||
@@ -218,19 +210,24 @@ private fun MessageTextWithClickableNicknames(
|
||||
)
|
||||
)
|
||||
} else {
|
||||
// Use selectable text when no interactions needed
|
||||
SelectionContainer {
|
||||
Text(
|
||||
text = annotatedText,
|
||||
modifier = modifier,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
softWrap = true,
|
||||
overflow = TextOverflow.Visible,
|
||||
style = androidx.compose.ui.text.TextStyle(
|
||||
color = colorScheme.onSurface
|
||||
// Use regular text with message long press support for own messages
|
||||
Text(
|
||||
text = annotatedText,
|
||||
modifier = if (onMessageLongPress != null) {
|
||||
modifier.combinedClickable(
|
||||
onClick = { /* No action for own messages */ },
|
||||
onLongClick = { onMessageLongPress.invoke(message) }
|
||||
)
|
||||
} else {
|
||||
modifier
|
||||
},
|
||||
fontFamily = FontFamily.Monospace,
|
||||
softWrap = true,
|
||||
overflow = TextOverflow.Visible,
|
||||
style = androidx.compose.ui.text.TextStyle(
|
||||
color = colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user