1
0
Fork 0

For #1573 - Create Save to Collection Component and Views

master
Emily Kager 2019-04-29 15:52:55 -07:00 committed by Emily Kager
parent c81cfab84e
commit 34f4720e6b
9 changed files with 427 additions and 76 deletions

View File

@ -19,13 +19,29 @@ data class Tab(
val title: String val title: String
) )
data class CollectionCreationState(val tabs: List<Tab> = listOf(), val selectedTabs: Set<Tab> = setOf()) : ViewState data class Collection(
val collectionId: String,
val title: String
)
sealed class SaveCollectionStep {
object SelectTabs : SaveCollectionStep()
object SelectCollection : SaveCollectionStep()
object NameCollection : SaveCollectionStep()
}
data class CollectionCreationState(
val tabs: List<Tab> = listOf(),
val selectedTabs: Set<Tab> = setOf(),
val saveCollectionStep: SaveCollectionStep = SaveCollectionStep.SelectTabs
) : ViewState
sealed class CollectionCreationChange : Change { sealed class CollectionCreationChange : Change {
data class TabListChange(val tabs: List<Tab>) : CollectionCreationChange() data class TabListChange(val tabs: List<Tab>) : CollectionCreationChange()
object AddAllTabs : CollectionCreationChange() object AddAllTabs : CollectionCreationChange()
data class TabAdded(val tab: Tab) : CollectionCreationChange() data class TabAdded(val tab: Tab) : CollectionCreationChange()
data class TabRemoved(val tab: Tab) : CollectionCreationChange() data class TabRemoved(val tab: Tab) : CollectionCreationChange()
data class StepChanged(val saveCollectionStep: SaveCollectionStep) : CollectionCreationChange()
} }
sealed class CollectionCreationAction : Action { sealed class CollectionCreationAction : Action {
@ -34,6 +50,14 @@ sealed class CollectionCreationAction : Action {
data class AddTabToSelection(val tab: Tab) : CollectionCreationAction() data class AddTabToSelection(val tab: Tab) : CollectionCreationAction()
data class RemoveTabFromSelection(val tab: Tab) : CollectionCreationAction() data class RemoveTabFromSelection(val tab: Tab) : CollectionCreationAction()
data class SaveTabsToCollection(val tabs: List<Tab>) : CollectionCreationAction() data class SaveTabsToCollection(val tabs: List<Tab>) : CollectionCreationAction()
data class BackPressed(val backPressFrom: SaveCollectionStep) : CollectionCreationAction()
data class SaveCollectionName(val tabs: List<Tab>, val name: String) :
CollectionCreationAction()
data class SelectCollection(val collection: Collection) :
CollectionCreationAction()
data class AddNewCollection(val tabs: List<Tab>) : CollectionCreationAction()
} }
class CollectionCreationComponent( class CollectionCreationComponent(
@ -44,20 +68,24 @@ class CollectionCreationComponent(
bus.getManagedEmitter(CollectionCreationAction::class.java), bus.getManagedEmitter(CollectionCreationAction::class.java),
bus.getSafeManagedObservable(CollectionCreationChange::class.java) bus.getSafeManagedObservable(CollectionCreationChange::class.java)
) { ) {
override val reducer: Reducer<CollectionCreationState, CollectionCreationChange> = { state, change -> override val reducer: Reducer<CollectionCreationState, CollectionCreationChange> =
when (change) { { state, change ->
is CollectionCreationChange.AddAllTabs -> state.copy(selectedTabs = state.tabs.toSet()) when (change) {
is CollectionCreationChange.TabListChange -> state.copy(tabs = change.tabs) is CollectionCreationChange.AddAllTabs -> state.copy(selectedTabs = state.tabs.toSet())
is CollectionCreationChange.TabAdded -> { is CollectionCreationChange.TabListChange -> state.copy(tabs = change.tabs)
val selectedTabs = state.selectedTabs + setOf(change.tab) is CollectionCreationChange.TabAdded -> {
state.copy(selectedTabs = selectedTabs) val selectedTabs = state.selectedTabs + setOf(change.tab)
} state.copy(selectedTabs = selectedTabs)
is CollectionCreationChange.TabRemoved -> { }
val selectedTabs = state.selectedTabs - setOf(change.tab) is CollectionCreationChange.TabRemoved -> {
state.copy(selectedTabs = selectedTabs) val selectedTabs = state.selectedTabs - setOf(change.tab)
state.copy(selectedTabs = selectedTabs)
}
is CollectionCreationChange.StepChanged -> {
state.copy(saveCollectionStep = change.saveCollectionStep)
}
} }
} }
}
override fun initView() = CollectionCreationUIView(container, actionEmitter, changesObservable) override fun initView() = CollectionCreationUIView(container, actionEmitter, changesObservable)

View File

@ -4,15 +4,22 @@ package org.mozilla.fenix.collections
License, v. 2.0. If a copy of the MPL was not distributed with this 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/. */ file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import android.content.Context.INPUT_METHOD_SERVICE
import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.mozilla.fenix.R
import io.reactivex.Observer
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.functions.Consumer import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.component_collection_creation.*
import kotlinx.android.synthetic.main.component_collection_creation.view.* import kotlinx.android.synthetic.main.component_collection_creation.view.*
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.mvi.UIView import org.mozilla.fenix.mvi.UIView
@ -28,14 +35,14 @@ class CollectionCreationUIView(
override val view = LayoutInflater.from(container.context) override val view = LayoutInflater.from(container.context)
.inflate(R.layout.component_collection_creation, container, true) .inflate(R.layout.component_collection_creation, container, true)
var step: SaveCollectionStep = SaveCollectionStep.SelectTabs
private set
private val collectionCreationTabListAdapter = CollectionCreationTabListAdapter(actionEmitter) private val collectionCreationTabListAdapter = CollectionCreationTabListAdapter(actionEmitter)
private val collectionSaveListAdapter = SaveCollectionListAdapter(actionEmitter)
private var selectedTabs: Set<Tab> = setOf() private var selectedTabs: Set<Tab> = setOf()
init { init {
view.back_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.Close)
}
view.select_all_button.setOnClickListener { view.select_all_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.SelectAllTapped) actionEmitter.onNext(CollectionCreationAction.SelectAllTapped)
} }
@ -47,31 +54,127 @@ class CollectionCreationUIView(
} }
} }
name_collection_edittext.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
actionEmitter.onNext(
CollectionCreationAction.SaveCollectionName(
selectedTabs.toList(),
v.text.toString()
)
)
true
}
false
}
view.add_tabs_button.setOnClickListener { view.add_tabs_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.SaveTabsToCollection(selectedTabs.toList())) actionEmitter.onNext(CollectionCreationAction.SaveTabsToCollection(selectedTabs.toList()))
} }
view.add_collection_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.AddNewCollection(selectedTabs.toList()))
}
view.tab_list.run { view.tab_list.run {
adapter = collectionCreationTabListAdapter adapter = collectionCreationTabListAdapter
layoutManager = LinearLayoutManager(container.context, RecyclerView.VERTICAL, true) layoutManager = LinearLayoutManager(container.context, RecyclerView.VERTICAL, true)
} }
view.collections_list.run {
adapter = collectionSaveListAdapter
layoutManager = LinearLayoutManager(container.context, RecyclerView.VERTICAL, true)
}
} }
override fun updateView() = Consumer<CollectionCreationState> { override fun updateView() = Consumer<CollectionCreationState> {
this.selectedTabs = it.selectedTabs step = it.saveCollectionStep
collectionCreationTabListAdapter.updateData(it.tabs, it.selectedTabs) when (it.saveCollectionStep) {
is SaveCollectionStep.SelectTabs -> {
back_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.BackPressed(SaveCollectionStep.SelectTabs))
}
val buttonText = if (it.selectedTabs.isEmpty()) { name_collection_edittext.visibility = View.GONE
view.context.getString(R.string.create_collection_save_to_collection_empty) collections_list.visibility = View.GONE
} else { add_collection_button.visibility = View.GONE
view.context.getString(R.string.create_collection_save_to_collection_full, it.selectedTabs.size) divider.visibility = View.GONE
this.selectedTabs = it.selectedTabs
collectionCreationTabListAdapter.updateData(it.tabs, it.selectedTabs)
back_button.text = view.context.getString(R.string.create_collection_select_tabs)
val buttonText = if (it.selectedTabs.isEmpty()) {
view.context.getString(R.string.create_collection_save_to_collection_empty)
} else {
view.context.getString(
R.string.create_collection_save_to_collection_full,
it.selectedTabs.size
)
}
tab_list.visibility = View.VISIBLE
select_all_button.visibility = View.VISIBLE
add_tabs_button.visibility = View.VISIBLE
val enableSaveButton = it.selectedTabs.isNotEmpty()
view.add_tabs_button.isClickable = enableSaveButton
view.add_tabs_button.contentDescription = buttonText
view.add_tabs_button_text.text = buttonText
}
is SaveCollectionStep.SelectCollection -> {
back_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.BackPressed(SaveCollectionStep.SelectCollection))
}
collections_list.visibility = View.VISIBLE
add_collection_button.visibility = View.VISIBLE
divider.visibility = View.VISIBLE
tab_list.visibility = View.GONE
select_all_button.visibility = View.GONE
add_tabs_button.visibility = View.GONE
name_collection_edittext.visibility = View.GONE
back_button.text =
view.context.getString(R.string.create_collection_select_collection)
}
is SaveCollectionStep.NameCollection -> {
back_button.setOnClickListener {
actionEmitter.onNext(CollectionCreationAction.BackPressed(SaveCollectionStep.NameCollection))
}
name_collection_edittext.visibility = View.VISIBLE
name_collection_edittext.requestFocus()
val imm =
view.context.getSystemService(INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.showSoftInput(name_collection_edittext, SHOW_IMPLICIT)
collections_list.visibility = View.GONE
add_collection_button.visibility = View.GONE
divider.visibility = View.GONE
tab_list.visibility = View.GONE
select_all_button.visibility = View.GONE
add_tabs_button.visibility = View.GONE
back_button.text =
view.context.getString(R.string.create_collection_name_collection)
}
} }
}
val enableSaveButton = it.selectedTabs.isNotEmpty() fun onKey(keyCode: Int, event: KeyEvent?): Boolean {
view.add_tabs_button.isClickable = enableSaveButton if (event?.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
when (step) {
view.add_tabs_button.contentDescription = buttonText SaveCollectionStep.SelectTabs -> {
view.add_tabs_button_text.text = buttonText actionEmitter.onNext(CollectionCreationAction.BackPressed(SaveCollectionStep.SelectTabs))
}
SaveCollectionStep.SelectCollection -> {
actionEmitter.onNext(CollectionCreationAction.BackPressed(SaveCollectionStep.SelectCollection))
}
SaveCollectionStep.NameCollection -> {
actionEmitter.onNext(CollectionCreationAction.BackPressed(SaveCollectionStep.NameCollection))
}
}
}
return true
} }
companion object { companion object {

View File

@ -4,10 +4,13 @@ package org.mozilla.fenix.collections
License, v. 2.0. If a copy of the MPL was not distributed with this 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/. */ file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import android.app.Dialog
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import kotlinx.android.synthetic.main.fragment_create_collection.view.* import kotlinx.android.synthetic.main.fragment_create_collection.view.*
@ -15,15 +18,14 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter import org.mozilla.fenix.mvi.getManagedEmitter
import org.mozilla.fenix.utils.ItsNotBrokenSnack
class CreateCollectionFragment : DialogFragment() { class CreateCollectionFragment : DialogFragment() {
private lateinit var collectionCreationComponent: CollectionCreationComponent private lateinit var collectionCreationComponent: CollectionCreationComponent
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CreateCollectionDialogStyle) isCancelable = false
setStyle(STYLE_NO_TITLE, R.style.CreateCollectionDialogStyle)
} }
override fun onCreateView( override fun onCreateView(
@ -44,19 +46,29 @@ class CreateCollectionFragment : DialogFragment() {
ActionBusFactory.get(this), ActionBusFactory.get(this),
CollectionCreationState(tabs = tabs, selectedTabs = selectedTabs) CollectionCreationState(tabs = tabs, selectedTabs = selectedTabs)
) )
return view return view
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
super.onViewCreated(view, savedInstanceState) val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnKeyListener { _, keyCode, event ->
(collectionCreationComponent.uiView as CollectionCreationUIView).onKey(keyCode, event)
}
return dialog
}
override fun onResume() {
super.onResume()
subscribeToActions()
}
private fun subscribeToActions() {
getAutoDisposeObservable<CollectionCreationAction>().subscribe { getAutoDisposeObservable<CollectionCreationAction>().subscribe {
when (it) { when (it) {
is CollectionCreationAction.Close -> dismiss() is CollectionCreationAction.Close -> dismiss()
is CollectionCreationAction.SaveTabsToCollection -> { is CollectionCreationAction.SaveTabsToCollection -> {
dismiss() getManagedEmitter<CollectionCreationChange>()
ItsNotBrokenSnack(requireContext()) .onNext(CollectionCreationChange.StepChanged(SaveCollectionStep.SelectCollection))
.showSnackbar("1843")
} }
is CollectionCreationAction.AddTabToSelection -> getManagedEmitter<CollectionCreationChange>() is CollectionCreationAction.AddTabToSelection -> getManagedEmitter<CollectionCreationChange>()
.onNext(CollectionCreationChange.TabAdded(it.tab)) .onNext(CollectionCreationChange.TabAdded(it.tab))
@ -64,6 +76,27 @@ class CreateCollectionFragment : DialogFragment() {
.onNext(CollectionCreationChange.TabRemoved(it.tab)) .onNext(CollectionCreationChange.TabRemoved(it.tab))
is CollectionCreationAction.SelectAllTapped -> getManagedEmitter<CollectionCreationChange>() is CollectionCreationAction.SelectAllTapped -> getManagedEmitter<CollectionCreationChange>()
.onNext(CollectionCreationChange.AddAllTabs) .onNext(CollectionCreationChange.AddAllTabs)
is CollectionCreationAction.AddNewCollection -> getManagedEmitter<CollectionCreationChange>().onNext(
CollectionCreationChange.StepChanged(SaveCollectionStep.NameCollection)
)
is CollectionCreationAction.BackPressed -> handleBackPress(backPressFrom = it.backPressFrom)
}
}
}
private fun handleBackPress(backPressFrom: SaveCollectionStep) {
when (backPressFrom) {
SaveCollectionStep.SelectTabs -> dismiss()
SaveCollectionStep.SelectCollection -> getManagedEmitter<CollectionCreationChange>().onNext(
CollectionCreationChange.StepChanged(SaveCollectionStep.SelectTabs)
)
SaveCollectionStep.NameCollection -> {
val imm =
view?.context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(view?.windowToken, 0)
getManagedEmitter<CollectionCreationChange>().onNext(
CollectionCreationChange.StepChanged(SaveCollectionStep.SelectCollection)
)
} }
} }
} }

View File

@ -0,0 +1,82 @@
package org.mozilla.fenix.collections
/* 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/. */
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observer
import kotlinx.android.synthetic.main.collections_list_item.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import org.mozilla.fenix.R
import kotlin.coroutines.CoroutineContext
class SaveCollectionListAdapter(
val actionEmitter: Observer<CollectionCreationAction>
) : RecyclerView.Adapter<CollectionViewHolder>() {
private var collections: List<Collection> = listOf()
private lateinit var job: Job
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollectionViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(CollectionViewHolder.LAYOUT_ID, parent, false)
return CollectionViewHolder(view, actionEmitter, job)
}
override fun onBindViewHolder(holder: CollectionViewHolder, position: Int) {
val collection = collections[position]
holder.bind(collection)
}
override fun getItemCount(): Int = collections.size
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
job = Job()
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.onDetachedFromRecyclerView(recyclerView)
job.cancel()
}
}
class CollectionViewHolder(
val view: View,
actionEmitter: Observer<CollectionCreationAction>,
val job: Job
) :
RecyclerView.ViewHolder(view), CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
private var collection: Collection? = null
private val listener = View.OnClickListener {
collection?.apply {
val action = CollectionCreationAction.SelectCollection(this)
actionEmitter.onNext(action)
}
}
init {
view.setOnClickListener(listener)
}
fun bind(collection: Collection) {
this.collection = collection
view.collection_item.text = collection.title
}
companion object {
const val LAYOUT_ID = R.layout.collections_list_item
}
}

View File

@ -0,0 +1,35 @@
<?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">
<TextView
android:id="@+id/collection_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?foundation"
android:drawableStart="@drawable/ic_archive"
android:drawablePadding="14dp"
android:drawableTint="?accent"
android:paddingStart="20dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:textColor="?primaryText"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/divider"
app:layout_constraintTop_toTopOf="parent"
tools:targetApi="m" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?neutralFaded"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2,108 +2,164 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- 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 - 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/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false" android:clipToPadding="false">
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button <Button
android:id="@+id/back_button" android:id="@+id/back_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:drawableStart="@drawable/mozac_ic_back" android:drawableStart="@drawable/mozac_ic_back"
android:drawablePadding="8dp"
android:drawableTint="@color/neutral_text"
android:text="@string/create_collection_select_tabs"
android:textAppearance="@style/HeaderTextStyle" android:textAppearance="@style/HeaderTextStyle"
android:textColor="@color/neutral_text" android:textColor="@color/neutral_text"
android:drawableTint="@color/neutral_text"
android:drawablePadding="8dp"
android:text="@string/create_collection_select_tabs"
android:textSize="20sp" android:textSize="20sp"
android:layout_margin="16dp" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintStart_toStartOf="parent" />
<Button <Button
android:id="@+id/select_all_button" android:id="@+id/select_all_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:textSize="16sp"
android:text="@string/create_collection_select_all" android:text="@string/create_collection_select_all"
android:textAllCaps="false" android:textAllCaps="false"
android:textColor="@color/neutral_text" android:textColor="@color/neutral_text"
android:layout_margin="16dp" android:textSize="16sp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/collections_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/add_collection_button" />
<TextView
android:id="@+id/add_collection_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?foundation"
android:drawableStart="@drawable/ic_new"
android:drawablePadding="14dp"
android:drawableTint="?accent"
android:paddingStart="20dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:text="@string/create_collection_add_new_collection"
android:textColor="?primaryText"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/divider"
tools:targetApi="m" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?neutralFaded"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" />
<EditText
android:id="@+id/name_collection_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:autofillHints="false"
android:background="?foundation"
android:focusedByDefault="true"
android:imeOptions="actionDone"
android:importantForAutofill="no"
android:inputType="text"
android:paddingStart="20dp"
android:paddingTop="12dp"
android:paddingEnd="20dp"
android:paddingBottom="12dp"
android:text="Collection 1"
android:textColor="?primaryText"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
tools:targetApi="o" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/tab_list" android:id="@+id/tab_list"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="30dp" android:fadingEdgeLength="30dp"
app:layout_constraintTop_toBottomOf="@id/back_button" android:requiresFadingEdge="vertical"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toTopOf="@+id/add_tabs_button"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@+id/add_tabs_button" /> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/back_button" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/add_tabs_button" android:id="@+id/add_tabs_button"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/add_tabs_to_collection_background" android:background="@drawable/add_tabs_to_collection_background"
android:foreground="?android:attr/selectableItemBackgroundBorderless" android:clickable="true"
android:clipToPadding="false" android:clipToPadding="false"
app:layout_constraintStart_toStartOf="parent" android:focusable="true"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"> app:layout_constraintStart_toStartOf="parent">
<ImageButton <ImageButton
android:id="@+id/close_icon" android:id="@+id/close_icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/create_collection_close" android:contentDescription="@string/create_collection_close"
android:src="@drawable/mozac_ic_close" android:src="@drawable/mozac_ic_close"
android:layout_margin="16dp"
android:tint="?neutral" android:tint="?neutral"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/add_tabs_button_text" android:id="@+id/add_tabs_button_text"
android:importantForAccessibility="no"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:importantForAccessibility="no"
android:singleLine="true" android:singleLine="true"
android:text="@string/create_collection_save_to_collection_empty"
android:textColor="?neutral"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="?neutral" app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/create_collection_save_to_collection_empty"
app:layout_constraintStart_toEndOf="@id/close_icon" app:layout_constraintStart_toEndOf="@id/close_icon"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageView <ImageView
android:id="@+id/save_icon" android:id="@+id/save_icon"
android:importantForAccessibility="no"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_margin="16dp"
android:importantForAccessibility="no"
android:tint="?neutral"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:tint="?neutral"
app:srcCompat="@drawable/ic_archive" /> app:srcCompat="@drawable/ic_archive" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -419,6 +419,15 @@
<!-- Title for the "select tabs" step of the collection creator --> <!-- Title for the "select tabs" step of the collection creator -->
<string name="create_collection_select_tabs">Select Tabs</string> <string name="create_collection_select_tabs">Select Tabs</string>
<!-- Title for the "select collection" step of the collection creator -->
<string name="create_collection_select_collection">Select collection</string>
<!-- Title for the "name collection" step of the collection creator -->
<string name="create_collection_name_collection">Name collection</string>
<!-- Button to add new collection for the "select collection" step of the collection creator -->
<string name="create_collection_add_new_collection">Add new collection</string>
<!-- Button to select all tabs in the "select tabs" step of the collection creator --> <!-- Button to select all tabs in the "select tabs" step of the collection creator -->
<string name="create_collection_select_all">Select All</string> <string name="create_collection_select_all">Select All</string>
@ -432,6 +441,9 @@
<!-- Content description (not visible, for screen readers etc.): button to close the collection creator --> <!-- Content description (not visible, for screen readers etc.): button to close the collection creator -->
<string name="create_collection_close">Close</string> <string name="create_collection_close">Close</string>
<!-- Button to save currently selected tabs in the "select tabs" step of the collection creator-->
<string name="create_collection_save">Save</string>
<!-- QR code scanner prompt which appears after scanning a code, but before navigating to it <!-- QR code scanner prompt which appears after scanning a code, but before navigating to it
First parameter is the name of the app, second parameter is the URL or text scanned--> First parameter is the name of the app, second parameter is the URL or text scanned-->
<string name="qr_scanner_confirmation_dialog_message">Allow %1$s to open %2$s</string> <string name="qr_scanner_confirmation_dialog_message">Allow %1$s to open %2$s</string>

View File

@ -134,8 +134,10 @@
<item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/Animation.Design.BottomSheetDialog</item> <item name="android:windowAnimationStyle">@style/Animation.Design.BottomSheetDialog</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">false</item>
<item name="android:windowContentOverlay">@null</item> <item name="android:windowContentOverlay">@null</item>
<item name="android:navigationBarColor">@android:color/transparent</item> <item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation">true</item> <item name="android:windowTranslucentNavigation">true</item>

View File

@ -20,7 +20,7 @@ private object Versions {
const val androidx_legacy = "1.0.0" const val androidx_legacy = "1.0.0"
const val androidx_annotation = "1.1.0-beta01" const val androidx_annotation = "1.1.0-beta01"
const val androidx_lifecycle = "2.1.0-alpha04" const val androidx_lifecycle = "2.1.0-alpha04"
const val androidx_fragment = "1.1.0-alpha06" const val androidx_fragment = "1.1.0-alpha07"
const val androidx_navigation = "2.1.0-alpha02" const val androidx_navigation = "2.1.0-alpha02"
const val androidx_recyclerview = "1.1.0-alpha04" const val androidx_recyclerview = "1.1.0-alpha04"