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
18 
19 import android.text.format.DateUtils
20 import androidx.annotation.UiThread
21 import androidx.lifecycle.Observer
22 import com.android.systemui.R
23 
24 /**
25  * Observer for changes from SeekBarViewModel.
26  *
27  * <p>Updates the seek bar views in response to changes to the model.
28  */
29 class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarViewModel.Progress> {
30 
31     val seekBarEnabledMaxHeight = holder.seekBar.context.resources
32         .getDimensionPixelSize(R.dimen.qs_media_enabled_seekbar_height)
33     val seekBarDisabledHeight = holder.seekBar.context.resources
34         .getDimensionPixelSize(R.dimen.qs_media_disabled_seekbar_height)
35     val seekBarEnabledVerticalPadding = holder.seekBar.context.resources
36             .getDimensionPixelSize(R.dimen.qs_media_enabled_seekbar_vertical_padding)
37     val seekBarDisabledVerticalPadding = holder.seekBar.context.resources
38             .getDimensionPixelSize(R.dimen.qs_media_disabled_seekbar_vertical_padding)
39 
40     /** Updates seek bar views when the data model changes. */
41     @UiThread
42     override fun onChanged(data: SeekBarViewModel.Progress) {
43         if (!data.enabled) {
44             if (holder.seekBar.maxHeight != seekBarDisabledHeight) {
45                 holder.seekBar.maxHeight = seekBarDisabledHeight
46                 setVerticalPadding(seekBarDisabledVerticalPadding)
47             }
48             holder.seekBar.setEnabled(false)
49             holder.seekBar.getThumb().setAlpha(0)
50             holder.seekBar.setProgress(0)
51             holder.elapsedTimeView.setText("")
52             holder.totalTimeView.setText("")
53             holder.seekBar.contentDescription = ""
54             return
55         }
56 
57         holder.seekBar.getThumb().setAlpha(if (data.seekAvailable) 255 else 0)
58         holder.seekBar.setEnabled(data.seekAvailable)
59 
60         if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) {
61             holder.seekBar.maxHeight = seekBarEnabledMaxHeight
62             setVerticalPadding(seekBarEnabledVerticalPadding)
63         }
64 
65         holder.seekBar.setMax(data.duration)
66         val totalTimeString = DateUtils.formatElapsedTime(
67             data.duration / DateUtils.SECOND_IN_MILLIS)
68         holder.totalTimeView.setText(totalTimeString)
69 
70         data.elapsedTime?.let {
71             holder.seekBar.setProgress(it)
72             val elapsedTimeString = DateUtils.formatElapsedTime(
73                 it / DateUtils.SECOND_IN_MILLIS)
74             holder.elapsedTimeView.setText(elapsedTimeString)
75 
76             holder.seekBar.contentDescription = holder.seekBar.context.getString(
77                 R.string.controls_media_seekbar_description,
78                 elapsedTimeString,
79                 totalTimeString
80             )
81         }
82     }
83 
84     @UiThread
85     fun setVerticalPadding(padding: Int) {
86         val leftPadding = holder.seekBar.paddingLeft
87         val rightPadding = holder.seekBar.paddingRight
88         val bottomPadding = holder.seekBar.paddingBottom
89         holder.seekBar.setPadding(leftPadding, padding, rightPadding, bottomPadding)
90     }
91 }
92