From ad08a4325f76aa97f6740a633038b7e979ff563f Mon Sep 17 00:00:00 2001 From: Louis Legrand Date: Mon, 17 Feb 2025 11:19:48 +0100 Subject: [PATCH] fix(CON-271) : Fix rich text issue --- consentium-ui/build.gradle.kts | 5 +- .../ConsentiumUIDetailConsentComponent.kt | 4 +- .../ConsentiumUIGeneralConsentComponent.kt | 37 +++++++------ .../ui/components/core/PurposeComponent.kt | 4 +- .../ui/utils/HtmlToAnnotatedString.kt | 55 +++---------------- gradle/libs.versions.toml | 3 + 6 files changed, 40 insertions(+), 68 deletions(-) diff --git a/consentium-ui/build.gradle.kts b/consentium-ui/build.gradle.kts index 484c953..f8b87c3 100644 --- a/consentium-ui/build.gradle.kts +++ b/consentium-ui/build.gradle.kts @@ -102,10 +102,11 @@ dependencies { implementation(libs.coil) implementation(libs.coil.network) + // Rich text formatting + implementation(libs.rich.text) + // Tests testImplementation(libs.test.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.test.espresso) - - } \ No newline at end of file diff --git a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIDetailConsentComponent.kt b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIDetailConsentComponent.kt index a83d86c..9e1dd10 100644 --- a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIDetailConsentComponent.kt +++ b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIDetailConsentComponent.kt @@ -29,7 +29,7 @@ import fr.openium.consentium_ui.ui.components.core.button.ConsentiumUIButtonStyl import fr.openium.consentium_ui.ui.components.style.ConsentiumUITheme import fr.openium.consentium_ui.ui.model.DetailConsentUI import fr.openium.consentium_ui.ui.model.LoadingElement -import fr.openium.consentium_ui.ui.utils.htmlToAnnotatedString +import fr.openium.consentium_ui.ui.utils.toRichHtmlString @Composable @@ -73,7 +73,7 @@ internal fun ConsentiumUIDetailConsentComponent( Spacer(modifier = Modifier.height(25.dp)) Text( - text = htmlToAnnotatedString(detailConsentUI.conservationDurationText), + text = detailConsentUI.conservationDurationText.toRichHtmlString(), style = ConsentiumUITheme.typography.p3, color = ConsentiumUITheme.colors.onSurface, ) diff --git a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIGeneralConsentComponent.kt b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIGeneralConsentComponent.kt index 76ef21d..b3d5b91 100644 --- a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIGeneralConsentComponent.kt +++ b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/ConsentiumUIGeneralConsentComponent.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage @@ -25,7 +26,7 @@ import fr.openium.consentium_ui.ui.components.core.button.ConsentiumUIButtonStyl import fr.openium.consentium_ui.ui.components.style.ConsentiumUITheme import fr.openium.consentium_ui.ui.model.GeneralConsentUI import fr.openium.consentium_ui.ui.model.LoadingElement -import fr.openium.consentium_ui.ui.utils.htmlToAnnotatedString +import fr.openium.consentium_ui.ui.utils.toRichHtmlString @Composable internal fun ConsentiumUIGeneralConsentComponent( @@ -42,36 +43,40 @@ internal fun ConsentiumUIGeneralConsentComponent( .fillMaxSize() .padding(horizontal = 24.dp), ) { + if (generalConsentUI.iconUrl != null) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + AsyncImage( + modifier = Modifier.heightIn(min = 48.dp), + model = generalConsentUI.iconUrl, + contentDescription = "Image", + contentScale = ContentScale.FillBounds, + ) + } - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center, - ) { - AsyncImage( - modifier = Modifier.heightIn(min = 48.dp), - model = generalConsentUI.iconUrl, - contentDescription = "Image", - contentScale = ContentScale.FillBounds, - ) + Spacer(modifier = Modifier.height(24.dp)) } - Spacer(modifier = Modifier.height(24.dp)) - Text( - text = htmlToAnnotatedString(generalConsentUI.mainConsentText), + text = generalConsentUI.mainConsentText.toRichHtmlString(), style = ConsentiumUITheme.typography.p3, textAlign = TextAlign.Start, color = ConsentiumUITheme.colors.onSurface, + overflow = TextOverflow.Ellipsis, ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(16.dp)) TextLink( text = stringResource(R.string.cookies), onclick = onClickCookiesPolicies, ) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier + .heightIn(16.dp) + .weight(1f)) TextLink( text = stringResource(R.string.refuse), diff --git a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/core/PurposeComponent.kt b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/core/PurposeComponent.kt index 4fca922..23a4aa3 100644 --- a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/core/PurposeComponent.kt +++ b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/components/core/PurposeComponent.kt @@ -21,7 +21,7 @@ import fr.openium.consentium_ui.ui.components.core.toggle.ConsentiumUISwitch import fr.openium.consentium_ui.ui.components.style.ConsentiumUITheme import fr.openium.consentium_ui.ui.model.PurposeStatusUI import fr.openium.consentium_ui.ui.model.PurposeUI -import fr.openium.consentium_ui.ui.utils.htmlToAnnotatedString +import fr.openium.consentium_ui.ui.utils.toRichHtmlString @Composable internal fun PurposeComponent( @@ -81,7 +81,7 @@ internal fun PurposeComponent( Spacer(modifier = Modifier.height(10.dp)) Text( - text = htmlToAnnotatedString(purposeUI.description), + text = purposeUI.description.toRichHtmlString(), style = ConsentiumUITheme.typography.p3, color = ConsentiumUITheme.colors.onSurface, ) diff --git a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/utils/HtmlToAnnotatedString.kt b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/utils/HtmlToAnnotatedString.kt index 98d02c3..0203100 100644 --- a/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/utils/HtmlToAnnotatedString.kt +++ b/consentium-ui/src/main/java/fr/openium/consentium_ui/ui/utils/HtmlToAnnotatedString.kt @@ -1,54 +1,17 @@ package fr.openium.consentium_ui.ui.utils -import android.text.ParcelableSpan -import android.text.Spanned +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextDecoration -import androidx.compose.ui.text.withStyle -import androidx.core.text.HtmlCompat +import com.mohamedrejeb.richeditor.model.rememberRichTextState -fun htmlToAnnotatedString(html: String): AnnotatedString { - val spanned: Spanned = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY) - return buildAnnotatedString { - val text = spanned.toString() - var start = 0 - spanned.getSpans(0, spanned.length, Any::class.java).map { it as ParcelableSpan }.forEach { span -> - val startSpan = spanned.getSpanStart(span) - val endSpan = spanned.getSpanEnd(span) +@Composable +fun String.toRichHtmlString(): AnnotatedString { + val state = rememberRichTextState() - // Ajoutez le texte précédent sans style - if (start < startSpan) { - append(text.substring(start, startSpan)) - } - - // Ajoutez le texte stylé - withStyle(style = span.toSpanStyle()) { - append(text.substring(startSpan, endSpan)) - } - start = endSpan - } - - // Ajoutez le texte restant sans style - if (start < text.length) { - append(text.substring(start, text.length).trimEnd()) - } + LaunchedEffect(this) { + state.setHtml(this@toRichHtmlString) } -} -fun ParcelableSpan.toSpanStyle(): SpanStyle { - return when (this) { - is android.text.style.StyleSpan -> { - when (style) { - android.graphics.Typeface.BOLD -> SpanStyle(fontWeight = androidx.compose.ui.text.font.FontWeight.Bold) - android.graphics.Typeface.ITALIC -> SpanStyle(fontStyle = androidx.compose.ui.text.font.FontStyle.Italic) - else -> SpanStyle() - } - } - - is android.text.style.UnderlineSpan -> SpanStyle(textDecoration = TextDecoration.Underline) - is android.text.style.StrikethroughSpan -> SpanStyle(textDecoration = TextDecoration.LineThrough) - else -> SpanStyle() - } + return state.annotatedString } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e010497..bd64599 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -144,6 +144,9 @@ ga4 = { module = "com.google.firebase:firebase-analytics", version.ref = "ga4" } coil = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } coil-network = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" } +# Rich text formating +rich-text = { module = "com.mohamedrejeb.richeditor:richeditor-compose", version = "1.0.0-rc05-k2" } + [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }