image-loader Fix data scheme handler
This commit is contained in:
parent
e7d4c0fb33
commit
11d80786d4
@ -79,6 +79,14 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
// todo: should we cancel pending request for the same destination?
|
||||
// we _could_ but there is possibility that one resource is request in multiple places
|
||||
|
||||
// todo: error handing (simply applying errorDrawable is not a good solution
|
||||
// as reason for an error is unclear (no scheme handler, no input data, error decoding, etc)
|
||||
|
||||
// todo: more efficient ImageMediaDecoder... BitmapFactory.decodeStream is a bit not optimal
|
||||
// for big images for sure. We _could_ introduce internal Drawable that will check for
|
||||
// image bounds (but we will need to cache inputStream in order to inspect and optimize
|
||||
// input image...)
|
||||
|
||||
// todo, if not a link -> show placeholder
|
||||
|
||||
return executorService.submit(new Runnable() {
|
||||
@ -176,6 +184,10 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
return out;
|
||||
}
|
||||
|
||||
// todo: as now we have different layers of abstraction (for scheme handling and media decoding)
|
||||
// we no longer should add dependencies implicitly, it would be way better to allow adding
|
||||
// multiple artifacts (file, data, network, svg, gif)... at least, maybe we can extract API
|
||||
// for this module (without implementations), but keep _all-in_ (fat) artifact with all of these.
|
||||
public static class Builder {
|
||||
|
||||
private OkHttpClient client;
|
||||
|
@ -19,6 +19,8 @@ public class DataUriSchemeHandler extends SchemeHandler {
|
||||
return new DataUriSchemeHandler(DataUriParser.create(), DataUriDecoder.create());
|
||||
}
|
||||
|
||||
private static final String START = "data://";
|
||||
|
||||
private final DataUriParser uriParser;
|
||||
private final DataUriDecoder uriDecoder;
|
||||
|
||||
@ -32,12 +34,12 @@ public class DataUriSchemeHandler extends SchemeHandler {
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
final String part = uri.getSchemeSpecificPart();
|
||||
|
||||
if (TextUtils.isEmpty(part)) {
|
||||
if (!raw.startsWith(START)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String part = raw.substring(START.length());
|
||||
|
||||
final DataUri dataUri = uriParser.parse(part);
|
||||
if (dataUri == null) {
|
||||
return null;
|
||||
|
@ -16,6 +16,10 @@ public abstract class SchemeHandler {
|
||||
|
||||
public abstract void cancel(@NonNull String raw);
|
||||
|
||||
/**
|
||||
* Will be called only once during initialization, should return schemes that are
|
||||
* handled by this handler
|
||||
*/
|
||||
@NonNull
|
||||
public abstract Collection<String> schemes();
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
package ru.noties.markwon.il;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class DataUriSchemeHandlerTest {
|
||||
|
||||
private DataUriSchemeHandler handler;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
handler = DataUriSchemeHandler.create();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheme_specific_part_is_empty() {
|
||||
assertNull(handler.handle("data:", Uri.parse("data:")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void data_uri_is_empty() {
|
||||
assertNull(handler.handle("data://whatever", Uri.parse("data://whatever")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void no_data() {
|
||||
assertNull(handler.handle("data://,", Uri.parse("data://,")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correct() {
|
||||
|
||||
final class Item {
|
||||
|
||||
final String contentType;
|
||||
final String data;
|
||||
|
||||
Item(String contentType, String data) {
|
||||
this.contentType = contentType;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, Item> expected = new HashMap<String, Item>() {{
|
||||
put("data://text/plain;,123", new Item("text/plain", "123"));
|
||||
put("data://image/svg+xml;base64,MTIz", new Item("image/svg+xml", "123"));
|
||||
}};
|
||||
|
||||
for (Map.Entry<String, Item> entry : expected.entrySet()) {
|
||||
final ImageItem item = handler.handle(entry.getKey(), Uri.parse(entry.getKey()));
|
||||
assertNotNull(entry.getKey(), item);
|
||||
assertEquals(entry.getKey(), entry.getValue().contentType, item.contentType());
|
||||
assertEquals(entry.getKey(), entry.getValue().data, readStream(item.inputStream()));
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String readStream(@NonNull InputStream stream) {
|
||||
try {
|
||||
final Scanner scanner = new Scanner(stream, "UTF-8").useDelimiter("\\A");
|
||||
return scanner.hasNext()
|
||||
? scanner.next()
|
||||
: "";
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user