@@ -48,8 +48,6 @@ private TextLinkifier() {
4848 *
4949 * @param textView the TextView to set the htmlBlock linked
5050 * @param description the htmlBlock to be linked
51- * @param htmlCompatFlag the int flag to be set if {@link HtmlCompat#fromHtml(String, int)}
52- * will be called (not used for formats different than HTML)
5351 * @param relatedInfoService if given, handle hashtags to search for the term in the correct
5452 * service
5553 * @param relatedStreamUrl if given, used alongside {@code relatedInfoService} to handle
@@ -62,23 +60,59 @@ private TextLinkifier() {
6260 */
6361 public static void fromDescription (@ NonNull final TextView textView ,
6462 @ NonNull final Description description ,
65- final int htmlCompatFlag ,
6663 @ Nullable final StreamingService relatedInfoService ,
6764 @ Nullable final String relatedStreamUrl ,
6865 @ NonNull final CompositeDisposable disposables ,
6966 @ Nullable final Consumer <TextView > onCompletion ) {
67+ fromDescription (textView , description , relatedInfoService ,
68+ relatedStreamUrl , disposables , onCompletion , null );
69+ }
70+
71+ /**
72+ * Like {@link #fromDescription(TextView, Description, StreamingService, String,
73+ * CompositeDisposable, Consumer)} but with an extra callback that fires after a timestamp
74+ * link is tapped and the player seek has been dispatched.
75+ *
76+ * @param textView the TextView to set the linked description on
77+ * @param description the description to be linked
78+ * @param relatedInfoService if given, handle hashtags and timestamps for this service
79+ * @param relatedStreamUrl if given, used to open the stream in the popup player at the
80+ * time indicated by a timestamp
81+ * @param disposables disposables created by the method are added here and their
82+ * lifecycle should be handled by the calling class
83+ * @param onCompletion will be run when setting text to the textView completes; use
84+ * {@link #SET_LINK_MOVEMENT_METHOD} to make links clickable
85+ * @param onAfterTimestampClick invoked after a timestamp click is handled; use this to e.g.
86+ * scroll the UI so the player is visible. May be {@code null}.
87+ */
88+ public static void fromDescription (@ NonNull final TextView textView ,
89+ @ NonNull final Description description ,
90+ @ Nullable final StreamingService relatedInfoService ,
91+ @ Nullable final String relatedStreamUrl ,
92+ @ NonNull final CompositeDisposable disposables ,
93+ @ Nullable final Consumer <TextView > onCompletion ,
94+ @ Nullable final Runnable onAfterTimestampClick ) {
7095 switch (description .getType ()) {
7196 case Description .HTML :
72- TextLinkifier .fromHtml (textView , description .getContent (), htmlCompatFlag ,
73- relatedInfoService , relatedStreamUrl , disposables , onCompletion );
97+ changeLinkIntents (textView ,
98+ HtmlCompat .fromHtml (description .getContent (),
99+ HtmlCompat .FROM_HTML_MODE_LEGACY ),
100+ relatedInfoService , relatedStreamUrl , disposables , onCompletion ,
101+ onAfterTimestampClick );
74102 break ;
75103 case Description .MARKDOWN :
76- TextLinkifier .fromMarkdown (textView , description .getContent (),
77- relatedInfoService , relatedStreamUrl , disposables , onCompletion );
104+ changeLinkIntents (textView ,
105+ Markwon .builder (textView .getContext ())
106+ .usePlugin (LinkifyPlugin .create ()).build ()
107+ .toMarkdown (description .getContent ()),
108+ relatedInfoService , relatedStreamUrl , disposables , onCompletion ,
109+ onAfterTimestampClick );
78110 break ;
79111 case Description .PLAIN_TEXT : default :
80- TextLinkifier .fromPlainText (textView , description .getContent (),
81- relatedInfoService , relatedStreamUrl , disposables , onCompletion );
112+ textView .setAutoLinkMask (Linkify .WEB_URLS );
113+ textView .setText (description .getContent (), TextView .BufferType .SPANNABLE );
114+ changeLinkIntents (textView , textView .getText (), relatedInfoService ,
115+ relatedStreamUrl , disposables , onCompletion , onAfterTimestampClick );
82116 break ;
83117 }
84118 }
@@ -115,7 +149,7 @@ public static void fromHtml(@NonNull final TextView textView,
115149 @ Nullable final Consumer <TextView > onCompletion ) {
116150 changeLinkIntents (
117151 textView , HtmlCompat .fromHtml (htmlBlock , htmlCompatFlag ), relatedInfoService ,
118- relatedStreamUrl , disposables , onCompletion );
152+ relatedStreamUrl , disposables , onCompletion , null );
119153 }
120154
121155 /**
@@ -149,7 +183,7 @@ public static void fromPlainText(@NonNull final TextView textView,
149183 textView .setAutoLinkMask (Linkify .WEB_URLS );
150184 textView .setText (plainTextBlock , TextView .BufferType .SPANNABLE );
151185 changeLinkIntents (textView , textView .getText (), relatedInfoService ,
152- relatedStreamUrl , disposables , onCompletion );
186+ relatedStreamUrl , disposables , onCompletion , null );
153187 }
154188
155189 /**
@@ -182,7 +216,7 @@ public static void fromMarkdown(@NonNull final TextView textView,
182216 final Markwon markwon = Markwon .builder (textView .getContext ())
183217 .usePlugin (LinkifyPlugin .create ()).build ();
184218 changeLinkIntents (textView , markwon .toMarkdown (markdownBlock ),
185- relatedInfoService , relatedStreamUrl , disposables , onCompletion );
219+ relatedInfoService , relatedStreamUrl , disposables , onCompletion , null );
186220 }
187221
188222 /**
@@ -221,13 +255,15 @@ public static void fromMarkdown(@NonNull final TextView textView,
221255 * lifecycle should be handled by the calling class
222256 * @param onCompletion will be run when setting text to the textView completes; use {@link
223257 * #SET_LINK_MOVEMENT_METHOD} to make links clickable and focusable
258+ * @param onAfterTimestampClick will be run after a timestamp link click action is resolved
224259 */
225260 private static void changeLinkIntents (@ NonNull final TextView textView ,
226261 @ NonNull final CharSequence chars ,
227262 @ Nullable final StreamingService relatedInfoService ,
228263 @ Nullable final String relatedStreamUrl ,
229264 @ NonNull final CompositeDisposable disposables ,
230- @ Nullable final Consumer <TextView > onCompletion ) {
265+ @ Nullable final Consumer <TextView > onCompletion ,
266+ @ Nullable final Runnable onAfterTimestampClick ) {
231267 disposables .add (Single .fromCallable (() -> {
232268 final Context context = textView .getContext ();
233269
@@ -240,7 +276,8 @@ private static void changeLinkIntents(@NonNull final TextView textView,
240276 for (final URLSpan span : urls ) {
241277 final String url = span .getURL ();
242278 final LongPressClickableSpan longPressClickableSpan =
243- new UrlLongPressClickableSpan (context , url );
279+ new UrlLongPressClickableSpan (context , url ,
280+ onAfterTimestampClick );
244281
245282 textBlockLinked .setSpan (longPressClickableSpan ,
246283 textBlockLinked .getSpanStart (span ),
@@ -254,7 +291,8 @@ private static void changeLinkIntents(@NonNull final TextView textView,
254291 if (relatedInfoService != null ) {
255292 if (relatedStreamUrl != null ) {
256293 addClickListenersOnTimestamps (context , textBlockLinked ,
257- relatedInfoService , relatedStreamUrl , disposables );
294+ relatedInfoService , relatedStreamUrl , disposables ,
295+ onAfterTimestampClick );
258296 }
259297 addClickListenersOnHashtags (context , textBlockLinked , relatedInfoService );
260298 }
@@ -329,13 +367,15 @@ private static void addClickListenersOnHashtags(
329367 * @param relatedStreamUrl what to open in the popup player when timestamps are clicked
330368 * @param disposables disposables created by the method are added here and their
331369 * lifecycle should be handled by the calling class
370+ * @param onAfterTimestampClick will be run after a timestamp link click action is resolved
332371 */
333372 private static void addClickListenersOnTimestamps (
334373 @ NonNull final Context context ,
335374 @ NonNull final SpannableStringBuilder spannableDescription ,
336375 @ NonNull final StreamingService relatedInfoService ,
337376 @ NonNull final String relatedStreamUrl ,
338- @ NonNull final CompositeDisposable disposables ) {
377+ @ NonNull final CompositeDisposable disposables ,
378+ @ Nullable final Runnable onAfterTimestampClick ) {
339379 final String descriptionText = spannableDescription .toString ();
340380 final Matcher timestampsMatches = TimestampExtractor .TIMESTAMPS_PATTERN .matcher (
341381 descriptionText );
@@ -350,7 +390,8 @@ private static void addClickListenersOnTimestamps(
350390
351391 spannableDescription .setSpan (
352392 new TimestampLongPressClickableSpan (context , descriptionText , disposables ,
353- relatedInfoService , relatedStreamUrl , timestampMatchDTO ),
393+ relatedInfoService , relatedStreamUrl , timestampMatchDTO ,
394+ onAfterTimestampClick ),
354395 timestampMatchDTO .timestampStart (),
355396 timestampMatchDTO .timestampEnd (),
356397 0 );
0 commit comments