1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  *
14  */
15 
16 package com.android.systemui.statusbar.notification.domain.interactor
17 
18 import com.android.systemui.dagger.qualifiers.Background
19 import com.android.systemui.statusbar.notification.collection.render.NotifStats
20 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
21 import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
22 import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
23 import javax.inject.Inject
24 import kotlinx.coroutines.CoroutineDispatcher
25 import kotlinx.coroutines.flow.Flow
26 import kotlinx.coroutines.flow.distinctUntilChanged
27 import kotlinx.coroutines.flow.flowOn
28 import kotlinx.coroutines.flow.map
29 
30 class ActiveNotificationsInteractor
31 @Inject
32 constructor(
33     private val repository: ActiveNotificationListRepository,
34     @Background private val backgroundDispatcher: CoroutineDispatcher,
35 ) {
36     /**
37      * Top level list of Notifications actively presented to the user in the notification stack, in
38      * order.
39      */
40     val topLevelRepresentativeNotifications: Flow<List<ActiveNotificationModel>> =
41         repository.activeNotifications
42             .map { store ->
43                 store.renderList.map { key ->
44                     val entry =
45                         store[key]
46                             ?: error(
47                                 "Could not find notification with key $key in active notif store."
48                             )
49                     when (entry) {
50                         is ActiveNotificationGroupModel -> entry.summary
51                         is ActiveNotificationModel -> entry
52                     }
53                 }
54             }
55             .flowOn(backgroundDispatcher)
56 
57     /**
58      * Flattened list of Notifications actively presented to the user in the notification stack, in
59      * order.
60      */
61     val allRepresentativeNotifications: Flow<Map<String, ActiveNotificationModel>> =
62         repository.activeNotifications.map { store -> store.individuals }
63 
64     /** Size of the flattened list of Notifications actively presented in the stack. */
65     val allNotificationsCount: Flow<Int> =
66         repository.activeNotifications.map { store -> store.individuals.size }
67 
68     /**
69      * The same as [allNotificationsCount], but without flows, for easy access in synchronous code.
70      */
71     val allNotificationsCountValue: Int
72         get() = repository.activeNotifications.value.individuals.size
73 
74     /** Are any notifications being actively presented in the notification stack? */
75     val areAnyNotificationsPresent: Flow<Boolean> =
76         repository.activeNotifications
77             .map { it.renderList.isNotEmpty() }
78             .distinctUntilChanged()
79             .flowOn(backgroundDispatcher)
80 
81     /**
82      * The same as [areAnyNotificationsPresent], but without flows, for easy access in synchronous
83      * code.
84      */
85     val areAnyNotificationsPresentValue: Boolean
86         get() = repository.activeNotifications.value.renderList.isNotEmpty()
87 
88     /**
89      * Map of notification key to rank, where rank is the 0-based index of the notification in the
90      * system server, meaning that in the unfiltered flattened list of notification entries. Used
91      * for logging purposes.
92      *
93      * @see [com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger].
94      */
95     val activeNotificationRanks: Flow<Map<String, Int>> =
96         repository.activeNotifications.map { store -> store.rankingsMap }
97 
98     /** Are there are any notifications that can be cleared by the "Clear all" button? */
99     val hasClearableNotifications: Flow<Boolean> =
100         repository.notifStats
101             .map { it.hasClearableAlertingNotifs || it.hasClearableSilentNotifs }
102             .distinctUntilChanged()
103             .flowOn(backgroundDispatcher)
104 
105     val hasClearableAlertingNotifications: Flow<Boolean> =
106         repository.notifStats
107             .map { it.hasClearableAlertingNotifs }
108             .distinctUntilChanged()
109             .flowOn(backgroundDispatcher)
110 
111     val hasNonClearableSilentNotifications: Flow<Boolean> =
112         repository.notifStats
113             .map { it.hasNonClearableSilentNotifs }
114             .distinctUntilChanged()
115             .flowOn(backgroundDispatcher)
116 
117     fun setNotifStats(notifStats: NotifStats) {
118         repository.notifStats.value = notifStats
119     }
120 }
121