Search in sources :

Example 11 with TouchableUrlSpan

use of in.uncod.android.bypass.style.TouchableUrlSpan in project plaid by nickbutcher.

the class Bypass method recurseElement.

// The 'numberOfSiblings' parameters refers to the number of siblings within the parent, including
// the 'element' parameter, as in "How many siblings are you?" rather than "How many siblings do
// you have?".
private CharSequence recurseElement(Element element, int indexWithinParent, int numberOfSiblings, ColorStateList linksColors, int highlightColor, LoadImageCallback loadImageCallback) {
    Type type = element.getType();
    boolean isOrderedList = false;
    if (type == Type.LIST) {
        String flagsStr = element.getAttribute("flags");
        if (flagsStr != null) {
            int flags = Integer.parseInt(flagsStr);
            isOrderedList = (flags & Element.F_LIST_ORDERED) != 0;
            if (isOrderedList) {
                mOrderedListNumber.put(element, 1);
            }
        }
    }
    int size = element.size();
    CharSequence[] spans = new CharSequence[size];
    for (int i = 0; i < size; i++) {
        spans[i] = recurseElement(element.children[i], i, size, linksColors, highlightColor, loadImageCallback);
    }
    // Clean up after we're done
    if (isOrderedList) {
        mOrderedListNumber.remove(this);
    }
    CharSequence concat = TextUtils.concat(spans);
    SpannableStringBuilder builder = new ReverseSpannableStringBuilder();
    String text = element.getText();
    if (element.size() == 0 && element.getParent() != null && element.getParent().getType() != Type.BLOCK_CODE) {
        text = text.replace('\n', ' ');
    }
    switch(type) {
        case LIST:
            if (element.getParent() != null && element.getParent().getType() == Type.LIST_ITEM) {
                builder.append("\n");
            }
            break;
        case LINEBREAK:
            builder.append("\n");
            break;
        case LIST_ITEM:
            builder.append(" ");
            if (mOrderedListNumber.containsKey(element.getParent())) {
                int number = mOrderedListNumber.get(element.getParent());
                builder.append(Integer.toString(number) + ".");
                mOrderedListNumber.put(element.getParent(), number + 1);
            } else {
                builder.append(mOptions.mUnorderedListItem);
            }
            builder.append("  ");
            break;
        case AUTOLINK:
            builder.append(element.getAttribute("link"));
            break;
        case HRULE:
            // This ultimately gets drawn over by the line span, but
            // we need something here or the span isn't even drawn.
            builder.append("-");
            break;
        case IMAGE:
            if (loadImageCallback != null && !TextUtils.isEmpty(element.getAttribute("link"))) {
                // prepend a new line so that images are always on a new line
                builder.append("\n");
                // Display alt text (or title text) if there is no image
                String alt = element.getAttribute("alt");
                if (TextUtils.isEmpty(alt)) {
                    alt = element.getAttribute("title");
                }
                if (!TextUtils.isEmpty(alt)) {
                    alt = "[" + alt + "]";
                    builder.append(alt);
                } else {
                    // Character to be replaced
                    builder.append("\uFFFC");
                }
            } else {
                // Character to be replaced
                builder.append("\uFFFC");
            }
            break;
    }
    builder.append(text);
    builder.append(concat);
    // of the last child within the parent.
    if (element.getParent() != null || indexWithinParent < (numberOfSiblings - 1)) {
        if (type == Type.LIST_ITEM) {
            if (element.size() == 0 || !element.children[element.size() - 1].isBlockElement()) {
                builder.append("\n");
            }
        } else if (element.isBlockElement() && type != Type.BLOCK_QUOTE) {
            if (type == Type.LIST) {
                // If this is a nested list, don't include newlines
                if (element.getParent() == null || element.getParent().getType() != Type.LIST_ITEM) {
                    builder.append("\n");
                }
            } else if (element.getParent() != null && element.getParent().getType() == Type.LIST_ITEM) {
                // List items should never double-space their entries
                builder.append("\n");
            } else {
                builder.append("\n\n");
            }
        }
    }
    switch(type) {
        case HEADER:
            String levelStr = element.getAttribute("level");
            int level = Integer.parseInt(levelStr);
            setSpan(builder, new RelativeSizeSpan(mOptions.mHeaderSizes[level - 1]));
            setSpan(builder, new StyleSpan(Typeface.BOLD));
            break;
        case LIST:
            setBlockSpan(builder, new LeadingMarginSpan.Standard(mListItemIndent));
            break;
        case EMPHASIS:
            setSpan(builder, new StyleSpan(Typeface.ITALIC));
            break;
        case DOUBLE_EMPHASIS:
            setSpan(builder, new StyleSpan(Typeface.BOLD));
            break;
        case TRIPLE_EMPHASIS:
            setSpan(builder, new StyleSpan(Typeface.BOLD_ITALIC));
            break;
        case BLOCK_CODE:
            setSpan(builder, new LeadingMarginSpan.Standard(mCodeBlockIndent));
            setSpan(builder, new TypefaceSpan("monospace"));
            break;
        case CODE_SPAN:
            setSpan(builder, new TypefaceSpan("monospace"));
            break;
        case LINK:
        case AUTOLINK:
            String link = element.getAttribute("link");
            if (!TextUtils.isEmpty(link) && Patterns.EMAIL_ADDRESS.matcher(link).matches()) {
                link = "mailto:" + link;
            }
            setSpan(builder, new TouchableUrlSpan(link, linksColors, highlightColor));
            break;
        case BLOCK_QUOTE:
            // We add two leading margin spans so that when the order is reversed,
            // the QuoteSpan will always be in the same spot.
            setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
            // setBlockSpan(builder, new QuoteSpan(mOptions.mBlockQuoteLineColor));
            setBlockSpan(builder, new FancyQuoteSpan(mBlockQuoteLineWidth, mBlockQuoteLineIndent, mOptions.mBlockQuoteLineColor));
            setBlockSpan(builder, new ForegroundColorSpan(mOptions.mBlockQuoteTextColor));
            setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
            setBlockSpan(builder, new StyleSpan(Typeface.ITALIC));
            break;
        case STRIKETHROUGH:
            setSpan(builder, new StrikethroughSpan());
            break;
        case HRULE:
            setSpan(builder, new HorizontalLineSpan(mOptions.mHruleColor, mHruleSize, mHruleTopBottomPadding));
            break;
        case IMAGE:
            String url = element.getAttribute("link");
            if (loadImageCallback != null && !TextUtils.isEmpty(url)) {
                setPrependedNewlineSpan(builder, mOptions.mPreImageLinebreakHeight);
                ImageLoadingSpan loadingSpan = new ImageLoadingSpan();
                setSpanWithPrependedNewline(builder, loadingSpan);
                // make the (eventually loaded) image span clickable to open in browser
                setSpanWithPrependedNewline(builder, new TouchableUrlSpan(url, linksColors, highlightColor));
                loadImageCallback.loadImage(url, loadingSpan);
            }
            break;
    }
    return builder;
}
Also used : TouchableUrlSpan(in.uncod.android.bypass.style.TouchableUrlSpan) HorizontalLineSpan(in.uncod.android.bypass.style.HorizontalLineSpan) ForegroundColorSpan(android.text.style.ForegroundColorSpan) FancyQuoteSpan(in.uncod.android.bypass.style.FancyQuoteSpan) RelativeSizeSpan(android.text.style.RelativeSizeSpan) Type(in.uncod.android.bypass.Element.Type) StyleSpan(android.text.style.StyleSpan) LeadingMarginSpan(android.text.style.LeadingMarginSpan) ImageLoadingSpan(in.uncod.android.bypass.style.ImageLoadingSpan) SpannableStringBuilder(android.text.SpannableStringBuilder) TypefaceSpan(android.text.style.TypefaceSpan) StrikethroughSpan(android.text.style.StrikethroughSpan)

Example 12 with TouchableUrlSpan

use of in.uncod.android.bypass.style.TouchableUrlSpan in project plaid by nickbutcher.

the class HtmlUtils method linkifyPlainLinks.

static SpannableStringBuilder linkifyPlainLinks(CharSequence input, ColorStateList linkTextColor, @ColorInt int linkHighlightColor) {
    // copy of input
    final SpannableString plainLinks = new SpannableString(input);
    // Linkify doesn't seem to work as expected on M+
    // TODO: figure out why
    // Linkify.addLinks(plainLinks, Linkify.WEB_URLS);
    final URLSpan[] urlSpans = plainLinks.getSpans(0, plainLinks.length(), URLSpan.class);
    // add any plain links to the output
    final SpannableStringBuilder ssb = new SpannableStringBuilder(input);
    for (URLSpan urlSpan : urlSpans) {
        ssb.removeSpan(urlSpan);
        ssb.setSpan(new TouchableUrlSpan(urlSpan.getURL(), linkTextColor, linkHighlightColor), plainLinks.getSpanStart(urlSpan), plainLinks.getSpanEnd(urlSpan), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    return ssb;
}
Also used : SpannableString(android.text.SpannableString) TouchableUrlSpan(in.uncod.android.bypass.style.TouchableUrlSpan) URLSpan(android.text.style.URLSpan) SpannableStringBuilder(android.text.SpannableStringBuilder)

Aggregations

TouchableUrlSpan (in.uncod.android.bypass.style.TouchableUrlSpan)12 SpannableStringBuilder (android.text.SpannableStringBuilder)7 Layout (android.text.Layout)3 ForegroundColorSpan (android.text.style.ForegroundColorSpan)3 LeadingMarginSpan (android.text.style.LeadingMarginSpan)3 RelativeSizeSpan (android.text.style.RelativeSizeSpan)3 StrikethroughSpan (android.text.style.StrikethroughSpan)3 StyleSpan (android.text.style.StyleSpan)3 TypefaceSpan (android.text.style.TypefaceSpan)3 URLSpan (android.text.style.URLSpan)3 Type (in.uncod.android.bypass.Element.Type)3 FancyQuoteSpan (in.uncod.android.bypass.style.FancyQuoteSpan)3 HorizontalLineSpan (in.uncod.android.bypass.style.HorizontalLineSpan)3 ImageLoadingSpan (in.uncod.android.bypass.style.ImageLoadingSpan)3 SpannableString (android.text.SpannableString)2 Paint (android.graphics.Paint)1 Spannable (android.text.Spannable)1 Spanned (android.text.Spanned)1 TextPaint (android.text.TextPaint)1 PlayerSpan (io.plaidapp.ui.span.PlayerSpan)1