Support data-uri thumbnails

Stephen Paul Weber created

Change summary

src/main/java/eu/siacs/conversations/persistance/FileBackend.java   | 43 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java |  2 
2 files changed, 43 insertions(+), 2 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -55,11 +55,13 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.nio.ByteBuffer;
 import java.security.DigestOutputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
@@ -1039,7 +1041,46 @@ public class FileBackend {
     }
 
     public Drawable getThumbnail(Message message, Resources res, int size, boolean cacheOnly) throws IOException {
-        return getThumbnail(getFile(message), res, size, cacheOnly);
+        final LruCache<String, Drawable> cache = mXmppConnectionService.getDrawableCache();
+        DownloadableFile file = getFile(message);
+        Drawable thumbnail = cache.get(file.getAbsolutePath());
+        if (thumbnail != null) return thumbnail;
+
+        if ((thumbnail == null) && (!cacheOnly)) {
+            synchronized (THUMBNAIL_LOCK) {
+                List<Element> thumbs = message.getFileParams() != null ? message.getFileParams().getThumbnails() : null;
+                if (thumbs != null && !thumbs.isEmpty()) {
+                    for (Element thumb : thumbs) {
+                        Uri uri = Uri.parse(thumb.getAttribute("uri"));
+                        if (uri.getScheme().equals("data")) {
+                            if (android.os.Build.VERSION.SDK_INT < 28) continue;
+                            String[] parts = uri.getSchemeSpecificPart().split(",", 2);
+                            byte[] data;
+                            if (Arrays.asList(parts[0].split(";")).contains("base64")) {
+                                data = Base64.decode(parts[1], 0);
+                            } else {
+                                data = parts[1].getBytes("UTF-8");
+                            }
+
+                            ImageDecoder.Source source = ImageDecoder.createSource(ByteBuffer.wrap(data));
+                            thumbnail = ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
+                                int w = info.getSize().getWidth();
+                                int h = info.getSize().getHeight();
+                                Rect r = rectForSize(w, h, size);
+                                decoder.setTargetSize(r.width(), r.height());
+                            });
+
+                            if (thumbnail != null) {
+                                cache.put(file.getAbsolutePath(), thumbnail);
+                                return thumbnail;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return getThumbnail(file, res, size, cacheOnly);
     }
 
     public Drawable getThumbnail(DownloadableFile file, Resources res, int size, boolean cacheOnly) throws IOException {

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -600,7 +600,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
                 if (uri.getScheme().equals("data")) {
                     String[] parts = uri.getSchemeSpecificPart().split(",", 2);
                     parts = parts[0].split(";");
-                    if (!parts[0].equals("image/blurhash")) continue;
+                    if (!parts[0].equals("image/blurhash") && !parts[0].equals("image/jpeg") && !parts[0].equals("image/png") && !parts[0].equals("image/webp") && !parts[0].equals("image/gif")) continue;
                 } else {
                     continue;
                 }