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

Commit 67b28ff3 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Magnetic Swipe Refactor to better handle edge cases." into main

parents 436c93d6 ce9d014a
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
    private val sectionsManager = mock<NotificationSectionsManager>()
    private val msdlPlayer = kosmos.fakeMSDLPlayer
    private var canRowBeDismissed = true
    private var magneticAnimationsCancelled = false

    private val underTest = kosmos.magneticNotificationRowManagerImpl

@@ -64,6 +65,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
        children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
        swipedRow = children.attachedChildren[childrenNumber / 2]
        configureMagneticRowListener(swipedRow)
        magneticAnimationsCancelled = false
    }

    @Test
@@ -247,6 +249,35 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            assertThat(underTest.currentState).isEqualTo(State.IDLE)
        }

    @Test
    fun onMagneticInteractionEnd_whenDetached_cancelsMagneticAnimations() =
        kosmos.testScope.runTest {
            // GIVEN the swiped row is detached
            setDetachedState()

            // WHEN the interaction ends on the row
            underTest.onMagneticInteractionEnd(swipedRow, velocity = null)

            // THEN magnetic animations are cancelled
            assertThat(magneticAnimationsCancelled).isTrue()
        }

    @Test
    fun onMagneticInteractionEnd_forMagneticNeighbor_cancelsMagneticAnimations() =
        kosmos.testScope.runTest {
            val neighborRow = children.attachedChildren[childrenNumber / 2 - 1]
            configureMagneticRowListener(neighborRow)

            // GIVEN that targets are set
            setTargets()

            // WHEN the interactionEnd is called on a target different from the swiped row
            underTest.onMagneticInteractionEnd(neighborRow, null)

            // THEN magnetic animations are cancelled
            assertThat(magneticAnimationsCancelled).isTrue()
        }

    private fun setDetachedState() {
        val threshold = 100f
        underTest.setSwipeThresholdPx(threshold)
@@ -284,7 +315,11 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
                    startVelocity: Float,
                ) {}

                override fun cancelMagneticAnimations() {}
                override fun cancelMagneticAnimations() {
                    magneticAnimationsCancelled = true
                }

                override fun cancelTranslationAnimations() {}

                override fun canRowBeDismissed(): Boolean = canRowBeDismissed
            }
+3 −3
Original line number Diff line number Diff line
@@ -405,7 +405,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
        doNothing().when(mSwipeHelper).superSnapChild(mNotificationRow, 0, 0);
        mSwipeHelper.snapChild(mNotificationRow, 0, 0);

        verify(mCallback, times(1)).onDragCancelledWithVelocity(mNotificationRow, 0);
        verify(mCallback, times(1)).onDragCancelled(mNotificationRow);
        verify(mSwipeHelper, times(1)).superSnapChild(mNotificationRow, 0, 0);
        verify(mSwipeHelper, times(1)).handleMenuCoveredOrDismissed();
    }
@@ -416,7 +416,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
        doNothing().when(mSwipeHelper).superSnapChild(mNotificationRow, 10, 0);
        mSwipeHelper.snapChild(mNotificationRow, 10, 0);

        verify(mCallback, times(1)).onDragCancelledWithVelocity(mNotificationRow, 0);
        verify(mCallback, times(1)).onDragCancelled(mNotificationRow);
        verify(mSwipeHelper, times(1)).superSnapChild(mNotificationRow, 10, 0);
        verify(mSwipeHelper, times(0)).handleMenuCoveredOrDismissed();
    }
@@ -426,7 +426,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
        doNothing().when(mSwipeHelper).superSnapChild(mView, 10, 0);
        mSwipeHelper.snapChild(mView, 10, 0);

        verify(mCallback).onDragCancelledWithVelocity(mView, 0);
        verify(mCallback).onDragCancelled(mView);
        verify(mSwipeHelper, never()).superSnapChild(mView, 10, 0);
    }

+16 −7
Original line number Diff line number Diff line
@@ -352,6 +352,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
                            && Math.abs(delta) > Math.abs(deltaPerpendicular)) {
                        if (mCallback.canChildBeDragged(mTouchedView)) {
                            mIsSwiping = true;
                            mCallback.setMagneticAndRoundableTargets(mTouchedView);
                            mCallback.onBeginDrag(mTouchedView);
                            mInitialTouchPos = getPos(ev);
                            mTranslation = getTranslation(mTouchedView);
@@ -444,6 +445,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
        };

        Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
        mCallback.onMagneticInteractionEnd(animView, velocity);
        if (anim == null) {
            onDismissChildWithAnimationFinished();
            return;
@@ -733,7 +735,8 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
                        dismissChild(mTouchedView, velocity,
                                !swipedFastEnough() /* useAccelerateInterpolator */);
                    } else {
                        mCallback.onDragCancelledWithVelocity(mTouchedView, velocity);
                        mCallback.onMagneticInteractionEnd(mTouchedView, velocity);
                        mCallback.onDragCancelled(mTouchedView);
                        snapChild(mTouchedView, 0 /* leftTarget */, velocity);
                    }
                    mTouchedView = null;
@@ -935,18 +938,24 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {

        void onBeginDrag(View v);

        /**
         * Set magnetic and roundable targets for a view.
         */
        void setMagneticAndRoundableTargets(View v);

        void onChildDismissed(View v);

        void onDragCancelled(View v);

        /**
         * A drag operation has been cancelled on a view with a final velocity.
         * @param v View that was dragged.
         * @param finalVelocity Final velocity of the drag.
         * Notify that a magnetic interaction ended on a view with a velocity.
         * <p>
         * This method should be called when a view will snap back or be dismissed.
         *
         * @param view The {@link  View} whose magnetic interaction ended.
         * @param velocity The velocity when the interaction ended.
         */
        default void onDragCancelledWithVelocity(View v, float finalVelocity) {
            onDragCancelled(v);
        }
        void onMagneticInteractionEnd(View view, float velocity);

        /**
         * Called when the child is long pressed and available to start drag and drop.
+6 −2
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro
        @Override
        public void triggerMagneticForce(float endTranslation, @NonNull SpringForce springForce,
                float startVelocity) {
            cancelMagneticAnimations();
            cancelTranslationAnimations();
            mMagneticAnimator.setSpring(springForce);
            mMagneticAnimator.setStartVelocity(startVelocity);
            mMagneticAnimator.animateToFinalPosition(endTranslation);
@@ -114,10 +114,14 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro

        @Override
        public void cancelMagneticAnimations() {
            cancelTranslationAnimations();
            mMagneticAnimator.cancel();
        }

        @Override
        public void cancelTranslationAnimations() {
            ExpandableView.this.cancelTranslationAnimations();
        }

        @Override
        public boolean canRowBeDismissed() {
            return canExpandableViewBeDismissed();
+22 −11
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ constructor(
                stackScrollLayout,
                MAGNETIC_TRANSLATION_MULTIPLIERS.size,
            )
        currentMagneticListeners.swipedListener()?.cancelTranslationAnimations()
        newListeners.forEach {
            if (currentMagneticListeners.contains(it)) {
                it?.cancelMagneticAnimations()
@@ -214,22 +215,32 @@ constructor(
    }

    override fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float?) {
        if (!row.isSwipedTarget()) return

        if (row.isSwipedTarget()) {
            when (currentState) {
                State.PULLING -> {
                    snapNeighborsBack(velocity)
                    currentState = State.IDLE
                }
                State.DETACHED -> {
                    // Cancel any detaching animation that may be occurring
                    currentMagneticListeners.swipedListener()?.cancelMagneticAnimations()
                    currentState = State.IDLE
                }
                else -> {}
            }
        } else {
            // A magnetic neighbor may be dismissing. In this case, we need to cancel any snap back
            // magnetic animation to let the external dismiss animation proceed.
            val listener = currentMagneticListeners.find { it == row.magneticRowListener }
            listener?.cancelMagneticAnimations()
        }
    }

    override fun reset() {
        currentMagneticListeners.forEach { it?.cancelMagneticAnimations() }
        currentMagneticListeners.forEach {
            it?.cancelMagneticAnimations()
            it?.cancelTranslationAnimations()
        }
        currentState = State.IDLE
        currentMagneticListeners = listOf()
        currentRoundableTargets = null
Loading