Merge pull request #3574 from element-hq/feature/bma/improveMediaModel

Clarify model for Event with attachment
This commit is contained in:
Benoit Marty 2024-10-16 14:57:05 +02:00 committed by GitHub
commit 7ece687740
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 444 additions and 259 deletions

View file

@ -46,7 +46,8 @@ class DefaultPinnedMessagesBannerFormatter @Inject constructor(
return when (val content = event.content) {
is MessageContent -> processMessageContents(event, content)
is StickerContent -> {
content.body.prefixWith(CommonStrings.common_sticker)
val text = content.body ?: content.filename
text.prefixWith(CommonStrings.common_sticker)
}
is UnableToDecryptContent -> {
sp.getString(CommonStrings.common_waiting_for_decryption_key)
@ -76,25 +77,25 @@ class DefaultPinnedMessagesBannerFormatter @Inject constructor(
messageType.toPlainText(permalinkParser)
}
is VideoMessageType -> {
messageType.body.prefixWith(CommonStrings.common_video)
messageType.bestDescription.prefixWith(CommonStrings.common_video)
}
is ImageMessageType -> {
messageType.body.prefixWith(CommonStrings.common_image)
messageType.bestDescription.prefixWith(CommonStrings.common_image)
}
is StickerMessageType -> {
messageType.body.prefixWith(CommonStrings.common_sticker)
messageType.bestDescription.prefixWith(CommonStrings.common_sticker)
}
is LocationMessageType -> {
messageType.body.prefixWith(CommonStrings.common_shared_location)
}
is FileMessageType -> {
messageType.body.prefixWith(CommonStrings.common_file)
messageType.bestDescription.prefixWith(CommonStrings.common_file)
}
is AudioMessageType -> {
messageType.body.prefixWith(CommonStrings.common_audio)
messageType.bestDescription.prefixWith(CommonStrings.common_audio)
}
is VoiceMessageType -> {
messageType.body.prefixWith(CommonStrings.common_voice_message)
messageType.bestDescription.prefixWith(CommonStrings.common_voice_message)
}
is OtherMessageType -> {
messageType.body

View file

@ -67,7 +67,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
}
is StickerContent -> {
val message = sp.getString(CommonStrings.common_sticker) + " (" + content.body + ")"
val message = sp.getString(CommonStrings.common_sticker) + " (" + content.bestDescription + ")"
message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
}
is UnableToDecryptContent -> {

View file

@ -32,7 +32,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
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.StickerMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
@ -46,6 +45,7 @@ import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.timeline.aPollContent
import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent
import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails
import io.element.android.libraries.matrix.test.timeline.aStickerContent
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
@ -91,7 +91,7 @@ class DefaultPinnedMessagesBannerFormatterTest {
fun `Sticker content`() {
val body = "a sticker body"
val info = ImageInfo(null, null, null, null, null, null, null)
val message = createRoomEvent(false, null, StickerContent(body, info, aMediaSource(url = "url")))
val message = createRoomEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url")))
val result = formatter.format(message)
val expectedBody = "Sticker: a sticker body"
assertThat(result.toString()).isEqualTo(expectedBody)
@ -135,11 +135,11 @@ class DefaultPinnedMessagesBannerFormatterTest {
val sharedContentMessagesTypes = arrayOf(
TextMessageType(body, null),
VideoMessageType(body, null, null, MediaSource("url"), null),
AudioMessageType(body, MediaSource("url"), null),
VoiceMessageType(body, MediaSource("url"), null, null),
AudioMessageType(body, null, null, MediaSource("url"), null),
VoiceMessageType(body, null, null, MediaSource("url"), null, null),
ImageMessageType(body, null, null, MediaSource("url"), null),
StickerMessageType(body, MediaSource("url"), null),
FileMessageType(body, MediaSource("url"), null),
StickerMessageType(body, null, null, MediaSource("url"), null),
FileMessageType(body, null, null, MediaSource("url"), null),
LocationMessageType(body, "geo:1,2", null),
NoticeMessageType(body, null),
EmoteMessageType(body, null),

View file

@ -32,7 +32,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
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.StickerMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
@ -46,6 +45,7 @@ import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.timeline.aPollContent
import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent
import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails
import io.element.android.libraries.matrix.test.timeline.aStickerContent
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
import org.junit.Before
@ -98,7 +98,7 @@ class DefaultRoomLastMessageFormatterTest {
fun `Sticker content`() {
val body = "a sticker body"
val info = ImageInfo(null, null, null, null, null, null, null)
val message = createRoomEvent(false, null, StickerContent(body, info, aMediaSource(url = "url")))
val message = createRoomEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url")))
val result = formatter.format(message, false)
val expectedBody = someoneElseId.toString() + ": Sticker (a sticker body)"
assertThat(result.toString()).isEqualTo(expectedBody)
@ -179,11 +179,11 @@ class DefaultRoomLastMessageFormatterTest {
val sharedContentMessagesTypes = arrayOf(
TextMessageType(body, null),
VideoMessageType(body, null, null, MediaSource("url"), null),
AudioMessageType(body, MediaSource("url"), null),
VoiceMessageType(body, MediaSource("url"), null, null),
AudioMessageType(body, null, null, MediaSource("url"), null),
VoiceMessageType(body, null, null, MediaSource("url"), null, null),
ImageMessageType(body, null, null, MediaSource("url"), null),
StickerMessageType(body, MediaSource("url"), null),
FileMessageType(body, MediaSource("url"), null),
StickerMessageType(body, null, null, MediaSource("url"), null),
FileMessageType(body, null, null, MediaSource("url"), null),
LocationMessageType(body, "geo:1,2", null),
NoticeMessageType(body, null),
EmoteMessageType(body, null),

View file

@ -30,10 +30,14 @@ data class MessageContent(
data object RedactedContent : EventContent
data class StickerContent(
val body: String,
val filename: String,
val body: String?,
val info: ImageInfo,
val source: MediaSource,
) : EventContent
) : EventContent {
val bestDescription: String
get() = body ?: filename
}
data class PollContent(
val question: String,

View file

@ -18,24 +18,37 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
@Immutable
sealed interface MessageType
@Immutable
sealed interface MessageTypeWithAttachment : MessageType {
val filename: String
val caption: String?
val formattedCaption: FormattedBody?
val bestDescription: String
get() = caption ?: filename
}
data class EmoteMessageType(
val body: String,
val formatted: FormattedBody?
) : MessageType
data class ImageMessageType(
val body: String,
val formatted: FormattedBody?,
val filename: String?,
override val filename: String,
override val caption: String?,
override val formattedCaption: FormattedBody?,
val source: MediaSource,
val info: ImageInfo?
) : MessageType
) : MessageTypeWithAttachment
// FIXME This is never used in production code.
data class StickerMessageType(
val body: String,
override val filename: String,
override val caption: String?,
override val formattedCaption: FormattedBody?,
val source: MediaSource,
val info: ImageInfo?
) : MessageType
) : MessageTypeWithAttachment
data class LocationMessageType(
val body: String,
@ -44,31 +57,37 @@ data class LocationMessageType(
) : MessageType
data class AudioMessageType(
val body: String,
override val filename: String,
override val caption: String?,
override val formattedCaption: FormattedBody?,
val source: MediaSource,
val info: AudioInfo?,
) : MessageType
) : MessageTypeWithAttachment
data class VoiceMessageType(
val body: String,
override val filename: String,
override val caption: String?,
override val formattedCaption: FormattedBody?,
val source: MediaSource,
val info: AudioInfo?,
val details: AudioDetails?,
) : MessageType
) : MessageTypeWithAttachment
data class VideoMessageType(
val body: String,
val formatted: FormattedBody?,
val filename: String?,
override val filename: String,
override val caption: String?,
override val formattedCaption: FormattedBody?,
val source: MediaSource,
val info: VideoInfo?
) : MessageType
) : MessageTypeWithAttachment
data class FileMessageType(
val body: String,
override val filename: String,
override val caption: String?,
override val formattedCaption: FormattedBody?,
val source: MediaSource,
val info: FileInfo?
) : MessageType
) : MessageTypeWithAttachment
data class NoticeMessageType(
val body: String,

View file

@ -50,14 +50,18 @@ class EventMessageMapper {
when (type.content.voice) {
null -> {
AudioMessageType(
body = type.content.body,
filename = type.content.filename,
caption = type.content.caption,
formattedCaption = type.content.formattedCaption?.map(),
source = type.content.source.map(),
info = type.content.info?.map(),
)
}
else -> {
VoiceMessageType(
body = type.content.body,
filename = type.content.filename,
caption = type.content.caption,
formattedCaption = type.content.formattedCaption?.map(),
source = type.content.source.map(),
info = type.content.info?.map(),
details = type.content.audio?.map(),
@ -66,10 +70,22 @@ class EventMessageMapper {
}
}
is RustMessageType.File -> {
FileMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
FileMessageType(
filename = type.content.filename,
caption = type.content.caption,
formattedCaption = type.content.formattedCaption?.map(),
source = type.content.source.map(),
info = type.content.info?.map(),
)
}
is RustMessageType.Image -> {
ImageMessageType(type.content.body, type.content.formatted?.map(), type.content.filename, type.content.source.map(), type.content.info?.map())
ImageMessageType(
filename = type.content.filename,
caption = type.content.caption,
formattedCaption = type.content.formattedCaption?.map(),
source = type.content.source.map(),
info = type.content.info?.map(),
)
}
is RustMessageType.Notice -> {
NoticeMessageType(type.content.body, type.content.formatted?.map())
@ -81,7 +97,13 @@ class EventMessageMapper {
EmoteMessageType(type.content.body, type.content.formatted?.map())
}
is RustMessageType.Video -> {
VideoMessageType(type.content.body, type.content.formatted?.map(), type.content.filename, type.content.source.map(), type.content.info?.map())
VideoMessageType(
filename = type.content.filename,
caption = type.content.caption,
formattedCaption = type.content.formattedCaption?.map(),
source = type.content.source.map(),
info = type.content.info?.map(),
)
}
is RustMessageType.Location -> {
LocationMessageType(type.content.body, type.content.geoUri, type.content.description)

View file

@ -84,7 +84,8 @@ class TimelineEventContentMapper(
}
is TimelineItemContent.Sticker -> {
StickerContent(
body = it.body,
filename = it.body,
body = null,
info = it.info.map(),
source = it.source.map(),
)

View file

@ -10,6 +10,8 @@ package io.element.android.libraries.matrix.test.timeline
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UserId
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.poll.PollAnswer
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
@ -25,6 +27,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
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.Receipt
import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_USER_ID
@ -110,6 +113,18 @@ fun aMessageContent(
type = messageType
)
fun aStickerContent(
filename: String = "filename",
info: ImageInfo,
mediaSource: MediaSource,
body: String? = null,
) = StickerContent(
filename = filename,
body = body,
info = info,
source = mediaSource,
)
fun aTimelineItemDebugInfo(
model: String = "Rust(Model())",
originalJson: String? = null,

View file

@ -44,7 +44,7 @@ internal class CoilMediaFetcher(
*
*/
private suspend fun fetchFile(mediaSource: MediaSource, kind: MediaRequestData.Kind.File): FetchResult? {
return mediaLoader.downloadMediaFile(mediaSource, kind.mimeType, kind.body)
return mediaLoader.downloadMediaFile(mediaSource, kind.mimeType, kind.fileName)
.map { mediaFile ->
val file = mediaFile.toFile()
SourceResult(

View file

@ -26,7 +26,12 @@ data class MediaRequestData(
) {
sealed interface Kind {
data object Content : Kind
data class File(val body: String?, val mimeType: String) : Kind
data class File(
val fileName: String,
val mimeType: String,
) : Kind
data class Thumbnail(val width: Long, val height: Long) : Kind {
constructor(size: Long) : this(size, size)
}

View file

@ -49,11 +49,11 @@ open class InReplyToDetailsProvider : PreviewParameterProvider<InReplyToDetails>
),
aMessageContent(
body = "Audio",
type = AudioMessageType("Audio", MediaSource("url"), null),
type = AudioMessageType("Audio", null, null, MediaSource("url"), null),
),
aMessageContent(
body = "Voice",
type = VoiceMessageType("Voice", MediaSource("url"), null, null),
type = VoiceMessageType("Voice", null, null, MediaSource("url"), null, null),
),
aMessageContent(
body = "Image",
@ -61,11 +61,11 @@ open class InReplyToDetailsProvider : PreviewParameterProvider<InReplyToDetails>
),
aMessageContent(
body = "Sticker",
type = StickerMessageType("Image", MediaSource("url"), null),
type = StickerMessageType("Image", null, null, MediaSource("url"), null),
),
aMessageContent(
body = "File",
type = FileMessageType("File", MediaSource("url"), null),
type = FileMessageType("File", null, null, MediaSource("url"), null),
),
aMessageContent(
body = "Location",

View file

@ -75,9 +75,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = ImageMessageType(
body = "body",
formatted = null,
filename = null,
filename = "filename",
caption = null,
formattedCaption = null,
source = aMediaSource(),
info = anImageInfo(),
)
@ -105,9 +105,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = ImageMessageType(
body = "body",
formatted = null,
filename = null,
filename = "filename",
caption = "caption",
formattedCaption = null,
source = aMediaSource(),
info = anImageInfo(),
)
@ -134,6 +134,7 @@ class InReplyToMetadataKtTest {
moleculeFlow(RecompositionMode.Immediate) {
anInReplyToDetailsReady(
eventContent = StickerContent(
filename = "filename",
body = "body",
info = anImageInfo(),
source = aMediaSource(url = "url")
@ -160,6 +161,7 @@ class InReplyToMetadataKtTest {
moleculeFlow(RecompositionMode.Immediate) {
anInReplyToDetailsReady(
eventContent = StickerContent(
filename = "filename",
body = "body",
info = anImageInfo(),
source = aMediaSource(url = "url")
@ -187,9 +189,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = VideoMessageType(
body = "body",
formatted = null,
filename = null,
filename = "filename",
caption = null,
formattedCaption = null,
source = aMediaSource(),
info = aVideoInfo(),
)
@ -217,9 +219,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = VideoMessageType(
body = "body",
formatted = null,
filename = null,
filename = "filename",
caption = "caption",
formattedCaption = null,
source = aMediaSource(),
info = aVideoInfo(),
)
@ -247,7 +249,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = FileMessageType(
body = "body",
filename = "filename",
caption = "caption",
formattedCaption = null,
source = aMediaSource(),
info = FileInfo(
mimetype = null,
@ -280,7 +284,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = FileMessageType(
body = "body",
filename = "filename",
caption = "caption",
formattedCaption = null,
source = aMediaSource(),
info = FileInfo(
mimetype = null,
@ -313,7 +319,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = AudioMessageType(
body = "body",
filename = "filename",
caption = "caption",
formattedCaption = null,
source = aMediaSource(),
info = AudioInfo(
duration = null,
@ -375,7 +383,9 @@ class InReplyToMetadataKtTest {
anInReplyToDetailsReady(
eventContent = aMessageContent(
messageType = VoiceMessageType(
body = "body",
filename = "filename",
caption = "caption",
formattedCaption = null,
source = aMediaSource(),
info = null,
details = null,

View file

@ -303,7 +303,7 @@ private fun MediaFileView(
if (info != null) {
Spacer(modifier = Modifier.height(20.dp))
Text(
text = info.name,
text = info.filename,
maxLines = 2,
style = ElementTheme.typography.fontBodyLgRegular,
overflow = TextOverflow.Ellipsis,

View file

@ -13,43 +13,49 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class MediaInfo(
val name: String,
val filename: String,
val caption: String?,
val mimeType: String,
val formattedFileSize: String,
val fileExtension: String,
) : Parcelable
fun anImageMediaInfo(): MediaInfo = MediaInfo(
"an image file.jpg",
MimeTypes.Jpeg,
"4MB",
"jpg"
filename = "an image file.jpg",
caption = null,
mimeType = MimeTypes.Jpeg,
formattedFileSize = "4MB",
fileExtension = "jpg",
)
fun aVideoMediaInfo(): MediaInfo = MediaInfo(
"a video file.mp4",
MimeTypes.Mp4,
"14MB",
"mp4"
filename = "a video file.mp4",
caption = null,
mimeType = MimeTypes.Mp4,
formattedFileSize = "14MB",
fileExtension = "mp4",
)
fun aPdfMediaInfo(): MediaInfo = MediaInfo(
"a pdf file.pdf",
MimeTypes.Pdf,
"23MB",
"pdf"
filename = "a pdf file.pdf",
caption = null,
mimeType = MimeTypes.Pdf,
formattedFileSize = "23MB",
fileExtension = "pdf",
)
fun anApkMediaInfo(): MediaInfo = MediaInfo(
"an apk file.apk",
MimeTypes.Apk,
"50MB",
"apk"
filename = "an apk file.apk",
caption = null,
mimeType = MimeTypes.Apk,
formattedFileSize = "50MB",
fileExtension = "apk",
)
fun anAudioMediaInfo(): MediaInfo = MediaInfo(
"an audio file.mp3",
MimeTypes.Mp3,
"7MB",
"mp3"
filename = "an audio file.mp3",
caption = null,
mimeType = MimeTypes.Mp3,
formattedFileSize = "7MB",
fileExtension = "mp3",
)

View file

@ -92,7 +92,7 @@ class MediaViewerPresenter @AssistedInject constructor(
mediaLoader.downloadMediaFile(
source = inputs.mediaSource,
mimeType = inputs.mediaInfo.mimeType,
body = inputs.mediaInfo.name
body = inputs.mediaInfo.filename
)
.onSuccess {
mediaFile.value = it

View file

@ -322,7 +322,7 @@ private fun ThumbnailView(
if (isVisible) {
val mediaRequestData = MediaRequestData(
source = thumbnailSource,
kind = MediaRequestData.Kind.File(mediaInfo.name, mediaInfo.mimeType)
kind = MediaRequestData.Kind.File(mediaInfo.filename, mediaInfo.mimeType)
)
AsyncImage(
modifier = Modifier.fillMaxSize(),

View file

@ -157,7 +157,7 @@ class AndroidLocalMediaActions @Inject constructor(
@RequiresApi(Build.VERSION_CODES.Q)
private fun saveOnDiskUsingMediaStore(localMedia: LocalMedia) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, localMedia.info.name)
put(MediaStore.MediaColumns.DISPLAY_NAME, localMedia.info.filename)
put(MediaStore.MediaColumns.MIME_TYPE, localMedia.info.mimeType)
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
}
@ -175,7 +175,7 @@ class AndroidLocalMediaActions @Inject constructor(
private fun saveOnDiskUsingExternalStorageApi(localMedia: LocalMedia) {
val target = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
localMedia.info.name
localMedia.info.filename
)
localMedia.openStream()?.use { input ->
FileOutputStream(target).use { output ->

View file

@ -32,21 +32,36 @@ class AndroidLocalMediaFactory @Inject constructor(
private val fileSizeFormatter: FileSizeFormatter,
private val fileExtensionExtractor: FileExtensionExtractor,
) : LocalMediaFactory {
override fun createFromMediaFile(mediaFile: MediaFile, mediaInfo: MediaInfo): LocalMedia {
val uri = mediaFile.toFile().toUri()
return createFromUri(
uri = uri,
mimeType = mediaInfo.mimeType,
name = mediaInfo.name,
formattedFileSize = mediaInfo.formattedFileSize,
)
}
override fun createFromMediaFile(
mediaFile: MediaFile,
mediaInfo: MediaInfo,
): LocalMedia = createFromUri(
uri = mediaFile.toFile().toUri(),
mimeType = mediaInfo.mimeType,
name = mediaInfo.filename,
caption = mediaInfo.caption,
formattedFileSize = mediaInfo.formattedFileSize,
)
override fun createFromUri(
uri: Uri,
mimeType: String?,
name: String?,
formattedFileSize: String?
): LocalMedia = createFromUri(
uri = uri,
mimeType = mimeType,
name = name,
caption = null,
formattedFileSize = formattedFileSize,
)
private fun createFromUri(
uri: Uri,
mimeType: String?,
name: String?,
caption: String?,
formattedFileSize: String?
): LocalMedia {
val resolvedMimeType = mimeType ?: context.getMimeType(uri) ?: MimeTypes.OctetStream
val fileName = name ?: context.getFileName(uri) ?: ""
@ -56,7 +71,8 @@ class AndroidLocalMediaFactory @Inject constructor(
uri = uri,
info = MediaInfo(
mimeType = resolvedMimeType,
name = fileName,
filename = fileName,
caption = caption,
formattedFileSize = fileSize,
fileExtension = fileExtension
)

View file

@ -29,7 +29,8 @@ class AndroidLocalMediaFactoryTest {
assertThat(result.uri.toString()).endsWith("aPath")
assertThat(result.info).isEqualTo(
MediaInfo(
name = "an image file.jpg",
filename = "an image file.jpg",
caption = null,
mimeType = MimeTypes.Jpeg,
formattedFileSize = "4MB",
fileExtension = "jpg",

View file

@ -32,7 +32,8 @@ class FakeLocalMediaFactory(
override fun createFromUri(uri: Uri, mimeType: String?, name: String?, formattedFileSize: String?): LocalMedia {
val safeName = name ?: fallbackName
val mediaInfo = MediaInfo(
name = safeName,
filename = safeName,
caption = null,
mimeType = mimeType ?: fallbackMimeType,
formattedFileSize = formattedFileSize ?: fallbackFileSize,
fileExtension = fileExtensionExtractor.extractFromName(safeName)

View file

@ -265,15 +265,15 @@ class DefaultNotifiableEventResolver @Inject constructor(
senderDisambiguatedDisplayName: String,
): String {
return when (val messageType = content.messageType) {
is AudioMessageType -> messageType.body
is AudioMessageType -> messageType.bestDescription
is VoiceMessageType -> stringProvider.getString(CommonStrings.common_voice_message)
is EmoteMessageType -> "* $senderDisambiguatedDisplayName ${messageType.body}"
is FileMessageType -> messageType.body
is ImageMessageType -> messageType.body
is StickerMessageType -> messageType.body
is FileMessageType -> messageType.bestDescription
is ImageMessageType -> messageType.bestDescription
is StickerMessageType -> messageType.bestDescription
is NoticeMessageType -> messageType.body
is TextMessageType -> messageType.toPlainText(permalinkParser = permalinkParser)
is VideoMessageType -> messageType.body
is VideoMessageType -> messageType.bestDescription
is LocationMessageType -> messageType.body
is OtherMessageType -> messageType.body
}
@ -299,7 +299,7 @@ class DefaultNotifiableEventResolver @Inject constructor(
.getMediaFile(
mediaSource = messageType.source,
mimeType = messageType.info?.mimetype,
body = messageType.body,
body = messageType.filename,
)
is VideoMessageType -> null // Use the thumbnail here?
else -> null

View file

@ -47,7 +47,7 @@ interface NotificationMediaRepo {
*
* @param mediaSource the media source of the media.
* @param mimeType the mime type of the media.
* @param body the body of the message.
* @param body optional body which will be used to name the file.
* @return A [Result] holding either the media [File] from the cache directory or an [Exception].
*/
suspend fun getMediaFile(

View file

@ -187,7 +187,7 @@ class DefaultNotifiableEventResolverTest {
aNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
messageType = AudioMessageType(body = "Audio", MediaSource("url"), null)
messageType = AudioMessageType("Audio", null, null, MediaSource("url"), null)
),
)
)
@ -206,7 +206,7 @@ class DefaultNotifiableEventResolverTest {
aNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
messageType = VideoMessageType(body = "Video", null, null, MediaSource("url"), null)
messageType = VideoMessageType("Video", null, null, MediaSource("url"), null)
),
)
)
@ -225,7 +225,7 @@ class DefaultNotifiableEventResolverTest {
aNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
messageType = VoiceMessageType(body = "Voice", MediaSource("url"), null, null)
messageType = VoiceMessageType("Voice", null, null, MediaSource("url"), null, null)
),
)
)
@ -263,7 +263,7 @@ class DefaultNotifiableEventResolverTest {
aNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
messageType = StickerMessageType("Sticker", MediaSource("url"), null),
messageType = StickerMessageType("Sticker", null, null, MediaSource("url"), null),
),
)
)
@ -282,7 +282,7 @@ class DefaultNotifiableEventResolverTest {
aNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
messageType = FileMessageType("File", MediaSource("url"), null),
messageType = FileMessageType("File", null, null, MediaSource("url"), null),
),
)
)