95 lines
3.7 KiB
Kotlin
95 lines
3.7 KiB
Kotlin
package chats.data.remote.signalr
|
|
|
|
import android.content.Context
|
|
import core.notifications.data.ActiveChatTracker
|
|
import core.notifications.data.NotificationHelper
|
|
import core.security.TokenManager
|
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.SupervisorJob
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.flow.filterIsInstance
|
|
import kotlinx.coroutines.flow.launchIn
|
|
import kotlinx.coroutines.flow.onEach
|
|
import javax.inject.Inject
|
|
import javax.inject.Singleton
|
|
|
|
@Singleton
|
|
class SignalRNotificationObserver @Inject constructor(
|
|
private val signalrClient: ChatHubClient,
|
|
private val activeChatTracker: ActiveChatTracker,
|
|
private val tokenManager: TokenManager,
|
|
private val chatRepository: chats.domain.repository.ChatRepository,
|
|
@ApplicationContext private val context: Context
|
|
) {
|
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
private var isStarted = false
|
|
private val processedMessageIds = mutableSetOf<String>()
|
|
|
|
fun refresh() {
|
|
scope.launch {
|
|
try {
|
|
val chats = chatRepository.getChats()
|
|
val total = chats.sumOf { it.unreadCount }
|
|
activeChatTracker.setTotalUnreadCount(total)
|
|
} catch (e: Exception) {
|
|
// Ignore load error
|
|
}
|
|
}
|
|
}
|
|
|
|
fun start() {
|
|
if (isStarted) return
|
|
isStarted = true
|
|
|
|
// Initial count load
|
|
refresh()
|
|
|
|
signalrClient.events
|
|
.onEach { event ->
|
|
when (event) {
|
|
is ChatEvent.NewMessage -> {
|
|
val currentUserId = tokenManager.getUserId()
|
|
val message = event.message
|
|
|
|
// Don't show if it's our message or already processed
|
|
if (message.senderId == currentUserId) return@onEach
|
|
if (processedMessageIds.contains(message.id)) return@onEach
|
|
|
|
// Mark as processed
|
|
processedMessageIds.add(message.id)
|
|
if (processedMessageIds.size > 200) {
|
|
processedMessageIds.remove(processedMessageIds.first())
|
|
}
|
|
|
|
// Increment immediately for UI feedback
|
|
activeChatTracker.incrementUnreadCount()
|
|
|
|
// Refresh total count from source of truth in background
|
|
refresh()
|
|
|
|
// Don't show if this chat is currently open
|
|
if (activeChatTracker.currentChatId.value == message.chatId) return@onEach
|
|
|
|
NotificationHelper.showNotification(
|
|
context = context,
|
|
title = message.sender?.displayName ?: "Новое сообщение",
|
|
body = message.content ?: "Вам прислали вложение",
|
|
type = "chat",
|
|
chatId = message.chatId,
|
|
notificationId = message.id.hashCode(),
|
|
totalCount = activeChatTracker.totalUnreadCount.value
|
|
)
|
|
}
|
|
is ChatEvent.MessagesRead -> {
|
|
// If anyone read messages, sync our total count
|
|
refresh()
|
|
}
|
|
else -> Unit
|
|
}
|
|
}
|
|
.launchIn(scope)
|
|
}
|
|
}
|