All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.com.sceyt.chatuikit.services.SceytPresenceChecker.kt Maven / Gradle / Ivy

There is a newer version: 1.7.2
Show newest version
package com.sceyt.chatuikit.services

import com.sceyt.chat.models.user.Presence
import com.sceyt.chatuikit.data.managers.connection.ConnectionEventManager
import com.sceyt.chatuikit.data.models.SceytResponse
import com.sceyt.chatuikit.data.models.messages.SceytUser
import com.sceyt.chatuikit.extensions.getPresentableName
import com.sceyt.chatuikit.extensions.isAppOnForeground
import com.sceyt.chatuikit.koin.SceytKoinComponent
import com.sceyt.chatuikit.persistence.interactor.UserInteractor
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.runBlocking
import org.koin.core.component.inject
import java.util.Collections
import java.util.Timer
import kotlin.concurrent.timer

object SceytPresenceChecker : SceytKoinComponent {
    private val userInteractor: UserInteractor by inject()

    private val onPresenceCheckUsersFlow_: MutableSharedFlow> = MutableSharedFlow(
        extraBufferCapacity = 5,
        onBufferOverflow = BufferOverflow.DROP_OLDEST)
    val onPresenceCheckUsersFlow = onPresenceCheckUsersFlow_.asSharedFlow()

    private const val presenceCheckCapacity = 12
    private var workJob: Job? = null

    @Volatile
    private var presenceCheckTimer: Timer? = null
    private val presenceCheckUsers = Collections.synchronizedMap(object : LinkedHashMap(presenceCheckCapacity) {
        override fun removeEldestEntry(eldest: MutableMap.MutableEntry): Boolean {
            return size > presenceCheckCapacity
        }
    })

    @Synchronized
    fun startPresenceCheck() {
        if (presenceCheckTimer == null) {
            presenceCheckTimer = timer(name = "presence", initialDelay = 4000, period = 4000) {
                runBlocking { getUsers() }
            }
        }
    }

    private suspend fun getUsers() {
        if (presenceCheckUsers.keys.isEmpty() || !isAppOnForeground() || !ConnectionEventManager.isConnected) return
        val result = userInteractor.getUsersByIds(presenceCheckUsers.keys.toList())
        if (result is SceytResponse.Success) {
            result.data?.let { users ->
                users.forEach {
                    updateUserPresence(it)
                }
                onPresenceCheckUsersFlow_.tryEmit(users.map { PresenceUser(it) })
            }
        }
    }

    private fun updateUserPresence(user: SceytUser) {
        val oldUser = presenceCheckUsers[user.id]
        if (oldUser != null) presenceCheckUsers[user.id] = user
    }

    fun addNewUserToPresenceCheck(userId: String?) {
        userId ?: return
        presenceCheckUsers[userId] = SceytUser(userId)
    }

    fun removeFromPresenceCheck(userId: String) {
        presenceCheckUsers.remove(userId)
    }

    fun getUser(id: String): SceytUser? {
        return presenceCheckUsers[id]
    }

    @Synchronized
    fun stopPresenceCheck() {
        if (presenceCheckTimer != null) {
            presenceCheckTimer?.cancel()
            presenceCheckTimer?.purge()
            workJob?.cancel()
            presenceCheckTimer = null
        }
    }

    data class PresenceUser(val user: SceytUser) {

        private fun arePresencesEquals(one: Presence?, two: Presence?): Boolean {
            return one?.status == two?.status && one?.state == two?.state && one?.lastActiveAt == two?.lastActiveAt
        }

        override fun equals(other: Any?): Boolean {
            return other is PresenceUser && other.user.id == user.id
                    && arePresencesEquals(other.user.presence, user.presence)
                    && other.user.getPresentableName() == user.getPresentableName()
                    && other.user.avatarURL == user.avatarURL
        }

        override fun hashCode(): Int {
            return user.hashCode()
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy