[fenix] For https://github.com/mozilla-mobile/fenix/pull/24455 - Migrate NoCollectionsMessageViewHolder to Compose
parent
d75322cbaf
commit
d2fa53ff1d
@ -0,0 +1,117 @@
|
||||
/* 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 org.mozilla.fenix.compose
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.compose.button.PrimaryButton
|
||||
import org.mozilla.fenix.compose.ext.dashedBorder
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
import org.mozilla.fenix.theme.Theme
|
||||
|
||||
/**
|
||||
* [CollectionsPlaceholder] for displaying a message detailing the collections feature and
|
||||
* allowing users to easily start creating their collection.
|
||||
*
|
||||
* @param showAddToCollectionButton Whether or not the "Add to Collection" button should be shown.
|
||||
* @param onAddTabsToCollectionButtonClick Invoked when the user clicks on the "Add Tabs to Collection" button.
|
||||
* @param onRemovePlaceholderClick Invoked when the user clicks on the close button to remove the Collections
|
||||
* placeholder.
|
||||
*/
|
||||
@Composable
|
||||
fun CollectionsPlaceholder(
|
||||
showAddToCollectionButton: Boolean,
|
||||
onAddTabsToCollectionButtonClick: () -> Unit,
|
||||
onRemovePlaceholderClick: () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.semantics(mergeDescendants = true) {}
|
||||
.dashedBorder(
|
||||
color = FirefoxTheme.colors.borderPrimary,
|
||||
cornerRadius = 8.dp,
|
||||
dashHeight = 2.dp,
|
||||
dashWidth = 4.dp
|
||||
)
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(16.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SectionHeader(
|
||||
text = stringResource(R.string.collections_header),
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
|
||||
IconButton(
|
||||
onClick = onRemovePlaceholderClick,
|
||||
modifier = Modifier.size(20.dp),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_close),
|
||||
contentDescription = stringResource(
|
||||
R.string.remove_home_collection_placeholder_content_description
|
||||
),
|
||||
tint = FirefoxTheme.colors.iconPrimary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
SecondaryText(
|
||||
text = stringResource(R.string.no_collections_description2),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
fontSize = 14.sp
|
||||
)
|
||||
|
||||
if (showAddToCollectionButton) {
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
PrimaryButton(
|
||||
text = stringResource(R.string.tabs_menu_save_to_collection1),
|
||||
icon = painterResource(R.drawable.ic_tab_collection),
|
||||
onClick = onAddTabsToCollectionButtonClick
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
private fun CollectionsPlaceholderPreview() {
|
||||
FirefoxTheme(theme = Theme.getTheme(isPrivate = false)) {
|
||||
Box(Modifier.background(FirefoxTheme.colors.layer1)) {
|
||||
CollectionsPlaceholder(
|
||||
showAddToCollectionButton = true,
|
||||
onAddTabsToCollectionButtonClick = {},
|
||||
onRemovePlaceholderClick = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<?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/. -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke android:width="2dp" android:dashWidth="4dp" android:color="?borderPrimary" android:dashGap="4dp" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
@ -1,69 +0,0 @@
|
||||
<?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"
|
||||
android:id="@+id/no_collections_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/home_item_horizontal_margin"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="@drawable/empty_session_control_background"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_collections_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/collections_header"
|
||||
android:textAppearance="@style/HeaderTextStyle"
|
||||
android:textSize="16sp"
|
||||
app:fontFamily="@font/metropolis_semibold"
|
||||
app:layout_constraintEnd_toStartOf="@id/remove_collection_placeholder"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/remove_collection_placeholder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/remove_home_collection_placeholder_content_description"
|
||||
app:layout_constraintBottom_toBottomOf="@id/no_collections_header"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/no_collections_header"
|
||||
app:srcCompat="@drawable/ic_close" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_collections_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/no_collections_description2"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/textSecondary"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_collections_header" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_tabs_to_collections_button"
|
||||
style="@style/PositiveButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/tabs_menu_save_to_collection1"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_tab_collection"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_collections_description" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,78 +0,0 @@
|
||||
/* 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 org.mozilla.fenix.home.sessioncontrol.viewholders
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.databinding.NoCollectionsMessageBinding
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class NoCollectionsMessageViewHolderTest {
|
||||
|
||||
private lateinit var binding: NoCollectionsMessageBinding
|
||||
private val store: BrowserStore = BrowserStore(
|
||||
initialState = BrowserState(
|
||||
listOf(
|
||||
createTab("https://www.mozilla.org", id = "reader-inactive-tab")
|
||||
)
|
||||
)
|
||||
)
|
||||
private lateinit var lifecycleOwner: LifecycleOwner
|
||||
private lateinit var interactor: CollectionInteractor
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
binding = NoCollectionsMessageBinding.inflate(LayoutInflater.from(testContext))
|
||||
lifecycleOwner = mockk(relaxed = true)
|
||||
interactor = mockk(relaxed = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hide add to collection button when there are no tabs open`() {
|
||||
val noTabsStore = BrowserStore()
|
||||
NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, noTabsStore, interactor)
|
||||
|
||||
assertFalse(binding.addTabsToCollectionsButton.isVisible)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `show add to collection button when there are tabs`() {
|
||||
NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, store, interactor)
|
||||
|
||||
assertTrue(binding.addTabsToCollectionsButton.isVisible)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `call interactor on click`() {
|
||||
NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, store, interactor)
|
||||
|
||||
binding.addTabsToCollectionsButton.performClick()
|
||||
verify { interactor.onAddTabsToCollectionTapped() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hide view and change setting on remove placeholder click`() {
|
||||
NoCollectionsMessageViewHolder(binding.root, lifecycleOwner, store, interactor)
|
||||
|
||||
binding.removeCollectionPlaceholder.performClick()
|
||||
verify {
|
||||
interactor.onRemoveCollectionsPlaceholder()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue