1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-2966 Chats | Fix | Fix visibility range detection logic (#2396)

This commit is contained in:
Evgenii Kozlov 2025-05-12 22:55:17 +02:00 committed by GitHub
parent 70219cce56
commit 71f4e03524
Signed by: github
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 14 deletions

View file

@ -66,7 +66,7 @@ class ChatContainer @Inject constructor(
}
}
.distinctUntilChanged()
.map { wrappers -> wrappers.associate { it.id to it } }
.map { wrappers -> wrappers.associateBy { it.id } }
}
// TODO Naive implementation. Add caching logic
@ -115,18 +115,18 @@ class ChatContainer @Inject constructor(
cacheLastMessages(result.messages)
}
val state = response.chatState ?: Chat.State()
val initialState = response.chatState ?: Chat.State()
var intent: Intent = Intent.None
val initial = buildList<Chat.Message> {
if (state.hasUnReadMessages && !state.oldestMessageOrderId.isNullOrEmpty()) {
if (initialState.hasUnReadMessages && !initialState.oldestMessageOrderId.isNullOrEmpty()) {
// Starting from the unread-messages window.
val aroundUnread = loadAroundMessageOrder(
chat = chat,
order = state.oldestMessageOrderId.orEmpty()
order = initialState.oldestMessageOrderId.orEmpty()
).also {
val target = it.find { it.order == state.oldestMessageOrderId }
val target = it.find { it.order == initialState.oldestMessageOrderId }
if (target != null) {
intent = Intent.ScrollToMessage(target.id)
}
@ -148,7 +148,7 @@ class ChatContainer @Inject constructor(
inputs.scan(
initial = ChatStreamState(
messages = initial,
state = state,
state = initialState,
intent = intent
)
) { state, transform ->
@ -184,6 +184,7 @@ class ChatContainer @Inject constructor(
)
}
is Transformation.Commands.LoadEnd -> {
logger.logInfo("DROID-2966 intent while load end: $intent")
if (state.messages.isNotEmpty()) {
if (state.state.hasUnReadMessages) {
// Check if above the unread messages
@ -238,6 +239,7 @@ class ChatContainer @Inject constructor(
)
}
} else {
// TODO optimise by checking last message and last message in state
if (lastMessages.contains(transform.lastVisibleMessage)) {
// No need to paginate, just scroll to bottom.
state.copy(
@ -245,12 +247,15 @@ class ChatContainer @Inject constructor(
)
} else {
val messages = try {
loadToEnd(chat)
loadToEnd(chat).also {
logger.logInfo("DROID-2966 Loaded chat tail because last message did not contained last visible message")
}
} catch (e: Exception) {
state.messages.also {
logger.logException(e, "DROID-2966 Error while scrolling to bottom")
}
}
ChatStreamState(
messages = messages,
intent = Intent.ScrollToBottom,
@ -262,6 +267,11 @@ class ChatContainer @Inject constructor(
state
}
}
is Transformation.Commands.ClearIntent -> {
state.copy(
intent = Intent.None
)
}
is Transformation.Commands.UpdateVisibleRange -> {
val unread = state.state
val readFrom = state.messages.find { it.id == transform.from }
@ -280,9 +290,9 @@ class ChatContainer @Inject constructor(
)
)
}.onFailure {
logger.logException(it, "Error while reading messages")
logger.logException(it, "DROID-2966 Error while reading messages")
}.onSuccess {
logger.logInfo("Read messages with success")
logger.logInfo("DROID-2966 Read messages with success")
}
}
state
@ -291,6 +301,8 @@ class ChatContainer @Inject constructor(
state.reduce(transform.events)
}
}
}.onEach {
logger.logInfo("DROID-2966 New emission with intent: ${it.intent}")
}.distinctUntilChanged()
)
}.catch { e ->
@ -557,6 +569,11 @@ class ChatContainer @Inject constructor(
}
}
suspend fun onClearIntent() {
logger.logInfo("DROID-2966 onClearIntent called")
commands.emit(Transformation.Commands.ClearIntent)
}
internal sealed class Transformation {
sealed class Events : Transformation() {
data class Payload(val events: List<Event.Command.Chats>) : Events()
@ -585,6 +602,8 @@ class ChatContainer @Inject constructor(
data class LoadEnd(val lastVisibleMessage: Id?): Commands()
data class UpdateVisibleRange(val from: Id, val to: Id) : Commands()
data object ClearIntent : Commands()
}
}

View file

@ -949,9 +949,7 @@ class ChatViewModel @Inject constructor(
fun onClearChatViewStateIntent() {
Timber.d("DROID-2966 onClearChatViewStateIntent")
viewModelScope.launch {
uiState.update { current ->
current.copy(intent = ChatContainer.Intent.None)
}
chatContainer.onClearIntent()
}
}

View file

@ -371,7 +371,7 @@ fun ChatScreen(
// Applying view model intents
LaunchedEffect(intent) {
when (val intent = intent) {
when (intent) {
is ChatContainer.Intent.ScrollToMessage -> {
isPerformingScrollIntent.value = true
val index = messages.indexOfFirst {
@ -404,9 +404,10 @@ fun ChatScreen(
}
// Tracking visible range
LaunchedEffect(lazyListState) {
LaunchedEffect(lazyListState, messages) {
snapshotFlow { lazyListState.layoutInfo }
.mapNotNull { layoutInfo ->
// TODO optimise by only sending event when scrolling towards bottom
val viewportHeight = layoutInfo.viewportSize.height
val visibleMessages = layoutInfo.visibleItemsInfo
.filter { item ->
@ -899,6 +900,7 @@ fun TopDiscussionToolbar(
}
suspend fun smoothScrollToBottom(lazyListState: LazyListState) {
Timber.d("DROID-2966 Performing scroll-to-bottom")
lazyListState.scrollToItem(0)
// Wait for the layout to settle after scrolling