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

Commit 9689879d authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez Committed by Android (Google) Code Review
Browse files

Merge "Adding roundness during pre-detachment." into main

parents b2d828a5 a0f7e974
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            // THEN the magnetic and roundable targets are defined and the state is TARGETS_SET
            assertThat(underTest.currentState).isEqualTo(State.TARGETS_SET)
            assertThat(underTest.currentMagneticListeners.isNotEmpty()).isTrue()
            assertThat(underTest.currentRoundableTargets).isNotNull()
            assertThat(underTest.isSwipedViewRoundableSet).isTrue()
        }

    @Test
@@ -281,6 +281,19 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            assertThat(magneticAnimationsCancelled[neighborIndex]).isTrue()
        }

    @Test
    fun onResetRoundness_swipedRoundableGetsCleared() =
        kosmos.testScope.runTest {
            // GIVEN targets are set
            setTargets()

            // WHEN we reset the roundness
            underTest.resetRoundness()

            // THEN the swiped roundable gets cleared
            assertThat(underTest.isSwipedViewRoundableSet).isFalse()
        }

    @After
    fun tearDown() {
        // We reset the manager so that all MagneticRowListener can cancel all animations
+5 −0
Original line number Diff line number Diff line
@@ -87,6 +87,9 @@ interface MagneticNotificationRowManager {
     */
    fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float? = null)

    /* Reset any roundness that magnetic targets may have */
    fun resetRoundness()

    /**
     * Reset any magnetic and roundable targets set, as well as any internal state.
     *
@@ -124,6 +127,8 @@ interface MagneticNotificationRowManager {
                        velocity: Float?,
                    ) {}

                    override fun resetRoundness() {}

                    override fun reset() {}
                }
    }
+33 −9
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.google.android.msdl.domain.MSDLPlayer
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.pow
import org.jetbrains.annotations.TestOnly

@SysUISingleton
class MagneticNotificationRowManagerImpl
@@ -41,15 +42,16 @@ constructor(
    var currentState = State.IDLE
        private set

    // Magnetic and roundable targets
    // Magnetic targets
    var currentMagneticListeners = listOf<MagneticRowListener?>()
        private set

    var currentRoundableTargets: RoundableTargets? = null
        private set

    private var magneticDetachThreshold = Float.POSITIVE_INFINITY

    // Has the roundable target been set for the magnetic view that is being swiped.
    val isSwipedViewRoundableSet: Boolean
        @TestOnly get() = notificationRoundnessManager.isSwipedViewSet

    // Animation spring forces
    private val detachForce =
        SpringForce().setStiffness(DETACH_STIFFNESS).setDampingRatio(DETACH_DAMPING_RATIO)
@@ -83,12 +85,14 @@ constructor(
        sectionsManager: NotificationSectionsManager,
    ) {
        // Update roundable targets
        currentRoundableTargets =
        notificationRoundnessManager.clear()
        val currentRoundableTargets =
            notificationTargetsHelper.findRoundableTargets(
                expandableNotificationRow,
                stackScrollLayout,
                sectionsManager,
            )
        notificationRoundnessManager.setRoundableTargets(currentRoundableTargets)

        // Update magnetic targets
        val newListeners =
@@ -127,6 +131,7 @@ constructor(
                currentState = State.PULLING
            }
            State.PULLING -> {
                updateRoundness(translation)
                if (canTargetBeDismissed) {
                    pullDismissibleRow(translation)
                } else {
@@ -141,6 +146,14 @@ constructor(
        return true
    }

    private fun updateRoundness(translation: Float) {
        val normalizedTranslation = abs(swipedRowMultiplier * translation) / magneticDetachThreshold
        notificationRoundnessManager.setRoundnessForAffectedViews(
            /* roundness */ normalizedTranslation.coerceIn(0f, MAX_PRE_DETACH_ROUNDNESS),
            /* animate */ false,
        )
    }

    private fun pullDismissibleRow(translation: Float) {
        val targetTranslation = swipedRowMultiplier * translation
        val crossedThreshold = abs(targetTranslation) >= magneticDetachThreshold
@@ -203,9 +216,10 @@ constructor(
    private fun detach(listener: MagneticRowListener, toPosition: Float) {
        listener.cancelMagneticAnimations()
        listener.triggerMagneticForce(toPosition, detachForce)
        currentRoundableTargets?.let {
            notificationRoundnessManager.setViewsAffectedBySwipe(it.before, it.swiped, it.after)
        }
        notificationRoundnessManager.setRoundnessForAffectedViews(
            /* roundness */ 1f,
            /* animate */ true,
        )
        msdlPlayer.playToken(MSDLToken.SWIPE_THRESHOLD_INDICATOR)
    }

@@ -240,6 +254,8 @@ constructor(
        }
    }

    override fun resetRoundness() = notificationRoundnessManager.clear()

    override fun reset() {
        currentMagneticListeners.forEach {
            it?.cancelMagneticAnimations()
@@ -247,7 +263,7 @@ constructor(
        }
        currentState = State.IDLE
        currentMagneticListeners = listOf()
        currentRoundableTargets = null
        notificationRoundnessManager.clear()
    }

    private fun List<MagneticRowListener?>.swipedListener(): MagneticRowListener? =
@@ -256,6 +272,11 @@ constructor(
    private fun ExpandableNotificationRow.isSwipedTarget(): Boolean =
        magneticRowListener == currentMagneticListeners.swipedListener()

    private fun NotificationRoundnessManager.clear() = setViewsAffectedBySwipe(null, null, null)

    private fun NotificationRoundnessManager.setRoundableTargets(targets: RoundableTargets) =
        setViewsAffectedBySwipe(targets.before, targets.swiped, targets.after)

    enum class State {
        IDLE,
        TARGETS_SET,
@@ -280,6 +301,9 @@ constructor(
        private const val SNAP_BACK_STIFFNESS = 550f
        private const val SNAP_BACK_DAMPING_RATIO = 0.52f

        // Maximum value of corner roundness that gets applied during the pre-detach dragging
        private const val MAX_PRE_DETACH_ROUNDNESS = 0.8f

        private val VIBRATION_ATTRIBUTES_PIPELINING =
            VibrationAttributes.Builder()
                .setUsage(VibrationAttributes.USAGE_TOUCH)
+34 −7
Original line number Diff line number Diff line
@@ -71,10 +71,8 @@ public class NotificationRoundnessManager implements Dumpable {
            Roundable viewBefore,
            ExpandableView viewSwiped,
            Roundable viewAfter) {
        // This method requires you to change the roundness of the current View targets and reset
        // the roundness of the old View targets (if any) to 0f.
        // To avoid conflicts, it generates a set of old Views and removes the current Views
        // from this set.
        // This method caches a new set of current View targets and reset the roundness of the old
        // View targets (if any) to 0f.
        HashSet<Roundable> oldViews = new HashSet<>();
        if (mViewBeforeSwipedView != null) oldViews.add(mViewBeforeSwipedView);
        if (mSwipedView != null) oldViews.add(mSwipedView);
@@ -83,19 +81,16 @@ public class NotificationRoundnessManager implements Dumpable {
        mViewBeforeSwipedView = viewBefore;
        if (viewBefore != null) {
            oldViews.remove(viewBefore);
            viewBefore.requestRoundness(/* top = */ 0f, /* bottom = */ 1f, DISMISS_ANIMATION);
        }

        mSwipedView = viewSwiped;
        if (viewSwiped != null) {
            oldViews.remove(viewSwiped);
            viewSwiped.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, DISMISS_ANIMATION);
        }

        mViewAfterSwipedView = viewAfter;
        if (viewAfter != null) {
            oldViews.remove(viewAfter);
            viewAfter.requestRoundness(/* top = */ 1f, /* bottom = */ 0f, DISMISS_ANIMATION);
        }

        // After setting the current Views, reset the views that are still present in the set.
@@ -104,6 +99,34 @@ public class NotificationRoundnessManager implements Dumpable {
        }
    }

    void setRoundnessForAffectedViews(float roundness) {
        if (mViewBeforeSwipedView != null) {
            mViewBeforeSwipedView.requestBottomRoundness(roundness, DISMISS_ANIMATION);
        }

        if (mSwipedView != null) {
            mSwipedView.requestRoundness(roundness, roundness, DISMISS_ANIMATION);
        }

        if (mViewAfterSwipedView != null) {
            mViewAfterSwipedView.requestTopRoundness(roundness, DISMISS_ANIMATION);
        }
    }

    void setRoundnessForAffectedViews(float roundness, boolean animate) {
        if (mViewBeforeSwipedView != null) {
            mViewBeforeSwipedView.requestBottomRoundness(roundness, DISMISS_ANIMATION, animate);
        }

        if (mSwipedView != null) {
            mSwipedView.requestRoundness(roundness, roundness, DISMISS_ANIMATION, animate);
        }

        if (mViewAfterSwipedView != null) {
            mViewAfterSwipedView.requestTopRoundness(roundness, DISMISS_ANIMATION, animate);
        }
    }

    void setClearAllInProgress(boolean isClearingAll) {
        mIsClearAllInProgress = isClearingAll;
    }
@@ -138,4 +161,8 @@ public class NotificationRoundnessManager implements Dumpable {
    public void setShouldRoundPulsingViews(boolean shouldRoundPulsingViews) {
        mRoundForPulsingViews = shouldRoundPulsingViews;
    }

    public boolean isSwipedViewSet() {
        return mSwipedView != null;
    }
}
+6 −3
Original line number Diff line number Diff line
@@ -5840,7 +5840,8 @@ public class NotificationStackScrollLayout
                            targets.getBefore(),
                            targets.getSwiped(),
                            targets.getAfter());

            mController.getNotificationRoundnessManager()
                    .setRoundnessForAffectedViews(/* roundness */ 1f);
        }

        updateFirstAndLastBackgroundViews();
@@ -5851,8 +5852,10 @@ public class NotificationStackScrollLayout

    void onSwipeEnd() {
        updateFirstAndLastBackgroundViews();
        if (!magneticNotificationSwipes()) {
            mController.getNotificationRoundnessManager()
                    .setViewsAffectedBySwipe(null, null, null);
        }
        // Round bottom corners for notification right before shelf.
        mShelf.updateAppearance();
    }
Loading