Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bad85af authored by Selim Cinek's avatar Selim Cinek Committed by Android (Google) Code Review
Browse files

Merge changes I0d79642d,If8756ac8,I29e73897,Ia8c5121a,I533b8f06 into rvc-dev

* changes:
  Indented the conversation action list
  Fixed some issues where conversation badges would not be visible
  Improved the animations of the conversation badges
  Important conversations now also transform into the shelf
  Adapted Shelf algorithm to also use conversation icons
parents b259d151 e027da23
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5817,7 +5817,7 @@ public class Notification implements Parcelable
                        PorterDuff.Mode.SRC_ATOP);

            }
            contentView.setInt(R.id.notification_header, "setOriginalIconColor",
            contentView.setInt(R.id.icon, "setOriginalIconColor",
                    colorable ? color : NotificationHeaderView.NO_COLOR);
        }

+1 −7
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ public class NotificationHeaderView extends ViewGroup {
    private View mMicIcon;
    private View mAppOps;
    private View mAudiblyAlertedIcon;
    private int mIconColor;
    private boolean mExpanded;
    private boolean mShowExpandButtonAtEnd;
    private boolean mShowWorkBadgeAtEnd;
@@ -315,13 +314,8 @@ public class NotificationHeaderView extends ViewGroup {
        updateTouchListener();
    }

    @RemotableViewMethod
    public void setOriginalIconColor(int color) {
        mIconColor = color;
    }

    public int getOriginalIconColor() {
        return mIconColor;
        return mIcon.getOriginalIconColor();
    }

    public int getOriginalNotificationColor() {
+47 −2
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ public class CachingIconView extends ImageView {
    private boolean mForceHidden;
    private int mDesiredVisibility;
    private Consumer<Integer> mOnVisibilityChangedListener;
    private Consumer<Boolean> mOnForceHiddenChangedListener;
    private int mIconColor;
    private boolean mWillBeForceHidden;

    @UnsupportedAppUsage
    public CachingIconView(Context context, @Nullable AttributeSet attrs) {
@@ -184,10 +187,18 @@ public class CachingIconView extends ImageView {

    /**
     * Set the icon to be forcibly hidden, even when it's visibility is changed to visible.
     * This is necessary since we still want to keep certain views hidden when their visibility
     * is modified from other sources like the shelf.
     */
    public void setForceHidden(boolean forceHidden) {
        if (forceHidden != mForceHidden) {
            mForceHidden = forceHidden;
            mWillBeForceHidden = false;
            updateVisibility();
            if (mOnForceHiddenChangedListener != null) {
                mOnForceHiddenChangedListener.accept(forceHidden);
            }
        }
    }

    @Override
@@ -209,4 +220,38 @@ public class CachingIconView extends ImageView {
    public void setOnVisibilityChangedListener(Consumer<Integer> listener) {
        mOnVisibilityChangedListener = listener;
    }

    public void setOnForceHiddenChangedListener(Consumer<Boolean> listener) {
        mOnForceHiddenChangedListener = listener;
    }


    public boolean isForceHidden() {
        return mForceHidden;
    }

    @RemotableViewMethod
    public void setOriginalIconColor(int color) {
        mIconColor = color;
    }

    public int getOriginalIconColor() {
        return mIconColor;
    }

    /**
     * @return if the view will be forceHidden after an animation
     */
    public boolean willBeForceHidden() {
        return mWillBeForceHidden;
    }

    /**
     * Set that this view will be force hidden after an animation
     *
     * @param forceHidden if it will be forcehidden
     */
    public void setWillBeForceHidden(boolean forceHidden) {
        mWillBeForceHidden = forceHidden;
    }
}
+98 −7
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.internal.widget;

import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_EXTERNAL;
import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE;
import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_IN;
import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_OUT;

import android.annotation.AttrRes;
import android.annotation.NonNull;
@@ -106,7 +108,7 @@ public class ConversationLayout extends FrameLayout
    private CharSequence mNameReplacement;
    private boolean mIsCollapsed;
    private ImageResolver mImageResolver;
    private ImageView mConversationIcon;
    private CachingIconView mConversationIcon;
    private View mConversationIconContainer;
    private int mConversationIconTopPadding;
    private int mConversationIconTopPaddingExpandedGroup;
@@ -114,7 +116,7 @@ public class ConversationLayout extends FrameLayout
    private int mExpandedGroupMessagePaddingNoAppName;
    private TextView mConversationText;
    private View mConversationIconBadge;
    private ImageView mConversationIconBadgeBg;
    private CachingIconView mConversationIconBadgeBg;
    private Icon mLargeIcon;
    private View mExpandButtonContainer;
    private ViewGroup mExpandButtonAndContentContainer;
@@ -125,7 +127,7 @@ public class ConversationLayout extends FrameLayout
    private int mConversationAvatarSize;
    private int mConversationAvatarSizeExpanded;
    private CachingIconView mIcon;
    private View mImportanceRingView;
    private CachingIconView mImportanceRingView;
    private int mExpandedGroupSideMargin;
    private int mExpandedGroupSideMarginFacePile;
    private View mConversationFacePile;
@@ -140,11 +142,15 @@ public class ConversationLayout extends FrameLayout
    private int mContentMarginEnd;
    private Rect mMessagingClipRect;
    private ObservableTextView mAppName;
    private ViewGroup mActions;
    private int mConversationContentStart;
    private int mInternalButtonPadding;
    private boolean mAppNameGone;
    private int mFacePileAvatarSize;
    private int mFacePileAvatarSizeExpandedGroup;
    private int mFacePileProtectionWidth;
    private int mFacePileProtectionWidthExpanded;
    private boolean mImportantConversation;

    public ConversationLayout(@NonNull Context context) {
        super(context);
@@ -168,6 +174,7 @@ public class ConversationLayout extends FrameLayout
    protected void onFinishInflate() {
        super.onFinishInflate();
        mMessagingLinearLayout = findViewById(R.id.notification_messaging);
        mActions = findViewById(R.id.actions);
        mMessagingLinearLayout.setMessagingLayout(this);
        mImageMessageContainer = findViewById(R.id.conversation_image_message_container);
        // We still want to clip, but only on the top, since views can temporarily out of bounds
@@ -186,9 +193,41 @@ public class ConversationLayout extends FrameLayout
        mConversationIconBadge = findViewById(R.id.conversation_icon_badge);
        mConversationIconBadgeBg = findViewById(R.id.conversation_icon_badge_bg);
        mIcon.setOnVisibilityChangedListener((visibility) -> {
            // Always keep the badge visibility in sync with the icon. This is necessary in cases

            // Let's hide the background directly or in an animated way
            boolean isGone = visibility == GONE;
            int oldVisibility = mConversationIconBadgeBg.getVisibility();
            boolean wasGone = oldVisibility == GONE;
            if (wasGone != isGone) {
                // Keep the badge gone state in sync with the icon. This is necessary in cases
                // Where the icon is being hidden externally like in group children.
                mConversationIconBadgeBg.animate().cancel();
                mConversationIconBadgeBg.setVisibility(visibility);
            }

            // Let's handle the importance ring which can also be be gone normally
            oldVisibility = mImportanceRingView.getVisibility();
            wasGone = oldVisibility == GONE;
            visibility = !mImportantConversation ? GONE : visibility;
            isGone = visibility == GONE;
            if (wasGone != isGone) {
                // Keep the badge visibility in sync with the icon. This is necessary in cases
                // Where the icon is being hidden externally like in group children.
            mConversationIconBadge.setVisibility(visibility);
                mImportanceRingView.animate().cancel();
                mImportanceRingView.setVisibility(visibility);
            }
        });
        // When the small icon is gone, hide the rest of the badge
        mIcon.setOnForceHiddenChangedListener((forceHidden) -> {
            animateViewForceHidden(mConversationIconBadgeBg, forceHidden);
            animateViewForceHidden(mImportanceRingView, forceHidden);
        });

        // When the conversation icon is gone, hide the whole badge
        mConversationIcon.setOnForceHiddenChangedListener((forceHidden) -> {
            animateViewForceHidden(mConversationIconBadgeBg, forceHidden);
            animateViewForceHidden(mImportanceRingView, forceHidden);
            animateViewForceHidden(mIcon, forceHidden);
        });
        mConversationText = findViewById(R.id.conversation_text);
        mExpandButtonContainer = findViewById(R.id.expand_button_container);
@@ -238,6 +277,33 @@ public class ConversationLayout extends FrameLayout
        mAppName.setOnVisibilityChangedListener((visibility) -> {
            onAppNameVisibilityChanged();
        });
        mConversationContentStart = getResources().getDimensionPixelSize(
                R.dimen.conversation_content_start);
        mInternalButtonPadding
                = getResources().getDimensionPixelSize(R.dimen.button_padding_horizontal_material)
                + getResources().getDimensionPixelSize(R.dimen.button_inset_horizontal_material);
    }

    private void animateViewForceHidden(CachingIconView view, boolean forceHidden) {
        boolean nowForceHidden = view.willBeForceHidden() || view.isForceHidden();
        if (forceHidden == nowForceHidden) {
            // We are either already forceHidden or will be
            return;
        }
        view.animate().cancel();
        view.setWillBeForceHidden(forceHidden);
        view.animate()
                .scaleX(forceHidden ? 0.5f : 1.0f)
                .scaleY(forceHidden ? 0.5f : 1.0f)
                .alpha(forceHidden ? 0.0f : 1.0f)
                .setInterpolator(forceHidden ? ALPHA_OUT : ALPHA_IN)
                .setDuration(160);
        if (view.getVisibility() != VISIBLE) {
            view.setForceHidden(forceHidden);
        } else {
            view.animate().withEndAction(() -> view.setForceHidden(forceHidden));
        }
        view.animate().start();
    }

    @RemotableViewMethod
@@ -255,9 +321,14 @@ public class ConversationLayout extends FrameLayout
     */
    @RemotableViewMethod
    public void setIsImportantConversation(boolean isImportantConversation) {
        mImportantConversation = isImportantConversation;
        mImportanceRingView.setVisibility(isImportantConversation ? VISIBLE : GONE);
    }

    public boolean isImportantConversation() {
        return mImportantConversation;
    }

    /**
     * Set this layout to show the collapsed representation.
     *
@@ -363,7 +434,6 @@ public class ConversationLayout extends FrameLayout
    private void updateConversationLayout() {
        // Set avatar and name
        CharSequence conversationText = mConversationTitle;
        // TODO: display the secondary text somewhere
        if (mIsOneToOne) {
            // Let's resolve the icon / text from the last sender
            mConversationIcon.setVisibility(VISIBLE);
@@ -418,6 +488,27 @@ public class ConversationLayout extends FrameLayout
        updateIconPositionAndSize();
        updateImageMessages();
        updatePaddingsBasedOnContentAvailability();
        updateActionListPadding();
    }

    private void updateActionListPadding() {
        if (mActions == null) {
            return;
        }
        View firstAction = mActions.getChildAt(0);
        if (firstAction != null) {
            // Let's visually position the first action where the content starts
            int paddingStart = mConversationContentStart;

            MarginLayoutParams layoutParams = (MarginLayoutParams) firstAction.getLayoutParams();
            paddingStart -= layoutParams.getMarginStart();
            paddingStart -= mInternalButtonPadding;

            mActions.setPaddingRelative(paddingStart,
                    mActions.getPaddingTop(),
                    mActions.getPaddingEnd(),
                    mActions.getPaddingBottom());
        }
    }

    private void updateImageMessages() {
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import com.android.internal.R;
 */
public class MessagingPropertyAnimator implements View.OnLayoutChangeListener {
    private static final long APPEAR_ANIMATION_LENGTH = 210;
    private static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
    private static final int TAG_TOP_ANIMATOR = R.id.tag_top_animator;
    private static final int TAG_TOP = R.id.tag_top_override;
Loading