Skip to content

Commit 2989318

Browse files
committed
fix(fc): prevent jumping back to unread separator
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 61dc026 commit 2989318

4 files changed

Lines changed: 22 additions & 15 deletions

File tree

flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationMessages.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package xyz.flipchat.app.features.chat.conversation
22

3+
import androidx.compose.animation.core.animateFloatAsState
4+
import androidx.compose.animation.core.tween
35
import androidx.compose.foundation.Image
46
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.ExperimentalLayoutApi
58
import androidx.compose.foundation.layout.fillMaxSize
69
import androidx.compose.foundation.layout.padding
710
import androidx.compose.foundation.lazy.rememberLazyListState
@@ -135,10 +138,16 @@ internal fun ConversationMessages(
135138
}
136139
)
137140

141+
val animatedAlpha by animateFloatAsState(
142+
targetValue = if (lazyListState.canScrollBackward) 1f else 0f,
143+
animationSpec = tween(durationMillis = 300),
144+
label = "alpha of jump-to-bottom"
145+
)
146+
138147
Surface(
139148
modifier = Modifier
140149
.graphicsLayer {
141-
alpha = if (lazyListState.canScrollBackward) 1f else 0f
150+
alpha = animatedAlpha
142151
}
143152
.padding(
144153
end = CodeTheme.dimens.inset,

flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationViewModel.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,6 @@ class ConversationViewModel @Inject constructor(
720720
messageControls = MessageControls(
721721
actions = buildMessageActions(message, member, contents, enableReply),
722722
),
723-
key = message.id.uuid.toString()
724723
)
725724
}
726725
}

ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.compose.runtime.LaunchedEffect
1212
import androidx.compose.runtime.getValue
1313
import androidx.compose.runtime.mutableStateOf
1414
import androidx.compose.runtime.remember
15+
import androidx.compose.runtime.saveable.rememberSaveable
1516
import androidx.compose.runtime.setValue
1617
import androidx.compose.runtime.snapshotFlow
1718
import androidx.compose.ui.Modifier
@@ -33,6 +34,7 @@ import com.getcode.util.formatDateRelatively
3334
import kotlinx.coroutines.flow.combine
3435
import kotlinx.coroutines.flow.distinctUntilChanged
3536
import kotlinx.coroutines.flow.filter
37+
import kotlinx.coroutines.flow.filterNot
3638

3739
sealed interface MessageListEvent {
3840
data class AdvancePointer(val messageId: ID) : MessageListEvent
@@ -66,7 +68,7 @@ fun MessageList(
6668
},
6769
dispatch: (MessageListEvent) -> Unit = { },
6870
) {
69-
var hasSetAtUnread by remember { mutableStateOf(false) }
71+
var hasSetAtUnread by rememberSaveable(key = "0") { mutableStateOf(false) }
7072

7173
HandleMessageReads(listState, messages, hasSetAtUnread) {
7274
dispatch(MessageListEvent.AdvancePointer(it))
@@ -252,23 +254,21 @@ private fun HandleStartAtUnread(
252254
hasSetAtUnread: Boolean,
253255
onHandled: () -> Unit,
254256
) {
255-
val density = LocalDensity.current
257+
// Flag to ensure scroll logic runs only once
258+
var hasScrolledToUnread by rememberSaveable { mutableStateOf(false) }
259+
256260
LaunchedEffect(listState, messages) {
257261
snapshotFlow { messages.loadState }
262+
.filterNot { hasScrolledToUnread }
258263
.collect { loadState ->
259264
if (loadState.refresh is LoadState.NotLoading && messages.itemCount > 0) {
260265
val separatorIndex = messages.itemSnapshotList
261266
.indexOfFirst { it is ChatItem.UnreadSeparator }
262267

263-
if (separatorIndex >= 0 && !hasSetAtUnread) {
264-
// Calculate the center offset
265-
val centerOffset = with(density) {
266-
val viewportHeight = listState.layoutInfo.viewportSize.height.toDp()
267-
viewportHeight.roundToPx() / 2
268-
}
269-
268+
if (separatorIndex > 0 && !hasSetAtUnread) {
270269
onHandled()
271-
listState.scrollToItem(separatorIndex, scrollOffset = -centerOffset)
270+
hasScrolledToUnread = true
271+
listState.scrollToItem(separatorIndex - 1)
272272
} else {
273273
onHandled()
274274
}

ui/components/src/main/kotlin/com/getcode/ui/components/chat/utils/ChatItem.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.getcode.model.chat.ChatMessage
66
import com.getcode.model.chat.MessageContent
77
import com.getcode.model.chat.MessageStatus
88
import com.getcode.model.chat.Sender
9+
import com.getcode.model.uuid
910
import com.getcode.ui.components.chat.messagecontents.MessageControls
1011
import com.getcode.util.formatDateRelatively
1112
import kotlinx.datetime.Instant
@@ -26,7 +27,6 @@ data class ReplyMessageAnchor(
2627
sealed class ChatItem(open val key: Any) {
2728
@Stable
2829
data class Message(
29-
val id: String = UUID.randomUUID().toString(),
3030
val chatMessageId: ID,
3131
val message: MessageContent,
3232
val sender: Sender,
@@ -40,8 +40,7 @@ sealed class ChatItem(open val key: Any) {
4040
val enableMarkup: Boolean = false,
4141
val enableReply: Boolean = false,
4242
val originalMessage: ReplyMessageAnchor? = null,
43-
override val key: Any = id
44-
) : ChatItem(key) {
43+
) : ChatItem(chatMessageId.uuid!!) {
4544
val relativeDate: String = date.formatDateRelatively()
4645
}
4746

0 commit comments

Comments
 (0)