1 /* <lambda>null2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.notification.footer.ui.viewmodel 18 19 import com.android.systemui.dagger.SysUISingleton 20 import com.android.systemui.res.R 21 import com.android.systemui.shade.domain.interactor.ShadeInteractor 22 import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor 23 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor 24 import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor 25 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor 26 import com.android.systemui.statusbar.notification.footer.ui.view.FooterView 27 import com.android.systemui.util.kotlin.sample 28 import com.android.systemui.util.ui.AnimatableEvent 29 import com.android.systemui.util.ui.AnimatedValue 30 import com.android.systemui.util.ui.toAnimatedValueFlow 31 import dagger.Module 32 import dagger.Provides 33 import java.util.Optional 34 import javax.inject.Provider 35 import kotlinx.coroutines.flow.Flow 36 import kotlinx.coroutines.flow.combine 37 import kotlinx.coroutines.flow.distinctUntilChanged 38 import kotlinx.coroutines.flow.flowOf 39 import kotlinx.coroutines.flow.map 40 import kotlinx.coroutines.flow.onStart 41 42 /** ViewModel for [FooterView]. */ 43 class FooterViewModel( 44 activeNotificationsInteractor: ActiveNotificationsInteractor, 45 notificationSettingsInteractor: NotificationSettingsInteractor, 46 seenNotificationsInteractor: SeenNotificationsInteractor, 47 shadeInteractor: ShadeInteractor, 48 ) { 49 /** A message to show instead of the footer buttons. */ 50 val message: FooterMessageViewModel = 51 FooterMessageViewModel( 52 messageId = R.string.unlock_to_see_notif_text, 53 iconId = R.drawable.ic_friction_lock_closed, 54 isVisible = seenNotificationsInteractor.hasFilteredOutSeenNotifications, 55 ) 56 57 private val clearAllButtonVisible = 58 activeNotificationsInteractor.hasClearableNotifications 59 .combine(message.isVisible) { hasClearableNotifications, isMessageVisible -> 60 if (isMessageVisible) { 61 // If the message is visible, the button never is 62 false 63 } else { 64 hasClearableNotifications 65 } 66 } 67 .distinctUntilChanged() 68 69 /** The button for clearing notifications. */ 70 val clearAllButton: FooterButtonViewModel = 71 FooterButtonViewModel( 72 labelId = flowOf(R.string.clear_all_notifications_text), 73 accessibilityDescriptionId = flowOf(R.string.accessibility_clear_all), 74 isVisible = 75 clearAllButtonVisible 76 .sample( 77 // TODO(b/322167853): This check is currently duplicated in 78 // NotificationListViewModel, but instead it should be a field in 79 // ShadeAnimationInteractor. 80 combine( 81 shadeInteractor.isShadeFullyExpanded, 82 shadeInteractor.isShadeTouchable, 83 ::Pair 84 ) 85 .onStart { emit(Pair(false, false)) } 86 ) { clearAllButtonVisible, (isShadeFullyExpanded, animationsEnabled) -> 87 val shouldAnimate = isShadeFullyExpanded && animationsEnabled 88 AnimatableEvent(clearAllButtonVisible, shouldAnimate) 89 } 90 .toAnimatedValueFlow(), 91 ) 92 93 val manageButtonShouldLaunchHistory = 94 notificationSettingsInteractor.isNotificationHistoryEnabled 95 96 private val manageOrHistoryButtonText: Flow<Int> = 97 manageButtonShouldLaunchHistory.map { shouldLaunchHistory -> 98 if (shouldLaunchHistory) R.string.manage_notifications_history_text 99 else R.string.manage_notifications_text 100 } 101 102 /** The button for managing notification settings or opening notification history. */ 103 val manageOrHistoryButton: FooterButtonViewModel = 104 FooterButtonViewModel( 105 labelId = manageOrHistoryButtonText, 106 accessibilityDescriptionId = manageOrHistoryButtonText, 107 isVisible = 108 // Hide the manage button if the message is visible 109 message.isVisible.map { messageVisible -> 110 AnimatedValue.NotAnimating(!messageVisible) 111 }, 112 ) 113 } 114 115 @Module 116 object FooterViewModelModule { 117 @Provides 118 @SysUISingleton provideOptionalnull119 fun provideOptional( 120 activeNotificationsInteractor: Provider<ActiveNotificationsInteractor>, 121 notificationSettingsInteractor: Provider<NotificationSettingsInteractor>, 122 seenNotificationsInteractor: Provider<SeenNotificationsInteractor>, 123 shadeInteractor: Provider<ShadeInteractor>, 124 ): Optional<FooterViewModel> { 125 return if (FooterViewRefactor.isEnabled) { 126 Optional.of( 127 FooterViewModel( 128 activeNotificationsInteractor.get(), 129 notificationSettingsInteractor.get(), 130 seenNotificationsInteractor.get(), 131 shadeInteractor.get() 132 ) 133 ) 134 } else { 135 Optional.empty() 136 } 137 } 138 } 139