diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 9259a2bca9..19c8b11ca5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -19,6 +19,8 @@ import chat.simplex.res.MR import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.StringResource import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.internal.ChannelFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.datetime.* @@ -301,9 +303,7 @@ object ChatModel { else chat.chatStats ) - if (i > 0) { - chats.add(index = 0, chats.removeAt(i)) - } + popChatCollector.addChat(chat.remoteHostId, chat.id) } else { addChat(Chat(remoteHostId = rhId, chatInfo = cInfo, chatItems = arrayListOf(cItem))) } @@ -421,6 +421,32 @@ object ChatModel { } } + private val popChatCollector = PopChatCollector() + + class PopChatCollector { + private val subject = MutableSharedFlow() + + init { + withLongRunningApi { + subject + .throttleLatest(2000) + .collect { + withChats { + chats.replaceAll(chats.value.sortedByDescending { it.popTs }) + } + } + } + } + + suspend fun addChat(remoteHostId: Long?, chatId: ChatId) { + val index = getChatIndex(remoteHostId, chatId) + if (index >= 0) { + chats.value[index].popTs = Clock.System.now() + subject.emit(Unit) + } + } + } + fun markChatItemsRead(remoteHostId: Long?, chatInfo: ChatInfo, range: CC.ItemRange? = null, unreadCountAfter: Int? = null) { val cInfo = chatInfo val markedRead = markItemsReadInCurrentChat(chatInfo, range) @@ -847,6 +873,9 @@ data class Chat( val chatItems: List, val chatStats: ChatStats = ChatStats() ) { + @Transient + var popTs: Instant? = null + val nextSendGrpInv: Boolean get() = when (chatInfo) { is ChatInfo.Direct -> chatInfo.contact.nextSendGrpInv diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index cc4194d0c8..7512cf872e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -16,6 +16,7 @@ import chat.simplex.res.MR import com.charleskorn.kaml.decodeFromStream import dev.icerock.moko.resources.StringResource import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* import kotlinx.serialization.encodeToString import java.io.* import java.net.URI @@ -535,6 +536,13 @@ fun TextUnit.toDp(): Dp { return Dp(value * LocalDensity.current.fontScale) } +fun Flow.throttleLatest(delayMillis: Long): Flow = this + .conflate() + .transform { + emit(it) + delay(delayMillis) + } + @Composable fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenGone: () -> Unit) { DisposableEffect(Unit) {