@@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable
77import androidx.compose.runtime.remember
88import androidx.compose.runtime.rememberUpdatedState
99import androidx.compose.ui.Modifier
10+ import androidx.compose.ui.platform.LocalContext
1011import androidx.compose.ui.text.AnnotatedString
1112import androidx.compose.ui.text.LinkAnnotation
1213import androidx.compose.ui.text.SpanStyle
@@ -17,6 +18,7 @@ import androidx.compose.ui.text.fromHtml
1718import androidx.compose.ui.text.style.TextDecoration
1819import androidx.compose.ui.text.style.TextOverflow
1920import org.schabi.newpipe.extractor.stream.Description
21+ import org.schabi.newpipe.util.external_communication.ShareUtils
2022import org.schabi.newpipe.util.text.TimestampExtractor
2123
2224@Composable
@@ -46,6 +48,7 @@ fun rememberParsedDescription(
4648 // rememberUpdatedState lets the click handlers inside the AnnotatedString always invoke
4749 // the latest callback without rebuilding the string on every recomposition.
4850 val onTimestampClickState = rememberUpdatedState(onTimestampClick)
51+ val contextState = rememberUpdatedState(LocalContext .current)
4952 // Use a boolean key so the string is only rebuilt when handler presence changes,
5053 // not on every lambda identity change.
5154 val hasTimestampHandler = onTimestampClick != null
@@ -57,41 +60,53 @@ fun rememberParsedDescription(
5760 val baseString = AnnotatedString .fromHtml(description.content, linkStyle)
5861 if (! hasTimestampHandler) return @remember baseString
5962
60- // Rebuild the AnnotatedString, replacing YouTube timestamp URL annotations
61- // with Clickable ones so they seek the player instead of opening YouTube .
63+ // Rebuild the AnnotatedString, replacing timestamp URL annotations
64+ // with Clickable ones so they seek the player instead of opening the browser .
6265 buildAnnotatedString {
6366 append(baseString.text)
64- for (span in baseString.spanStyles) {
67+ baseString.spanStyles.forEach { span ->
6568 addStyle(span.item, span.start, span.end)
6669 }
67- for (para in baseString.paragraphStyles) {
70+ baseString.paragraphStyles.forEach { para ->
6871 addStyle(para.item, para.start, para.end)
6972 }
7073
7174 val handledRanges = mutableListOf<IntRange >()
7275
73- for (link in baseString.getLinkAnnotations(0 , baseString.length)) {
76+ baseString.getLinkAnnotations(0 , baseString.length).forEach { link ->
7477 val ann = link.item
75- if (ann is LinkAnnotation .Url ) {
76- val secs = getTimestampSecondsFromUrl(ann.url)
77- if (secs != null ) {
78- addLink(
79- clickable = LinkAnnotation .Clickable (
80- tag = " timestamp" ,
81- styles = linkStyle,
82- linkInteractionListener = {
83- onTimestampClickState.value?.invoke(secs)
84- }
85- ),
86- start = link.start,
87- end = link.end
88- )
89- handledRanges + = link.start.. link.end
90- continue
78+ when (ann) {
79+ is LinkAnnotation .Url -> {
80+ val secs = getTimestampSecondsFromUrl(ann.url)
81+ if (secs != null ) {
82+ addLink(
83+ clickable = LinkAnnotation .Clickable (
84+ tag = " timestamp" ,
85+ styles = linkStyle,
86+ linkInteractionListener = {
87+ onTimestampClickState.value?.invoke(secs)
88+ }
89+ ),
90+ start = link.start,
91+ end = link.end
92+ )
93+ handledRanges + = link.start.. link.end
94+ } else {
95+ val url = ann.url
96+ addLink(
97+ clickable = LinkAnnotation .Clickable (
98+ tag = " url" ,
99+ styles = ann.styles,
100+ linkInteractionListener = {
101+ ShareUtils .openUrlInApp(contextState.value, url)
102+ }
103+ ),
104+ start = link.start,
105+ end = link.end
106+ )
107+ }
91108 }
92- addLink(ann, link.start, link.end)
93- } else if (ann is LinkAnnotation .Clickable ) {
94- addLink(ann, link.start, link.end)
109+ is LinkAnnotation .Clickable -> addLink(ann, link.start, link.end)
95110 }
96111 }
97112
@@ -151,7 +166,7 @@ fun rememberParsedDescription(
151166private fun getTimestampSecondsFromUrl (url : String ): Int? {
152167 return try {
153168 Uri .parse(url).getQueryParameter(" t" )?.toIntOrNull()
154- } catch (e : Exception ) {
169+ } catch (_ : Exception ) {
155170 null
156171 }
157172}
0 commit comments