Display only valid emojis in recent emoji list (#5612)
* Create `:libraries:recentemojis` and move `AddRecentEmoji` and `GetRecentEmojis` there - Make sure `GetRecentEmojis` won't return duplicate or invalid emojis. - `ActionListPresenter` now handles merging suggested and recent emojis, not `ActionListView`.
This commit is contained in:
parent
7facc40771
commit
45b5783b23
24 changed files with 351 additions and 111 deletions
|
|
@ -73,7 +73,6 @@ import io.element.android.libraries.matrix.api.core.toThreadId
|
|||
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
|
||||
import io.element.android.libraries.matrix.api.recentemojis.AddRecentEmoji
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.room.RoomInfo
|
||||
|
|
@ -87,6 +86,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransa
|
|||
import io.element.android.libraries.matrix.ui.messages.reply.map
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
|
||||
import io.element.android.libraries.recentemojis.api.AddRecentEmoji
|
||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ 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.recentemojis.GetRecentEmojis
|
||||
import io.element.android.libraries.matrix.api.room.BaseRoom
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import io.element.android.libraries.recentemojis.api.GetRecentEmojis
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -87,6 +87,8 @@ class DefaultActionListPresenter(
|
|||
|
||||
private val comparator = TimelineItemActionComparator()
|
||||
|
||||
private val suggestedEmojis = persistentListOf("👍️", "👎️", "🔥", "❤️", "👏")
|
||||
|
||||
@Composable
|
||||
override fun present(): ActionListState {
|
||||
val localCoroutineScope = rememberCoroutineScope()
|
||||
|
|
@ -146,6 +148,7 @@ class DefaultActionListPresenter(
|
|||
val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.content.canReact()
|
||||
|
||||
if (actions.isNotEmpty() || displayEmojiReactions || verifiedUserSendFailure != VerifiedUserSendFailure.None) {
|
||||
val recentEmojis = getRecentEmojis().getOrNull()?.toImmutableList() ?: persistentListOf()
|
||||
target.value = ActionListState.Target.Success(
|
||||
event = timelineItem,
|
||||
sentTimeFull = dateFormatter.format(
|
||||
|
|
@ -156,7 +159,10 @@ class DefaultActionListPresenter(
|
|||
displayEmojiReactions = displayEmojiReactions,
|
||||
verifiedUserSendFailure = verifiedUserSendFailure,
|
||||
actions = actions.toImmutableList(),
|
||||
recentEmojis = getRecentEmojis().getOrNull()?.toImmutableList() ?: persistentListOf()
|
||||
// Merge suggested and recent emojis, removing duplicates and returning at most 100
|
||||
recentEmojis = (suggestedEmojis + recentEmojis).distinct()
|
||||
.take(100)
|
||||
.toImmutableList()
|
||||
)
|
||||
} else {
|
||||
target.value = ActionListState.Target.None
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
||||
private val suggestedEmojis = persistentListOf("👍️", "👎️", "🔥", "❤️", "👏")
|
||||
|
||||
override val values: Sequence<ActionListState>
|
||||
get() {
|
||||
val reactionsState = aTimelineItemReactions(1, isHighlighted = true)
|
||||
|
|
@ -42,7 +44,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
displayEmojiReactions = true,
|
||||
verifiedUserSendFailure = VerifiedUserSendFailure.None,
|
||||
actions = aTimelineItemActionList(),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -58,7 +60,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
actions = aTimelineItemActionList(
|
||||
copyAction = TimelineItemAction.CopyCaption,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -73,7 +75,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
actions = aTimelineItemActionList(
|
||||
copyAction = TimelineItemAction.CopyCaption,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -88,7 +90,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
actions = aTimelineItemActionList(
|
||||
copyAction = null,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -103,7 +105,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
actions = aTimelineItemActionList(
|
||||
copyAction = TimelineItemAction.CopyCaption,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -118,7 +120,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
actions = aTimelineItemActionList(
|
||||
copyAction = null,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -131,7 +133,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
displayEmojiReactions = true,
|
||||
verifiedUserSendFailure = VerifiedUserSendFailure.None,
|
||||
actions = aTimelineItemActionList(),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -144,7 +146,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
displayEmojiReactions = false,
|
||||
verifiedUserSendFailure = VerifiedUserSendFailure.None,
|
||||
actions = aTimelineItemActionList(),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
),
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -157,7 +159,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
displayEmojiReactions = false,
|
||||
verifiedUserSendFailure = VerifiedUserSendFailure.None,
|
||||
actions = aTimelineItemPollActionList(),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
),
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -170,7 +172,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
displayEmojiReactions = true,
|
||||
verifiedUserSendFailure = VerifiedUserSendFailure.None,
|
||||
actions = aTimelineItemActionList(),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
anActionListState(
|
||||
|
|
@ -180,7 +182,7 @@ open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
|
|||
displayEmojiReactions = true,
|
||||
verifiedUserSendFailure = anUnsignedDeviceSendFailure(),
|
||||
actions = aTimelineItemActionList(),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -97,8 +97,6 @@ import io.element.android.libraries.matrix.ui.messages.sender.SenderName
|
|||
import io.element.android.libraries.matrix.ui.messages.sender.SenderNameMode
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
|
@ -345,7 +343,6 @@ private fun MessageSummary(
|
|||
}
|
||||
|
||||
private val emojiRippleRadius = 24.dp
|
||||
private val suggestedEmojis = persistentListOf("👍️", "👎️", "🔥", "❤️", "👏")
|
||||
|
||||
@Composable
|
||||
private fun EmojiReactionsRow(
|
||||
|
|
@ -360,12 +357,6 @@ private fun EmojiReactionsRow(
|
|||
) {
|
||||
val backgroundColor = ElementTheme.colors.bgCanvasDefault
|
||||
|
||||
val emojis = remember(recentEmojis) {
|
||||
(suggestedEmojis + recentEmojis.filter { it !in suggestedEmojis })
|
||||
.take(100)
|
||||
.toImmutableList()
|
||||
}
|
||||
|
||||
LazyRow(
|
||||
modifier = Modifier
|
||||
.weight(1f, fill = true)
|
||||
|
|
@ -388,7 +379,7 @@ private fun EmojiReactionsRow(
|
|||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
items(emojis) { emoji ->
|
||||
items(recentEmojis) { emoji ->
|
||||
val isHighlighted = highlightedEmojis.contains(emoji)
|
||||
EmojiButton(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ import androidx.compose.runtime.setValue
|
|||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.matrix.api.recentemojis.GetRecentEmojis
|
||||
import io.element.android.libraries.recentemojis.api.EmojibaseProvider
|
||||
import io.element.android.libraries.recentemojis.api.GetRecentEmojis
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableSet
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class CustomReactionPresenter(
|
|||
fun handleShowCustomReactionSheet(event: TimelineItem.Event) {
|
||||
target.value = CustomReactionState.Target.Loading(event)
|
||||
localCoroutineScope.launch {
|
||||
recentEmojis = getRecentEmojis().getOrNull().orEmpty().toImmutableList()
|
||||
recentEmojis = getRecentEmojis().getOrNull() ?: persistentListOf()
|
||||
target.value = CustomReactionState.Target.Success(
|
||||
event = event,
|
||||
emojibaseStore = emojibaseProvider.emojibaseStore
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023, 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.timeline.components.customreaction
|
||||
|
||||
import android.content.Context
|
||||
import io.element.android.emojibasebindings.EmojibaseDatasource
|
||||
import io.element.android.emojibasebindings.EmojibaseStore
|
||||
|
||||
class DefaultEmojibaseProvider(val context: Context) : EmojibaseProvider {
|
||||
override val emojibaseStore: EmojibaseStore by lazy {
|
||||
EmojibaseDatasource().load(context)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023, 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.timeline.components.customreaction
|
||||
|
||||
import io.element.android.emojibasebindings.EmojibaseStore
|
||||
|
||||
interface EmojibaseProvider {
|
||||
val emojibaseStore: EmojibaseStore
|
||||
}
|
||||
|
|
@ -59,7 +59,6 @@ import io.element.android.libraries.matrix.api.core.toThreadId
|
|||
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
|
||||
import io.element.android.libraries.matrix.api.recentemojis.AddRecentEmoji
|
||||
import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembersState
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
|
|
@ -89,6 +88,7 @@ import io.element.android.libraries.matrix.test.room.aRoomMember
|
|||
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
|
||||
import io.element.android.libraries.matrix.test.timeline.aTimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails
|
||||
import io.element.android.libraries.recentemojis.api.AddRecentEmoji
|
||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||
import io.element.android.libraries.textcomposer.model.TextEditorState
|
||||
import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown
|
||||
|
|
|
|||
|
|
@ -42,9 +42,11 @@ import io.element.android.libraries.matrix.test.A_USER_ID
|
|||
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
|
||||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||
import io.element.android.libraries.recentemojis.api.GetRecentEmojis
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.test
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -54,6 +56,8 @@ class ActionListPresenterTest {
|
|||
@get:Rule
|
||||
val warmUpRule = WarmUpRule()
|
||||
|
||||
private val suggestedEmojis = persistentListOf("👍️", "👎️", "🔥", "❤️", "👏")
|
||||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
|
|
@ -95,7 +99,7 @@ class ActionListPresenterTest {
|
|||
actions = persistentListOf(
|
||||
TimelineItemAction.ViewSource,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -137,7 +141,7 @@ class ActionListPresenterTest {
|
|||
actions = persistentListOf(
|
||||
TimelineItemAction.ViewSource,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -185,7 +189,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.ReportContent,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -232,7 +236,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.ReportContent,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -279,7 +283,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.ReportContent,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -328,7 +332,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ReportContent,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -377,7 +381,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ReportContent,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -425,7 +429,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -472,7 +476,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -519,7 +523,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.CopyText,
|
||||
TimelineItemAction.ViewSource,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -563,7 +567,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.CopyText,
|
||||
TimelineItemAction.ViewSource,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -611,7 +615,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -663,7 +667,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -713,7 +717,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.ReportContent,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -754,7 +758,7 @@ class ActionListPresenterTest {
|
|||
actions = persistentListOf(
|
||||
TimelineItemAction.ViewSource,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -828,7 +832,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.CopyText,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -875,7 +879,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -929,7 +933,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.ViewSource,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
initialState.eventSink.invoke(ActionListEvents.Clear)
|
||||
|
|
@ -1023,7 +1027,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.CopyText,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1068,7 +1072,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1112,7 +1116,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1155,7 +1159,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1201,7 +1205,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1239,7 +1243,7 @@ class ActionListPresenterTest {
|
|||
actions = persistentListOf(
|
||||
TimelineItemAction.ViewSource
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1317,7 +1321,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1371,7 +1375,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1426,7 +1430,7 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Pin,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1478,11 +1482,56 @@ class ActionListPresenterTest {
|
|||
TimelineItemAction.Reply,
|
||||
TimelineItemAction.Redact,
|
||||
),
|
||||
recentEmojis = persistentListOf(),
|
||||
recentEmojis = suggestedEmojis,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - recentEmojis merges suggested and recent emojis`() = runTest {
|
||||
val suggestedEmojis = persistentListOf("👍️", "👎️", "🔥", "❤️", "👏")
|
||||
val otherEmojis = (0..100).map { it.toString() }
|
||||
|
||||
val presenter = createActionListPresenter(
|
||||
isDeveloperModeEnabled = false,
|
||||
recentEmojis = GetRecentEmojis { Result.success((listOf("👍️", ":)", "❤️") + otherEmojis).toImmutableList()) },
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val messageEvent = aMessageEvent(
|
||||
eventId = null,
|
||||
transactionId = A_TRANSACTION_ID,
|
||||
isMine = true,
|
||||
isEditable = false,
|
||||
content = aTimelineItemVoiceContent(
|
||||
caption = null,
|
||||
),
|
||||
)
|
||||
|
||||
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).isInstanceOf(ActionListState.Target.Success::class.java)
|
||||
|
||||
// Check items are deduplicated between suggested and recent emojis and we take at most 100 items
|
||||
val expectedEmojis = (suggestedEmojis + persistentListOf(":)") + otherEmojis).take(100)
|
||||
assertThat((successState.target as ActionListState.Target.Success).recentEmojis)
|
||||
.isEqualTo(expectedEmojis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createActionListPresenter(
|
||||
|
|
@ -1490,6 +1539,7 @@ private fun createActionListPresenter(
|
|||
room: BaseRoom = FakeBaseRoom(),
|
||||
timelineMode: Timeline.Mode = Timeline.Mode.Live,
|
||||
featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(),
|
||||
recentEmojis: GetRecentEmojis = GetRecentEmojis { Result.success(persistentListOf()) },
|
||||
): ActionListPresenter {
|
||||
val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled)
|
||||
return DefaultActionListPresenter(
|
||||
|
|
@ -1500,6 +1550,6 @@ private fun createActionListPresenter(
|
|||
dateFormatter = FakeDateFormatter(),
|
||||
timelineMode = timelineMode,
|
||||
featureFlagService = featureFlagService,
|
||||
getRecentEmojis = { Result.success(persistentListOf()) },
|
||||
getRecentEmojis = recentEmojis,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
|
||||
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.recentemojis.test.FakeEmojibaseProvider
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -25,7 +27,7 @@ class CustomReactionPresenterTest {
|
|||
|
||||
private val presenter = CustomReactionPresenter(
|
||||
emojibaseProvider = FakeEmojibaseProvider(),
|
||||
getRecentEmojis = { Result.success(emptyList()) },
|
||||
getRecentEmojis = { Result.success(persistentListOf()) },
|
||||
)
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023, 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.timeline.components.customreaction
|
||||
|
||||
import io.element.android.emojibasebindings.EmojibaseStore
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
||||
class FakeEmojibaseProvider : EmojibaseProvider {
|
||||
override val emojibaseStore: EmojibaseStore
|
||||
get() = EmojibaseStore(persistentMapOf())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue