Browse Source

Highlight user's reactions in message actions menu (#778)

Part of #342
---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
pull/798/head
jonnyandrew 1 year ago committed by GitHub
parent
commit
8e72d5cab5
  1. 30
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt
  2. 26
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt
  3. 9
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItemReactions.kt
  4. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_2,NEXUS_5,1.0,en].png
  5. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_3,NEXUS_5,1.0,en].png
  6. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_4,NEXUS_5,1.0,en].png
  7. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_5,NEXUS_5,1.0,en].png
  8. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_6,NEXUS_5,1.0,en].png
  9. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_7,NEXUS_5,1.0,en].png
  10. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_2,NEXUS_5,1.0,en].png
  11. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_3,NEXUS_5,1.0,en].png
  12. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_4,NEXUS_5,1.0,en].png
  13. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_5,NEXUS_5,1.0,en].png
  14. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_6,NEXUS_5,1.0,en].png
  15. BIN
      tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_7,NEXUS_5,1.0,en].png

30
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt

@ -19,6 +19,7 @@ package io.element.android.features.messages.impl.actionlist @@ -19,6 +19,7 @@ package io.element.android.features.messages.impl.actionlist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemLocationContent
@ -28,47 +29,62 @@ import kotlinx.collections.immutable.persistentListOf @@ -28,47 +29,62 @@ import kotlinx.collections.immutable.persistentListOf
open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
override val values: Sequence<ActionListState>
get() = sequenceOf(
get() {
val reactionsState = aTimelineItemReactions(1, isHighlighted = true)
return sequenceOf(
anActionListState(),
anActionListState().copy(target = ActionListState.Target.Loading(aTimelineItemEvent())),
anActionListState().copy(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(),
event = aTimelineItemEvent().copy(
reactionsState = reactionsState
),
actions = aTimelineItemActionList(),
)
),
anActionListState().copy(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(content = aTimelineItemImageContent()),
event = aTimelineItemEvent(content = aTimelineItemImageContent()).copy(
reactionsState = reactionsState
),
actions = aTimelineItemActionList(),
)
),
anActionListState().copy(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(content = aTimelineItemVideoContent()),
event = aTimelineItemEvent(content = aTimelineItemVideoContent()).copy(
reactionsState = reactionsState
),
actions = aTimelineItemActionList(),
)
),
anActionListState().copy(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(content = aTimelineItemFileContent()),
event = aTimelineItemEvent(content = aTimelineItemFileContent()).copy(
reactionsState = reactionsState
),
actions = aTimelineItemActionList(),
)
),
anActionListState().copy(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(content = aTimelineItemLocationContent()),
event = aTimelineItemEvent(content = aTimelineItemLocationContent()).copy(
reactionsState = reactionsState
),
actions = aTimelineItemActionList(),
)
),
anActionListState().copy(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(content = aTimelineItemLocationContent()),
event = aTimelineItemEvent(content = aTimelineItemLocationContent()).copy(
reactionsState = reactionsState
),
actions = aTimelineItemActionList(),
),
displayEmojiReactions = false,
),
)
}
}
fun anActionListState() = ActionListState(

26
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package io.element.android.features.messages.impl.actionlist
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
@ -46,6 +47,7 @@ import androidx.compose.runtime.rememberCoroutineScope @@ -46,6 +47,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@ -78,7 +80,9 @@ import io.element.android.libraries.designsystem.theme.components.hide @@ -78,7 +80,9 @@ import io.element.android.libraries.designsystem.theme.components.hide
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -178,6 +182,7 @@ private fun SheetContent( @@ -178,6 +182,7 @@ private fun SheetContent(
if (state.displayEmojiReactions) {
item {
EmojiReactionsRow(
highlightedEmojis = target.event.reactionsState.highlightedKeys,
onEmojiReactionClicked = onEmojiReactionClicked,
onCustomReactionClicked = onCustomReactionClicked,
modifier = Modifier.fillMaxWidth(),
@ -322,6 +327,7 @@ private val emojiRippleRadius = 24.dp @@ -322,6 +327,7 @@ private val emojiRippleRadius = 24.dp
@Composable
internal fun EmojiReactionsRow(
highlightedEmojis: ImmutableList<String>,
onEmojiReactionClicked: (String) -> Unit,
onCustomReactionClicked: () -> Unit,
modifier: Modifier = Modifier,
@ -335,7 +341,8 @@ internal fun EmojiReactionsRow( @@ -335,7 +341,8 @@ internal fun EmojiReactionsRow(
"👍", "👎", "🔥", "", "👏"
)
for (emoji in defaultEmojis) {
EmojiButton(emoji, onEmojiReactionClicked)
val isHighlighted = highlightedEmojis.contains(emoji)
EmojiButton(emoji, isHighlighted, onEmojiReactionClicked)
}
Icon(
@ -358,19 +365,34 @@ internal fun EmojiReactionsRow( @@ -358,19 +365,34 @@ internal fun EmojiReactionsRow(
@Composable
private fun EmojiButton(
emoji: String,
isHighlighted: Boolean,
onClicked: (String) -> Unit,
modifier: Modifier = Modifier,
) {
val backgroundColor = if (isHighlighted) {
ElementTheme.colors.bgActionPrimaryRest
} else {
Color.Transparent
}
Box(
modifier = modifier
.size(48.dp)
.background(backgroundColor, RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
Text(
emoji,
fontSize = 28.dp.toSp(),
modifier = modifier.clickable(
color = Color.White,
modifier = Modifier
.clickable(
enabled = true,
onClick = { onClicked(emoji) },
indication = rememberRipple(bounded = false, radius = emojiRippleRadius),
interactionSource = remember { MutableInteractionSource() }
)
)
}
}
@Preview

9
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItemReactions.kt

@ -17,7 +17,14 @@ @@ -17,7 +17,14 @@
package io.element.android.features.messages.impl.timeline.model
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList
data class TimelineItemReactions(
val reactions: ImmutableList<AggregatedReaction>
)
) {
val highlightedKeys: ImmutableList<String>
get() = reactions
.filter { it.isHighlighted }
.map { it.key }
.toPersistentList()
}

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_2,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_3,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_4,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_6,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentDarkPreview_0_null_7,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_2,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_3,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_4,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_6,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentLightPreview_0_null_7,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.
Loading…
Cancel
Save