package com.mcxiaoke.minicat.util;
import android.graphics.Typeface;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.widget.TextView;
import android.widget.TextView.BufferType;
import com.mcxiaoke.minicat.AppContext;
import com.mcxiaoke.minicat.dao.model.StatusModel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author mcxiaoke
* @version 2.0 2012.03.18
*/
public class StatusHelper {
private static final String TAG = "StatusHelper";
private static final int COLOR_HIGHLIGHT = 0xFFFF6666;
private static final Pattern PATTERN_HIGHLIGHT = Pattern.compile("<b>(\\w+?)</b>");
private static final Pattern PATTERN_USER = Pattern.compile("(@.+?)\\s+", Pattern.MULTILINE);
private static final String SCHEME_USER = "fanfouapp://profile/";
private static final Pattern PATTERN_SEARCH = Pattern.compile("#\\w+#");
private static final Linkify.TransformFilter TRANSFORM_SEARCH = new Linkify.TransformFilter() {
@Override
public final String transformUrl(Matcher match, String url) {
return url.substring(1, url.length() - 1);
}
};
private static final String SCHEME_SEARCH = "fanfouapp://search/";
private static final int LINK_COLOR = 0xff28a5c0;
/**
* 从消息中获取全部提到的人,将它们按先后顺序放入一个列表
*
* @param text
* 消息文本
* @return 消息中@的人的列表,按顺序存放
*/
private static final Pattern namePattern = Pattern.compile("@(.*?)\\s");
private static final int MAX_NAME_LENGTH = 12;
private static Pattern PATTERN_USERLINK = Pattern
.compile("<a href=\"http://fanfou\\.com/(.*?)\" class=\"former\">(.*?)</a>");
public static void linkifyUsers(final Spannable spannable, final HashMap<String, String> mentions) {
// LogUtil.v(TAG, "linkifyUsers:mentions:" + mentions.keySet());
final Linkify.MatchFilter filter = new Linkify.MatchFilter() {
@Override
public final boolean acceptMatch(final CharSequence s, final int start,
final int end) {
String name = s.subSequence(start + 1, end).toString().trim();
return mentions.containsKey(name);
}
};
final Linkify.TransformFilter transformer = new Linkify.TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
String name = url.subSequence(1, url.length()).toString().trim();
return mentions.get(name);
}
};
Linkify.addLinks(spannable, PATTERN_USER, SCHEME_USER, filter,
transformer);
}
public static void linkifyTags(final Spannable spannable) {
Linkify.addLinks(spannable, PATTERN_SEARCH, SCHEME_SEARCH, null,
TRANSFORM_SEARCH);
}
private static List<String> findHighlightWords(final String htmlText) {
final Matcher m = PATTERN_HIGHLIGHT.matcher(htmlText);
List<String> words = new ArrayList<>();
while (m.find()) {
final String word = m.group(1);
words.add(word);
}
return words;
}
private static HashMap<String, String> findMentions(final String htmlText) {
final HashMap<String, String> map = new HashMap<String, String>();
final Matcher m = PATTERN_USERLINK.matcher(htmlText);
while (m.find()) {
final String userId = m.group(1);
final String screenName = Html.fromHtml(m.group(2)).toString();
map.put(screenName, userId);
}
return map;
}
public static void setStatus(final TextView textView, final String text) {
final String htmlText = text + " ";
// LogUtil.v(TAG, "setStatus:htmlText:" + htmlText);
final HashMap<String, String> mentions = findMentions(htmlText);
// LogUtil.v(TAG, "setStatus:mentions:" + mentions);
final String plainText = Html.fromHtml(htmlText).toString();
// LogUtil.v(TAG, "setStatus:plainText:" + plainText);
final SpannableString spannable = new SpannableString(plainText);
Linkify.addLinks(spannable, Linkify.WEB_URLS);
linkifyUsers(spannable, mentions);
linkifyTags(spannable);
removeUnderLines(spannable);
// LogUtil.v(TAG, "setStatus:finalText:" + spannable);
textView.setText(spannable, BufferType.SPANNABLE);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
public static void setItemStatus(final TextView textView, final String text) {
final String htmlText = text + " ";
final List<String> highlightWords = findHighlightWords(htmlText);
final String plainText = Html.fromHtml(htmlText).toString();
final SpannableString spannable = new SpannableString(plainText);
Linkify.addLinks(spannable, Linkify.WEB_URLS);
final Matcher m = PATTERN_USER.matcher(spannable);
while (m.find()) {
int start = m.start(1);
int end = m.end(1);
if (start >= 0 && start < end) {
spannable.setSpan(new ForegroundColorSpan(LINK_COLOR), start, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
linkifyTags(spannable);
removeUnderLines(spannable);
applyHighlightSpan(spannable, highlightWords);
textView.setText(spannable, BufferType.SPANNABLE);
}
public static void removeUnderLines(final SpannableString spannable) {
URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
for (final URLSpan span : spans) {
int start = spannable.getSpanStart(span);
int end = spannable.getSpanEnd(span);
spannable.removeSpan(span);
spannable.setSpan(new URLSpanNoUnderline(span.getURL()), start, end, 0);
}
}
public static void applyHighlightSpan(final SpannableString span,
final List<String> keywords) {
if (keywords == null || keywords.isEmpty()) {
return;
}
// LogUtil.v(TAG, "applyHighlightSpan() keywords:" + keywords);
for (final String keyword : keywords) {
if (!TextUtils.isEmpty(keyword)) {
final Pattern pattern = Pattern.compile(keyword);
Matcher m = pattern.matcher(span);
if (m.find()) {
int start = m.start();
int end = m.end();
span.setSpan(new ForegroundColorSpan(COLOR_HIGHLIGHT), start,
end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new StyleSpan(Typeface.BOLD), start, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
}
public static ArrayList<String> getMentions(final StatusModel status) {
String text = status.getSimpleText();
ArrayList<String> names = new ArrayList<String>();
names.add(status.getUserScreenName());
Matcher m = namePattern.matcher(text);
while (m.find()) {
String name = m.group(1);
if (!names.contains(name) && name.length() <= MAX_NAME_LENGTH + 1) {
names.add(m.group(1));
}
}
String name = AppContext.getScreenName();
names.remove(name);
return names;
}
public static class URLSpanNoUnderline extends URLSpan {
public URLSpanNoUnderline(String url) {
super(url);
}
@Override
public void updateDrawState(TextPaint tp) {
super.updateDrawState(tp);
tp.setUnderlineText(false);
tp.setColor(LINK_COLOR);
}
}
}