package org.edx.mobile.discussion;
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.DateUtils;
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.view.View;
import android.widget.TextView;
import com.google.inject.Inject;
import org.edx.mobile.R;
import org.edx.mobile.util.Config;
import org.edx.mobile.util.ResourceUtil;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public abstract class DiscussionTextUtils {
@Inject
private static Config config;
private DiscussionTextUtils() {
}
public enum AuthorAttributionLabel {ANSWER, ENDORSEMENT}
public static void setAuthorAttributionText(@NonNull TextView textView,
@NonNull AuthorAttributionLabel authorAttributionLabel,
@NonNull final IAuthorData authorData,
long initialTimeStampMs,
@NonNull final Runnable onAuthorClickListener) {
final CharSequence text;
{
final Context context = textView.getContext();
List<CharSequence> joinableStrings = new ArrayList<>();
boolean isEndorsed = false;
switch (authorAttributionLabel) {
case ANSWER:
isEndorsed = true;
joinableStrings.add(context.getString(R.string.discussion_post_marked_as_answer));
break;
case ENDORSEMENT:
isEndorsed = true;
joinableStrings.add(context.getString(R.string.discussion_post_endorsed));
break;
}
final Date dateCreated = authorData.getCreatedAt();
if (dateCreated != null) {
joinableStrings.add(getRelativeTimeSpanString(context, initialTimeStampMs,
dateCreated.getTime()));
}
final String author = authorData.getAuthor();
if (!TextUtils.isEmpty(author)) {
final SpannableString authorSpan = new SpannableString(author);
if (config.isUserProfilesEnabled() && !authorData.isAuthorAnonymous()) {
// Change the author text color and style
authorSpan.setSpan(new ForegroundColorSpan(context.getResources().
getColor(R.color.edx_brand_primary_base)), 0,
authorSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
authorSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, authorSpan.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// Set the click listener on the whole textView
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onAuthorClickListener.run();
}
});
} else {
textView.setOnClickListener(null);
textView.setClickable(false);
}
joinableStrings.add(ResourceUtil.getFormattedString(context.getResources(),
R.string.discussion_post_author_attribution, "author", authorSpan));
}
final String authorLabel = authorData.getAuthorLabel();
if (!TextUtils.isEmpty(authorLabel)) {
joinableStrings.add(ResourceUtil.getFormattedString(context.getResources(),
R.string.discussion_post_author_label_attribution, "text", authorLabel));
}
int joinableStringsSize = joinableStrings.size();
if (joinableStringsSize == 0 || (isEndorsed && joinableStringsSize == 1)) {
text = null;
} else {
text = org.edx.mobile.util.TextUtils.join(" ", joinableStrings);
}
}
if (TextUtils.isEmpty(text)) {
textView.setVisibility(View.GONE);
} else {
textView.setText(text);
}
}
public static void setAuthorText(@NonNull TextView textView, @NonNull IAuthorData authorData) {
final CharSequence authorText;
{
final Context context = textView.getContext();
List<CharSequence> joinableStrings = new ArrayList<>();
final String author = authorData.getAuthor();
if (!TextUtils.isEmpty(author)) {
final SpannableString authorSpan = new SpannableString(author);
// Change the author text color and style
if (!authorData.isAuthorAnonymous()) {
authorSpan.setSpan(new ForegroundColorSpan(context.getResources().
getColor(R.color.edx_brand_primary_base)), 0,
authorSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
authorSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, authorSpan.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
joinableStrings.add(authorSpan);
}
final String authorLabel = authorData.getAuthorLabel();
if (!TextUtils.isEmpty(authorLabel)) {
joinableStrings.add(ResourceUtil.getFormattedString(context.getResources(),
R.string.discussion_post_author_label_attribution, "text", authorLabel));
}
authorText = org.edx.mobile.util.TextUtils.join(" ", joinableStrings);
}
if (TextUtils.isEmpty(authorText)) {
textView.setVisibility(View.GONE);
} else {
textView.setText(authorText);
}
}
public static CharSequence getRelativeTimeSpanString(@NonNull Context context, long nowMs,
long timeMs) {
return getRelativeTimeSpanString(context, nowMs, timeMs,
DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_YEAR);
}
public static CharSequence getRelativeTimeSpanString(@NonNull Context context, long nowMs,
long timeMs, int flags) {
if (nowMs - timeMs < DateUtils.SECOND_IN_MILLIS) {
return context.getString(R.string.just_now);
} else {
return DateUtils.getRelativeTimeSpanString(timeMs, nowMs,
DateUtils.SECOND_IN_MILLIS, flags);
}
}
public static Spanned parseHtml(@NonNull String html) {
// If the HTML contains a paragraph at the end, there will be blank lines following the text
// Therefore, we need to trim the resulting CharSequence to remove those extra lines
return (Spanned) trim(Html.fromHtml(html));
}
public static CharSequence trim(CharSequence s) {
int start = 0, end = s.length();
while (start < end && Character.isWhitespace(s.charAt(start))) {
start++;
}
while (end > start && Character.isWhitespace(s.charAt(end - 1))) {
end--;
}
return s.subSequence(start, end);
}
public static void setEndorsedState(@NonNull TextView target,
@NonNull DiscussionThread thread,
@NonNull DiscussionComment response) {
if (response.isEndorsed()) {
switch (thread.getType()) {
case QUESTION:
target.setText(R.string.discussion_responses_answer);
break;
case DISCUSSION:
default:
target.setText(R.string.discussion_responses_endorsed);
break;
}
target.setVisibility(View.VISIBLE);
}
}
/**
* Renders various HTML elements and plain hyperlinks in the given HTML to clickable items
* while applying it on the given {@link TextView}.
*
* @param textView The {@link TextView} which will render the given HTML.
* @param html The HTML to render.
*/
public static void renderHtml(@NonNull TextView textView, @NonNull String html) {
Spanned spannedHtml = DiscussionTextUtils.parseHtml(html);
URLSpan[] urlSpans = spannedHtml.getSpans(0, spannedHtml.length(), URLSpan.class);
textView.setAutoLinkMask(Linkify.ALL);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(spannedHtml);
SpannableString viewText = (SpannableString) textView.getText();
for (final URLSpan spanObj : urlSpans) {
final int start = spannedHtml.getSpanStart(spanObj);
final int end = spannedHtml.getSpanEnd(spanObj);
final int flags = spannedHtml.getSpanFlags(spanObj);
viewText.setSpan(spanObj, start, end, flags);
}
}
}