This repository has been archived by the owner on Nov 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 472
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
7900: For mozilla-mobile/fenix#8765: Add site item widget r=gabrielluong a=NotWoods `WidgetSiteItemView` is used to show a website inside bookmarks, history, collections, and other lists. Has the following API: - `iconView` getter to load favicons into the view - `setText(label, caption)` to set the text shown. If caption is null, the caption text view is hidden and the label is centered. - `addIconOverlay` inserts other views above the `iconView`, such as a checkmark. - `setSecondaryButton(icon, contentDescription, onClickListener)` will show an icon button with the given icon and content description. `onClickListener` is called when the button is clicked. - `removeSecondaryButton` hides the button if it was previously shown by `setSecondaryButton`. Co-authored-by: Tiger Oakes <[email protected]>
- Loading branch information
Showing
9 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
components/ui/widgets/src/main/java/mozilla/components/ui/widgets/WidgetSiteItemView.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* 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.ui.widgets | ||
|
||
import android.content.Context | ||
import android.graphics.drawable.Drawable | ||
import android.util.AttributeSet | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.widget.FrameLayout | ||
import android.widget.ImageButton | ||
import android.widget.ImageView | ||
import android.widget.TextView | ||
import androidx.annotation.DrawableRes | ||
import androidx.annotation.StringRes | ||
import androidx.appcompat.content.res.AppCompatResources.getDrawable | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.core.view.isVisible | ||
|
||
/** | ||
* Shared UI widget for showing a website in a list of websites, | ||
* such as in bookmarks, history, site exceptions, or collections. | ||
*/ | ||
class WidgetSiteItemView @JvmOverloads constructor( | ||
context: Context, | ||
attrs: AttributeSet? = null, | ||
defStyleAttr: Int = 0 | ||
) : ConstraintLayout(context, attrs, defStyleAttr) { | ||
|
||
private val labelView: TextView by lazy { findViewById<TextView>(R.id.label) } | ||
private val captionView: TextView by lazy { findViewById<TextView>(R.id.caption) } | ||
private val iconWrapper: FrameLayout by lazy { findViewById<FrameLayout>(R.id.favicon_wrapper) } | ||
private val secondaryButton: ImageButton by lazy { findViewById<ImageButton>(R.id.secondary_button) } | ||
|
||
/** | ||
* ImageView that should display favicons. | ||
*/ | ||
val iconView: ImageView by lazy { findViewById<ImageView>(R.id.favicon) } | ||
|
||
init { | ||
LayoutInflater.from(context).inflate(R.layout.mozac_widget_site_item, this, true) | ||
} | ||
|
||
/** | ||
* Sets the text displayed inside of the site item view. | ||
* | ||
* @param label Main label text, such as a site title. | ||
* @param caption Sub caption text, such as a URL. If null, the caption is hidden. | ||
*/ | ||
fun setText(label: CharSequence, caption: CharSequence?) { | ||
labelView.text = label | ||
captionView.text = caption | ||
captionView.isVisible = caption != null | ||
} | ||
|
||
/** | ||
* Add a view that will overlay the favicon, such as a checkmark. | ||
*/ | ||
fun addIconOverlay(overlay: View) { | ||
iconWrapper.addView(overlay) | ||
} | ||
|
||
/** | ||
* Add a secondary button, such as an overflow menu. | ||
* | ||
* @param icon Drawable to display in the button. | ||
* @param contentDescription Accessible description of the button's purpose. | ||
* @param onClickListener Listener called when the button is clicked. | ||
*/ | ||
fun setSecondaryButton( | ||
icon: Drawable?, | ||
contentDescription: CharSequence, | ||
onClickListener: (View) -> Unit | ||
) { | ||
secondaryButton.isVisible = true | ||
secondaryButton.setImageDrawable(icon) | ||
secondaryButton.contentDescription = contentDescription | ||
secondaryButton.setOnClickListener(onClickListener) | ||
} | ||
|
||
/** | ||
* Add a secondary button, such as an overflow menu. | ||
* | ||
* @param icon Drawable to display in the button. | ||
* @param contentDescription Accessible description of the button's purpose. | ||
* @param onClickListener Listener called when the button is clicked. | ||
*/ | ||
fun setSecondaryButton( | ||
@DrawableRes icon: Int, | ||
@StringRes contentDescription: Int, | ||
onClickListener: (View) -> Unit | ||
) = setSecondaryButton( | ||
icon = getDrawable(context, icon), | ||
contentDescription = context.getString(contentDescription), | ||
onClickListener = onClickListener | ||
) | ||
|
||
/** | ||
* Removes the secondary button if it was previously set in [setSecondaryButton]. | ||
*/ | ||
fun removeSecondaryButton() { | ||
secondaryButton.isVisible = false | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
components/ui/widgets/src/main/res/layout/mozac_widget_site_item.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<?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/. --> | ||
<androidx.constraintlayout.widget.ConstraintLayout | ||
xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
xmlns:tools="http://schemas.android.com/tools" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:minHeight="@dimen/mozac_widget_site_item_height" | ||
android:background="?android:attr/selectableItemBackground"> | ||
|
||
<FrameLayout | ||
android:id="@+id/favicon_wrapper" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:layout_marginStart="16dp" | ||
android:layout_marginEnd="16dp" | ||
app:layout_constraintHorizontal_chainStyle="spread_inside" | ||
app:layout_constraintTop_toTopOf="parent" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintEnd_toStartOf="@id/label"> | ||
<ImageView | ||
android:id="@+id/favicon" | ||
style="@style/Mozac.Widgets.Favicon" | ||
android:importantForAccessibility="no" | ||
tools:src="@android:drawable/ic_secure" /> | ||
</FrameLayout> | ||
|
||
<TextView | ||
android:id="@+id/label" | ||
style="@style/Mozac.Widgets.SiteItem.Label" | ||
android:layout_width="0dp" | ||
tools:textColor="#20123A" | ||
tools:text="Example site" | ||
app:layout_goneMarginEnd="16dp" | ||
app:layout_constraintTop_toTopOf="parent" | ||
app:layout_constraintBottom_toTopOf="@id/caption" | ||
app:layout_constraintStart_toEndOf="@id/favicon_wrapper" | ||
app:layout_constraintEnd_toStartOf="@id/secondary_button" | ||
app:layout_constraintVertical_chainStyle="packed" /> | ||
|
||
<TextView | ||
android:id="@+id/caption" | ||
style="@style/Mozac.Widgets.SiteItem.Caption" | ||
android:layout_width="0dp" | ||
android:layout_marginTop="2dp" | ||
tools:text="https://example.com/" | ||
tools:textColor="@color/photonLightGrey90" | ||
app:layout_constraintEnd_toEndOf="@id/label" | ||
app:layout_constraintStart_toStartOf="@id/label" | ||
app:layout_constraintTop_toBottomOf="@id/label" | ||
app:layout_constraintBottom_toBottomOf="parent" /> | ||
|
||
<ImageButton | ||
android:id="@+id/secondary_button" | ||
android:layout_width="@dimen/mozac_widget_site_item_secondary_button_size" | ||
android:layout_height="@dimen/mozac_widget_site_item_secondary_button_size" | ||
android:padding="@dimen/mozac_widget_site_item_secondary_button_padding" | ||
android:layout_marginStart="12dp" | ||
android:layout_marginEnd="12dp" | ||
android:background="?android:attr/selectableItemBackgroundBorderless" | ||
android:visibility="gone" | ||
tools:visibility="visible" | ||
tools:src="@drawable/mozac_ic_menu" | ||
tools:ignore="ContentDescription" | ||
tools:tint="#20123A" | ||
app:tint="?attr/mozac_primary_text_color" | ||
app:layout_constraintTop_toTopOf="parent" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintStart_toEndOf="@id/label" | ||
app:layout_constraintEnd_toEndOf="parent" /> | ||
|
||
</androidx.constraintlayout.widget.ConstraintLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
components/ui/widgets/src/test/java/mozilla/components/ui/widgets/WidgetSiteItemViewTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* 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.ui.widgets | ||
|
||
import android.graphics.drawable.Drawable | ||
import android.widget.ImageButton | ||
import android.widget.TextView | ||
import androidx.appcompat.view.ContextThemeWrapper | ||
import androidx.core.view.isGone | ||
import androidx.core.view.isVisible | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import mozilla.components.support.test.mock | ||
import mozilla.components.support.test.robolectric.testContext | ||
import org.junit.Assert.assertEquals | ||
import org.junit.Assert.assertNotNull | ||
import org.junit.Assert.assertTrue | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class WidgetSiteItemViewTest { | ||
|
||
private lateinit var view: WidgetSiteItemView | ||
|
||
@Before | ||
fun setup() { | ||
val context = ContextThemeWrapper(testContext, R.style.Mozac_Widgets_TestTheme) | ||
view = WidgetSiteItemView(context) | ||
} | ||
|
||
@Test | ||
fun `setText hides the caption`() { | ||
val labelView = view.findViewById<TextView>(R.id.label) | ||
val captionView = view.findViewById<TextView>(R.id.caption) | ||
|
||
view.setText(label = "label", caption = null) | ||
assertEquals("label", labelView.text) | ||
assertTrue(captionView.isGone) | ||
|
||
view.setText(label = "Label", caption = "") | ||
assertEquals("Label", labelView.text) | ||
assertEquals("", captionView.text) | ||
assertTrue(captionView.isVisible) | ||
} | ||
|
||
@Test | ||
fun `setSecondaryButton shows the button`() { | ||
val secondaryButton = view.findViewById<ImageButton>(R.id.secondary_button) | ||
val drawable = mock<Drawable>() | ||
var clicked = false | ||
view.setSecondaryButton( | ||
icon = drawable, | ||
contentDescription = "Menu", | ||
onClickListener = { clicked = true } | ||
) | ||
assertTrue(secondaryButton.isVisible) | ||
assertEquals(drawable, secondaryButton.drawable) | ||
assertEquals("Menu", secondaryButton.contentDescription) | ||
|
||
secondaryButton.performClick() | ||
assertTrue(clicked) | ||
} | ||
|
||
@Test | ||
fun `setSecondaryButton with resource IDs shows the button`() { | ||
val secondaryButton = view.findViewById<ImageButton>(R.id.secondary_button) | ||
var clicked = false | ||
view.setSecondaryButton( | ||
icon = R.drawable.mozac_ic_lock, | ||
contentDescription = R.string.mozac_error_lock, | ||
onClickListener = { clicked = true } | ||
) | ||
assertTrue(secondaryButton.isVisible) | ||
assertNotNull(secondaryButton.drawable) | ||
assertEquals("mozac_error_lock", secondaryButton.contentDescription) | ||
|
||
secondaryButton.performClick() | ||
assertTrue(clicked) | ||
} | ||
|
||
@Test | ||
fun `removeSecondaryButton does nothing if set was not called`() { | ||
val secondaryButton = view.findViewById<ImageButton>(R.id.secondary_button) | ||
assertTrue(secondaryButton.isGone) | ||
|
||
view.removeSecondaryButton() | ||
assertTrue(secondaryButton.isGone) | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
components/ui/widgets/src/test/resources/robolectric.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sdk=28 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters