Skip to content

Commit ebfa50c

Browse files
authored
Merge pull request #3816 from element-hq/feature/bma/moreCaptionWork
Iteration on caption
2 parents a678fe4 + f2c63a5 commit ebfa50c

File tree

11 files changed

+84
-29
lines changed

11 files changed

+84
-29
lines changed

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ fun TimelineItemVideoView(
7070
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
7171
modifier: Modifier = Modifier,
7272
) {
73-
val description = stringResource(CommonStrings.common_image)
73+
val description = stringResource(CommonStrings.common_video)
7474
Column(
7575
modifier = modifier.semantics { contentDescription = description }
7676
) {
7777
val containerModifier = if (content.showCaption) {
7878
Modifier
79-
.padding(top = 6.dp)
80-
.clip(RoundedCornerShape(6.dp))
79+
.padding(top = 6.dp)
80+
.clip(RoundedCornerShape(6.dp))
8181
} else {
8282
Modifier
8383
}
@@ -93,8 +93,8 @@ fun TimelineItemVideoView(
9393
var isLoaded by remember { mutableStateOf(false) }
9494
AsyncImage(
9595
modifier = Modifier
96-
.fillMaxWidth()
97-
.then(if (isLoaded) Modifier.background(Color.White) else Modifier),
96+
.fillMaxWidth()
97+
.then(if (isLoaded) Modifier.background(Color.White) else Modifier),
9898
model = MediaRequestData(
9999
source = content.thumbnailSource,
100100
kind = MediaRequestData.Kind.File(

libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ class DefaultPinnedMessagesBannerFormatter @Inject constructor(
9595
messageType.bestDescription.prefixWith(CommonStrings.common_audio)
9696
}
9797
is VoiceMessageType -> {
98-
messageType.bestDescription.prefixWith(CommonStrings.common_voice_message)
98+
// In this case, do not use bestDescription, because the filename is useless, only use the caption if available.
99+
messageType.caption?.prefixWith(sp.getString(CommonStrings.common_voice_message))
100+
?: sp.getString(CommonStrings.common_voice_message)
99101
}
100102
is OtherMessageType -> {
101103
messageType.body

libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,25 +110,27 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
110110
messageType.toPlainText(permalinkParser)
111111
}
112112
is VideoMessageType -> {
113-
sp.getString(CommonStrings.common_video)
113+
messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_video))
114114
}
115115
is ImageMessageType -> {
116-
sp.getString(CommonStrings.common_image)
116+
messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_image))
117117
}
118118
is StickerMessageType -> {
119-
sp.getString(CommonStrings.common_sticker)
119+
messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_sticker))
120120
}
121121
is LocationMessageType -> {
122122
sp.getString(CommonStrings.common_shared_location)
123123
}
124124
is FileMessageType -> {
125-
sp.getString(CommonStrings.common_file)
125+
messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_file))
126126
}
127127
is AudioMessageType -> {
128-
sp.getString(CommonStrings.common_audio)
128+
messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_audio))
129129
}
130130
is VoiceMessageType -> {
131-
sp.getString(CommonStrings.common_voice_message)
131+
// In this case, do not use bestDescription, because the filename is useless, only use the caption if available.
132+
messageType.caption?.prefixWith(sp.getString(CommonStrings.common_voice_message))
133+
?: sp.getString(CommonStrings.common_voice_message)
132134
}
133135
is OtherMessageType -> {
134136
messageType.body
@@ -140,7 +142,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
140142
return message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
141143
}
142144

143-
private fun String.prefixIfNeeded(
145+
private fun CharSequence.prefixIfNeeded(
144146
senderDisambiguatedDisplayName: String,
145147
isDmRoom: Boolean,
146148
isOutgoing: Boolean,

libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ class DefaultPinnedMessagesBannerFormatterTest {
159159
val expectedResult = when (type) {
160160
is VideoMessageType,
161161
is AudioMessageType,
162-
is VoiceMessageType,
163162
is ImageMessageType,
164163
is StickerMessageType,
165164
is FileMessageType,
166165
is LocationMessageType -> AnnotatedString::class.java
166+
is VoiceMessageType,
167167
is EmoteMessageType,
168168
is TextMessageType,
169169
is NoticeMessageType,
@@ -176,7 +176,7 @@ class DefaultPinnedMessagesBannerFormatterTest {
176176
val expectedResult = when (type) {
177177
is VideoMessageType -> "Video: Shared body"
178178
is AudioMessageType -> "Audio: Shared body"
179-
is VoiceMessageType -> "Voice message: Shared body"
179+
is VoiceMessageType -> "Voice message"
180180
is ImageMessageType -> "Image: Shared body"
181181
is StickerMessageType -> "Sticker: Shared body"
182182
is FileMessageType -> "File: Shared body"

libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -208,32 +208,51 @@ class DefaultRoomLastMessageFormatterTest {
208208

209209
// Verify results of DM mode
210210
for ((type, result) in resultsInDm) {
211+
val string = result.toString()
211212
val expectedResult = when (type) {
212-
is VideoMessageType -> "Video"
213-
is AudioMessageType -> "Audio"
213+
is VideoMessageType -> "Video: Shared body"
214+
is AudioMessageType -> "Audio: Shared body"
214215
is VoiceMessageType -> "Voice message"
215-
is ImageMessageType -> "Image"
216-
is StickerMessageType -> "Sticker"
217-
is FileMessageType -> "File"
216+
is ImageMessageType -> "Image: Shared body"
217+
is StickerMessageType -> "Sticker: Shared body"
218+
is FileMessageType -> "File: Shared body"
218219
is LocationMessageType -> "Shared location"
219220
is EmoteMessageType -> "* $senderName ${type.body}"
220221
is TextMessageType,
221222
is NoticeMessageType,
222223
is OtherMessageType -> body
223224
}
224-
assertWithMessage("$type was not properly handled for DM").that(result).isEqualTo(expectedResult)
225+
val shouldCreateAnnotatedString = when (type) {
226+
is VideoMessageType -> true
227+
is AudioMessageType -> true
228+
is VoiceMessageType -> false
229+
is ImageMessageType -> true
230+
is StickerMessageType -> true
231+
is FileMessageType -> true
232+
is LocationMessageType -> false
233+
is EmoteMessageType -> false
234+
is TextMessageType -> false
235+
is NoticeMessageType -> false
236+
is OtherMessageType -> false
237+
}
238+
if (shouldCreateAnnotatedString) {
239+
assertWithMessage("$type doesn't produce an AnnotatedString")
240+
.that(result)
241+
.isInstanceOf(AnnotatedString::class.java)
242+
}
243+
assertWithMessage("$type was not properly handled for DM").that(string).isEqualTo(expectedResult)
225244
}
226245

227246
// Verify results of Room mode
228247
for ((type, result) in resultsInRoom) {
229248
val string = result.toString()
230249
val expectedResult = when (type) {
231-
is VideoMessageType -> "$expectedPrefix: Video"
232-
is AudioMessageType -> "$expectedPrefix: Audio"
250+
is VideoMessageType -> "$expectedPrefix: Video: Shared body"
251+
is AudioMessageType -> "$expectedPrefix: Audio: Shared body"
233252
is VoiceMessageType -> "$expectedPrefix: Voice message"
234-
is ImageMessageType -> "$expectedPrefix: Image"
235-
is StickerMessageType -> "$expectedPrefix: Sticker"
236-
is FileMessageType -> "$expectedPrefix: File"
253+
is ImageMessageType -> "$expectedPrefix: Image: Shared body"
254+
is StickerMessageType -> "$expectedPrefix: Sticker: Shared body"
255+
is FileMessageType -> "$expectedPrefix: File: Shared body"
237256
is LocationMessageType -> "$expectedPrefix: Shared location"
238257
is TextMessageType,
239258
is NoticeMessageType,
@@ -249,7 +268,8 @@ class DefaultRoomLastMessageFormatterTest {
249268
is FileMessageType -> true
250269
is LocationMessageType -> false
251270
is EmoteMessageType -> false
252-
is TextMessageType, is NoticeMessageType -> true
271+
is TextMessageType -> true
272+
is NoticeMessageType -> true
253273
is OtherMessageType -> true
254274
}
255275
if (shouldCreateAnnotatedString) {

libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class DefaultNotifiableEventResolver @Inject constructor(
107107
senderDisambiguatedDisplayName = senderDisambiguatedDisplayName,
108108
body = messageBody,
109109
imageUriString = content.fetchImageIfPresent(client)?.toString(),
110+
imageMimeType = content.getImageMimetype(),
110111
roomName = roomDisplayName,
111112
roomIsDm = isDm,
112113
roomAvatarPath = roomAvatarUrl,
@@ -316,6 +317,17 @@ class DefaultNotifiableEventResolver @Inject constructor(
316317
}
317318
.getOrNull()
318319
}
320+
321+
private suspend fun NotificationContent.MessageLike.RoomMessage.getImageMimetype(): String? {
322+
if (appPreferencesStore.doesHideImagesAndVideosFlow().first()) {
323+
return null
324+
}
325+
return when (val messageType = messageType) {
326+
is ImageMessageType -> messageType.info?.mimetype
327+
is VideoMessageType -> null // Use the thumbnail here?
328+
else -> null
329+
}
330+
}
319331
}
320332

321333
@Suppress("LongParameterList")
@@ -333,6 +345,7 @@ internal fun buildNotifiableMessageEvent(
333345
// We cannot use Uri? type here, as that could trigger a
334346
// NotSerializableException when persisting this to storage
335347
imageUriString: String? = null,
348+
imageMimeType: String? = null,
336349
threadId: ThreadId? = null,
337350
roomName: String? = null,
338351
roomIsDm: Boolean = false,
@@ -358,6 +371,7 @@ internal fun buildNotifiableMessageEvent(
358371
senderDisambiguatedDisplayName = senderDisambiguatedDisplayName,
359372
body = body,
360373
imageUriString = imageUriString,
374+
imageMimeType = imageMimeType,
361375
threadId = threadId,
362376
roomName = roomName,
363377
roomIsDm = roomIsDm,

libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class NotificationBroadcastReceiverHandler @Inject constructor(
150150
?: stringProvider.getString(R.string.notification_sender_me),
151151
body = message,
152152
imageUriString = null,
153+
imageMimeType = null,
153154
threadId = threadId,
154155
roomName = room.displayName,
155156
roomIsDm = room.isDm,

libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,22 @@ class DefaultNotificationCreator @Inject constructor(
419419
senderPerson
420420
).also { message ->
421421
event.imageUri?.let {
422-
message.setData("image/", it)
422+
message.setData(event.imageMimeType ?: "image/", it)
423423
}
424424
message.extras.putString(MESSAGE_EVENT_ID, event.eventId.value)
425425
}
426426
addMessage(message)
427+
428+
// Add additional message for captions
429+
if (event.imageUri != null && event.body != null) {
430+
addMessage(
431+
MessagingStyle.Message(
432+
event.body,
433+
event.timestamp,
434+
senderPerson,
435+
)
436+
)
437+
}
427438
}
428439
}
429440
}

libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ data class NotifiableMessageEvent(
3131
val body: String?,
3232
// We cannot use Uri? type here, as that could trigger a
3333
// NotSerializableException when persisting this to storage
34-
val imageUriString: String?,
34+
private val imageUriString: String?,
35+
val imageMimeType: String?,
3536
val threadId: ThreadId?,
3637
val roomName: String?,
3738
val roomIsDm: Boolean = false,

libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ class DefaultNotifiableEventResolverTest {
590590
senderDisambiguatedDisplayName = A_USER_NAME_2,
591591
body = "Call in progress (unsupported)",
592592
imageUriString = null,
593+
imageMimeType = null,
593594
threadId = null,
594595
roomName = A_ROOM_NAME,
595596
roomAvatarPath = null,
@@ -669,6 +670,7 @@ class DefaultNotifiableEventResolverTest {
669670
canBeReplaced = false,
670671
isRedacted = false,
671672
imageUriString = null,
673+
imageMimeType = null,
672674
type = EventType.CALL_NOTIFY,
673675
)
674676
)
@@ -704,6 +706,7 @@ class DefaultNotifiableEventResolverTest {
704706
canBeReplaced = false,
705707
isRedacted = false,
706708
imageUriString = null,
709+
imageMimeType = null,
707710
type = EventType.CALL_NOTIFY,
708711
)
709712
)

0 commit comments

Comments
 (0)