blob: 04715abe5f99caa1c59dd55cf3ea6c07db2cc11c [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.controls.management
import android.app.Activity
import android.content.ComponentName
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.view.ViewStub
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.viewpager2.widget.ViewPager2
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.PageIndicator
import com.android.systemui.settings.CurrentUserTracker
import java.text.Collator
import java.util.concurrent.Executor
import java.util.function.Consumer
import javax.inject.Inject
class ControlsFavoritingActivity @Inject constructor(
@Main private val executor: Executor,
private val controller: ControlsControllerImpl,
private val listingController: ControlsListingController,
broadcastDispatcher: BroadcastDispatcher
) : Activity() {
companion object {
private const val TAG = "ControlsFavoritingActivity"
const val EXTRA_APP = "extra_app_label"
}
private var component: ComponentName? = null
private var appName: CharSequence? = null
private lateinit var structurePager: ViewPager2
private lateinit var statusText: TextView
private lateinit var titleView: TextView
private lateinit var iconView: ImageView
private lateinit var iconFrame: View
private lateinit var pageIndicator: PageIndicator
private var listOfStructures = emptyList<StructureContainer>()
private lateinit var comparator: Comparator<StructureContainer>
private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
private val startingUser = controller.currentUserId
override fun onUserSwitched(newUserId: Int) {
if (newUserId != startingUser) {
stopTracking()
finish()
}
}
}
private val listingCallback = object : ControlsListingController.ControlsListingCallback {
private var icon: Drawable? = null
override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {
val newIcon = serviceInfos.firstOrNull { it.componentName == component }?.loadIcon()
if (icon == newIcon) return
icon = newIcon
executor.execute {
if (icon != null) {
iconView.setImageDrawable(icon)
}
iconFrame.visibility = if (icon != null) View.VISIBLE else View.GONE
}
}
}
override fun onBackPressed() {
finish()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val collator = Collator.getInstance(resources.configuration.locales[0])
comparator = compareBy(collator) { it.structureName }
appName = intent.getCharSequenceExtra(EXTRA_APP)
component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
bindViews()
setUpPager()
loadControls()
listingController.addCallback(listingCallback)
currentUserTracker.startTracking()
}
private fun loadControls() {
component?.let {
statusText.text = resources.getText(com.android.internal.R.string.loading)
val emptyZoneString = resources.getText(
R.string.controls_favorite_other_zone_header)
controller.loadForComponent(it, Consumer { data ->
val allControls = data.allControls
val favoriteKeys = data.favoritesIds
val error = data.errorOnLoad
val controlsByStructure = allControls.groupBy { it.control.structure ?: "" }
listOfStructures = controlsByStructure.map {
StructureContainer(it.key, AllModel(it.value, favoriteKeys, emptyZoneString))
}.sortedWith(comparator)
executor.execute {
structurePager.adapter = StructureAdapter(listOfStructures)
if (error) {
statusText.text = resources.getText(R.string.controls_favorite_load_error)
} else {
statusText.visibility = View.GONE
}
pageIndicator.setNumPages(listOfStructures.size)
pageIndicator.setLocation(0f)
pageIndicator.visibility =
if (listOfStructures.size > 1) View.VISIBLE else View.GONE
}
})
}
}
private fun setUpPager() {
structurePager.apply {
adapter = StructureAdapter(emptyList())
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val name = listOfStructures[position].structureName
titleView.text = if (!TextUtils.isEmpty(name)) name else appName
}
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
pageIndicator.setLocation(position + positionOffset)
}
})
}
}
private fun bindViews() {
setContentView(R.layout.controls_management)
requireViewById<ViewStub>(R.id.stub).apply {
layoutResource = R.layout.controls_management_favorites
inflate()
}
statusText = requireViewById(R.id.status_message)
pageIndicator = requireViewById(R.id.structure_page_indicator)
titleView = requireViewById<TextView>(R.id.title).apply {
text = appName ?: resources.getText(R.string.controls_favorite_default_title)
}
requireViewById<TextView>(R.id.subtitle).text =
resources.getText(R.string.controls_favorite_subtitle)
iconView = requireViewById(com.android.internal.R.id.icon)
iconFrame = requireViewById(R.id.icon_frame)
structurePager = requireViewById<ViewPager2>(R.id.structure_pager)
bindButtons()
}
private fun bindButtons() {
requireViewById<Button>(R.id.other_apps).apply {
visibility = View.VISIBLE
setOnClickListener {
this@ControlsFavoritingActivity.onBackPressed()
}
}
requireViewById<Button>(R.id.done).setOnClickListener {
if (component == null) return@setOnClickListener
listOfStructures.forEach {
val favoritesForStorage = it.model.favorites.map { it.build() }
controller.replaceFavoritesForStructure(StructureInfo(component!!, it.structureName,
favoritesForStorage))
}
finishAffinity()
}
}
override fun onDestroy() {
currentUserTracker.stopTracking()
listingController.removeCallback(listingCallback)
super.onDestroy()
}
}
data class StructureContainer(val structureName: CharSequence, val model: ControlsModel)