diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index 4e99b37592..87792edf1d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -16,25 +16,17 @@ package io.element.android.features.messages.impl.timeline.factories.event +import io.element.android.features.messages.impl.timeline.groups.canBeDisplayedInBubbleBlock import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions +import io.element.android.libraries.core.bool.orTrue import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.EventSendState -import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent -import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent -import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails -import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent -import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent -import io.element.android.libraries.matrix.api.timeline.item.event.StateContent -import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent -import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent -import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent import kotlinx.collections.immutable.toImmutableList import java.text.DateFormat import java.util.Date @@ -112,8 +104,8 @@ class TimelineItemEventFactory @Inject constructor( val previousSender = prevTimelineItem?.event?.sender val nextSender = nextTimelineItem?.event?.sender - val previousIsGroupable = prevTimelineItem.isGroupable() - val nextIsGroupable = nextTimelineItem.isGroupable() + val previousIsGroupable = prevTimelineItem?.canBeDisplayedInBubbleBlock().orTrue() + val nextIsGroupable = nextTimelineItem?.canBeDisplayedInBubbleBlock().orTrue() return when { previousSender != currentSender && nextSender == currentSender -> { @@ -149,19 +141,3 @@ class TimelineItemEventFactory @Inject constructor( } } } - -private fun MatrixTimelineItem.Event?.isGroupable(): Boolean { - if (this == null) return true - return when (event.content) { - is FailedToParseStateContent, - is ProfileChangeContent, - is RoomMembershipContent, - UnknownContent, - is StateContent -> false - is FailedToParseMessageLikeContent, - is MessageContent, - RedactedContent, - is StickerContent, - is UnableToDecryptContent -> true - } -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt new file mode 100644 index 0000000000..9d54d372be --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 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 + * + * http://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.messages.impl.timeline.groups + +import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent +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.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent +import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent +import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent +import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent +import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent +import io.element.android.libraries.matrix.api.timeline.item.event.StateContent +import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent +import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent +import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent + +/** + * Return true if the Event can be grouped in a collapse/expand block + * When [canBeGrouped] returns a value, [canBeDisplayedInBubbleBlock] MUST return the opposite value. + * Since the receiving type are not the same, the two functions exist. + */ +internal fun TimelineItem.Event.canBeGrouped(): Boolean { + return when (content) { + is TimelineItemTextBasedContent, + is TimelineItemEncryptedContent, + is TimelineItemImageContent, + TimelineItemRedactedContent, + TimelineItemUnknownContent -> false + is TimelineItemProfileChangeContent, + is TimelineItemRoomMembershipContent, + is TimelineItemStateEventContent -> true + } +} + +/** + * Return true if the Event can be grouped in a block of message bubbles. + * When [canBeDisplayedInBubbleBlock] returns a value, [canBeGrouped] MUST return the opposite value. + * Since the receiving type are not the same, the two functions exist. + */ +internal fun MatrixTimelineItem.Event.canBeDisplayedInBubbleBlock(): Boolean { + return when (event.content) { + is FailedToParseMessageLikeContent, + is MessageContent, + RedactedContent, + is StickerContent, + is UnableToDecryptContent -> true + is FailedToParseStateContent, + is ProfileChangeContent, + is RoomMembershipContent, + UnknownContent, + is StateContent -> false + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt index d996406102..b04509ba22 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt @@ -17,18 +17,6 @@ package io.element.android.features.messages.impl.timeline.groups import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEmoteContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemNoticeContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent -import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject @@ -57,23 +45,6 @@ class TimelineItemGrouper @Inject constructor() { } return result } - - private fun TimelineItem.Event.canBeGrouped(): Boolean { - return when (content) { - is TimelineItemEncryptedContent, - is TimelineItemImageContent, - TimelineItemRedactedContent, - is TimelineItemEmoteContent, - is TimelineItemNoticeContent, - is TimelineItemTextContent, - is TimelineItemFileContent, - is TimelineItemVideoContent, - TimelineItemUnknownContent -> false - is TimelineItemProfileChangeContent, - is TimelineItemRoomMembershipContent, - is TimelineItemStateEventContent -> true - } - } } /**