Allow autofocus of name field.

This commit is contained in:
Alex Hart
2022-09-28 09:33:17 -03:00
committed by Cody Henthorne
parent b05f4430f6
commit 0312dfcfcd
8 changed files with 154 additions and 65 deletions

View File

@@ -6,6 +6,7 @@ import androidx.fragment.app.setFragmentResult
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.stories.settings.select.BaseStoryRecipientSelectionFragment
import org.thoughtcrime.securesms.util.WindowUtil
class CreateStoryFlowDialogFragment : DialogFragment(R.layout.create_story_flow_dialog_fragment), BaseStoryRecipientSelectionFragment.Callback, CreateStoryWithViewersFragment.Callback {
@@ -27,4 +28,8 @@ class CreateStoryFlowDialogFragment : DialogFragment(R.layout.create_story_flow_
)
dismissAllowingStateLoss()
}
override fun setStatusBarColor(color: Int) {
WindowUtil.setStatusBarColor(requireDialog().window!!, color)
}
}

View File

@@ -2,17 +2,24 @@ package org.thoughtcrime.securesms.stories.settings.create
import android.os.Bundle
import android.view.View
import androidx.annotation.ColorInt
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.ViewBinderDelegate
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.databinding.StoriesCreateWithRecipientsFragmentBinding
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
import org.thoughtcrime.securesms.util.ViewUtil
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.fragments.findListener
import org.thoughtcrime.securesms.util.fragments.requireListener
import org.thoughtcrime.securesms.util.viewholders.RecipientMappingModel
import org.thoughtcrime.securesms.util.viewholders.RecipientViewHolder
@@ -35,27 +42,48 @@ class CreateStoryWithViewersFragment : DSLSettingsFragment(
}
)
private val binding by ViewBinderDelegate(StoriesCreateWithRecipientsFragmentBinding::bind)
private val recipientIds: Array<RecipientId>
get() = CreateStoryWithViewersFragmentArgs.fromBundle(requireArguments()).recipients
override fun bindAdapter(adapter: MappingAdapter) {
adapter.registerFactory(RecipientMappingModel.RecipientIdMappingModel::class.java, LayoutFactory({ RecipientViewHolder(it, null) }, R.layout.stories_recipient_item))
CreateStoryNameFieldItem.register(adapter) {
binding.create.setOnClickListener { viewModel.create(recipientIds.toSet()) }
val nameViewHolder = CreateStoryNameFieldItem.ViewHolder(binding.nameField.root) {
viewModel.setLabel(it)
}
val createButton: View = requireView().findViewById(R.id.create)
createButton.setOnClickListener { viewModel.create(recipientIds.toSet()) }
adapter.submitList(getConfiguration().toMappingModelList())
viewModel.state.observe(viewLifecycleOwner) { state ->
adapter.submitList(getConfiguration(state).toMappingModelList())
val nameModel = CreateStoryNameFieldItem.Model(
body = state.label,
error = presentError(state.error)
)
nameViewHolder.bind(nameModel)
when (state.saveState) {
CreateStoryWithViewersState.SaveState.Init -> createButton.setCanPress(state.label.isNotEmpty())
CreateStoryWithViewersState.SaveState.Saving -> createButton.setCanPress(false)
CreateStoryWithViewersState.SaveState.Init -> binding.create.setCanPress(state.label.isNotEmpty())
CreateStoryWithViewersState.SaveState.Saving -> binding.create.setCanPress(false)
is CreateStoryWithViewersState.SaveState.Saved -> onDone(state.saveState.recipientId)
}
}
Material3OnScrollHelper(requireContext(), { requireListener<Callback>().setStatusBarColor(it) }, listOf(binding.toolbar)).attach(binding.appBarLayout)
ViewUtil.focusAndShowKeyboard(binding.nameField.editText)
}
override fun onPause() {
super.onPause()
ViewUtil.hideKeyboard(requireContext(), binding.nameField.editText)
}
override fun onToolbarNavigationClicked() {
findNavController().popBackStack()
}
private fun View.setCanPress(canPress: Boolean) {
@@ -63,15 +91,12 @@ class CreateStoryWithViewersFragment : DSLSettingsFragment(
alpha = if (canPress) 1f else 0.5f
}
private fun getConfiguration(state: CreateStoryWithViewersState): DSLConfiguration {
return configure {
customPref(
CreateStoryNameFieldItem.Model(
body = state.label,
error = presentError(state.error)
)
)
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper? {
return null
}
private fun getConfiguration(): DSLConfiguration {
return configure {
dividerPref()
sectionHeaderPref(R.string.CreateStoryWithViewersFragment__viewers)
@@ -106,6 +131,7 @@ class CreateStoryWithViewersFragment : DSLSettingsFragment(
}
interface Callback {
fun setStatusBarColor(@ColorInt color: Int)
fun onDone(recipientId: RecipientId)
}
}

View File

@@ -68,6 +68,8 @@ class EditStoryNameFragment : Fragment(R.layout.stories_edit_story_name_fragment
saveButton.setOnClickListener {
onSaveClicked()
}
ViewUtil.focusAndShowKeyboard(storyName)
}
override fun onPause() {

View File

@@ -2,12 +2,14 @@ package org.thoughtcrime.securesms.util
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.animation.ArgbEvaluatorCompat
import com.google.android.material.appbar.AppBarLayout
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.views.Stub
@@ -17,11 +19,18 @@ import org.thoughtcrime.securesms.util.views.Stub
* for other purposes.
*/
open class Material3OnScrollHelper(
private val activity: Activity,
private val context: Context,
private val setStatusBarColor: (Int) -> Unit,
private val views: List<View>,
private val viewStubs: List<Stub<out View>> = emptyList()
) {
constructor(activity: Activity, views: List<View>, viewStubs: List<Stub<out View>>) : this(activity, { WindowUtil.setStatusBarColor(activity.window, it) }, views, viewStubs)
constructor(activity: Activity, views: List<View>) : this(activity, { WindowUtil.setStatusBarColor(activity.window, it) }, views, emptyList())
constructor(activity: Activity, view: View) : this(activity, { WindowUtil.setStatusBarColor(activity.window, it) }, listOf(view), emptyList())
/**
* A pair of colors tied to a specific state.
*/
@@ -35,15 +44,23 @@ open class Material3OnScrollHelper(
open val activeColorSet: ColorSet = ColorSet(R.color.signal_colorSurface2)
open val inactiveColorSet: ColorSet = ColorSet(R.color.signal_colorBackground)
constructor(activity: Activity, view: View) : this(activity, listOf(view), emptyList())
private var animator: ValueAnimator? = null
private var active: Boolean? = null
private val scrollListener = OnScrollListener()
fun attach(recyclerView: RecyclerView) {
recyclerView.addOnScrollListener(scrollListener)
scrollListener.onScrolled(recyclerView, 0, 0)
recyclerView.addOnScrollListener(
OnScrollListener().apply {
onScrolled(recyclerView, 0, 0)
}
)
}
fun attach(appBarLayout: AppBarLayout) {
appBarLayout.addOnOffsetChangedListener(
OnOffsetChangedListener().apply {
onOffsetChanged(appBarLayout, 0)
}
)
}
/**
@@ -56,8 +73,8 @@ open class Material3OnScrollHelper(
animator?.cancel()
val colorSet = if (active == true) activeColorSet else inactiveColorSet
setToolbarColor(ContextCompat.getColor(activity, colorSet.toolbarColorRes))
setStatusBarColor(ContextCompat.getColor(activity, colorSet.statusBarColorRes))
setToolbarColor(ContextCompat.getColor(context, colorSet.toolbarColorRes))
setStatusBarColor(ContextCompat.getColor(context, colorSet.statusBarColorRes))
}
private fun updateActiveState(isActive: Boolean) {
@@ -78,10 +95,10 @@ open class Material3OnScrollHelper(
val endColorSet = if (isActive) activeColorSet else inactiveColorSet
if (hadActiveState) {
val startToolbarColor = ContextCompat.getColor(activity, startColorSet.toolbarColorRes)
val endToolbarColor = ContextCompat.getColor(activity, endColorSet.toolbarColorRes)
val startStatusBarColor = ContextCompat.getColor(activity, startColorSet.statusBarColorRes)
val endStatusBarColor = ContextCompat.getColor(activity, endColorSet.statusBarColorRes)
val startToolbarColor = ContextCompat.getColor(context, startColorSet.toolbarColorRes)
val endToolbarColor = ContextCompat.getColor(context, endColorSet.toolbarColorRes)
val startStatusBarColor = ContextCompat.getColor(context, startColorSet.statusBarColorRes)
val endStatusBarColor = ContextCompat.getColor(context, endColorSet.statusBarColorRes)
animator = ValueAnimator.ofFloat(0f, 1f).apply {
duration = 200
@@ -102,13 +119,15 @@ open class Material3OnScrollHelper(
viewStubs.filter { it.resolved() }.forEach { it.get().setBackgroundColor(color) }
}
private fun setStatusBarColor(@ColorInt color: Int) {
WindowUtil.setStatusBarColor(activity.window, color)
}
private inner class OnScrollListener : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
updateActiveState(recyclerView.canScrollVertically(-1))
}
}
private inner class OnOffsetChangedListener : AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
updateActiveState(verticalOffset != 0)
}
}
}