1 /*
2  * Copyright (C) 2020 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.media.controls.models.recommendation
18 
19 import android.view.LayoutInflater
20 import android.view.View
21 import android.view.ViewGroup
22 import android.widget.ImageView
23 import android.widget.SeekBar
24 import android.widget.TextView
25 import com.android.internal.widget.CachingIconView
26 import com.android.systemui.R
27 import com.android.systemui.media.controls.models.GutsViewHolder
28 import com.android.systemui.media.controls.ui.IlluminationDrawable
29 import com.android.systemui.util.animation.TransitionLayout
30 
31 private const val TAG = "RecommendationViewHolder"
32 
33 /** ViewHolder for a Smartspace media recommendation. */
34 class RecommendationViewHolder private constructor(itemView: View) {
35 
36     val recommendations = itemView as TransitionLayout
37 
38     // Recommendation screen
39     val cardTitle: TextView = itemView.requireViewById(R.id.media_rec_title)
40 
41     val mediaCoverContainers =
42         listOf<ViewGroup>(
43             itemView.requireViewById(R.id.media_cover1_container),
44             itemView.requireViewById(R.id.media_cover2_container),
45             itemView.requireViewById(R.id.media_cover3_container)
46         )
47     val mediaAppIcons: List<CachingIconView> =
48         mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
49     val mediaTitles: List<TextView> =
50         mediaCoverContainers.map { it.requireViewById(R.id.media_title) }
51     val mediaSubtitles: List<TextView> =
52         mediaCoverContainers.map { it.requireViewById(R.id.media_subtitle) }
53     val mediaProgressBars: List<SeekBar> =
54         mediaCoverContainers.map {
55             it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply {
56                 // Media playback is in the direction of tape, not time, so it stays LTR
57                 layoutDirection = View.LAYOUT_DIRECTION_LTR
58             }
59         }
60 
61     val mediaCoverItems: List<ImageView> =
62         mediaCoverContainers.map { it.requireViewById(R.id.media_cover) }
63     val gutsViewHolder = GutsViewHolder(itemView)
64 
65     init {
66         (recommendations.background as IlluminationDrawable).let { background ->
67             mediaCoverContainers.forEach { background.registerLightSource(it) }
68             background.registerLightSource(gutsViewHolder.cancel)
69             background.registerLightSource(gutsViewHolder.dismiss)
70             background.registerLightSource(gutsViewHolder.settings)
71         }
72     }
73 
74     fun marquee(start: Boolean, delay: Long) {
75         gutsViewHolder.marquee(start, delay, TAG)
76     }
77 
78     companion object {
79         /**
80          * Creates a RecommendationViewHolder.
81          *
82          * @param inflater LayoutInflater to use to inflate the layout.
83          * @param parent Parent of inflated view.
84          */
85         @JvmStatic
86         fun create(inflater: LayoutInflater, parent: ViewGroup): RecommendationViewHolder {
87             val itemView =
88                 inflater.inflate(R.layout.media_recommendations, parent, false /* attachToRoot */)
89             // Because this media view (a TransitionLayout) is used to measure and layout the views
90             // in various states before being attached to its parent, we can't depend on the default
91             // LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
92             itemView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE
93             return RecommendationViewHolder(itemView)
94         }
95 
96         // Res Ids for the control components on the recommendation view.
97         val controlsIds =
98             setOf(
99                 R.id.media_rec_title,
100                 R.id.media_cover,
101                 R.id.media_cover1_container,
102                 R.id.media_cover2_container,
103                 R.id.media_cover3_container,
104                 R.id.media_title,
105                 R.id.media_subtitle,
106             )
107 
108         val mediaTitlesAndSubtitlesIds =
109             setOf(
110                 R.id.media_title,
111                 R.id.media_subtitle,
112             )
113 
114         val mediaContainersIds =
115             setOf(
116                 R.id.media_cover1_container,
117                 R.id.media_cover2_container,
118                 R.id.media_cover3_container
119             )
120 
121         val backgroundId = R.id.sizing_view
122     }
123 }
124