Listening to changes in community write access

In order to allow the showing and hiding of the input bar dynamically
This commit is contained in:
ThomasSession 2024-09-16 09:03:17 +10:00
parent 74787f949c
commit e80f463bd1
4 changed files with 44 additions and 5 deletions

View File

@ -710,7 +710,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// called from onCreate // called from onCreate
private fun setUpInputBar() { private fun setUpInputBar() {
binding.inputBar.isGone = viewModel.hidesInputBar()
binding.inputBar.delegate = this binding.inputBar.delegate = this
binding.inputBarRecordingView.delegate = this binding.inputBarRecordingView.delegate = this
// GIF button // GIF button
@ -854,6 +853,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// Conversation should be deleted now, just go back // Conversation should be deleted now, just go back
finish() finish()
} }
binding.inputBar.isGone = uiState.hideInputBar
} }
} }
} }

View File

@ -9,8 +9,12 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.session.libsession.database.MessageDataProvider import org.session.libsession.database.MessageDataProvider
@ -29,6 +33,7 @@ import org.thoughtcrime.securesms.audio.AudioSlidePlayer
import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.Storage
import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.repository.ConversationRepository import org.thoughtcrime.securesms.repository.ConversationRepository
import java.util.UUID import java.util.UUID
@ -65,6 +70,8 @@ class ConversationViewModel(
} }
} }
private var communityWriteAccessJob: Job? = null
private var _openGroup: RetrieveOnce<OpenGroup> = RetrieveOnce { private var _openGroup: RetrieveOnce<OpenGroup> = RetrieveOnce {
storage.getOpenGroup(threadId) storage.getOpenGroup(threadId)
} }
@ -105,6 +112,23 @@ class ConversationViewModel(
} }
} }
} }
// listen to community write access updates from this point
communityWriteAccessJob?.cancel()
communityWriteAccessJob = viewModelScope.launch {
OpenGroupManager.getCommunitiesWriteAccessFlow()
.map { it[openGroup?.server] }
.filterNotNull()
.collect{
// update our community object
_openGroup.updateTo(openGroup?.copy(canWrite = it))
// when we get an update on the write access of a community
// we need to update the input text accordingly
_uiState.update {
it.copy(hideInputBar = shouldHideInputBar())
}
}
}
} }
override fun onCleared() { override fun onCleared() {
@ -267,7 +291,7 @@ class ConversationViewModel(
* - We are dealing with a contact from a community (blinded recipient) that does not allow * - We are dealing with a contact from a community (blinded recipient) that does not allow
* requests form community members * requests form community members
*/ */
fun hidesInputBar(): Boolean = openGroup?.canWrite == false || private fun shouldHideInputBar(): Boolean = openGroup?.canWrite == false ||
blindedRecipient?.blocksCommunityMessageRequests == true blindedRecipient?.blocksCommunityMessageRequests == true
fun legacyBannerRecipient(context: Context): Recipient? = recipient?.run { fun legacyBannerRecipient(context: Context): Recipient? = recipient?.run {
@ -311,7 +335,8 @@ data class UiMessage(val id: Long, val message: String)
data class ConversationUiState( data class ConversationUiState(
val uiMessages: List<UiMessage> = emptyList(), val uiMessages: List<UiMessage> = emptyList(),
val isMessageRequestAccepted: Boolean? = null, val isMessageRequestAccepted: Boolean? = null,
val conversationExists: Boolean val conversationExists: Boolean,
val hideInputBar: Boolean = false
) )
data class RetrieveOnce<T>(val retrieval: () -> T?) { data class RetrieveOnce<T>(val retrieval: () -> T?) {

View File

@ -4,6 +4,9 @@ import android.content.Context
import android.widget.Toast import android.widget.Toast
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import com.squareup.phrase.Phrase import com.squareup.phrase.Phrase
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.util.concurrent.Executors import java.util.concurrent.Executors
import network.loki.messenger.R import network.loki.messenger.R
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@ -39,6 +42,9 @@ object OpenGroupManager {
return true return true
} }
// flow holding information on write access for our current communities
private val _communityWriteAccess: MutableStateFlow<Map<String, Boolean>> = MutableStateFlow(emptyMap())
fun startPolling() { fun startPolling() {
if (isPolling) { return } if (isPolling) { return }
isPolling = true isPolling = true
@ -66,6 +72,8 @@ object OpenGroupManager {
} }
} }
fun getCommunitiesWriteAccessFlow() = _communityWriteAccess.asStateFlow()
@WorkerThread @WorkerThread
fun add(server: String, room: String, publicKey: String, context: Context): Pair<Long,OpenGroupApi.RoomInfo?> { fun add(server: String, room: String, publicKey: String, context: Context): Pair<Long,OpenGroupApi.RoomInfo?> {
val openGroupID = "$server.$room" val openGroupID = "$server.$room"
@ -167,6 +175,11 @@ object OpenGroupManager {
val openGroupID = "${openGroup.server}.${openGroup.room}" val openGroupID = "${openGroup.server}.${openGroup.room}"
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context) val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context)
threadDB.setOpenGroupChat(openGroup, threadID) threadDB.setOpenGroupChat(openGroup, threadID)
// update write access for this community
val writeAccesses = _communityWriteAccess.value.toMutableMap()
writeAccesses[openGroup.server] = openGroup.canWrite
_communityWriteAccess.value = writeAccesses
} }
fun isUserModerator(context: Context, groupId: String, standardPublicKey: String, blindedPublicKey: String? = null): Boolean { fun isUserModerator(context: Context, groupId: String, standardPublicKey: String, blindedPublicKey: String? = null): Boolean {

View File

@ -203,7 +203,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
@Test @Test
fun `local recipient should have input and no blinded recipient`() { fun `local recipient should have input and no blinded recipient`() {
whenever(recipient.isLocalNumber).thenReturn(true) whenever(recipient.isLocalNumber).thenReturn(true)
assertThat(viewModel.hidesInputBar(), equalTo(false)) assertThat(viewModel.uiState.value.hideInputBar, equalTo(false))
assertThat(viewModel.blindedRecipient, nullValue()) assertThat(viewModel.blindedRecipient, nullValue())
} }
@ -215,7 +215,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
} }
whenever(repository.maybeGetBlindedRecipient(recipient)).thenReturn(blinded) whenever(repository.maybeGetBlindedRecipient(recipient)).thenReturn(blinded)
assertThat(viewModel.blindedRecipient, notNullValue()) assertThat(viewModel.blindedRecipient, notNullValue())
assertThat(viewModel.hidesInputBar(), equalTo(true)) assertThat(viewModel.uiState.value.hideInputBar, equalTo(true))
} }
} }