diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ef6bda9ebc..34a8fe31f5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -147,14 +147,6 @@ - - - - @@ -171,7 +163,7 @@ - + , private val appErrorStateService: AppErrorStateService, private val analyticsService: AnalyticsService, - private val shareService: ShareService, private val sdkMetadata: SdkMetadata, ) : Presenter { @Composable @@ -45,10 +43,6 @@ class RootPresenter @Inject constructor( ) } - LaunchedEffect(Unit) { - shareService.observeFeatureFlag(this) - } - return RootState( rageshakeDetectionState = rageshakeDetectionState, crashDetectionState = crashDetectionState, diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt index 6d0878d812..4c8b2a803d 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt @@ -14,16 +14,12 @@ import com.google.common.truth.Truth.assertThat import io.element.android.appnav.root.RootPresenter import io.element.android.features.rageshake.api.crash.aCrashDetectionState import io.element.android.features.rageshake.api.detection.aRageshakeDetectionState -import io.element.android.features.share.api.ShareService -import io.element.android.features.share.test.FakeShareService import io.element.android.libraries.matrix.test.FakeSdkMetadata import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.apperror.api.AppErrorState import io.element.android.services.apperror.api.AppErrorStateService import io.element.android.services.apperror.impl.DefaultAppErrorStateService import io.element.android.tests.testutils.WarmUpRule -import io.element.android.tests.testutils.lambda.lambdaRecorder -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -43,22 +39,6 @@ class RootPresenterTest { } } - @Test - fun `present - check that share service is invoked`() = runTest { - val lambda = lambdaRecorder { _ -> } - val presenter = createRootPresenter( - shareService = FakeShareService { - lambda(it) - } - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - skipItems(1) - lambda.assertions().isCalledOnce() - } - } - @Test fun `present - passes app error state`() = runTest { val presenter = createRootPresenter( @@ -82,14 +62,12 @@ class RootPresenterTest { private fun createRootPresenter( appErrorService: AppErrorStateService = DefaultAppErrorStateService(), - shareService: ShareService = FakeShareService {}, ): RootPresenter { return RootPresenter( crashDetectionPresenter = { aCrashDetectionState() }, rageshakeDetectionPresenter = { aRageshakeDetectionState() }, appErrorStateService = appErrorService, analyticsService = FakeAnalyticsService(), - shareService = shareService, sdkMetadata = FakeSdkMetadata("sha") ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt index f729667e53..6ef73770f6 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt @@ -101,36 +101,34 @@ private fun RoomListModalBottomSheetContent( ) } ) - if (contextMenu.markAsUnreadFeatureFlagEnabled) { - if (contextMenu.hasNewContent) { - ListItem( - headlineContent = { - Text( - text = stringResource(id = R.string.screen_roomlist_mark_as_read), - style = MaterialTheme.typography.bodyLarge, - ) - }, - onClick = onRoomMarkReadClick, - leadingContent = ListItemContent.Icon( - iconSource = IconSource.Vector(CompoundIcons.MarkAsRead()) - ), - style = ListItemStyle.Primary, - ) - } else { - ListItem( - headlineContent = { - Text( - text = stringResource(id = R.string.screen_roomlist_mark_as_unread), - style = MaterialTheme.typography.bodyLarge, - ) - }, - onClick = onRoomMarkUnreadClick, - leadingContent = ListItemContent.Icon( - iconSource = IconSource.Vector(CompoundIcons.MarkAsUnread()) - ), - style = ListItemStyle.Primary, - ) - } + if (contextMenu.hasNewContent) { + ListItem( + headlineContent = { + Text( + text = stringResource(id = R.string.screen_roomlist_mark_as_read), + style = MaterialTheme.typography.bodyLarge, + ) + }, + onClick = onRoomMarkReadClick, + leadingContent = ListItemContent.Icon( + iconSource = IconSource.Vector(CompoundIcons.MarkAsRead()) + ), + style = ListItemStyle.Primary, + ) + } else { + ListItem( + headlineContent = { + Text( + text = stringResource(id = R.string.screen_roomlist_mark_as_unread), + style = MaterialTheme.typography.bodyLarge, + ) + }, + onClick = onRoomMarkUnreadClick, + leadingContent = ListItemContent.Icon( + iconSource = IconSource.Vector(CompoundIcons.MarkAsUnread()) + ), + style = ListItemStyle.Primary, + ) } ListItem( headlineContent = { diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt index 1cab846021..ba5007c57c 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt @@ -36,8 +36,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -74,7 +72,6 @@ class RoomListPresenter @Inject constructor( private val client: MatrixClient, private val leaveRoomPresenter: Presenter, private val roomListDataSource: RoomListDataSource, - private val featureFlagService: FeatureFlagService, private val filtersPresenter: Presenter, private val searchPresenter: Presenter, private val sessionPreferencesStore: SessionPreferencesStore, @@ -244,7 +241,6 @@ class RoomListPresenter @Inject constructor( roomName = event.roomSummary.name, isDm = event.roomSummary.isDm, isFavorite = event.roomSummary.isFavorite, - markAsUnreadFeatureFlagEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.MarkAsUnread), hasNewContent = event.roomSummary.hasNewContent, displayClearRoomCacheAction = appPreferencesStore.isDeveloperModeEnabledFlow().first(), ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt index 4cfa82fbfc..4a301f0897 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt @@ -41,7 +41,6 @@ data class RoomListState( val roomName: String?, val isDm: Boolean, val isFavorite: Boolean, - val markAsUnreadFeatureFlagEnabled: Boolean, val hasNewContent: Boolean, val displayClearRoomCacheAction: Boolean, ) : ContextMenu diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateContextMenuShownProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateContextMenuShownProvider.kt index 0cd3117de4..856b7662af 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateContextMenuShownProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateContextMenuShownProvider.kt @@ -28,7 +28,6 @@ internal fun aContextMenuShown( roomId = RoomId("!aRoom:aDomain"), roomName = roomName, isDm = isDm, - markAsUnreadFeatureFlagEnabled = true, hasNewContent = hasNewContent, isFavorite = isFavorite, displayClearRoomCacheAction = false, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt index 11db1b80a5..044c150ad2 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt @@ -32,8 +32,6 @@ import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -217,7 +215,6 @@ class RoomListPresenterTest { roomName = summary.name, isDm = false, isFavorite = false, - markAsUnreadFeatureFlagEnabled = true, hasNewContent = false, displayClearRoomCacheAction = false, ) @@ -235,7 +232,6 @@ class RoomListPresenterTest { roomName = summary.name, isDm = false, isFavorite = true, - markAsUnreadFeatureFlagEnabled = true, hasNewContent = false, displayClearRoomCacheAction = false, ) @@ -263,7 +259,6 @@ class RoomListPresenterTest { roomName = summary.name, isDm = false, isFavorite = false, - markAsUnreadFeatureFlagEnabled = true, // true here. hasNewContent = false, displayClearRoomCacheAction = true, @@ -295,7 +290,6 @@ class RoomListPresenterTest { roomName = summary.name, isDm = false, isFavorite = false, - markAsUnreadFeatureFlagEnabled = true, hasNewContent = false, displayClearRoomCacheAction = false, ) @@ -604,7 +598,6 @@ class RoomListPresenterTest { dateFormatter: DateFormatter = FakeDateFormatter(), roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(), sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), analyticsService: AnalyticsService = FakeAnalyticsService(), filtersPresenter: Presenter = Presenter { aRoomListFiltersState() }, searchPresenter: Presenter = Presenter { aRoomListSearchState() }, @@ -626,7 +619,6 @@ class RoomListPresenterTest { sessionCoroutineScope = backgroundScope, dateTimeObserver = FakeDateTimeObserver(), ), - featureFlagService = featureFlagService, searchPresenter = searchPresenter, sessionPreferencesStore = sessionPreferencesStore, filtersPresenter = filtersPresenter, diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt index 5b584a39f8..3d8ab97504 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/actions/AndroidLocationActionsTest.kt @@ -67,6 +67,7 @@ internal class AndroidLocationActionsTest { accuracy = 0f ) // Set a locale with comma as decimal separator + @Suppress("DEPRECATION") Locale.setDefault(Locale.Category.FORMAT, Locale("pt", "BR")) val actual = buildUrl(location, "(weird/stuff here)", ::urlEncoder) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt index 85ec2e3130..8be72a113e 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt @@ -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 { - return combine( - featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinUnlock), - pinCodeManager.hasPinCode() - ) { isEnabled, hasPinCode -> - isEnabled && hasPinCode - } + return pinCodeManager.hasPinCode() } override fun isSetupRequired(): Flow { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt index ba60cfd222..0e545f44e6 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt @@ -27,14 +27,11 @@ import io.element.android.features.login.impl.login.LoginHelper import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.ui.utils.MultipleTapToUnlock class OnBoardingPresenter @AssistedInject constructor( @Assisted private val params: OnBoardingNode.Params, private val buildMeta: BuildMeta, - private val featureFlagService: FeatureFlagService, private val enterpriseService: EnterpriseService, private val defaultAccountProviderAccessControl: DefaultAccountProviderAccessControl, private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, @@ -80,8 +77,7 @@ class OnBoardingPresenter @AssistedInject constructor( forcedAccountProvider ?: linkAccountProvider } val canLoginWithQrCode by produceState(initialValue = false, linkAccountProvider) { - value = linkAccountProvider == null && - featureFlagService.isFeatureEnabled(FeatureFlags.QrCodeLogin) + value = linkAccountProvider == null } val canReportBug by remember { rageshakeFeatureAvailability.isAvailable() }.collectAsState(false) var showReportBug by rememberSaveable { mutableStateOf(false) } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt index c559db9056..b47adf4cd8 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt @@ -19,9 +19,6 @@ import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationR import io.element.android.features.wellknown.test.FakeWellknownRetriever import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2 @@ -70,13 +67,8 @@ class OnBoardingPresenterTest { productionApplicationName = "B", desktopApplicationName = "C", ) - val featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.QrCodeLogin.key to true), - buildMeta = buildMeta, - ) val presenter = createPresenter( buildMeta = buildMeta, - featureFlagService = featureFlagService, enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG, EnterpriseService.ANY_ACCOUNT_PROVIDER) }, ), @@ -131,9 +123,6 @@ class OnBoardingPresenterTest { accountProvider = ACCOUNT_PROVIDER_FROM_LINK, loginHint = null, ), - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.QrCodeLogin.key to true), - ), enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG, EnterpriseService.ANY_ACCOUNT_PROVIDER) }, isAllowedToConnectToHomeserverResult = { true }, @@ -156,9 +145,6 @@ class OnBoardingPresenterTest { accountProvider = ACCOUNT_PROVIDER_FROM_LINK, loginHint = null, ), - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.QrCodeLogin.key to true), - ), enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG, ACCOUNT_PROVIDER_FROM_CONFIG_2) }, isAllowedToConnectToHomeserverResult = { false }, @@ -181,9 +167,6 @@ class OnBoardingPresenterTest { accountProvider = ACCOUNT_PROVIDER_FROM_LINK, loginHint = null, ), - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.QrCodeLogin.key to true), - ), enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG) }, ) @@ -237,7 +220,6 @@ class OnBoardingPresenterTest { private fun createPresenter( params: OnBoardingNode.Params = OnBoardingNode.Params(null, null), buildMeta: BuildMeta = aBuildMeta(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), enterpriseService: EnterpriseService = FakeEnterpriseService(), wellknownRetriever: WellknownRetriever = FakeWellknownRetriever(), rageshakeFeatureAvailability: () -> Flow = { flowOf(true) }, @@ -245,7 +227,6 @@ private fun createPresenter( ) = OnBoardingPresenter( params = params, buildMeta = buildMeta, - featureFlagService = featureFlagService, enterpriseService = enterpriseService, defaultAccountProviderAccessControl = DefaultAccountProviderAccessControl( enterpriseService = enterpriseService, diff --git a/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/pinned/IsPinnedMessagesFeatureEnabled.kt b/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/pinned/IsPinnedMessagesFeatureEnabled.kt deleted file mode 100644 index c430eedf4f..0000000000 --- a/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/pinned/IsPinnedMessagesFeatureEnabled.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.messages.api.pinned - -import androidx.compose.runtime.Composable - -fun interface IsPinnedMessagesFeatureEnabled { - @Composable - operator fun invoke(): Boolean -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 3390b55d5e..434f6643d4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -63,8 +63,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage 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.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.permalink.PermalinkParser @@ -111,7 +109,6 @@ class MessagesPresenter @AssistedInject constructor( private val snackbarDispatcher: SnackbarDispatcher, private val dispatchers: CoroutineDispatchers, private val clipboardHelper: ClipboardHelper, - private val featureFlagsService: FeatureFlagService, private val htmlConverterProvider: HtmlConverterProvider, private val buildMeta: BuildMeta, private val timelineController: TimelineController, @@ -187,11 +184,6 @@ class MessagesPresenter @AssistedInject constructor( val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() - var enableVoiceMessages by remember { mutableStateOf(false) } - LaunchedEffect(featureFlagsService) { - enableVoiceMessages = featureFlagsService.isFeatureEnabled(FeatureFlags.VoiceMessages) - } - var dmUserVerificationState by remember { mutableStateOf(null) } val membersState by room.membersStateFlow.collectAsState() @@ -261,7 +253,6 @@ class MessagesPresenter @AssistedInject constructor( showReinvitePrompt = showReinvitePrompt, inviteProgress = inviteProgress.value, enableTextFormatting = MessageComposerConfig.ENABLE_RICH_TEXT_EDITING, - enableVoiceMessages = enableVoiceMessages, appName = buildMeta.applicationName, roomCallState = roomCallState, pinnedMessagesBannerState = pinnedMessagesBannerState, @@ -449,7 +440,6 @@ class MessagesPresenter @AssistedInject constructor( val composerMode = MessageComposerMode.EditCaption( eventOrTransactionId = targetEvent.eventOrTransactionId, content = "", - showCaptionCompatibilityWarning = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaCaptionWarning), ) composerState.eventSink( MessageComposerEvents.SetMode(composerMode) @@ -463,7 +453,6 @@ class MessagesPresenter @AssistedInject constructor( val composerMode = MessageComposerMode.EditCaption( eventOrTransactionId = targetEvent.eventOrTransactionId, content = (targetEvent.content as? TimelineItemEventContentWithAttachment)?.caption.orEmpty(), - showCaptionCompatibilityWarning = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaCaptionWarning), ) composerState.eventSink( MessageComposerEvents.SetMode(composerMode) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index bedce147dc..ddeff51b7e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -51,7 +51,6 @@ data class MessagesState( val inviteProgress: AsyncData, val showReinvitePrompt: Boolean, val enableTextFormatting: Boolean, - val enableVoiceMessages: Boolean, val roomCallState: RoomCallState, val appName: String, val pinnedMessagesBannerState: PinnedMessagesBannerState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 8fa539dd94..b45bb781c5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -61,14 +61,12 @@ open class MessagesStateProvider : PreviewParameterProvider { aMessagesState(roomName = null), aMessagesState(composerState = aMessageComposerState(showTextFormatting = true)), aMessagesState( - enableVoiceMessages = true, voiceMessageComposerState = aVoiceMessageComposerState(showPermissionRationaleDialog = true), ), aMessagesState( roomCallState = anOngoingCallState(), ), aMessagesState( - enableVoiceMessages = true, voiceMessageComposerState = aVoiceMessageComposerState( voiceMessageState = aVoiceMessagePreviewState(), showSendFailureDialog = true @@ -113,7 +111,6 @@ fun aMessagesState( reactionSummaryState: ReactionSummaryState = aReactionSummaryState(), hasNetworkConnection: Boolean = true, showReinvitePrompt: Boolean = false, - enableVoiceMessages: Boolean = true, roomCallState: RoomCallState = aStandByCallState(), pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(), dmUserVerificationState: IdentityState? = null, @@ -141,7 +138,6 @@ fun aMessagesState( inviteProgress = AsyncData.Uninitialized, showReinvitePrompt = showReinvitePrompt, enableTextFormatting = true, - enableVoiceMessages = enableVoiceMessages, roomCallState = roomCallState, appName = "Element", pinnedMessagesBannerState = pinnedMessagesBannerState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index fb588b5908..74f2fb18a5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -377,7 +377,7 @@ private fun MessagesViewContent( enableTextFormatting = state.enableTextFormatting, ) - if (state.enableVoiceMessages && state.voiceMessageComposerState.showPermissionRationaleDialog) { + if (state.voiceMessageComposerState.showPermissionRationaleDialog) { VoiceMessagePermissionRationaleDialog( onContinue = { state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.AcceptPermissionRationale) @@ -388,7 +388,7 @@ private fun MessagesViewContent( appName = state.appName ) } - if (state.enableVoiceMessages && state.voiceMessageComposerState.showSendFailureDialog) { + if (state.voiceMessageComposerState.showSendFailureDialog) { VoiceMessageSendingFailedDialog( onDismiss = { state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.DismissSendFailureDialog) }, ) @@ -464,7 +464,6 @@ private fun MessagesViewComposerBottomSheetContents( MessageComposerView( state = state.composerState, voiceMessageState = state.voiceMessageComposerState, - enableVoiceMessages = state.enableVoiceMessages, modifier = Modifier.fillMaxWidth(), ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 9c2760bf6c..375e2bdefe 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -18,7 +18,6 @@ import com.squareup.anvil.annotations.ContributesBinding import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionComparator @@ -40,8 +39,6 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.api.DateFormatterMode import io.element.android.libraries.di.RoomScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.preferences.api.store.AppPreferencesStore @@ -62,10 +59,8 @@ class DefaultActionListPresenter @AssistedInject constructor( @Assisted private val postProcessor: TimelineItemActionPostProcessor, private val appPreferencesStore: AppPreferencesStore, - private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled, private val room: BaseRoom, private val userSendFailureFactory: VerifiedUserSendFailureFactory, - private val featureFlagService: FeatureFlagService, private val dateFormatter: DateFormatter, ) : ActionListPresenter { @AssistedFactory @@ -87,7 +82,6 @@ class DefaultActionListPresenter @AssistedInject constructor( val isDeveloperModeEnabled by remember { appPreferencesStore.isDeveloperModeEnabledFlow() }.collectAsState(initial = false) - val isPinnedEventsEnabled = isPinnedMessagesFeatureEnabled() val pinnedEventIds by remember { room.roomInfoFlow.map { it.pinnedEventIds } }.collectAsState(initial = persistentListOf()) @@ -99,7 +93,6 @@ class DefaultActionListPresenter @AssistedInject constructor( timelineItem = event.event, usersEventPermissions = event.userEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, - isPinnedEventsEnabled = isPinnedEventsEnabled, pinnedEventIds = pinnedEventIds, target = target, ) @@ -116,7 +109,6 @@ class DefaultActionListPresenter @AssistedInject constructor( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, - isPinnedEventsEnabled: Boolean, pinnedEventIds: ImmutableList, target: MutableState ) = launch { @@ -126,7 +118,6 @@ class DefaultActionListPresenter @AssistedInject constructor( timelineItem = timelineItem, usersEventPermissions = usersEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, - isPinnedEventsEnabled = isPinnedEventsEnabled, isEventPinned = pinnedEventIds.contains(timelineItem.eventId), ) @@ -154,7 +145,6 @@ class DefaultActionListPresenter @AssistedInject constructor( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, - isPinnedEventsEnabled: Boolean, isEventPinned: Boolean, ): List { val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther @@ -173,9 +163,7 @@ class DefaultActionListPresenter @AssistedInject constructor( if (timelineItem.content is TimelineItemEventContentWithAttachment) { // Caption if (timelineItem.content.caption == null) { - if (featureFlagService.isFeatureEnabled(FeatureFlags.MediaCaptionCreation)) { - add(TimelineItemAction.AddCaption) - } + add(TimelineItemAction.AddCaption) } else { add(TimelineItemAction.EditCaption) add(TimelineItemAction.RemoveCaption) @@ -189,7 +177,7 @@ class DefaultActionListPresenter @AssistedInject constructor( if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) { add(TimelineItemAction.EndPoll) } - val canPinUnpin = isPinnedEventsEnabled && usersEventPermissions.canPinUnpin && timelineItem.isRemote + val canPinUnpin = usersEventPermissions.canPinUnpin && timelineItem.isRemote if (canPinUnpin) { if (isEventPinned) { add(TimelineItemAction.Unpin) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index 6af3033345..45c5c33e11 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -10,7 +10,6 @@ package io.element.android.features.messages.impl.attachments.preview import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -32,8 +31,6 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo import io.element.android.libraries.di.annotations.SessionCoroutineScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder @@ -58,7 +55,6 @@ class AttachmentsPreviewPresenter @AssistedInject constructor( private val mediaSender: MediaSender, private val permalinkBuilder: PermalinkBuilder, private val temporaryUriDeleter: TemporaryUriDeleter, - private val featureFlagService: FeatureFlagService, private val mediaOptimizationSelectorPresenterFactory: MediaOptimizationSelectorPresenter.Factory, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val dispatchers: CoroutineDispatchers, @@ -86,14 +82,6 @@ class AttachmentsPreviewPresenter @AssistedInject constructor( val ongoingSendAttachmentJob = remember { mutableStateOf(null) } - val allowCaption by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionCreation) - }.collectAsState(initial = false) - val showCaptionCompatibilityWarning by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionWarning) - }.collectAsState(initial = false) - - var useSendQueue by remember { mutableStateOf(false) } var preprocessMediaJob by remember { mutableStateOf(null) } val mediaAttachment = attachment as Attachment.Media @@ -106,10 +94,6 @@ class AttachmentsPreviewPresenter @AssistedInject constructor( var displayFileTooLargeError by remember { mutableStateOf(false) } - LaunchedEffect(Unit) { - useSendQueue = featureFlagService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue) - } - LaunchedEffect(mediaOptimizationSelectorState.displayMediaSelectorViews) { // If the media optimization selector is not displayed, we can pre-process the media // to prepare it for sending. This is done to avoid blocking the UI thread when the @@ -182,18 +166,17 @@ class AttachmentsPreviewPresenter @AssistedInject constructor( .takeIf { it.isNotEmpty() } // If we're supposed to send the media as a background job, we can dismiss this screen already - if (useSendQueue && coroutineContext.isActive) { + if (coroutineContext.isActive) { onDoneListener() } - // If using the send queue, send it using the session coroutine scope so it doesn't matter if this screen or the chat one are closed - val sendMediaCoroutineScope = if (useSendQueue) sessionCoroutineScope else coroutineScope - sendMediaCoroutineScope.launch(dispatchers.io) { + // Send the media using the session coroutine scope so it doesn't matter if this screen or the chat one are closed + sessionCoroutineScope.launch(dispatchers.io) { sendPreProcessedMedia( mediaUploadInfo = mediaUploadInfo, caption = caption, sendActionState = sendActionState, - dismissAfterSend = !useSendQueue, + dismissAfterSend = false, inReplyToEventId = null, ) @@ -238,8 +221,6 @@ class AttachmentsPreviewPresenter @AssistedInject constructor( attachment = attachment, sendActionState = sendActionState.value, textEditorState = textEditorState, - allowCaption = allowCaption, - showCaptionCompatibilityWarning = showCaptionCompatibilityWarning, mediaOptimizationSelectorState = mediaOptimizationSelectorState, displayFileTooLargeError = displayFileTooLargeError, eventSink = ::handleEvents diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt index a935dd3afe..71d29cbfb6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt @@ -17,8 +17,6 @@ data class AttachmentsPreviewState( val attachment: Attachment, val sendActionState: SendActionState, val textEditorState: TextEditorState, - val allowCaption: Boolean, - val showCaptionCompatibilityWarning: Boolean, val mediaOptimizationSelectorState: MediaOptimizationSelectorState, val displayFileTooLargeError: Boolean, val eventSink: (AttachmentsPreviewEvents) -> Unit diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt index b1985482f6..43410efa46 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt @@ -41,8 +41,6 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider @@ -376,7 +367,6 @@ class MessageComposerPresenter @AssistedInject constructor( showAttachmentSourcePicker = showAttachmentSourcePicker, showTextFormatting = showTextFormatting, canShareLocation = canShareLocation.value, - canCreatePoll = canCreatePoll.value, suggestions = suggestions.toPersistentList(), resolveMentionDisplay = resolveMentionDisplay, resolveAtRoomMentionDisplay = resolveAtRoomMentionDisplay, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt index 1f1f80b203..6eadc14260 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt @@ -22,7 +22,6 @@ data class MessageComposerState( val showAttachmentSourcePicker: Boolean, val showTextFormatting: Boolean, val canShareLocation: Boolean, - val canCreatePoll: Boolean, val suggestions: ImmutableList, val resolveMentionDisplay: (String, String) -> TextDisplay, val resolveAtRoomMentionDisplay: () -> TextDisplay, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt index 590cfd20cf..36e2c69f96 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt @@ -30,7 +30,6 @@ fun aMessageComposerState( showTextFormatting: Boolean = false, showAttachmentSourcePicker: Boolean = false, canShareLocation: Boolean = true, - canCreatePoll: Boolean = true, suggestions: ImmutableList = persistentListOf(), eventSink: (MessageComposerEvents) -> Unit = {}, ) = MessageComposerState( @@ -40,7 +39,6 @@ fun aMessageComposerState( showTextFormatting = showTextFormatting, showAttachmentSourcePicker = showAttachmentSourcePicker, canShareLocation = canShareLocation, - canCreatePoll = canCreatePoll, suggestions = suggestions, resolveMentionDisplay = { _, _ -> TextDisplay.Plain }, resolveAtRoomMentionDisplay = { TextDisplay.Plain }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt index b3d8e5bf2d..0cc5bd93ec 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt @@ -33,7 +33,6 @@ import kotlinx.coroutines.launch internal fun MessageComposerView( state: MessageComposerState, voiceMessageState: VoiceMessageComposerState, - enableVoiceMessages: Boolean, modifier: Modifier = Modifier, ) { val view = LocalView.current @@ -104,7 +103,6 @@ internal fun MessageComposerView( onResetComposerMode = ::onCloseSpecialMode, onAddAttachment = ::onAddAttachment, onDismissTextFormatting = ::onDismissTextFormatting, - enableVoiceMessages = enableVoiceMessages, onVoiceRecorderEvent = onVoiceRecorderEvent, onVoicePlayerEvent = onVoicePlayerEvent, onSendVoiceMessage = onSendVoiceMessage, @@ -128,13 +126,11 @@ internal fun MessageComposerViewPreview( modifier = Modifier.height(IntrinsicSize.Min), state = state, voiceMessageState = aVoiceMessageComposerState(), - enableVoiceMessages = true, ) MessageComposerView( modifier = Modifier.height(200.dp), state = state, voiceMessageState = aVoiceMessageComposerState(), - enableVoiceMessages = true, ) DisabledComposerView() } @@ -150,7 +146,6 @@ internal fun MessageComposerViewVoicePreview( modifier = Modifier.height(IntrinsicSize.Min), state = aMessageComposerState(), voiceMessageState = state, - enableVoiceMessages = true, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/DefaultIsPinnedMessagesFeatureEnabled.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/DefaultIsPinnedMessagesFeatureEnabled.kt deleted file mode 100644 index 7c7448f536..0000000000 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/DefaultIsPinnedMessagesFeatureEnabled.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.messages.impl.pinned - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled -import io.element.android.libraries.di.AppScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import javax.inject.Inject - -@ContributesBinding(AppScope::class) -class DefaultIsPinnedMessagesFeatureEnabled @Inject constructor( - private val featureFlagService: FeatureFlagService, -) : IsPinnedMessagesFeatureEnabled { - @Composable - override operator fun invoke(): Boolean { - var isFeatureEnabled by rememberSaveable { - mutableStateOf(false) - } - LaunchedEffect(Unit) { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents) - .onEach { isFeatureEnabled = it } - .launchIn(this) - } - return isFeatureEnabled - } -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/PinnedEventsTimelineProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/PinnedEventsTimelineProvider.kt index 5210631409..9f18ec86ae 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/PinnedEventsTimelineProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/PinnedEventsTimelineProvider.kt @@ -12,8 +12,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.SingleIn -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.sync.SyncService @@ -23,7 +21,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map @@ -35,7 +32,6 @@ import javax.inject.Inject class PinnedEventsTimelineProvider @Inject constructor( private val room: JoinedRoom, private val syncService: SyncService, - private val featureFlagService: FeatureFlagService, private val dispatchers: CoroutineDispatchers, ) : TimelineProvider { private val _timelineStateFlow: MutableStateFlow> = @@ -66,20 +62,10 @@ class PinnedEventsTimelineProvider @Inject constructor( } private suspend fun onActive() = coroutineScope { - combine( - featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents), - syncService.syncState, - ) { isEnabled, _ -> + syncService.syncState.onEach { // do not use syncState here as data can be loaded from cache, it's just to trigger retry if needed - isEnabled + loadTimelineIfNeeded() } - .onEach { isFeatureEnabled -> - if (isFeatureEnabled) { - loadTimelineIfNeeded() - } else { - resetTimeline() - } - } .launchIn(this) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt index c6a6e3c10c..f9e705b1ca 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt @@ -28,8 +28,6 @@ import io.element.android.features.messages.impl.utils.TextPillificationHelper import io.element.android.libraries.androidutils.filesize.FileSizeFormatter import io.element.android.libraries.androidutils.text.safeLinkify import io.element.android.libraries.core.mimetype.MimeTypes -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType @@ -56,7 +54,6 @@ import kotlin.time.Duration class TimelineItemContentMessageFactory @Inject constructor( private val fileSizeFormatter: FileSizeFormatter, private val fileExtensionExtractor: FileExtensionExtractor, - private val featureFlagService: FeatureFlagService, private val htmlConverterProvider: HtmlConverterProvider, private val permalinkParser: PermalinkParser, private val textPillificationHelper: TextPillificationHelper, @@ -177,38 +174,20 @@ class TimelineItemContentMessageFactory @Inject constructor( ) } is VoiceMessageType -> { - when (featureFlagService.isFeatureEnabled(FeatureFlags.VoiceMessages)) { - true -> { - TimelineItemVoiceContent( - eventId = eventId, - filename = messageType.filename, - fileSize = messageType.info?.size ?: 0, - caption = messageType.caption?.trimEnd(), - formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(), - isEdited = content.isEdited, - mediaSource = messageType.source, - duration = messageType.info?.duration ?: Duration.ZERO, - mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream, - waveform = messageType.details?.waveform?.toImmutableList() ?: persistentListOf(), - formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0), - fileExtension = fileExtensionExtractor.extractFromName(messageType.filename) - ) - } - false -> { - TimelineItemAudioContent( - filename = messageType.filename, - fileSize = messageType.info?.size ?: 0, - caption = messageType.caption?.trimEnd(), - formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(), - isEdited = content.isEdited, - mediaSource = messageType.source, - duration = messageType.info?.duration ?: Duration.ZERO, - mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream, - formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0), - fileExtension = fileExtensionExtractor.extractFromName(messageType.filename), - ) - } - } + TimelineItemVoiceContent( + eventId = eventId, + filename = messageType.filename, + fileSize = messageType.info?.size ?: 0, + caption = messageType.caption?.trimEnd(), + formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(), + isEdited = content.isEdited, + mediaSource = messageType.source, + duration = messageType.info?.duration ?: Duration.ZERO, + mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream, + waveform = messageType.details?.waveform?.toImmutableList() ?: persistentListOf(), + formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0), + fileExtension = fileExtensionExtractor.extractFromName(messageType.filename) + ) } is FileMessageType -> { val fileExtension = fileExtensionExtractor.extractFromName(messageType.filename) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt index ba3d397b61..c0da622d15 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt @@ -9,23 +9,18 @@ package io.element.android.features.messages.impl.timeline.factories.event import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent import io.element.android.features.poll.api.pollcontent.PollContentStateFactory -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import javax.inject.Inject class TimelineItemContentPollFactory @Inject constructor( - private val featureFlagService: FeatureFlagService, private val pollContentStateFactory: PollContentStateFactory, ) { suspend fun create( event: EventTimelineItem, content: PollContent, ): TimelineItemEventContent { - if (!featureFlagService.isFeatureEnabled(FeatureFlags.Polls)) return TimelineItemUnknownContent val pollContentState = pollContentStateFactory.create(event, content) return TimelineItemPollContent( isMine = pollContentState.isMine, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 001da88bd4..a64fa03e2b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -46,9 +46,6 @@ import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -994,37 +991,6 @@ class MessagesPresenterTest { composerMode = MessageComposerMode.EditCaption( eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(), content = A_CAPTION, - showCaptionCompatibilityWarning = true, - ) - ) - ) - } - } - - @Test - fun `present - handle action edit caption without warning`() = runTest { - val messageEvent = aMessageEvent( - content = aTimelineItemImageContent( - caption = A_CAPTION, - ) - ) - val composerRecorder = EventsRecorder() - val presenter = createMessagesPresenter( - messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) }, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.MediaCaptionWarning.key to false) - ) - ) - presenter.testWithLifecycleOwner { - val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EditCaption, messageEvent)) - awaitItem() - composerRecorder.assertSingle( - MessageComposerEvents.SetMode( - composerMode = MessageComposerMode.EditCaption( - eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(), - content = A_CAPTION, - showCaptionCompatibilityWarning = false, ) ) ) @@ -1051,37 +1017,6 @@ class MessagesPresenterTest { composerMode = MessageComposerMode.EditCaption( eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(), content = "", - showCaptionCompatibilityWarning = true, - ) - ) - ) - } - } - - @Test - fun `present - handle action add caption without warning`() = runTest { - val composerRecorder = EventsRecorder() - val presenter = createMessagesPresenter( - messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) }, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.MediaCaptionWarning.key to false) - ) - ) - val messageEvent = aMessageEvent( - content = aTimelineItemImageContent( - caption = null, - ) - ) - presenter.testWithLifecycleOwner { - val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.AddCaption, messageEvent)) - awaitItem() - composerRecorder.assertSingle( - MessageComposerEvents.SetMode( - composerMode = MessageComposerMode.EditCaption( - eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(), - content = "", - showCaptionCompatibilityWarning = false, ) ) ) @@ -1234,7 +1169,6 @@ class MessagesPresenterTest { typingNoticeResult = { Result.success(Unit) }, ), navigator: FakeMessagesNavigator = FakeMessagesNavigator(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(), analyticsService: FakeAnalyticsService = FakeAnalyticsService(), timelineEventSink: (TimelineEvents) -> Unit = {}, @@ -1270,7 +1204,6 @@ class MessagesPresenterTest { snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, clipboardHelper = clipboardHelper, - featureFlagsService = featureFlagService, buildMeta = aBuildMeta(), dispatchers = coroutineDispatchers, htmlConverterProvider = FakeHtmlConverterProvider(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index a082b36b39..50dbb2b7ca 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -27,8 +27,6 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList import io.element.android.libraries.dateformatter.test.FakeDateFormatter -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.test.AN_EVENT_ID @@ -52,7 +50,7 @@ class ActionListPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -63,7 +61,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from me redacted`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -100,7 +98,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from others redacted`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -141,7 +139,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -188,7 +186,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message in a thread`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( @@ -234,7 +232,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message cannot sent message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -280,7 +278,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and can redact`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -328,7 +326,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and cannot send reaction`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -376,7 +374,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -423,7 +421,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message in a thread`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( @@ -469,7 +467,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message cannot redact`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -515,7 +513,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message no permission`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -558,7 +556,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media item`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -603,61 +601,9 @@ class ActionListPresenterTest { } } - @Test - fun `present - compute for a media item - caption disabled`() = runTest { - val presenter = createActionListPresenter( - isDeveloperModeEnabled = true, - isPinFeatureEnabled = true, - allowCaption = false, - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() - val messageEvent = aMessageEvent( - isMine = true, - isEditable = true, - content = aTimelineItemImageContent(), - ) - initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( - event = messageEvent, - userEventPermissions = aUserEventPermissions( - canRedactOwn = true, - canRedactOther = false, - canSendMessage = true, - canSendReaction = true, - canPinUnpin = true, - ), - ) - ) - val successState = awaitItem() - assertThat(successState.target).isEqualTo( - ActionListState.Target.Success( - event = messageEvent, - sentTimeFull = "0 Full true", - displayEmojiReactions = true, - verifiedUserSendFailure = VerifiedUserSendFailure.None, - actions = persistentListOf( - TimelineItemAction.Reply, - TimelineItemAction.Forward, - // Not here - // TimelineItemAction.AddCaption, - TimelineItemAction.CopyLink, - TimelineItemAction.Pin, - TimelineItemAction.ViewSource, - TimelineItemAction.Redact, - ) - ) - ) - initialState.eventSink.invoke(ActionListEvents.Clear) - assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) - } - } - @Test fun `present - compute for a media with caption item`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -708,7 +654,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media with caption item - other user event`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -757,7 +703,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in debug build`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -797,7 +743,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in non-debuggable build`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -824,7 +770,7 @@ class ActionListPresenterTest { @Test fun `present - compute message in non-debuggable build`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -870,7 +816,7 @@ class ActionListPresenterTest { @Test fun `present - compute message when user can't pin`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -921,7 +867,6 @@ class ActionListPresenterTest { } val presenter = createActionListPresenter( isDeveloperModeEnabled = true, - isPinFeatureEnabled = true, room = room ) moleculeFlow(RecompositionMode.Immediate) { @@ -970,7 +915,7 @@ class ActionListPresenterTest { @Test fun `present - compute message with no actions`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1017,7 +962,7 @@ class ActionListPresenterTest { @Test fun `present - compute not sent message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1061,7 +1006,7 @@ class ActionListPresenterTest { @Test fun `present - compute for editable poll message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1105,7 +1050,7 @@ class ActionListPresenterTest { @Test fun `present - compute for non-editable poll message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1148,7 +1093,7 @@ class ActionListPresenterTest { @Test fun `present - compute for ended poll message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1190,7 +1135,7 @@ class ActionListPresenterTest { @Test fun `present - compute for voice message`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1235,7 +1180,7 @@ class ActionListPresenterTest { @Test fun `present - compute for call notify`() = runTest { - val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1275,7 +1220,7 @@ class ActionListPresenterTest { val room = FakeBaseRoom( userDisplayNameResult = { Result.success("Alice") } ) - val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = false, room = room) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -1299,22 +1244,14 @@ class ActionListPresenterTest { private fun createActionListPresenter( isDeveloperModeEnabled: Boolean, - isPinFeatureEnabled: Boolean, room: BaseRoom = FakeBaseRoom(), - allowCaption: Boolean = true, ): ActionListPresenter { val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) return DefaultActionListPresenter( postProcessor = TimelineItemActionPostProcessor.Default, appPreferencesStore = preferencesStore, - isPinnedMessagesFeatureEnabled = { isPinFeatureEnabled }, room = room, userSendFailureFactory = VerifiedUserSendFailureFactory(room), - featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.MediaCaptionCreation.key to allowCaption, - ), - ), dateFormatter = FakeDateFormatter(), ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 18808d9ddf..7f8e10c5b1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -25,8 +25,6 @@ import io.element.android.features.messages.test.attachments.video.FakeMediaOpti import io.element.android.libraries.androidutils.file.TemporaryUriDeleter import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.mimetype.MimeTypes -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.media.AudioInfo @@ -84,34 +82,8 @@ class AttachmentsPreviewPresenterTest { @Test fun `present - initial state`() = runTest { createAttachmentsPreviewPresenter().test { - skipItems(1) val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - assertThat(initialState.allowCaption).isTrue() - assertThat(initialState.showCaptionCompatibilityWarning).isTrue() - } - } - - @Test - fun `present - initial state no caption warning`() = runTest { - createAttachmentsPreviewPresenter( - showCaptionCompatibilityWarning = false, - ).test { - skipItems(1) - val initialState = awaitItem() - assertThat(initialState.showCaptionCompatibilityWarning).isFalse() - } - } - - @Test - fun `present - initial state - caption not allowed`() = runTest { - createAttachmentsPreviewPresenter( - allowCaption = false, - ).test { - skipItems(1) - val initialState = awaitItem() - assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - assertThat(initialState.allowCaption).isFalse() } } @@ -144,7 +116,6 @@ class AttachmentsPreviewPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = true)) @@ -186,7 +157,6 @@ class AttachmentsPreviewPresenterTest { // Pre-processing finishes processLatch.complete(Unit) advanceUntilIdle() - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) @@ -221,7 +191,6 @@ class AttachmentsPreviewPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) // Pre-processing finishes @@ -253,7 +222,6 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) // Pre-processing finishes processLatch.complete(Unit) @@ -282,7 +250,6 @@ class AttachmentsPreviewPresenterTest { processLatch.complete(Unit) advanceUntilIdle() initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Failure::class.java) } @@ -304,7 +271,6 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvents.CancelAndDismiss) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done) deleteCallback.assertions().isCalledOnce() onDoneListener.assertions().isCalledOnce() @@ -339,7 +305,6 @@ class AttachmentsPreviewPresenterTest { assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.ReadyToUpload::class.java) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done) @@ -383,7 +348,6 @@ class AttachmentsPreviewPresenterTest { assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.ReadyToUpload::class.java) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done) @@ -425,7 +389,6 @@ class AttachmentsPreviewPresenterTest { assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.ReadyToUpload::class.java) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done) @@ -442,38 +405,7 @@ class AttachmentsPreviewPresenterTest { } @Test - fun `present - send media failure scenario without media queue`() = runTest { - val failure = MediaPreProcessor.Failure(null) - val sendFileResult = - lambdaRecorder> { _, _, _, _, _, _ -> - Result.failure(failure) - } - val room = FakeJoinedRoom( - liveTimeline = FakeTimeline().apply { - sendFileLambda = sendFileResult - }, - ) - val presenter = createAttachmentsPreviewPresenter(room = room, mediaUploadOnSendQueueEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() - assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) - val failureState = awaitItem() - assertThat(failureState.sendActionState).isEqualTo(SendActionState.Failure(failure, mediaUploadInfo)) - sendFileResult.assertions().isCalledOnce() - failureState.eventSink(AttachmentsPreviewEvents.CancelAndClearSendState) - val clearedState = awaitLastSequentialItem() - assertThat(clearedState.sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) - } - } - - @Test - fun `present - send media failure scenario with media queue`() = runTest { + fun `present - send media failure scenario`() = runTest { val failure = MediaPreProcessor.Failure(null) val sendFileResult = lambdaRecorder> { _, _, _, _, _, _ -> @@ -485,14 +417,13 @@ class AttachmentsPreviewPresenterTest { sendFileLambda = sendFileResult }, ) - val presenter = createAttachmentsPreviewPresenter(room = room, mediaUploadOnSendQueueEnabled = true, onDoneListener = onDoneListenerResult) + val presenter = createAttachmentsPreviewPresenter(room = room, onDoneListener = onDoneListenerResult) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) @@ -509,25 +440,7 @@ class AttachmentsPreviewPresenterTest { } @Test - fun `present - dismissing the progress dialog stops media upload without media queue`() = runTest { - val presenter = createAttachmentsPreviewPresenter(mediaUploadOnSendQueueEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() - assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) - initialState.eventSink(AttachmentsPreviewEvents.CancelAndClearSendState) - // The sending is cancelled and the state is kept at ReadyToUpload - ensureAllEventsConsumed() - } - } - - @Test - fun `present - dismissing the progress dialog stops media upload with media queue`() = runTest { + fun `present - dismissing the progress dialog stops media upload`() = runTest { val onDoneListenerResult = lambdaRecorder {} val presenter = createAttachmentsPreviewPresenter( room = FakeJoinedRoom( @@ -537,7 +450,6 @@ class AttachmentsPreviewPresenterTest { } } ), - mediaUploadOnSendQueueEnabled = true, onDoneListener = onDoneListenerResult, ) moleculeFlow(RecompositionMode.Immediate) { @@ -546,7 +458,6 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) - assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) initialState.eventSink(AttachmentsPreviewEvents.CancelAndClearSendState) @@ -574,7 +485,6 @@ class AttachmentsPreviewPresenterTest { } } ), - mediaUploadOnSendQueueEnabled = true, onDoneListener = onDoneListenerResult, mediaOptimizationSelectorPresenterFactory = FakeMediaOptimizationSelectorPresenterFactory { MediaOptimizationSelectorState( @@ -616,7 +526,6 @@ class AttachmentsPreviewPresenterTest { } } ), - mediaUploadOnSendQueueEnabled = true, onDoneListener = onDoneListenerResult, mediaOptimizationSelectorPresenterFactory = FakeMediaOptimizationSelectorPresenterFactory { MediaOptimizationSelectorState( @@ -672,9 +581,6 @@ class AttachmentsPreviewPresenterTest { mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(), temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(), onDoneListener: OnDoneListener = OnDoneListener { lambdaError() }, - mediaUploadOnSendQueueEnabled: Boolean = true, - allowCaption: Boolean = true, - showCaptionCompatibilityWarning: Boolean = true, displayMediaQualitySelectorViews: Boolean = false, mediaOptimizationSelectorPresenterFactory: FakeMediaOptimizationSelectorPresenterFactory = FakeMediaOptimizationSelectorPresenterFactory( fakePresenter = { @@ -698,13 +604,6 @@ class AttachmentsPreviewPresenterTest { }), permalinkBuilder = permalinkBuilder, temporaryUriDeleter = temporaryUriDeleter, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.MediaUploadOnSendQueue.key to mediaUploadOnSendQueueEnabled, - FeatureFlags.MediaCaptionCreation.key to allowCaption, - FeatureFlags.MediaCaptionWarning.key to showCaptionCompatibilityWarning, - ), - ), sessionCoroutineScope = this, dispatchers = testCoroutineDispatchers(), mediaOptimizationSelectorPresenterFactory = mediaOptimizationSelectorPresenterFactory, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt index b62e77e08e..2cf0f8a3c9 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt @@ -30,7 +30,6 @@ import io.element.android.features.poll.test.pollcontent.FakePollContentStateFac import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.eventformatter.api.TimelineEventFormatter -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser @@ -60,7 +59,6 @@ internal fun TestScope.aTimelineItemsFactory( messageFactory = TimelineItemContentMessageFactory( fileSizeFormatter = FakeFileSizeFormatter(), fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), - featureFlagService = FakeFeatureFlagService(), htmlConverterProvider = FakeHtmlConverterProvider(), permalinkParser = FakePermalinkParser(), textPillificationHelper = FakeTextPillificationHelper(), @@ -70,7 +68,7 @@ internal fun TestScope.aTimelineItemsFactory( fileSizeFormatter = FakeFileSizeFormatter(), fileExtensionExtractor = FileExtensionExtractorWithoutValidation() ), - pollFactory = TimelineItemContentPollFactory(FakeFeatureFlagService(), FakePollContentStateFactory()), + pollFactory = TimelineItemContentPollFactory(FakePollContentStateFactory()), utdFactory = TimelineItemContentUTDFactory(), roomMembershipFactory = TimelineItemContentRoomMembershipFactory(timelineEventFormatter), profileChangeFactory = TimelineItemContentProfileChangeFactory(timelineEventFormatter), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index a677207b13..c0df1a2b19 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -32,9 +32,6 @@ import io.element.android.features.messages.impl.utils.FakeTextPillificationHelp import io.element.android.features.messages.impl.utils.TextPillificationHelper import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.ThreadId @@ -125,9 +122,6 @@ class MessageComposerPresenterTest { private val pickerProvider = FakePickerProvider().apply { givenResult(mockk()) // Uri is not available in JVM, so the only way to have a non-null Uri is using Mockk } - private val featureFlagService = FakeFeatureFlagService( - mapOf(FeatureFlags.LocationSharing.key to true) - ) private val mediaPreProcessor = FakeMediaPreProcessor() private val snackbarDispatcher = SnackbarDispatcher() private val mockMediaUrl: Uri = mockk("localMediaUri") @@ -1529,7 +1523,6 @@ class MessageComposerPresenterTest { ), navigator: MessagesNavigator = FakeMessagesNavigator(), pickerProvider: PickerProvider = this@MessageComposerPresenterTest.pickerProvider, - featureFlagService: FeatureFlagService = this@MessageComposerPresenterTest.featureFlagService, locationService: LocationService = FakeLocationService(true), sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), mediaPreProcessor: MediaPreProcessor = this@MessageComposerPresenterTest.mediaPreProcessor, @@ -1551,7 +1544,6 @@ class MessageComposerPresenterTest { sessionCoroutineScope = this, room = room, mediaPickerProvider = pickerProvider, - featureFlagService = featureFlagService, sessionPreferencesStore = sessionPreferencesStore, localMediaFactory = localMediaFactory, mediaSender = MediaSender( @@ -1593,11 +1585,9 @@ fun anEditMode( fun anEditCaptionMode( eventOrTransactionId: EventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(), caption: String = A_CAPTION, - showCaptionCompatibilityWarning: Boolean = false, ) = MessageComposerMode.EditCaption( eventOrTransactionId = eventOrTransactionId, content = caption, - showCaptionCompatibilityWarning = showCaptionCompatibilityWarning, ) fun aReplyMode() = MessageComposerMode.Reply( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index f1fcd7e787..4840d5bed1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -10,8 +10,6 @@ package io.element.android.features.messages.impl.pinned.banner import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProvider import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem @@ -35,7 +33,7 @@ import org.junit.Test class PinnedMessagesBannerPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = true) + val presenter = createPinnedMessagesBannerPresenter() presenter.test { val initialState = awaitItem() assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden) @@ -43,15 +41,6 @@ class PinnedMessagesBannerPresenterTest { } } - @Test - fun `present - feature disabled`() = runTest { - val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = false) - presenter.test { - val initialState = awaitItem() - assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden) - } - } - @Test fun `present - loading state`() = runTest { val room = FakeJoinedRoom( @@ -188,14 +177,10 @@ class PinnedMessagesBannerPresenterTest { ) ), syncService: SyncService = FakeSyncService(), - isFeatureEnabled: Boolean = true, ): PinnedMessagesBannerPresenter { val timelineProvider = PinnedEventsTimelineProvider( room = room, syncService = syncService, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.PinnedEvents.key to isFeatureEnabled) - ), dispatchers = testCoroutineDispatchers(), ) timelineProvider.launchIn(backgroundScope) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt index 535b11c522..507edf9d9a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt @@ -17,8 +17,6 @@ import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProv import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.sync.SyncService @@ -51,34 +49,17 @@ import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class PinnedMessagesListPresenterTest { @Test - fun `present - initial state feature disabled`() = runTest { + fun `present - initial state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + } ) - ) - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = false) - presenter.test { - val initialState = awaitItem() - assertThat(initialState).isEqualTo(PinnedMessagesListState.Loading) - cancelAndIgnoreRemainingEvents() - } - } - - @Test - fun `present - initial state feature enabled`() = runTest { - val room = FakeJoinedRoom( - baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - } - ) - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room) presenter.test { val initialState = awaitItem() assertThat(initialState).isEqualTo(PinnedMessagesListState.Loading) @@ -90,15 +71,15 @@ class PinnedMessagesListPresenterTest { fun `present - timeline failure state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + }, createTimelineResult = { Result.failure(RuntimeException()) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room) presenter.test { skipItems(3) val failureState = awaitItem() @@ -111,15 +92,15 @@ class PinnedMessagesListPresenterTest { fun `present - empty state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf())) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf())) + }, createTimelineResult = { Result.success(FakeTimeline()) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room) presenter.test { skipItems(3) val emptyState = awaitItem() @@ -133,15 +114,15 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + }, createTimelineResult = { Result.success(pinnedEventsTimeline) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room) presenter.test { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled @@ -162,15 +143,15 @@ class PinnedMessagesListPresenterTest { val analyticsService = FakeAnalyticsService() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + }, createTimelineResult = { Result.success(pinnedEventsTimeline) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true, analyticsService = analyticsService) + val presenter = createPinnedMessagesListPresenter(room = room, analyticsService = analyticsService) presenter.test { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled @@ -210,15 +191,15 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + }, createTimelineResult = { Result.success(pinnedEventsTimeline) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator) presenter.test { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled @@ -241,15 +222,15 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + }, createTimelineResult = { Result.success(pinnedEventsTimeline) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator) presenter.test { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled @@ -272,15 +253,15 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserPinUnpinResult = { Result.success(true) }, + ).apply { + givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) + }, createTimelineResult = { Result.success(pinnedEventsTimeline) }, ) - val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true) + val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator) presenter.test { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled @@ -315,15 +296,11 @@ class PinnedMessagesListPresenterTest { navigator: PinnedMessagesListNavigator = FakePinnedMessagesListNavigator(), room: JoinedRoom = FakeJoinedRoom(), syncService: SyncService = FakeSyncService(), - isFeatureEnabled: Boolean = true, analyticsService: AnalyticsService = FakeAnalyticsService(), ): PinnedMessagesListPresenter { val timelineProvider = PinnedEventsTimelineProvider( room = room, syncService = syncService, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.PinnedEvents.key to isFeatureEnabled) - ), dispatchers = testCoroutineDispatchers(), ) timelineProvider.launchIn(backgroundScope) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index 9aaa49f4ca..10efc72e71 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -32,9 +32,6 @@ import io.element.android.features.messages.impl.utils.FakeTextPillificationHelp import io.element.android.features.messages.test.timeline.FakeHtmlConverterProvider import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter import io.element.android.libraries.core.mimetype.MimeTypes -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.media.AudioDetails import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo @@ -430,35 +427,6 @@ class TimelineItemContentMessageFactoryTest { assertThat(result).isEqualTo(expected) } - @Test - fun `test create VoiceMessageType feature disabled`() = runTest { - val sut = createTimelineItemContentMessageFactory( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.VoiceMessages.key to false, - ) - ) - ) - val result = sut.create( - content = createMessageContent(type = VoiceMessageType("filename", null, null, MediaSource("url"), null, null)), - senderDisambiguatedDisplayName = "Bob", - eventId = AN_EVENT_ID, - ) - val expected = TimelineItemAudioContent( - filename = "filename", - fileSize = 0L, - caption = null, - formattedCaption = null, - isEdited = false, - duration = Duration.ZERO, - mediaSource = MediaSource(url = "url", json = null), - mimeType = MimeTypes.OctetStream, - formattedFileSize = "0 Bytes", - fileExtension = "" - ) - assertThat(result).isEqualTo(expected) - } - @Test fun `test create ImageMessageType`() = runTest { val sut = createTimelineItemContentMessageFactory() @@ -794,13 +762,11 @@ class TimelineItemContentMessageFactoryTest { } private fun createTimelineItemContentMessageFactory( - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), htmlConverterTransform: (String) -> CharSequence = { it }, permalinkParser: FakePermalinkParser = FakePermalinkParser(), ) = TimelineItemContentMessageFactory( fileSizeFormatter = FakeFileSizeFormatter(), fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), - featureFlagService = featureFlagService, htmlConverterProvider = FakeHtmlConverterProvider(htmlConverterTransform), permalinkParser = permalinkParser, textPillificationHelper = FakeTextPillificationHelper(), diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt index ee73b7f721..b0bcfed44c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt @@ -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, 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, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt index 2e5cb4fa14..ebe8aaf57f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt @@ -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?, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index 43307e9988..91b32fe12d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -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), diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index 337544ed7f..85c180ddac 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -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 diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt index a65e61661e..42fee711a7 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt @@ -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, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 3356c899d0..026b616996 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -12,14 +12,12 @@ 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 import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomState -import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter import io.element.android.features.roomdetails.impl.securityandprivacy.permissions.securityAndPrivacyPermissionsAsState @@ -69,7 +67,6 @@ class RoomDetailsPresenter @Inject constructor( private val roomCallStatePresenter: Presenter, private val dispatchers: CoroutineDispatchers, private val analyticsService: AnalyticsService, - private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled, private val clipboardHelper: ClipboardHelper, private val appPreferencesStore: AppPreferencesStore, ) : Presenter { @@ -77,7 +74,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() @@ -88,19 +84,11 @@ class RoomDetailsPresenter @Inject constructor( val isFavorite by remember { derivedStateOf { roomInfo.isFavorite } } val joinRule by remember { derivedStateOf { roomInfo.joinRule } } - val canShowPinnedMessages = isPinnedMessagesFeatureEnabled() val pinnedMessagesCount by remember { derivedStateOf { roomInfo.pinnedEventIds.size } } - val canShowMediaGallery by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaGallery) - }.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 +185,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, @@ -207,8 +194,6 @@ class RoomDetailsPresenter @Inject constructor( displayRolesAndPermissionsSettings = !isDm && isUserAdmin, isPublic = joinRule == JoinRule.Public, heroes = roomInfo.heroes.toPersistentList(), - canShowPinnedMessages = canShowPinnedMessages, - canShowMediaGallery = canShowMediaGallery, pinnedMessagesCount = pinnedMessagesCount, snackbarMessage = snackbarMessage, canShowKnockRequests = canShowKnockRequests, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index 331329a034..70810ee46b 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -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?, @@ -40,8 +39,6 @@ data class RoomDetailsState( val displayRolesAndPermissionsSettings: Boolean, val isPublic: Boolean, val heroes: ImmutableList, - val canShowPinnedMessages: Boolean, - val canShowMediaGallery: Boolean, val pinnedMessagesCount: Int?, val snackbarMessage: SnackbarMessage?, val canShowKnockRequests: Boolean, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index 9631be01c2..e41392ee76 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -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, @@ -110,8 +109,6 @@ fun aRoomDetailsState( displayAdminSettings: Boolean = false, isPublic: Boolean = true, heroes: List = emptyList(), - canShowPinnedMessages: Boolean = true, - canShowMediaGallery: Boolean = true, pinnedMessagesCount: Int? = null, snackbarMessage: SnackbarMessage? = null, canShowKnockRequests: Boolean = false, @@ -132,7 +129,6 @@ fun aRoomDetailsState( isEncrypted = isEncrypted, canInvite = canInvite, canEdit = canEdit, - canShowNotificationSettings = canShowNotificationSettings, roomCallState = roomCallState, roomType = roomType, roomMemberDetailsState = roomMemberDetailsState, @@ -142,8 +138,6 @@ fun aRoomDetailsState( displayRolesAndPermissionsSettings = displayAdminSettings, isPublic = isPublic, heroes = heroes.toPersistentList(), - canShowPinnedMessages = canShowPinnedMessages, - canShowMediaGallery = canShowMediaGallery, pinnedMessagesCount = pinnedMessagesCount, snackbarMessage = snackbarMessage, canShowKnockRequests = canShowKnockRequests, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index fe14fd983c..3fdb2a0800 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -185,7 +185,7 @@ fun RoomDetailsView( } PreferenceCategory { - if (state.canShowNotificationSettings && state.roomNotificationSettings != null) { + if (state.roomNotificationSettings != null) { NotificationItem( isDefaultMode = state.roomNotificationSettings.isDefault, openRoomNotificationSettings = openRoomNotificationSettings @@ -237,20 +237,16 @@ fun RoomDetailsView( } PreferenceCategory { - if (state.canShowPinnedMessages) { - PinnedMessagesItem( - pinnedMessagesCount = state.pinnedMessagesCount, - onPinnedMessagesClick = onPinnedMessagesClick - ) - } + PinnedMessagesItem( + pinnedMessagesCount = state.pinnedMessagesCount, + onPinnedMessagesClick = onPinnedMessagesClick + ) PollsItem( openPollHistory = openPollHistory ) - if (state.canShowMediaGallery) { - MediaGalleryItem( - onClick = openMediaGallery - ) - } + MediaGalleryItem( + onClick = openMediaGallery + ) } if (state.roomType is RoomDetailsType.Dm && state.roomMemberDetailsState != null) { @@ -337,8 +333,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), diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index 7dd954011e..bfcfa184cb 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -79,11 +79,9 @@ class RoomDetailsPresenterTest { analyticsService: AnalyticsService = FakeAnalyticsService(), featureFlagService: FeatureFlagService = FakeFeatureFlagService( mapOf( - FeatureFlags.NotificationSettings.key to true, FeatureFlags.Knock.key to false, ) ), - isPinnedMessagesFeatureEnabled: Boolean = true, encryptionService: FakeEncryptionService = FakeEncryptionService(), clipboardHelper: ClipboardHelper = FakeClipboardHelper(), appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore() @@ -111,7 +109,6 @@ class RoomDetailsPresenterTest { leaveRoomPresenter = { leaveRoomState }, roomCallStatePresenter = { aStandByCallState() }, dispatchers = dispatchers, - isPinnedMessagesFeatureEnabled = { isPinnedMessagesFeatureEnabled }, analyticsService = analyticsService, clipboardHelper = clipboardHelper, appPreferencesStore = appPreferencesStore, @@ -133,7 +130,6 @@ class RoomDetailsPresenterTest { assertThat(initialState.roomAvatarUrl).isEqualTo(room.info().avatarUrl) assertThat(initialState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(room.info().topic!!)) assertThat(initialState.memberCount).isEqualTo(room.info().joinedMembersCount) - assertThat(initialState.canShowPinnedMessages).isTrue() assertThat(initialState.pinnedMessagesCount).isEqualTo(0) assertThat(initialState.canShowSecurityAndPrivacy).isFalse() assertThat(initialState.showDebugInfo).isFalse() diff --git a/features/share/api/src/main/kotlin/io/element/android/features/share/api/ShareService.kt b/features/share/api/src/main/kotlin/io/element/android/features/share/api/ShareService.kt deleted file mode 100644 index db5bdd7f29..0000000000 --- a/features/share/api/src/main/kotlin/io/element/android/features/share/api/ShareService.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.share.api - -import kotlinx.coroutines.CoroutineScope - -interface ShareService { - fun observeFeatureFlag(coroutineScope: CoroutineScope) -} diff --git a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/DefaultShareService.kt b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/DefaultShareService.kt deleted file mode 100644 index 87f8088fdc..0000000000 --- a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/DefaultShareService.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.share.impl - -import android.content.ComponentName -import android.content.Context -import android.content.pm.PackageManager -import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.features.share.api.ShareService -import io.element.android.libraries.di.AppScope -import io.element.android.libraries.di.ApplicationContext -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import timber.log.Timber -import javax.inject.Inject - -@ContributesBinding(AppScope::class) -class DefaultShareService @Inject constructor( - private val featureFlagService: FeatureFlagService, - @ApplicationContext private val context: Context, -) : ShareService { - override fun observeFeatureFlag(coroutineScope: CoroutineScope) { - val shareActivityComponent = getShareActivityComponent() - ?: return Unit.also { - Timber.w("ShareActivity not found") - } - featureFlagService.isFeatureEnabledFlow(FeatureFlags.IncomingShare) - .onEach { enabled -> - shareActivityComponent.enableOrDisable(enabled) - } - .launchIn(coroutineScope) - } - - private fun getShareActivityComponent(): ComponentName? { - return context.packageManager - .getPackageInfo( - context.packageName, - PackageManager.GET_ACTIVITIES or PackageManager.MATCH_DISABLED_COMPONENTS - ) - .activities - ?.firstOrNull { it.name.endsWith(".ShareActivity") } - ?.let { shareActivityInfo -> - ComponentName( - shareActivityInfo.packageName, - shareActivityInfo.name, - ) - } - } - - private fun ComponentName.enableOrDisable(enabled: Boolean) { - val state = if (enabled) { - PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - } else { - PackageManager.COMPONENT_ENABLED_STATE_DISABLED - } - try { - context.packageManager.setComponentEnabledSetting( - this, - state, - PackageManager.DONT_KILL_APP, - ) - } catch (e: Exception) { - Timber.e(e, "Failed to enable or disable the component") - } - } -} diff --git a/features/share/test/build.gradle.kts b/features/share/test/build.gradle.kts deleted file mode 100644 index 871e856adb..0000000000 --- a/features/share/test/build.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ -plugins { - id("io.element.android-library") -} - -android { - namespace = "io.element.android.features.share.test" -} - -dependencies { - implementation(projects.features.share.api) - implementation(libs.coroutines.core) - implementation(projects.tests.testutils) -} diff --git a/features/share/test/src/main/kotlin/io/element/android/features/share/test/FakeShareService.kt b/features/share/test/src/main/kotlin/io/element/android/features/share/test/FakeShareService.kt deleted file mode 100644 index b5b6111004..0000000000 --- a/features/share/test/src/main/kotlin/io/element/android/features/share/test/FakeShareService.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.share.test - -import io.element.android.features.share.api.ShareService -import io.element.android.tests.testutils.lambda.lambdaError -import kotlinx.coroutines.CoroutineScope - -class FakeShareService( - private val observeFeatureFlagLambda: (CoroutineScope) -> Unit = { lambdaError() } -) : ShareService { - override fun observeFeatureFlag(coroutineScope: CoroutineScope) { - observeFeatureFlagLambda(coroutineScope) - } -} diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 16a6d6839a..9d34c03a93 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -7,7 +7,6 @@ package io.element.android.libraries.featureflag.api -import io.element.android.appconfig.OnBoardingConfig import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildType @@ -21,46 +20,6 @@ enum class FeatureFlags( override val defaultValue: (BuildMeta) -> Boolean, override val isFinished: Boolean, ) : Feature { - LocationSharing( - key = "feature.locationsharing", - title = "Allow user to share location", - defaultValue = { true }, - isFinished = true, - ), - Polls( - key = "feature.polls", - title = "Polls", - description = "Create poll and render poll events in the timeline", - defaultValue = { true }, - isFinished = true, - ), - NotificationSettings( - key = "feature.notificationsettings", - title = "Show notification settings", - defaultValue = { true }, - isFinished = true, - ), - VoiceMessages( - key = "feature.voicemessages", - title = "Voice messages", - description = "Send and receive voice messages", - 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", - description = "Allow user to mark a room as unread", - defaultValue = { true }, - isFinished = false, - ), RoomDirectorySearch( key = "feature.roomdirectorysearch", title = "Room directory search", @@ -75,27 +34,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - QrCodeLogin( - key = "feature.qrCodeLogin", - title = "Enable login using QR code", - description = "Allow the user to login using the QR code flow", - defaultValue = { OnBoardingConfig.CAN_LOGIN_WITH_QR_CODE }, - isFinished = false, - ), - IncomingShare( - key = "feature.incomingShare", - title = "Incoming Share support", - description = "Allow the application to receive data from other applications", - defaultValue = { true }, - isFinished = false, - ), - PinnedEvents( - key = "feature.pinnedEvents", - title = "Pinned Events", - description = "Allow user to pin events in a room", - defaultValue = { true }, - isFinished = false, - ), SyncOnPush( key = "feature.syncOnPush", title = "Sync on push", @@ -137,34 +75,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - MediaUploadOnSendQueue( - key = "feature.media_upload_through_send_queue", - title = "Media upload through send queue", - description = "Support for treating media uploads as regular events, with an improved retry and cancellation implementation.", - defaultValue = { true }, - isFinished = true, - ), - MediaCaptionCreation( - key = "feature.media_caption_creation", - title = "Allow creation of media captions", - description = null, - defaultValue = { true }, - isFinished = false, - ), - MediaCaptionWarning( - key = "feature.media_caption_creation_warning", - title = "Show a compatibility warning on media captions creation", - description = null, - defaultValue = { true }, - isFinished = false, - ), - MediaGallery( - key = "feature.media_gallery", - title = "Allow user to open the media gallery", - description = null, - defaultValue = { true }, - isFinished = false, - ), PrintLogsToLogcat( key = "feature.print_logs_to_logcat", title = "Print logs to logcat", @@ -175,15 +85,6 @@ enum class FeatureFlags( // False so it's displayed in the developer options screen isFinished = false, ), - SharePos( - key = "feature.share_pos_v2", - title = "Share pos in sliding sync", - description = "Keep the sliding sync pos to make initial syncs faster. Requires an app restart to take effect." + - "\n\nWARNING: this may cause issues with syncs.", - defaultValue = { true }, - // False so it's displayed in the developer options screen - isFinished = false, - ), SelectableMediaQuality( key = "feature.selectable_media_quality", title = "Select media quality per upload", diff --git a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt index 9794fdd6d4..097e318609 100644 --- a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt +++ b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt @@ -19,8 +19,8 @@ class DefaultFeatureFlagServiceTest { fun `given service without provider when feature is checked then it returns the default value`() = runTest { val buildMeta = aBuildMeta() val featureFlagService = DefaultFeatureFlagService(emptySet(), buildMeta) - featureFlagService.isFeatureEnabledFlow(FeatureFlags.LocationSharing).test { - assertThat(awaitItem()).isEqualTo(FeatureFlags.LocationSharing.defaultValue(buildMeta)) + featureFlagService.isFeatureEnabledFlow(FeatureFlags.Space).test { + assertThat(awaitItem()).isEqualTo(FeatureFlags.Space.defaultValue(buildMeta)) cancelAndIgnoreRemainingEvents() } } @@ -28,7 +28,7 @@ class DefaultFeatureFlagServiceTest { @Test fun `given service without provider when set enabled feature is called then it returns false`() = runTest { val featureFlagService = DefaultFeatureFlagService(emptySet(), aBuildMeta()) - val result = featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true) + val result = featureFlagService.setFeatureEnabled(FeatureFlags.Space, true) assertThat(result).isFalse() } @@ -37,7 +37,7 @@ class DefaultFeatureFlagServiceTest { val buildMeta = aBuildMeta() val featureFlagProvider = FakeMutableFeatureFlagProvider(0, buildMeta) val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider), buildMeta) - val result = featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true) + val result = featureFlagService.setFeatureEnabled(FeatureFlags.Space, true) assertThat(result).isTrue() } @@ -46,10 +46,10 @@ class DefaultFeatureFlagServiceTest { val buildMeta = aBuildMeta() val featureFlagProvider = FakeMutableFeatureFlagProvider(0, buildMeta) val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider), buildMeta) - featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true) - featureFlagService.isFeatureEnabledFlow(FeatureFlags.LocationSharing).test { + featureFlagService.setFeatureEnabled(FeatureFlags.Space, true) + featureFlagService.isFeatureEnabledFlow(FeatureFlags.Space).test { assertThat(awaitItem()).isTrue() - featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, false) + featureFlagService.setFeatureEnabled(FeatureFlags.Space, false) assertThat(awaitItem()).isFalse() } } @@ -60,9 +60,9 @@ class DefaultFeatureFlagServiceTest { val lowPriorityFeatureFlagProvider = FakeMutableFeatureFlagProvider(LOW_PRIORITY, buildMeta) val highPriorityFeatureFlagProvider = FakeMutableFeatureFlagProvider(HIGH_PRIORITY, buildMeta) val featureFlagService = DefaultFeatureFlagService(setOf(lowPriorityFeatureFlagProvider, highPriorityFeatureFlagProvider), buildMeta) - lowPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, false) - highPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, true) - featureFlagService.isFeatureEnabledFlow(FeatureFlags.LocationSharing).test { + lowPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.Space, false) + highPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.Space, true) + featureFlagService.isFeatureEnabledFlow(FeatureFlags.Space).test { assertThat(awaitItem()).isTrue() } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 4b546232a3..bb5ff45e15 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -14,7 +14,6 @@ import io.element.android.libraries.core.coroutine.childScope import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions -import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.ProgressCallback @@ -136,7 +135,6 @@ class RustMatrixClient( baseCacheDirectory: File, clock: SystemClock, timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, - featureFlagService: FeatureFlagService, ) : MatrixClient { override val sessionId: UserId = UserId(innerClient.userId()) override val deviceId: DeviceId = DeviceId(innerClient.deviceId()) @@ -205,7 +203,6 @@ class RustMatrixClient( roomContentForwarder = RoomContentForwarder(innerRoomListService), roomSyncSubscriber = roomSyncSubscriber, timelineEventTypeFilterFactory = timelineEventTypeFilterFactory, - featureFlagService = featureFlagService, roomMembershipObserver = roomMembershipObserver, roomInfoMapper = roomInfoMapper, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 6086da5d5b..2a4abe6dc2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -78,7 +78,7 @@ class RustMatrixClientFactory @Inject constructor( client.setUtdDelegate(UtdTracker(analyticsService)) val syncService = client.syncService() - .withSharePos(enable = featureFlagService.isFeatureEnabled(FeatureFlags.SharePos)) + .withSharePos(true) .withOfflineMode() .finish() @@ -93,7 +93,6 @@ class RustMatrixClientFactory @Inject constructor( baseCacheDirectory = cacheDirectory, clock = clock, timelineEventTypeFilterFactory = timelineEventTypeFilterFactory, - featureFlagService = featureFlagService, ).also { Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt index 889c583c4e..5edff19d84 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt @@ -11,7 +11,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.childScope import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions -import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomAlias @@ -84,7 +83,6 @@ class JoinedRustRoom( private val coroutineDispatchers: CoroutineDispatchers, private val systemClock: SystemClock, private val roomContentForwarder: RoomContentForwarder, - private val featureFlagService: FeatureFlagService, ) : JoinedRoom, BaseRoom by baseRoom { // Create a dispatcher for all room methods... private val roomDispatcher = coroutineDispatchers.io.limitedParallelism(32) @@ -478,7 +476,6 @@ class JoinedRustRoom( dispatcher = roomDispatcher, roomContentForwarder = roomContentForwarder, onNewSyncedEvent = onNewSyncedEvent, - featureFlagsService = featureFlagService, ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt index dd6a6e974f..e53ac5c478 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.matrix.impl.room import io.element.android.appconfig.TimelineConfig import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId @@ -49,7 +48,6 @@ class RustRoomFactory( private val innerRoomListService: InnerRoomListService, private val roomSyncSubscriber: RoomSyncSubscriber, private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, - private val featureFlagService: FeatureFlagService, private val roomMembershipObserver: RoomMembershipObserver, private val roomInfoMapper: RoomInfoMapper, ) { @@ -127,7 +125,6 @@ class RustRoomFactory( liveInnerTimeline = timeline, coroutineDispatchers = dispatchers, systemClock = systemClock, - featureFlagService = featureFlagService, ) ) } else { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 00f89e39a3..b1540d353d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -8,8 +8,6 @@ package io.element.android.libraries.matrix.impl.timeline import io.element.android.libraries.core.extensions.runCatchingExceptions -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId @@ -89,7 +87,6 @@ class RustTimeline( private val coroutineScope: CoroutineScope, private val dispatcher: CoroutineDispatcher, private val roomContentForwarder: RoomContentForwarder, - private val featureFlagsService: FeatureFlagService, onNewSyncedEvent: () -> Unit, ) : Timeline { private val _timelineItems: MutableSharedFlow> = @@ -342,7 +339,6 @@ class RustTimeline( progressCallback: ProgressCallback?, inReplyToEventId: EventId?, ): Result { - val useSendQueue = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue) return sendAttachment(listOfNotNull(file, thumbnailFile)) { inner.sendImage( params = UploadParameters( @@ -351,7 +347,7 @@ class RustTimeline( formattedCaption = formattedCaption?.let { FormattedBody(body = it, format = MessageFormat.Html) }, - useSendQueue = useSendQueue, + useSendQueue = true, mentions = null, inReplyTo = inReplyToEventId?.value, ), @@ -371,7 +367,6 @@ class RustTimeline( progressCallback: ProgressCallback?, inReplyToEventId: EventId?, ): Result { - val useSendQueue = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue) return sendAttachment(listOfNotNull(file, thumbnailFile)) { inner.sendVideo( params = UploadParameters( @@ -380,7 +375,7 @@ class RustTimeline( formattedCaption = formattedCaption?.let { FormattedBody(body = it, format = MessageFormat.Html) }, - useSendQueue = useSendQueue, + useSendQueue = true, mentions = null, inReplyTo = inReplyToEventId?.value, ), @@ -399,7 +394,6 @@ class RustTimeline( progressCallback: ProgressCallback?, inReplyToEventId: EventId?, ): Result { - val useSendQueue = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue) return sendAttachment(listOf(file)) { inner.sendAudio( params = UploadParameters( @@ -408,7 +402,7 @@ class RustTimeline( formattedCaption = formattedCaption?.let { FormattedBody(body = it, format = MessageFormat.Html) }, - useSendQueue = useSendQueue, + useSendQueue = true, mentions = null, inReplyTo = inReplyToEventId?.value, ), @@ -426,7 +420,6 @@ class RustTimeline( progressCallback: ProgressCallback?, inReplyToEventId: EventId?, ): Result { - val useSendQueue = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue) return sendAttachment(listOf(file)) { inner.sendFile( params = UploadParameters( @@ -435,7 +428,7 @@ class RustTimeline( formattedCaption = formattedCaption?.let { FormattedBody(body = it, format = MessageFormat.Html) }, - useSendQueue = useSendQueue, + useSendQueue = true, mentions = null, inReplyTo = inReplyToEventId?.value, ), @@ -489,7 +482,6 @@ class RustTimeline( progressCallback: ProgressCallback?, inReplyToEventId: EventId?, ): Result { - val useSendQueue = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue) return sendAttachment(listOf(file)) { inner.sendVoiceMessage( params = UploadParameters( @@ -497,7 +489,7 @@ class RustTimeline( // Maybe allow a caption in the future? caption = null, formattedCaption = null, - useSendQueue = useSendQueue, + useSendQueue = true, mentions = null, inReplyTo = inReplyToEventId?.value, ), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 91d0f06d1c..cb316452c5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -8,7 +8,6 @@ package io.element.android.libraries.matrix.impl import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiSyncService import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory @@ -67,6 +66,5 @@ class RustMatrixClientTest { baseCacheDirectory = File(""), clock = FakeSystemClock(), timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), - featureFlagService = FakeFeatureFlagService(), ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt index 3fea130ece..2819dd6ac7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt @@ -10,8 +10,6 @@ package io.element.android.libraries.matrix.impl.timeline import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline @@ -98,7 +96,6 @@ private fun TestScope.createRustTimeline( coroutineScope: CoroutineScope = backgroundScope, dispatcher: CoroutineDispatcher = testCoroutineDispatchers().io, roomContentForwarder: RoomContentForwarder = RoomContentForwarder(FakeFfiRoomListService()), - featureFlagsService: FeatureFlagService = FakeFeatureFlagService(), onNewSyncedEvent: () -> Unit = {}, ): RustTimeline { return RustTimeline( @@ -109,7 +106,6 @@ private fun TestScope.createRustTimeline( coroutineScope = coroutineScope, dispatcher = dispatcher, roomContentForwarder = roomContentForwarder, - featureFlagsService = featureFlagsService, onNewSyncedEvent = onNewSyncedEvent, ) } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 91e36de12c..1126a39466 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -91,7 +91,6 @@ import io.element.android.wysiwyg.compose.RichTextEditor import io.element.android.wysiwyg.display.TextDisplay import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.launch import uniffi.wysiwyg_composer.MenuAction import kotlin.time.Duration.Companion.seconds @@ -101,7 +100,6 @@ fun TextComposer( state: TextEditorState, voiceMessageState: VoiceMessageState, composerMode: MessageComposerMode, - enableVoiceMessages: Boolean, onRequestFocus: () -> Unit, onSendMessage: () -> Unit, onResetComposerMode: () -> Unit, @@ -141,8 +139,8 @@ fun TextComposer( } val layoutModifier = modifier - .fillMaxSize() - .height(IntrinsicSize.Min) + .fillMaxSize() + .height(IntrinsicSize.Min) val composerOptionsButton: @Composable () -> Unit = remember(composerMode) { @Composable { @@ -171,22 +169,17 @@ fun TextComposer( } else { stringResource(id = R.string.rich_text_editor_composer_placeholder) } - val textInput: @Composable () -> Unit = if ((composerMode as? MessageComposerMode.Attachment)?.allowCaption == false) { - { - // No text input when in attachment mode and caption not allowed. - } - } else { - when (state) { - is TextEditorState.Rich -> { - val coroutineScope = rememberCoroutineScope() - val view = LocalView.current - remember(state.richTextEditorState, composerMode, onResetComposerMode, onError) { - @Composable { - TextInputBox( - modifier = Modifier + val textInput: @Composable () -> Unit = when (state) { + is TextEditorState.Rich -> { + val coroutineScope = rememberCoroutineScope() + val view = LocalView.current + remember(state.richTextEditorState, composerMode, onResetComposerMode, onError) { + @Composable { + TextInputBox( + modifier = Modifier .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, + interactionSource = remember { MutableInteractionSource() }, + indication = null, ) { coroutineScope.launch { state.requestFocus() @@ -196,46 +189,45 @@ fun TextComposer( .semantics { hideFromAccessibility() }, - composerMode = composerMode, - onResetComposerMode = onResetComposerMode, - isTextEmpty = state.richTextEditorState.messageHtml.isEmpty(), - ) { - RichTextEditor( - state = state.richTextEditorState, - placeholder = placeholder, - registerStateUpdates = true, - modifier = Modifier + composerMode = composerMode, + onResetComposerMode = onResetComposerMode, + isTextEmpty = state.richTextEditorState.messageHtml.isEmpty(), + ) { + RichTextEditor( + state = state.richTextEditorState, + placeholder = placeholder, + registerStateUpdates = true, + modifier = Modifier .padding(top = 6.dp, bottom = 6.dp) .fillMaxWidth(), - style = ElementRichTextEditorStyle.composerStyle(hasFocus = state.richTextEditorState.hasFocus), - resolveMentionDisplay = resolveMentionDisplay, - resolveRoomMentionDisplay = resolveAtRoomMentionDisplay, - onError = onError, - onRichContentSelected = onSelectRichContent, - onTyping = onTyping, - ) - } + style = ElementRichTextEditorStyle.composerStyle(hasFocus = state.richTextEditorState.hasFocus), + resolveMentionDisplay = resolveMentionDisplay, + resolveRoomMentionDisplay = resolveAtRoomMentionDisplay, + onError = onError, + onRichContentSelected = onSelectRichContent, + onTyping = onTyping, + ) } } } - is TextEditorState.Markdown -> { - @Composable { - val style = ElementRichTextEditorStyle.composerStyle(hasFocus = state.hasFocus()) - TextInputBox( - composerMode = composerMode, - onResetComposerMode = onResetComposerMode, - isTextEmpty = state.state.text.value().isEmpty(), - ) { - MarkdownTextInput( - state = state.state, - placeholder = placeholder, - placeholderColor = ElementTheme.colors.textSecondary, - onTyping = onTyping, - onReceiveSuggestion = onReceiveSuggestion, - richTextEditorStyle = style, - onSelectRichContent = onSelectRichContent, - ) - } + } + is TextEditorState.Markdown -> { + @Composable { + val style = ElementRichTextEditorStyle.composerStyle(hasFocus = state.hasFocus()) + TextInputBox( + composerMode = composerMode, + onResetComposerMode = onResetComposerMode, + isTextEmpty = state.state.text.value().isEmpty(), + ) { + MarkdownTextInput( + state = state.state, + placeholder = placeholder, + placeholderColor = ElementTheme.colors.textSecondary, + onTyping = onTyping, + onReceiveSuggestion = onReceiveSuggestion, + richTextEditorStyle = style, + onSelectRichContent = onSelectRichContent, + ) } } } @@ -273,7 +265,7 @@ fun TextComposer( } val sendOrRecordButton = when { - enableVoiceMessages && !canSendMessage -> + !canSendMessage -> when (voiceMessageState) { VoiceMessageState.Idle, is VoiceMessageState.Recording -> recordVoiceButton @@ -288,7 +280,6 @@ fun TextComposer( val endButtonA11y = endButtonA11y( composerMode = composerMode, voiceMessageState = voiceMessageState, - enableVoiceMessages = enableVoiceMessages, canSendMessage = canSendMessage, ) @@ -341,7 +332,6 @@ fun TextComposer( } else { StandardLayout( voiceMessageState = voiceMessageState, - enableVoiceMessages = enableVoiceMessages, isRoomEncrypted = state.isRoomEncrypted, modifier = layoutModifier, composerOptionsButton = composerOptionsButton, @@ -378,12 +368,11 @@ fun TextComposer( private fun endButtonA11y( composerMode: MessageComposerMode, voiceMessageState: VoiceMessageState, - enableVoiceMessages: Boolean, canSendMessage: Boolean, ): (SemanticsPropertyReceiver) -> Unit { val a11ySendButtonDescription = stringResource( id = when { - enableVoiceMessages && !canSendMessage -> + !canSendMessage -> when (voiceMessageState) { VoiceMessageState.Idle, is VoiceMessageState.Recording -> if (voiceMessageState is VoiceMessageState.Recording) { @@ -410,7 +399,6 @@ private fun endButtonA11y( @Composable private fun StandardLayout( voiceMessageState: VoiceMessageState, - enableVoiceMessages: Boolean, isRoomEncrypted: Boolean?, textInput: @Composable () -> Unit, composerOptionsButton: @Composable () -> Unit, @@ -427,12 +415,12 @@ private fun StandardLayout( Spacer(Modifier.height(4.dp)) } Row(verticalAlignment = Alignment.Bottom) { - if (enableVoiceMessages && voiceMessageState !is VoiceMessageState.Idle) { + if (voiceMessageState !is VoiceMessageState.Idle) { if (voiceMessageState is VoiceMessageState.Preview || voiceMessageState is VoiceMessageState.Recording) { Box( modifier = Modifier - .padding(bottom = 5.dp, top = 5.dp, end = 3.dp, start = 3.dp) - .size(48.dp), + .padding(bottom = 5.dp, top = 5.dp, end = 3.dp, start = 3.dp) + .size(48.dp), contentAlignment = Alignment.Center, ) { voiceDeleteButton() @@ -442,8 +430,8 @@ private fun StandardLayout( } Box( modifier = Modifier - .padding(bottom = 8.dp, top = 8.dp) - .weight(1f) + .padding(bottom = 8.dp, top = 8.dp) + .weight(1f) ) { voiceRecording() } @@ -456,17 +444,17 @@ private fun StandardLayout( } Box( modifier = Modifier - .padding(bottom = 8.dp, top = 8.dp) - .weight(1f) + .padding(bottom = 8.dp, top = 8.dp) + .weight(1f) ) { textInput() } } Box( Modifier - .padding(bottom = 5.dp, top = 5.dp, end = 6.dp, start = 6.dp) - .size(48.dp) - .clearAndSetSemantics(endButtonA11y), + .padding(bottom = 5.dp, top = 5.dp, end = 6.dp, start = 6.dp) + .size(48.dp) + .clearAndSetSemantics(endButtonA11y), contentAlignment = Alignment.Center, ) { endButton() @@ -517,8 +505,8 @@ private fun TextFormattingLayout( } Box( modifier = Modifier - .weight(1f) - .padding(horizontal = 12.dp) + .weight(1f) + .padding(horizontal = 12.dp) ) { textInput() } @@ -537,11 +525,11 @@ private fun TextFormattingLayout( } Box( modifier = Modifier - .padding( - start = 14.dp, - end = 6.dp, - ) - .clearAndSetSemantics(endButtonA11y) + .padding( + start = 14.dp, + end = 6.dp, + ) + .clearAndSetSemantics(endButtonA11y) ) { sendButton() } @@ -563,12 +551,12 @@ private fun TextInputBox( Column( modifier = Modifier - .clip(roundedCorners) - .border(0.5.dp, borderColor, roundedCorners) - .background(color = bgColor) - .requiredHeightIn(min = 42.dp) - .fillMaxSize() - .then(modifier), + .clip(roundedCorners) + .border(0.5.dp, borderColor, roundedCorners) + .background(color = bgColor) + .requiredHeightIn(min = 42.dp) + .fillMaxSize() + .then(modifier), ) { if (composerMode is MessageComposerMode.Special) { ComposerModeView( @@ -578,8 +566,8 @@ private fun TextInputBox( } Box( modifier = Modifier - .padding(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp) - .then(Modifier.testTag(TestTags.textEditor)), + .padding(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp) + .then(Modifier.testTag(TestTags.textEditor)), contentAlignment = Alignment.CenterStart, ) { textInput() @@ -587,9 +575,9 @@ private fun TextInputBox( var showBottomSheet by remember { mutableStateOf(false) } Icon( modifier = Modifier - .clickable { showBottomSheet = true } - .padding(horizontal = 8.dp, vertical = 4.dp) - .align(Alignment.CenterEnd), + .clickable { showBottomSheet = true } + .padding(horizontal = 8.dp, vertical = 4.dp) + .align(Alignment.CenterEnd), imageVector = CompoundIcons.InfoSolid(), tint = ElementTheme.colors.iconCriticalPrimary, contentDescription = null, @@ -631,12 +619,11 @@ private fun aTextEditorStateRichList(isRoomEncrypted: Boolean? = null) = persist internal fun TextComposerSimplePreview() = ElementPreview { PreviewColumn( items = aTextEditorStateMarkdownList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = MessageComposerMode.Normal, - enableVoiceMessages = true, ) } } @@ -646,12 +633,11 @@ internal fun TextComposerSimplePreview() = ElementPreview { internal fun TextComposerSimpleNotEncryptedPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateMarkdownList(isRoomEncrypted = false), - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = MessageComposerMode.Normal, - enableVoiceMessages = true, ) } } @@ -661,13 +647,12 @@ internal fun TextComposerSimpleNotEncryptedPreview() = ElementPreview { internal fun TextComposerFormattingPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, showTextFormatting = true, composerMode = MessageComposerMode.Normal, - enableVoiceMessages = true, ) } } @@ -677,13 +662,12 @@ internal fun TextComposerFormattingPreview() = ElementPreview { internal fun TextComposerFormattingNotEncryptedPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList(isRoomEncrypted = false) - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, showTextFormatting = true, composerMode = MessageComposerMode.Normal, - enableVoiceMessages = true, ) } } @@ -693,12 +677,11 @@ internal fun TextComposerFormattingNotEncryptedPreview() = ElementPreview { internal fun TextComposerEditPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = aMessageComposerModeEdit(), - enableVoiceMessages = true, ) } } @@ -708,12 +691,11 @@ internal fun TextComposerEditPreview() = ElementPreview { internal fun TextComposerEditNotEncryptedPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList(isRoomEncrypted = false) - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = aMessageComposerModeEdit(), - enableVoiceMessages = true, ) } } @@ -723,7 +705,7 @@ internal fun TextComposerEditNotEncryptedPreview() = ElementPreview { internal fun TextComposerEditCaptionPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -731,7 +713,6 @@ internal fun TextComposerEditCaptionPreview() = ElementPreview { // Set an existing caption so that the UI will be in edit caption mode content = "An existing caption", ), - enableVoiceMessages = false, ) } } @@ -741,16 +722,14 @@ internal fun TextComposerEditCaptionPreview() = ElementPreview { internal fun TextComposerAddCaptionPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { index, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = aMessageComposerModeEditCaption( // No caption so that the UI will be in add caption mode content = "", - showCompatibilityWarning = index == 0, ), - enableVoiceMessages = false, ) } } @@ -760,12 +739,11 @@ internal fun TextComposerAddCaptionPreview() = ElementPreview { internal fun MarkdownTextComposerEditPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateMarkdownList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = aMessageComposerModeEdit(), - enableVoiceMessages = true, ) } } @@ -775,14 +753,13 @@ internal fun MarkdownTextComposerEditPreview() = ElementPreview { internal fun TextComposerReplyPreview(@PreviewParameter(InReplyToDetailsProvider::class) inReplyToDetails: InReplyToDetails) = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = aMessageComposerModeReply( replyToDetails = inReplyToDetails, ), - enableVoiceMessages = true, ) } } @@ -800,14 +777,13 @@ internal fun TextComposerReplyPreview(@PreviewParameter(InReplyToDetailsProvider internal fun TextComposerReplyNotEncryptedPreview(@PreviewParameter(InReplyToDetailsProvider::class) inReplyToDetails: InReplyToDetails) = ElementPreview { PreviewColumn( items = aTextEditorStateRichList(isRoomEncrypted = false) - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, composerMode = aMessageComposerModeReply( replyToDetails = inReplyToDetails, ), - enableVoiceMessages = true, ) } } @@ -817,16 +793,12 @@ internal fun TextComposerReplyNotEncryptedPreview(@PreviewParameter(InReplyToDet internal fun TextComposerCaptionPreview() = ElementPreview { val list = aTextEditorStateMarkdownList() PreviewColumn( - items = (list + aTextEditorStateMarkdown(initialText = "NO_CAPTION", initialFocus = true)).toPersistentList() - ) { index, textEditorState -> + items = list, + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, - composerMode = MessageComposerMode.Attachment( - allowCaption = index < list.size, - showCaptionCompatibilityWarning = index == 0, - ), - enableVoiceMessages = false, + composerMode = MessageComposerMode.Attachment, ) } } @@ -862,12 +834,11 @@ internal fun TextComposerVoicePreview() = ElementPreview { playbackProgress = 0.0f ), ) - ) { _, voiceMessageState -> + ) { voiceMessageState -> ATextComposer( state = aTextEditorStateRich(initialFocus = true), voiceMessageState = voiceMessageState, composerMode = MessageComposerMode.Normal, - enableVoiceMessages = true, ) } } @@ -903,12 +874,11 @@ internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview { playbackProgress = 0.0f ), ) - ) { _, voiceMessageState -> + ) { voiceMessageState -> ATextComposer( state = aTextEditorStateRich(initialFocus = true, isRoomEncrypted = false), voiceMessageState = voiceMessageState, composerMode = MessageComposerMode.Normal, - enableVoiceMessages = true, ) } } @@ -916,15 +886,15 @@ internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview { @Composable private fun PreviewColumn( items: ImmutableList, - view: @Composable (Int, T) -> Unit, + view: @Composable (T) -> Unit, ) { Column { - items.forEachIndexed { index, item -> + items.forEach { item -> HorizontalDivider() Box( modifier = Modifier.height(IntrinsicSize.Min) ) { - view(index, item) + view(item) } } } @@ -935,7 +905,6 @@ private fun ATextComposer( state: TextEditorState, voiceMessageState: VoiceMessageState, composerMode: MessageComposerMode, - enableVoiceMessages: Boolean, showTextFormatting: Boolean = false, ) { TextComposer( @@ -943,7 +912,6 @@ private fun ATextComposer( showTextFormatting = showTextFormatting, voiceMessageState = voiceMessageState, composerMode = composerMode, - enableVoiceMessages = enableVoiceMessages, onRequestFocus = {}, onSendMessage = {}, onResetComposerMode = {}, @@ -973,11 +941,9 @@ fun aMessageComposerModeEdit( fun aMessageComposerModeEditCaption( eventOrTransactionId: EventOrTransactionId = EventId("$1234").toEventOrTransactionId(), content: String, - showCompatibilityWarning: Boolean = false, ) = MessageComposerMode.EditCaption( eventOrTransactionId = eventOrTransactionId, content = content, - showCaptionCompatibilityWarning = showCompatibilityWarning, ) fun aMessageComposerModeReply( diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt index 2fa596e875..002fefec62 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt @@ -18,10 +18,7 @@ import io.element.android.libraries.matrix.ui.messages.reply.eventId sealed interface MessageComposerMode { data object Normal : MessageComposerMode - data class Attachment( - val allowCaption: Boolean, - val showCaptionCompatibilityWarning: Boolean, - ) : MessageComposerMode + data object Attachment : MessageComposerMode sealed interface Special : MessageComposerMode @@ -33,7 +30,6 @@ sealed interface MessageComposerMode { data class EditCaption( val eventOrTransactionId: EventOrTransactionId, val content: String, - val showCaptionCompatibilityWarning: Boolean, ) : Special data class Reply( @@ -58,8 +54,8 @@ sealed interface MessageComposerMode { fun MessageComposerMode.showCaptionCompatibilityWarning(): Boolean { return when (this) { - is MessageComposerMode.Attachment -> showCaptionCompatibilityWarning - is MessageComposerMode.EditCaption -> showCaptionCompatibilityWarning && content.isEmpty() + is MessageComposerMode.Attachment -> true + is MessageComposerMode.EditCaption -> content.isEmpty() else -> false } } diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_10_en.png deleted file mode 100644 index 23c8cbc45b..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_10_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dbeb0287f75afc662c28cca13fe39f9d24e67ee5b507cf976324d5d9dd4c381b -size 83505 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png index 78b7a33606..8b48d015f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba8fe03e073a2279c68c49c25388568182ddb1da1e20d7df1ce72d150df51d86 -size 395881 +oid sha256:b8119afe2e6a12bd41f8e838461c9e3f311ed0b5e5ce3c524a70226feb120996 +size 72836 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_7_en.png index 8cb4e5d4f9..fefd103edb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:400426592b0020e5de30899574ce0abb70cebccbcff10c43728ee6dae4a421f3 -size 400259 +oid sha256:8e0cf2a3fc5f92c5b7e8caff9e60ad9495ba1703dbb160aa64f9fd0a1bd4822f +size 406105 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_8_en.png index 8b48d015f0..23c8cbc45b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8119afe2e6a12bd41f8e838461c9e3f311ed0b5e5ce3c524a70226feb120996 -size 72836 +oid sha256:dbeb0287f75afc662c28cca13fe39f9d24e67ee5b507cf976324d5d9dd4c381b +size 83505 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_9_en.png deleted file mode 100644 index fefd103edb..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_9_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e0cf2a3fc5f92c5b7e8caff9e60ad9495ba1703dbb160aa64f9fd0a1bd4822f -size 406105 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png index 1d53e616bf..619f22f360 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55a3aa36196ff755f207e47abb3060a4727a6baa79fe02ce5f5a62d3648619b5 -size 53661 +oid sha256:4d33345e7d8cb2a55e6d291ae9dcabe66c8ec1ea4124ebc32b679566e585ca0e +size 54020 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png index 6ec843bdff..e2ef3acc25 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c8cd2e6427bc0ffacca88900511cb3761e7bf57fcafb3dbc9ec7f519ec8349d -size 51678 +oid sha256:a6af3cf20ad9b57abbe61107f758c143a676dec960fdf583b517d18e404411a3 +size 51953 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png index 8f01f227dd..5a1a036cf9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d9c7a841dbe183f84c8527a8745d30aaeee6d7b4aa8a472794b7b4d739b21cd -size 47268 +oid sha256:936a9e86eddcb00e20de8af1fe60ae2153c3dfa384f8070466026969a34eb057 +size 45074 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png index 4bb783fb04..718abc20fd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8275ab2ec26aed30fc162be1d5b49d6b9e9d73c303b00220ac91306dd04280e -size 45645 +oid sha256:dee196ccc9872a15897426f2581c178ff92a393136aefc5f7342ba1984d8e418 +size 43492 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png index 8d4fe5ebfd..dae95c00b8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59d57f02efee0ab0f413e3d14d22d069862143e9d6d69fb29fa6972348356016 -size 52332 +oid sha256:dea3e3f516afb98543f458e0db6472a7157428e25d8170bee6abbc505ece7bd7 +size 52677 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png index a2ac20fad5..cc6c7917b2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae8804def7f6922e29ee4564f96d490d233909d6383dc5b92ed091d239ffb609 -size 50797 +oid sha256:8ff7e86b3aefc4092514c0312a91747ac0a8a3f90234ca9774cd52ab90eeab17 +size 51072