Show WebXDC name and icon

Stephen Paul Weber created

Change summary

src/cheogram/java/com/cheogram/android/WebxdcPage.java              | 35 
src/main/java/eu/siacs/conversations/entities/Conversation.java     |  8 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 31 
3 files changed, 60 insertions(+), 14 deletions(-)

Detailed changes

src/cheogram/java/com/cheogram/android/WebxdcPage.java 🔗

@@ -5,8 +5,12 @@ package com.cheogram.android;
 
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.graphics.ImageDecoder;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Gravity;
@@ -25,6 +29,8 @@ import androidx.annotation.RequiresApi;
 import androidx.core.content.ContextCompat;
 import androidx.databinding.DataBindingUtil;
 
+import com.google.common.io.ByteStreams;
+
 import io.ipfs.cid.Cid;
 
 import java.lang.ref.WeakReference;
@@ -32,6 +38,7 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.zip.ZipEntry;
@@ -48,6 +55,7 @@ import eu.siacs.conversations.R;
 import eu.siacs.conversations.databinding.WebxdcPageBinding;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.utils.Consumer;
 import eu.siacs.conversations.utils.MimeUtils;
@@ -85,6 +93,33 @@ public class WebxdcPage implements ConversationPage {
 		baseUrl = "https://" + source.getUuid() + ".localhost";
 	}
 
+	public Drawable getIcon() {
+		if (android.os.Build.VERSION.SDK_INT < 28) return null;
+		ZipEntry entry = zip.getEntry("icon.webp");
+		if (entry == null) entry = zip.getEntry("icon.png");
+		if (entry == null) entry = zip.getEntry("icon.jpg");
+		if (entry == null) return null;
+
+		try {
+			DisplayMetrics metrics = xmppConnectionService.getResources().getDisplayMetrics();
+			ImageDecoder.Source source = ImageDecoder.createSource(ByteBuffer.wrap(ByteStreams.toByteArray(zip.getInputStream(entry))));
+			return ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
+				int w = info.getSize().getWidth();
+				int h = info.getSize().getHeight();
+				Rect r = FileBackend.rectForSize(w, h, (int)(metrics.density * 288));
+				decoder.setTargetSize(r.width(), r.height());
+			});
+		} catch (final IOException e) {
+			Log.w(Config.LOGTAG, "WebxdcPage.getIcon: " + e);
+			return null;
+		}
+	}
+
+	public String getName() {
+		String title = manifest == null ? null : manifest.getString("name");
+		return title == null ? "ChatApp" : title;
+	}
+
 	public String getTitle() {
 		String title = manifest == null ? null : manifest.getString("name");
 		if (lastUpdate != null && lastUpdate.getDocument() != null) {

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -1309,8 +1309,8 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
         pagerAdapter.refreshSessions();
     }
 
-    public void startWebxdc(Cid cid, Message message, XmppConnectionService xmppConnectionService) {
-        pagerAdapter.startWebxdc(cid, message, xmppConnectionService);
+    public void startWebxdc(WebxdcPage page) {
+        pagerAdapter.startWebxdc(page);
     }
 
     public void startCommand(Element command, XmppConnectionService xmppConnectionService) {
@@ -1423,9 +1423,9 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
             }
         }
 
-        public void startWebxdc(Cid cid, Message message, XmppConnectionService xmppConnectionService) {
+        public void startWebxdc(WebxdcPage page) {
             show();
-            sessions.add(new WebxdcPage(cid, message, xmppConnectionService));
+            sessions.add(page);
             notifyDataSetChanged();
             if (mPager != null) mPager.setCurrentItem(getCount() - 1);
         }

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

@@ -42,6 +42,7 @@ import androidx.core.content.res.ResourcesCompat;
 
 import com.cheogram.android.BobTransfer;
 import com.cheogram.android.SwipeDetector;
+import com.cheogram.android.WebxdcPage;
 import com.cheogram.android.WebxdcUpdate;
 
 import com.google.common.base.Strings;
@@ -675,25 +676,35 @@ public class MessageAdapter extends ArrayAdapter<Message> {
     }
 
     private void displayWebxdcMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground, final int type) {
+        WebxdcPage webxdc = new WebxdcPage(message.getFileParams().getCids().get(0), message, activity.xmppConnectionService);
         displayTextMessage(viewHolder, message, darkBackground, type);
         viewHolder.image.setVisibility(View.GONE);
         viewHolder.audioPlayer.setVisibility(View.GONE);
         viewHolder.download_button.setVisibility(View.VISIBLE);
-        viewHolder.download_button.setText("Open ChatApp");
+        viewHolder.download_button.setText("Open " + webxdc.getName());
         viewHolder.download_button.setOnClickListener(v -> {
             Conversation conversation = (Conversation) message.getConversation();
             if (!conversation.switchToSession("webxdc\0" + message.getUuid())) {
-                conversation.startWebxdc(message.getFileParams().getCids().get(0), message, activity.xmppConnectionService);
+                conversation.startWebxdc(webxdc);
             }
         });
-        WebxdcUpdate lastUpdate = activity.xmppConnectionService.findLastWebxdcUpdate(message);
-        if (lastUpdate != null && (lastUpdate.getSummary() != null || lastUpdate.getDocument() != null)) {
-            viewHolder.messageBody.setVisibility(View.VISIBLE);
-            viewHolder.messageBody.setText(
-                (lastUpdate.getDocument() == null ? "" : lastUpdate.getDocument() + "\n") +
-                (lastUpdate.getSummary() == null ? "" : lastUpdate.getSummary())
-            );
-        }
+        new Thread(() -> {
+            Drawable icon = webxdc.getIcon();
+            WebxdcUpdate lastUpdate = activity.xmppConnectionService.findLastWebxdcUpdate(message);
+            activity.runOnUiThread(() -> {
+                if (lastUpdate != null && (lastUpdate.getSummary() != null || lastUpdate.getDocument() != null)) {
+                    viewHolder.messageBody.setVisibility(View.VISIBLE);
+                    viewHolder.messageBody.setText(
+                        (lastUpdate.getDocument() == null ? "" : lastUpdate.getDocument() + "\n") +
+                        (lastUpdate.getSummary() == null ? "" : lastUpdate.getSummary())
+                    );
+                }
+                if (icon != null) {
+                    viewHolder.image.setVisibility(View.VISIBLE);
+                    viewHolder.image.setImageDrawable(icon);
+                }
+            });
+        }).start();
     }
 
     private void displayOpenableMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground, final int type) {