diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java
index 9279f808b6..eac0b03a39 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java
@@ -114,6 +114,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
+import org.thoughtcrime.securesms.util.views.AdaptiveActionsToolbar;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
@@ -1211,6 +1212,7 @@ public class ConversationFragment extends Fragment
}
setCorrectMenuVisibility(menu);
+ AdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth());
listener.onMessageActionToolbarOpened();
return true;
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java
index ba99406018..3782dc3f0e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java
@@ -29,6 +29,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
+
+import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -203,6 +205,14 @@ public class ViewUtil {
return Math.round(dp * Resources.getSystem().getDisplayMetrics().density);
}
+ public static int dpToSp(int dp) {
+ return (int) (dpToPx(dp) / Resources.getSystem().getDisplayMetrics().scaledDensity);
+ }
+
+ public static int spToPx(float sp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, Resources.getSystem().getDisplayMetrics());
+ }
+
public static void updateLayoutParams(@NonNull View view, int width, int height) {
view.getLayoutParams().width = width;
view.getLayoutParams().height = height;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/views/AdaptiveActionsToolbar.java b/app/src/main/java/org/thoughtcrime/securesms/util/views/AdaptiveActionsToolbar.java
new file mode 100644
index 0000000000..bf6e28239b
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/views/AdaptiveActionsToolbar.java
@@ -0,0 +1,86 @@
+package org.thoughtcrime.securesms.util.views;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.Toolbar;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.util.ViewUtil;
+
+/**
+ * AdaptiveActionsToolbar behaves like a normal {@link Toolbar} except in that it ignores the
+ * showAsAlways attributes of menu items added via menu inflation, opting for an adaptive algorithm
+ * instead. This algorithm will display as many icons as it can up to a specific percentage of the
+ * screen.
+ *
+ * Each ActionView icon is expected to occupy 48dp of space, including padding. Items are stacked one
+ * after the next with no margins.
+ *
+ * This view can be customized via attributes:
+ *
+ * aat_max_shown -- controls the max number of items to display.
+ * aat_percent_for_actions -- controls the max percent of screen width the buttons can occupy.
+ */
+public class AdaptiveActionsToolbar extends Toolbar {
+
+ private static final int NAVIGATION_SP = 48;
+ private static final int ACTION_VIEW_WIDTH_SP = 42;
+ private static final int OVERFLOW_VIEW_WIDTH_SP = 35;
+
+ private int maxShown;
+
+ public AdaptiveActionsToolbar(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public AdaptiveActionsToolbar(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, R.attr.toolbarStyle);
+ }
+
+ public AdaptiveActionsToolbar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.AdaptiveActionsToolbar);
+
+ maxShown = array.getInteger(R.styleable.AdaptiveActionsToolbar_aat_max_shown, 100);
+
+ array.recycle();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ adjustMenuActions(getMenu(), maxShown, getMeasuredWidth());
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ public static void adjustMenuActions(@NonNull Menu menu, int maxToShow, int toolbarWidthPx) {
+ int menuSize = menu.size();
+
+ int widthAllowed = toolbarWidthPx - ViewUtil.spToPx(NAVIGATION_SP);
+ int nItemsToShow = Math.min(maxToShow, Math.round(widthAllowed / ViewUtil.spToPx(ACTION_VIEW_WIDTH_SP)));
+
+ if (nItemsToShow < menuSize) {
+ widthAllowed -= ViewUtil.spToPx(OVERFLOW_VIEW_WIDTH_SP);
+ }
+
+ nItemsToShow = Math.min(maxToShow, Math.round(widthAllowed / ViewUtil.spToPx(ACTION_VIEW_WIDTH_SP)));
+
+ for (int i = 0; i < menu.size(); i++) {
+ MenuItem item = menu.getItem(i);
+ if (nItemsToShow > 0) {
+ item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ } else {
+ item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ }
+ nItemsToShow--;
+ }
+ }
+
+}
diff --git a/app/src/main/res/layout/conversation_reaction_long_press_toolbar.xml b/app/src/main/res/layout/conversation_reaction_long_press_toolbar.xml
index fdcfa492cc..e47279075a 100644
--- a/app/src/main/res/layout/conversation_reaction_long_press_toolbar.xml
+++ b/app/src/main/res/layout/conversation_reaction_long_press_toolbar.xml
@@ -1,11 +1,11 @@
-
+ app:menu="@menu/conversation_reactions_long_press_menu"
+ app:navigationIcon="@drawable/ic_x_conversation">
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index a0469f0040..f193692025 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -454,4 +454,8 @@
+
+
+
+