Merge branch 'develop' into feature/dla/emojibase_integration

This commit is contained in:
David Langley 2023-08-31 11:38:28 +01:00 committed by GitHub
commit d2e4cda28c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 259 additions and 50 deletions

View file

@ -22,4 +22,8 @@ sealed interface TimelineEvents {
data object LoadMore : TimelineEvents
data class SetHighlightedEvent(val eventId: EventId?) : TimelineEvents
data class OnScrollFinished(val firstIndex: Int) : TimelineEvents
data class PollAnswerSelected(
val pollStartId: EventId,
val answerId: String
) : TimelineEvents
}

View file

@ -87,6 +87,13 @@ class TimelinePresenter @Inject constructor(
lastReadReceiptId = lastReadReceiptId
)
}
is TimelineEvents.PollAnswerSelected -> appScope.launch {
room.sendPollResponse(
pollStartId = event.pollStartId,
answers = listOf(event.answerId),
)
// TODO Polls: Send poll vote analytic
}
}
}

View file

@ -100,6 +100,9 @@ fun TimelineView(
// TODO implement this logic once we have support to 'jump to event X' in sliding sync
}
fun onPollAnswerSelected(pollStartId: EventId, answerId: String) {
state.eventSink(TimelineEvents.PollAnswerSelected(pollStartId, answerId))
}
Box(modifier = modifier) {
LazyColumn(
@ -125,6 +128,7 @@ fun TimelineView(
onReactionLongClick = onReactionLongClicked,
onMoreReactionsClick = onMoreReactionsClicked,
onTimestampClicked = onTimestampClicked,
onPollAnswerSelected = ::onPollAnswerSelected,
onSwipeToReply = onSwipeToReply,
)
}
@ -162,6 +166,7 @@ fun TimelineItemRow(
onMoreReactionsClick: (TimelineItem.Event) -> Unit,
onTimestampClicked: (TimelineItem.Event) -> Unit,
onSwipeToReply: (TimelineItem.Event) -> Unit,
onPollAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
modifier: Modifier = Modifier
) {
when (timelineItem) {
@ -194,6 +199,7 @@ fun TimelineItemRow(
onMoreReactionsClick = onMoreReactionsClick,
onTimestampClicked = onTimestampClicked,
onSwipeToReply = { onSwipeToReply(timelineItem) },
onPollAnswerSelected = onPollAnswerSelected,
modifier = modifier,
)
}
@ -231,6 +237,7 @@ fun TimelineItemRow(
onReactionClick = onReactionClick,
onReactionLongClick = onReactionLongClick,
onMoreReactionsClick = onMoreReactionsClick,
onPollAnswerSelected = onPollAnswerSelected,
onSwipeToReply = {},
)
}

View file

@ -118,6 +118,7 @@ fun TimelineItemEventRow(
onReactionLongClick: (emoji: String, eventId: TimelineItem.Event) -> Unit,
onMoreReactionsClick: (eventId: TimelineItem.Event) -> Unit,
onSwipeToReply: () -> Unit,
onPollAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
modifier: Modifier = Modifier
) {
val coroutineScope = rememberCoroutineScope()
@ -175,6 +176,7 @@ fun TimelineItemEventRow(
onReactionClicked = { emoji -> onReactionClick(emoji, event) },
onReactionLongClicked = { emoji -> onReactionLongClick(emoji, event) },
onMoreReactionsClicked = { onMoreReactionsClick(event) },
onPollAnswerSelected = onPollAnswerSelected,
)
}
}
@ -191,6 +193,7 @@ fun TimelineItemEventRow(
onReactionClicked = { emoji -> onReactionClick(emoji, event) },
onReactionLongClicked = { emoji -> onReactionLongClick(emoji, event) },
onMoreReactionsClicked = { onMoreReactionsClick(event) },
onPollAnswerSelected = onPollAnswerSelected,
)
}
}
@ -232,6 +235,7 @@ private fun TimelineItemEventRowContent(
onReactionClicked: (emoji: String) -> Unit,
onReactionLongClicked: (emoji: String) -> Unit,
onMoreReactionsClicked: (event: TimelineItem.Event) -> Unit,
onPollAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
modifier: Modifier = Modifier,
) {
fun ConstrainScope.linkStartOrEnd(event: TimelineItem.Event) = if (event.isMine) {
@ -289,7 +293,8 @@ private fun TimelineItemEventRowContent(
inReplyToClick = inReplyToClicked,
onTimestampClicked = {
onTimestampClicked(event)
}
},
onPollAnswerSelected = onPollAnswerSelected,
)
}
@ -360,6 +365,7 @@ private fun MessageEventBubbleContent(
onMessageLongClick: () -> Unit,
inReplyToClick: () -> Unit,
onTimestampClicked: () -> Unit,
onPollAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
@SuppressLint("ModifierParameter") bubbleModifier: Modifier = Modifier, // need to rename this modifier to distinguish it from the following ones
) {
val timestampPosition = when (event.content) {
@ -385,6 +391,7 @@ private fun MessageEventBubbleContent(
onClick = onMessageClick,
onLongClick = onMessageLongClick,
extraPadding = event.toExtraPadding(),
onPollAnswerSelected = onPollAnswerSelected,
modifier = modifier,
)
}
@ -607,6 +614,7 @@ private fun ContentToPreview() {
onMoreReactionsClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
onPollAnswerSelected = { _, _ -> },
)
TimelineItemEventRow(
event = aTimelineItemEvent(
@ -627,6 +635,7 @@ private fun ContentToPreview() {
onMoreReactionsClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
onPollAnswerSelected = { _, _ -> },
)
}
}
@ -674,6 +683,7 @@ private fun ContentToPreviewWithReply() {
onMoreReactionsClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
onPollAnswerSelected = { _, _ -> },
)
TimelineItemEventRow(
event = aTimelineItemEvent(
@ -695,6 +705,7 @@ private fun ContentToPreviewWithReply() {
onMoreReactionsClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
onPollAnswerSelected = { _, _ -> },
)
}
}
@ -752,6 +763,7 @@ private fun ContentTimestampToPreview(event: TimelineItem.Event) {
onMoreReactionsClick = {},
onTimestampClicked = {},
onSwipeToReply = {},
onPollAnswerSelected = { _, _ -> },
)
}
}
@ -792,6 +804,7 @@ private fun ContentWithManyReactionsToPreview() {
onMoreReactionsClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
onPollAnswerSelected = { _, _ -> },
)
}
}
@ -816,6 +829,7 @@ internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight {
onMoreReactionsClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
onPollAnswerSelected = { _, _ -> },
)
}
@ -836,5 +850,6 @@ internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight {
onMoreReactionsClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
onPollAnswerSelected = { _, _ -> },
)
}

View file

@ -70,6 +70,7 @@ fun TimelineItemStateEventRow(
onClick = onClick,
onLongClick = onLongClick,
extraPadding = noExtraPadding,
onPollAnswerSelected = { _, _ -> error("Polls are not supported in state events") },
modifier = Modifier.defaultTimelineContentPadding()
)
}

View file

@ -31,6 +31,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
import io.element.android.libraries.matrix.api.core.EventId
@Composable
fun TimelineItemEventContentView(
@ -39,6 +40,7 @@ fun TimelineItemEventContentView(
extraPadding: ExtraPadding,
onClick: () -> Unit,
onLongClick: () -> Unit,
onPollAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
modifier: Modifier = Modifier
) {
when (content) {
@ -93,7 +95,7 @@ fun TimelineItemEventContentView(
)
is TimelineItemPollContent -> TimelineItemPollView(
content = content,
onAnswerSelected = {},
onAnswerSelected = onPollAnswerSelected,
modifier = modifier,
)
}

View file

@ -24,16 +24,17 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.poll.api.PollContentView
import io.element.android.libraries.designsystem.preview.DayNightPreviews
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.api.poll.PollAnswer
import io.element.android.libraries.matrix.api.core.EventId
import kotlinx.collections.immutable.toImmutableList
@Composable
fun TimelineItemPollView(
content: TimelineItemPollContent,
onAnswerSelected: (PollAnswer) -> Unit,
onAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit,
modifier: Modifier = Modifier,
) {
PollContentView(
eventId = content.eventId,
question = content.question,
answerItems = content.answerItems.toImmutableList(),
pollKind = content.pollKind,
@ -49,6 +50,6 @@ internal fun TimelineItemPollViewPreview(@PreviewParameter(TimelineItemPollConte
ElementPreview {
TimelineItemPollView(
content = content,
onAnswerSelected = {},
onAnswerSelected = { _, _ -> },
)
}

View file

@ -55,7 +55,7 @@ class TimelineItemContentFactory @Inject constructor(
is RoomMembershipContent -> roomMembershipFactory.create(eventTimelineItem)
is StateContent -> stateFactory.create(eventTimelineItem)
is StickerContent -> stickerFactory.create(itemContent)
is PollContent -> pollFactory.create(itemContent)
is PollContent -> pollFactory.create(itemContent, eventTimelineItem.eventId)
is UnableToDecryptContent -> utdFactory.create(itemContent)
is UnknownContent -> TimelineItemUnknownContent
}

View file

@ -23,6 +23,7 @@ import io.element.android.features.poll.api.PollAnswerItem
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.isDisclosed
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
import javax.inject.Inject
@ -32,7 +33,10 @@ class TimelineItemContentPollFactory @Inject constructor(
private val featureFlagService: FeatureFlagService,
) {
suspend fun create(content: PollContent): TimelineItemEventContent {
suspend fun create(
content: PollContent,
eventId: EventId?
): TimelineItemEventContent {
if (!featureFlagService.isFeatureEnabled(FeatureFlags.Polls)) return TimelineItemUnknownContent
// Todo Move this computation to the matrix rust sdk
@ -67,6 +71,7 @@ class TimelineItemContentPollFactory @Inject constructor(
}
return TimelineItemPollContent(
eventId = eventId,
question = content.question,
answerItems = answerItems,
pollKind = content.kind,

View file

@ -17,9 +17,11 @@
package io.element.android.features.messages.impl.timeline.model.event
import io.element.android.features.poll.api.PollAnswerItem
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.PollKind
data class TimelineItemPollContent(
val eventId: EventId?,
val question: String,
val answerItems: List<PollAnswerItem>,
val pollKind: PollKind,

View file

@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline.model.event
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.poll.api.aPollAnswerItemList
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.PollKind
open class TimelineItemPollContentProvider : PreviewParameterProvider<TimelineItemPollContent> {
@ -30,6 +31,7 @@ open class TimelineItemPollContentProvider : PreviewParameterProvider<TimelineIt
fun aTimelineItemPollContent(): TimelineItemPollContent {
return TimelineItemPollContent(
eventId = EventId("\$anEventId"),
pollKind = PollKind.Disclosed,
question = "What type of food should we have at the party?",
answerItems = aPollAnswerItemList(),

View file

@ -48,7 +48,7 @@ class MessageSummaryFormatterImpl @Inject constructor(
is TimelineItemLocationContent -> context.getString(CommonStrings.common_shared_location)
is TimelineItemEncryptedContent -> context.getString(CommonStrings.common_unable_to_decrypt)
is TimelineItemRedactedContent -> context.getString(CommonStrings.common_message_removed)
is TimelineItemPollContent, // Todo Polls: handle summary
is TimelineItemPollContent -> event.content.question
is TimelineItemUnknownContent -> context.getString(CommonStrings.common_unsupported_event)
is TimelineItemImageContent -> context.getString(CommonStrings.common_image)
is TimelineItemVideoContent -> context.getString(CommonStrings.common_video)