Sort action list item.

It will also ensure that the preview are closer to reality.
This commit is contained in:
Benoit Marty 2024-11-28 10:04:00 +01:00 committed by Benoit Marty
parent 6dcdee9928
commit 6b659a7dc8
4 changed files with 76 additions and 34 deletions

View file

@ -21,6 +21,7 @@ import dagger.assisted.AssistedInject
import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled
import io.element.android.features.messages.impl.UserEventPermissions 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.TimelineItemAction
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionComparator
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory
@ -70,6 +71,8 @@ class DefaultActionListPresenter @AssistedInject constructor(
override fun create(postProcessor: TimelineItemActionPostProcessor): DefaultActionListPresenter override fun create(postProcessor: TimelineItemActionPostProcessor): DefaultActionListPresenter
} }
private val comparator = TimelineItemActionComparator()
@Composable @Composable
override fun present(): ActionListState { override fun present(): ActionListState {
val localCoroutineScope = rememberCoroutineScope() val localCoroutineScope = rememberCoroutineScope()
@ -137,7 +140,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
} }
} }
// See order in https://www.figma.com/design/ux3tYoZV9WghC7hHT9Fhk0/Compound-iOS-Components?node-id=2946-2392
private suspend fun buildActions( private suspend fun buildActions(
timelineItem: TimelineItem.Event, timelineItem: TimelineItem.Event,
usersEventPermissions: UserEventPermissions, usersEventPermissions: UserEventPermissions,
@ -146,7 +148,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
isEventPinned: Boolean, isEventPinned: 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 buildSet {
if (timelineItem.canBeRepliedTo && usersEventPermissions.canSendMessage) { if (timelineItem.canBeRepliedTo && usersEventPermissions.canSendMessage) {
if (timelineItem.isThreaded) { if (timelineItem.isThreaded) {
add(TimelineItemAction.ReplyInThread) add(TimelineItemAction.ReplyInThread)
@ -202,6 +204,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
} }
} }
.postFilter(timelineItem.content) .postFilter(timelineItem.content)
.sortedWith(comparator)
.let(postProcessor::process) .let(postProcessor::process)
} }
} }
@ -209,7 +212,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
/** /**
* Post filter the actions based on the content of the event. * Post filter the actions based on the content of the event.
*/ */
private fun List<TimelineItemAction>.postFilter(content: TimelineItemEventContent): List<TimelineItemAction> { private fun Iterable<TimelineItemAction>.postFilter(content: TimelineItemEventContent): Iterable<TimelineItemAction> {
return filter { action -> return filter { action ->
when (content) { when (content) {
is TimelineItemCallNotifyContent, is TimelineItemCallNotifyContent,

View file

@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.actionlist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionComparator
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.anUnsignedDeviceSendFailure import io.element.android.features.messages.impl.crypto.sendfailure.resolve.anUnsignedDeviceSendFailure
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
@ -22,7 +23,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.messages.impl.timeline.model.event.aTimelineItemVoiceContent
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
open class ActionListStateProvider : PreviewParameterProvider<ActionListState> { open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
@ -175,7 +175,7 @@ fun anActionListState(
fun aTimelineItemActionList( fun aTimelineItemActionList(
copyAction: TimelineItemAction? = TimelineItemAction.CopyText copyAction: TimelineItemAction? = TimelineItemAction.CopyText
): ImmutableList<TimelineItemAction> { ): ImmutableList<TimelineItemAction> {
return listOfNotNull( return setOfNotNull(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
copyAction, copyAction,
@ -184,17 +184,19 @@ fun aTimelineItemActionList(
TimelineItemAction.Redact, TimelineItemAction.Redact,
TimelineItemAction.ReportContent, TimelineItemAction.ReportContent,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
).toPersistentList() )
.sortedWith(TimelineItemActionComparator())
.toPersistentList()
} }
fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> { fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> {
return persistentListOf( return setOf(
TimelineItemAction.EndPoll, TimelineItemAction.EndPoll,
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.CopyText, TimelineItemAction.Pin,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
.sortedWith(TimelineItemActionComparator())
.toPersistentList()
} }

View file

@ -0,0 +1,37 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.features.messages.impl.actionlist.model
class TimelineItemActionComparator : Comparator<TimelineItemAction> {
// See order in https://www.figma.com/design/ux3tYoZV9WghC7hHT9Fhk0/Compound-iOS-Components?node-id=2946-2392
private val orderedList = listOf(
TimelineItemAction.EndPoll,
TimelineItemAction.ViewInTimeline,
TimelineItemAction.Reply,
TimelineItemAction.ReplyInThread,
TimelineItemAction.Forward,
TimelineItemAction.Pin,
TimelineItemAction.Unpin,
TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.CopyText,
TimelineItemAction.AddCaption,
TimelineItemAction.EditCaption,
TimelineItemAction.CopyCaption,
TimelineItemAction.RemoveCaption,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
TimelineItemAction.Redact,
)
override fun compare(o1: TimelineItemAction, o2: TimelineItemAction): Int {
val index1 = orderedList.indexOf(o1)
val index2 = orderedList.indexOf(o2)
return index1.compareTo(index2)
}
}

View file

@ -176,8 +176,8 @@ class ActionListPresenterTest {
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent, TimelineItemAction.ReportContent,
) )
@ -221,8 +221,8 @@ class ActionListPresenterTest {
TimelineItemAction.ReplyInThread, TimelineItemAction.ReplyInThread,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent, TimelineItemAction.ReportContent,
) )
@ -268,8 +268,8 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent, TimelineItemAction.ReportContent,
) )
@ -314,8 +314,8 @@ class ActionListPresenterTest {
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent, TimelineItemAction.ReportContent,
TimelineItemAction.Redact, TimelineItemAction.Redact,
@ -361,8 +361,8 @@ class ActionListPresenterTest {
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent, TimelineItemAction.ReportContent,
TimelineItemAction.Redact, TimelineItemAction.Redact,
@ -408,10 +408,10 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Edit,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
@ -453,10 +453,10 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.ReplyInThread, TimelineItemAction.ReplyInThread,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Edit,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
@ -501,10 +501,10 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Edit,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
) )
) )
@ -547,9 +547,9 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.AddCaption,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.AddCaption,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
@ -646,11 +646,11 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
TimelineItemAction.EditCaption, TimelineItemAction.EditCaption,
TimelineItemAction.CopyCaption, TimelineItemAction.CopyCaption,
TimelineItemAction.RemoveCaption, TimelineItemAction.RemoveCaption,
TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
@ -696,11 +696,11 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.CopyCaption,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.CopyCaption,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.ReportContent,
) )
) )
) )
@ -813,10 +813,10 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Edit,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.CopyText,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
) )
@ -860,9 +860,9 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.CopyLink,
TimelineItemAction.Edit, TimelineItemAction.Edit,
TimelineItemAction.CopyText, TimelineItemAction.CopyText,
TimelineItemAction.CopyLink,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
@ -914,10 +914,10 @@ class ActionListPresenterTest {
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply, TimelineItemAction.Reply,
TimelineItemAction.Forward, TimelineItemAction.Forward,
TimelineItemAction.Edit,
TimelineItemAction.Unpin, TimelineItemAction.Unpin,
TimelineItemAction.CopyText,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.CopyText,
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
@ -1049,11 +1049,11 @@ class ActionListPresenterTest {
displayEmojiReactions = true, displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None, verifiedUserSendFailure = VerifiedUserSendFailure.None,
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Edit,
TimelineItemAction.EndPoll, TimelineItemAction.EndPoll,
TimelineItemAction.Reply,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
) )
@ -1092,8 +1092,8 @@ class ActionListPresenterTest {
displayEmojiReactions = true, displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None, verifiedUserSendFailure = VerifiedUserSendFailure.None,
actions = persistentListOf( actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.EndPoll, TimelineItemAction.EndPoll,
TimelineItemAction.Reply,
TimelineItemAction.Pin, TimelineItemAction.Pin,
TimelineItemAction.CopyLink, TimelineItemAction.CopyLink,
TimelineItemAction.Redact, TimelineItemAction.Redact,