Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 0 additions & 76 deletions core/src/main/java/org/openedx/core/extension/TextConverter.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package org.openedx.core.extension

import android.os.Parcelable
import android.util.Patterns
import kotlinx.parcelize.Parcelize
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements
Expand Down Expand Up @@ -36,84 +34,10 @@ object TextConverter : KoinComponent {
return LinkedText(text, linksMap.toMap())
}

fun textToLinkedImageText(html: String): LinkedImageText {
val doc: Document =
Jsoup.parse(html)
val links: Elements = doc.select("a[href]")
var text = doc.text()
val headers = getHeaders(doc)
val linksMap = mutableMapOf<String, String>()
for (link in links) {
if (isLinkValid(link.attr("href"))) {
val linkText = if (link.hasText()) link.text() else link.attr("href")
linksMap[linkText] = link.attr("href")
} else {
val resultLink =
if (link.attr("href").isNotEmpty() && link.attr("href")[0] == '/') {
link.attr("href").substring(1)
} else {
link.attr("href")
}
if (resultLink.isNotEmpty() && isLinkValid(config.getApiHostURL() + resultLink)) {
linksMap[link.text()] = config.getApiHostURL() + resultLink
}
}
}
text = setSpacesForHeaders(text, headers)
return LinkedImageText(
text,
linksMap.toMap(),
getImageLinks(doc),
headers
)
}

fun isLinkValid(link: String) = Patterns.WEB_URL.matcher(link.lowercase()).matches()

@Suppress("MagicNumber")
private fun getHeaders(document: Document): List<String> {
val headersList = mutableListOf<String>()
for (index in 1..6) {
if (document.select("h$index").hasText()) {
headersList.add(document.select("h$index").text())
}
}
return headersList.toList()
}

private fun setSpacesForHeaders(text: String, headers: List<String>): String {
var result = text
headers.forEach {
val startIndex = text.indexOf(it)
val endIndex = startIndex + it.length + 1
result = text.replaceRange(startIndex, endIndex, it + "\n")
}
return result
}

private fun getImageLinks(document: Document): Map<String, String> {
val imageLinks = mutableMapOf<String, String>()
val elements = document.getElementsByTag("img")
for (element in elements) {
if (element.hasAttr("alt")) {
imageLinks[element.attr("alt")] = element.attr("src")
} else {
imageLinks[element.attr("src")] = element.attr("src")
}
}
return imageLinks.toMap()
}
}

data class LinkedText(
val text: String,
val links: Map<String, String>
)

@Parcelize
data class LinkedImageText(
val text: String,
val links: Map<String, String>,
val imageLinks: Map<String, String>,
val headers: List<String>
) : Parcelable
134 changes: 0 additions & 134 deletions core/src/main/java/org/openedx/core/ui/ComposeCommon.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.openedx.core.ui

import android.os.Build
import android.os.Build.VERSION.SDK_INT
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
Expand All @@ -19,7 +17,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
Expand Down Expand Up @@ -81,7 +78,6 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
Expand All @@ -106,15 +102,10 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import coil.ImageLoader
import coil.compose.AsyncImage
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import kotlinx.coroutines.launch
import org.openedx.core.NoContentScreenType
import org.openedx.core.R
import org.openedx.core.domain.model.RegistrationField
import org.openedx.core.extension.LinkedImageText
import org.openedx.core.presentation.global.ErrorType
import org.openedx.core.ui.theme.OpenEdXTheme
import org.openedx.core.ui.theme.appColors
Expand Down Expand Up @@ -508,131 +499,6 @@ fun HyperlinkText(
)
}

@Composable
fun HyperlinkImageText(
modifier: Modifier = Modifier,
title: String = "",
imageText: LinkedImageText,
textStyle: TextStyle = TextStyle.Default,
linkTextColor: Color = MaterialTheme.appColors.primary,
linkTextFontWeight: FontWeight = FontWeight.Normal,
linkTextDecoration: TextDecoration = TextDecoration.None,
fontSize: TextUnit = TextUnit.Unspecified,
) {
val fullText = imageText.text
val hyperLinks = imageText.links
val annotatedString = buildAnnotatedString {
if (title.isNotEmpty()) {
append(title)
append("\n\n")
}
append(fullText)
addStyle(
style = SpanStyle(
color = MaterialTheme.appColors.textPrimary,
fontSize = fontSize
),
start = 0,
end = this.length
)

for ((key, value) in hyperLinks) {
val startIndex = this.toString().indexOf(key)
if (startIndex == -1) continue
val endIndex = startIndex + key.length
addStyle(
style = SpanStyle(
color = linkTextColor,
fontSize = fontSize,
fontWeight = linkTextFontWeight,
textDecoration = linkTextDecoration
),
start = startIndex,
end = endIndex
)
addStringAnnotation(
tag = "URL",
annotation = value,
start = startIndex,
end = endIndex
)
}
if (title.isNotEmpty()) {
addStyle(
style = SpanStyle(
color = MaterialTheme.appColors.textPrimary,
fontSize = MaterialTheme.appTypography.titleLarge.fontSize,
fontWeight = MaterialTheme.appTypography.titleLarge.fontWeight
),
start = 0,
end = title.length
)
}
for (item in imageText.headers) {
val startIndex = this.toString().indexOf(item)
if (startIndex == -1) continue
val endIndex = startIndex + item.length
addStyle(
style = SpanStyle(
color = MaterialTheme.appColors.textPrimary,
fontSize = MaterialTheme.appTypography.titleLarge.fontSize,
fontWeight = MaterialTheme.appTypography.titleLarge.fontWeight
),
start = startIndex,
end = endIndex
)
}
addStyle(
style = SpanStyle(
fontSize = fontSize
),
start = 0,
end = this.length
)
}

val uriHandler = LocalUriHandler.current
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
.components {
if (SDK_INT >= Build.VERSION_CODES.P) {
add(ImageDecoderDecoder.Factory())
} else {
add(GifDecoder.Factory())
}
}
.build()

Column(Modifier.fillMaxWidth()) {
BasicText(
text = annotatedString,
modifier = modifier.pointerInput(Unit) {
detectTapGestures { offset ->
val position = offset.x.toInt()
annotatedString.getStringAnnotations("URL", position, position)
.firstOrNull()?.let { stringAnnotation ->
uriHandler.openUri(stringAnnotation.item)
}
}
},
style = textStyle
)
imageText.imageLinks.values.forEach {
Spacer(Modifier.height(8.dp))
AsyncImage(
modifier = Modifier
.fillMaxWidth()
.heightIn(0.dp, 360.dp),
contentScale = ContentScale.Fit,
model = it,
contentDescription = null,
imageLoader = imageLoader
)
}
Spacer(Modifier.height(16.dp))
}
}

@Composable
fun SheetContent(
searchValue: TextFieldValue,
Expand Down
Loading