|
|
@ -15,11 +15,14 @@ import kotlinx.coroutines.flow.StateFlow
|
|
|
|
import kotlinx.coroutines.flow.combine
|
|
|
|
import kotlinx.coroutines.flow.combine
|
|
|
|
import kotlinx.coroutines.flow.debounce
|
|
|
|
import kotlinx.coroutines.flow.debounce
|
|
|
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
|
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.filter
|
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.flowOn
|
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
import kotlinx.coroutines.flow.mapLatest
|
|
|
|
import kotlinx.coroutines.flow.mapLatest
|
|
|
|
import kotlinx.coroutines.flow.merge
|
|
|
|
import kotlinx.coroutines.flow.merge
|
|
|
|
import kotlinx.coroutines.flow.onStart
|
|
|
|
import kotlinx.coroutines.flow.onStart
|
|
|
|
import kotlinx.coroutines.flow.stateIn
|
|
|
|
import kotlinx.coroutines.flow.stateIn
|
|
|
|
import kotlinx.coroutines.withContext
|
|
|
|
import org.session.libsession.utilities.TextSecurePreferences
|
|
|
|
import org.thoughtcrime.securesms.ApplicationContext
|
|
|
|
import org.thoughtcrime.securesms.ApplicationContext
|
|
|
|
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
|
|
|
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
|
|
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
|
|
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
|
|
@ -30,9 +33,10 @@ import dagger.hilt.android.qualifiers.ApplicationContext as ApplicationContextQu
|
|
|
|
|
|
|
|
|
|
|
|
@HiltViewModel
|
|
|
|
@HiltViewModel
|
|
|
|
class HomeViewModel @Inject constructor(
|
|
|
|
class HomeViewModel @Inject constructor(
|
|
|
|
private val threadDb: ThreadDatabase,
|
|
|
|
private val threadDb: ThreadDatabase,
|
|
|
|
private val contentResolver: ContentResolver,
|
|
|
|
private val contentResolver: ContentResolver,
|
|
|
|
@ApplicationContextQualifier private val context: Context,
|
|
|
|
private val prefs: TextSecurePreferences,
|
|
|
|
|
|
|
|
@ApplicationContextQualifier private val context: Context,
|
|
|
|
) : ViewModel() {
|
|
|
|
) : ViewModel() {
|
|
|
|
// SharedFlow that emits whenever the user asks us to reload the conversation
|
|
|
|
// SharedFlow that emits whenever the user asks us to reload the conversation
|
|
|
|
private val manualReloadTrigger = MutableSharedFlow<Unit>(
|
|
|
|
private val manualReloadTrigger = MutableSharedFlow<Unit>(
|
|
|
@ -46,8 +50,18 @@ class HomeViewModel @Inject constructor(
|
|
|
|
* This flow will emit whenever the user asks us to reload the conversation list or
|
|
|
|
* This flow will emit whenever the user asks us to reload the conversation list or
|
|
|
|
* whenever the conversation list changes.
|
|
|
|
* whenever the conversation list changes.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
val threads: StateFlow<Data?> = combine(observeConversationList(), observeTypingStatus(), ::Data)
|
|
|
|
val data: StateFlow<Data?> = combine(
|
|
|
|
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
|
|
|
|
observeConversationList(),
|
|
|
|
|
|
|
|
unapprovedConversationCount(),
|
|
|
|
|
|
|
|
hasHiddenMessageRequestsFlow(),
|
|
|
|
|
|
|
|
observeTypingStatus(),
|
|
|
|
|
|
|
|
::Data
|
|
|
|
|
|
|
|
).stateIn(viewModelScope, SharingStarted.Eagerly, null)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun hasHiddenMessageRequestsFlow() = TextSecurePreferences.events
|
|
|
|
|
|
|
|
.filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS }
|
|
|
|
|
|
|
|
.map { prefs.hasHiddenMessageRequests() }
|
|
|
|
|
|
|
|
.onStart { emit(prefs.hasHiddenMessageRequests()) }
|
|
|
|
|
|
|
|
|
|
|
|
private fun observeTypingStatus(): Flow<Set<Long>> =
|
|
|
|
private fun observeTypingStatus(): Flow<Set<Long>> =
|
|
|
|
ApplicationContext.getInstance(context).typingStatusRepository
|
|
|
|
ApplicationContext.getInstance(context).typingStatusRepository
|
|
|
@ -56,30 +70,38 @@ class HomeViewModel @Inject constructor(
|
|
|
|
.onStart { emit(emptySet()) }
|
|
|
|
.onStart { emit(emptySet()) }
|
|
|
|
.distinctUntilChanged()
|
|
|
|
.distinctUntilChanged()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun unapprovedConversationCount() =
|
|
|
|
|
|
|
|
contentResolver.observeChanges(DatabaseContentProviders.ConversationList.CONTENT_URI)
|
|
|
|
|
|
|
|
.flowOn(Dispatchers.IO)
|
|
|
|
|
|
|
|
.map { threadDb.unapprovedConversationCount }
|
|
|
|
|
|
|
|
.onStart { emit(threadDb.unapprovedConversationCount) }
|
|
|
|
|
|
|
|
|
|
|
|
@Suppress("OPT_IN_USAGE")
|
|
|
|
@Suppress("OPT_IN_USAGE")
|
|
|
|
private fun observeConversationList(): Flow<List<ThreadRecord>> = merge(
|
|
|
|
private fun observeConversationList(): Flow<List<ThreadRecord>> = merge(
|
|
|
|
manualReloadTrigger,
|
|
|
|
manualReloadTrigger,
|
|
|
|
contentResolver.observeChanges(DatabaseContentProviders.ConversationList.CONTENT_URI))
|
|
|
|
contentResolver.observeChanges(DatabaseContentProviders.ConversationList.CONTENT_URI)
|
|
|
|
.debounce(CHANGE_NOTIFICATION_DEBOUNCE_MILLS)
|
|
|
|
)
|
|
|
|
.onStart { emit(Unit) }
|
|
|
|
.flowOn(Dispatchers.IO)
|
|
|
|
.mapLatest { _ ->
|
|
|
|
.debounce(CHANGE_NOTIFICATION_DEBOUNCE_MILLS)
|
|
|
|
withContext(Dispatchers.IO) {
|
|
|
|
.onStart { emit(Unit) }
|
|
|
|
threadDb.approvedConversationList.use { openCursor ->
|
|
|
|
.mapLatest { _ ->
|
|
|
|
val reader = threadDb.readerFor(openCursor)
|
|
|
|
threadDb.approvedConversationList.use { openCursor ->
|
|
|
|
buildList(reader.count) {
|
|
|
|
val reader = threadDb.readerFor(openCursor)
|
|
|
|
while (true) {
|
|
|
|
buildList(reader.count) {
|
|
|
|
add(reader.next ?: break)
|
|
|
|
while (true) {
|
|
|
|
}
|
|
|
|
add(reader.next ?: break)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fun tryReload() = manualReloadTrigger.tryEmit(Unit)
|
|
|
|
fun tryReload() = manualReloadTrigger.tryEmit(Unit)
|
|
|
|
|
|
|
|
|
|
|
|
data class Data(
|
|
|
|
data class Data(
|
|
|
|
val threads: List<ThreadRecord>,
|
|
|
|
val threads: List<ThreadRecord>,
|
|
|
|
val typingThreadIDs: Set<Long>
|
|
|
|
val unapprovedConversationCount: Int,
|
|
|
|
|
|
|
|
val hasHiddenMessageRequests: Boolean,
|
|
|
|
|
|
|
|
val typingThreadIDs: Set<Long>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
companion object {
|
|
|
|