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

Commit 9272fd2f authored by Evan Laird's avatar Evan Laird
Browse files

Expose notification guts on menu shown

This change adds a few methods to NotificationMenuRowPlugin so that a
menu row can tell the stack scroller to expose the notification guts
when the menu is fully exposed.

TODO: fix the menu close animation so it happens after the guts open,
and if you close the guts by swiping you can trigger a flicker.

Also there are some things to make lint happy and lots of null checks.

Bug: 127998765
Test: swipe RTL on any notification
Change-Id: I46f7c7dc90032a1914f7b5513bc57e089887c722
parent d9246ef1
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -14,7 +14,9 @@

package com.android.systemui.plugins.statusbar;

import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Point;
import android.service.notification.StatusBarNotification;
import android.view.MotionEvent;
import android.view.View;
@@ -84,6 +86,38 @@ public interface NotificationMenuRowPlugin extends Plugin {

    public void setMenuItems(ArrayList<MenuItem> items);

    /**
     * If this returns {@code true}, then the menu row will bind and fade in the notification guts
     * view for the menu item it holds.
     *
     * @see #menuItemToExposeOnSnap()
     * @return whether or not to immediately expose the notification guts
     */
    default boolean shouldShowGutsOnSnapOpen() {
        return false;
    }

    /**
     * When #shouldShowGutsOnExpose is true, this method must return the menu item to expose on
     * #onSnapOpen. Otherwise we will fall back to the default behavior of fading in the menu row
     *
     * @return the {@link MenuItem} containing the NotificationGuts that should be exposed
     */
    @Nullable
    default MenuItem menuItemToExposeOnSnap() {
        return null;
    }

    /**
     * Get the origin for the circular reveal animation when expanding the notification guts. Only
     * used when #shouldShowGutsOnSnapOpen is true
     * @return the x,y coordinates for the start of the animation
     */
    @Nullable
    default Point getRevealAnimationOrigin() {
        return new Point(0, 0);
    }

    public void setMenuClickListener(OnMenuEventListener listener);

    public void setAppName(String appName);
+11 −1
Original line number Diff line number Diff line
@@ -265,8 +265,10 @@ public class SwipeHelper implements Gefingerpoken {
    public boolean onInterceptTouchEvent(final MotionEvent ev) {
        if (mCurrView instanceof ExpandableNotificationRow) {
            NotificationMenuRowPlugin nmr = ((ExpandableNotificationRow) mCurrView).getProvider();
            if (nmr != null) {
                mMenuRowIntercepting = nmr.onInterceptTouchEvent(mCurrView, ev);
            }
        }
        final int action = ev.getAction();

        switch (action) {
@@ -487,6 +489,7 @@ public class SwipeHelper implements Gefingerpoken {
                mSnappingChild = false;
                if (!wasCancelled) {
                    updateSwipeProgressFromOffset(animView, canBeDismissed);
                    onChildSnappedBack(animView, targetLeft);
                    mCallback.onChildSnappedBack(animView, targetLeft);
                }
            }
@@ -499,6 +502,13 @@ public class SwipeHelper implements Gefingerpoken {
        anim.start();
    }

    /**
     * Give the swipe helper itself a chance to do something on snap back so NSSL doesn't have
     * to tell us what to do
     */
    protected void onChildSnappedBack(View animView, float targetLeft) {
    }

    /**
     * Called to update the snap back animation.
     */
+45 −14
Original line number Diff line number Diff line
@@ -1147,10 +1147,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView

    @Override
    public void onPluginConnected(NotificationMenuRowPlugin plugin, Context pluginContext) {
        boolean existed = mMenuRow.getMenuView() != null;
        boolean existed = mMenuRow != null && mMenuRow.getMenuView() != null;
        if (existed) {
            removeView(mMenuRow.getMenuView());
        }
        if (plugin == null) {
            return;
        }
        mMenuRow = plugin;
        if (mMenuRow.shouldUseDefaultMenuItems()) {
            ArrayList<MenuItem> items = new ArrayList<>();
@@ -1173,7 +1176,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        }
    }

    /**
     * Get a handle to a NotificationMenuRowPlugin whose menu view has been added to our hierarchy,
     * or null if there is no menu row
     *
     * @return a {@link NotificationMenuRowPlugin}, or null
     */
    @Nullable
    public NotificationMenuRowPlugin createMenu() {
        if (mMenuRow == null) {
            return null;
        }

        if (mMenuRow.getMenuView() == null) {
            mMenuRow.createMenu(this, mStatusBarNotification);
            mMenuRow.setAppName(mAppName);
@@ -1184,6 +1198,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        return mMenuRow;
    }

    @Nullable
    public NotificationMenuRowPlugin getProvider() {
        return mMenuRow;
    }
@@ -1211,7 +1226,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
            mGuts.setVisibility(oldGuts.getVisibility());
            addView(mGuts, index);
        }
        View oldMenu = mMenuRow.getMenuView();
        View oldMenu = mMenuRow == null ? null : mMenuRow.getMenuView();
        if (oldMenu != null) {
            int menuIndex = indexOfChild(oldMenu);
            removeView(oldMenu);
@@ -1230,7 +1245,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (mMenuRow.getMenuView() != null) {
        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
            mMenuRow.onConfigurationChanged();
        }
    }
@@ -1728,7 +1743,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
    public void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
        mOnAppOpsClickListener = v -> {
            createMenu();
            MenuItem menuItem = getProvider().getAppOpsMenuItem(mContext);
            NotificationMenuRowPlugin provider = getProvider();
            if (provider == null) {
                return;
            }
            MenuItem menuItem = provider.getAppOpsMenuItem(mContext);
            if (menuItem != null) {
                l.onClick(this, v.getWidth() / 2, v.getHeight() / 2, menuItem);
            }
@@ -1790,7 +1809,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView

    public void doLongClickCallback(int x, int y) {
        createMenu();
        MenuItem menuItem = getProvider().getLongpressMenuItem(mContext);
        NotificationMenuRowPlugin provider = getProvider();
        MenuItem menuItem = null;
        if (provider != null) {
            menuItem = provider.getLongpressMenuItem(mContext);
        }
        doLongClickCallback(x, y, menuItem);
    }

@@ -1844,8 +1867,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
            getEntry().expandedIcon.setScrollX(0);
        }

        if (mMenuRow != null) {
            mMenuRow.resetMenu();
        }
    }

    void onGutsOpened() {
        updateContentAccessibilityImportanceForGuts(false /* isEnabled */);
@@ -1921,7 +1946,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
            getEntry().expandedIcon.setScrollX((int) -translationX);
        }

        if (mMenuRow.getMenuView() != null) {
        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
            mMenuRow.onParentTranslationUpdate(translationX);
        }
    }
@@ -1973,7 +1998,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
                    mNotificationTranslationFinished = true;
                }
                if (!cancelled && leftTarget == 0) {
                    if (mMenuRow != null) {
                        mMenuRow.resetMenu();
                    }
                    mTranslateAnim = null;
                }
            }
@@ -1982,7 +2009,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        return translateAnim;
    }

    public void inflateGuts() {
    void ensureGutsInflated() {
        if (mGuts == null) {
            mGutsStub.inflate();
        }
@@ -2438,7 +2465,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        if (intrinsicBefore != getIntrinsicHeight() && intrinsicBefore != 0) {
            notifyHeightChanged(true  /* needsAnimation */);
        }
        if (mMenuRow.getMenuView() != null) {
        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
            mMenuRow.onParentHeightUpdate();
        }
        updateContentShiftHeight();
@@ -2641,7 +2668,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
    public long performRemoveAnimation(long duration, long delay, float translationDirection,
            boolean isHeadsUpAnimation, float endLocation, Runnable onFinishedRunnable,
            AnimatorListenerAdapter animationListener) {
        if (mMenuRow.isMenuVisible()) {
        if (mMenuRow != null && mMenuRow.isMenuVisible()) {
            Animator anim = getTranslateViewAnimator(0f, null /* listener */);
            if (anim != null) {
                anim.addListener(new AnimatorListenerAdapter() {
@@ -2712,7 +2739,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        if (mGuts != null) {
            mGuts.setActualHeight(height);
        }
        if (mMenuRow.getMenuView() != null) {
        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
            mMenuRow.onParentHeightUpdate();
        }
    }
@@ -2977,8 +3004,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
            default:
                if (action == R.id.action_snooze) {
                    NotificationMenuRowPlugin provider = getProvider();
                    if (provider == null) {
                    if (provider == null && mMenuRow != null) {
                        provider = createMenu();
                    } else {
                        return false;
                    }
                    MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
                    if (snoozeMenu != null) {
@@ -3109,8 +3138,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView

    /** Sets whether dismiss gestures are right-to-left (instead of left-to-right). */
    public void setDismissRtl(boolean dismissRtl) {
        if (mMenuRow != null) {
            mMenuRow.setDismissRtl(dismissRtl);
        }
    }

    private static class NotificationViewState extends ExpandableViewState {

+3 −1
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ public class NotificationGuts extends FrameLayout {
        public void onHeightChanged(NotificationGuts guts);
    }

    interface OnSettingsClickListener {
    private interface OnSettingsClickListener {
        void onClick(View v, int appUid);
    }

@@ -271,6 +271,8 @@ public class NotificationGuts extends FrameLayout {
                double horz = Math.max(getWidth() - x, x);
                double vert = Math.max(getHeight() - y, y);
                float r = (float) Math.hypot(horz, vert);
                // Make sure we'll be visible after the circular reveal
                setAlpha(1f);
                // Circular reveal originating at (x, y)
                Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+3 −3
Original line number Diff line number Diff line
@@ -165,8 +165,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
        }
    }

    public boolean bindGuts(final ExpandableNotificationRow row) {
        row.inflateGuts();
    private boolean bindGuts(final ExpandableNotificationRow row) {
        row.ensureGutsInflated();
        return bindGuts(row, mGutsMenuItem);
    }

@@ -387,7 +387,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
            return false;
        }

        row.inflateGuts();
        row.ensureGutsInflated();
        NotificationGuts guts = row.getGuts();
        mNotificationGutsExposed = guts;
        if (!bindGuts(row, menuItem)) {
Loading