Skip to content

Commit 7c6d4f4

Browse files
committed
add WPImageGetter and fix HtmlUtils
1 parent b4baff8 commit 7c6d4f4

File tree

4 files changed

+213
-12
lines changed

4 files changed

+213
-12
lines changed

WordPressUtils/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ repositories {
1414

1515
dependencies {
1616
compile 'commons-lang:commons-lang:2.6'
17+
compile 'com.mcxiaoke.volley:library:1.0.+'
1718
}
1819

1920
android {

WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ public class HtmlUtils {
1717
* but it's very slow, so avoid using this where performance is important
1818
*/
1919
public static String stripHtml(final String text) {
20-
if (TextUtils.isEmpty(text))
20+
if (TextUtils.isEmpty(text)) {
2121
return "";
22+
}
2223
return Html.fromHtml(text).toString().trim();
2324
}
2425

@@ -55,8 +56,7 @@ private static String trimStart(final String str) {
5556
return "";
5657
}
5758
int start = 0;
58-
while (start != strLen
59-
&& (Character.isWhitespace(str.charAt(start)) || str.charAt(start) == 160)) {
59+
while (start != strLen && (Character.isWhitespace(str.charAt(start)) || str.charAt(start) == 160)) {
6060
start++;
6161
}
6262
return str.substring(start);
@@ -66,8 +66,9 @@ private static String trimStart(final String str) {
6666
* convert html entities to actual Unicode characters - relies on commons apache lang
6767
*/
6868
public static String fastUnescapeHtml(final String text) {
69-
if (text == null || !text.contains("&"))
69+
if (text == null || !text.contains("&")) {
7070
return text;
71+
}
7172
return StringEscapeUtils.unescapeHtml(text);
7273
}
7374

@@ -90,16 +91,18 @@ public static String colorResToHtmlColor(Context context, int resId) {
9091
* first seen at http://houseofgeekery.com/2013/11/03/13-terrible-x-men-we-wont-see-in-the-movies/
9192
*/
9293
public static String stripScript(final String text) {
93-
if (text == null)
94+
if (text == null) {
9495
return null;
96+
}
9597

9698
StringBuilder sb = new StringBuilder(text);
9799
int start = sb.indexOf("<script");
98100

99101
while (start > -1) {
100102
int end = sb.indexOf("</script>", start);
101-
if (end == -1)
103+
if (end == -1) {
102104
return sb.toString();
105+
}
103106
sb.delete(start, end + 9);
104107
start = sb.indexOf("<script", start);
105108
}
@@ -121,10 +124,9 @@ public static SpannableStringBuilder fromHtml(String source, WPImageGetter wpIma
121124
Emoticons.replaceEmoticonsWithEmoji(html);
122125
QuoteSpan spans[] = html.getSpans(0, html.length(), QuoteSpan.class);
123126
for (QuoteSpan span : spans) {
124-
html.setSpan(new WPHtml.WPQuoteSpan(), html.getSpanStart(span), html.getSpanEnd(span), html.getSpanFlags(
125-
span));
126-
html.setSpan(new ForegroundColorSpan(0xFF666666), html.getSpanStart(span), html.getSpanEnd(span), html.getSpanFlags(
127-
span));
127+
html.setSpan(new WPQuoteSpan(), html.getSpanStart(span), html.getSpanEnd(span), html.getSpanFlags(span));
128+
html.setSpan(new ForegroundColorSpan(0xFF666666), html.getSpanStart(span), html.getSpanEnd(span),
129+
html.getSpanFlags(span));
128130
html.removeSpan(span);
129131
}
130132
return html;
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package org.wordpress.android.util;
2+
3+
import android.graphics.Canvas;
4+
import android.graphics.drawable.BitmapDrawable;
5+
import android.graphics.drawable.Drawable;
6+
import android.text.Html;
7+
import android.text.TextUtils;
8+
import android.widget.TextView;
9+
10+
import com.android.volley.VolleyError;
11+
import com.android.volley.toolbox.ImageLoader;
12+
13+
import org.wordpress.android.util.AppLog.T;
14+
15+
import java.lang.ref.WeakReference;
16+
17+
/**
18+
* ImageGetter for Html.fromHtml()
19+
* adapted from existing ImageGetter code in NoteCommentFragment
20+
*/
21+
public class WPImageGetter implements Html.ImageGetter {
22+
private WeakReference<TextView> mWeakView;
23+
private int mMaxSize;
24+
private ImageLoader mImageLoader;
25+
private Drawable mLoadingDrawable;
26+
private Drawable mFailedDrawable;
27+
28+
public WPImageGetter(TextView view) {
29+
this(view, 0);
30+
}
31+
32+
public WPImageGetter(TextView view, int maxSize) {
33+
mWeakView = new WeakReference<TextView>(view);
34+
mMaxSize = maxSize;
35+
}
36+
37+
public WPImageGetter(TextView view, int maxSize, ImageLoader imageLoader, Drawable loadingDrawable,
38+
Drawable failedDrawable) {
39+
mWeakView = new WeakReference<TextView>(view);
40+
mMaxSize = maxSize;
41+
mImageLoader = imageLoader;
42+
mLoadingDrawable = loadingDrawable;
43+
mFailedDrawable = failedDrawable;
44+
}
45+
46+
public void setImageLoader(ImageLoader imageLoader) {
47+
mImageLoader = imageLoader;
48+
}
49+
50+
public void setLoadingDrawable(Drawable loadingDrawable) {
51+
mLoadingDrawable = loadingDrawable;
52+
}
53+
54+
public void setFailedDrawable(Drawable failedDrawable) {
55+
mFailedDrawable = failedDrawable;
56+
}
57+
58+
private TextView getView() {
59+
return mWeakView.get();
60+
}
61+
62+
@Override
63+
public Drawable getDrawable(String source) {
64+
if (mImageLoader == null || mLoadingDrawable == null || mFailedDrawable == null) {
65+
throw new RuntimeException("Developer, you need to call setImageLoader, setLoadingDrawable and setFailedDrawable");
66+
}
67+
68+
if (TextUtils.isEmpty(source)) {
69+
return null;
70+
}
71+
72+
// images in reader comments may skip "http:" (no idea why) so make sure to add protocol here
73+
if (source.startsWith("//")) {
74+
source = "http:" + source;
75+
}
76+
77+
// use Photon if a max size is requested (otherwise the full-sized image will be downloaded
78+
// and then resized)
79+
if (mMaxSize > 0) {
80+
source = PhotonUtils.getPhotonImageUrl(source, mMaxSize, 0);
81+
}
82+
83+
TextView view = getView();
84+
// Drawable loading = view.getContext().getResources().getDrawable(R.drawable.remote_image); FIXME: here
85+
// Drawable failed = view.getContext().getResources().getDrawable(R.drawable.remote_failed);
86+
final RemoteDrawable remote = new RemoteDrawable(mLoadingDrawable, mFailedDrawable);
87+
88+
mImageLoader.get(source, new ImageLoader.ImageListener() {
89+
@Override
90+
public void onErrorResponse(VolleyError error) {
91+
remote.displayFailed();
92+
TextView view = getView();
93+
if (view != null) {
94+
view.invalidate();
95+
}
96+
}
97+
98+
@Override
99+
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
100+
if (response.getBitmap() != null) {
101+
// make sure view is still valid
102+
TextView view = getView();
103+
if (view == null) {
104+
AppLog.w(T.UTILS, "WPImageGetter view is invalid");
105+
return;
106+
}
107+
108+
Drawable drawable = new BitmapDrawable(view.getContext().getResources(), response.getBitmap());
109+
final int oldHeight = remote.getBounds().height();
110+
int maxWidth = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight();
111+
if (mMaxSize > 0 && (maxWidth > mMaxSize || maxWidth == 0)) {
112+
maxWidth = mMaxSize;
113+
}
114+
remote.setRemoteDrawable(drawable, maxWidth);
115+
116+
// image is from cache? don't need to modify view height
117+
if (isImmediate) {
118+
return;
119+
}
120+
121+
int newHeight = remote.getBounds().height();
122+
view.invalidate();
123+
// For ICS
124+
view.setHeight(view.getHeight() + newHeight - oldHeight);
125+
// Pre ICS
126+
view.setEllipsize(null);
127+
}
128+
}
129+
});
130+
return remote;
131+
}
132+
133+
private static class RemoteDrawable extends BitmapDrawable {
134+
protected Drawable mRemoteDrawable;
135+
protected Drawable mLoadingDrawable;
136+
protected Drawable mFailedDrawable;
137+
private boolean mDidFail = false;
138+
139+
public RemoteDrawable(Drawable loadingDrawable, Drawable failedDrawable) {
140+
mLoadingDrawable = loadingDrawable;
141+
mFailedDrawable = failedDrawable;
142+
setBounds(0, 0, mLoadingDrawable.getIntrinsicWidth(), mLoadingDrawable.getIntrinsicHeight());
143+
}
144+
145+
public void displayFailed() {
146+
mDidFail = true;
147+
}
148+
149+
public void setBounds(int x, int y, int width, int height) {
150+
super.setBounds(x, y, width, height);
151+
if (mRemoteDrawable != null) {
152+
mRemoteDrawable.setBounds(x, y, width, height);
153+
return;
154+
}
155+
if (mLoadingDrawable != null) {
156+
mLoadingDrawable.setBounds(x, y, width, height);
157+
mFailedDrawable.setBounds(x, y, width, height);
158+
}
159+
}
160+
161+
public void setRemoteDrawable(Drawable remote) {
162+
mRemoteDrawable = remote;
163+
setBounds(0, 0, mRemoteDrawable.getIntrinsicWidth(), mRemoteDrawable.getIntrinsicHeight());
164+
}
165+
166+
public void setRemoteDrawable(Drawable remote, int maxWidth) {
167+
// null sentinel for now
168+
if (remote == null) {
169+
// throw error
170+
return;
171+
}
172+
mRemoteDrawable = remote;
173+
// determine if we need to scale the image to fit in view
174+
int imgWidth = remote.getIntrinsicWidth();
175+
int imgHeight = remote.getIntrinsicHeight();
176+
float xScale = (float) imgWidth / (float) maxWidth;
177+
if (xScale > 1.0f) {
178+
setBounds(0, 0, Math.round(imgWidth / xScale), Math.round(imgHeight / xScale));
179+
} else {
180+
setBounds(0, 0, imgWidth, imgHeight);
181+
}
182+
}
183+
184+
public boolean didFail() {
185+
return mDidFail;
186+
}
187+
188+
public void draw(Canvas canvas) {
189+
if (mRemoteDrawable != null) {
190+
mRemoteDrawable.draw(canvas);
191+
} else if (didFail()) {
192+
mFailedDrawable.draw(canvas);
193+
} else {
194+
mLoadingDrawable.draw(canvas);
195+
}
196+
}
197+
}
198+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Mon Jun 30 12:35:54 EDT 2014
1+
#Wed Jul 09 11:48:51 CEST 2014
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-1.11-bin.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-1.11-all.zip

0 commit comments

Comments
 (0)