Pinned event: add action on timeline

This commit is contained in:
ganfra 2024-07-26 18:20:17 +02:00
parent 3adc6d0be8
commit 233a1ff09e
8 changed files with 26 additions and 3 deletions

View file

@ -245,6 +245,7 @@ class MessagesPresenter @AssistedInject constructor(
canRedactOwn = userHasPermissionToRedactOwn, canRedactOwn = userHasPermissionToRedactOwn,
canRedactOther = userHasPermissionToRedactOther, canRedactOther = userHasPermissionToRedactOther,
canSendReaction = userHasPermissionToSendReaction, canSendReaction = userHasPermissionToSendReaction,
canPin = false,
) )
} }
} }
@ -283,6 +284,7 @@ class MessagesPresenter @AssistedInject constructor(
TimelineItemAction.Forward -> handleForwardAction(targetEvent) TimelineItemAction.Forward -> handleForwardAction(targetEvent)
TimelineItemAction.ReportContent -> handleReportAction(targetEvent) TimelineItemAction.ReportContent -> handleReportAction(targetEvent)
TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent, timelineState) TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent, timelineState)
TimelineItemAction.Pin -> Timber.d("Pin action not implemented")
} }
} }

View file

@ -144,11 +144,13 @@ fun aUserEventPermissions(
canRedactOther: Boolean = false, canRedactOther: Boolean = false,
canSendMessage: Boolean = true, canSendMessage: Boolean = true,
canSendReaction: Boolean = true, canSendReaction: Boolean = true,
canPin: Boolean = false,
) = UserEventPermissions( ) = UserEventPermissions(
canRedactOwn = canRedactOwn, canRedactOwn = canRedactOwn,
canRedactOther = canRedactOther, canRedactOther = canRedactOther,
canSendMessage = canSendMessage, canSendMessage = canSendMessage,
canSendReaction = canSendReaction, canSendReaction = canSendReaction,
canPin = canPin,
) )
fun aReactionSummaryState( fun aReactionSummaryState(

View file

@ -25,4 +25,5 @@ data class UserEventPermissions(
val canRedactOther: Boolean, val canRedactOther: Boolean,
val canSendMessage: Boolean, val canSendMessage: Boolean,
val canSendReaction: Boolean, val canSendReaction: Boolean,
val canPin: Boolean,
) )

View file

@ -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.canBeForwarded
import io.element.android.features.messages.impl.timeline.model.event.canReact import io.element.android.features.messages.impl.timeline.model.event.canReact
import io.element.android.libraries.architecture.Presenter 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 io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -44,6 +46,7 @@ import javax.inject.Inject
class ActionListPresenter @Inject constructor( class ActionListPresenter @Inject constructor(
private val appPreferencesStore: AppPreferencesStore, private val appPreferencesStore: AppPreferencesStore,
private val featureFlagsService: FeatureFlagService,
) : Presenter<ActionListState> { ) : Presenter<ActionListState> {
@Composable @Composable
override fun present(): ActionListState { override fun present(): ActionListState {
@ -54,6 +57,7 @@ class ActionListPresenter @Inject constructor(
} }
val isDeveloperModeEnabled by appPreferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false) val isDeveloperModeEnabled by appPreferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false)
val isPinnedEventsEnabled by featureFlagsService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false)
fun handleEvents(event: ActionListEvents) { fun handleEvents(event: ActionListEvents) {
when (event) { when (event) {
@ -62,6 +66,7 @@ class ActionListPresenter @Inject constructor(
timelineItem = event.event, timelineItem = event.event,
usersEventPermissions = event.userEventPermissions, usersEventPermissions = event.userEventPermissions,
isDeveloperModeEnabled = isDeveloperModeEnabled, isDeveloperModeEnabled = isDeveloperModeEnabled,
isPinnedEventsEnabled = isPinnedEventsEnabled,
target = target, target = target,
) )
} }
@ -77,6 +82,7 @@ class ActionListPresenter @Inject constructor(
timelineItem: TimelineItem.Event, timelineItem: TimelineItem.Event,
usersEventPermissions: UserEventPermissions, usersEventPermissions: UserEventPermissions,
isDeveloperModeEnabled: Boolean, isDeveloperModeEnabled: Boolean,
isPinnedEventsEnabled: Boolean,
target: MutableState<ActionListState.Target> target: MutableState<ActionListState.Target>
) = launch { ) = launch {
target.value = ActionListState.Target.Loading(timelineItem) target.value = ActionListState.Target.Loading(timelineItem)
@ -85,6 +91,7 @@ class ActionListPresenter @Inject constructor(
timelineItem = timelineItem, timelineItem = timelineItem,
usersEventPermissions = usersEventPermissions, usersEventPermissions = usersEventPermissions,
isDeveloperModeEnabled = isDeveloperModeEnabled, isDeveloperModeEnabled = isDeveloperModeEnabled,
isPinnedEventsEnabled = isPinnedEventsEnabled,
) )
val displayEmojiReactions = usersEventPermissions.canSendReaction && val displayEmojiReactions = usersEventPermissions.canSendReaction &&
timelineItem.isRemote && timelineItem.isRemote &&
@ -105,6 +112,7 @@ private fun buildActions(
timelineItem: TimelineItem.Event, timelineItem: TimelineItem.Event,
usersEventPermissions: UserEventPermissions, usersEventPermissions: UserEventPermissions,
isDeveloperModeEnabled: Boolean, isDeveloperModeEnabled: Boolean,
isPinnedEventsEnabled: Boolean,
): List<TimelineItemAction> { ): List<TimelineItemAction> {
val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther
return buildList { return buildList {
@ -124,6 +132,11 @@ private fun buildActions(
if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) { if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) {
add(TimelineItemAction.EndPoll) add(TimelineItemAction.EndPoll)
} }
// TODO: handle unpin
val canPin = isPinnedEventsEnabled && usersEventPermissions.canPin && timelineItem.isRemote
if (canPin) {
add(TimelineItemAction.Pin)
}
if (timelineItem.content.canBeCopied()) { if (timelineItem.content.canBeCopied()) {
add(TimelineItemAction.Copy) add(TimelineItemAction.Copy)
} }

View file

@ -39,4 +39,5 @@ sealed class TimelineItemAction(
data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, CommonDrawables.ic_developer_options) 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 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 EndPoll : TimelineItemAction(CommonStrings.action_end_poll, CompoundDrawables.ic_compound_polls_end)
data object Pin : TimelineItemAction(CommonStrings.action_pin, CompoundDrawables.ic_compound_pin)
} }

View file

@ -958,7 +958,8 @@ class MessagesPresenterTest {
return timelinePresenter return timelinePresenter
} }
} }
val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore) val featureFlagService = FakeFeatureFlagService()
val actionListPresenter = ActionListPresenter(appPreferencesStore = appPreferencesStore, featureFlagsService = featureFlagService)
val typingNotificationPresenter = TypingNotificationPresenter( val typingNotificationPresenter = TypingNotificationPresenter(
room = matrixRoom, room = matrixRoom,
sessionPreferencesStore = sessionPreferencesStore, sessionPreferencesStore = sessionPreferencesStore,
@ -981,7 +982,7 @@ class MessagesPresenterTest {
snackbarDispatcher = SnackbarDispatcher(), snackbarDispatcher = SnackbarDispatcher(),
navigator = navigator, navigator = navigator,
clipboardHelper = clipboardHelper, clipboardHelper = clipboardHelper,
featureFlagsService = FakeFeatureFlagService(), featureFlagsService = featureFlagService,
buildMeta = aBuildMeta(), buildMeta = aBuildMeta(),
dispatchers = coroutineDispatchers, dispatchers = coroutineDispatchers,
htmlConverterProvider = FakeHtmlConverterProvider(), htmlConverterProvider = FakeHtmlConverterProvider(),

View file

@ -169,6 +169,7 @@ class MessagesViewTest {
userHasPermissionToRedactOwn: Boolean = false, userHasPermissionToRedactOwn: Boolean = false,
userHasPermissionToRedactOther: Boolean = false, userHasPermissionToRedactOther: Boolean = false,
userHasPermissionToSendReaction: Boolean = false, userHasPermissionToSendReaction: Boolean = false,
userCanPinEvent: Boolean = false,
) { ) {
val eventsRecorder = EventsRecorder<ActionListEvents>() val eventsRecorder = EventsRecorder<ActionListEvents>()
val state = aMessagesState( val state = aMessagesState(
@ -180,6 +181,7 @@ class MessagesViewTest {
canRedactOwn = userHasPermissionToRedactOwn, canRedactOwn = userHasPermissionToRedactOwn,
canRedactOther = userHasPermissionToRedactOther, canRedactOther = userHasPermissionToRedactOther,
canSendReaction = userHasPermissionToSendReaction, canSendReaction = userHasPermissionToSendReaction,
canPin = userCanPinEvent,
), ),
) )
val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event

View file

@ -835,5 +835,6 @@ class ActionListPresenterTest {
private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter {
val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled)
return ActionListPresenter(appPreferencesStore = preferencesStore) val featureFlagsService = FakeFeatureFlagService()
return ActionListPresenter(appPreferencesStore = preferencesStore, featureFlagsService = featureFlagsService)
} }