Loading res/values/colors.xml +3 −0 Original line number Diff line number Diff line Loading @@ -71,4 +71,7 @@ <!-- Color of the semi-transparent shadow box on contact tiles --> <color name="contact_tile_shadow_box_color">#7F000000</color> <!-- Color of the vertical stripe that goes on the left of a block quote inside a stream item --> <color name="stream_item_stripe_color">#CCCCCC</color> </resources> res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -191,4 +191,7 @@ <!-- Vertical and horizontal padding in between contact tiles --> <dimen name="contact_tile_divider_padding">1dip</dimen> <!-- Width of the lead margin on the left of a block quote inside a stream item --> <dimen name="stream_item_stripe_width">8dip</dimen> </resources> src/com/android/contacts/detail/ContactDetailDisplayUtils.java +5 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import com.android.contacts.ContactPhotoManager; import com.android.contacts.R; import com.android.contacts.preference.ContactsPreferences; import com.android.contacts.util.ContactBadgeUtil; import com.android.contacts.util.HtmlUtils; import com.android.contacts.util.StreamItemEntry; import com.android.contacts.util.StreamItemPhotoEntry; import com.google.common.annotations.VisibleForTesting; Loading Loading @@ -236,7 +237,7 @@ public class ContactDetailDisplayUtils { String photoUri = null; if (!contactData.getStreamItems().isEmpty()) { StreamItemEntry firstEntry = contactData.getStreamItems().get(0); snippet = Html.fromHtml(firstEntry.getText()); snippet = HtmlUtils.fromHtml(context, firstEntry.getText()); if (!firstEntry.getPhotos().isEmpty()) { StreamItemPhotoEntry firstPhoto = firstEntry.getPhotos().get(0); photoUri = firstPhoto.getPhotoUri(); Loading Loading @@ -338,10 +339,11 @@ public class ContactDetailDisplayUtils { R.id.stream_item_attribution); TextView commentsView = (TextView) rootView.findViewById(R.id.stream_item_comments); ImageGetter imageGetter = new DefaultImageGetter(context.getPackageManager()); htmlView.setText(Html.fromHtml(streamItem.getText(), imageGetter, null)); htmlView.setText(HtmlUtils.fromHtml(context, streamItem.getText(), imageGetter, null)); attributionView.setText(ContactBadgeUtil.getSocialDate(streamItem, context)); if (streamItem.getComments() != null) { commentsView.setText(Html.fromHtml(streamItem.getComments(), imageGetter, null)); commentsView.setText(HtmlUtils.fromHtml(context, streamItem.getComments(), imageGetter, null)); commentsView.setVisibility(View.VISIBLE); } else { commentsView.setVisibility(View.GONE); Loading src/com/android/contacts/socialwidget/SocialWidgetProvider.java +2 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import com.android.contacts.R; import com.android.contacts.model.AccountType; import com.android.contacts.model.AccountTypeManager; import com.android.contacts.util.ContactBadgeUtil; import com.android.contacts.util.HtmlUtils; import com.android.contacts.util.StreamItemEntry; import android.app.PendingIntent; Loading @@ -36,7 +37,6 @@ import android.graphics.Typeface; import android.net.Uri; import android.provider.ContactsContract.QuickContact; import android.provider.ContactsContract.StreamItems; import android.text.Html; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; Loading Loading @@ -208,7 +208,7 @@ public class SocialWidgetProvider extends AppWidgetProvider { } else { // TODO: Rotate between all the stream items? StreamItemEntry streamItem = streamItems.get(0); CharSequence status = Html.fromHtml(streamItem.getText()); CharSequence status = HtmlUtils.fromHtml(context, streamItem.getText()); if (status.length() <= SHORT_SNIPPET_LENGTH) { sb.append("\n"); } else { Loading src/com/android/contacts/util/HtmlUtils.java 0 → 100644 +101 −0 Original line number Diff line number Diff line package com.android.contacts.util; import android.content.Context; import android.content.res.Resources; import android.text.Html; import android.text.Html.ImageGetter; import android.text.Html.TagHandler; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ImageSpan; import android.text.style.QuoteSpan; import com.android.contacts.R; /** * Provides static functions to perform custom HTML to text conversions. * Specifically, it adjusts the color and padding of the vertical * stripe on block quotes and alignment of inlined images. */ public class HtmlUtils { /** * Converts HTML string to a {@link Spanned} text, adjusting formatting. */ public static Spanned fromHtml(Context context, String text) { Spanned spanned = Html.fromHtml(text); postprocess(context, spanned); return spanned; } /** * Converts HTML string to a {@link Spanned} text, adjusting formatting and using a custom * image getter. */ public static CharSequence fromHtml(Context context, String text, ImageGetter imageGetter, TagHandler tagHandler) { Spanned spanned = Html.fromHtml(text, imageGetter, tagHandler); postprocess(context, spanned); return spanned; } /** * Replaces some spans with custom versions of those. */ private static void postprocess(Context context, Spanned spanned) { if (!(spanned instanceof SpannableStringBuilder)) { return; } int length = spanned.length(); SpannableStringBuilder builder = (SpannableStringBuilder)spanned; QuoteSpan[] quoteSpans = spanned.getSpans(0, length, QuoteSpan.class); if (quoteSpans != null && quoteSpans.length != 0) { Resources resources = context.getResources(); int color = resources.getColor(R.color.stream_item_stripe_color); int width = resources.getDimensionPixelSize(R.dimen.stream_item_stripe_width); for (int i = 0; i < quoteSpans.length; i++) { replaceSpan(builder, quoteSpans[i], new StreamItemQuoteSpan(color, width)); } } ImageSpan[] imageSpans = spanned.getSpans(0, length, ImageSpan.class); if (imageSpans != null) { for (int i = 0; i < imageSpans.length; i++) { ImageSpan span = imageSpans[i]; replaceSpan(builder, span, new ImageSpan(span.getDrawable(), ImageSpan.ALIGN_BASELINE)); } } } /** * Replaces one span with the other. */ private static void replaceSpan(SpannableStringBuilder builder, Object originalSpan, Object newSpan) { builder.setSpan(newSpan, builder.getSpanStart(originalSpan), builder.getSpanEnd(originalSpan), builder.getSpanFlags(originalSpan)); builder.removeSpan(originalSpan); } public static class StreamItemQuoteSpan extends QuoteSpan { private final int mWidth; public StreamItemQuoteSpan(int color, int width) { super(color); this.mWidth = width; } /** * {@inheritDoc} */ @Override public int getLeadingMargin(boolean first) { return mWidth; } } } Loading
res/values/colors.xml +3 −0 Original line number Diff line number Diff line Loading @@ -71,4 +71,7 @@ <!-- Color of the semi-transparent shadow box on contact tiles --> <color name="contact_tile_shadow_box_color">#7F000000</color> <!-- Color of the vertical stripe that goes on the left of a block quote inside a stream item --> <color name="stream_item_stripe_color">#CCCCCC</color> </resources>
res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -191,4 +191,7 @@ <!-- Vertical and horizontal padding in between contact tiles --> <dimen name="contact_tile_divider_padding">1dip</dimen> <!-- Width of the lead margin on the left of a block quote inside a stream item --> <dimen name="stream_item_stripe_width">8dip</dimen> </resources>
src/com/android/contacts/detail/ContactDetailDisplayUtils.java +5 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import com.android.contacts.ContactPhotoManager; import com.android.contacts.R; import com.android.contacts.preference.ContactsPreferences; import com.android.contacts.util.ContactBadgeUtil; import com.android.contacts.util.HtmlUtils; import com.android.contacts.util.StreamItemEntry; import com.android.contacts.util.StreamItemPhotoEntry; import com.google.common.annotations.VisibleForTesting; Loading Loading @@ -236,7 +237,7 @@ public class ContactDetailDisplayUtils { String photoUri = null; if (!contactData.getStreamItems().isEmpty()) { StreamItemEntry firstEntry = contactData.getStreamItems().get(0); snippet = Html.fromHtml(firstEntry.getText()); snippet = HtmlUtils.fromHtml(context, firstEntry.getText()); if (!firstEntry.getPhotos().isEmpty()) { StreamItemPhotoEntry firstPhoto = firstEntry.getPhotos().get(0); photoUri = firstPhoto.getPhotoUri(); Loading Loading @@ -338,10 +339,11 @@ public class ContactDetailDisplayUtils { R.id.stream_item_attribution); TextView commentsView = (TextView) rootView.findViewById(R.id.stream_item_comments); ImageGetter imageGetter = new DefaultImageGetter(context.getPackageManager()); htmlView.setText(Html.fromHtml(streamItem.getText(), imageGetter, null)); htmlView.setText(HtmlUtils.fromHtml(context, streamItem.getText(), imageGetter, null)); attributionView.setText(ContactBadgeUtil.getSocialDate(streamItem, context)); if (streamItem.getComments() != null) { commentsView.setText(Html.fromHtml(streamItem.getComments(), imageGetter, null)); commentsView.setText(HtmlUtils.fromHtml(context, streamItem.getComments(), imageGetter, null)); commentsView.setVisibility(View.VISIBLE); } else { commentsView.setVisibility(View.GONE); Loading
src/com/android/contacts/socialwidget/SocialWidgetProvider.java +2 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import com.android.contacts.R; import com.android.contacts.model.AccountType; import com.android.contacts.model.AccountTypeManager; import com.android.contacts.util.ContactBadgeUtil; import com.android.contacts.util.HtmlUtils; import com.android.contacts.util.StreamItemEntry; import android.app.PendingIntent; Loading @@ -36,7 +37,6 @@ import android.graphics.Typeface; import android.net.Uri; import android.provider.ContactsContract.QuickContact; import android.provider.ContactsContract.StreamItems; import android.text.Html; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; Loading Loading @@ -208,7 +208,7 @@ public class SocialWidgetProvider extends AppWidgetProvider { } else { // TODO: Rotate between all the stream items? StreamItemEntry streamItem = streamItems.get(0); CharSequence status = Html.fromHtml(streamItem.getText()); CharSequence status = HtmlUtils.fromHtml(context, streamItem.getText()); if (status.length() <= SHORT_SNIPPET_LENGTH) { sb.append("\n"); } else { Loading
src/com/android/contacts/util/HtmlUtils.java 0 → 100644 +101 −0 Original line number Diff line number Diff line package com.android.contacts.util; import android.content.Context; import android.content.res.Resources; import android.text.Html; import android.text.Html.ImageGetter; import android.text.Html.TagHandler; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ImageSpan; import android.text.style.QuoteSpan; import com.android.contacts.R; /** * Provides static functions to perform custom HTML to text conversions. * Specifically, it adjusts the color and padding of the vertical * stripe on block quotes and alignment of inlined images. */ public class HtmlUtils { /** * Converts HTML string to a {@link Spanned} text, adjusting formatting. */ public static Spanned fromHtml(Context context, String text) { Spanned spanned = Html.fromHtml(text); postprocess(context, spanned); return spanned; } /** * Converts HTML string to a {@link Spanned} text, adjusting formatting and using a custom * image getter. */ public static CharSequence fromHtml(Context context, String text, ImageGetter imageGetter, TagHandler tagHandler) { Spanned spanned = Html.fromHtml(text, imageGetter, tagHandler); postprocess(context, spanned); return spanned; } /** * Replaces some spans with custom versions of those. */ private static void postprocess(Context context, Spanned spanned) { if (!(spanned instanceof SpannableStringBuilder)) { return; } int length = spanned.length(); SpannableStringBuilder builder = (SpannableStringBuilder)spanned; QuoteSpan[] quoteSpans = spanned.getSpans(0, length, QuoteSpan.class); if (quoteSpans != null && quoteSpans.length != 0) { Resources resources = context.getResources(); int color = resources.getColor(R.color.stream_item_stripe_color); int width = resources.getDimensionPixelSize(R.dimen.stream_item_stripe_width); for (int i = 0; i < quoteSpans.length; i++) { replaceSpan(builder, quoteSpans[i], new StreamItemQuoteSpan(color, width)); } } ImageSpan[] imageSpans = spanned.getSpans(0, length, ImageSpan.class); if (imageSpans != null) { for (int i = 0; i < imageSpans.length; i++) { ImageSpan span = imageSpans[i]; replaceSpan(builder, span, new ImageSpan(span.getDrawable(), ImageSpan.ALIGN_BASELINE)); } } } /** * Replaces one span with the other. */ private static void replaceSpan(SpannableStringBuilder builder, Object originalSpan, Object newSpan) { builder.setSpan(newSpan, builder.getSpanStart(originalSpan), builder.getSpanEnd(originalSpan), builder.getSpanFlags(originalSpan)); builder.removeSpan(originalSpan); } public static class StreamItemQuoteSpan extends QuoteSpan { private final int mWidth; public StreamItemQuoteSpan(int color, int width) { super(color); this.mWidth = width; } /** * {@inheritDoc} */ @Override public int getLeadingMargin(boolean first) { return mWidth; } } }