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 2a1ea9dd51..16698d7e34 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 @@ -245,6 +245,7 @@ class MessagesPresenter @AssistedInject constructor( canRedactOwn = userHasPermissionToRedactOwn, canRedactOther = userHasPermissionToRedactOther, canSendReaction = userHasPermissionToSendReaction, + canPin = false, ) } } @@ -283,6 +284,7 @@ class MessagesPresenter @AssistedInject constructor( TimelineItemAction.Forward -> handleForwardAction(targetEvent) TimelineItemAction.ReportContent -> handleReportAction(targetEvent) TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent, timelineState) + TimelineItemAction.Pin -> Timber.d("Pin action not implemented") } } 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 082edb1ca3..61f2189cc6 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 @@ -144,11 +144,13 @@ fun aUserEventPermissions( canRedactOther: Boolean = false, canSendMessage: Boolean = true, canSendReaction: Boolean = true, + canPin: Boolean = false, ) = UserEventPermissions( canRedactOwn = canRedactOwn, canRedactOther = canRedactOther, canSendMessage = canSendMessage, canSendReaction = canSendReaction, + canPin = canPin, ) fun aReactionSummaryState( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt index 84b60ae228..c75054be3a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt @@ -25,4 +25,5 @@ data class UserEventPermissions( val canRedactOther: Boolean, val canSendMessage: Boolean, val canSendReaction: Boolean, + val canPin: Boolean, ) 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 0f4379cffb..3387373734 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 @@ -36,6 +36,8 @@ import io.element.android.features.messages.impl.timeline.model.event.canBeCopie import io.element.android.features.messages.impl.timeline.model.event.canBeForwarded import io.element.android.features.messages.impl.timeline.model.event.canReact import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.preferences.api.store.AppPreferencesStore import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope @@ -44,6 +46,7 @@ import javax.inject.Inject class ActionListPresenter @Inject constructor( private val appPreferencesStore: AppPreferencesStore, + private val featureFlagsService: FeatureFlagService, ) : Presenter { @Composable override fun present(): ActionListState { @@ -54,6 +57,7 @@ class ActionListPresenter @Inject constructor( } val isDeveloperModeEnabled by appPreferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false) + val isPinnedEventsEnabled by featureFlagsService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) fun handleEvents(event: ActionListEvents) { when (event) { @@ -62,6 +66,7 @@ class ActionListPresenter @Inject constructor( timelineItem = event.event, usersEventPermissions = event.userEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, + isPinnedEventsEnabled = isPinnedEventsEnabled, target = target, ) } @@ -77,6 +82,7 @@ class ActionListPresenter @Inject constructor( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, + isPinnedEventsEnabled: Boolean, target: MutableState ) = launch { target.value = ActionListState.Target.Loading(timelineItem) @@ -85,6 +91,7 @@ class ActionListPresenter @Inject constructor( timelineItem = timelineItem, usersEventPermissions = usersEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, + isPinnedEventsEnabled = isPinnedEventsEnabled, ) val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.isRemote && @@ -105,6 +112,7 @@ private fun buildActions( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, isDeveloperModeEnabled: Boolean, + isPinnedEventsEnabled: Boolean, ): List { val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther return buildList { @@ -124,6 +132,11 @@ private fun buildActions( if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) { add(TimelineItemAction.EndPoll) } + // TODO: handle unpin + val canPin = isPinnedEventsEnabled && usersEventPermissions.canPin && timelineItem.isRemote + if (canPin) { + add(TimelineItemAction.Pin) + } if (timelineItem.content.canBeCopied()) { add(TimelineItemAction.Copy) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index f61e6197c2..e8da131d8d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -39,4 +39,5 @@ sealed class TimelineItemAction( data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, CommonDrawables.ic_developer_options) data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, CompoundDrawables.ic_compound_chat_problem, destructive = true) data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, CompoundDrawables.ic_compound_polls_end) + data object Pin : TimelineItemAction(CommonStrings.action_pin, CompoundDrawables.ic_compound_pin) } 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 6b06adeb03..74eccd00ca 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 @@ -958,7 +958,8 @@ class MessagesPresenterTest { return timelinePresenter } } - val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore) + val featureFlagService = FakeFeatureFlagService() + val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore, featureFlagsService = featureFlagService) val typingNotificationPresenter = TypingNotificationPresenter( room = matrixRoom, sessionPreferencesStore = sessionPreferencesStore, @@ -981,7 +982,7 @@ class MessagesPresenterTest { snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, clipboardHelper = clipboardHelper, - featureFlagsService = FakeFeatureFlagService(), + featureFlagsService = featureFlagService, buildMeta = aBuildMeta(), dispatchers = coroutineDispatchers, htmlConverterProvider = FakeHtmlConverterProvider(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 446c36f74c..17a051ba9b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -169,6 +169,7 @@ class MessagesViewTest { userHasPermissionToRedactOwn: Boolean = false, userHasPermissionToRedactOther: Boolean = false, userHasPermissionToSendReaction: Boolean = false, + userCanPinEvent: Boolean = false, ) { val eventsRecorder = EventsRecorder() val state = aMessagesState( @@ -180,6 +181,7 @@ class MessagesViewTest { canRedactOwn = userHasPermissionToRedactOwn, canRedactOther = userHasPermissionToRedactOther, canSendReaction = userHasPermissionToSendReaction, + canPin = userCanPinEvent, ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event 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 716c133c0a..5bd16bfe61 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 @@ -835,5 +835,6 @@ class ActionListPresenterTest { private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) - return ActionListPresenter(appPreferencesStore = preferencesStore) + val featureFlagsService = FakeFeatureFlagService() + return ActionListPresenter(appPreferencesStore = preferencesStore, featureFlagsService = featureFlagsService) }