Updates on rust: makes SS working but slow. Also branch some timeline virtual items.

This commit is contained in:
ganfra 2023-02-03 14:41:24 +01:00
parent f0db8b00ea
commit 6e6d2141b9
41 changed files with 352 additions and 138 deletions

View file

@ -32,7 +32,7 @@ import io.element.android.features.messages.textcomposer.MessageComposerState
import io.element.android.features.messages.timeline.TimelineEvents import io.element.android.features.messages.timeline.TimelineEvents
import io.element.android.features.messages.timeline.TimelinePresenter import io.element.android.features.messages.timeline.TimelinePresenter
import io.element.android.features.messages.timeline.model.TimelineItem import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.model.content.TimelineItemTextBasedContent import io.element.android.features.messages.timeline.model.event.TimelineItemTextBasedContent
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize

View file

@ -23,7 +23,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import io.element.android.features.messages.actionlist.model.TimelineItemAction import io.element.android.features.messages.actionlist.model.TimelineItemAction
import io.element.android.features.messages.timeline.model.TimelineItem import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent import io.element.android.features.messages.timeline.model.event.TimelineItemRedactedContent
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope

View file

@ -70,13 +70,14 @@ import io.element.android.features.messages.timeline.model.MessagesItemGroupPosi
import io.element.android.features.messages.timeline.model.TimelineItem import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.model.TimelineItemGroupPositionProvider import io.element.android.features.messages.timeline.model.TimelineItemGroupPositionProvider
import io.element.android.features.messages.timeline.model.TimelineItemReactions import io.element.android.features.messages.timeline.model.TimelineItemReactions
import io.element.android.features.messages.timeline.model.content.MessagesTimelineItemContentProvider import io.element.android.features.messages.timeline.model.event.MessagesTimelineItemContentProvider
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.features.messages.timeline.model.content.TimelineItemEncryptedContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemImageContent import io.element.android.features.messages.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent import io.element.android.features.messages.timeline.model.event.TimelineItemRedactedContent
import io.element.android.features.messages.timeline.model.content.TimelineItemTextBasedContent import io.element.android.features.messages.timeline.model.event.TimelineItemTextBasedContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import io.element.android.features.messages.timeline.model.virtual.TimelineItemLoadingModel
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.utils.PairCombinedPreviewParameter import io.element.android.libraries.designsystem.utils.PairCombinedPreviewParameter
@ -158,8 +159,10 @@ fun TimelineItemRow(
onLongClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit,
) { ) {
when (timelineItem) { when (timelineItem) {
is TimelineItem.Virtual -> return is TimelineItem.Virtual -> TimelineItemVirtualRow(
is TimelineItem.Event -> MessageEventRow( virtual = timelineItem
)
is TimelineItem.Event -> TimelineItemEventRow(
event = timelineItem, event = timelineItem,
isHighlighted = isHighlighted, isHighlighted = isHighlighted,
onClick = { onClick(timelineItem) }, onClick = { onClick(timelineItem) },
@ -169,7 +172,18 @@ fun TimelineItemRow(
} }
@Composable @Composable
fun MessageEventRow( fun TimelineItemVirtualRow(
virtual: TimelineItem.Virtual,
modifier: Modifier = Modifier
) {
when (virtual.model) {
is TimelineItemLoadingModel -> TimelineLoadingMoreIndicator(modifier)
else -> return
}
}
@Composable
fun TimelineItemEventRow(
event: TimelineItem.Event, event: TimelineItem.Event,
isHighlighted: Boolean, isHighlighted: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
@ -338,9 +352,9 @@ internal fun BoxScope.TimelineScrollHelper(
} }
@Composable @Composable
internal fun TimelineLoadingMoreIndicator() { internal fun TimelineLoadingMoreIndicator(modifier: Modifier) {
Box( Box(
Modifier modifier
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight() .wrapContentHeight()
.padding(8.dp), .padding(8.dp),
@ -354,7 +368,7 @@ internal fun TimelineLoadingMoreIndicator() {
} }
class MessagesItemGroupPositionToMessagesTimelineItemContentProvider : class MessagesItemGroupPositionToMessagesTimelineItemContentProvider :
PairCombinedPreviewParameter<MessagesItemGroupPosition, TimelineItemContent>( PairCombinedPreviewParameter<MessagesItemGroupPosition, TimelineItemEventContent>(
TimelineItemGroupPositionProvider() to MessagesTimelineItemContentProvider() TimelineItemGroupPositionProvider() to MessagesTimelineItemContentProvider()
) )
@ -363,7 +377,7 @@ class MessagesItemGroupPositionToMessagesTimelineItemContentProvider :
@Composable @Composable
fun TimelineItemsPreview( fun TimelineItemsPreview(
@PreviewParameter(MessagesTimelineItemContentProvider::class) @PreviewParameter(MessagesTimelineItemContentProvider::class)
content: TimelineItemContent content: TimelineItemEventContent
) { ) {
val timelineItems = persistentListOf( val timelineItems = persistentListOf(
// 3 items (First Middle Last) with isMine = false // 3 items (First Middle Last) with isMine = false
@ -410,7 +424,7 @@ fun TimelineItemsPreview(
private fun createMessageEvent( private fun createMessageEvent(
isMine: Boolean, isMine: Boolean,
content: TimelineItemContent, content: TimelineItemEventContent,
groupPosition: MessagesItemGroupPosition groupPosition: MessagesItemGroupPosition
): TimelineItem { ): TimelineItem {
return TimelineItem.Event( return TimelineItem.Event(

View file

@ -20,7 +20,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Warning import androidx.compose.material.icons.filled.Warning
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import io.element.android.features.messages.timeline.model.content.TimelineItemEncryptedContent import io.element.android.features.messages.timeline.model.event.TimelineItemEncryptedContent
@Composable @Composable
fun TimelineItemEncryptedView( fun TimelineItemEncryptedView(

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import coil.compose.AsyncImage import coil.compose.AsyncImage
import coil.request.ImageRequest import coil.request.ImageRequest
import io.element.android.features.messages.timeline.model.content.TimelineItemImageContent import io.element.android.features.messages.timeline.model.event.TimelineItemImageContent
@Composable @Composable
fun TimelineItemImageView( fun TimelineItemImageView(

View file

@ -20,7 +20,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent import io.element.android.features.messages.timeline.model.event.TimelineItemRedactedContent
@Composable @Composable
fun TimelineItemRedactedView( fun TimelineItemRedactedView(

View file

@ -29,7 +29,7 @@ import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.core.text.util.LinkifyCompat import androidx.core.text.util.LinkifyCompat
import io.element.android.features.messages.timeline.components.html.HtmlDocument import io.element.android.features.messages.timeline.components.html.HtmlDocument
import io.element.android.features.messages.timeline.model.content.TimelineItemTextBasedContent import io.element.android.features.messages.timeline.model.event.TimelineItemTextBasedContent
import io.element.android.libraries.designsystem.LinkColor import io.element.android.libraries.designsystem.LinkColor
import io.element.android.libraries.designsystem.components.ClickableLinkText import io.element.android.libraries.designsystem.components.ClickableLinkText

View file

@ -20,7 +20,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Info
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
@Composable @Composable
fun TimelineItemUnknownView( fun TimelineItemUnknownView(

View file

@ -19,11 +19,12 @@ package io.element.android.features.messages.timeline.factories
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import io.element.android.features.messages.timeline.diff.CacheInvalidator import io.element.android.features.messages.timeline.diff.CacheInvalidator
import io.element.android.features.messages.timeline.diff.MatrixTimelineItemsDiffCallback import io.element.android.features.messages.timeline.diff.MatrixTimelineItemsDiffCallback
import io.element.android.features.messages.timeline.factories.event.TimelineItemEventFactory
import io.element.android.features.messages.timeline.factories.virtual.TimelineItemVirtualFactory
import io.element.android.features.messages.timeline.model.TimelineItem import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.util.invalidateLast import io.element.android.features.messages.timeline.util.invalidateLast
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.timeline.MatrixTimelineItem
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow

View file

@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
@ -34,7 +34,7 @@ class TimelineItemContentFactory @Inject constructor(
private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory
) { ) {
fun create(itemContent: RustTimelineItemContent): TimelineItemContent { fun create(itemContent: RustTimelineItemContent): TimelineItemEventContent {
return when (val kind = itemContent.kind()) { return when (val kind = itemContent.kind()) {
is TimelineItemContentKind.Message -> messageFactory.create(itemContent.asMessage()) is TimelineItemContentKind.Message -> messageFactory.create(itemContent.asMessage())
is TimelineItemContentKind.RedactedMessage -> redactedMessageFactory.create(kind) is TimelineItemContentKind.RedactedMessage -> redactedMessageFactory.create(kind)

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentFailedToParseMessageFactory @Inject constructor() { class TimelineItemContentFailedToParseMessageFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.FailedToParseMessageLike): TimelineItemContent { fun create(kind: TimelineItemContentKind.FailedToParseMessageLike): TimelineItemEventContent {
return TimelineItemUnknownContent return TimelineItemUnknownContent
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentFailedToParseStateFactory @Inject constructor() { class TimelineItemContentFailedToParseStateFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.FailedToParseState): TimelineItemContent { fun create(kind: TimelineItemContentKind.FailedToParseState): TimelineItemEventContent {
return TimelineItemUnknownContent return TimelineItemUnknownContent
} }
} }

View file

@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemEmoteContent import io.element.android.features.messages.timeline.model.event.TimelineItemEmoteContent
import io.element.android.features.messages.timeline.model.content.TimelineItemImageContent import io.element.android.features.messages.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.timeline.model.content.TimelineItemNoticeContent import io.element.android.features.messages.timeline.model.event.TimelineItemNoticeContent
import io.element.android.features.messages.timeline.model.content.TimelineItemTextContent import io.element.android.features.messages.timeline.model.event.TimelineItemTextContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import io.element.android.features.messages.timeline.util.toHtmlDocument import io.element.android.features.messages.timeline.util.toHtmlDocument
import io.element.android.libraries.matrix.media.MediaResolver import io.element.android.libraries.matrix.media.MediaResolver
import org.matrix.rustcomponents.sdk.Message import org.matrix.rustcomponents.sdk.Message
@ -30,7 +30,7 @@ import javax.inject.Inject
class TimelineItemContentMessageFactory @Inject constructor() { class TimelineItemContentMessageFactory @Inject constructor() {
fun create(contentAsMessage: Message?): TimelineItemContent { fun create(contentAsMessage: Message?): TimelineItemEventContent {
return when (val messageType = contentAsMessage?.msgtype()) { return when (val messageType = contentAsMessage?.msgtype()) {
is MessageType.Emote -> TimelineItemEmoteContent( is MessageType.Emote -> TimelineItemEmoteContent(
body = messageType.content.body, body = messageType.content.body,

View file

@ -14,17 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentProfileChangeFactory @Inject constructor() { class TimelineItemContentProfileChangeFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.ProfileChange): TimelineItemContent { fun create(kind: TimelineItemContentKind.ProfileChange): TimelineItemEventContent {
return TimelineItemUnknownContent return TimelineItemUnknownContent
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent import io.element.android.features.messages.timeline.model.event.TimelineItemRedactedContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentRedactedFactory @Inject constructor() { class TimelineItemContentRedactedFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.RedactedMessage): TimelineItemContent { fun create(kind: TimelineItemContentKind.RedactedMessage): TimelineItemEventContent {
return TimelineItemRedactedContent return TimelineItemRedactedContent
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentRoomMembershipFactory @Inject constructor() { class TimelineItemContentRoomMembershipFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.RoomMembership): TimelineItemContent { fun create(kind: TimelineItemContentKind.RoomMembership): TimelineItemEventContent {
return TimelineItemUnknownContent return TimelineItemUnknownContent
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentStateFactory @Inject constructor() { class TimelineItemContentStateFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.State): TimelineItemContent { fun create(kind: TimelineItemContentKind.State): TimelineItemEventContent {
return TimelineItemUnknownContent return TimelineItemUnknownContent
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent import io.element.android.features.messages.timeline.model.event.TimelineItemUnknownContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentStickerFactory @Inject constructor() { class TimelineItemContentStickerFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.Sticker): TimelineItemContent { fun create(kind: TimelineItemContentKind.Sticker): TimelineItemEventContent {
return TimelineItemUnknownContent return TimelineItemUnknownContent
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.content.TimelineItemEncryptedContent import io.element.android.features.messages.timeline.model.event.TimelineItemEncryptedContent
import org.matrix.rustcomponents.sdk.TimelineItemContentKind import org.matrix.rustcomponents.sdk.TimelineItemContentKind
import javax.inject.Inject import javax.inject.Inject
class TimelineItemContentUTDFactory @Inject constructor() { class TimelineItemContentUTDFactory @Inject constructor() {
fun create(kind: TimelineItemContentKind.UnableToDecrypt): TimelineItemContent { fun create(kind: TimelineItemContentKind.UnableToDecrypt): TimelineItemEventContent {
return TimelineItemEncryptedContent(kind.msg) return TimelineItemEncryptedContent(kind.msg)
} }
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.event
import io.element.android.features.messages.timeline.model.AggregatedReaction import io.element.android.features.messages.timeline.model.AggregatedReaction
import io.element.android.features.messages.timeline.model.MessagesItemGroupPosition import io.element.android.features.messages.timeline.model.MessagesItemGroupPosition

View file

@ -14,21 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.factories package io.element.android.features.messages.timeline.factories.virtual
import io.element.android.features.messages.timeline.model.TimelineItem import io.element.android.features.messages.timeline.model.virtual.TimelineItemDaySeparatorModel
import io.element.android.libraries.matrix.timeline.MatrixTimelineItem import io.element.android.features.messages.timeline.model.virtual.TimelineItemVirtualModel
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
import javax.inject.Inject import javax.inject.Inject
class TimelineItemVirtualFactory @Inject constructor() { class TimelineItemDaySeparatorFactory @Inject constructor() {
suspend fun create( fun create(virtualItem: VirtualTimelineItem.DayDivider): TimelineItemVirtualModel {
currentTimelineItem: MatrixTimelineItem.Virtual, return TimelineItemDaySeparatorModel(
index: Int, day = "${virtualItem.ts}"
timelineItems: List<MatrixTimelineItem>,
): TimelineItem.Virtual {
return TimelineItem.Virtual(
id = "virtual_item_$index"
) )
} }
} }

View file

@ -0,0 +1,52 @@
/*
* 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.timeline.factories.virtual
import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.model.virtual.TimelineItemLoadingModel
import io.element.android.features.messages.timeline.model.virtual.TimelineItemReadMarkerModel
import io.element.android.features.messages.timeline.model.virtual.TimelineItemUnknownVirtualModel
import io.element.android.features.messages.timeline.model.virtual.TimelineItemVirtualModel
import io.element.android.libraries.matrix.timeline.MatrixTimelineItem
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
import javax.inject.Inject
class TimelineItemVirtualFactory @Inject constructor(
private val daySeparatorFactory: TimelineItemDaySeparatorFactory,
) {
suspend fun create(
currentTimelineItem: MatrixTimelineItem.Virtual,
index: Int,
timelineItems: List<MatrixTimelineItem>,
): TimelineItem.Virtual {
return TimelineItem.Virtual(
id = "virtual_item_$index",
model = currentTimelineItem.computeModel(index)
)
}
private fun MatrixTimelineItem.Virtual.computeModel(index: Int): TimelineItemVirtualModel {
return when (val inner = virtual) {
is VirtualTimelineItem.DayDivider -> daySeparatorFactory.create(inner)
is VirtualTimelineItem.ReadMarker -> TimelineItemReadMarkerModel
is VirtualTimelineItem.LoadingIndicator -> TimelineItemLoadingModel
is VirtualTimelineItem.TimelineStart -> TimelineItemReadMarkerModel
else -> TimelineItemUnknownVirtualModel
}
}
}

View file

@ -17,14 +17,16 @@
package io.element.android.features.messages.timeline.model package io.element.android.features.messages.timeline.model
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import io.element.android.features.messages.timeline.model.content.TimelineItemContent import io.element.android.features.messages.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.timeline.model.virtual.TimelineItemVirtualModel
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.matrix.core.EventId import io.element.android.libraries.matrix.core.EventId
@Immutable @Immutable
sealed interface TimelineItem { sealed interface TimelineItem {
data class Virtual( data class Virtual(
val id: String val id: String,
val model: TimelineItemVirtualModel
) : TimelineItem ) : TimelineItem
data class Event( data class Event(
@ -32,7 +34,7 @@ sealed interface TimelineItem {
val senderId: String, val senderId: String,
val senderDisplayName: String?, val senderDisplayName: String?,
val senderAvatar: AvatarData, val senderAvatar: AvatarData,
val content: TimelineItemContent, val content: TimelineItemEventContent,
val sentTime: String = "", val sentTime: String = "",
val isMine: Boolean = false, val isMine: Boolean = false,
val groupPosition: MessagesItemGroupPosition = MessagesItemGroupPosition.None, val groupPosition: MessagesItemGroupPosition = MessagesItemGroupPosition.None,

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import org.jsoup.nodes.Document import org.jsoup.nodes.Document

View file

@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import org.matrix.rustcomponents.sdk.EncryptedMessage import org.matrix.rustcomponents.sdk.EncryptedMessage
data class TimelineItemEncryptedContent( data class TimelineItemEncryptedContent(
val encryptedMessage: EncryptedMessage val encryptedMessage: EncryptedMessage
) : TimelineItemContent ) : TimelineItemEventContent

View file

@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import org.matrix.rustcomponents.sdk.EncryptedMessage import org.matrix.rustcomponents.sdk.EncryptedMessage
sealed interface TimelineItemContent sealed interface TimelineItemEventContent
class MessagesTimelineItemContentProvider : PreviewParameterProvider<TimelineItemContent> { class MessagesTimelineItemContentProvider : PreviewParameterProvider<TimelineItemEventContent> {
override val values = sequenceOf( override val values = sequenceOf(
TimelineItemEmoteContent( TimelineItemEmoteContent(
body = "Emote", body = "Emote",

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import io.element.android.libraries.matrix.media.MediaResolver import io.element.android.libraries.matrix.media.MediaResolver
@ -23,4 +23,4 @@ data class TimelineItemImageContent(
val imageMeta: MediaResolver.Meta, val imageMeta: MediaResolver.Meta,
val blurhash: String?, val blurhash: String?,
val aspectRatio: Float val aspectRatio: Float
) : TimelineItemContent ) : TimelineItemEventContent

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import org.jsoup.nodes.Document import org.jsoup.nodes.Document

View file

@ -14,6 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
object TimelineItemRedactedContent : TimelineItemContent object TimelineItemRedactedContent : TimelineItemEventContent

View file

@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
sealed interface TimelineItemTextBasedContent : TimelineItemContent { sealed interface TimelineItemTextBasedContent : TimelineItemEventContent {
val body: String val body: String
val htmlDocument: Document? val htmlDocument: Document?
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
import org.jsoup.nodes.Document import org.jsoup.nodes.Document

View file

@ -14,6 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.timeline.model.content package io.element.android.features.messages.timeline.model.event
object TimelineItemUnknownContent : TimelineItemContent object TimelineItemUnknownContent : TimelineItemEventContent

View file

@ -0,0 +1,21 @@
/*
* 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.timeline.model.virtual
data class TimelineItemDaySeparatorModel(
val day: String
) : TimelineItemVirtualModel

View file

@ -0,0 +1,19 @@
/*
* 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.timeline.model.virtual
object TimelineItemLoadingModel : TimelineItemVirtualModel

View file

@ -0,0 +1,19 @@
/*
* 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.timeline.model.virtual
object TimelineItemReadMarkerModel : TimelineItemVirtualModel

View file

@ -0,0 +1,19 @@
/*
* 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.timeline.model.virtual
object TimelineItemTimelineStartModel : TimelineItemVirtualModel

View file

@ -0,0 +1,19 @@
/*
* 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.timeline.model.virtual
object TimelineItemUnknownVirtualModel : TimelineItemVirtualModel

View file

@ -0,0 +1,22 @@
/*
* 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.timeline.model.virtual
import androidx.compose.runtime.Immutable
@Immutable
sealed interface TimelineItemVirtualModel

View file

@ -36,6 +36,7 @@ import org.matrix.rustcomponents.sdk.ClientDelegate
import org.matrix.rustcomponents.sdk.MediaSource import org.matrix.rustcomponents.sdk.MediaSource
import org.matrix.rustcomponents.sdk.RequiredState import org.matrix.rustcomponents.sdk.RequiredState
import org.matrix.rustcomponents.sdk.SlidingSyncMode import org.matrix.rustcomponents.sdk.SlidingSyncMode
import org.matrix.rustcomponents.sdk.SlidingSyncRequestListFilters
import org.matrix.rustcomponents.sdk.SlidingSyncViewBuilder import org.matrix.rustcomponents.sdk.SlidingSyncViewBuilder
import org.matrix.rustcomponents.sdk.StoppableSpawn import org.matrix.rustcomponents.sdk.StoppableSpawn
import timber.log.Timber import timber.log.Timber
@ -66,7 +67,22 @@ internal class RustMatrixClient internal constructor(
} }
} }
private val slidingSyncView = SlidingSyncViewBuilder() private val slidingSyncFilters by lazy {
SlidingSyncRequestListFilters(
isDm = null,
spaces = emptyList(),
isEncrypted = null,
isInvite = false,
isTombstoned = false,
roomTypes = emptyList(),
notRoomTypes = listOf("m.space"),
roomNameLike = null,
tags = emptyList(),
notTags = emptyList()
)
}
private val visibleRoomsView = SlidingSyncViewBuilder()
.timelineLimit(limit = 10u) .timelineLimit(limit = 10u)
.requiredState( .requiredState(
requiredState = listOf( requiredState = listOf(
@ -74,17 +90,19 @@ internal class RustMatrixClient internal constructor(
RequiredState(key = "m.room.encryption", value = ""), RequiredState(key = "m.room.encryption", value = ""),
) )
) )
.name(name = "HomeScreenView") .filters(slidingSyncFilters)
.name(name = "CurrentlyVisibleRooms")
.sendUpdatesForItems(true)
.syncMode(mode = SlidingSyncMode.SELECTIVE) .syncMode(mode = SlidingSyncMode.SELECTIVE)
.addRange(0u, 30u) .addRange(0u, 20u)
.build() .build()
private val slidingSync = client private val slidingSync = client
.slidingSync() .slidingSync()
.homeserver("https://slidingsync.lab.element.dev") .homeserver("https://slidingsync.lab.matrix.org")
.withCommonExtensions() .withCommonExtensions()
// .coldCache("ElementX") .coldCache("ElementX")
.addView(slidingSyncView) .addView(visibleRoomsView)
.build() .build()
private val slidingSyncObserverProxy = SlidingSyncObserverProxy(coroutineScope) private val slidingSyncObserverProxy = SlidingSyncObserverProxy(coroutineScope)
@ -92,7 +110,7 @@ internal class RustMatrixClient internal constructor(
RustRoomSummaryDataSource( RustRoomSummaryDataSource(
slidingSyncObserverProxy.updateSummaryFlow, slidingSyncObserverProxy.updateSummaryFlow,
slidingSync, slidingSync,
slidingSyncView, visibleRoomsView,
dispatchers, dispatchers,
::onRestartSync ::onRestartSync
) )

View file

@ -18,13 +18,14 @@ package io.element.android.libraries.matrix.timeline
import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.EventTimelineItem
import org.matrix.rustcomponents.sdk.TimelineItem import org.matrix.rustcomponents.sdk.TimelineItem
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
sealed interface MatrixTimelineItem { sealed interface MatrixTimelineItem {
data class Event(val event: EventTimelineItem) : MatrixTimelineItem { data class Event(val event: EventTimelineItem) : MatrixTimelineItem {
val uniqueId: String = event.uniqueIdentifier() val uniqueId: String = event.uniqueIdentifier()
} }
object Virtual : MatrixTimelineItem data class Virtual(val virtual: VirtualTimelineItem) : MatrixTimelineItem
object Other : MatrixTimelineItem object Other : MatrixTimelineItem
} }
@ -35,7 +36,7 @@ fun TimelineItem.asMatrixTimelineItem(): MatrixTimelineItem {
} }
val asVirtual = asVirtual() val asVirtual = asVirtual()
if (asVirtual != null) { if (asVirtual != null) {
return MatrixTimelineItem.Virtual return MatrixTimelineItem.Virtual(asVirtual)
} }
return MatrixTimelineItem.Other return MatrixTimelineItem.Other
} }

View file

@ -17,48 +17,59 @@
package io.element.android.libraries.matrix.tracing package io.element.android.libraries.matrix.tracing
data class TracingConfiguration( data class TracingConfiguration(
val common: LogLevel = LogLevel.Warn, val overrides: Map<Target, LogLevel> = emptyMap()
val targets: Map<Target, LogLevel> = emptyMap()
) { ) {
val filter = "$common,${ private val targets = mapOf(
targets.map { "${it.key.filter}=${it.value.filter}" }.joinToString(separator = ",") Target.Common to LogLevel.Warn,
}" Target.Hyper to LogLevel.Warn,
Target.Sled to LogLevel.Warn,
Target.MatrixSdk.Sled to LogLevel.Warn,
Target.MatrixSdk.HttpClient to LogLevel.Trace,
Target.MatrixSdk.SlidingSync to LogLevel.Trace,
Target.MatrixSdk.BaseSlidingSync to LogLevel.Trace
)
sealed class Target(open val filter: String) { val filter: String
object Hyper : Target("hyper") get() {
object Sled : Target("sled") val newTargets = HashMap(targets)
sealed class MatrixSdk(override val filter: String) : Target(filter) { overrides.forEach { (target, logLevel) ->
object Root : MatrixSdk("matrix_sdk") newTargets[target] = logLevel
object Sled : MatrixSdk("matrix_sdk_sled") }
object FFI : MatrixSdk("matrix_sdk_ffi") return newTargets.map { "${it.key.filter}=${it.value.filter}" }.joinToString(separator = ",")
object HttpClient : MatrixSdk("matrix_sdk::http_client")
object UniffiAPI : MatrixSdk("matrix_sdk_ffi::uniffi_api")
object SlidingSync : MatrixSdk("matrix_sdk::sliding_sync")
object BaseSlidingSync : MatrixSdk("matrix_sdk_base::sliding_sync")
} }
} }
sealed class LogLevel(val filter: String) { sealed class Target(open val filter: String) {
object Warn : LogLevel("warn") object Common : Target("common")
object Trace : LogLevel("trace") object Hyper : Target("hyper")
object Info : LogLevel("info") object Sled : Target("sled")
object Debug : LogLevel("debug") sealed class MatrixSdk(override val filter: String) : Target(filter) {
object Error : LogLevel("error") object Root : MatrixSdk("matrix_sdk")
object Sled : MatrixSdk("matrix_sdk_sled")
object FFI : MatrixSdk("matrix_sdk_ffi")
object HttpClient : MatrixSdk("matrix_sdk::http_client")
object UniffiAPI : MatrixSdk("matrix_sdk_ffi::uniffi_api")
object SlidingSync : MatrixSdk("matrix_sdk::sliding_sync")
object BaseSlidingSync : MatrixSdk("matrix_sdk_base::sliding_sync")
} }
} }
sealed class LogLevel(val filter: String) {
object Warn : LogLevel("warn")
object Trace : LogLevel("trace")
object Info : LogLevel("info")
object Debug : LogLevel("debug")
object Error : LogLevel("error")
}
fun setupTracing(tracingConfiguration: TracingConfiguration) { fun setupTracing(tracingConfiguration: TracingConfiguration) {
org.matrix.rustcomponents.sdk.setupTracing(tracingConfiguration.filter) org.matrix.rustcomponents.sdk.setupTracing(tracingConfiguration.filter)
} }
object TracingConfigurations { object TracingConfigurations {
val release = TracingConfiguration(common = TracingConfiguration.LogLevel.Info) val release = TracingConfiguration(overrides = mapOf(Target.Common to LogLevel.Info))
val debug = TracingConfiguration() val debug = TracingConfiguration(overrides = mapOf(Target.Common to LogLevel.Info))
val full = TracingConfiguration(
common = TracingConfiguration.LogLevel.Info, fun custom(overrides: Map<Target, LogLevel>) = TracingConfiguration(overrides)
targets = mapOf(
TracingConfiguration.Target.Sled to TracingConfiguration.LogLevel.Warn
)
)
} }