blob: 8b6d6a4f3170231a121b606ed585547e0f2b2087 [file] [log] [blame]
package com.android.systemui.statusbar.notification.stack
import androidx.core.view.children
import androidx.core.view.isVisible
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.notification.Roundable
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import javax.inject.Inject
/**
* Utility class that helps us find the targets of an animation, often used to find the notification
* ([Roundable]) above and below the current one (see [findRoundableTargets]).
*/
@SysUISingleton
class NotificationTargetsHelper
@Inject
constructor(
featureFlags: FeatureFlags,
) {
private val useRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
* notification swipe.
*
* @return The [Roundable] targets above/below the [viewSwiped] (if available). The
* [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
* no above/below notification or the notification is not part of the same section.
*/
fun findRoundableTargets(
viewSwiped: ExpandableNotificationRow,
stackScrollLayout: NotificationStackScrollLayout,
sectionsManager: NotificationSectionsManager,
): RoundableTargets {
val viewBefore: Roundable?
val viewAfter: Roundable?
val notificationParent = viewSwiped.notificationParent
val childrenContainer = notificationParent?.childrenContainer
val visibleStackChildren =
stackScrollLayout.children
.filterIsInstance<ExpandableView>()
.filter { it.isVisible }
.toList()
if (notificationParent != null && childrenContainer != null) {
// We are inside a notification group
if (!useRoundnessSourceTypes) {
return RoundableTargets(null, null, null)
}
val visibleGroupChildren = childrenContainer.attachedChildren.filter { it.isVisible }
val indexOfParentSwipedView = visibleGroupChildren.indexOf(viewSwiped)
viewBefore =
visibleGroupChildren.getOrNull(indexOfParentSwipedView - 1)
?: childrenContainer.notificationHeaderWrapper
viewAfter =
visibleGroupChildren.getOrNull(indexOfParentSwipedView + 1)
?: visibleStackChildren.indexOf(notificationParent).let {
visibleStackChildren.getOrNull(it + 1)
}
} else {
// Assumption: we are inside the NotificationStackScrollLayout
val indexOfSwipedView = visibleStackChildren.indexOf(viewSwiped)
viewBefore =
visibleStackChildren.getOrNull(indexOfSwipedView - 1)?.takeIf {
!sectionsManager.beginsSection(viewSwiped, it)
}
viewAfter =
visibleStackChildren.getOrNull(indexOfSwipedView + 1)?.takeIf {
!sectionsManager.beginsSection(it, viewSwiped)
}
}
return RoundableTargets(
before = viewBefore,
swiped = viewSwiped,
after = viewAfter,
)
}
}
/**
* This object contains targets above/below the [swiped] (if available). The [before] and [after]
* parameters can be `null` if there is no above/below notification or the notification is not part
* of the same section.
*/
data class RoundableTargets(
val before: Roundable?,
val swiped: ExpandableNotificationRow?,
val after: Roundable?,
)