Skip to content

Commit 22a17c0

Browse files
authored
feat: adminless feature flag (WPB-25275) (#4862)
1 parent 3f06238 commit 22a17c0

7 files changed

Lines changed: 87 additions & 14 deletions

File tree

app/src/main/kotlin/com/wire/android/di/accountScoped/UserModule.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import com.wire.kalium.logic.feature.user.GetSelfTeamIdUseCase
4242
import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
4343
import com.wire.kalium.logic.feature.user.GetUserInfoUseCase
4444
import com.wire.kalium.logic.feature.user.IsPasswordRequiredUseCase
45+
import com.wire.kalium.logic.feature.user.IsPreventAdminlessGroupsEnabledUseCase
4546
import com.wire.kalium.logic.feature.user.IsReadOnlyAccountUseCase
4647
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
4748
import com.wire.kalium.logic.feature.user.ObserveSelfUserWithTeamUseCase
@@ -161,6 +162,14 @@ class UserModule {
161162
userScope: UserScope
162163
): IsPasswordRequiredUseCase = userScope.isPasswordRequired
163164

165+
@ViewModelScoped
166+
@Provides
167+
fun provideIsPreventAdminlessGroupsEnabledUseCase(
168+
@KaliumCoreLogic coreLogic: CoreLogic,
169+
@CurrentAccount currentAccount: UserId,
170+
): IsPreventAdminlessGroupsEnabledUseCase =
171+
coreLogic.getSessionScope(currentAccount).isPreventAdminlessGroupsEnabled
172+
164173
@ViewModelScoped
165174
@Provides
166175
fun provideIsReadOnlyAccountUseCase(

app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationOptionsMenuViewModel.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.runtime.getValue
2121
import androidx.compose.runtime.mutableStateOf
2222
import androidx.lifecycle.viewModelScope
2323
import androidx.work.WorkManager
24-
import com.wire.android.BuildConfig
2524
import com.wire.android.appLogger
2625
import com.wire.android.di.CurrentAccount
2726
import com.wire.android.di.ViewModelScopedPreview
@@ -62,6 +61,7 @@ import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromF
6261
import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFolderUseCase
6362
import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase
6463
import com.wire.kalium.logic.feature.team.Result
64+
import com.wire.kalium.logic.feature.user.IsPreventAdminlessGroupsEnabledUseCase
6565
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
6666
import com.wire.kalium.util.DateTimeUtil
6767
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -124,6 +124,7 @@ class ConversationOptionsMenuViewModelImpl @Inject constructor(
124124
private val markConversationAsDeletedLocally: MarkConversationAsDeletedLocallyUseCase,
125125
private val leaveConversation: LeaveConversationUseCase,
126126
private val checkConversationLeaveConditions: CheckConversationLeaveConditionsUseCase,
127+
private val isPreventAdminlessGroupsEnabled: IsPreventAdminlessGroupsEnabledUseCase,
127128
private val blockUser: BlockUserUseCase,
128129
private val unblockUser: UnblockUserUseCase,
129130
private val clearConversationContent: ClearConversationContentUseCase,
@@ -253,8 +254,8 @@ class ConversationOptionsMenuViewModelImpl @Inject constructor(
253254
}
254255

255256
override fun onLeaveGroup(leaveGroupState: LeaveGroupDialogState) {
256-
if (BuildConfig.ADMINLESS_GROUP_HANDLING_ENABLED) {
257-
viewModelScope.launch {
257+
viewModelScope.launch {
258+
if (isPreventAdminlessGroupsEnabled()) {
258259
when (val result = checkConversationLeaveConditions(leaveGroupState.conversationId)) {
259260
CheckConversationLeaveConditionsUseCase.Result.Allow -> leaveGroupDialogState.show(leaveGroupState)
260261
is CheckConversationLeaveConditionsUseCase.Result.DoNotAllow -> {
@@ -271,9 +272,9 @@ class ConversationOptionsMenuViewModelImpl @Inject constructor(
271272
onMessage(HomeSnackBarMessage.LeaveConversationError)
272273
}
273274
}
275+
} else {
276+
leaveGroupDialogState.show(leaveGroupState)
274277
}
275-
} else {
276-
leaveGroupDialogState.show(leaveGroupState)
277278
}
278279
}
279280

app/src/main/kotlin/com/wire/android/ui/debug/featureflags/DebugFeatureFlagsViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class DebugFeatureFlagsViewModel @Inject constructor(
6969
addFeature("Allowed Global Operations", allowedGlobalOperationsModel?.status, allowedGlobalOperationsModel)
7070
addFeature("Wire Cells", cellsModel?.status)
7171
addFeature("User Profile QR code", enableUserProfileQRCodeConfigModel?.status)
72+
addFeature("Prevent Adminless Groups", preventAdminlessGroupsModel?.status)
7273
add(
7374
Feature(
7475
name = "Channels",

app/src/test/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationOptionsMenuViewModelTest.kt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.wire.android.assertIs
2323
import com.wire.android.config.CoroutineTestExtension
2424
import com.wire.android.config.TestDispatcherProvider
2525
import com.wire.android.ui.home.HomeSnackBarMessage
26+
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
2627
import com.wire.android.workmanager.worker.ConversationDeletionLocallyStatus
2728
import com.wire.android.workmanager.worker.enqueueConversationDeletionLocally
2829
import com.wire.kalium.common.error.CoreFailure
@@ -51,6 +52,7 @@ import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromF
5152
import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFolderUseCase
5253
import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase
5354
import com.wire.kalium.logic.feature.team.Result
55+
import com.wire.kalium.logic.feature.user.IsPreventAdminlessGroupsEnabledUseCase
5456
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
5557
import io.mockk.MockKAnnotations
5658
import io.mockk.coEvery
@@ -589,6 +591,57 @@ class ConversationOptionsMenuViewModelTest {
589591
}
590592
}
591593

594+
@Test
595+
fun `given preventAdminlessGroups disabled, when onLeaveGroup, then show simple leave dialog`() =
596+
runTest(dispatcherProvider.main()) {
597+
val (arrangement, viewModel) = Arrangement()
598+
.withPreventAdminlessGroupsEnabled(false)
599+
.arrange()
600+
601+
viewModel.onLeaveGroup(LeaveGroupDialogState(conversationId, "name"))
602+
603+
coVerify(exactly = 0) { arrangement.checkConversationLeaveConditions(any()) }
604+
assertEquals(true, viewModel.leaveGroupDialogState.isVisible)
605+
assertEquals(false, viewModel.leaveGroupOptionsDialogState.isVisible)
606+
}
607+
608+
@Test
609+
fun `given preventAdminlessGroups enabled and conditions allow, when onLeaveGroup, then show simple leave dialog`() =
610+
runTest(dispatcherProvider.main()) {
611+
val (arrangement, viewModel) = Arrangement()
612+
.withPreventAdminlessGroupsEnabled(true)
613+
.withCheckConversationLeaveConditions(CheckConversationLeaveConditionsUseCase.Result.Allow)
614+
.arrange()
615+
616+
viewModel.onLeaveGroup(LeaveGroupDialogState(conversationId, "name"))
617+
618+
coVerify(exactly = 1) { arrangement.checkConversationLeaveConditions(conversationId) }
619+
assertEquals(true, viewModel.leaveGroupDialogState.isVisible)
620+
assertEquals(false, viewModel.leaveGroupOptionsDialogState.isVisible)
621+
}
622+
623+
@Test
624+
fun `given preventAdminlessGroups enabled and conditions error, when onLeaveGroup, then show snackbar error`() =
625+
runTest(dispatcherProvider.main()) {
626+
val (arrangement, viewModel) = Arrangement()
627+
.withPreventAdminlessGroupsEnabled(true)
628+
.withCheckConversationLeaveConditions(
629+
CheckConversationLeaveConditionsUseCase.Result.Error(CoreFailure.Unknown(null))
630+
)
631+
.arrange()
632+
633+
viewModel.actions.test {
634+
viewModel.onLeaveGroup(LeaveGroupDialogState(conversationId, "name"))
635+
636+
coVerify(exactly = 1) { arrangement.checkConversationLeaveConditions(conversationId) }
637+
assertIs<ConversationOptionsMenuViewAction.Message>(awaitItem()).also {
638+
assertIs<HomeSnackBarMessage.LeaveConversationError>(it.message)
639+
}
640+
assertEquals(false, viewModel.leaveGroupDialogState.isVisible)
641+
cancelAndIgnoreRemainingEvents()
642+
}
643+
}
644+
592645
inner class Arrangement {
593646
@MockK
594647
lateinit var observeConversationDetails: ObserveConversationDetailsUseCase
@@ -623,6 +676,9 @@ class ConversationOptionsMenuViewModelTest {
623676
@MockK
624677
lateinit var checkConversationLeaveConditions: CheckConversationLeaveConditionsUseCase
625678

679+
@MockK
680+
lateinit var isPreventAdminlessGroupsEnabled: IsPreventAdminlessGroupsEnabledUseCase
681+
626682
@MockK
627683
lateinit var blockUser: BlockUserUseCase
628684

@@ -638,6 +694,7 @@ class ConversationOptionsMenuViewModelTest {
638694
init {
639695
MockKAnnotations.init(this, relaxUnitFun = true)
640696
mockkStatic("com.wire.android.workmanager.worker.DeleteConversationLocallyWorkerKt")
697+
coEvery { isPreventAdminlessGroupsEnabled() } returns true
641698
}
642699

643700
fun arrange() = this to ConversationOptionsMenuViewModelImpl(
@@ -653,6 +710,7 @@ class ConversationOptionsMenuViewModelTest {
653710
markConversationAsDeletedLocally = markConversationAsDeletedLocally,
654711
leaveConversation = leaveConversation,
655712
checkConversationLeaveConditions = checkConversationLeaveConditions,
713+
isPreventAdminlessGroupsEnabled = isPreventAdminlessGroupsEnabled,
656714
blockUser = blockUser,
657715
unblockUser = unblockUser,
658716
clearConversationContent = clearConversationContent,
@@ -708,6 +766,14 @@ class ConversationOptionsMenuViewModelTest {
708766
fun withClearConversationContent(result: ClearConversationContentUseCase.Result) = apply {
709767
coEvery { clearConversationContent(any(), any()) } returns result
710768
}
769+
770+
fun withPreventAdminlessGroupsEnabled(enabled: Boolean) = apply {
771+
coEvery { isPreventAdminlessGroupsEnabled() } returns enabled
772+
}
773+
774+
fun withCheckConversationLeaveConditions(result: CheckConversationLeaveConditionsUseCase.Result) = apply {
775+
coEvery { checkConversationLeaveConditions(any()) } returns result
776+
}
711777
}
712778

713779
companion object {

buildSrc/src/main/kotlin/customization/FeatureConfigs.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,5 @@ enum class FeatureConfigs(val value: String, val configType: ConfigType) {
155155

156156
CALL_QUALITY_MENU_ENABLED("call_quality_menu_enabled", ConfigType.BOOLEAN),
157157

158-
CALL_REACTIONS_ENABLED("call_reactions_enabled", ConfigType.BOOLEAN),
159-
160-
ADMINLESS_GROUP_HANDLING_ENABLED("adminless_group_handling_enabled", ConfigType.BOOLEAN)
158+
CALL_REACTIONS_ENABLED("call_reactions_enabled", ConfigType.BOOLEAN)
161159
}

default.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
"analytics_app_key": "8ffae535f1836ed5f58fd5c8a11c00eca07c5438",
7474
"analytics_server_url": "https://wire.count.ly/",
7575
"enable_new_registration": true,
76-
"enforce_configuration_signature": true,
76+
"enforce_configuration_signature": true
7777
},
7878
"internal": {
7979
"application_id": "com.wire.internal",
@@ -88,8 +88,7 @@
8888
"enforce_configuration_signature": true,
8989
"use_strict_mls_filter": false,
9090
"conversation_feeder_enabled": true,
91-
"db_invalidation_control_enabled": false,
92-
"adminless_group_handling_enabled": true
91+
"db_invalidation_control_enabled": false
9392
},
9493
"fdroid": {
9594
"application_id": "com.wire",
@@ -175,6 +174,5 @@
175174
"enforce_configuration_signature": true,
176175
"call_quality_menu_enabled": true,
177176
"call_reactions_enabled": true,
178-
"nomad_profiles_enabled": true,
179-
"adminless_group_handling_enabled": false
177+
"nomad_profiles_enabled": true
180178
}

kalium

Submodule kalium updated 19 files

0 commit comments

Comments
 (0)