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 
18 package com.android.systemui.keyguard.ui.binder
19 
20 import android.util.Log
21 import androidx.constraintlayout.widget.ConstraintLayout
22 import androidx.constraintlayout.widget.ConstraintSet
23 import androidx.lifecycle.Lifecycle
24 import androidx.lifecycle.repeatOnLifecycle
25 import com.android.app.tracing.coroutines.launch
26 import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
27 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
28 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.BaseBlueprintTransition
29 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
30 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
31 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
32 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
33 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
34 import com.android.systemui.lifecycle.repeatWhenAttached
35 import com.android.systemui.res.R
36 import com.android.systemui.shared.R as sharedR
37 import com.android.systemui.util.kotlin.pairwise
38 
39 object KeyguardBlueprintViewBinder {
40     @JvmStatic
41     fun bind(
42         constraintLayout: ConstraintLayout,
43         viewModel: KeyguardBlueprintViewModel,
44         clockViewModel: KeyguardClockViewModel,
45         smartspaceViewModel: KeyguardSmartspaceViewModel,
46     ) {
47         constraintLayout.repeatWhenAttached {
48             repeatOnLifecycle(Lifecycle.State.CREATED) {
49                 launch("$TAG#viewModel.blueprint") {
50                     viewModel.blueprint
51                         .pairwise(
52                             null as KeyguardBlueprint?,
53                         )
54                         .collect { (prevBlueprint, blueprint) ->
55                             val config = Config.DEFAULT
56                             val transition =
57                                 if (
58                                     !KeyguardBottomAreaRefactor.isEnabled &&
59                                         prevBlueprint != null &&
60                                         prevBlueprint != blueprint
61                                 ) {
62                                     BaseBlueprintTransition(clockViewModel)
63                                         .addTransition(
64                                             IntraBlueprintTransition(
65                                                 config,
66                                                 clockViewModel,
67                                                 smartspaceViewModel
68                                             )
69                                         )
70                                 } else {
71                                     IntraBlueprintTransition(
72                                         config,
73                                         clockViewModel,
74                                         smartspaceViewModel
75                                     )
76                                 }
77 
78                             viewModel.runTransition(constraintLayout, transition, config) {
79                                 // Replace sections from the previous blueprint with the new ones
80                                 blueprint.replaceViews(
81                                     constraintLayout,
82                                     prevBlueprint,
83                                     config.rebuildSections
84                                 )
85 
86                                 val cs =
87                                     ConstraintSet().apply {
88                                         clone(constraintLayout)
89                                         val emptyLayout = ConstraintSet.Layout()
90                                         knownIds.forEach {
91                                             getConstraint(it).layout.copyFrom(emptyLayout)
92                                         }
93                                         blueprint.applyConstraints(this)
94                                     }
95 
96                                 logAlphaVisibilityOfAppliedConstraintSet(cs, clockViewModel)
97                                 cs.applyTo(constraintLayout)
98                             }
99                         }
100                 }
101 
102                 launch("$TAG#viewModel.refreshTransition") {
103                     viewModel.refreshTransition.collect { config ->
104                         val blueprint = viewModel.blueprint.value
105 
106                         viewModel.runTransition(
107                             constraintLayout,
108                             IntraBlueprintTransition(config, clockViewModel, smartspaceViewModel),
109                             config,
110                         ) {
111                             blueprint.rebuildViews(constraintLayout, config.rebuildSections)
112 
113                             val cs =
114                                 ConstraintSet().apply {
115                                     clone(constraintLayout)
116                                     blueprint.applyConstraints(this)
117                                 }
118                             logAlphaVisibilityOfAppliedConstraintSet(cs, clockViewModel)
119                             cs.applyTo(constraintLayout)
120                         }
121                     }
122                 }
123             }
124         }
125     }
126 
127     private fun logAlphaVisibilityOfAppliedConstraintSet(
128         cs: ConstraintSet,
129         viewModel: KeyguardClockViewModel
130     ) {
131         val currentClock = viewModel.currentClock.value
132         if (!DEBUG || currentClock == null) return
133         val smallClockViewId = R.id.lockscreen_clock_view
134         val largeClockViewId = currentClock.largeClock.layout.views[0].id
135         val smartspaceDateId = sharedR.id.date_smartspace_view
136         Log.i(
137             TAG,
138             "applyCsToSmallClock: vis=${cs.getVisibility(smallClockViewId)} " +
139                 "alpha=${cs.getConstraint(smallClockViewId).propertySet.alpha}"
140         )
141         Log.i(
142             TAG,
143             "applyCsToLargeClock: vis=${cs.getVisibility(largeClockViewId)} " +
144                 "alpha=${cs.getConstraint(largeClockViewId).propertySet.alpha}"
145         )
146         Log.i(
147             TAG,
148             "applyCsToSmartspaceDate: vis=${cs.getVisibility(smartspaceDateId)} " +
149                 "alpha=${cs.getConstraint(smartspaceDateId).propertySet.alpha}"
150         )
151     }
152 
153     private const val TAG = "KeyguardBlueprintViewBinder"
154     private const val DEBUG = false
155 }
156