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 
18 package com.android.systemui.keyguard.ui.view.layout.sections
19 
20 import android.content.Context
21 import android.view.View
22 import android.view.ViewGroup
23 import androidx.constraintlayout.widget.Barrier
24 import androidx.constraintlayout.widget.ConstraintLayout
25 import androidx.constraintlayout.widget.ConstraintSet
26 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
27 import androidx.constraintlayout.widget.ConstraintSet.TOP
28 import com.android.systemui.keyguard.MigrateClocksToBlueprint
29 import com.android.systemui.keyguard.shared.model.KeyguardSection
30 import com.android.systemui.res.R
31 import com.android.systemui.shade.NotificationPanelView
32 import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
33 import com.android.systemui.statusbar.notification.stack.ui.viewbinder.SharedNotificationContainerBinder
34 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
35 import kotlinx.coroutines.DisposableHandle
36 
37 abstract class NotificationStackScrollLayoutSection
38 constructor(
39     protected val context: Context,
40     private val notificationPanelView: NotificationPanelView,
41     private val sharedNotificationContainer: SharedNotificationContainer,
42     private val sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
43     private val sharedNotificationContainerBinder: SharedNotificationContainerBinder,
44 ) : KeyguardSection() {
45     private val placeHolderId = R.id.nssl_placeholder
46     private var disposableHandle: DisposableHandle? = null
47 
48     /**
49      * Align the notification placeholder bottom to the top of either the lock icon or the ambient
50      * indication area, whichever is higher.
51      */
addNotificationPlaceholderBarriernull52     protected fun addNotificationPlaceholderBarrier(constraintSet: ConstraintSet) {
53         constraintSet.apply {
54             createBarrier(
55                 R.id.nssl_placeholder_barrier_bottom,
56                 Barrier.TOP,
57                 0,
58                 *intArrayOf(
59                     R.id.device_entry_icon_view,
60                     R.id.lock_icon_view,
61                     R.id.ambient_indication_container
62                 )
63             )
64             connect(placeHolderId, BOTTOM, R.id.nssl_placeholder_barrier_bottom, TOP)
65         }
66     }
67 
addViewsnull68     override fun addViews(constraintLayout: ConstraintLayout) {
69         if (!MigrateClocksToBlueprint.isEnabled) {
70             return
71         }
72         // This moves the existing NSSL view to a different parent, as the controller is a
73         // singleton and recreating it has other bad side effects.
74         // In the SceneContainer, this is done by the NotificationSection composable.
75         notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
76             (it.parent as ViewGroup).removeView(it)
77             sharedNotificationContainer.addNotificationStackScrollLayout(it)
78         }
79 
80         val view = View(context, null).apply { id = placeHolderId }
81         constraintLayout.addView(view)
82     }
83 
bindDatanull84     override fun bindData(constraintLayout: ConstraintLayout) {
85         if (!MigrateClocksToBlueprint.isEnabled) {
86             return
87         }
88 
89         disposableHandle?.dispose()
90         disposableHandle =
91             sharedNotificationContainerBinder.bind(
92                 sharedNotificationContainer,
93                 sharedNotificationContainerViewModel,
94             )
95     }
96 
removeViewsnull97     override fun removeViews(constraintLayout: ConstraintLayout) {
98         disposableHandle?.dispose()
99         disposableHandle = null
100         constraintLayout.removeView(placeHolderId)
101     }
102 }
103