Skip to content

Commit 91794f4

Browse files
committed
Measure tag's actual width to know when to ellipsize or not
1 parent 59625b2 commit 91794f4

File tree

5 files changed

+43
-30
lines changed

5 files changed

+43
-30
lines changed

app/src/main/java/com/infomaniak/mail/ui/main/folder/ThreadListAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class ThreadListAdapter @Inject constructor(
258258
tag = thread.folderName,
259259
tagColor = TagColor(R.color.folderTagBackground, R.color.folderTagTextColor),
260260
ellipsizeConfiguration = SubjectFormatter.EllipsizeConfiguration(
261-
maxWidth = context.resources.getDimension(R.dimen.folderNameTagMaxSize).toInt(),
261+
maxWidth = context.resources.getDimension(R.dimen.folderNameTagMaxSize),
262262
truncateAt = TruncateAt.END,
263263
),
264264
)

app/src/main/java/com/infomaniak/mail/ui/main/thread/RoundedBackgroundSpan.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Infomaniak Mail - Android
3-
* Copyright (C) 2023 Infomaniak Network SA
3+
* Copyright (C) 2023-2024 Infomaniak Network SA
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -95,5 +95,7 @@ class RoundedBackgroundSpan(
9595
private const val LEFT_MARGIN = 4
9696
private const val PADDING = 16
9797
private const val VERTICAL_OFFSET = 4
98+
99+
fun getTotalHorizontalSpace(): Int = PADDING * 2 + LEFT_MARGIN
98100
}
99101
}

app/src/main/java/com/infomaniak/mail/ui/main/thread/SubjectFormatter.kt

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
package com.infomaniak.mail.ui.main.thread
1919

2020
import android.content.Context
21-
import android.content.res.Resources
2221
import android.graphics.Paint
2322
import android.text.StaticLayout
2423
import android.text.TextPaint
@@ -29,20 +28,21 @@ import com.infomaniak.mail.MatomoMail.trackExternalEvent
2928
import com.infomaniak.mail.R
3029
import com.infomaniak.mail.data.models.thread.Thread
3130
import com.infomaniak.mail.utils.ExternalUtils.findExternalRecipients
31+
import com.infomaniak.mail.utils.Utils
3232
import com.infomaniak.mail.utils.extensions.MergedContactDictionary
3333
import com.infomaniak.mail.utils.extensions.formatSubject
3434
import com.infomaniak.mail.utils.extensions.postfixWithTag
3535
import javax.inject.Inject
3636
import javax.inject.Singleton
3737

3838
@Singleton
39-
class SubjectFormatter @Inject constructor(private val context: Context) {
39+
class SubjectFormatter @Inject constructor(private val appContext: Context) {
4040

4141
fun generateSubjectContent(
4242
subjectData: SubjectData,
4343
onExternalClicked: (String) -> Unit,
4444
): Pair<String, CharSequence> = with(subjectData) {
45-
val subject = context.formatSubject(thread.subject)
45+
val subject = appContext.formatSubject(thread.subject)
4646

4747
val spannedSubjectWithExternal = handleExternals(subject, onExternalClicked)
4848
val spannedSubjectWithFolder = handleFolders(spannedSubjectWithExternal)
@@ -67,14 +67,14 @@ class SubjectFormatter @Inject constructor(private val context: Context) {
6767
externalRecipientQuantity: Int,
6868
externalRecipientEmail: String?,
6969
onExternalClicked: (String) -> Unit,
70-
) = context.postfixWithTag(
70+
) = appContext.postfixWithTag(
7171
previousContent,
7272
R.string.externalTag,
7373
TagColor(R.color.externalTagBackground, R.color.externalTagOnBackground),
7474
) {
75-
context.trackExternalEvent("threadTag")
75+
appContext.trackExternalEvent("threadTag")
7676

77-
val description = context.resources.getQuantityString(
77+
val description = appContext.resources.getQuantityString(
7878
R.plurals.externalDialogDescriptionExpeditor,
7979
externalRecipientQuantity,
8080
externalRecipientEmail,
@@ -94,7 +94,7 @@ class SubjectFormatter @Inject constructor(private val context: Context) {
9494
previousContent: CharSequence,
9595
folderName: String,
9696
ellipsizeConfiguration: EllipsizeConfiguration?,
97-
) = context.postfixWithTag(
97+
) = appContext.postfixWithTag(
9898
previousContent,
9999
folderName,
100100
TagColor(R.color.folderTagBackground, R.color.folderTagTextColor),
@@ -104,14 +104,29 @@ class SubjectFormatter @Inject constructor(private val context: Context) {
104104
private fun getFolderName(thread: Thread) = if (thread.messages.size > 1) "" else thread.folderName
105105

106106
private fun getEllipsizeConfiguration(tag: String): EllipsizeConfiguration? {
107-
val paddingsInPixels = (context.resources.getDimension(R.dimen.threadHorizontalMargin) * 2).toInt()
108-
val widthInPixels = Resources.getSystem().displayMetrics.widthPixels - paddingsInPixels
107+
val paddingsInPixels = (appContext.resources.getDimension(R.dimen.threadHorizontalMargin) * 2).toInt()
108+
val containerWidth = appContext.resources.displayMetrics.widthPixels - paddingsInPixels
109109

110-
val tagTextPaint = getTagsPaint(context)
111-
val layoutWithTag = StaticLayout.Builder.obtain(tag, 0, tag.length, tagTextPaint, widthInPixels).build()
112-
113-
return layoutWithTag.takeIf { it.lineCount > 1 }?.let {
114-
EllipsizeConfiguration(widthInPixels, TruncateAt.MIDDLE, withNewLine = true)
110+
// spannedTagForMeasurement only contains the tag's text itself and its formatting, nothing more nothing less
111+
val spannedTagForMeasurement = with(postFixWithFolder("", tag, null)) {
112+
subSequence(Utils.TAG_SEPARATOR.length, length)
113+
}
114+
val layout = StaticLayout.Builder.obtain(
115+
spannedTagForMeasurement,
116+
0,
117+
spannedTagForMeasurement.length,
118+
TextPaint(Paint.ANTI_ALIAS_FLAG),
119+
containerWidth,
120+
).build()
121+
val tagWidth = layout.getLineWidth(0)
122+
123+
return if (tagWidth >= containerWidth) {
124+
val roundedBackgroundSpanHorizontalSpace = RoundedBackgroundSpan.getTotalHorizontalSpace()
125+
val tagAvailableWidth = (containerWidth - roundedBackgroundSpanHorizontalSpace).toFloat()
126+
127+
EllipsizeConfiguration(tagAvailableWidth, TruncateAt.MIDDLE)
128+
} else {
129+
null
115130
}
116131
}
117132

@@ -123,9 +138,8 @@ class SubjectFormatter @Inject constructor(private val context: Context) {
123138
)
124139

125140
data class EllipsizeConfiguration(
126-
val maxWidth: Int,
141+
val maxWidth: Float,
127142
val truncateAt: TruncateAt = TruncateAt.MIDDLE,
128-
val withNewLine: Boolean = false,
129143
)
130144

131145
data class TagColor(@ColorRes val backgroundColorRes: Int, @ColorRes val textColorRes: Int)

app/src/main/java/com/infomaniak/mail/utils/extensions/Extensions.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -515,31 +515,29 @@ fun Context.postfixWithTag(
515515
*/
516516
fun Context.postfixWithTag(
517517
original: CharSequence = "",
518-
tag: CharSequence,
518+
tag: String,
519519
tagColor: TagColor,
520520
ellipsizeConfiguration: EllipsizeConfiguration? = null,
521521
onClicked: (() -> Unit)? = null,
522522
): Spannable {
523523

524-
fun getEllipsizedTag(): CharSequence {
525-
val baseTag = "$TAG_SEPARATOR$tag"
524+
fun getEllipsizedTagContent(): String {
526525
return ellipsizeConfiguration?.let {
527-
val modifiedTag = if (ellipsizeConfiguration.withNewLine) "\n$baseTag" else baseTag
528526
TextUtils.ellipsize(
529-
modifiedTag,
527+
tag,
530528
getTagsPaint(this),
531-
ellipsizeConfiguration.maxWidth.toFloat(),
529+
ellipsizeConfiguration.maxWidth,
532530
ellipsizeConfiguration.truncateAt
533-
)
534-
} ?: baseTag
531+
).toString()
532+
} ?: tag
535533
}
536534

537-
val ellipsizedTag = getEllipsizedTag()
538-
val postFixed = TextUtils.concat(original, ellipsizedTag)
535+
val ellipsizedTagContent = getEllipsizedTagContent()
536+
val postFixed = TextUtils.concat(original, TAG_SEPARATOR, ellipsizedTagContent)
539537

540538
return postFixed.toSpannable().apply {
541539
val startIndex = original.length + TAG_SEPARATOR.length
542-
val endIndex = startIndex + ellipsizedTag.length - TAG_SEPARATOR.length
540+
val endIndex = startIndex + ellipsizedTagContent.length
543541

544542
with(tagColor) {
545543
setTagSpan(this@postfixWithTag, startIndex, endIndex, backgroundColorRes, textColorRes)

app/src/main/res/layout/fragment_thread.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@
9393
tools:text="@tools:sample/lorem[7]" />
9494

9595
</com.google.android.material.appbar.CollapsingToolbarLayout>
96-
9796
</com.google.android.material.appbar.AppBarLayout>
9897

9998
<androidx.core.widget.NestedScrollView

0 commit comments

Comments
 (0)