diff --git a/FAQ.md b/FAQ.md index 3b3d2d774e..f8084c5bf0 100644 --- a/FAQ.md +++ b/FAQ.md @@ -21,6 +21,7 @@ The low priority status bar notification shows the number of pending operations, * Move message to another remote folder * Delete message from remote folder * Send message +* Download attachment **(3) What is a valid security certificate?** diff --git a/app/src/main/java/eu/faircode/email/AdapterAttachment.java b/app/src/main/java/eu/faircode/email/AdapterAttachment.java index c07bc2fa14..7df294a065 100644 --- a/app/src/main/java/eu/faircode/email/AdapterAttachment.java +++ b/app/src/main/java/eu/faircode/email/AdapterAttachment.java @@ -28,15 +28,19 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class AdapterAttachment extends RecyclerView.Adapter { private Context context; + private ExecutorService executor = Executors.newCachedThreadPool(); private List all = new ArrayList<>(); private List filtered = new ArrayList<>(); @@ -45,30 +49,39 @@ public class AdapterAttachment extends RecyclerView.Adapter> liveAttachments(long message); + @Query("SELECT * FROM attachment WHERE message = :message AND sequence = :sequence") + EntityAttachment getAttachment(long message, int sequence); + @Insert(onConflict = OnConflictStrategy.REPLACE) long insertAttachment(EntityAttachment attachment); + + @Update + void updateAttachment(EntityAttachment attachment); } diff --git a/app/src/main/java/eu/faircode/email/EntityAttachment.java b/app/src/main/java/eu/faircode/email/EntityAttachment.java index 774c5c9568..664952664b 100644 --- a/app/src/main/java/eu/faircode/email/EntityAttachment.java +++ b/app/src/main/java/eu/faircode/email/EntityAttachment.java @@ -21,10 +21,13 @@ package eu.faircode.email; import android.arch.persistence.room.Entity; import android.arch.persistence.room.ForeignKey; +import android.arch.persistence.room.Ignore; import android.arch.persistence.room.Index; import android.arch.persistence.room.PrimaryKey; import android.support.annotation.NonNull; +import javax.mail.BodyPart; + import static android.arch.persistence.room.ForeignKey.CASCADE; @Entity( @@ -50,4 +53,7 @@ public class EntityAttachment { @NonNull public String type; public byte[] content; + + @Ignore + BodyPart part; } diff --git a/app/src/main/java/eu/faircode/email/EntityOperation.java b/app/src/main/java/eu/faircode/email/EntityOperation.java index 0480e9039c..cdaa32e7cc 100644 --- a/app/src/main/java/eu/faircode/email/EntityOperation.java +++ b/app/src/main/java/eu/faircode/email/EntityOperation.java @@ -58,6 +58,7 @@ public class EntityOperation { public static final String MOVE = "move"; public static final String DELETE = "delete"; public static final String SEND = "send"; + public static final String ATTACHMENT = "attachment"; static void queue(Context context, EntityMessage message, String name) { JSONArray jsonArray = new JSONArray(); diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 9a91b48f06..b86679847d 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -67,6 +67,14 @@ public class Helper { return sb.toString(); } + static String humanReadableByteCount(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) return bytes + " B"; + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } + static StringBuilder getDebugInfo() { StringBuilder sb = new StringBuilder(); diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 5d40134590..d346b0f843 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -313,6 +313,7 @@ public class MessageHelper { attachment.sequence = result.size() + 1; attachment.name = part.getFileName(); attachment.type = ct.getBaseType(); + attachment.part = part; result.add(attachment); } } else if (content instanceof Multipart) { diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index b34bb24cba..8ac017e3b3 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -50,7 +50,9 @@ import com.sun.mail.imap.protocol.IMAPProtocol; import org.json.JSONArray; import org.json.JSONException; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -566,124 +568,151 @@ public class ServiceSynchronize extends LifecycleService { } } - private void processOperations(EntityFolder folder, IMAPStore istore, IMAPFolder ifolder) throws MessagingException, JSONException { + private void processOperations(EntityFolder folder, IMAPStore istore, IMAPFolder ifolder) throws MessagingException, JSONException, IOException { try { Log.i(Helper.TAG, folder.name + " start process"); DB db = DB.getInstance(this); DaoOperation operation = db.operation(); DaoMessage message = db.message(); - for (TupleOperationEx op : operation.getOperations(folder.id)) { - Log.i(Helper.TAG, folder.name + - " Process op=" + op.id + "/" + op.name + - " args=" + op.args + - " msg=" + op.message); - - JSONArray jargs = new JSONArray(op.args); + for (TupleOperationEx op : operation.getOperations(folder.id)) try { - if (EntityOperation.SEEN.equals(op.name)) { - // Mark message (un)seen - Message imessage = ifolder.getMessageByUID(op.uid); - if (imessage == null) - throw new MessageRemovedException(); - imessage.setFlag(Flags.Flag.SEEN, jargs.getBoolean(0)); - - } else if (EntityOperation.ADD.equals(op.name)) { - if (!folder.synchronize) { - // Local drafts - Log.w(Helper.TAG, "Folder synchronization disabled"); - return; - } + Log.i(Helper.TAG, folder.name + + " start op=" + op.id + "/" + op.name + + " args=" + op.args + + " msg=" + op.message); + + JSONArray jargs = new JSONArray(op.args); + try { + if (EntityOperation.SEEN.equals(op.name)) { + // Mark message (un)seen + Message imessage = ifolder.getMessageByUID(op.uid); + if (imessage == null) + throw new MessageRemovedException(); + imessage.setFlag(Flags.Flag.SEEN, jargs.getBoolean(0)); + + } else if (EntityOperation.ADD.equals(op.name)) { + if (!folder.synchronize) { + // Local drafts + Log.w(Helper.TAG, "Folder synchronization disabled"); + return; + } - // Append message - EntityMessage msg = message.getMessage(op.message); - Properties props = MessageHelper.getSessionProperties(); - Session isession = Session.getDefaultInstance(props, null); - MimeMessage imessage = MessageHelper.from(msg, isession); - ifolder.appendMessages(new Message[]{imessage}); + // Append message + EntityMessage msg = message.getMessage(op.message); + Properties props = MessageHelper.getSessionProperties(); + Session isession = Session.getDefaultInstance(props, null); + MimeMessage imessage = MessageHelper.from(msg, isession); + ifolder.appendMessages(new Message[]{imessage}); - // Drafts can be appended multiple times - try { - if (msg.uid != null) { - Message previously = ifolder.getMessageByUID(msg.uid); - previously.setFlag(Flags.Flag.DELETED, true); - ifolder.expunge(); + // Drafts can be appended multiple times + try { + if (msg.uid != null) { + Message previously = ifolder.getMessageByUID(msg.uid); + previously.setFlag(Flags.Flag.DELETED, true); + ifolder.expunge(); + } + } finally { + // Remote will report appended + message.deleteMessage(op.message); } - } finally { - // Remote will report appended + + } else if (EntityOperation.MOVE.equals(op.name)) { + // Move message + EntityFolder archive = db.folder().getFolder(jargs.getLong(0)); + Message imessage = ifolder.getMessageByUID(op.uid); + Folder target = istore.getFolder(archive.name); + ifolder.moveMessages(new Message[]{imessage}, target); + message.deleteMessage(op.message); - } - } else if (EntityOperation.MOVE.equals(op.name)) { - // Move message - EntityFolder archive = db.folder().getFolder(jargs.getLong(0)); - Message imessage = ifolder.getMessageByUID(op.uid); - Folder target = istore.getFolder(archive.name); - ifolder.moveMessages(new Message[]{imessage}, target); - - message.deleteMessage(op.message); - - } else if (EntityOperation.DELETE.equals(op.name)) { - // Delete message - Message imessage = ifolder.getMessageByUID(op.uid); - if (imessage == null) - throw new MessageRemovedException(); - imessage.setFlag(Flags.Flag.DELETED, true); - ifolder.expunge(); - - message.deleteMessage(op.message); - - } else if (EntityOperation.SEND.equals(op.name)) { - // Send message - EntityMessage msg = message.getMessage(op.message); - EntityMessage reply = (msg.replying == null ? null : message.getMessage(msg.replying)); - EntityIdentity ident = db.identity().getIdentity(msg.identity); - - if (!ident.synchronize) { - // Message will remain in outbox - return; - } + } else if (EntityOperation.DELETE.equals(op.name)) { + // Delete message + Message imessage = ifolder.getMessageByUID(op.uid); + if (imessage == null) + throw new MessageRemovedException(); + imessage.setFlag(Flags.Flag.DELETED, true); + ifolder.expunge(); - Properties props = MessageHelper.getSessionProperties(); - Session isession = Session.getDefaultInstance(props, null); + message.deleteMessage(op.message); - MimeMessage imessage; - if (reply == null) - imessage = MessageHelper.from(msg, isession); - else - imessage = MessageHelper.from(msg, reply, isession); - if (ident.replyto != null) - imessage.setReplyTo(new Address[]{new InternetAddress(ident.replyto)}); + } else if (EntityOperation.SEND.equals(op.name)) { + // Send message + EntityMessage msg = message.getMessage(op.message); + EntityMessage reply = (msg.replying == null ? null : message.getMessage(msg.replying)); + EntityIdentity ident = db.identity().getIdentity(msg.identity); - Transport itransport = isession.getTransport(ident.starttls ? "smtp" : "smtps"); - try { - itransport.connect(ident.host, ident.port, ident.user, ident.password); + if (!ident.synchronize) { + // Message will remain in outbox + return; + } - Address[] to = imessage.getAllRecipients(); - itransport.sendMessage(imessage, to); - Log.i(Helper.TAG, "Sent via " + ident.host + "/" + ident.user + - " to " + TextUtils.join(", ", to)); + Properties props = MessageHelper.getSessionProperties(); + Session isession = Session.getDefaultInstance(props, null); - // Make sure the message is sent only once - operation.deleteOperation(op.id); - message.deleteMessage(op.message); - } finally { - itransport.close(); - } + MimeMessage imessage; + if (reply == null) + imessage = MessageHelper.from(msg, isession); + else + imessage = MessageHelper.from(msg, reply, isession); + if (ident.replyto != null) + imessage.setReplyTo(new Address[]{new InternetAddress(ident.replyto)}); - } else - throw new MessagingException("Unknown operation name=" + op.name); + Transport itransport = isession.getTransport(ident.starttls ? "smtp" : "smtps"); + try { + itransport.connect(ident.host, ident.port, ident.user, ident.password); + + Address[] to = imessage.getAllRecipients(); + itransport.sendMessage(imessage, to); + Log.i(Helper.TAG, "Sent via " + ident.host + "/" + ident.user + + " to " + TextUtils.join(", ", to)); + + // Make sure the message is sent only once + operation.deleteOperation(op.id); + message.deleteMessage(op.message); + } finally { + itransport.close(); + } - // Operation succeeded - operation.deleteOperation(op.id); + } else if (EntityOperation.ATTACHMENT.equals(op.name)) { + int sequence = jargs.getInt(0); + EntityAttachment attachment = db.attachment().getAttachment(op.message, sequence); - } catch (MessageRemovedException ex) { - Log.w(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + Message imessage = ifolder.getMessageByUID(op.uid); + if (imessage == null) + throw new MessageRemovedException(); + + Properties props = MessageHelper.getSessionProperties(); + Session isession = Session.getDefaultInstance(props, null); + + MessageHelper helper = new MessageHelper((MimeMessage) imessage); + EntityAttachment a = helper.getAttachments().get(sequence - 1); + + InputStream is = a.part.getInputStream(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; + for (int len = is.read(buffer); len != -1; len = is.read(buffer)) + os.write(buffer, 0, len); - // There is no use in repeating - operation.deleteOperation(op.id); + attachment.content = os.toByteArray(); + db.attachment().updateAttachment(attachment); + Log.i(Helper.TAG, "Downloaded bytes=" + attachment.content.length); + + } else + throw new MessagingException("Unknown operation name=" + op.name); + + // Operation succeeded + operation.deleteOperation(op.id); + + } catch (MessageRemovedException ex) { + Log.w(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + + // There is no use in repeating + operation.deleteOperation(op.id); + } + } finally { + Log.i(Helper.TAG, folder.name + " end op=" + op.id + "/" + op.name); } - } } finally { Log.i(Helper.TAG, folder.name + " end process"); } diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_black_18.png b/app/src/main/res/drawable-hdpi/baseline_get_app_black_18.png new file mode 100755 index 0000000000..91f1ec8698 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_black_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_black_24.png b/app/src/main/res/drawable-hdpi/baseline_get_app_black_24.png new file mode 100755 index 0000000000..d94bd3f784 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_black_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_black_36.png b/app/src/main/res/drawable-hdpi/baseline_get_app_black_36.png new file mode 100755 index 0000000000..bd44e03686 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_black_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_black_48.png b/app/src/main/res/drawable-hdpi/baseline_get_app_black_48.png new file mode 100755 index 0000000000..481f7309ab Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_black_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_white_18.png b/app/src/main/res/drawable-hdpi/baseline_get_app_white_18.png new file mode 100755 index 0000000000..e87c43db6a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_white_24.png b/app/src/main/res/drawable-hdpi/baseline_get_app_white_24.png new file mode 100755 index 0000000000..b6874a6013 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_white_36.png b/app/src/main/res/drawable-hdpi/baseline_get_app_white_36.png new file mode 100755 index 0000000000..bf2c09e978 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_get_app_white_48.png b/app/src/main/res/drawable-hdpi/baseline_get_app_white_48.png new file mode 100755 index 0000000000..5dc1f63015 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_get_app_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_black_18.png b/app/src/main/res/drawable-mdpi/baseline_get_app_black_18.png new file mode 100755 index 0000000000..043f6f6b71 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_black_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_black_24.png b/app/src/main/res/drawable-mdpi/baseline_get_app_black_24.png new file mode 100755 index 0000000000..0b23150f24 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_black_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_black_36.png b/app/src/main/res/drawable-mdpi/baseline_get_app_black_36.png new file mode 100755 index 0000000000..d94bd3f784 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_black_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_black_48.png b/app/src/main/res/drawable-mdpi/baseline_get_app_black_48.png new file mode 100755 index 0000000000..b96f19e224 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_black_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_white_18.png b/app/src/main/res/drawable-mdpi/baseline_get_app_white_18.png new file mode 100755 index 0000000000..e9a75f2809 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_white_24.png b/app/src/main/res/drawable-mdpi/baseline_get_app_white_24.png new file mode 100755 index 0000000000..ebfc6e9ab2 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_white_36.png b/app/src/main/res/drawable-mdpi/baseline_get_app_white_36.png new file mode 100755 index 0000000000..b6874a6013 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_get_app_white_48.png b/app/src/main/res/drawable-mdpi/baseline_get_app_white_48.png new file mode 100755 index 0000000000..0032a69813 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_get_app_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_black_18.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_18.png new file mode 100755 index 0000000000..d94bd3f784 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_black_24.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_24.png new file mode 100755 index 0000000000..b96f19e224 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_black_36.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_36.png new file mode 100755 index 0000000000..481f7309ab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_black_48.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_48.png new file mode 100755 index 0000000000..1dab5bbcf9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_black_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_18.png new file mode 100755 index 0000000000..b6874a6013 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_24.png new file mode 100755 index 0000000000..0032a69813 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_36.png new file mode 100755 index 0000000000..5dc1f63015 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_get_app_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_48.png new file mode 100755 index 0000000000..221786ba99 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_get_app_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_18.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_18.png new file mode 100755 index 0000000000..bd44e03686 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_24.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_24.png new file mode 100755 index 0000000000..481f7309ab Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_36.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_36.png new file mode 100755 index 0000000000..9ee99ccd7f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_48.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_48.png new file mode 100755 index 0000000000..fad39a14c4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_black_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_18.png new file mode 100755 index 0000000000..bf2c09e978 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_24.png new file mode 100755 index 0000000000..5dc1f63015 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_36.png new file mode 100755 index 0000000000..4e04a30198 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_48.png new file mode 100755 index 0000000000..f9bfb5edba Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_get_app_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_18.png new file mode 100755 index 0000000000..481f7309ab Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_24.png new file mode 100755 index 0000000000..1dab5bbcf9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_36.png new file mode 100755 index 0000000000..fad39a14c4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_48.png new file mode 100755 index 0000000000..1415a59fbe Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_black_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_18.png new file mode 100755 index 0000000000..5dc1f63015 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_24.png new file mode 100755 index 0000000000..221786ba99 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_36.png new file mode 100755 index 0000000000..f9bfb5edba Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_48.png new file mode 100755 index 0000000000..bb66c5d1df Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_get_app_white_48.png differ diff --git a/app/src/main/res/drawable/baseline_get_app_24.xml b/app/src/main/res/drawable/baseline_get_app_24.xml new file mode 100755 index 0000000000..ae14452601 --- /dev/null +++ b/app/src/main/res/drawable/baseline_get_app_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/item_attachment.xml b/app/src/main/res/layout/item_attachment.xml index 6f116ded30..373c1b3265 100644 --- a/app/src/main/res/layout/item_attachment.xml +++ b/app/src/main/res/layout/item_attachment.xml @@ -16,25 +16,38 @@ + + \ No newline at end of file