You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationView.kt

259 lines
10 KiB
Kotlin

/* 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.os.Handler
import android.os.Looper
import android.text.InputFilter
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.constraintlayout.widget.ConstraintSet
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.AutoTransition
import androidx.transition.Transition
import androidx.transition.TransitionManager
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_collection_creation.*
import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.android.view.showKeyboard
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.toShortUrl
import org.mozilla.fenix.home.Tab
class CollectionCreationView(
container: ViewGroup,
private val interactor: CollectionCreationInteractor
) : LayoutContainer {
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 collectionSaveListAdapter = SaveCollectionListAdapter(interactor)
private val selectTabsConstraints = ConstraintSet()
private val selectCollectionConstraints = ConstraintSet()
private val nameCollectionConstraints = ConstraintSet()
private val transition = AutoTransition()
private var selectedCollection: TabCollection? = null
private var selectedTabs: Set<Tab> = setOf()
var step: SaveCollectionStep = SaveCollectionStep.SelectTabs
private set
init {
transition.duration = TRANSITION_DURATION
transition.excludeTarget(back_button, true)
name_collection_edittext.filters += InputFilter.LengthFilter(COLLECTION_NAME_MAX_LENGTH)
name_collection_edittext.setOnEditorActionListener { view, actionId, _ ->
val text = view.text.toString()
if (actionId == EditorInfo.IME_ACTION_DONE && text.isNotBlank()) {
when (step) {
SaveCollectionStep.NameCollection ->
interactor.onNewCollectionNameSaved(selectedTabs.toList(), text)
SaveCollectionStep.RenameCollection ->
selectedCollection?.let { interactor.onCollectionRenamed(it, text) }
else -> { /* noop */ }
}
}
false
}
tab_list.run {
adapter = collectionCreationTabListAdapter
itemAnimator = null
layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true)
}
collections_list.run {
adapter = collectionSaveListAdapter
layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true)
}
}
fun update(state: CollectionCreationState) {
cacheState(state)
bottomBarView.update(step, state)
when (step) {
SaveCollectionStep.SelectTabs -> updateForSelectTabs(state)
SaveCollectionStep.SelectCollection -> updateForSelectCollection()
SaveCollectionStep.NameCollection -> updateForNameCollection(state)
SaveCollectionStep.RenameCollection -> updateForRenameCollection(state)
}
collectionSaveListAdapter.updateData(state.tabCollections, state.selectedTabs)
}
private fun cacheState(state: CollectionCreationState) {
step = state.saveCollectionStep
selectedTabs = state.selectedTabs
selectedCollection = state.selectedTabCollection
}
private fun updateForSelectTabs(state: CollectionCreationState) {
containerView.context.components.analytics.metrics.track(Event.CollectionTabSelectOpened)
tab_list.isClickable = true
back_button.apply {
text = context.getString(R.string.create_collection_select_tabs)
setOnClickListener {
interactor.onBackPressed(SaveCollectionStep.SelectTabs)
}
}
select_all_button.apply {
val allSelected = state.selectedTabs.size == state.tabs.size
text =
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(
containerView.context,
R.layout.component_collection_creation
)
collectionCreationTabListAdapter.updateData(state.tabs, state.selectedTabs)
selectTabsConstraints.applyTo(collection_constraint_layout)
}
private fun updateForSelectCollection() {
tab_list.isClickable = false
selectCollectionConstraints.clone(
containerView.context,
R.layout.component_collection_creation_select_collection
)
selectCollectionConstraints.applyTo(collection_constraint_layout)
back_button.apply {
text = context.getString(R.string.create_collection_select_collection)
setOnClickListener {
interactor.onBackPressed(SaveCollectionStep.SelectCollection)
}
}
TransitionManager.beginDelayedTransition(collection_constraint_layout, transition)
}
private fun updateForNameCollection(state: CollectionCreationState) {
tab_list.isClickable = false
nameCollectionConstraints.clone(
containerView.context,
R.layout.component_collection_creation_name_collection
)
nameCollectionConstraints.applyTo(collection_constraint_layout)
collectionCreationTabListAdapter.updateData(state.selectedTabs.toList(), state.selectedTabs, true)
back_button.apply {
text = context.getString(R.string.create_collection_name_collection)
setOnClickListener {
name_collection_edittext.hideKeyboard()
val handler = Handler(Looper.getMainLooper())
handler.postDelayed({
interactor.onBackPressed(SaveCollectionStep.NameCollection)
}, TRANSITION_DURATION)
}
}
name_collection_edittext.showKeyboard()
name_collection_edittext.setText(
containerView.context.getString(
R.string.create_collection_default_name,
state.defaultCollectionNumber
)
)
name_collection_edittext.setSelection(0, name_collection_edittext.text.length)
}
private fun updateForRenameCollection(state: CollectionCreationState) {
tab_list.isClickable = false
state.selectedTabCollection?.let { tabCollection ->
val publicSuffixList = containerView.context.components.publicSuffixList
tabCollection.tabs.map { tab ->
Tab(
sessionId = tab.id.toString(),
url = tab.url,
hostname = tab.url.toShortUrl(publicSuffixList),
title = tab.title
)
}.let { tabs ->
collectionCreationTabListAdapter.updateData(tabs, tabs.toSet(), true)
}
}
nameCollectionConstraints.clone(
containerView.context,
R.layout.component_collection_creation_name_collection
)
nameCollectionConstraints.applyTo(collection_constraint_layout)
name_collection_edittext.setText(state.selectedTabCollection?.title)
name_collection_edittext.setSelection(0, name_collection_edittext.text.length)
back_button.apply {
text = context.getString(R.string.collection_rename)
setOnClickListener {
name_collection_edittext.hideKeyboard()
val handler = Handler(Looper.getMainLooper())
handler.postDelayed({
interactor.onBackPressed(SaveCollectionStep.RenameCollection)
}, TRANSITION_DURATION)
}
}
transition.addListener(object : Transition.TransitionListener {
override fun onTransitionStart(transition: Transition) { /* noop */ }
override fun onTransitionEnd(transition: Transition) {
name_collection_edittext.showKeyboard()
transition.removeListener(this)
}
override fun onTransitionCancel(transition: Transition) { /* noop */ }
override fun onTransitionPause(transition: Transition) { /* noop */ }
override fun onTransitionResume(transition: Transition) { /* noop */ }
})
TransitionManager.beginDelayedTransition(collection_constraint_layout, transition)
}
fun onResumed() {
if (step == SaveCollectionStep.NameCollection || step == SaveCollectionStep.RenameCollection) {
name_collection_edittext.showKeyboard()
}
}
fun onKey(keyCode: Int, event: KeyEvent): Boolean {
return if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
interactor.onBackPressed(step)
true
} else {
false
}
}
companion object {
private const val TRANSITION_DURATION = 200L
private const val COLLECTION_NAME_MAX_LENGTH = 128
}
}