11package org .schabi .newpipe .info_list .holder ;
22
3- import static android .text .TextUtils .isEmpty ;
43import static org .schabi .newpipe .util .ServiceHelper .getServiceById ;
54
6- import android .graphics .Paint ;
7- import android .text .Layout ;
85import android .text .method .LinkMovementMethod ;
96import android .text .style .URLSpan ;
107import android .view .View ;
1512import android .widget .TextView ;
1613
1714import androidx .annotation .NonNull ;
18- import androidx .annotation .Nullable ;
19- import androidx .core .text .HtmlCompat ;
2015import androidx .fragment .app .FragmentActivity ;
2116
2217import org .schabi .newpipe .R ;
2318import org .schabi .newpipe .extractor .InfoItem ;
24- import org .schabi .newpipe .extractor .StreamingService ;
2519import org .schabi .newpipe .extractor .comments .CommentsInfoItem ;
26- import org .schabi .newpipe .extractor .stream .Description ;
2720import org .schabi .newpipe .info_list .InfoItemBuilder ;
2821import org .schabi .newpipe .local .history .HistoryRecordManager ;
2922import org .schabi .newpipe .util .DeviceUtils ;
3023import org .schabi .newpipe .util .Localization ;
3124import org .schabi .newpipe .util .NavigationHelper ;
25+ import org .schabi .newpipe .util .external_communication .ShareUtils ;
3226import org .schabi .newpipe .util .image .ImageStrategy ;
3327import org .schabi .newpipe .util .image .PicassoHelper ;
34- import org .schabi .newpipe .util .external_communication .ShareUtils ;
3528import org .schabi .newpipe .util .text .CommentTextOnTouchListener ;
36- import org .schabi .newpipe .util .text .TextLinkifier ;
37-
38- import java .util .function .Consumer ;
39-
40- import io .reactivex .rxjava3 .disposables .CompositeDisposable ;
29+ import org .schabi .newpipe .util .text .TextEllipsizer ;
4130
4231public class CommentInfoItemHolder extends InfoItemHolder {
43- private static final String ELLIPSIS = "…" ;
4432
4533 private static final int COMMENT_DEFAULT_LINES = 2 ;
46- private static final int COMMENT_EXPANDED_LINES = 1000 ;
47-
4834 private final int commentHorizontalPadding ;
4935 private final int commentVerticalPadding ;
5036
51- private final Paint paintAtContentSize ;
52- private final float ellipsisWidthPx ;
53-
5437 private final RelativeLayout itemRoot ;
5538 private final ImageView itemThumbnailView ;
5639 private final TextView itemContentView ;
@@ -61,13 +44,8 @@ public class CommentInfoItemHolder extends InfoItemHolder {
6144 private final ImageView itemPinnedView ;
6245 private final Button repliesButton ;
6346
64- private final CompositeDisposable disposables = new CompositeDisposable ();
65- @ Nullable
66- private Description commentText ;
67- @ Nullable
68- private StreamingService streamService ;
69- @ Nullable
70- private String streamUrl ;
47+ @ NonNull
48+ private final TextEllipsizer textEllipsizer ;
7149
7250 public CommentInfoItemHolder (final InfoItemBuilder infoItemBuilder ,
7351 final ViewGroup parent ) {
@@ -88,9 +66,14 @@ public CommentInfoItemHolder(final InfoItemBuilder infoItemBuilder,
8866 commentVerticalPadding = (int ) infoItemBuilder .getContext ()
8967 .getResources ().getDimension (R .dimen .comments_vertical_padding );
9068
91- paintAtContentSize = new Paint ();
92- paintAtContentSize .setTextSize (itemContentView .getTextSize ());
93- ellipsisWidthPx = paintAtContentSize .measureText (ELLIPSIS );
69+ textEllipsizer = new TextEllipsizer (itemContentView , COMMENT_DEFAULT_LINES , null );
70+ textEllipsizer .setStateChangeListener (isEllipsized -> {
71+ if (Boolean .TRUE .equals (isEllipsized )) {
72+ denyLinkFocus ();
73+ } else {
74+ determineMovementMethod ();
75+ }
76+ });
9477 }
9578
9679 @ Override
@@ -139,16 +122,16 @@ public void updateFromItem(final InfoItem infoItem,
139122
140123
141124 // setup comment content and click listeners to expand/ellipsize it
142- streamService = getServiceById (item .getServiceId ());
143- streamUrl = item .getUrl ();
144- commentText = item .getCommentText ();
145- ellipsize ();
125+ textEllipsizer . setStreamingService ( getServiceById (item .getServiceId () ));
126+ textEllipsizer . setStreamUrl ( item .getUrl () );
127+ textEllipsizer . setContent ( item .getCommentText () );
128+ textEllipsizer . ellipsize ();
146129
147130 //noinspection ClickableViewAccessibility
148131 itemContentView .setOnTouchListener (CommentTextOnTouchListener .INSTANCE );
149132
150133 itemView .setOnClickListener (view -> {
151- toggleEllipsize ();
134+ textEllipsizer . toggle ();
152135 if (itemBuilder .getOnCommentsSelectedListener () != null ) {
153136 itemBuilder .getOnCommentsSelectedListener ().selected (item );
154137 }
@@ -202,76 +185,4 @@ private void determineMovementMethod() {
202185 denyLinkFocus ();
203186 }
204187 }
205-
206- private void ellipsize () {
207- itemContentView .setMaxLines (COMMENT_EXPANDED_LINES );
208- linkifyCommentContentView (v -> {
209- boolean hasEllipsis = false ;
210-
211- final CharSequence charSeqText = itemContentView .getText ();
212- if (charSeqText != null && itemContentView .getLineCount () > COMMENT_DEFAULT_LINES ) {
213- // Note that converting to String removes spans (i.e. links), but that's something
214- // we actually want since when the text is ellipsized we want all clicks on the
215- // comment to expand the comment, not to open links.
216- final String text = charSeqText .toString ();
217-
218- final Layout layout = itemContentView .getLayout ();
219- final float lineWidth = layout .getLineWidth (COMMENT_DEFAULT_LINES - 1 );
220- final float layoutWidth = layout .getWidth ();
221- final int lineStart = layout .getLineStart (COMMENT_DEFAULT_LINES - 1 );
222- final int lineEnd = layout .getLineEnd (COMMENT_DEFAULT_LINES - 1 );
223-
224- // remove characters up until there is enough space for the ellipsis
225- // (also summing 2 more pixels, just to be sure to avoid float rounding errors)
226- int end = lineEnd ;
227- float removedCharactersWidth = 0.0f ;
228- while (lineWidth - removedCharactersWidth + ellipsisWidthPx + 2.0f > layoutWidth
229- && end >= lineStart ) {
230- end -= 1 ;
231- // recalculate each time to account for ligatures or other similar things
232- removedCharactersWidth = paintAtContentSize .measureText (
233- text .substring (end , lineEnd ));
234- }
235-
236- // remove trailing spaces and newlines
237- while (end > 0 && Character .isWhitespace (text .charAt (end - 1 ))) {
238- end -= 1 ;
239- }
240-
241- final String newVal = text .substring (0 , end ) + ELLIPSIS ;
242- itemContentView .setText (newVal );
243- hasEllipsis = true ;
244- }
245-
246- itemContentView .setMaxLines (COMMENT_DEFAULT_LINES );
247- if (hasEllipsis ) {
248- denyLinkFocus ();
249- } else {
250- determineMovementMethod ();
251- }
252- });
253- }
254-
255- private void toggleEllipsize () {
256- final CharSequence text = itemContentView .getText ();
257- if (!isEmpty (text ) && text .charAt (text .length () - 1 ) == ELLIPSIS .charAt (0 )) {
258- expand ();
259- } else if (itemContentView .getLineCount () > COMMENT_DEFAULT_LINES ) {
260- ellipsize ();
261- }
262- }
263-
264- private void expand () {
265- itemContentView .setMaxLines (COMMENT_EXPANDED_LINES );
266- linkifyCommentContentView (v -> determineMovementMethod ());
267- }
268-
269- private void linkifyCommentContentView (@ Nullable final Consumer <TextView > onCompletion ) {
270- disposables .clear ();
271- if (commentText != null ) {
272- TextLinkifier .fromDescription (itemContentView , commentText ,
273- HtmlCompat .FROM_HTML_MODE_LEGACY , streamService , streamUrl , disposables ,
274- onCompletion );
275- }
276- }
277188}
0 commit comments