For #8765: Use shared list widget in exceptions (#14113)

* For #8765: Add resource for shared list widget

* For #8765: Use shared list widget in exceptions
pull/35/head
Tiger Oakes 4 years ago committed by GitHub
parent ac2d65cc5e
commit bb3fd4eb16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,6 +11,7 @@ import androidx.annotation.StringRes
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.ui.widgets.WidgetSiteItemView
import org.mozilla.fenix.exceptions.viewholders.ExceptionsDeleteButtonViewHolder
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
@ -67,7 +68,7 @@ abstract class ExceptionsAdapter<T : Any>(
ExceptionsHeaderViewHolder.LAYOUT_ID ->
ExceptionsHeaderViewHolder(view, headerDescriptionResource)
ExceptionsListItemViewHolder.LAYOUT_ID ->
ExceptionsListItemViewHolder(view, interactor)
ExceptionsListItemViewHolder(view as WidgetSiteItemView, interactor)
else -> throw IllegalStateException()
}
}

@ -4,39 +4,41 @@
package org.mozilla.fenix.exceptions.viewholders
import android.view.View
import kotlinx.android.synthetic.main.exception_item.*
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.browser.icons.BrowserIcons
import mozilla.components.ui.widgets.WidgetSiteItemView
import org.mozilla.fenix.R
import org.mozilla.fenix.exceptions.ExceptionsInteractor
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.loadIntoView
import org.mozilla.fenix.utils.view.ViewHolder
/**
* View holder for a single website that is exempted from Tracking Protection or Logins.
*/
class ExceptionsListItemViewHolder<T : Any>(
view: View,
private val view: WidgetSiteItemView,
private val interactor: ExceptionsInteractor<T>,
private val icons: BrowserIcons = view.context.components.core.icons
) : ViewHolder(view) {
) : RecyclerView.ViewHolder(view) {
private lateinit var item: T
init {
delete_exception.setOnClickListener {
view.setSecondaryButton(
icon = R.drawable.ic_close,
contentDescription = R.string.history_delete_item
) {
interactor.onDeleteOne(item)
}
}
fun bind(item: T, url: String) {
this.item = item
webAddressView.text = url
icons.loadIntoView(favicon_image, url)
view.setText(label = url, caption = null)
icons.loadIntoView(view.iconView, url)
}
companion object {
const val LAYOUT_ID = R.layout.exception_item
const val LAYOUT_ID = R.layout.site_list_item
}
}

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<mozilla.components.ui.widgets.WidgetSiteItemView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/site_list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

@ -7,6 +7,7 @@
<color name="primary_text_normal_theme">@color/primary_text_dark_theme</color>
<color name="secondary_text_normal_theme">@color/secondary_text_dark_theme</color>
<color name="contrast_text_normal_theme">@color/contrast_text_dark_theme</color>
<color name="caption_text_normal_theme">@color/caption_text_dark_theme</color>
<color name="foundation_normal_theme">@color/foundation_dark_theme</color>
<color name="above_normal_theme">@color/above_dark_theme</color>
<color name="inset_normal_theme">@color/inset_dark_theme</color>

@ -16,6 +16,7 @@
<color name="primary_text_light_theme">#20123A</color>
<color name="secondary_text_light_theme">@color/photonGrey50</color>
<color name="contrast_text_light_theme">@color/primary_text_dark_theme</color>
<color name="caption_text_light_theme">@color/photonLightGrey90</color>
<color name="foundation_light_theme">#F9F9FB</color>
<color name="inset_light_theme">#E0E0E6</color>
<color name="above_light_theme">#FFF</color>
@ -85,6 +86,7 @@
<color name="primary_text_dark_theme">#FBFBFE</color>
<color name="secondary_text_dark_theme">#A7A2B7</color>
<color name="contrast_text_dark_theme">@color/primary_text_dark_theme</color>
<color name="caption_text_dark_theme">@color/photonLightGrey70</color>
<color name="foundation_dark_theme">#1C1B22</color>
<color name="inset_dark_theme">#32313C</color>
<color name="above_dark_theme">#32313C</color>
@ -151,6 +153,7 @@
<color name="primary_text_private_theme">#FBFBFE</color>
<color name="secondary_text_private_theme">#A7A2B7</color>
<color name="contrast_text_private_theme">@color/primary_text_private_theme</color>
<color name="caption_text_private_theme">@color/photonLightGrey70</color>
<color name="foundation_private_theme">#261E4B</color>
<color name="inset_private_theme">@color/photonInk50</color>
<color name="above_private_theme">@color/photonInk50</color>
@ -209,6 +212,7 @@
<color name="primary_text_normal_theme">@color/primary_text_light_theme</color>
<color name="secondary_text_normal_theme">@color/secondary_text_light_theme</color>
<color name="contrast_text_normal_theme">@color/contrast_text_light_theme</color>
<color name="caption_text_normal_theme">@color/caption_text_light_theme</color>
<color name="foundation_normal_theme">@color/foundation_light_theme</color>
<color name="above_normal_theme">@color/above_light_theme</color>
<color name="inset_normal_theme">@color/inset_light_theme</color>

@ -81,6 +81,8 @@
<item name="awesomeBarIndicatorBookmarkColor">@color/search_suggestion_indicator_icon_bookmark_color_normal_theme</item>
<!-- Shared widget colors -->
<item name="mozac_primary_text_color">@color/primary_text_normal_theme</item>
<item name="mozac_caption_text_color">@color/caption_text_normal_theme</item>
<item name="mozac_widget_favicon_background_color">@color/mozac_widget_favicon_background_normal_theme</item>
<item name="mozac_widget_favicon_border_color">@color/mozac_widget_favicon_border_normal_theme</item>
@ -221,6 +223,8 @@
<item name="awesomeBarIndicatorBookmarkColor">@color/search_suggestion_indicator_icon_bookmark_color_dark_theme</item>
<!-- Shared widget colors -->
<item name="mozac_primary_text_color">@color/primary_text_private_theme</item>
<item name="mozac_caption_text_color">@color/caption_text_private_theme</item>
<item name="mozac_widget_favicon_background_color">@color/mozac_widget_favicon_background_private_theme</item>
<item name="mozac_widget_favicon_border_color">@color/mozac_widget_favicon_border_private_theme</item>

@ -5,9 +5,6 @@
package org.mozilla.fenix.exceptions.viewholders
import android.view.View
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.every
@ -18,17 +15,14 @@ import io.mockk.slot
import io.mockk.verify
import mozilla.components.browser.icons.BrowserIcons
import mozilla.components.browser.icons.IconRequest
import mozilla.components.ui.widgets.WidgetSiteItemView
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.exceptions.ExceptionsInteractor
class ExceptionsListItemViewHolderTest {
@MockK private lateinit var view: View
@MockK(relaxUnitFun = true) private lateinit var url: TextView
@MockK(relaxUnitFun = true) private lateinit var deleteButton: ImageButton
@MockK private lateinit var favicon: ImageView
@MockK(relaxed = true) private lateinit var view: WidgetSiteItemView
@MockK private lateinit var icons: BrowserIcons
@MockK private lateinit var interactor: ExceptionsInteractor<Exception>
@ -36,37 +30,34 @@ class ExceptionsListItemViewHolderTest {
fun setup() {
MockKAnnotations.init(this)
every { view.findViewById<TextView>(R.id.webAddressView) } returns url
every { view.findViewById<ImageButton>(R.id.delete_exception) } returns deleteButton
every { view.findViewById<ImageView>(R.id.favicon_image) } returns favicon
every { icons.loadIntoView(favicon, any()) } returns mockk()
every { icons.loadIntoView(view.iconView, any()) } returns mockk()
}
@Test
fun `sets url text and loads favicon - mozilla`() {
ExceptionsListItemViewHolder(view, interactor, icons)
.bind(Exception(), url = "mozilla.org")
verify { url.text = "mozilla.org" }
verify { icons.loadIntoView(favicon, IconRequest("mozilla.org")) }
verify { view.setText(label = "mozilla.org", caption = null) }
verify { icons.loadIntoView(view.iconView, IconRequest("mozilla.org")) }
}
@Test
fun `sets url text and loads favicon - example`() {
ExceptionsListItemViewHolder(view, interactor, icons)
.bind(Exception(), url = "https://example.com/icon.svg")
verify { url.text = "https://example.com/icon.svg" }
verify { icons.loadIntoView(favicon, IconRequest("https://example.com/icon.svg")) }
verify { view.setText(label = "https://example.com/icon.svg", caption = null) }
verify { icons.loadIntoView(view.iconView, IconRequest("https://example.com/icon.svg")) }
}
@Test
fun `delete button calls interactor`() {
val slot = slot<View.OnClickListener>()
val slot = slot<(View) -> Unit>()
val exception = Exception()
every { deleteButton.setOnClickListener(capture(slot)) } just Runs
every { view.setSecondaryButton(any(), any<Int>(), capture(slot)) } just Runs
ExceptionsListItemViewHolder(view, interactor, icons).bind(exception, url = "mozilla.org")
every { interactor.onDeleteOne(exception) } just Runs
slot.captured.onClick(mockk())
slot.captured.invoke(mockk())
verify { interactor.onDeleteOne(exception) }
}

Loading…
Cancel
Save