Commit b4adf1e2 authored by MozLando's avatar MozLando
Browse files

Merge #6406

6406: Add api for customizing the ui of the AddonPermissionsAdapter and AddonsManagerAdapter r=psymoon a=Amejia481

Relate Fenix issue https://github.com/mozilla-mobile/fenix/issues/8520

Co-authored-by: default avatarArturo Mejia <arturomejiamarmol@gmail.com>
parents 5131ec9f d31130bb
......@@ -8,16 +8,20 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.feature.addons.R
/**
* An adapter for displaying the permissions of an add-on.
*
* @property permissions The list of [Addon] permissions to display.
* @property permissions The list of [mozilla.components.feature.addons.Addon] permissions to display.
* @property style Indicates how permission items should look like.
*/
class AddonPermissionsAdapter(
private val permissions: List<String>
private val permissions: List<String>,
private val style: Style? = null
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PermissionViewHolder {
val context = parent.context
......@@ -35,7 +39,10 @@ class AddonPermissionsAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder as PermissionViewHolder
val permission = permissions[position]
holder.textView.text = permission
with(holder.textView) {
text = permission
style?.maybeSetItemTextColor(this)
}
}
/**
......@@ -45,4 +52,16 @@ class AddonPermissionsAdapter(
val view: View,
val textView: TextView
) : RecyclerView.ViewHolder(view)
/**
* Allows to customize how permission items should look like.
*/
data class Style(@ColorRes val itemsTextColor: Int? = null) {
internal fun maybeSetItemTextColor(textView: TextView) {
itemsTextColor?.let {
val color = ContextCompat.getColor(textView.context, it)
textView.setTextColor(color)
}
}
}
}
......@@ -13,6 +13,7 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.RatingBar
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.core.content.ContextCompat
......@@ -45,12 +46,14 @@ private const val VIEW_HOLDER_TYPE_ADDON = 2
* @property addonCollectionProvider Provider of AMO collection API.
* @property addonsManagerDelegate Delegate that will provides method for handling the add-on items.
* @property addons The list of add-on based on the AMO store.
* @property style Indicates how items should look like.
*/
@Suppress("TooManyFunctions", "LargeClass")
class AddonsManagerAdapter(
private val addonCollectionProvider: AddonCollectionProvider,
private val addonsManagerDelegate: AddonsManagerAdapterDelegate,
addons: List<Addon>
addons: List<Addon>,
private val style: Style? = null
) : RecyclerView.Adapter<CustomViewHolder>() {
private val scope = CoroutineScope(Dispatchers.IO)
private val items: List<Any>
......@@ -75,7 +78,6 @@ class AddonsManagerAdapter(
val inflater = LayoutInflater.from(context)
val view = inflater.inflate(R.layout.mozac_feature_addons_section_item, parent, false)
val titleView = view.findViewById<TextView>(R.id.title)
return SectionViewHolder(view, titleView)
}
......@@ -140,8 +142,10 @@ class AddonsManagerAdapter(
}
}
private fun bindSection(holder: SectionViewHolder, section: Section) {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal fun bindSection(holder: SectionViewHolder, section: Section) {
holder.titleView.setText(section.title)
style?.maybeSetStatusTextColor(holder.titleView)
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
......@@ -210,6 +214,8 @@ class AddonsManagerAdapter(
}
fetchIcon(addon, holder.iconView)
style?.maybeSetAddonNameTextColor(holder.titleView)
style?.maybeSetAddonSummaryTextColor(holder.summaryView)
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
......@@ -278,10 +284,43 @@ class AddonsManagerAdapter(
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal inner class Section(@StringRes val title: Int)
internal data class Section(@StringRes val title: Int)
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal inner class NotYetSupportedSection(@StringRes val title: Int)
internal data class NotYetSupportedSection(@StringRes val title: Int)
/**
* Allows to customize how items should look like.
*/
data class Style(
@ColorRes
val sectionsTextColor: Int? = null,
@ColorRes
val addonNameTextColor: Int? = null,
@ColorRes
val addonSummaryTextColor: Int? = null
) {
internal fun maybeSetStatusTextColor(textView: TextView) {
sectionsTextColor?.let {
val color = ContextCompat.getColor(textView.context, it)
textView.setTextColor(color)
}
}
internal fun maybeSetAddonNameTextColor(textView: TextView) {
addonNameTextColor?.let {
val color = ContextCompat.getColor(textView.context, it)
textView.setTextColor(color)
}
}
internal fun maybeSetAddonSummaryTextColor(textView: TextView) {
addonSummaryTextColor?.let {
val color = ContextCompat.getColor(textView.context, it)
textView.setTextColor(color)
}
}
}
}
private fun Addon.inUnsupportedSection() = isInstalled() && !isSupported()
......
......@@ -53,17 +53,17 @@
android:id="@+id/add_on_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:layout_marginBottom="2dp"
android:ellipsize="end"
android:maxLines="1"
android:textStyle="bold"
android:textSize="16sp"
tools:text="uBlock Origin" />
<TextView
android:id="@+id/add_on_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textSize="14sp"
tools:text="An efficient blocker: easy on memory and CPU footprint, and yet can load and enforce thousands more filters than other popular blockers out there." />
<LinearLayout
......
......@@ -19,12 +19,13 @@
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
tools:text="Access your data for all websites" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/photonGrey40"
android:background="?android:attr/listDivider"
android:importantForAccessibility="no" />
</LinearLayout>
......@@ -7,6 +7,7 @@ package mozilla.components.feature.addons.amo.mozilla.components.feature.addons.
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
......@@ -146,13 +147,24 @@ class AddonsManagerAdapterTest {
translatableDescription = mapOf("en-US" to "description", "de" to "Beschreibung", "es" to "descripción"),
translatableSummary = mapOf("en-US" to "summary", "de" to "Kurzfassung", "es" to "resumen")
)
val adapter = AddonsManagerAdapter(mock(), addonsManagerAdapterDelegate, emptyList())
whenever(titleView.context).thenReturn(testContext)
whenever(summaryView.context).thenReturn(testContext)
val style = AddonsManagerAdapter.Style(
sectionsTextColor = android.R.color.black,
addonNameTextColor = android.R.color.transparent,
addonSummaryTextColor = android.R.color.white
)
val adapter = AddonsManagerAdapter(mock(), addonsManagerAdapterDelegate, emptyList(), style)
adapter.bindAddon(addonViewHolder, addon)
verify(ratingAccessibleView).setText("4.50/5")
verify(titleView).setText("name")
verify(titleView).setTextColor(ContextCompat.getColor(testContext, style.addonNameTextColor!!))
verify(summaryView).setText("summary")
verify(summaryView).setTextColor(ContextCompat.getColor(testContext, style.addonSummaryTextColor!!))
assertNotNull(addonViewHolder.itemView.tag)
addonViewHolder.itemView.performClick()
......@@ -161,6 +173,24 @@ class AddonsManagerAdapterTest {
verify(addonsManagerAdapterDelegate).onInstallAddonButtonClicked(addon)
}
@Test
fun `bind section`() {
val titleView: TextView = mock()
val addonViewHolder = CustomViewHolder.SectionViewHolder(View(testContext), titleView)
whenever(titleView.context).thenReturn(testContext)
val style = AddonsManagerAdapter.Style(
sectionsTextColor = android.R.color.black
)
val adapter = AddonsManagerAdapter(mock(), mock(), emptyList(), style)
adapter.bindSection(addonViewHolder, Section(R.string.mozac_feature_addons_disabled_section))
verify(titleView).setText(R.string.mozac_feature_addons_disabled_section)
verify(titleView).setTextColor(ContextCompat.getColor(testContext, style.sectionsTextColor!!))
}
@Test
fun `bind add-on with no available translatable name`() {
Locale.setDefault(Locale.ENGLISH)
......
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package mozilla.components.feature.addons.ui
import android.view.View
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.feature.addons.R
import mozilla.components.feature.addons.ui.AddonPermissionsAdapter.PermissionViewHolder
import mozilla.components.feature.addons.ui.AddonPermissionsAdapter.Style
import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.whenever
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.verify
@ExperimentalCoroutinesApi
@RunWith(AndroidJUnit4::class)
class AddonsPermissionsAdapterTest {
@Test
fun `bind permissions`() {
val textView: TextView = mock()
val view = View(testContext)
val permissions = listOf("permission")
val style = Style(itemsTextColor = R.color.photonBlue40)
val viewHolder = PermissionViewHolder(view, textView)
whenever(textView.context).thenReturn(testContext)
val adapter = AddonPermissionsAdapter(permissions, style)
adapter.onBindViewHolder(viewHolder, 0)
verify(textView).text = "permission"
verify(textView).setTextColor(ContextCompat.getColor(testContext, style.itemsTextColor!!))
}
}
......@@ -12,6 +12,9 @@ permalink: /changelog/
* [Gecko](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Gecko.kt)
* [Configuration](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Config.kt)
* **feature-addons**
* Added `AddonPermissionsAdapter.Style` and `AddonsManagerAdapter.Style` classes to allow UI customization.
* **service-accounts-push**
* Fixed a bug where the push subscription was incorrectly cached and caused some `GeneralError`s.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment