Browse Source

Pinned events : simplify poll content view

pull/3392/head
ganfra 3 weeks ago
parent
commit
bd327aac88
  1. 40
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt
  2. 39
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
  3. 24
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt
  4. 16
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt
  5. 34
      features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollContentView.kt
  6. 71
      features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollTitleView.kt

40
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt

@ -36,7 +36,11 @@ import io.element.android.features.messages.impl.actionlist.ActionListEvents @@ -36,7 +36,11 @@ import io.element.android.features.messages.impl.actionlist.ActionListEvents
import io.element.android.features.messages.impl.actionlist.ActionListView
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.timeline.components.TimelineItemRow
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.poll.api.pollcontent.PollTitleView
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.icons.CompoundDrawables
@ -70,8 +74,8 @@ fun PinnedMessagesListView( @@ -70,8 +74,8 @@ fun PinnedMessagesListView(
onUserDataClick = onUserDataClick,
onLinkClick = onLinkClick,
modifier = Modifier
.padding(padding)
.consumeWindowInsets(padding),
.padding(padding)
.consumeWindowInsets(padding),
)
}
)
@ -208,11 +212,43 @@ private fun PinnedMessagesListLoaded( @@ -208,11 +212,43 @@ private fun PinnedMessagesListLoaded(
onSwipeToReply = {},
onJoinCallClick = {},
onShieldClick = {},
eventContentView = { event, contentModifier, onContentLayoutChange ->
TimelineItemEventContentViewWrapper(
event = event,
onLinkClick = onLinkClick,
modifier = contentModifier,
onContentLayoutChange = onContentLayoutChange
)
},
)
}
}
}
@Composable
private fun TimelineItemEventContentViewWrapper(
event: TimelineItem.Event,
onLinkClick: (String) -> Unit,
modifier: Modifier = Modifier,
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
) {
if (event.content is TimelineItemPollContent) {
PollTitleView(
title = event.content.question,
isPollEnded = event.content.isEnded,
modifier = modifier
)
} else {
TimelineItemEventContentView(
content = event.content,
onLinkClick = onLinkClick,
eventSink = { },
modifier = modifier,
onContentLayoutChange = onContentLayoutChange
)
}
}
@PreviewsDayNight
@Composable
fun PinnedMessagesTimelineViewPreview(@PreviewParameter(PinnedMessagesTimelineStateProvider::class) state: PinnedMessagesListState) =

39
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt

@ -129,7 +129,16 @@ fun TimelineItemEventRow( @@ -129,7 +129,16 @@ fun TimelineItemEventRow(
onReadReceiptClick: (event: TimelineItem.Event) -> Unit,
onSwipeToReply: () -> Unit,
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { contentModifier, onContentLayoutChange ->
TimelineItemEventContentView(
content = event.content,
onLinkClick = onLinkClick,
eventSink = eventSink,
modifier = contentModifier,
onContentLayoutChange = onContentLayoutChange
)
},
) {
val coroutineScope = rememberCoroutineScope()
val interactionSource = remember { MutableInteractionSource() }
@ -188,8 +197,7 @@ fun TimelineItemEventRow( @@ -188,8 +197,7 @@ fun TimelineItemEventRow(
onReactionClick = { emoji -> onReactionClick(emoji, event) },
onReactionLongClick = { emoji -> onReactionLongClick(emoji, event) },
onMoreReactionsClick = { onMoreReactionsClick(event) },
onLinkClick = onLinkClick,
eventSink = eventSink,
eventContentView = eventContentView,
)
}
}
@ -207,8 +215,7 @@ fun TimelineItemEventRow( @@ -207,8 +215,7 @@ fun TimelineItemEventRow(
onReactionClick = { emoji -> onReactionClick(emoji, event) },
onReactionLongClick = { emoji -> onReactionLongClick(emoji, event) },
onMoreReactionsClick = { onMoreReactionsClick(event) },
onLinkClick = onLinkClick,
eventSink = eventSink,
eventContentView = eventContentView,
)
}
// Read receipts / Send state
@ -263,9 +270,8 @@ private fun TimelineItemEventRowContent( @@ -263,9 +270,8 @@ private fun TimelineItemEventRowContent(
onReactionClick: (emoji: String) -> Unit,
onReactionLongClick: (emoji: String) -> Unit,
onMoreReactionsClick: (event: TimelineItem.Event) -> Unit,
onLinkClick: (String) -> Unit,
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
modifier: Modifier = Modifier,
eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit,
) {
fun ConstrainScope.linkStartOrEnd(event: TimelineItem.Event) = if (event.isMine) {
end.linkTo(parent.end)
@ -328,8 +334,7 @@ private fun TimelineItemEventRowContent( @@ -328,8 +334,7 @@ private fun TimelineItemEventRowContent(
onShieldClick = onShieldClick,
onMessageLongClick = onLongClick,
inReplyToClick = inReplyToClick,
onLinkClick = onLinkClick,
eventSink = eventSink,
eventContentView = eventContentView,
)
}
@ -389,12 +394,11 @@ private fun MessageEventBubbleContent( @@ -389,12 +394,11 @@ private fun MessageEventBubbleContent(
onShieldClick: (MessageShield) -> Unit,
onMessageLongClick: () -> Unit,
inReplyToClick: () -> Unit,
onLinkClick: (String) -> Unit,
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
@SuppressLint("ModifierParameter")
// need to rename this modifier to prevent linter false positives
@Suppress("ModifierNaming")
bubbleModifier: Modifier = Modifier,
eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit,
) {
// Long clicks are not not automatically propagated from a `clickable`
// to its `combinedClickable` parent so we do it manually
@ -521,15 +525,10 @@ private fun MessageEventBubbleContent( @@ -521,15 +525,10 @@ private fun MessageEventBubbleContent(
onShieldClick = onShieldClick,
canShrinkContent = canShrinkContent,
modifier = timestampLayoutModifier,
) { onContentLayoutChange ->
TimelineItemEventContentView(
content = event.content,
onLinkClick = onLinkClick,
eventSink = eventSink,
onContentLayoutChange = onContentLayoutChange,
modifier = contentModifier
)
}
content = { onContentLayoutChange ->
eventContentView(contentModifier, onContentLayoutChange)
}
)
}
val inReplyTo = @Composable { inReplyTo: InReplyToDetails ->

24
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt

@ -28,7 +28,9 @@ import io.element.android.features.messages.impl.timeline.TimelineEvents @@ -28,7 +28,9 @@ import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.aGroupedEvents
import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
import io.element.android.features.messages.impl.timeline.components.group.GroupHeaderView
import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData
import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState
import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView
import io.element.android.features.messages.impl.timeline.model.TimelineItem
@ -56,7 +58,16 @@ fun TimelineItemGroupedEventsRow( @@ -56,7 +58,16 @@ fun TimelineItemGroupedEventsRow(
onMoreReactionsClick: (TimelineItem.Event) -> Unit,
onReadReceiptClick: (TimelineItem.Event) -> Unit,
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange ->
TimelineItemEventContentView(
content = event.content,
onLinkClick = onLinkClick,
eventSink = eventSink,
modifier = contentModifier,
onContentLayoutChange = onContentLayoutChange
)
},
) {
val isExpanded = rememberSaveable(key = timelineItem.identifier()) { mutableStateOf(false) }
@ -84,6 +95,7 @@ fun TimelineItemGroupedEventsRow( @@ -84,6 +95,7 @@ fun TimelineItemGroupedEventsRow(
onReadReceiptClick = onReadReceiptClick,
eventSink = eventSink,
modifier = modifier,
eventContentView = eventContentView,
)
}
@ -108,6 +120,15 @@ private fun TimelineItemGroupedEventsRowContent( @@ -108,6 +120,15 @@ private fun TimelineItemGroupedEventsRowContent(
onReadReceiptClick: (TimelineItem.Event) -> Unit,
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
modifier: Modifier = Modifier,
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange ->
TimelineItemEventContentView(
content = event.content,
onLinkClick = onLinkClick,
eventSink = eventSink,
modifier = contentModifier,
onContentLayoutChange = onContentLayoutChange
)
},
) {
Column(modifier = modifier.animateContentSize()) {
GroupHeaderView(
@ -142,6 +163,7 @@ private fun TimelineItemGroupedEventsRowContent( @@ -142,6 +163,7 @@ private fun TimelineItemGroupedEventsRowContent(
eventSink = eventSink,
onSwipeToReply = {},
onJoinCallClick = {},
eventContentView = eventContentView,
)
}
}

16
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt

@ -29,6 +29,8 @@ import androidx.compose.ui.unit.dp @@ -29,6 +29,8 @@ import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent
@ -59,7 +61,16 @@ internal fun TimelineItemRow( @@ -59,7 +61,16 @@ internal fun TimelineItemRow(
onSwipeToReply: (TimelineItem.Event) -> Unit,
onJoinCallClick: () -> Unit,
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange ->
TimelineItemEventContentView(
content = event.content,
onLinkClick = onLinkClick,
eventSink = eventSink,
modifier = contentModifier,
onContentLayoutChange = onContentLayoutChange
)
},
) {
val backgroundModifier = if (timelineItem.isEvent(focusedEventId)) {
val focusedEventOffset = if ((timelineItem as? TimelineItem.Event)?.showSenderInformation == true) {
@ -122,6 +133,9 @@ internal fun TimelineItemRow( @@ -122,6 +133,9 @@ internal fun TimelineItemRow(
onReadReceiptClick = onReadReceiptClick,
onSwipeToReply = { onSwipeToReply(timelineItem) },
eventSink = eventSink,
eventContentView = { contentModifier, onContentLayoutChange ->
eventContentView(timelineItem, contentModifier, onContentLayoutChange)
},
)
}
}

34
features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollContentView.kt

@ -19,10 +19,8 @@ package io.element.android.features.poll.api.pollcontent @@ -19,10 +19,8 @@ package io.element.android.features.poll.api.pollcontent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.runtime.Composable
@ -36,12 +34,10 @@ import androidx.compose.ui.res.stringResource @@ -36,12 +34,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.PollAnswer
@ -117,7 +113,7 @@ fun PollContentView( @@ -117,7 +113,7 @@ fun PollContentView(
modifier = modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
PollTitle(title = question, isPollEnded = isPollEnded)
PollTitleView(title = question, isPollEnded = isPollEnded)
PollAnswers(answerItems = answerItems, onSelectAnswer = ::onSelectAnswer)
@ -139,34 +135,6 @@ fun PollContentView( @@ -139,34 +135,6 @@ fun PollContentView(
}
}
@Composable
private fun PollTitle(
title: String,
isPollEnded: Boolean,
) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
if (isPollEnded) {
Icon(
imageVector = CompoundIcons.PollsEnd(),
contentDescription = stringResource(id = CommonStrings.a11y_poll_end),
modifier = Modifier.size(22.dp)
)
} else {
Icon(
imageVector = CompoundIcons.Polls(),
contentDescription = stringResource(id = CommonStrings.a11y_poll),
modifier = Modifier.size(22.dp)
)
}
Text(
text = title,
style = ElementTheme.typography.fontBodyLgMedium
)
}
}
@Composable
private fun PollAnswers(
answerItems: ImmutableList<PollAnswerItem>,

71
features/poll/api/src/main/kotlin/io/element/android/features/poll/api/pollcontent/PollTitleView.kt

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.poll.api.pollcontent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun PollTitleView(
title: String,
isPollEnded: Boolean,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
if (isPollEnded) {
Icon(
imageVector = CompoundIcons.PollsEnd(),
contentDescription = stringResource(id = CommonStrings.a11y_poll_end),
modifier = Modifier.size(22.dp)
)
} else {
Icon(
imageVector = CompoundIcons.Polls(),
contentDescription = stringResource(id = CommonStrings.a11y_poll),
modifier = Modifier.size(22.dp)
)
}
Text(
text = title,
style = ElementTheme.typography.fontBodyLgMedium
)
}
}
@PreviewsDayNight
@Composable
internal fun PollTitleViewPreview() = ElementPreview {
PollTitleView(
title = "What is your favorite color?",
isPollEnded = false
)
}
Loading…
Cancel
Save