mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-30 12:36:00 +02:00
Calculate the text width of a space outside a composable.
This commit is contained in:
parent
c2532322fd
commit
0e5b5d657f
@ -11,7 +11,7 @@ import com.vitorpamplona.amethyst.ui.components.ZoomableUrlImage
|
||||
import com.vitorpamplona.amethyst.ui.components.ZoomableUrlVideo
|
||||
import com.vitorpamplona.amethyst.ui.components.hashTagsPattern
|
||||
import com.vitorpamplona.amethyst.ui.components.imageExtensions
|
||||
import com.vitorpamplona.amethyst.ui.components.removeQueryParams
|
||||
import com.vitorpamplona.amethyst.ui.components.removeQueryParamsForExtensionComparison
|
||||
import com.vitorpamplona.amethyst.ui.components.tagIndex
|
||||
import com.vitorpamplona.amethyst.ui.components.videoExtensions
|
||||
import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
||||
@ -88,7 +88,7 @@ class RichTextParser() {
|
||||
}
|
||||
|
||||
val imagesForPager = urlSet.mapNotNull { fullUrl ->
|
||||
val removedParamsFromUrl = removeQueryParams(fullUrl)
|
||||
val removedParamsFromUrl = removeQueryParamsForExtensionComparison(fullUrl)
|
||||
if (imageExtensions.any { removedParamsFromUrl.endsWith(it) }) {
|
||||
val frags = URI(fullUrl).fragments()
|
||||
ZoomableUrlImage(
|
||||
|
@ -93,7 +93,7 @@ class MarkdownParser {
|
||||
content.split('\n').forEach { paragraph ->
|
||||
paragraph.split(' ').forEach { word: String ->
|
||||
if (isValidURL(word)) {
|
||||
val removedParamsFromUrl = removeQueryParams(word)
|
||||
val removedParamsFromUrl = removeQueryParamsForExtensionComparison(word)
|
||||
if (imageExtensions.any { removedParamsFromUrl.endsWith(it) }) {
|
||||
returnContent += " "
|
||||
} else {
|
||||
|
@ -30,17 +30,18 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.takeOrElse
|
||||
import androidx.compose.ui.layout.SubcomposeLayout
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalFontFamilyResolver
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.Placeholder
|
||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextMeasurer
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.em
|
||||
@ -95,7 +96,7 @@ val videoExtensions = listOf("mp4", "avi", "wmv", "mpg", "amv", "webm", "mov", "
|
||||
val tagIndex = Pattern.compile("\\#\\[([0-9]+)\\](.*)")
|
||||
val hashTagsPattern: Pattern = Pattern.compile("#([^\\s!@#\$%^&*()=+./,\\[{\\]};:'\"?><]+)(.*)", Pattern.CASE_INSENSITIVE)
|
||||
|
||||
fun removeQueryParams(fullUrl: String): String {
|
||||
fun removeQueryParamsForExtensionComparison(fullUrl: String): String {
|
||||
return if (fullUrl.contains("?")) {
|
||||
fullUrl.split("?")[0].lowercase()
|
||||
} else if (fullUrl.contains("#")) {
|
||||
@ -170,59 +171,59 @@ private fun RenderRegular(
|
||||
)
|
||||
}
|
||||
|
||||
MeasureSpaceWidth() { spaceWidth ->
|
||||
Column() {
|
||||
if (canPreview) {
|
||||
// FlowRow doesn't work well with paragraphs. So we need to split them
|
||||
state.paragraphs.forEach { paragraph ->
|
||||
val direction = if (paragraph.isRTL) {
|
||||
LayoutDirection.Rtl
|
||||
} else {
|
||||
LayoutDirection.Ltr
|
||||
}
|
||||
val spaceWidth = measureSpaceWidth(textStyle)
|
||||
|
||||
CompositionLocalProvider(LocalLayoutDirection provides direction) {
|
||||
FlowRow(
|
||||
modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start),
|
||||
horizontalArrangement = Arrangement.spacedBy(spaceWidth)
|
||||
) {
|
||||
paragraph.words.forEach { word ->
|
||||
RenderWordWithPreview(
|
||||
word,
|
||||
state,
|
||||
backgroundColor,
|
||||
textStyle,
|
||||
accountViewModel,
|
||||
nav
|
||||
)
|
||||
}
|
||||
Column() {
|
||||
if (canPreview) {
|
||||
// FlowRow doesn't work well with paragraphs. So we need to split them
|
||||
state.paragraphs.forEach { paragraph ->
|
||||
val direction = if (paragraph.isRTL) {
|
||||
LayoutDirection.Rtl
|
||||
} else {
|
||||
LayoutDirection.Ltr
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalLayoutDirection provides direction) {
|
||||
FlowRow(
|
||||
modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start),
|
||||
horizontalArrangement = Arrangement.spacedBy(spaceWidth)
|
||||
) {
|
||||
paragraph.words.forEach { word ->
|
||||
RenderWordWithPreview(
|
||||
word,
|
||||
state,
|
||||
backgroundColor,
|
||||
textStyle,
|
||||
accountViewModel,
|
||||
nav
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FlowRow doesn't work well with paragraphs. So we need to split them
|
||||
state.paragraphs.forEach { paragraph ->
|
||||
val direction = if (paragraph.isRTL) {
|
||||
LayoutDirection.Rtl
|
||||
} else {
|
||||
LayoutDirection.Ltr
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FlowRow doesn't work well with paragraphs. So we need to split them
|
||||
state.paragraphs.forEach { paragraph ->
|
||||
val direction = if (paragraph.isRTL) {
|
||||
LayoutDirection.Rtl
|
||||
} else {
|
||||
LayoutDirection.Ltr
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalLayoutDirection provides direction) {
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(spaceWidth),
|
||||
modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start)
|
||||
) {
|
||||
paragraph.words.forEach { word ->
|
||||
RenderWordWithoutPreview(
|
||||
word,
|
||||
state,
|
||||
backgroundColor,
|
||||
textStyle,
|
||||
accountViewModel,
|
||||
nav
|
||||
)
|
||||
}
|
||||
CompositionLocalProvider(LocalLayoutDirection provides direction) {
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(spaceWidth),
|
||||
modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start)
|
||||
) {
|
||||
paragraph.words.forEach { word ->
|
||||
RenderWordWithoutPreview(
|
||||
word,
|
||||
state,
|
||||
backgroundColor,
|
||||
textStyle,
|
||||
accountViewModel,
|
||||
nav
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,17 +233,15 @@ private fun RenderRegular(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MeasureSpaceWidth(
|
||||
content: @Composable (measuredWidth: Dp) -> Unit
|
||||
) {
|
||||
SubcomposeLayout { constraints ->
|
||||
val measuredWidth = subcompose("viewToMeasure", { Text(" ") })[0].measure(Constraints()).width.toDp()
|
||||
fun measureSpaceWidth(textStyle: TextStyle): Dp {
|
||||
val fontFamilyResolver = LocalFontFamilyResolver.current
|
||||
val density = LocalDensity.current
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
|
||||
val contentPlaceable = subcompose("content") {
|
||||
content(measuredWidth)
|
||||
}[0].measure(constraints)
|
||||
layout(contentPlaceable.width, contentPlaceable.height) {
|
||||
contentPlaceable.place(0, 0)
|
||||
return remember(fontFamilyResolver, density, layoutDirection, textStyle) {
|
||||
val widthPx = TextMeasurer(fontFamilyResolver, density, layoutDirection, 1).measure(" ", textStyle).size.width
|
||||
with(density) {
|
||||
widthPx.toDp()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -567,7 +566,7 @@ private fun RenderHashtag(
|
||||
) {
|
||||
val primary = MaterialTheme.colorScheme.primary
|
||||
val background = MaterialTheme.colorScheme.onBackground
|
||||
val hashtagIcon = remember(segment.hashtag) {
|
||||
val hashtagIcon: HashtagIcon? = remember(segment.hashtag) {
|
||||
checkForHashtagWithIcon(segment.hashtag, primary)
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ class ZoomableLocalVideo(
|
||||
) : ZoomablePreloadedContent(localFile, description, mimeType, isVerified, dim, uri)
|
||||
|
||||
fun figureOutMimeType(fullUrl: String): ZoomableContent {
|
||||
val removedParamsFromUrl = removeQueryParams(fullUrl)
|
||||
val removedParamsFromUrl = removeQueryParamsForExtensionComparison(fullUrl)
|
||||
val isImage = imageExtensions.any { removedParamsFromUrl.endsWith(it) }
|
||||
val isVideo = videoExtensions.any { removedParamsFromUrl.endsWith(it) }
|
||||
|
||||
|
@ -97,7 +97,6 @@ import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadThumbAndThenVideoView
|
||||
import com.vitorpamplona.amethyst.ui.components.MeasureSpaceWidth
|
||||
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
||||
@ -113,7 +112,8 @@ import com.vitorpamplona.amethyst.ui.components.ZoomableUrlImage
|
||||
import com.vitorpamplona.amethyst.ui.components.ZoomableUrlVideo
|
||||
import com.vitorpamplona.amethyst.ui.components.figureOutMimeType
|
||||
import com.vitorpamplona.amethyst.ui.components.imageExtensions
|
||||
import com.vitorpamplona.amethyst.ui.components.removeQueryParams
|
||||
import com.vitorpamplona.amethyst.ui.components.measureSpaceWidth
|
||||
import com.vitorpamplona.amethyst.ui.components.removeQueryParamsForExtensionComparison
|
||||
import com.vitorpamplona.amethyst.ui.screen.equalImmutableLists
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChannelHeader
|
||||
@ -3024,19 +3024,19 @@ private fun DisplayQuoteAuthor(
|
||||
}
|
||||
}
|
||||
|
||||
MeasureSpaceWidth {
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(it), verticalArrangement = Arrangement.Center) {
|
||||
userBase?.let { userBase ->
|
||||
LoadAndDisplayUser(userBase, nav)
|
||||
}
|
||||
val spaceWidth = measureSpaceWidth(textStyle = LocalTextStyle.current)
|
||||
|
||||
url?.let { url ->
|
||||
LoadAndDisplayUrl(url)
|
||||
}
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(spaceWidth), verticalArrangement = Arrangement.Center) {
|
||||
userBase?.let { userBase ->
|
||||
LoadAndDisplayUser(userBase, nav)
|
||||
}
|
||||
|
||||
postAddress?.let { address ->
|
||||
LoadAndDisplayPost(address, accountViewModel, nav)
|
||||
}
|
||||
url?.let { url ->
|
||||
LoadAndDisplayUrl(url)
|
||||
}
|
||||
|
||||
postAddress?.let { address ->
|
||||
LoadAndDisplayPost(address, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3455,7 +3455,7 @@ fun FileHeaderDisplay(note: Note, roundedCorner: Boolean, accountViewModel: Acco
|
||||
val hash = event.hash()
|
||||
val dimensions = event.dimensions()
|
||||
val description = event.alt() ?: event.content
|
||||
val isImage = imageExtensions.any { removeQueryParams(fullUrl).lowercase().endsWith(it) }
|
||||
val isImage = imageExtensions.any { removeQueryParamsForExtensionComparison(fullUrl).lowercase().endsWith(it) }
|
||||
val uri = note.toNostrUri()
|
||||
|
||||
mutableStateOf<ZoomableContent>(
|
||||
|
Loading…
x
Reference in New Issue
Block a user