1 /* 2 * 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.shelf.ui.viewbinder 18 19 import android.view.View 20 import androidx.lifecycle.Lifecycle 21 import androidx.lifecycle.repeatOnLifecycle 22 import com.android.systemui.dagger.SysUISingleton 23 import com.android.systemui.flags.FeatureFlags 24 import com.android.systemui.lifecycle.repeatWhenAttached 25 import com.android.systemui.plugins.FalsingManager 26 import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl 27 import com.android.systemui.statusbar.NotificationShelf 28 import com.android.systemui.statusbar.NotificationShelfController 29 import com.android.systemui.statusbar.notification.row.ui.viewbinder.ActivatableNotificationViewBinder 30 import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel 31 import com.android.systemui.statusbar.notification.stack.AmbientState 32 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController 33 import com.android.systemui.statusbar.phone.NotificationIconAreaController 34 import com.android.systemui.statusbar.phone.NotificationIconContainer 35 import javax.inject.Inject 36 import kotlinx.coroutines.awaitCancellation 37 import kotlinx.coroutines.launch 38 39 /** 40 * Controller class for [NotificationShelf]. This implementation serves as a temporary wrapper 41 * around a [NotificationShelfViewBinder], so that external code can continue to depend on the 42 * [NotificationShelfController] interface. Once the [LegacyNotificationShelfControllerImpl] is 43 * removed, this class can go away and the ViewBinder can be used directly. 44 */ 45 @SysUISingleton 46 class NotificationShelfViewBinderWrapperControllerImpl @Inject constructor() : 47 NotificationShelfController { 48 49 override val view: NotificationShelf 50 get() = unsupported 51 52 override val intrinsicHeight: Int 53 get() = unsupported 54 55 override val shelfIcons: NotificationIconContainer 56 get() = unsupported 57 58 override fun canModifyColorOfNotifications(): Boolean = unsupported 59 60 override fun bind( 61 ambientState: AmbientState, 62 notificationStackScrollLayoutController: NotificationStackScrollLayoutController, 63 ) = unsupported 64 65 override fun setOnClickListener(listener: View.OnClickListener) = unsupported 66 67 companion object { 68 val unsupported: Nothing 69 get() = error("Code path not supported when NOTIFICATION_SHELF_REFACTOR is disabled") 70 } 71 } 72 73 /** Binds a [NotificationShelf] to its [view model][NotificationShelfViewModel]. */ 74 object NotificationShelfViewBinder { 75 fun bind( 76 shelf: NotificationShelf, 77 viewModel: NotificationShelfViewModel, 78 falsingManager: FalsingManager, 79 featureFlags: FeatureFlags, 80 notificationIconAreaController: NotificationIconAreaController, 81 ) { 82 ActivatableNotificationViewBinder.bind(viewModel, shelf, falsingManager) 83 shelf.apply { 84 // TODO(278765923): Replace with eventual NotificationIconContainerViewBinder#bind() 85 notificationIconAreaController.setShelfIcons(shelfIcons) 86 repeatWhenAttached { 87 repeatOnLifecycle(Lifecycle.State.STARTED) { 88 launch { 89 viewModel.canModifyColorOfNotifications.collect( 90 ::setCanModifyColorOfNotifications 91 ) 92 } 93 launch { viewModel.isClickable.collect(::setCanInteract) } 94 registerViewListenersWhileAttached(shelf, viewModel) 95 } 96 } 97 } 98 } 99 100 private suspend fun registerViewListenersWhileAttached( 101 shelf: NotificationShelf, 102 viewModel: NotificationShelfViewModel, 103 ) { 104 try { 105 shelf.setOnClickListener { viewModel.onShelfClicked() } 106 awaitCancellation() 107 } finally { 108 shelf.setOnClickListener(null) 109 } 110 } 111 } 112