Make sure we can display both Live and Static locations in ShowLocation

This commit is contained in:
ganfra 2026-02-26 22:07:30 +01:00
parent 222b9f0c9e
commit b4cf8c274e
16 changed files with 168 additions and 67 deletions

View file

@ -15,8 +15,7 @@ import io.element.android.libraries.architecture.NodeInputs
interface ShowLocationEntryPoint : FeatureEntryPoint { interface ShowLocationEntryPoint : FeatureEntryPoint {
data class Inputs( data class Inputs(
val location: Location, val mode: ShowLocationMode,
val description: String?,
) : NodeInputs ) : NodeInputs
fun createNode( fun createNode(

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.location.api
import android.os.Parcelable
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.location.AssetType
import kotlinx.parcelize.Parcelize
sealed interface ShowLocationMode : Parcelable {
@Parcelize
data class Static(
val location: Location,
val senderName: String,
val senderId: UserId,
val senderAvatarUrl: String?,
val timestamp: Long,
val assetType: AssetType?,
) : ShowLocationMode
@Parcelize
data object Live : ShowLocationMode
}

View file

@ -40,7 +40,7 @@ class ShowLocationNode(
} }
private val inputs: ShowLocationEntryPoint.Inputs = inputs() private val inputs: ShowLocationEntryPoint.Inputs = inputs()
private val presenter = presenterFactory.create(inputs.location, inputs.description) private val presenter = presenterFactory.create(inputs.mode)
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {

View file

@ -18,7 +18,7 @@ import androidx.compose.runtime.setValue
import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject import dev.zacsweers.metro.AssistedInject
import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationMode
import io.element.android.features.location.impl.common.MapDefaults import io.element.android.features.location.impl.common.MapDefaults
import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.location.impl.common.actions.LocationActions
import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsEvents
@ -29,15 +29,14 @@ import io.element.android.libraries.core.meta.BuildMeta
@AssistedInject @AssistedInject
class ShowLocationPresenter( class ShowLocationPresenter(
@Assisted private val location: Location, @Assisted private val mode: ShowLocationMode,
@Assisted private val description: String?,
permissionsPresenterFactory: PermissionsPresenter.Factory, permissionsPresenterFactory: PermissionsPresenter.Factory,
private val locationActions: LocationActions, private val locationActions: LocationActions,
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
) : Presenter<ShowLocationState> { ) : Presenter<ShowLocationState> {
@AssistedFactory @AssistedFactory
fun interface Factory { fun interface Factory {
fun create(location: Location, description: String?): ShowLocationPresenter fun create(mode: ShowLocationMode): ShowLocationPresenter
} }
private val permissionsPresenter = permissionsPresenterFactory.create(MapDefaults.permissions) private val permissionsPresenter = permissionsPresenterFactory.create(MapDefaults.permissions)
@ -59,7 +58,16 @@ class ShowLocationPresenter(
fun handleEvent(event: ShowLocationEvents) { fun handleEvent(event: ShowLocationEvents) {
when (event) { when (event) {
ShowLocationEvents.Share -> locationActions.share(location, description) ShowLocationEvents.Share -> {
when (mode) {
is ShowLocationMode.Static -> {
locationActions.share(mode.location, null)
}
ShowLocationMode.Live -> {
// TODO: Handle sharing for live locations
}
}
}
is ShowLocationEvents.TrackMyLocation -> { is ShowLocationEvents.TrackMyLocation -> {
if (event.enabled) { if (event.enabled) {
when { when {
@ -82,8 +90,7 @@ class ShowLocationPresenter(
return ShowLocationState( return ShowLocationState(
permissionDialog = permissionDialog, permissionDialog = permissionDialog,
location = location, mode = mode,
description = description,
hasLocationPermission = permissionsState.isAnyGranted, hasLocationPermission = permissionsState.isAnyGranted,
isTrackMyLocation = isTrackMyLocation, isTrackMyLocation = isTrackMyLocation,
appName = appName, appName = appName,

View file

@ -8,12 +8,11 @@
package io.element.android.features.location.impl.show package io.element.android.features.location.impl.show
import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationMode
data class ShowLocationState( data class ShowLocationState(
val permissionDialog: Dialog, val permissionDialog: Dialog,
val location: Location, val mode: ShowLocationMode,
val description: String?,
val hasLocationPermission: Boolean, val hasLocationPermission: Boolean,
val isTrackMyLocation: Boolean, val isTrackMyLocation: Boolean,
val appName: String, val appName: String,

View file

@ -10,6 +10,9 @@ package io.element.android.features.location.impl.show
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.location.api.Location import io.element.android.features.location.api.Location
import io.element.android.features.location.api.ShowLocationMode
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.location.AssetType
private const val APP_NAME = "ApplicationName" private const val APP_NAME = "ApplicationName"
@ -31,32 +34,47 @@ class ShowLocationStateProvider : PreviewParameterProvider<ShowLocationState> {
isTrackMyLocation = true, isTrackMyLocation = true,
), ),
aShowLocationState( aShowLocationState(
description = "My favourite place!", mode = aStaticLocationMode(senderName = "My favourite place!"),
), ),
aShowLocationState( aShowLocationState(
description = "For some reason I decided to to write a small essay that wraps at just two lines!", mode = aStaticLocationMode(
senderName = "For some reason I decided to write a small essay that wraps at just two lines!"
),
), ),
aShowLocationState( aShowLocationState(
description = "For some reason I decided to write a small essay in the location description. " + mode = ShowLocationMode.Live,
"It is so long that it will wrap onto more than two lines!",
), ),
) )
} }
fun aShowLocationState( fun aShowLocationState(
permissionDialog: ShowLocationState.Dialog = ShowLocationState.Dialog.None, permissionDialog: ShowLocationState.Dialog = ShowLocationState.Dialog.None,
location: Location = Location(1.23, 2.34, 4f), mode: ShowLocationMode = aStaticLocationMode(),
description: String? = null,
hasLocationPermission: Boolean = false, hasLocationPermission: Boolean = false,
isTrackMyLocation: Boolean = false, isTrackMyLocation: Boolean = false,
appName: String = APP_NAME, appName: String = APP_NAME,
eventSink: (ShowLocationEvents) -> Unit = {}, eventSink: (ShowLocationEvents) -> Unit = {},
) = ShowLocationState( ) = ShowLocationState(
permissionDialog = permissionDialog, permissionDialog = permissionDialog,
location = location, mode = mode,
description = description,
hasLocationPermission = hasLocationPermission, hasLocationPermission = hasLocationPermission,
isTrackMyLocation = isTrackMyLocation, isTrackMyLocation = isTrackMyLocation,
appName = appName, appName = appName,
eventSink = eventSink, eventSink = eventSink,
) )
fun aStaticLocationMode(
location: Location = Location(1.23, 2.34, 4f),
senderName: String = "Alice",
senderId: UserId = UserId("@alice:matrix.org"),
senderAvatarUrl: String? = null,
timestamp: Long = System.currentTimeMillis(),
assetType: AssetType? = null,
) = ShowLocationMode.Static(
location = location,
senderName = senderName,
senderId = senderId,
senderAvatarUrl = senderAvatarUrl,
timestamp = timestamp,
assetType = assetType,
)

View file

@ -11,6 +11,9 @@ package io.element.android.features.location.impl.show
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetValue
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.material3.rememberStandardBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -23,6 +26,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.compound.tokens.generated.TypographyTokens import io.element.android.compound.tokens.generated.TypographyTokens
import io.element.android.features.location.api.ShowLocationMode
import io.element.android.features.location.impl.R import io.element.android.features.location.impl.R
import io.element.android.features.location.impl.common.MapDefaults import io.element.android.features.location.impl.common.MapDefaults
import io.element.android.features.location.impl.common.PermissionDeniedDialog import io.element.android.features.location.impl.common.PermissionDeniedDialog
@ -74,12 +78,16 @@ fun ShowLocationView(
) )
} }
val cameraState = rememberCameraState( val initialPosition = when (val mode = state.mode) {
firstPosition = CameraPosition( is ShowLocationMode.Static -> CameraPosition(
target = Position(latitude = state.location.lat, longitude = state.location.lon), target = Position(latitude = mode.location.lat, longitude = mode.location.lon),
zoom = MapDefaults.DEFAULT_ZOOM zoom = MapDefaults.DEFAULT_ZOOM
) )
) ShowLocationMode.Live -> CameraPosition(
zoom = MapDefaults.DEFAULT_ZOOM
)
}
val cameraState = rememberCameraState(firstPosition = initialPosition)
val locationProvider = if (state.hasLocationPermission) { val locationProvider = if (state.hasLocationPermission) {
rememberDefaultLocationProvider( rememberDefaultLocationProvider(
updateInterval = 1.minutes, updateInterval = 1.minutes,
@ -96,10 +104,13 @@ fun ShowLocationView(
} }
} }
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberStandardBottomSheetState()
)
MapBottomSheetScaffold( MapBottomSheetScaffold(
scaffoldState = scaffoldState,
cameraState = cameraState, cameraState = cameraState,
modifier = modifier, modifier = modifier,
sheetPeekHeight = 80.dp,
topBar = { topBar = {
TopAppBar( TopAppBar(
titleStr = stringResource(CommonStrings.screen_view_location_title), titleStr = stringResource(CommonStrings.screen_view_location_title),
@ -121,17 +132,22 @@ fun ShowLocationView(
) )
}, },
sheetContent = { sheetContent = {
state.description?.let { when (val mode = state.mode) {
Text( is ShowLocationMode.Static -> {
text = it, Text(
textAlign = TextAlign.Center, text = mode.senderName,
maxLines = 2, textAlign = TextAlign.Center,
overflow = TextOverflow.Ellipsis, maxLines = 2,
style = TypographyTokens.fontBodyMdRegular, overflow = TextOverflow.Ellipsis,
modifier = Modifier style = TypographyTokens.fontBodyMdRegular,
.fillMaxWidth() modifier = Modifier
.padding(8.dp), .fillMaxWidth()
) .padding(8.dp),
)
}
ShowLocationMode.Live -> {
// TODO: Show list of active live location sharers
}
} }
}, },
mapContent = { mapContent = {
@ -140,22 +156,29 @@ fun ShowLocationView(
locationState = userLocationState, locationState = userLocationState,
trackUserLocation = state.isTrackMyLocation trackUserLocation = state.isTrackMyLocation
) )
val senderLocation = rememberGeoJsonSource( when (val mode = state.mode) {
data = GeoJsonData.Features( is ShowLocationMode.Static -> {
Point( val senderLocation = rememberGeoJsonSource(
Position( data = GeoJsonData.Features(
latitude = state.location.lat, Point(
longitude = state.location.lon Position(
latitude = mode.location.lat,
longitude = mode.location.lon
)
)
) )
) )
) val marker = painterResource(R.drawable.pin_small)
) SymbolLayer(
val marker = painterResource(R.drawable.pin_small) id = "sender_location",
SymbolLayer( source = senderLocation,
id = "sender_location", iconImage = image(marker)
source = senderLocation, )
iconImage = image(marker) }
) ShowLocationMode.Live -> {
// TODO: Show pins for all active live location sharers
}
}
}, },
overlayContent = { overlayContent = {
LocationFloatingActionButton( LocationFloatingActionButton(

View file

@ -28,10 +28,10 @@ import io.element.android.features.call.api.CallType
import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.call.api.ElementCallEntryPoint
import io.element.android.features.forward.api.ForwardEntryPoint import io.element.android.features.forward.api.ForwardEntryPoint
import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint
import io.element.android.features.location.api.Location
import io.element.android.features.location.api.LocationService import io.element.android.features.location.api.LocationService
import io.element.android.features.location.api.ShareLocationEntryPoint import io.element.android.features.location.api.ShareLocationEntryPoint
import io.element.android.features.location.api.ShowLocationEntryPoint import io.element.android.features.location.api.ShowLocationEntryPoint
import io.element.android.features.location.api.ShowLocationMode
import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.messages.api.MessagesEntryPoint
import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewNode import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewNode
@ -75,6 +75,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.room.alias.matches
import io.element.android.libraries.matrix.api.room.joinedRoomMembers import io.element.android.libraries.matrix.api.room.joinedRoomMembers
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
@ -148,7 +149,7 @@ class MessagesFlowNode(
data class AttachmentPreview(val timelineMode: Timeline.Mode, val attachment: Attachment, val inReplyToEventId: EventId?) : NavTarget data class AttachmentPreview(val timelineMode: Timeline.Mode, val attachment: Attachment, val inReplyToEventId: EventId?) : NavTarget
@Parcelize @Parcelize
data class LocationViewer(val location: Location, val description: String?) : NavTarget data class LocationViewer(val mode: ShowLocationMode) : NavTarget
@Parcelize @Parcelize
data class EventDebugInfo(val eventId: EventId?, val debugInfo: TimelineItemDebugInfo) : NavTarget data class EventDebugInfo(val eventId: EventId?, val debugInfo: TimelineItemDebugInfo) : NavTarget
@ -336,7 +337,7 @@ class MessagesFlowNode(
createNode<AttachmentsPreviewNode>(buildContext, listOf(inputs)) createNode<AttachmentsPreviewNode>(buildContext, listOf(inputs))
} }
is NavTarget.LocationViewer -> { is NavTarget.LocationViewer -> {
val inputs = ShowLocationEntryPoint.Inputs(navTarget.location, navTarget.description) val inputs = ShowLocationEntryPoint.Inputs(navTarget.mode)
showLocationEntryPoint.createNode( showLocationEntryPoint.createNode(
parentNode = this, parentNode = this,
buildContext = buildContext, buildContext = buildContext,
@ -558,9 +559,16 @@ class MessagesFlowNode(
) )
} }
is TimelineItemLocationContent -> { is TimelineItemLocationContent -> {
NavTarget.LocationViewer( val mode = ShowLocationMode.Static(
location = event.content.location, location = event.content.location,
description = event.content.description, senderName = event.safeSenderName,
senderId = event.senderId,
senderAvatarUrl = event.senderAvatar.url,
timestamp = event.sentTimeMillis,
assetType = event.content.assetType,
)
NavTarget.LocationViewer(
mode = mode
).takeIf { locationService.isServiceAvailable() } ).takeIf { locationService.isServiceAvailable() }
} }
else -> null else -> null

View file

@ -9,11 +9,13 @@
package io.element.android.features.messages.impl.timeline.model.event package io.element.android.features.messages.impl.timeline.model.event
import io.element.android.features.location.api.Location import io.element.android.features.location.api.Location
import io.element.android.libraries.matrix.api.room.location.AssetType
data class TimelineItemLocationContent( data class TimelineItemLocationContent(
val body: String, val body: String,
val location: Location, val location: Location,
val description: String? = null, val description: String? = null,
val assetType: AssetType? = null,
) : TimelineItemEventContent { ) : TimelineItemEventContent {
override val type: String = "TimelineItemLocationContent" override val type: String = "TimelineItemLocationContent"
} }

View file

@ -41,6 +41,7 @@ import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.media.ThumbnailInfo import io.element.android.libraries.matrix.api.media.ThumbnailInfo
import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
@ -98,8 +99,9 @@ class TimelineItemContentMessageFactoryTest {
@Test @Test
fun `test create LocationMessageType not null`() = runTest { fun `test create LocationMessageType not null`() = runTest {
val sut = createTimelineItemContentMessageFactory() val sut = createTimelineItemContentMessageFactory()
val assetType = AssetType.SENDER
val result = sut.create( val result = sut.create(
content = createMessageContent(type = LocationMessageType("body", "geo:1,2", "description")), content = createMessageContent(type = LocationMessageType("body", "geo:1,2", "description", assetType)),
senderDisambiguatedDisplayName = "Bob", senderDisambiguatedDisplayName = "Bob",
eventId = AN_EVENT_ID, eventId = AN_EVENT_ID,
) )
@ -107,6 +109,7 @@ class TimelineItemContentMessageFactoryTest {
body = "body", body = "body",
location = Location(lat = 1.0, lon = 2.0, accuracy = 0.0F), location = Location(lat = 1.0, lon = 2.0, accuracy = 0.0F),
description = "description", description = "description",
assetType = assetType,
) )
assertThat(result).isEqualTo(expected) assertThat(result).isEqualTo(expected)
} }
@ -115,7 +118,7 @@ class TimelineItemContentMessageFactoryTest {
fun `test create LocationMessageType null`() = runTest { fun `test create LocationMessageType null`() = runTest {
val sut = createTimelineItemContentMessageFactory() val sut = createTimelineItemContentMessageFactory()
val result = sut.create( val result = sut.create(
content = createMessageContent(type = LocationMessageType("body", "", null)), content = createMessageContent(type = LocationMessageType("body", "", null, null)),
senderDisambiguatedDisplayName = "Bob", senderDisambiguatedDisplayName = "Bob",
eventId = AN_EVENT_ID, eventId = AN_EVENT_ID,
) )

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.media.FileInfo
import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.room.location.AssetType
@Immutable @Immutable
sealed interface MessageType sealed interface MessageType
@ -55,6 +56,7 @@ data class LocationMessageType(
val body: String, val body: String,
val geoUri: String, val geoUri: String,
val description: String?, val description: String?,
val assetType: AssetType?,
) : MessageType ) : MessageType
data class AudioMessageType( data class AudioMessageType(

View file

@ -9,8 +9,14 @@
package io.element.android.libraries.matrix.impl.room.location package io.element.android.libraries.matrix.impl.room.location
import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.room.location.AssetType
import org.matrix.rustcomponents.sdk.AssetType as RustAssetType
fun AssetType.toInner(): org.matrix.rustcomponents.sdk.AssetType = when (this) { fun AssetType.into(): RustAssetType = when (this) {
AssetType.SENDER -> org.matrix.rustcomponents.sdk.AssetType.SENDER AssetType.SENDER -> RustAssetType.SENDER
AssetType.PIN -> org.matrix.rustcomponents.sdk.AssetType.PIN AssetType.PIN -> RustAssetType.PIN
}
fun RustAssetType.into(): AssetType = when(this){
RustAssetType.SENDER -> AssetType.SENDER
RustAssetType.PIN -> AssetType.PIN
} }

View file

@ -32,7 +32,7 @@ import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl
import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.media.map
import io.element.android.libraries.matrix.impl.poll.toInner import io.element.android.libraries.matrix.impl.poll.toInner
import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
import io.element.android.libraries.matrix.impl.room.location.toInner import io.element.android.libraries.matrix.impl.room.location.into
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
@ -478,7 +478,7 @@ class RustTimeline(
geoUri = geoUri, geoUri = geoUri,
description = description, description = description,
zoomLevel = zoomLevel?.toUByte(), zoomLevel = zoomLevel?.toUByte(),
assetType = assetType?.toInner(), assetType = assetType?.into(),
repliedToEventId = inReplyToEventId?.value, repliedToEventId = inReplyToEventId?.value,
) )
} }

View file

@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.media.map
import io.element.android.libraries.matrix.impl.room.location.into
import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper
import org.matrix.rustcomponents.sdk.InReplyToDetails import org.matrix.rustcomponents.sdk.InReplyToDetails
import org.matrix.rustcomponents.sdk.MessageType import org.matrix.rustcomponents.sdk.MessageType
@ -112,7 +113,12 @@ class EventMessageMapper {
) )
} }
is RustMessageType.Location -> { is RustMessageType.Location -> {
LocationMessageType(type.content.body, type.content.geoUri, type.content.description) LocationMessageType(
body = type.content.body,
geoUri = type.content.geoUri,
description = type.content.description,
assetType = type.content.asset?.into()
)
} }
is MessageType.Other -> { is MessageType.Other -> {
OtherMessageType(type.msgtype, type.body) OtherMessageType(type.msgtype, type.body)

View file

@ -15,7 +15,7 @@ import org.junit.Test
class AssetTypeKtTest { class AssetTypeKtTest {
@Test @Test
fun toInner() { fun toInner() {
assertThat(AssetType.SENDER.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.SENDER) assertThat(AssetType.SENDER.into()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.SENDER)
assertThat(AssetType.PIN.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.PIN) assertThat(AssetType.PIN.into()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.PIN)
} }
} }

View file

@ -71,7 +71,7 @@ open class InReplyToDetailsProvider : PreviewParameterProvider<InReplyToDetails>
), ),
aMessageContent( aMessageContent(
body = "Location", body = "Location",
type = LocationMessageType("Location", "geo:1,2", null), type = LocationMessageType("Location", "geo:1,2", null, assetType = null),
), ),
aMessageContent( aMessageContent(
body = "Notice", body = "Notice",