Remove FeatureFlag.NotificationSettings and FeatureFlag.PinUnlock

This commit is contained in:
Benoit Marty
2025-08-12 14:30:30 +02:00
committed by Benoit Marty
parent 92990b27f3
commit 0eadf275e1
12 changed files with 16 additions and 77 deletions

View File

@@ -18,8 +18,6 @@ import io.element.android.features.lockscreen.impl.storage.LockScreenStore
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.di.annotations.AppCoroutineScope
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
import io.element.android.services.appnavstate.api.AppForegroundStateService
@@ -29,7 +27,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@@ -40,7 +37,6 @@ import kotlin.time.Duration
@ContributesBinding(AppScope::class)
class DefaultLockScreenService @Inject constructor(
private val lockScreenConfig: LockScreenConfig,
private val featureFlagService: FeatureFlagService,
private val lockScreenStore: LockScreenStore,
private val pinCodeManager: PinCodeManager,
@AppCoroutineScope
@@ -108,12 +104,7 @@ class DefaultLockScreenService @Inject constructor(
}
override fun isPinSetup(): Flow<Boolean> {
return combine(
featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinUnlock),
pinCodeManager.hasPinCode()
) { isEnabled, hasPinCode ->
isEnabled && hasPinCode
}
return pinCodeManager.hasPinCode()
}
override fun isSetupRequired(): Flow<Boolean> {

View File

@@ -23,8 +23,6 @@ import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.indicator.api.IndicatorService
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
@@ -42,7 +40,6 @@ class PreferencesRootPresenter @Inject constructor(
private val analyticsService: AnalyticsService,
private val versionFormatter: VersionFormatter,
private val snackbarDispatcher: SnackbarDispatcher,
private val featureFlagService: FeatureFlagService,
private val indicatorService: IndicatorService,
private val directLogoutPresenter: Presenter<DirectLogoutState>,
private val showDeveloperSettingsProvider: ShowDeveloperSettingsProvider,
@@ -60,15 +57,6 @@ class PreferencesRootPresenter @Inject constructor(
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
val hasAnalyticsProviders = remember { analyticsService.getAvailableAnalyticsProviders().isNotEmpty() }
val showNotificationSettings = remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
showNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings)
}
val showLockScreenSettings = remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
showLockScreenSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.PinUnlock)
}
// We should display the 'complete verification' option if the current session can be verified
val canVerifyUserSession by sessionVerificationService.needsSessionVerification.collectAsState(false)
@@ -122,8 +110,6 @@ class PreferencesRootPresenter @Inject constructor(
canReportBug = canReportBug,
showDeveloperSettings = showDeveloperSettings,
canDeactivateAccount = canDeactivateAccount,
showNotificationSettings = showNotificationSettings.value,
showLockScreenSettings = showLockScreenSettings.value,
showBlockedUsersItem = showBlockedUsersItem,
directLogoutState = directLogoutState,
snackbarMessage = snackbarMessage,

View File

@@ -24,8 +24,6 @@ data class PreferencesRootState(
val showAnalyticsSettings: Boolean,
val showDeveloperSettings: Boolean,
val canDeactivateAccount: Boolean,
val showLockScreenSettings: Boolean,
val showNotificationSettings: Boolean,
val showBlockedUsersItem: Boolean,
val directLogoutState: DirectLogoutState,
val snackbarMessage: SnackbarMessage?,

View File

@@ -27,8 +27,6 @@ fun aPreferencesRootState(
showAnalyticsSettings = true,
canReportBug = true,
showDeveloperSettings = true,
showNotificationSettings = true,
showLockScreenSettings = true,
showBlockedUsersItem = true,
canDeactivateAccount = true,
snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete),

View File

@@ -121,20 +121,16 @@ private fun ColumnScope.ManageAppSection(
onOpenLockScreenSettings: () -> Unit,
onSecureBackupClick: () -> Unit,
) {
if (state.showNotificationSettings) {
ListItem(
headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Notifications())),
onClick = onOpenNotificationSettings,
)
}
if (state.showLockScreenSettings) {
ListItem(
headlineContent = { Text(stringResource(id = CommonStrings.common_screen_lock)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())),
onClick = onOpenLockScreenSettings,
)
}
ListItem(
headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Notifications())),
onClick = onOpenNotificationSettings,
)
ListItem(
headlineContent = { Text(stringResource(id = CommonStrings.common_screen_lock)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())),
onClick = onOpenLockScreenSettings,
)
if (state.showSecureBackup) {
ListItem(
headlineContent = { Text(stringResource(id = CommonStrings.common_encryption)) },
@@ -143,9 +139,7 @@ private fun ColumnScope.ManageAppSection(
onClick = onSecureBackupClick,
)
}
if (state.showNotificationSettings || state.showLockScreenSettings || state.showSecureBackup) {
HorizontalDivider()
}
HorizontalDivider()
}
@Composable

View File

@@ -16,7 +16,6 @@ import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsP
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.indicator.api.IndicatorService
import io.element.android.libraries.indicator.test.FakeIndicatorService
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
@@ -77,8 +76,6 @@ class PreferencesRootPresenterTest {
assertThat(loadedState.devicesManagementUrl).isNull()
assertThat(loadedState.showAnalyticsSettings).isFalse()
assertThat(loadedState.showDeveloperSettings).isTrue()
assertThat(loadedState.showLockScreenSettings).isTrue()
assertThat(loadedState.showNotificationSettings).isTrue()
assertThat(loadedState.canDeactivateAccount).isTrue()
assertThat(loadedState.canReportBug).isTrue()
assertThat(loadedState.directLogoutState).isEqualTo(aDirectLogoutState())
@@ -194,7 +191,6 @@ class PreferencesRootPresenterTest {
analyticsService = FakeAnalyticsService(),
versionFormatter = FakeVersionFormatter(),
snackbarDispatcher = SnackbarDispatcher(),
featureFlagService = FakeFeatureFlagService(),
indicatorService = indicatorService,
directLogoutPresenter = { aDirectLogoutState() },
showDeveloperSettingsProvider = showDeveloperSettingsProvider,

View File

@@ -12,7 +12,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@@ -77,7 +76,6 @@ class RoomDetailsPresenter @Inject constructor(
override fun present(): RoomDetailsState {
val scope = rememberCoroutineScope()
val leaveRoomState = leaveRoomPresenter.present()
val canShowNotificationSettings = remember { mutableStateOf(false) }
val roomInfo by room.roomInfoFlow.collectAsState()
val isUserAdmin = room.isOwnUserAdmin()
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
@@ -96,11 +94,8 @@ class RoomDetailsPresenter @Inject constructor(
}.collectAsState(false)
LaunchedEffect(Unit) {
canShowNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings)
if (canShowNotificationSettings.value) {
room.updateRoomNotificationSettings()
observeNotificationSettings()
}
room.updateRoomNotificationSettings()
observeNotificationSettings()
}
val membersState by room.membersStateFlow.collectAsState()
@@ -197,7 +192,6 @@ class RoomDetailsPresenter @Inject constructor(
isEncrypted = isEncrypted,
canInvite = canInvite,
canEdit = (canEditAvatar || canEditName || canEditTopic) && roomType == RoomDetailsType.Room,
canShowNotificationSettings = canShowNotificationSettings.value,
roomCallState = roomCallState,
roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState,

View File

@@ -32,7 +32,6 @@ data class RoomDetailsState(
val roomMemberDetailsState: UserProfileState?,
val canEdit: Boolean,
val canInvite: Boolean,
val canShowNotificationSettings: Boolean,
val roomCallState: RoomCallState,
val leaveRoomState: LeaveRoomState,
val roomNotificationSettings: RoomNotificationSettings?,

View File

@@ -100,7 +100,6 @@ fun aRoomDetailsState(
isEncrypted: Boolean = true,
canInvite: Boolean = false,
canEdit: Boolean = false,
canShowNotificationSettings: Boolean = true,
roomCallState: RoomCallState = aStandByCallState(),
roomType: RoomDetailsType = RoomDetailsType.Room,
roomMemberDetailsState: UserProfileState? = null,
@@ -132,7 +131,6 @@ fun aRoomDetailsState(
isEncrypted = isEncrypted,
canInvite = canInvite,
canEdit = canEdit,
canShowNotificationSettings = canShowNotificationSettings,
roomCallState = roomCallState,
roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState,

View File

@@ -185,7 +185,7 @@ fun RoomDetailsView(
}
PreferenceCategory {
if (state.canShowNotificationSettings && state.roomNotificationSettings != null) {
if (state.roomNotificationSettings != null) {
NotificationItem(
isDefaultMode = state.roomNotificationSettings.isDefault,
openRoomNotificationSettings = openRoomNotificationSettings
@@ -337,8 +337,7 @@ private fun MainActionsSection(
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
) {
val roomNotificationSettings = state.roomNotificationSettings
if (state.canShowNotificationSettings && roomNotificationSettings != null) {
state.roomNotificationSettings?.let { roomNotificationSettings ->
if (roomNotificationSettings.mode == RoomNotificationMode.MUTE) {
MainActionButton(
title = stringResource(CommonStrings.common_unmute),

View File

@@ -79,7 +79,6 @@ class RoomDetailsPresenterTest {
analyticsService: AnalyticsService = FakeAnalyticsService(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(
mapOf(
FeatureFlags.NotificationSettings.key to true,
FeatureFlags.Knock.key to false,
)
),

View File

@@ -21,12 +21,6 @@ enum class FeatureFlags(
override val defaultValue: (BuildMeta) -> Boolean,
override val isFinished: Boolean,
) : Feature {
NotificationSettings(
key = "feature.notificationsettings",
title = "Show notification settings",
defaultValue = { true },
isFinished = true,
),
VoiceMessages(
key = "feature.voicemessages",
title = "Voice messages",
@@ -34,13 +28,6 @@ enum class FeatureFlags(
defaultValue = { true },
isFinished = true,
),
PinUnlock(
key = "feature.pinunlock",
title = "Pin unlock",
description = "Allow user to lock/unlock the app with a pin code or biometrics",
defaultValue = { true },
isFinished = true,
),
MarkAsUnread(
key = "feature.markAsUnread",
title = "Mark as unread",