diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 1fe967b4750d4..5458676e1061d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -646,16 +646,17 @@
android:label="Controls Providers"
android:theme="@style/Theme.ControlsManagement"
android:showForAllUsers="true"
+ android:clearTaskOnLaunch="true"
android:excludeFromRecents="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
android:visibleToInstantApps="true">
diff --git a/packages/SystemUI/res-keyguard/layout/controls_management.xml b/packages/SystemUI/res-keyguard/layout/controls_management.xml
deleted file mode 100644
index 8330258e24569..0000000000000
--- a/packages/SystemUI/res-keyguard/layout/controls_management.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/controls_zone_header.xml b/packages/SystemUI/res-keyguard/layout/controls_zone_header.xml
new file mode 100644
index 0000000000000..7b43a0315c106
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/controls_zone_header.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index 68c824698b2d4..823bbcd6e68c6 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -72,8 +72,8 @@
diff --git a/packages/SystemUI/res/layout/controls_management.xml b/packages/SystemUI/res/layout/controls_management.xml
new file mode 100644
index 0000000000000..a7379bedebefe
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_management.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_management_apps.xml b/packages/SystemUI/res/layout/controls_management_apps.xml
new file mode 100644
index 0000000000000..2bab433d21f35
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_management_apps.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_management_favorites.xml b/packages/SystemUI/res/layout/controls_management_favorites.xml
new file mode 100644
index 0000000000000..a36dd1247a04e
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_management_favorites.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index 40b2476941c22..2cd9505b8fe40 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -1,3 +1,18 @@
+
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
index 53841e2f144b8..49a16d892ef40 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
@@ -20,6 +20,6 @@ import android.service.controls.Control
data class ControlStatus(
val control: Control,
- val favorite: Boolean,
+ var favorite: Boolean,
val removed: Boolean = false
)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index b3ba2b22f6df9..fce504120b624 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -26,10 +26,18 @@ interface ControlsController : UserAwareController {
val available: Boolean
fun getFavoriteControls(): List
- fun loadForComponent(componentName: ComponentName, callback: (List) -> Unit)
+ fun loadForComponent(
+ componentName: ComponentName,
+ callback: (List, List) -> Unit
+ )
+
fun subscribeToFavorites()
fun changeFavoriteStatus(controlInfo: ControlInfo, state: Boolean)
- fun countFavoritesForComponent(componentName: ComponentName): Int = 0
+ fun replaceFavoritesForComponent(componentName: ComponentName, favorites: List)
+
+ fun getFavoritesForComponent(componentName: ComponentName): List
+ fun countFavoritesForComponent(componentName: ComponentName): Int
+
fun unsubscribe()
fun action(controlInfo: ControlInfo, action: ControlAction)
fun refreshStatus(componentName: ComponentName, control: Control)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 7de1557ebc65d..e611197b78ae8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -70,9 +70,10 @@ class ControlsControllerImpl @Inject constructor (
}
// Map of map: ComponentName -> (String -> ControlInfo).
- // Only for current user
+ //
@GuardedBy("currentFavorites")
- private val currentFavorites = ArrayMap>()
+ private val currentFavorites = ArrayMap>()
+ .withDefault { mutableListOf() }
private var userChanging: Boolean = true
@@ -180,15 +181,14 @@ class ControlsControllerImpl @Inject constructor (
val infos = persistenceWrapper.readFavorites()
synchronized(currentFavorites) {
infos.forEach {
- currentFavorites.getOrPut(it.component, { ArrayMap() })
- .put(it.controlId, it)
+ currentFavorites.getOrPut(it.component, { mutableListOf() }).add(it)
}
}
}
override fun loadForComponent(
componentName: ComponentName,
- callback: (List) -> Unit
+ callback: (List, List) -> Unit
) {
if (!confirmAvailability()) {
if (userChanging) {
@@ -200,29 +200,34 @@ class ControlsControllerImpl @Inject constructor (
TimeUnit.MILLISECONDS
)
} else {
- callback(emptyList())
+ callback(emptyList(), emptyList())
}
return
}
bindingController.bindAndLoad(componentName) {
synchronized(currentFavorites) {
- val favoritesForComponentKeys: Set =
- currentFavorites.get(componentName)?.keys ?: emptySet()
- val changed = updateFavoritesLocked(componentName, it)
+ val favoritesForComponentKeys: List =
+ currentFavorites.getValue(componentName).map { it.controlId }
+ val changed = updateFavoritesLocked(componentName, it, favoritesForComponentKeys)
if (changed) {
persistenceWrapper.storeFavorites(favoritesAsListLocked())
}
- val removed = findRemovedLocked(favoritesForComponentKeys, it)
- callback(removed.map { currentFavorites.getValue(componentName).getValue(it) }
- .map(::createRemovedStatus) +
- it.map { ControlStatus(it, it.controlId in favoritesForComponentKeys) })
+ val removed = findRemovedLocked(favoritesForComponentKeys.toSet(), it)
+ val controlsWithFavorite =
+ it.map { ControlStatus(it, it.controlId in favoritesForComponentKeys) }
+ callback(
+ currentFavorites.getValue(componentName)
+ .filter { it.controlId in removed }
+ .map(::createRemovedStatus) + controlsWithFavorite,
+ favoritesForComponentKeys
+ )
}
}
}
private fun createRemovedStatus(controlInfo: ControlInfo): ControlStatus {
val intent = Intent(context, ControlsFavoritingActivity::class.java).apply {
- putExtra(ControlsFavoritingActivity.EXTRA_COMPONENT, controlInfo.component)
+ putExtra(Intent.EXTRA_COMPONENT_NAME, controlInfo.component)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP
}
val pendingIntent = PendingIntent.getActivity(context,
@@ -243,17 +248,24 @@ class ControlsControllerImpl @Inject constructor (
}
@GuardedBy("currentFavorites")
- private fun updateFavoritesLocked(componentName: ComponentName, list: List): Boolean {
- val favorites = currentFavorites.get(componentName) ?: mutableMapOf()
- val favoriteKeys = favorites.keys
+ private fun updateFavoritesLocked(
+ componentName: ComponentName,
+ list: List,
+ favoriteKeys: List
+ ): Boolean {
+ val favorites = currentFavorites.get(componentName) ?: mutableListOf()
if (favoriteKeys.isEmpty()) return false // early return
var changed = false
- list.forEach {
- if (it.controlId in favoriteKeys) {
- val value = favorites.getValue(it.controlId)
- if (value.controlTitle != it.title || value.deviceType != it.deviceType) {
- favorites[it.controlId] = value.copy(controlTitle = it.title,
- deviceType = it.deviceType)
+ list.forEach { control ->
+ if (control.controlId in favoriteKeys) {
+ val index = favorites.indexOfFirst { it.controlId == control.controlId }
+ val value = favorites[index]
+ if (value.controlTitle != control.title ||
+ value.deviceType != control.deviceType) {
+ favorites[index] = value.copy(
+ controlTitle = control.title,
+ deviceType = control.deviceType
+ )
changed = true
}
}
@@ -263,14 +275,14 @@ class ControlsControllerImpl @Inject constructor (
@GuardedBy("currentFavorites")
private fun favoritesAsListLocked(): List {
- return currentFavorites.flatMap { it.value.values }
+ return currentFavorites.flatMap { it.value }
}
override fun subscribeToFavorites() {
if (!confirmAvailability()) return
// Make a copy of the favorites list
val favorites = synchronized(currentFavorites) {
- currentFavorites.flatMap { it.value.values.toList() }
+ currentFavorites.flatMap { it.value }
}
bindingController.subscribe(favorites)
}
@@ -286,22 +298,19 @@ class ControlsControllerImpl @Inject constructor (
val listOfControls = synchronized(currentFavorites) {
if (state) {
if (controlInfo.component !in currentFavorites) {
- currentFavorites.put(controlInfo.component, ArrayMap())
+ currentFavorites.put(controlInfo.component, mutableListOf())
changed = true
}
val controlsForComponent = currentFavorites.getValue(controlInfo.component)
- if (controlInfo.controlId !in controlsForComponent) {
- controlsForComponent.put(controlInfo.controlId, controlInfo)
+ if (controlsForComponent.firstOrNull {
+ it.controlId == controlInfo.controlId
+ } == null) {
+ controlsForComponent.add(controlInfo)
changed = true
- } else {
- if (controlsForComponent.getValue(controlInfo.controlId) != controlInfo) {
- controlsForComponent.put(controlInfo.controlId, controlInfo)
- changed = true
- }
}
} else {
changed = currentFavorites.get(controlInfo.component)
- ?.remove(controlInfo.controlId) != null
+ ?.remove(controlInfo) != null
}
favoritesAsListLocked()
}
@@ -310,6 +319,19 @@ class ControlsControllerImpl @Inject constructor (
}
}
+ override fun replaceFavoritesForComponent(
+ componentName: ComponentName,
+ favorites: List
+ ) {
+ if (!confirmAvailability()) return
+ val filtered = favorites.filter { it.component == componentName }
+ val listOfControls = synchronized(currentFavorites) {
+ currentFavorites.put(componentName, filtered.toMutableList())
+ favoritesAsListLocked()
+ }
+ persistenceWrapper.storeFavorites(listOfControls)
+ }
+
override fun refreshStatus(componentName: ComponentName, control: Control) {
if (!confirmAvailability()) {
Log.d(TAG, "Controls not available")
@@ -317,7 +339,13 @@ class ControlsControllerImpl @Inject constructor (
}
executor.execute {
synchronized(currentFavorites) {
- val changed = updateFavoritesLocked(componentName, listOf(control))
+ val favoriteKeysForComponent =
+ currentFavorites.get(componentName)?.map { it.controlId } ?: emptyList()
+ val changed = updateFavoritesLocked(
+ componentName,
+ listOf(control),
+ favoriteKeysForComponent
+ )
if (changed) {
persistenceWrapper.storeFavorites(favoritesAsListLocked())
}
@@ -361,6 +389,12 @@ class ControlsControllerImpl @Inject constructor (
}
}
+ override fun getFavoritesForComponent(componentName: ComponentName): List {
+ return synchronized(currentFavorites) {
+ currentFavorites.get(componentName) ?: emptyList()
+ }
+ }
+
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array) {
pw.println("ControlsController state:")
pw.println(" Available: $available")
@@ -368,10 +402,8 @@ class ControlsControllerImpl @Inject constructor (
pw.println(" Current user: ${currentUser.identifier}")
pw.println(" Favorites:")
synchronized(currentFavorites) {
- currentFavorites.forEach {
- it.value.forEach {
- pw.println(" ${it.value}")
- }
+ favoritesAsListLocked().forEach {
+ pw.println(" ${ it }")
}
}
pw.println(bindingController.toString())
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
index b12243964fc18..89caaceebb5cd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
@@ -29,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.android.settingslib.applications.DefaultAppInfo
import com.android.settingslib.widget.CandidateInfo
import com.android.systemui.R
+import java.text.Collator
import java.util.concurrent.Executor
/**
@@ -44,23 +45,27 @@ import java.util.concurrent.Executor
* @param onAppSelected a callback to indicate that an app has been selected in the list.
*/
class AppAdapter(
+ backgroundExecutor: Executor,
uiExecutor: Executor,
lifecycle: Lifecycle,
controlsListingController: ControlsListingController,
private val layoutInflater: LayoutInflater,
private val onAppSelected: (ComponentName?) -> Unit = {},
- private val favoritesRenderer: FavoritesRenderer
+ private val favoritesRenderer: FavoritesRenderer,
+ private val resources: Resources
) : RecyclerView.Adapter() {
private var listOfServices = emptyList()
private val callback = object : ControlsListingController.ControlsListingCallback {
override fun onServicesUpdated(list: List) {
- uiExecutor.execute {
- listOfServices = list.sortedBy {
- it.loadLabel().toString()
+ backgroundExecutor.execute {
+ val collator = Collator.getInstance(resources.getConfiguration().locale)
+ val localeComparator = compareBy(collator) {
+ it.loadLabel()
}
- notifyDataSetChanged()
+ listOfServices = list.sortedWith(localeComparator)
+ uiExecutor.execute(::notifyDataSetChanged)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 65dcc2b193d5e..d3cabe67790e1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -25,101 +25,150 @@ import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
+import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.R
-import com.android.systemui.controls.ControlStatus
-import com.android.systemui.controls.controller.ControlInfo
import com.android.systemui.controls.ui.RenderInfo
+private typealias ModelFavoriteChanger = (String, Boolean) -> Unit
+
/**
* Adapter for binding [Control] information to views.
*
+ * The model for this adapter is provided by a [FavoriteModel] that is set using
+ * [changeFavoritesModel]. This allows for updating the model if there's a reload.
+ *
* @param layoutInflater an inflater for the views in the containing [RecyclerView]
- * @param favoriteCallback a callback to be called when the favorite status of a [Control] is
- * changed. The callback will take a [ControlInfo.Builder] that's
- * pre-populated with the [Control] information and the new favorite
- * status.
+ * @param onlyFavorites set to true to only display favorites instead of all controls
*/
class ControlAdapter(
private val layoutInflater: LayoutInflater,
- private val favoriteCallback: (ControlInfo.Builder, Boolean) -> Unit
-) : RecyclerView.Adapter() {
+ private val onlyFavorites: Boolean = false
+) : RecyclerView.Adapter() {
- var listOfControls = emptyList()
-
- override fun onCreateViewHolder(parent: ViewGroup, i: Int): Holder {
- return Holder(layoutInflater.inflate(R.layout.controls_base_item, parent, false).apply {
- layoutParams.apply {
- width = ViewGroup.LayoutParams.MATCH_PARENT
- }
- elevation = 15f
- })
+ companion object {
+ private const val TYPE_ZONE = 0
+ private const val TYPE_CONTROL = 1
}
- override fun getItemCount() = listOfControls.size
+ val spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
+ override fun getSpanSize(position: Int): Int {
+ return if (getItemViewType(position) == TYPE_ZONE) 2 else 1
+ }
+ }
+
+ var modelList: List = emptyList()
+ private var favoritesModel: FavoriteModel? = null
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
+ return when (viewType) {
+ TYPE_CONTROL -> {
+ ControlHolder(
+ layoutInflater.inflate(R.layout.controls_base_item, parent, false).apply {
+ layoutParams.apply {
+ width = ViewGroup.LayoutParams.MATCH_PARENT
+ }
+ elevation = 15f
+ },
+ { id, favorite ->
+ favoritesModel?.changeFavoriteStatus(id, favorite)
+ })
+ }
+ TYPE_ZONE -> {
+ ZoneHolder(layoutInflater.inflate(R.layout.controls_zone_header, parent, false))
+ }
+ else -> throw IllegalStateException("Wrong viewType: $viewType")
+ }
+ }
+
+ fun changeFavoritesModel(favoritesModel: FavoriteModel) {
+ this.favoritesModel = favoritesModel
+ if (onlyFavorites) {
+ modelList = favoritesModel.favorites
+ } else {
+ modelList = favoritesModel.all
+ }
+ notifyDataSetChanged()
+ }
+
+ override fun getItemCount() = modelList.size
override fun onBindViewHolder(holder: Holder, index: Int) {
- holder.bindData(listOfControls[index], favoriteCallback)
+ holder.bindData(modelList[index])
}
+ override fun getItemViewType(position: Int): Int {
+ return when (modelList[position]) {
+ is ZoneNameWrapper -> TYPE_ZONE
+ is ControlWrapper -> TYPE_CONTROL
+ }
+ }
+}
+
+/**
+ * Holder for binding views in the [RecyclerView]-
+ * @param view the [View] for this [Holder]
+ */
+sealed class Holder(view: View) : RecyclerView.ViewHolder(view) {
+
/**
- * Holder for binding views in the [RecyclerView]-
+ * Bind the data from the model into the view
*/
- class Holder(view: View) : RecyclerView.ViewHolder(view) {
- private val icon: ImageView = itemView.requireViewById(R.id.icon)
- private val title: TextView = itemView.requireViewById(R.id.title)
- private val subtitle: TextView = itemView.requireViewById(R.id.subtitle)
- private val removed: TextView = itemView.requireViewById(R.id.status)
- private val favorite: CheckBox = itemView.requireViewById(R.id.favorite).apply {
- visibility = View.VISIBLE
- }
+ abstract fun bindData(wrapper: ElementWrapper)
+}
- /**
- * Bind data to the view
- * @param data information about the [Control]
- * @param callback a callback to be called when the favorite status of the [Control] is
- * changed. The callback will take a [ControlInfo.Builder] that's
- * pre-populated with the [Control] information and the new favorite status.
- */
- fun bindData(data: ControlStatus, callback: (ControlInfo.Builder, Boolean) -> Unit) {
- val renderInfo = getRenderInfo(data.control.deviceType, data.favorite)
- title.text = data.control.title
- subtitle.text = data.control.subtitle
- favorite.isChecked = data.favorite
- removed.text = if (data.removed) "Removed" else ""
- favorite.setOnClickListener {
- val infoBuilder = ControlInfo.Builder().apply {
- controlId = data.control.controlId
- controlTitle = data.control.title
- deviceType = data.control.deviceType
- }
- callback(infoBuilder, favorite.isChecked)
- }
- itemView.setOnClickListener {
- favorite.performClick()
- }
- applyRenderInfo(renderInfo)
- }
+/**
+ * Holder for using with [ZoneNameWrapper] to display names of zones.
+ */
+private class ZoneHolder(view: View) : Holder(view) {
+ private val zone: TextView = itemView as TextView
- private fun getRenderInfo(
- @DeviceTypes.DeviceType deviceType: Int,
- favorite: Boolean
- ): RenderInfo {
- return RenderInfo.lookup(deviceType, favorite)
- }
+ override fun bindData(wrapper: ElementWrapper) {
+ wrapper as ZoneNameWrapper
+ zone.text = wrapper.zoneName
+ }
+}
- private fun applyRenderInfo(ri: RenderInfo) {
- val context = itemView.context
- val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
-
- icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId))
- icon.setImageTintList(fg)
- }
+/**
+ * Holder for using with [ControlWrapper] to display names of zones.
+ * @param favoriteCallback this callback will be called whenever the favorite state of the
+ * [Control] this view represents changes.
+ */
+private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChanger) : Holder(view) {
+ private val icon: ImageView = itemView.requireViewById(R.id.icon)
+ private val title: TextView = itemView.requireViewById(R.id.title)
+ private val subtitle: TextView = itemView.requireViewById(R.id.subtitle)
+ private val removed: TextView = itemView.requireViewById(R.id.status)
+ private val favorite: CheckBox = itemView.requireViewById(R.id.favorite).apply {
+ visibility = View.VISIBLE
}
- fun setItems(list: List) {
- listOfControls = list
- notifyDataSetChanged()
+ override fun bindData(wrapper: ElementWrapper) {
+ wrapper as ControlWrapper
+ val data = wrapper.controlStatus
+ val renderInfo = getRenderInfo(data.control.deviceType)
+ title.text = data.control.title
+ subtitle.text = data.control.subtitle
+ favorite.isChecked = data.favorite
+ removed.text = if (data.removed) "Removed" else ""
+ favorite.setOnClickListener {
+ favoriteCallback(data.control.controlId, favorite.isChecked)
+ }
+ applyRenderInfo(renderInfo)
+ }
+
+ private fun getRenderInfo(
+ @DeviceTypes.DeviceType deviceType: Int
+ ): RenderInfo {
+ return RenderInfo.lookup(deviceType, true)
+ }
+
+ private fun applyRenderInfo(ri: RenderInfo) {
+ val context = itemView.context
+ val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
+
+ icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId))
+ icon.setImageTintList(fg)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index be52583444927..1e52371481880 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -18,10 +18,14 @@ package com.android.systemui.controls.management
import android.app.Activity
import android.content.ComponentName
+import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
+import android.view.ViewStub
+import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
@@ -41,13 +45,36 @@ class ControlsFavoritingActivity @Inject constructor(
companion object {
private const val TAG = "ControlsFavoritingActivity"
const val EXTRA_APP = "extra_app_label"
- const val EXTRA_COMPONENT = "extra_component"
}
- private lateinit var recyclerView: RecyclerView
- private lateinit var adapter: ControlAdapter
+ private lateinit var recyclerViewAll: RecyclerView
+ private lateinit var adapterAll: ControlAdapter
+ private lateinit var recyclerViewFavorites: RecyclerView
+ private lateinit var adapterFavorites: ControlAdapter
private var component: ComponentName? = null
+ private var currentModel: FavoriteModel? = null
+ private var itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(
+ /* dragDirs */ ItemTouchHelper.UP
+ or ItemTouchHelper.DOWN
+ or ItemTouchHelper.LEFT
+ or ItemTouchHelper.RIGHT,
+ /* swipeDirs */0
+ ) {
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean {
+ return currentModel?.onMoveItem(
+ viewHolder.adapterPosition, target.adapterPosition) != null
+ }
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
+
+ override fun isItemViewSwipeEnabled() = false
+ }
+
private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
private val startingUser = controller.currentUserId
@@ -62,41 +89,77 @@ class ControlsFavoritingActivity @Inject constructor(
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.controls_management)
+ requireViewById(R.id.stub).apply {
+ layoutResource = R.layout.controls_management_favorites
+ inflate()
+ }
val app = intent.getCharSequenceExtra(EXTRA_APP)
- component = intent.getParcelableExtra(EXTRA_COMPONENT)
+ component = intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME)
- // If we have no component name, there's not much we can do.
- val callback = component?.let {
- { infoBuilder: ControlInfo.Builder, status: Boolean ->
- infoBuilder.componentName = it
- controller.changeFavoriteStatus(infoBuilder.build(), status)
- }
- } ?: { _, _ -> Unit }
-
- recyclerView = requireViewById(R.id.list)
- adapter = ControlAdapter(LayoutInflater.from(applicationContext), callback)
- recyclerView.adapter = adapter
- recyclerView.layoutManager = GridLayoutManager(applicationContext, 2)
- val margin = resources.getDimensionPixelSize(R.dimen.controls_card_margin)
- recyclerView.addItemDecoration(MarginItemDecorator(margin, margin))
+ setUpRecyclerViews()
requireViewById(R.id.title).text = app?.let { it }
?: resources.getText(R.string.controls_favorite_default_title)
requireViewById(R.id.subtitle).text =
resources.getText(R.string.controls_favorite_subtitle)
- currentUserTracker.startTracking()
- }
+ requireViewById