Allow autofocus of name field.

fork-5.53.8
Alex Hart 2022-09-28 09:33:17 -03:00 zatwierdzone przez Cody Henthorne
rodzic b05f4430f6
commit 0312dfcfcd
8 zmienionych plików z 154 dodań i 65 usunięć

Wyświetl plik

@ -6,6 +6,7 @@ import androidx.fragment.app.setFragmentResult
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.stories.settings.select.BaseStoryRecipientSelectionFragment 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 { 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() dismissAllowingStateLoss()
} }
override fun setStatusBarColor(color: Int) {
WindowUtil.setStatusBarColor(requireDialog().window!!, color)
}
} }

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" <merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
tools:viewBindingIgnore="true"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">

Wyświetl plik

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

Wyświetl plik

@ -1,23 +1,63 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true"
xmlns:app="http://schemas.android.com/apk/res-auto" 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:orientation="vertical">
<include layout="@layout/dsl_settings_toolbar" /> <org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/signal_m3_toolbar_height"
android:background="@null"
android:minHeight="@dimen/signal_m3_toolbar_height"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationContentDescription="@string/DSLSettingsToolbar__navigate_up"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:titleTextAppearance="@style/Signal.Text.TitleLarge"
tools:title="Settings" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:viewBindingIgnore="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/signal_colorBackground"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<include
android:id="@+id/name_field"
layout="@layout/stories_create_story_name_field_item" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler" android:id="@+id/recycler"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" /> app:layout_constraintTop_toBottomOf="@id/name_field" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/create" android:id="@+id/create"
@ -33,4 +73,5 @@
app:elevation="4dp" app:elevation="4dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

Wyświetl plik

@ -5,8 +5,7 @@
android:id="@+id/content" android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
tools:viewBindingIgnore="true">
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar <org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"