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 d3a27916ef..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, @@ -443,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) @@ -457,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/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 56c654872f..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 @@ -39,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 @@ -63,7 +61,6 @@ class DefaultActionListPresenter @AssistedInject constructor( private val appPreferencesStore: AppPreferencesStore, private val room: BaseRoom, private val userSendFailureFactory: VerifiedUserSendFailureFactory, - private val featureFlagService: FeatureFlagService, private val dateFormatter: DateFormatter, ) : ActionListPresenter { @AssistedFactory @@ -166,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) 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..e84de00ba4 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 @@ -86,13 +85,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) } @@ -238,8 +230,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() - 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 7019f93ff2..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 @@ -603,57 +601,6 @@ class ActionListPresenterTest { } } - @Test - fun `present - compute for a media item - caption disabled`() = runTest { - val presenter = createActionListPresenter( - isDeveloperModeEnabled = 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) @@ -1298,7 +1245,6 @@ class ActionListPresenterTest { private fun createActionListPresenter( isDeveloperModeEnabled: Boolean, room: BaseRoom = FakeBaseRoom(), - allowCaption: Boolean = true, ): ActionListPresenter { val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) return DefaultActionListPresenter( @@ -1306,11 +1252,6 @@ private fun createActionListPresenter( appPreferencesStore = preferencesStore, 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..a2d5359366 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 @@ -84,34 +84,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 +118,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 +159,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 +193,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 +224,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 +252,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 +273,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 +307,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 +350,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 +391,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) @@ -460,7 +425,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)) val failureState = awaitItem() @@ -492,7 +456,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)) @@ -516,7 +479,6 @@ class AttachmentsPreviewPresenterTest { }.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)) @@ -546,7 +508,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) @@ -673,8 +634,6 @@ class AttachmentsPreviewPresenterTest { temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(), onDoneListener: OnDoneListener = OnDoneListener { lambdaError() }, mediaUploadOnSendQueueEnabled: Boolean = true, - allowCaption: Boolean = true, - showCaptionCompatibilityWarning: Boolean = true, displayMediaQualitySelectorViews: Boolean = false, mediaOptimizationSelectorPresenterFactory: FakeMediaOptimizationSelectorPresenterFactory = FakeMediaOptimizationSelectorPresenterFactory( fakePresenter = { @@ -701,8 +660,6 @@ class AttachmentsPreviewPresenterTest { featureFlagService = FakeFeatureFlagService( initialState = mapOf( FeatureFlags.MediaUploadOnSendQueue.key to mediaUploadOnSendQueueEnabled, - FeatureFlags.MediaCaptionCreation.key to allowCaption, - FeatureFlags.MediaCaptionWarning.key to showCaptionCompatibilityWarning, ), ), sessionCoroutineScope = this, 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 9a98438566..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 @@ -1585,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/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 76879b927b..552d23c712 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 @@ -82,20 +82,6 @@ enum class FeatureFlags( 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, - ), PrintLogsToLogcat( key = "feature.print_logs_to_logcat", title = "Print logs to logcat", 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 722c1f8a50..af13ad3821 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 @@ -140,8 +140,8 @@ fun TextComposer( } val layoutModifier = modifier - .fillMaxSize() - .height(IntrinsicSize.Min) + .fillMaxSize() + .height(IntrinsicSize.Min) val composerOptionsButton: @Composable () -> Unit = remember(composerMode) { @Composable { @@ -170,22 +170,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() @@ -195,46 +190,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, + ) } } } @@ -426,8 +420,8 @@ private fun StandardLayout( 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() @@ -437,8 +431,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() } @@ -451,17 +445,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() @@ -512,8 +506,8 @@ private fun TextFormattingLayout( } Box( modifier = Modifier - .weight(1f) - .padding(horizontal = 12.dp) + .weight(1f) + .padding(horizontal = 12.dp) ) { textInput() } @@ -532,11 +526,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() } @@ -558,12 +552,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( @@ -573,8 +567,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() @@ -582,9 +576,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, @@ -626,7 +620,7 @@ private fun aTextEditorStateRichList(isRoomEncrypted: Boolean? = null) = persist internal fun TextComposerSimplePreview() = ElementPreview { PreviewColumn( items = aTextEditorStateMarkdownList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -640,7 +634,7 @@ internal fun TextComposerSimplePreview() = ElementPreview { internal fun TextComposerSimpleNotEncryptedPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateMarkdownList(isRoomEncrypted = false), - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -654,7 +648,7 @@ internal fun TextComposerSimpleNotEncryptedPreview() = ElementPreview { internal fun TextComposerFormattingPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -669,7 +663,7 @@ internal fun TextComposerFormattingPreview() = ElementPreview { internal fun TextComposerFormattingNotEncryptedPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList(isRoomEncrypted = false) - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -684,7 +678,7 @@ internal fun TextComposerFormattingNotEncryptedPreview() = ElementPreview { internal fun TextComposerEditPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -698,7 +692,7 @@ internal fun TextComposerEditPreview() = ElementPreview { internal fun TextComposerEditNotEncryptedPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList(isRoomEncrypted = false) - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -712,7 +706,7 @@ internal fun TextComposerEditNotEncryptedPreview() = ElementPreview { internal fun TextComposerEditCaptionPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -729,14 +723,13 @@ 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, ), ) } @@ -747,7 +740,7 @@ internal fun TextComposerAddCaptionPreview() = ElementPreview { internal fun MarkdownTextComposerEditPreview() = ElementPreview { PreviewColumn( items = aTextEditorStateMarkdownList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -761,7 +754,7 @@ internal fun MarkdownTextComposerEditPreview() = ElementPreview { internal fun TextComposerReplyPreview(@PreviewParameter(InReplyToDetailsProvider::class) inReplyToDetails: InReplyToDetails) = ElementPreview { PreviewColumn( items = aTextEditorStateRichList() - ) { _, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, @@ -785,7 +778,7 @@ 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, @@ -802,14 +795,11 @@ internal fun TextComposerCaptionPreview() = ElementPreview { val list = aTextEditorStateMarkdownList() PreviewColumn( items = (list + aTextEditorStateMarkdown(initialText = "NO_CAPTION", initialFocus = true)).toPersistentList() - ) { index, textEditorState -> + ) { textEditorState -> ATextComposer( state = textEditorState, voiceMessageState = VoiceMessageState.Idle, - composerMode = MessageComposerMode.Attachment( - allowCaption = index < list.size, - showCaptionCompatibilityWarning = index == 0, - ), + composerMode = MessageComposerMode.Attachment, ) } } @@ -845,7 +835,7 @@ internal fun TextComposerVoicePreview() = ElementPreview { playbackProgress = 0.0f ), ) - ) { _, voiceMessageState -> + ) { voiceMessageState -> ATextComposer( state = aTextEditorStateRich(initialFocus = true), voiceMessageState = voiceMessageState, @@ -885,7 +875,7 @@ internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview { playbackProgress = 0.0f ), ) - ) { _, voiceMessageState -> + ) { voiceMessageState -> ATextComposer( state = aTextEditorStateRich(initialFocus = true, isRoomEncrypted = false), voiceMessageState = voiceMessageState, @@ -897,15 +887,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) } } } @@ -952,11 +942,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 } }