Merge pull request #1669 from oxen-io/feature/dynamic-community-rights

Listening to changes in community write access
This commit is contained in:
ThomasSession 2024-09-16 10:09:58 +10:00 committed by GitHub
commit d044f12d3f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 70 additions and 20 deletions

View File

@ -710,7 +710,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// called from onCreate
private fun setUpInputBar() {
binding.inputBar.isGone = viewModel.hidesInputBar()
binding.inputBar.delegate = this
binding.inputBarRecordingView.delegate = this
// GIF button
@ -854,6 +853,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// Conversation should be deleted now, just go back
finish()
}
binding.inputBar.isGone = uiState.hideInputBar
}
}
}
@ -948,12 +949,21 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
block(deleteThread = true)
}
binding.declineMessageRequestButton.setOnClickListener {
fun doDecline() {
viewModel.declineMessageRequest()
lifecycleScope.launch(Dispatchers.IO) {
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@ConversationActivityV2)
}
finish()
}
showSessionDialog {
title(R.string.delete)
text(resources.getString(R.string.messageRequestsDelete))
dangerButton(R.string.delete) { doDecline() }
button(R.string.cancel)
}
}
}
private fun acceptMessageRequest() {

View File

@ -9,8 +9,12 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
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.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.repository.ConversationRepository
import java.util.UUID
@ -65,6 +70,8 @@ class ConversationViewModel(
}
}
private var communityWriteAccessJob: Job? = null
private var _openGroup: RetrieveOnce<OpenGroup> = RetrieveOnce {
storage.getOpenGroup(threadId)
}
@ -105,6 +112,27 @@ class ConversationViewModel(
}
}
}
// listen to community write access updates from this point
communityWriteAccessJob?.cancel()
communityWriteAccessJob = viewModelScope.launch {
OpenGroupManager.getCommunitiesWriteAccessFlow()
.map {
if(openGroup?.groupId != null)
it[openGroup?.groupId]
else null
}
.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 { state ->
state.copy(hideInputBar = shouldHideInputBar())
}
}
}
}
override fun onCleared() {
@ -267,7 +295,7 @@ class ConversationViewModel(
* - We are dealing with a contact from a community (blinded recipient) that does not allow
* requests form community members
*/
fun hidesInputBar(): Boolean = openGroup?.canWrite == false ||
fun shouldHideInputBar(): Boolean = openGroup?.canWrite == false ||
blindedRecipient?.blocksCommunityMessageRequests == true
fun legacyBannerRecipient(context: Context): Recipient? = recipient?.run {
@ -311,7 +339,8 @@ data class UiMessage(val id: Long, val message: String)
data class ConversationUiState(
val uiMessages: List<UiMessage> = emptyList(),
val isMessageRequestAccepted: Boolean? = null,
val conversationExists: Boolean
val conversationExists: Boolean,
val hideInputBar: Boolean = false
)
data class RetrieveOnce<T>(val retrieval: () -> T?) {

View File

@ -18,7 +18,7 @@ class LinkPreviewDialog(private val onEnabled: () -> Unit) : DialogFragment() {
title(R.string.linkPreviewsEnable)
val txt = context.getSubbedCharSequence(R.string.linkPreviewsFirstDescription, APP_NAME_KEY to APP_NAME)
text(txt)
button(R.string.enable) { enable() }
dangerButton(R.string.enable) { enable() }
cancelButton { dismiss() }
}

View File

@ -4,6 +4,9 @@ import android.content.Context
import android.widget.Toast
import androidx.annotation.WorkerThread
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 network.loki.messenger.R
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@ -39,6 +42,9 @@ object OpenGroupManager {
return true
}
// flow holding information on write access for our current communities
private val _communityWriteAccess: MutableStateFlow<Map<String, Boolean>> = MutableStateFlow(emptyMap())
fun startPolling() {
if (isPolling) { return }
isPolling = true
@ -66,6 +72,8 @@ object OpenGroupManager {
}
}
fun getCommunitiesWriteAccessFlow() = _communityWriteAccess.asStateFlow()
@WorkerThread
fun add(server: String, room: String, publicKey: String, context: Context): Pair<Long,OpenGroupApi.RoomInfo?> {
val openGroupID = "$server.$room"
@ -164,9 +172,13 @@ object OpenGroupManager {
fun updateOpenGroup(openGroup: OpenGroup, context: Context) {
val threadDB = DatabaseComponent.get(context).lokiThreadDatabase()
val openGroupID = "${openGroup.server}.${openGroup.room}"
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context)
val threadID = GroupManager.getOpenGroupThreadID(openGroup.groupId, context)
threadDB.setOpenGroupChat(openGroup, threadID)
// update write access for this community
val writeAccesses = _communityWriteAccess.value.toMutableMap()
writeAccesses[openGroup.groupId] = openGroup.canWrite
_communityWriteAccess.value = writeAccesses
}
fun isUserModerator(context: Context, groupId: String, standardPublicKey: String, blindedPublicKey: String? = null): Boolean {

View File

@ -19,6 +19,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import network.loki.messenger.R
import org.thoughtcrime.securesms.ui.SessionShieldIcon
import org.thoughtcrime.securesms.ui.components.PrimaryOutlineButton
import org.thoughtcrime.securesms.ui.components.SlimPrimaryOutlineButton
import org.thoughtcrime.securesms.ui.contentDescription
import org.thoughtcrime.securesms.ui.theme.LocalColors
@ -60,8 +61,8 @@ internal fun SeedReminder(startRecoveryPasswordActivity: () -> Unit) {
style = LocalType.current.small
)
}
Spacer(Modifier.width(LocalDimensions.current.xsSpacing))
SlimPrimaryOutlineButton(
Spacer(Modifier.width(LocalDimensions.current.smallSpacing))
PrimaryOutlineButton(
text = stringResource(R.string.theContinue),
modifier = Modifier
.align(Alignment.CenterVertically)

View File

@ -108,7 +108,7 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
showSessionDialog {
title(R.string.delete)
text(resources.getString(R.string.messageRequestsDelete))
button(R.string.delete) { doDecline() }
dangerButton(R.string.delete) { doDecline() }
button(R.string.cancel)
}
}
@ -129,9 +129,10 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
}
showSessionDialog {
title(resources.getString(R.string.clearAll))
text(resources.getString(R.string.messageRequestsClearAllExplanation))
button(R.string.yes) { doDeleteAllAndBlock() }
button(R.string.no)
dangerButton(R.string.clear) { doDeleteAllAndBlock() }
button(R.string.cancel)
}
}
}

View File

@ -7,9 +7,6 @@
android:title="@string/helpReportABug"
android:summary="@string/helpReportABugExportLogsDescription"
android:widgetLayout="@layout/export_logs_widget" />
<!-- Note: Having this as `android:layout` rather than `android:layoutWidget` allows it to fit the screen width -->
<Preference android:layout="@layout/preference_widget_progress" />
</PreferenceCategory>
<PreferenceCategory>

View File

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