Crops Posts in 350 chars.
This commit is contained in:
@@ -3,10 +3,19 @@ package com.vitorpamplona.amethyst.ui.components
|
|||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.util.LruCache
|
import android.util.LruCache
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
|
import androidx.compose.animation.animateContentSize
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.ClickableText
|
import androidx.compose.foundation.text.ClickableText
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
import androidx.compose.material.LocalTextStyle
|
import androidx.compose.material.LocalTextStyle
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
@@ -16,7 +25,10 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextDirection
|
import androidx.compose.ui.text.style.TextDirection
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -70,6 +82,7 @@ fun RichTextViewer(content: String, canPreview: Boolean, tags: List<List<String>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var showOriginal by remember { mutableStateOf(false) }
|
var showOriginal by remember { mutableStateOf(false) }
|
||||||
|
var showFullText by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
LanguageTranslatorService.autoTranslate(content).addOnCompleteListener { task ->
|
LanguageTranslatorService.autoTranslate(content).addOnCompleteListener { task ->
|
||||||
@@ -79,64 +92,99 @@ fun RichTextViewer(content: String, canPreview: Boolean, tags: List<List<String>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val text = if (showOriginal) content else translatedTextState.value.result
|
val toBeViewed = if (showOriginal) content else translatedTextState.value.result ?: content
|
||||||
|
val text = if (showFullText) toBeViewed else toBeViewed.take(350)
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(top = 5.dp)) {
|
Column(modifier = Modifier.padding(top = 5.dp)) {
|
||||||
// FlowRow doesn't work well with paragraphs. So we need to split them
|
|
||||||
text?.split('\n')?.forEach { paragraph ->
|
|
||||||
|
|
||||||
FlowRow() {
|
Box(contentAlignment = Alignment.BottomCenter) {
|
||||||
paragraph.split(' ').forEach { word: String ->
|
|
||||||
|
|
||||||
if (canPreview) {
|
Column(Modifier.fillMaxWidth().animateContentSize()) {
|
||||||
// Explicit URL
|
// FlowRow doesn't work well with paragraphs. So we need to split them
|
||||||
val lnInvoice = LnInvoiceUtil.findInvoice(word)
|
text.split('\n').forEach { paragraph ->
|
||||||
if (lnInvoice != null) {
|
|
||||||
InvoicePreview(lnInvoice)
|
FlowRow() {
|
||||||
} else if (isValidURL(word)) {
|
paragraph.split(' ').forEach { word: String ->
|
||||||
val removedParamsFromUrl = word.split("?")[0].toLowerCase()
|
|
||||||
if (imageExtension.matcher(removedParamsFromUrl).matches()) {
|
if (canPreview) {
|
||||||
ZoomableImageView(word)
|
// Explicit URL
|
||||||
} else if (videoExtension.matcher(removedParamsFromUrl).matches()) {
|
val lnInvoice = LnInvoiceUtil.findInvoice(word)
|
||||||
VideoView(word)
|
if (lnInvoice != null) {
|
||||||
|
InvoicePreview(lnInvoice)
|
||||||
|
} else if (isValidURL(word)) {
|
||||||
|
val removedParamsFromUrl = word.split("?")[0].toLowerCase()
|
||||||
|
if (imageExtension.matcher(removedParamsFromUrl).matches()) {
|
||||||
|
ZoomableImageView(word)
|
||||||
|
} else if (videoExtension.matcher(removedParamsFromUrl).matches()) {
|
||||||
|
VideoView(word)
|
||||||
|
} else {
|
||||||
|
UrlPreview(word, word)
|
||||||
|
}
|
||||||
|
} else if (Patterns.EMAIL_ADDRESS.matcher(word).matches()) {
|
||||||
|
ClickableEmail(word)
|
||||||
|
} else if (Patterns.PHONE.matcher(word).matches() && word.length > 6) {
|
||||||
|
ClickablePhone(word)
|
||||||
|
} else if (noProtocolUrlValidator.matcher(word).matches()) {
|
||||||
|
UrlPreview("https://$word", word)
|
||||||
|
} else if (tagIndex.matcher(word).matches() && tags != null) {
|
||||||
|
TagLink(word, tags, navController)
|
||||||
|
} else if (isBechLink(word)) {
|
||||||
|
BechLink(word, navController)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = "$word ",
|
||||||
|
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
UrlPreview(word, word)
|
if (isValidURL(word)) {
|
||||||
|
ClickableUrl("$word ", word)
|
||||||
|
} else if (Patterns.EMAIL_ADDRESS.matcher(word).matches()) {
|
||||||
|
ClickableEmail(word)
|
||||||
|
} else if (Patterns.PHONE.matcher(word).matches() && word.length > 6) {
|
||||||
|
ClickablePhone(word)
|
||||||
|
} else if (noProtocolUrlValidator.matcher(word).matches()) {
|
||||||
|
ClickableUrl(word, "https://$word")
|
||||||
|
} else if (tagIndex.matcher(word).matches() && tags != null) {
|
||||||
|
TagLink(word, tags, navController)
|
||||||
|
} else if (isBechLink(word)) {
|
||||||
|
BechLink(word, navController)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = "$word ",
|
||||||
|
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Patterns.EMAIL_ADDRESS.matcher(word).matches()) {
|
|
||||||
ClickableEmail(word)
|
|
||||||
} else if (Patterns.PHONE.matcher(word).matches() && word.length > 6) {
|
|
||||||
ClickablePhone(word)
|
|
||||||
} else if (noProtocolUrlValidator.matcher(word).matches()) {
|
|
||||||
UrlPreview("https://$word", word)
|
|
||||||
} else if (tagIndex.matcher(word).matches() && tags != null) {
|
|
||||||
TagLink(word, tags, navController)
|
|
||||||
} else if (isBechLink(word)) {
|
|
||||||
BechLink(word, navController)
|
|
||||||
} else {
|
|
||||||
Text(
|
|
||||||
text = "$word ",
|
|
||||||
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (isValidURL(word)) {
|
}
|
||||||
ClickableUrl("$word ", word)
|
}
|
||||||
} else if (Patterns.EMAIL_ADDRESS.matcher(word).matches()) {
|
|
||||||
ClickableEmail(word)
|
if (toBeViewed.length > 350 && !showFullText) {
|
||||||
} else if (Patterns.PHONE.matcher(word).matches() && word.length > 6) {
|
Row(
|
||||||
ClickablePhone(word)
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
} else if (noProtocolUrlValidator.matcher(word).matches()) {
|
horizontalArrangement = Arrangement.Center,
|
||||||
ClickableUrl(word, "https://$word")
|
modifier = Modifier.fillMaxWidth().background(
|
||||||
} else if (tagIndex.matcher(word).matches() && tags != null) {
|
brush = Brush.verticalGradient(
|
||||||
TagLink(word, tags, navController)
|
colors = listOf(
|
||||||
} else if (isBechLink(word)) {
|
MaterialTheme.colors.background.copy(alpha = 0f),
|
||||||
BechLink(word, navController)
|
MaterialTheme.colors.background
|
||||||
} else {
|
|
||||||
Text(
|
|
||||||
text = "$word ",
|
|
||||||
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
|
onClick = { showFullText = !showFullText },
|
||||||
|
shape = RoundedCornerShape(20.dp),
|
||||||
|
colors = ButtonDefaults
|
||||||
|
.buttonColors(
|
||||||
|
backgroundColor = MaterialTheme.colors.primary
|
||||||
|
),
|
||||||
|
contentPadding = PaddingValues(vertical = 6.dp, horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
Text(text = "Show More", color = Color.White)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,13 +195,13 @@ fun RichTextViewer(content: String, canPreview: Boolean, tags: List<List<String>
|
|||||||
|
|
||||||
if (source != null && target != null) {
|
if (source != null && target != null) {
|
||||||
if (source != target) {
|
if (source != target) {
|
||||||
Row() {
|
FlowRow() {
|
||||||
Text(
|
Text(
|
||||||
text = "Auto-translated from ",
|
text = "Auto-translated from ",
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
)
|
)
|
||||||
ClickableText(
|
ClickableText(
|
||||||
text = AnnotatedString("${Locale(source).displayName}"),
|
text = AnnotatedString(Locale(source).displayName),
|
||||||
onClick = { showOriginal = true },
|
onClick = { showOriginal = true },
|
||||||
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary.copy(alpha = 0.52f))
|
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary.copy(alpha = 0.52f))
|
||||||
)
|
)
|
||||||
@@ -162,7 +210,7 @@ fun RichTextViewer(content: String, canPreview: Boolean, tags: List<List<String>
|
|||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
)
|
)
|
||||||
ClickableText(
|
ClickableText(
|
||||||
text = AnnotatedString("${Locale(target).displayName}"),
|
text = AnnotatedString(Locale(target).displayName),
|
||||||
onClick = { showOriginal = false },
|
onClick = { showOriginal = false },
|
||||||
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary.copy(alpha = 0.52f))
|
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary.copy(alpha = 0.52f))
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user