Show descriptions for locations.

Descriptions show in the same message bubble above the map in
the timeline, and in a bar at the top of the expanded map view.
This commit is contained in:
Chris Smith 2023-07-05 12:04:55 +01:00
parent 02fa8aaf46
commit 77470b9a97
8 changed files with 31 additions and 15 deletions

View file

@ -17,7 +17,6 @@
package io.element.android.features.location.impl.show package io.element.android.features.location.impl.show
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject

View file

@ -16,8 +16,10 @@
package io.element.android.features.messages.impl.timeline.components.event package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -28,26 +30,36 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text
@Composable @Composable
fun TimelineItemLocationView( fun TimelineItemLocationView(
content: TimelineItemLocationContent, content: TimelineItemLocationContent,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
StaticMapView( Column(modifier = modifier.fillMaxWidth()) {
modifier = modifier content.description?.let {
.fillMaxWidth() Text(
.heightIn(max = 188.dp), text = it,
lat = content.location.lat, modifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp),
lon = content.location.lon, )
zoom = 15.0, }
contentDescription = content.body
) StaticMapView(
modifier = Modifier
.fillMaxWidth()
.heightIn(max = 188.dp),
lat = content.location.lat,
lon = content.location.lon,
zoom = 15.0,
contentDescription = content.body
)
}
} }
@Preview @Preview
@Composable @Composable
internal fun TimelineItemLocationViewLightPreview(@PreviewParameter(TimelineItemLocationContentProvider::class) content: TimelineItemLocationContent) = internal fun TimelineItemLocationViewPreview(@PreviewParameter(TimelineItemLocationContentProvider::class) content: TimelineItemLocationContent) =
ElementPreviewLight { ContentToPreview(content) } ElementPreviewLight { ContentToPreview(content) }
@Preview @Preview

View file

@ -79,6 +79,7 @@ class TimelineItemContentMessageFactory @Inject constructor(
TimelineItemLocationContent( TimelineItemLocationContent(
body = messageType.body, body = messageType.body,
location = location, location = location,
description = messageType.description
) )
} }
} }

View file

@ -29,6 +29,7 @@ class TimelineItemEventContentProvider : PreviewParameterProvider<TimelineItemEv
aTimelineItemFileContent("A file.pdf"), aTimelineItemFileContent("A file.pdf"),
aTimelineItemFileContent("A bigger file name which doesn't fit.pdf"), aTimelineItemFileContent("A bigger file name which doesn't fit.pdf"),
aTimelineItemLocationContent(), aTimelineItemLocationContent(),
aTimelineItemLocationContent("Location description"),
aTimelineItemNoticeContent(), aTimelineItemNoticeContent(),
aTimelineItemRedactedContent(), aTimelineItemRedactedContent(),
aTimelineItemTextContent(), aTimelineItemTextContent(),

View file

@ -23,14 +23,16 @@ open class TimelineItemLocationContentProvider : PreviewParameterProvider<Timeli
override val values: Sequence<TimelineItemLocationContent> override val values: Sequence<TimelineItemLocationContent>
get() = sequenceOf( get() = sequenceOf(
aTimelineItemLocationContent(), aTimelineItemLocationContent(),
aTimelineItemLocationContent("This is a description!"),
) )
} }
fun aTimelineItemLocationContent() = TimelineItemLocationContent( fun aTimelineItemLocationContent(description: String? = null) = TimelineItemLocationContent(
body = "User location geo:52.2445,0.7186;u=5000", body = "User location geo:52.2445,0.7186;u=5000",
location = Location( location = Location(
lat = 52.2445, lat = 52.2445,
lon = 0.7186, lon = 0.7186,
accuracy = 5000f, accuracy = 5000f,
) ),
description = description,
) )

View file

@ -162,7 +162,7 @@ class DefaultRoomLastMessageFormatterTests {
AudioMessageType(body, MediaSource("url"), null), AudioMessageType(body, MediaSource("url"), null),
ImageMessageType(body, MediaSource("url"), null), ImageMessageType(body, MediaSource("url"), null),
FileMessageType(body, MediaSource("url"), null), FileMessageType(body, MediaSource("url"), null),
LocationMessageType(body, "geo:1,2"), LocationMessageType(body, "geo:1,2", null),
NoticeMessageType(body, null), NoticeMessageType(body, null),
EmoteMessageType(body, null), EmoteMessageType(body, null),
) )

View file

@ -128,6 +128,7 @@ data class ImageMessageType(
data class LocationMessageType( data class LocationMessageType(
val body: String, val body: String,
val geoUri: String, val geoUri: String,
val description: String?,
) : MessageType ) : MessageType
data class AudioMessageType( data class AudioMessageType(

View file

@ -55,7 +55,7 @@ class EventMessageMapper {
ImageMessageType(type.content.body, type.content.source.map(), type.content.info?.map()) ImageMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
} }
is MessageType.Location -> { is MessageType.Location -> {
LocationMessageType(type.content.body, type.content.geoUri) LocationMessageType(type.content.body, type.content.geoUri, type.content.description)
} }
is MessageType.Notice -> { is MessageType.Notice -> {
NoticeMessageType(type.content.body, type.content.formatted?.map()) NoticeMessageType(type.content.body, type.content.formatted?.map())