Limit the text length in the 'in reply to' preview (#4491)
* Limit the text length in the 'in reply to' preview Otherwise, very long texts with no line breaks can cause a Compose crash
This commit is contained in:
parent
338267d4e3
commit
f59b26eb10
3 changed files with 28 additions and 8 deletions
|
|
@ -26,6 +26,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||||
|
import io.element.android.libraries.core.extensions.toSafeLength
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
@ -35,11 +36,6 @@ import javax.inject.Inject
|
||||||
class DefaultMessageSummaryFormatter @Inject constructor(
|
class DefaultMessageSummaryFormatter @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
) : MessageSummaryFormatter {
|
) : MessageSummaryFormatter {
|
||||||
companion object {
|
|
||||||
// Max characters to display in the summary message. This works around https://github.com/element-hq/element-x-android/issues/2105
|
|
||||||
private const val MAX_SAFE_LENGTH = 500
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun format(event: TimelineItem.Event): String {
|
override fun format(event: TimelineItem.Event): String {
|
||||||
return when (event.content) {
|
return when (event.content) {
|
||||||
is TimelineItemTextBasedContent -> event.content.plainText
|
is TimelineItemTextBasedContent -> event.content.plainText
|
||||||
|
|
@ -58,6 +54,8 @@ class DefaultMessageSummaryFormatter @Inject constructor(
|
||||||
is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio)
|
is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio)
|
||||||
is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call)
|
is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call)
|
||||||
is TimelineItemCallNotifyContent -> context.getString(CommonStrings.common_call_started)
|
is TimelineItemCallNotifyContent -> context.getString(CommonStrings.common_call_started)
|
||||||
}.take(MAX_SAFE_LENGTH)
|
}
|
||||||
|
// Truncate the message to a safe length to avoid crashes in Compose
|
||||||
|
.toSafeLength()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,3 +98,22 @@ fun String.ensureEndsLeftToRight() = if (containsRtLOverride()) "$this$LTR_OVERR
|
||||||
fun String.containsRtLOverride() = contains(RTL_OVERRIDE_CHAR)
|
fun String.containsRtLOverride() = contains(RTL_OVERRIDE_CHAR)
|
||||||
|
|
||||||
fun String.filterDirectionOverrides() = filterNot { it == RTL_OVERRIDE_CHAR || it == LTR_OVERRIDE_CHAR }
|
fun String.filterDirectionOverrides() = filterNot { it == RTL_OVERRIDE_CHAR || it == LTR_OVERRIDE_CHAR }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This works around https://github.com/element-hq/element-x-android/issues/2105.
|
||||||
|
* @param maxLength Max characters to retrieve. Defaults to `500`.
|
||||||
|
* @param ellipsize Whether to add an ellipsis (`…`) char at the end or not. Defaults to `false`.
|
||||||
|
* @return The string truncated to [maxLength] characters, with an optional ellipsis if larger.
|
||||||
|
*/
|
||||||
|
fun String.toSafeLength(
|
||||||
|
maxLength: Int = 500,
|
||||||
|
ellipsize: Boolean = false,
|
||||||
|
): String {
|
||||||
|
return if (ellipsize) {
|
||||||
|
ellipsize(maxLength)
|
||||||
|
} else if (length > maxLength) {
|
||||||
|
take(maxLength)
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
|
import io.element.android.libraries.core.extensions.toSafeLength
|
||||||
import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom
|
import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom
|
||||||
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
|
|
@ -152,8 +153,10 @@ private fun ReplyToContentText(metadata: InReplyToMetadata?) {
|
||||||
val text = when (metadata) {
|
val text = when (metadata) {
|
||||||
InReplyToMetadata.Redacted -> stringResource(id = CommonStrings.common_message_removed)
|
InReplyToMetadata.Redacted -> stringResource(id = CommonStrings.common_message_removed)
|
||||||
InReplyToMetadata.UnableToDecrypt -> stringResource(id = CommonStrings.common_waiting_for_decryption_key)
|
InReplyToMetadata.UnableToDecrypt -> stringResource(id = CommonStrings.common_waiting_for_decryption_key)
|
||||||
is InReplyToMetadata.Text -> metadata.text
|
// Add a limit to the text length to avoid a crash in Compose
|
||||||
is InReplyToMetadata.Thumbnail -> metadata.text
|
is InReplyToMetadata.Text -> metadata.text.toSafeLength()
|
||||||
|
// Add a limit to the text length to avoid a crash in Compose
|
||||||
|
is InReplyToMetadata.Thumbnail -> metadata.text.toSafeLength()
|
||||||
null -> ""
|
null -> ""
|
||||||
}
|
}
|
||||||
val iconResourceId = when (metadata) {
|
val iconResourceId = when (metadata) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue