Add tests for some of collection creation
parent
b5d03ff62d
commit
6317eea690
|
@ -0,0 +1,96 @@
|
||||||
|
/* 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.collections
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import mozilla.components.support.ktx.android.content.getDrawableWithTint
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates views in [R.id.bottom_button_bar_layout] for collection creation.
|
||||||
|
*/
|
||||||
|
class CollectionCreationBottomBarView(
|
||||||
|
private val interactor: CollectionCreationInteractor,
|
||||||
|
private val layout: ViewGroup,
|
||||||
|
private val iconButton: ImageButton,
|
||||||
|
private val textView: TextView,
|
||||||
|
private val saveButton: Button
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun update(step: SaveCollectionStep, state: CollectionCreationState) {
|
||||||
|
when (step) {
|
||||||
|
SaveCollectionStep.SelectTabs -> updateForSelectTabs(state)
|
||||||
|
SaveCollectionStep.SelectCollection -> updateForSelectCollection()
|
||||||
|
else -> { /* noop */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateForSelectTabs(state: CollectionCreationState) {
|
||||||
|
layout.setOnClickListener(null)
|
||||||
|
layout.isClickable = false
|
||||||
|
|
||||||
|
iconButton.apply {
|
||||||
|
val drawable = context.getDrawableWithTint(
|
||||||
|
R.drawable.ic_close,
|
||||||
|
ContextCompat.getColor(context, R.color.photonWhite)
|
||||||
|
)
|
||||||
|
setImageDrawable(drawable)
|
||||||
|
contentDescription = context.getString(R.string.create_collection_close)
|
||||||
|
importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
||||||
|
setOnClickListener { interactor.close() }
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.apply {
|
||||||
|
text = if (state.selectedTabs.isEmpty()) {
|
||||||
|
context.getString(R.string.create_collection_save_to_collection_empty)
|
||||||
|
} else {
|
||||||
|
context.getString(
|
||||||
|
if (state.selectedTabs.size == 1)
|
||||||
|
R.string.create_collection_save_to_collection_tab_selected else
|
||||||
|
R.string.create_collection_save_to_collection_tabs_selected,
|
||||||
|
state.selectedTabs.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveButton.apply {
|
||||||
|
setOnClickListener {
|
||||||
|
if (state.selectedTabCollection != null) {
|
||||||
|
interactor.selectCollection(
|
||||||
|
collection = state.selectedTabCollection,
|
||||||
|
tabs = state.selectedTabs.toList()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
interactor.saveTabsToCollection(tabs = state.selectedTabs.toList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isVisible = state.selectedTabs.isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateForSelectCollection() {
|
||||||
|
saveButton.visibility = View.GONE
|
||||||
|
|
||||||
|
textView.text =
|
||||||
|
textView.context.getString(R.string.create_collection_add_new_collection)
|
||||||
|
|
||||||
|
iconButton.apply {
|
||||||
|
val drawable = context.getDrawableWithTint(
|
||||||
|
R.drawable.ic_new,
|
||||||
|
ContextCompat.getColor(context, R.color.photonWhite)
|
||||||
|
)
|
||||||
|
setImageDrawable(drawable)
|
||||||
|
contentDescription = null
|
||||||
|
importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
||||||
|
setOnClickListener { interactor.addNewCollection() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ class CollectionCreationStore(
|
||||||
*
|
*
|
||||||
* TODO refactor [CollectionCreationState] into a sealed class with four implementations, each
|
* TODO refactor [CollectionCreationState] into a sealed class with four implementations, each
|
||||||
* replacing a [SaveCollectionStep] value. These will not need null / emptyCollection default
|
* replacing a [SaveCollectionStep] value. These will not need null / emptyCollection default
|
||||||
* values. Handle changes bebtween these state changes internally, here and in the controller,
|
* values. Handle changes between these state changes internally, here and in the controller,
|
||||||
* instead of exposing [StepChanged], which currently acts as a setter.
|
* instead of exposing [StepChanged], which currently acts as a setter.
|
||||||
*/
|
*/
|
||||||
enum class SaveCollectionStep {
|
enum class SaveCollectionStep {
|
||||||
|
|
|
@ -11,28 +11,14 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
|
||||||
import androidx.constraintlayout.widget.ConstraintSet
|
import androidx.constraintlayout.widget.ConstraintSet
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.transition.AutoTransition
|
import androidx.transition.AutoTransition
|
||||||
import androidx.transition.Transition
|
import androidx.transition.Transition
|
||||||
import androidx.transition.TransitionManager
|
import androidx.transition.TransitionManager
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.back_button
|
import kotlinx.android.synthetic.main.component_collection_creation.*
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.collection_constraint_layout
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.name_collection_edittext
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.save_button
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.select_all_button
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.bottom_bar_icon_button
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.bottom_bar_text
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.bottom_button_bar_layout
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.collection_constraint_layout
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.collections_list
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.name_collection_edittext
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.select_all_button
|
|
||||||
import kotlinx.android.synthetic.main.component_collection_creation.view.tab_list
|
|
||||||
import mozilla.components.browser.state.state.MediaState
|
import mozilla.components.browser.state.state.MediaState
|
||||||
import mozilla.components.feature.tab.collections.TabCollection
|
import mozilla.components.feature.tab.collections.TabCollection
|
||||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||||
|
@ -43,14 +29,21 @@ import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.toShortUrl
|
import org.mozilla.fenix.ext.toShortUrl
|
||||||
import org.mozilla.fenix.home.Tab
|
import org.mozilla.fenix.home.Tab
|
||||||
|
|
||||||
@SuppressWarnings("LargeClass")
|
|
||||||
class CollectionCreationView(
|
class CollectionCreationView(
|
||||||
override val containerView: ViewGroup,
|
container: ViewGroup,
|
||||||
private val interactor: CollectionCreationInteractor
|
private val interactor: CollectionCreationInteractor
|
||||||
) : LayoutContainer {
|
) : LayoutContainer {
|
||||||
val view: View = LayoutInflater.from(containerView.context)
|
|
||||||
.inflate(R.layout.component_collection_creation, containerView, true)
|
|
||||||
|
|
||||||
|
override val containerView: View = LayoutInflater.from(container.context)
|
||||||
|
.inflate(R.layout.component_collection_creation, container, true)
|
||||||
|
|
||||||
|
private val bottomBarView = CollectionCreationBottomBarView(
|
||||||
|
interactor = interactor,
|
||||||
|
layout = bottom_button_bar_layout,
|
||||||
|
iconButton = bottom_bar_icon_button,
|
||||||
|
textView = bottom_bar_text,
|
||||||
|
saveButton = save_button
|
||||||
|
)
|
||||||
private val collectionCreationTabListAdapter = CollectionCreationTabListAdapter(interactor)
|
private val collectionCreationTabListAdapter = CollectionCreationTabListAdapter(interactor)
|
||||||
private val collectionSaveListAdapter = SaveCollectionListAdapter(interactor)
|
private val collectionSaveListAdapter = SaveCollectionListAdapter(interactor)
|
||||||
private val selectTabsConstraints = ConstraintSet()
|
private val selectTabsConstraints = ConstraintSet()
|
||||||
|
@ -67,8 +60,8 @@ class CollectionCreationView(
|
||||||
transition.duration = TRANSITION_DURATION
|
transition.duration = TRANSITION_DURATION
|
||||||
transition.excludeTarget(back_button, true)
|
transition.excludeTarget(back_button, true)
|
||||||
|
|
||||||
view.name_collection_edittext.filters += InputFilter.LengthFilter(COLLECTION_NAME_MAX_LENGTH)
|
name_collection_edittext.filters += InputFilter.LengthFilter(COLLECTION_NAME_MAX_LENGTH)
|
||||||
view.name_collection_edittext.setOnEditorActionListener { view, actionId, _ ->
|
name_collection_edittext.setOnEditorActionListener { view, actionId, _ ->
|
||||||
val text = view.text.toString()
|
val text = view.text.toString()
|
||||||
if (actionId == EditorInfo.IME_ACTION_DONE && text.isNotBlank()) {
|
if (actionId == EditorInfo.IME_ACTION_DONE && text.isNotBlank()) {
|
||||||
when (step) {
|
when (step) {
|
||||||
|
@ -82,13 +75,13 @@ class CollectionCreationView(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
view.tab_list.run {
|
tab_list.run {
|
||||||
adapter = collectionCreationTabListAdapter
|
adapter = collectionCreationTabListAdapter
|
||||||
itemAnimator = null
|
itemAnimator = null
|
||||||
layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true)
|
layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
view.collections_list.run {
|
collections_list.run {
|
||||||
adapter = collectionSaveListAdapter
|
adapter = collectionSaveListAdapter
|
||||||
layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true)
|
layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true)
|
||||||
}
|
}
|
||||||
|
@ -98,6 +91,7 @@ class CollectionCreationView(
|
||||||
|
|
||||||
cacheState(state)
|
cacheState(state)
|
||||||
|
|
||||||
|
bottomBarView.update(step, state)
|
||||||
when (step) {
|
when (step) {
|
||||||
SaveCollectionStep.SelectTabs -> updateForSelectTabs(state)
|
SaveCollectionStep.SelectTabs -> updateForSelectTabs(state)
|
||||||
SaveCollectionStep.SelectCollection -> updateForSelectCollection()
|
SaveCollectionStep.SelectCollection -> updateForSelectCollection()
|
||||||
|
@ -114,148 +108,90 @@ class CollectionCreationView(
|
||||||
selectedCollection = state.selectedTabCollection
|
selectedCollection = state.selectedTabCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ComplexMethod")
|
|
||||||
private fun updateForSelectTabs(state: CollectionCreationState) {
|
private fun updateForSelectTabs(state: CollectionCreationState) {
|
||||||
view.context.components.analytics.metrics.track(Event.CollectionTabSelectOpened)
|
containerView.context.components.analytics.metrics.track(Event.CollectionTabSelectOpened)
|
||||||
|
|
||||||
view.tab_list.isClickable = true
|
tab_list.isClickable = true
|
||||||
|
|
||||||
back_button.setOnClickListener {
|
back_button.apply {
|
||||||
interactor.onBackPressed(SaveCollectionStep.SelectTabs)
|
text = context.getString(R.string.create_collection_select_tabs)
|
||||||
}
|
setOnClickListener {
|
||||||
val allSelected = state.selectedTabs.size == state.tabs.size
|
interactor.onBackPressed(SaveCollectionStep.SelectTabs)
|
||||||
select_all_button.text =
|
|
||||||
if (allSelected) view.context.getString(R.string.create_collection_deselect_all)
|
|
||||||
else view.context.getString(R.string.create_collection_select_all)
|
|
||||||
|
|
||||||
view.select_all_button.setOnClickListener {
|
|
||||||
if (allSelected) interactor.deselectAllTapped()
|
|
||||||
else interactor.selectAllTapped()
|
|
||||||
}
|
|
||||||
|
|
||||||
view.bottom_button_bar_layout.setOnClickListener(null)
|
|
||||||
view.bottom_button_bar_layout.isClickable = false
|
|
||||||
|
|
||||||
val drawable = AppCompatResources.getDrawable(view.context, R.drawable.ic_close)
|
|
||||||
drawable?.setTint(ContextCompat.getColor(view.context, R.color.photonWhite))
|
|
||||||
view.bottom_bar_icon_button.setImageDrawable(drawable)
|
|
||||||
view.bottom_bar_icon_button.contentDescription =
|
|
||||||
view.context.getString(R.string.create_collection_close)
|
|
||||||
view.bottom_bar_icon_button.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
|
||||||
view.bottom_bar_icon_button.setOnClickListener {
|
|
||||||
interactor.close()
|
|
||||||
}
|
|
||||||
selectTabsConstraints.clone(collection_constraint_layout)
|
|
||||||
selectTabsConstraints.applyTo(view.collection_constraint_layout)
|
|
||||||
|
|
||||||
collectionCreationTabListAdapter.updateData(state.tabs, state.selectedTabs)
|
|
||||||
|
|
||||||
back_button.text = view.context.getString(R.string.create_collection_select_tabs)
|
|
||||||
|
|
||||||
val selectTabsText = if (state.selectedTabs.isEmpty()) {
|
|
||||||
view.context.getString(R.string.create_collection_save_to_collection_empty)
|
|
||||||
} else {
|
|
||||||
view.context.getString(
|
|
||||||
if (state.selectedTabs.size == 1)
|
|
||||||
R.string.create_collection_save_to_collection_tab_selected else
|
|
||||||
R.string.create_collection_save_to_collection_tabs_selected,
|
|
||||||
state.selectedTabs.size
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
view.bottom_bar_text.text = selectTabsText
|
|
||||||
|
|
||||||
save_button.setOnClickListener { _ ->
|
|
||||||
if (selectedCollection != null) {
|
|
||||||
interactor.selectCollection(
|
|
||||||
collection = selectedCollection!!,
|
|
||||||
tabs = state.selectedTabs.toList()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
interactor.saveTabsToCollection(tabs = selectedTabs.toList())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
save_button.visibility = if (state.selectedTabs.isEmpty()) {
|
select_all_button.apply {
|
||||||
View.GONE
|
val allSelected = state.selectedTabs.size == state.tabs.size
|
||||||
} else {
|
text =
|
||||||
View.VISIBLE
|
if (allSelected) context.getString(R.string.create_collection_deselect_all)
|
||||||
|
else context.getString(R.string.create_collection_select_all)
|
||||||
|
setOnClickListener {
|
||||||
|
if (allSelected) interactor.deselectAllTapped()
|
||||||
|
else interactor.selectAllTapped()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectTabsConstraints.clone(collection_constraint_layout)
|
||||||
|
selectTabsConstraints.applyTo(collection_constraint_layout)
|
||||||
|
|
||||||
|
collectionCreationTabListAdapter.updateData(state.tabs, state.selectedTabs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateForSelectCollection() {
|
private fun updateForSelectCollection() {
|
||||||
view.tab_list.isClickable = false
|
tab_list.isClickable = false
|
||||||
|
|
||||||
save_button.visibility = View.GONE
|
|
||||||
|
|
||||||
view.bottom_bar_text.text =
|
|
||||||
view.context.getString(R.string.create_collection_add_new_collection)
|
|
||||||
|
|
||||||
val drawable = AppCompatResources.getDrawable(view.context, R.drawable.ic_new)
|
|
||||||
drawable?.setTint(ContextCompat.getColor(view.context, R.color.photonWhite))
|
|
||||||
view.bottom_bar_icon_button.setImageDrawable(drawable)
|
|
||||||
view.bottom_bar_icon_button.contentDescription = null
|
|
||||||
view.bottom_bar_icon_button.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
|
||||||
view.bottom_button_bar_layout.isClickable = true
|
|
||||||
view.bottom_button_bar_layout.setOnClickListener {
|
|
||||||
interactor.addNewCollection()
|
|
||||||
}
|
|
||||||
|
|
||||||
back_button.setOnClickListener {
|
back_button.setOnClickListener {
|
||||||
interactor.onBackPressed(SaveCollectionStep.SelectCollection)
|
interactor.onBackPressed(SaveCollectionStep.SelectCollection)
|
||||||
}
|
}
|
||||||
TransitionManager.beginDelayedTransition(
|
TransitionManager.beginDelayedTransition(collection_constraint_layout, transition)
|
||||||
view.collection_constraint_layout,
|
|
||||||
transition
|
|
||||||
)
|
|
||||||
selectCollectionConstraints.clone(
|
selectCollectionConstraints.clone(
|
||||||
view.context,
|
containerView.context,
|
||||||
R.layout.component_collection_creation_select_collection
|
R.layout.component_collection_creation_select_collection
|
||||||
)
|
)
|
||||||
selectCollectionConstraints.applyTo(view.collection_constraint_layout)
|
selectCollectionConstraints.applyTo(collection_constraint_layout)
|
||||||
back_button.text =
|
|
||||||
view.context.getString(R.string.create_collection_select_collection)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateForNameCollection(state: CollectionCreationState) {
|
private fun updateForNameCollection(state: CollectionCreationState) {
|
||||||
view.tab_list.isClickable = false
|
tab_list.isClickable = false
|
||||||
|
|
||||||
collectionCreationTabListAdapter.updateData(state.selectedTabs.toList(), state.selectedTabs, true)
|
collectionCreationTabListAdapter.updateData(state.selectedTabs.toList(), state.selectedTabs, true)
|
||||||
back_button.setOnClickListener {
|
back_button.apply {
|
||||||
name_collection_edittext.hideKeyboard()
|
text = context.getString(R.string.create_collection_name_collection)
|
||||||
val handler = Handler()
|
setOnClickListener {
|
||||||
handler.postDelayed({
|
name_collection_edittext.hideKeyboard()
|
||||||
interactor.onBackPressed(SaveCollectionStep.NameCollection)
|
val handler = Handler()
|
||||||
}, TRANSITION_DURATION)
|
handler.postDelayed({
|
||||||
|
interactor.onBackPressed(SaveCollectionStep.NameCollection)
|
||||||
|
}, TRANSITION_DURATION)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view.name_collection_edittext.showKeyboard()
|
name_collection_edittext.showKeyboard()
|
||||||
nameCollectionConstraints.clone(
|
nameCollectionConstraints.clone(
|
||||||
view.context,
|
containerView.context,
|
||||||
R.layout.component_collection_creation_name_collection
|
R.layout.component_collection_creation_name_collection
|
||||||
)
|
)
|
||||||
nameCollectionConstraints.applyTo(view.collection_constraint_layout)
|
nameCollectionConstraints.applyTo(collection_constraint_layout)
|
||||||
name_collection_edittext.setText(
|
name_collection_edittext.setText(
|
||||||
view.context.getString(
|
containerView.context.getString(
|
||||||
R.string.create_collection_default_name,
|
R.string.create_collection_default_name,
|
||||||
state.defaultCollectionNumber
|
state.defaultCollectionNumber
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
name_collection_edittext.setSelection(0, name_collection_edittext.text.length)
|
name_collection_edittext.setSelection(0, name_collection_edittext.text.length)
|
||||||
back_button.text =
|
|
||||||
view.context.getString(R.string.create_collection_name_collection)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateForRenameCollection(state: CollectionCreationState) {
|
private fun updateForRenameCollection(state: CollectionCreationState) {
|
||||||
view.tab_list.isClickable = false
|
tab_list.isClickable = false
|
||||||
|
|
||||||
state.selectedTabCollection?.let { tabCollection ->
|
state.selectedTabCollection?.let { tabCollection ->
|
||||||
|
val publicSuffixList = containerView.context.components.publicSuffixList
|
||||||
tabCollection.tabs.map { tab ->
|
tabCollection.tabs.map { tab ->
|
||||||
Tab(
|
Tab(
|
||||||
tab.id.toString(),
|
sessionId = tab.id.toString(),
|
||||||
tab.url,
|
url = tab.url,
|
||||||
tab.url.toShortUrl(view.context.components.publicSuffixList),
|
hostname = tab.url.toShortUrl(publicSuffixList),
|
||||||
tab.title,
|
title = tab.title,
|
||||||
mediaState = MediaState.State.NONE
|
mediaState = MediaState.State.NONE
|
||||||
)
|
)
|
||||||
}.let { tabs ->
|
}.let { tabs ->
|
||||||
|
@ -263,27 +199,28 @@ class CollectionCreationView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nameCollectionConstraints.clone(
|
nameCollectionConstraints.clone(
|
||||||
view.context,
|
containerView.context,
|
||||||
R.layout.component_collection_creation_name_collection
|
R.layout.component_collection_creation_name_collection
|
||||||
)
|
)
|
||||||
nameCollectionConstraints.applyTo(view.collection_constraint_layout)
|
nameCollectionConstraints.applyTo(collection_constraint_layout)
|
||||||
name_collection_edittext.setText(state.selectedTabCollection?.title)
|
name_collection_edittext.setText(state.selectedTabCollection?.title)
|
||||||
name_collection_edittext.setSelection(0, name_collection_edittext.text.length)
|
name_collection_edittext.setSelection(0, name_collection_edittext.text.length)
|
||||||
|
|
||||||
back_button.text =
|
back_button.apply {
|
||||||
view.context.getString(R.string.collection_rename)
|
text = context.getString(R.string.collection_rename)
|
||||||
back_button.setOnClickListener {
|
setOnClickListener {
|
||||||
name_collection_edittext.hideKeyboard()
|
name_collection_edittext.hideKeyboard()
|
||||||
val handler = Handler()
|
val handler = Handler()
|
||||||
handler.postDelayed({
|
handler.postDelayed({
|
||||||
interactor.onBackPressed(SaveCollectionStep.RenameCollection)
|
interactor.onBackPressed(SaveCollectionStep.RenameCollection)
|
||||||
}, TRANSITION_DURATION)
|
}, TRANSITION_DURATION)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
transition.addListener(object : Transition.TransitionListener {
|
transition.addListener(object : Transition.TransitionListener {
|
||||||
override fun onTransitionStart(transition: Transition) { /* noop */ }
|
override fun onTransitionStart(transition: Transition) { /* noop */ }
|
||||||
|
|
||||||
override fun onTransitionEnd(transition: Transition) {
|
override fun onTransitionEnd(transition: Transition) {
|
||||||
view.name_collection_edittext.showKeyboard()
|
name_collection_edittext.showKeyboard()
|
||||||
transition.removeListener(this)
|
transition.removeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,15 +228,12 @@ class CollectionCreationView(
|
||||||
override fun onTransitionPause(transition: Transition) { /* noop */ }
|
override fun onTransitionPause(transition: Transition) { /* noop */ }
|
||||||
override fun onTransitionResume(transition: Transition) { /* noop */ }
|
override fun onTransitionResume(transition: Transition) { /* noop */ }
|
||||||
})
|
})
|
||||||
TransitionManager.beginDelayedTransition(
|
TransitionManager.beginDelayedTransition(collection_constraint_layout, transition)
|
||||||
view.collection_constraint_layout,
|
|
||||||
transition
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onResumed() {
|
fun onResumed() {
|
||||||
if (step == SaveCollectionStep.NameCollection || step == SaveCollectionStep.RenameCollection) {
|
if (step == SaveCollectionStep.NameCollection || step == SaveCollectionStep.RenameCollection) {
|
||||||
view.name_collection_edittext.showKeyboard()
|
name_collection_edittext.showKeyboard()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
/* 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.collections
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import io.mockk.Called
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import mozilla.components.feature.tab.collections.TabCollection
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
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.helpers.FenixRobolectricTestRunner
|
||||||
|
import org.mozilla.fenix.home.Tab
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class CollectionCreationBottomBarViewTest {
|
||||||
|
|
||||||
|
private lateinit var bottomBarView: CollectionCreationBottomBarView
|
||||||
|
private lateinit var interactor: CollectionCreationInteractor
|
||||||
|
private lateinit var layout: ViewGroup
|
||||||
|
private lateinit var iconButton: ImageButton
|
||||||
|
private lateinit var textView: TextView
|
||||||
|
private lateinit var saveButton: Button
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
interactor = mockk(relaxed = true)
|
||||||
|
layout = mockk(relaxed = true)
|
||||||
|
iconButton = ImageButton(testContext)
|
||||||
|
textView = TextView(testContext)
|
||||||
|
saveButton = Button(testContext)
|
||||||
|
|
||||||
|
bottomBarView = CollectionCreationBottomBarView(
|
||||||
|
interactor,
|
||||||
|
layout,
|
||||||
|
iconButton,
|
||||||
|
textView,
|
||||||
|
saveButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIconButtonUpdateForSelectTabs() {
|
||||||
|
bottomBarView.update(SaveCollectionStep.SelectTabs, CollectionCreationState(0))
|
||||||
|
|
||||||
|
verify { layout.setOnClickListener(null) }
|
||||||
|
verify { layout.isClickable = false }
|
||||||
|
|
||||||
|
assertEquals("Close", iconButton.contentDescription)
|
||||||
|
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_YES, iconButton.importantForAccessibility)
|
||||||
|
|
||||||
|
iconButton.performClick()
|
||||||
|
verify { interactor.close() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIconButtonUpdateForSelectCollection() {
|
||||||
|
bottomBarView.update(SaveCollectionStep.SelectCollection, CollectionCreationState(0))
|
||||||
|
|
||||||
|
verify { layout wasNot Called }
|
||||||
|
|
||||||
|
assertEquals(null, iconButton.contentDescription)
|
||||||
|
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_NO, iconButton.importantForAccessibility)
|
||||||
|
|
||||||
|
iconButton.performClick()
|
||||||
|
verify { interactor.addNewCollection() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTextViewUpdateForSelectTabs() {
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabs = emptySet()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertEquals("Select tabs to save", textView.text)
|
||||||
|
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabs = setOf(mockk())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertEquals("1 tab selected", textView.text)
|
||||||
|
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabs = setOf(mockk(), mockk())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertEquals("2 tabs selected", textView.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTextViewUpdateForSelectCollection() {
|
||||||
|
bottomBarView.update(SaveCollectionStep.SelectCollection, CollectionCreationState(0))
|
||||||
|
|
||||||
|
assertEquals("Add new collection", textView.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSaveButtonUpdateForSelectTabs() {
|
||||||
|
val collection = mockk<TabCollection>()
|
||||||
|
val tabs = setOf<Tab>(mockk(), mockk())
|
||||||
|
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabCollection = null,
|
||||||
|
selectedTabs = emptySet()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertFalse(saveButton.isVisible)
|
||||||
|
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabCollection = collection,
|
||||||
|
selectedTabs = emptySet()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertFalse(saveButton.isVisible)
|
||||||
|
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabCollection = null,
|
||||||
|
selectedTabs = tabs
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertTrue(saveButton.isVisible)
|
||||||
|
saveButton.performClick()
|
||||||
|
verify { interactor.saveTabsToCollection(tabs.toList()) }
|
||||||
|
|
||||||
|
bottomBarView.update(
|
||||||
|
SaveCollectionStep.SelectTabs,
|
||||||
|
CollectionCreationState(
|
||||||
|
0,
|
||||||
|
selectedTabCollection = collection,
|
||||||
|
selectedTabs = tabs
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertTrue(saveButton.isVisible)
|
||||||
|
saveButton.performClick()
|
||||||
|
verify { interactor.selectCollection(collection, tabs.toList()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSaveButtonUpdateForSelectCollection() {
|
||||||
|
bottomBarView.update(SaveCollectionStep.SelectCollection, CollectionCreationState(0))
|
||||||
|
|
||||||
|
assertFalse(saveButton.isVisible)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue