• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.systemui.statusbar.notification.stack
2 
3 import androidx.core.view.children
4 import androidx.core.view.isVisible
5 import com.android.systemui.dagger.SysUISingleton
6 import com.android.systemui.flags.FeatureFlags
7 import com.android.systemui.flags.Flags
8 import com.android.systemui.statusbar.notification.Roundable
9 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
10 import com.android.systemui.statusbar.notification.row.ExpandableView
11 import javax.inject.Inject
12 
13 /**
14  * Utility class that helps us find the targets of an animation, often used to find the notification
15  * ([Roundable]) above and below the current one (see [findRoundableTargets]).
16  */
17 @SysUISingleton
18 class NotificationTargetsHelper
19 @Inject
20 constructor(
21     featureFlags: FeatureFlags,
22 ) {
23     private val useRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)
24 
25     /**
26      * This method looks for views that can be rounded (and implement [Roundable]) during a
27      * notification swipe.
28      *
29      * @return The [Roundable] targets above/below the [viewSwiped] (if available). The
30      *   [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
31      *   no above/below notification or the notification is not part of the same section.
32      */
findRoundableTargetsnull33     fun findRoundableTargets(
34         viewSwiped: ExpandableNotificationRow,
35         stackScrollLayout: NotificationStackScrollLayout,
36         sectionsManager: NotificationSectionsManager,
37     ): RoundableTargets {
38         val viewBefore: Roundable?
39         val viewAfter: Roundable?
40 
41         val notificationParent = viewSwiped.notificationParent
42         val childrenContainer = notificationParent?.childrenContainer
43         val visibleStackChildren =
44             stackScrollLayout.children
45                 .filterIsInstance<ExpandableView>()
46                 .filter { it.isVisible }
47                 .toList()
48         if (notificationParent != null && childrenContainer != null) {
49             // We are inside a notification group
50 
51             if (!useRoundnessSourceTypes) {
52                 return RoundableTargets(null, null, null)
53             }
54 
55             val visibleGroupChildren = childrenContainer.attachedChildren.filter { it.isVisible }
56             val indexOfParentSwipedView = visibleGroupChildren.indexOf(viewSwiped)
57 
58             viewBefore =
59                 visibleGroupChildren.getOrNull(indexOfParentSwipedView - 1)
60                     ?: childrenContainer.notificationHeaderWrapper
61 
62             viewAfter =
63                 visibleGroupChildren.getOrNull(indexOfParentSwipedView + 1)
64                     ?: visibleStackChildren.indexOf(notificationParent).let {
65                         visibleStackChildren.getOrNull(it + 1)
66                     }
67         } else {
68             // Assumption: we are inside the NotificationStackScrollLayout
69 
70             val indexOfSwipedView = visibleStackChildren.indexOf(viewSwiped)
71 
72             viewBefore =
73                 visibleStackChildren.getOrNull(indexOfSwipedView - 1)?.takeIf {
74                     !sectionsManager.beginsSection(viewSwiped, it)
75                 }
76 
77             viewAfter =
78                 visibleStackChildren.getOrNull(indexOfSwipedView + 1)?.takeIf {
79                     !sectionsManager.beginsSection(it, viewSwiped)
80                 }
81         }
82 
83         return RoundableTargets(
84             before = viewBefore,
85             swiped = viewSwiped,
86             after = viewAfter,
87         )
88     }
89 }
90 
91 /**
92  * This object contains targets above/below the [swiped] (if available). The [before] and [after]
93  * parameters can be `null` if there is no above/below notification or the notification is not part
94  * of the same section.
95  */
96 data class RoundableTargets(
97     val before: Roundable?,
98     val swiped: ExpandableNotificationRow?,
99     val after: Roundable?,
100 )
101