package com.xda.one.parser; import com.xda.one.R; import net.nightwhistler.htmlspanner.HtmlSpanner; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.kefirsf.bb.BBProcessorFactory; import org.kefirsf.bb.TextProcessor; import android.content.Context; import android.text.Spannable; import android.text.style.ImageSpan; import java.io.IOException; import java.io.InputStream; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ContentParser { public static final Map<Pattern, Integer> EMOTICONS_MAP = new LinkedHashMap<>(); private static final HtmlSpanner SPANNER = new HtmlSpanner(); private static TextProcessor sTextProcessor; static { SPANNER.registerHandler("mention", new XDATagHandlers.MentionHandler()); SPANNER.registerHandler("td", new XDATagHandlers.QuoteTagHandler()); SPANNER.registerHandler("xdaquote", new XDATagHandlers.QuoteTagHandler()); SPANNER.registerHandler("img", new XDATagHandlers.ImageHandler()); SPANNER.registerHandler("a", new XDATagHandlers.LinkHandler()); addPattern(EMOTICONS_MAP, ":)", R.drawable.smile); addPattern(EMOTICONS_MAP, ":(", R.drawable.frown); addPattern(EMOTICONS_MAP, ":victory:", R.drawable.victory); addPattern(EMOTICONS_MAP, ":confused:", R.drawable.confused); addPattern(EMOTICONS_MAP, ":silly:", R.drawable.silly); addPattern(EMOTICONS_MAP, ":laugh:", R.drawable.laugh); addPattern(EMOTICONS_MAP, ":mad:", R.drawable.mad); addPattern(EMOTICONS_MAP, ":highfive:", R.drawable.highfive); addPattern(EMOTICONS_MAP, ":good:", R.drawable.good); addPattern(EMOTICONS_MAP, ":fingers-crossed:", R.drawable.fingers_crossed); addPattern(EMOTICONS_MAP, ":p", R.drawable.tongue); addPattern(EMOTICONS_MAP, ":cyclops:", R.drawable.cyclops); addPattern(EMOTICONS_MAP, ";)", R.drawable.wink); addPattern(EMOTICONS_MAP, ":crying:", R.drawable.crying); addPattern(EMOTICONS_MAP, ":D", R.drawable.biggrin); addPattern(EMOTICONS_MAP, ":cowboy:", R.drawable.cowboy); addPattern(EMOTICONS_MAP, ":o", R.drawable.redface); addPattern(EMOTICONS_MAP, ":angel:", R.drawable.angel); addPattern(EMOTICONS_MAP, ":rolleyes:", R.drawable.rolleyes); addPattern(EMOTICONS_MAP, ":cool:", R.drawable.cool); addPattern(EMOTICONS_MAP, ":eek:", R.drawable.eek); addPattern(EMOTICONS_MAP, ":svetius:", R.drawable.good); } private static TextProcessor getBBCodeProcessor(final Context context) { if (sTextProcessor == null) { InputStream inputStream = null; try { inputStream = context.getAssets().open("xda.xml"); sTextProcessor = BBProcessorFactory.getInstance().create(inputStream); } catch (IOException e) { e.printStackTrace(); return null; } finally { IOUtils.closeQuietly(inputStream); } } return sTextProcessor; } private static void addPattern(final Map<Pattern, Integer> map, String smile, int resource) { map.put(Pattern.compile(smile, Pattern.LITERAL), resource); } public static boolean addSmiles(final Context context, final Spannable spannable) { boolean hasChanges = false; for (Map.Entry<Pattern, Integer> entry : EMOTICONS_MAP.entrySet()) { Matcher matcher = entry.getKey().matcher(spannable); while (matcher.find()) { boolean set = true; for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) { if (spannable.getSpanStart(span) >= matcher.start() && spannable.getSpanEnd(span) <= matcher.end()) { spannable.removeSpan(span); } else { set = false; break; } } if (set) { hasChanges = true; spannable.setSpan(new ImageSpan(context, entry.getValue()), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } return hasChanges; } public static Spannable parseAndSmilifyBBCode(final Context context, final CharSequence text) { final Spannable parsedText = parseBBCode(context, text); addSmiles(context, parsedText); return parsedText; } public static Spannable parseBBCode(final Context context, final CharSequence text) { return parseBBCode(ContentParser.getBBCodeProcessor(context), text); } private static Spannable parseBBCode(final TextProcessor processor, final CharSequence messageText) { final String htmlCode = processor.process(messageText).toString(); final String unescapedHtml = StringEscapeUtils.unescapeHtml4(htmlCode); return SPANNER.fromHtml(unescapedHtml); } }