--- a/ui/material2/src/commonMain/kotlin/com/geekorum/aboutoss/ui/material/OpenSourceLicenseScreen.kt Sun Apr 27 16:48:23 2025 -0400
+++ b/ui/material2/src/commonMain/kotlin/com/geekorum/aboutoss/ui/material/OpenSourceLicenseScreen.kt Sun Apr 27 17:28:37 2025 -0400
@@ -22,7 +22,6 @@
package com.geekorum.aboutoss.ui.material
import androidx.compose.animation.core.animateDpAsState
-import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
@@ -42,19 +41,17 @@
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.LinkAnnotation
+import androidx.compose.ui.text.LinkInteractionListener
import androidx.compose.ui.text.SpanStyle
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.UrlAnnotation
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.text.withAnnotation
+import androidx.compose.ui.text.withLink
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import com.geekorum.aboutoss.ui.common.BrowserLauncher
@@ -107,10 +104,12 @@
onUrlClick: (String) -> Unit,
onUrlsFound: (List<String>) -> Unit,
) {
- val linkifiedLicense = linkifyText(text = license)
+ val linkifiedLicense = linkifyText(text = license, onUrlClick)
LaunchedEffect(linkifiedLicense) {
val uris =
- linkifiedLicense.getUrlAnnotations(0, linkifiedLicense.length).map { it.item.url }
+ linkifiedLicense.getLinkAnnotations(0, linkifiedLicense.length).map { it.item }
+ .filterIsInstance<LinkAnnotation.Url>()
+ .map { it.url }
onUrlsFound(uris)
}
@@ -135,31 +134,13 @@
elevation = topBarElevation
)
}) { paddingValues ->
- val layoutResult = remember { mutableStateOf<TextLayoutResult?>(null) }
- val pressIndicator = Modifier.pointerInput(layoutResult, linkifiedLicense) {
- detectTapGestures { pos ->
- layoutResult.value?.let { layoutResult ->
- val posWithScroll = pos.copy(y = pos.y + scrollState.value)
- val offset = layoutResult.getOffsetForPosition(posWithScroll)
- linkifiedLicense.getUrlAnnotations(start = offset, end = offset)
- .firstOrNull()?.let { annotation ->
- onUrlClick(annotation.item.url)
- }
- }
- }
- }
-
Text(linkifiedLicense,
modifier = Modifier
.padding(paddingValues)
.consumeWindowInsets(paddingValues)
.padding(horizontal = 16.dp)
.fillMaxSize()
- .then(pressIndicator)
.verticalScroll(scrollState),
- onTextLayout = {
- layoutResult.value = it
- }
)
}
}
@@ -171,7 +152,7 @@
@OptIn(ExperimentalTextApi::class)
@Composable
-private fun linkifyText(text: String): AnnotatedString {
+private fun linkifyText(text: String, onUrlClick: (String) -> Unit): AnnotatedString {
val style = SpanStyle(
color = MaterialTheme.colors.secondary,
textDecoration = TextDecoration.Underline
@@ -184,7 +165,17 @@
append(text.substring(currentIdx, match.range.first))
}
val url = text.substring(match.range)
- withAnnotation(UrlAnnotation(url)) {
+ val linkInteractionListener = LinkInteractionListener {
+ val url = when(it) {
+ is LinkAnnotation.Url -> it.url
+ is LinkAnnotation.Clickable -> it.tag
+ else -> null
+ }
+ if (url != null) {
+ onUrlClick(url)
+ }
+ }
+ withLink(LinkAnnotation.Url(url, linkInteractionListener = linkInteractionListener)) {
withStyle(style) {
append(url)
}