add setting to disable avatars on message bubbles

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/AppSettings.java                                           |  8 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java                             | 55 
src/main/java/eu/siacs/conversations/ui/fragment/settings/InterfaceBubblesSettingsFragment.java | 19 
src/main/res/drawable/ic_account_circle_24dp.xml                                                | 12 
src/main/res/drawable/ic_colors_24dp.xml                                                        | 10 
src/main/res/layout/item_message_received.xml                                                   |  2 
src/main/res/layout/item_message_sent.xml                                                       |  4 
src/main/res/values/defaults.xml                                                                |  1 
src/main/res/values/dimens.xml                                                                  |  3 
src/main/res/values/strings.xml                                                                 |  5 
src/main/res/xml/preferences_interface.xml                                                      | 15 
src/main/res/xml/preferences_interface_bubbles.xml                                              | 21 
12 files changed, 131 insertions(+), 24 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/AppSettings.java πŸ”—

@@ -3,13 +3,10 @@ package eu.siacs.conversations;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.net.Uri;
-
 import androidx.annotation.BoolRes;
 import androidx.annotation.NonNull;
 import androidx.preference.PreferenceManager;
-
 import com.google.common.base.Strings;
-
 import java.security.SecureRandom;
 
 public class AppSettings {
@@ -45,6 +42,7 @@ public class AppSettings {
     public static final String SEND_CRASH_REPORTS = "send_crash_reports";
     public static final String COLORFUL_CHAT_BUBBLES = "use_green_background";
     public static final String LARGE_FONT = "large_font";
+    public static final String SHOW_AVATARS = "show_avatars";
 
     private static final String ACCEPT_INVITES_FROM_STRANGERS = "accept_invites_from_strangers";
     private static final String INSTALLATION_ID = "im.conversations.android.install_id";
@@ -108,6 +106,10 @@ public class AppSettings {
         return getBooleanPreference(LARGE_FONT, R.bool.large_font);
     }
 
+    public boolean isShowAvatars() {
+        return getBooleanPreference(SHOW_AVATARS, R.bool.show_avatars);
+    }
+
     public boolean isUseTor() {
         return getBooleanPreference(USE_TOR, R.bool.use_tor);
     }

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java πŸ”—

@@ -101,7 +101,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
     private final DisplayMetrics metrics;
     private OnContactPictureClicked mOnContactPictureClickedListener;
     private OnContactPictureLongClicked mOnContactPictureLongClickedListener;
-    private BubbleDesign bubbleDesign = new BubbleDesign(false, false);
+    private BubbleDesign bubbleDesign = new BubbleDesign(false, false, true);
     private final boolean mForceNames;
 
     public MessageAdapter(
@@ -722,6 +722,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
         }
     }
 
+    @NonNull
     @Override
     public View getView(final int position, View view, final @NonNull ViewGroup parent) {
         final Message message = getItem(position);
@@ -923,11 +924,21 @@ public class MessageAdapter extends ArrayAdapter<Message> {
             // sent and received bubbles
             final var mergeIntoTop = mergeIntoTop(position, message);
             final var mergeIntoBottom = mergeIntoBottom(position, message);
-            final var requiresAvatar = type == SENT ? !mergeIntoBottom : !mergeIntoTop;
+            final var showAvatar =
+                    bubbleDesign.showAvatars
+                            || (type == RECEIVED
+                                    && message.getConversation().getMode()
+                                            == Conversation.MODE_MULTI);
             setBubblePadding(viewHolder.root, mergeIntoTop, mergeIntoBottom);
-            setRequiresAvatar(viewHolder, requiresAvatar);
+            if (showAvatar) {
+                final var requiresAvatar = type == SENT ? !mergeIntoBottom : !mergeIntoTop;
+                setRequiresAvatar(viewHolder, requiresAvatar);
+                AvatarWorkerTask.loadAvatar(message, viewHolder.contact_picture, R.dimen.avatar);
+            } else {
+                viewHolder.contact_picture.setVisibility(View.GONE);
+            }
+            setAvatarDistance(viewHolder.message_box, type, showAvatar);
             viewHolder.message_box.setClipToOutline(true);
-            AvatarWorkerTask.loadAvatar(message, viewHolder.contact_picture, R.dimen.avatar);
         }
 
         resetClickListener(viewHolder.message_box, viewHolder.messageBody);
@@ -1084,6 +1095,30 @@ public class MessageAdapter extends ArrayAdapter<Message> {
         return view;
     }
 
+    private void setAvatarDistance(
+            final LinearLayout messageBox, final int type, final boolean showAvatar) {
+        final ViewGroup.MarginLayoutParams layoutParams =
+                (ViewGroup.MarginLayoutParams) messageBox.getLayoutParams();
+        if (showAvatar) {
+            final var resources = messageBox.getResources();
+            if (type == RECEIVED) {
+                layoutParams.setMarginStart(
+                        resources.getDimensionPixelSize(R.dimen.bubble_avatar_distance));
+                layoutParams.setMarginEnd(0);
+            } else if (type == SENT) {
+                layoutParams.setMarginStart(0);
+                layoutParams.setMarginEnd(
+                        resources.getDimensionPixelSize(R.dimen.bubble_avatar_distance));
+            } else {
+                throw new AssertionError("Avatar distances are not available on this view type");
+            }
+        } else {
+            layoutParams.setMarginStart(0);
+            layoutParams.setMarginEnd(0);
+        }
+        messageBox.setLayoutParams(layoutParams);
+    }
+
     private void setBubblePadding(
             final ConstraintLayout root,
             final boolean mergeIntoTop,
@@ -1254,7 +1289,10 @@ public class MessageAdapter extends ArrayAdapter<Message> {
     public void updatePreferences() {
         final AppSettings appSettings = new AppSettings(activity);
         this.bubbleDesign =
-                new BubbleDesign(appSettings.isColorfulChatBubbles(), appSettings.isLargeFont());
+                new BubbleDesign(
+                        appSettings.isColorfulChatBubbles(),
+                        appSettings.isLargeFont(),
+                        appSettings.isShowAvatars());
     }
 
     public void setHighlightedTerm(List<String> terms) {
@@ -1375,10 +1413,15 @@ public class MessageAdapter extends ArrayAdapter<Message> {
     private static class BubbleDesign {
         public final boolean colorfulChatBubbles;
         public final boolean largeFont;
+        public final boolean showAvatars;
 
-        private BubbleDesign(final boolean colorfulChatBubbles, final boolean largeFont) {
+        private BubbleDesign(
+                final boolean colorfulChatBubbles,
+                final boolean largeFont,
+                final boolean showAvatars) {
             this.colorfulChatBubbles = colorfulChatBubbles;
             this.largeFont = largeFont;
+            this.showAvatars = showAvatars;
         }
     }
 

src/main/java/eu/siacs/conversations/ui/fragment/settings/InterfaceBubblesSettingsFragment.java πŸ”—

@@ -0,0 +1,19 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import eu.siacs.conversations.R;
+
+public class InterfaceBubblesSettingsFragment extends XmppPreferenceFragment {
+
+    @Override
+    public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+        setPreferencesFromResource(R.xml.preferences_interface_bubbles, rootKey);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        requireActivity().setTitle(R.string.pref_title_bubbles);
+    }
+}

src/main/res/drawable/ic_account_circle_24dp.xml πŸ”—

@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="?colorControlNormal"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,6c1.93,0 3.5,1.57 3.5,3.5S13.93,13 12,13s-3.5,-1.57 -3.5,-3.5S10.07,6 12,6zM12,20c-2.03,0 -4.43,-0.82 -6.14,-2.88C7.55,15.8 9.68,15 12,15s4.45,0.8 6.14,2.12C16.43,19.18 14.03,20 12,20z" />
+
+</vector>

src/main/res/drawable/ic_colors_24dp.xml πŸ”—

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="?attr/colorControlNormal"
+    android:viewportWidth="960"
+    android:viewportHeight="960">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M346,820L100,574Q90,564 85,552Q80,540 80,527Q80,514 85,502Q90,490 100,480L330,251L224,145L286,80L686,480Q696,490 700.5,502Q705,514 705,527Q705,540 700.5,552Q696,564 686,574L440,820Q430,830 418,835Q406,840 393,840Q380,840 368,835Q356,830 346,820ZM393,314L179,528Q179,528 179,528Q179,528 179,528L607,528Q607,528 607,528Q607,528 607,528L393,314ZM792,840Q756,840 731,814.5Q706,789 706,752Q706,725 719.5,701Q733,677 750,654L792,600L836,654Q852,677 866,701Q880,725 880,752Q880,789 854,814.5Q828,840 792,840Z" />
+</vector>

src/main/res/layout/item_message_received.xml πŸ”—

@@ -23,7 +23,7 @@
             android:id="@+id/message_box"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginStart="6dp"
+            android:layout_marginStart="@dimen/bubble_avatar_distance"
             android:background="@drawable/background_message_bubble"
             android:backgroundTint="?colorTertiaryContainer"
             android:longClickable="true"

src/main/res/layout/item_message_sent.xml πŸ”—

@@ -15,14 +15,14 @@
             android:scaleType="fitXY"
             app:layout_constraintBottom_toBottomOf="@id/message_box"
             app:layout_constraintEnd_toEndOf="parent"
-            app:riv_corner_radius="8dp" />
+            app:riv_corner_radius="8dp"/>
 
 
         <LinearLayout
             android:id="@+id/message_box"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginEnd="6dp"
+            android:layout_marginEnd="@dimen/bubble_avatar_distance"
             android:background="@drawable/background_message_bubble"
             android:backgroundTint="?colorSecondaryContainer"
             android:longClickable="true"

src/main/res/values/defaults.xml πŸ”—

@@ -19,6 +19,7 @@
     <string name="picture_compression">auto</string>
     <bool name="use_green_background">true</bool>
     <bool name="large_font">false</bool>
+    <bool name="show_avatars">true</bool>
     <string name="quick_action">recent</string>
     <bool name="show_dynamic_tags">false</bool>
     <bool name="btbv">true</bool>

src/main/res/values/dimens.xml πŸ”—

@@ -47,4 +47,5 @@
     <dimen name="bubble_vertical_padding">4dp</dimen>
     <dimen name="bubble_vertical_padding_minimum">1dp</dimen>
     <dimen name="bubble_avatar_size">48dp</dimen>
-</resources>
+    <dimen name="bubble_avatar_distance">6dp</dimen>
+</resources>

src/main/res/values/strings.xml πŸ”—

@@ -1088,4 +1088,9 @@
     <string name="more_reactions">More reactions</string>
     <string name="could_not_modify_call">Could not modify call</string>
     <string name="clients_may_not_support_av">Your contact’s XMPP client might not support audio/video calls.</string>
+    <string name="pref_show_avatars">Show avatars</string>
+    <string name="pref_show_avatars_summary">Display avatars for your messages and in 1:1 chats, in addition to group chats.</string>
+    <string name="pref_chat_bubbles">Chat bubbles</string>
+    <string name="pref_chat_bubbles_summary">Background color, Font size, Avatars</string>
+    <string name="pref_title_bubbles">Chat Bubbles</string>
 </resources>

src/main/res/xml/preferences_interface.xml πŸ”—

@@ -15,18 +15,11 @@
             android:key="theme"
             android:title="@string/pref_light_dark_mode"
             app:useSimpleSummaryProvider="true" />
-        <SwitchPreferenceCompat
-            android:defaultValue="@bool/use_green_background"
+        <Preference
             android:icon="@drawable/ic_forum_24dp"
-            android:key="use_green_background"
-            android:summary="@string/pref_use_colorful_bubbles_summary"
-            android:title="@string/pref_use_colorful_bubbles" />
-        <SwitchPreferenceCompat
-            android:defaultValue="@bool/large_font"
-            android:icon="@drawable/ic_format_size_24dp"
-            android:key="large_font"
-            android:summary="@string/pref_large_font_summary"
-            android:title="@string/pref_large_font" />
+            app:fragment="eu.siacs.conversations.ui.fragment.settings.InterfaceBubblesSettingsFragment"
+            app:summary="@string/pref_chat_bubbles_summary"
+            app:title="@string/pref_chat_bubbles" />
         <SwitchPreferenceCompat
             android:defaultValue="@bool/show_dynamic_tags"
             android:icon="@drawable/ic_label_24dp"

src/main/res/xml/preferences_interface_bubbles.xml πŸ”—

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <SwitchPreferenceCompat
+        android:defaultValue="@bool/use_green_background"
+        android:icon="@drawable/ic_colors_24dp"
+        android:key="use_green_background"
+        android:summary="@string/pref_use_colorful_bubbles_summary"
+        android:title="@string/pref_use_colorful_bubbles" />
+    <SwitchPreferenceCompat
+        android:defaultValue="@bool/show_avatars"
+        android:icon="@drawable/ic_account_circle_24dp"
+        android:key="show_avatars"
+        android:summary="@string/pref_show_avatars_summary"
+        android:title="@string/pref_show_avatars" />
+    <SwitchPreferenceCompat
+        android:defaultValue="@bool/large_font"
+        android:icon="@drawable/ic_format_size_24dp"
+        android:key="large_font"
+        android:summary="@string/pref_large_font_summary"
+        android:title="@string/pref_large_font" />
+</PreferenceScreen>