Improve styling of ChooseGroupStoryBottomSheet.

This commit is contained in:
Greyson Parrelli 2022-10-05 16:00:48 -04:00
parent 26709177d2
commit 23ba5c874a
13 changed files with 66 additions and 58 deletions

View file

@ -66,6 +66,7 @@ sealed class DSLSettingsText {
} }
object TitleLargeModifier : TextAppearanceModifier(R.style.Signal_Text_TitleLarge) object TitleLargeModifier : TextAppearanceModifier(R.style.Signal_Text_TitleLarge)
object TitleMediumModifier : TextAppearanceModifier(R.style.Signal_Text_TitleMedium)
object Body1BoldModifier : TextAppearanceModifier(R.style.TextAppearance_Signal_Body1_Bold) object Body1BoldModifier : TextAppearanceModifier(R.style.TextAppearance_Signal_Body1_Bold)
open class TextAppearanceModifier(@StyleRes private val textAppearance: Int) : Modifier { open class TextAppearanceModifier(@StyleRes private val textAppearance: Int) : Modifier {

View file

@ -64,6 +64,7 @@ class ContactSearchConfiguration private constructor(
val includeInactive: Boolean = false, val includeInactive: Boolean = false,
val returnAsGroupStories: Boolean = false, val returnAsGroupStories: Boolean = false,
val sortOrder: ContactSearchSortOrder = ContactSearchSortOrder.NATURAL, val sortOrder: ContactSearchSortOrder = ContactSearchSortOrder.NATURAL,
val shortSummary: Boolean = false,
override val includeHeader: Boolean, override val includeHeader: Boolean,
override val expandConfig: ExpandConfig? = null override val expandConfig: ExpandConfig? = null
) : Section(SectionKey.GROUPS) ) : Section(SectionKey.GROUPS)

View file

@ -23,7 +23,7 @@ sealed class ContactSearchData(val contactSearchKey: ContactSearchKey) {
/** /**
* A row displaying a known recipient. * A row displaying a known recipient.
*/ */
data class KnownRecipient(val recipient: Recipient) : ContactSearchData(ContactSearchKey.RecipientSearchKey.KnownRecipient(recipient.id)) data class KnownRecipient(val recipient: Recipient, val shortSummary: Boolean = false) : ContactSearchData(ContactSearchKey.RecipientSearchKey.KnownRecipient(recipient.id))
/** /**
* A row containing a title for a given section * A row containing a title for a given section

View file

@ -73,7 +73,7 @@ object ContactSearchItems {
contactSearchData.filterNotNull().map { contactSearchData.filterNotNull().map {
when (it) { when (it) {
is ContactSearchData.Story -> StoryModel(it, selection.contains(it.contactSearchKey), SignalStore.storyValues().userHasBeenNotifiedAboutStories) is ContactSearchData.Story -> StoryModel(it, selection.contains(it.contactSearchKey), SignalStore.storyValues().userHasBeenNotifiedAboutStories)
is ContactSearchData.KnownRecipient -> RecipientModel(it, selection.contains(it.contactSearchKey)) is ContactSearchData.KnownRecipient -> RecipientModel(it, selection.contains(it.contactSearchKey), it.shortSummary)
is ContactSearchData.Expand -> ExpandModel(it) is ContactSearchData.Expand -> ExpandModel(it)
is ContactSearchData.Header -> HeaderModel(it) is ContactSearchData.Header -> HeaderModel(it)
is ContactSearchData.TestRow -> error("This row exists for testing only.") is ContactSearchData.TestRow -> error("This row exists for testing only.")
@ -207,7 +207,7 @@ object ContactSearchItems {
/** /**
* Recipient model * Recipient model
*/ */
private class RecipientModel(val knownRecipient: ContactSearchData.KnownRecipient, val isSelected: Boolean) : MappingModel<RecipientModel> { private class RecipientModel(val knownRecipient: ContactSearchData.KnownRecipient, val isSelected: Boolean, val shortSummary: Boolean) : MappingModel<RecipientModel> {
override fun areItemsTheSame(newItem: RecipientModel): Boolean { override fun areItemsTheSame(newItem: RecipientModel): Boolean {
return newItem.knownRecipient == knownRecipient return newItem.knownRecipient == knownRecipient
@ -230,6 +230,16 @@ object ContactSearchItems {
override fun isSelected(model: RecipientModel): Boolean = model.isSelected override fun isSelected(model: RecipientModel): Boolean = model.isSelected
override fun getData(model: RecipientModel): ContactSearchData.KnownRecipient = model.knownRecipient override fun getData(model: RecipientModel): ContactSearchData.KnownRecipient = model.knownRecipient
override fun getRecipient(model: RecipientModel): Recipient = model.knownRecipient.recipient override fun getRecipient(model: RecipientModel): Recipient = model.knownRecipient.recipient
override fun bindNumberField(model: RecipientModel) {
val recipient = getRecipient(model)
if (model.shortSummary && recipient.isGroup) {
val count = recipient.participantIds.size
number.setText(context.resources.getQuantityString(R.plurals.ContactSearchItems__group_d_members, count, count))
} else {
super.bindNumberField(model)
}
}
} }
/** /**

View file

@ -219,7 +219,7 @@ class ContactSearchPagedDataSource(
if (section.returnAsGroupStories) { if (section.returnAsGroupStories) {
ContactSearchData.Story(contactSearchPagedDataSourceRepository.getRecipientFromGroupRecord(it), 0, DistributionListPrivacyMode.ALL) ContactSearchData.Story(contactSearchPagedDataSourceRepository.getRecipientFromGroupRecord(it), 0, DistributionListPrivacyMode.ALL)
} else { } else {
ContactSearchData.KnownRecipient(contactSearchPagedDataSourceRepository.getRecipientFromGroupRecord(it)) ContactSearchData.KnownRecipient(contactSearchPagedDataSourceRepository.getRecipientFromGroupRecord(it), shortSummary = section.shortSummary)
} }
} }
) )

View file

@ -34,7 +34,6 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
private lateinit var confirmButton: View private lateinit var confirmButton: View
private lateinit var selectedList: RecyclerView private lateinit var selectedList: RecyclerView
private lateinit var backgroundHelper: View
private lateinit var divider: View private lateinit var divider: View
private lateinit var mediator: ContactSearchMediator private lateinit var mediator: ContactSearchMediator
@ -52,7 +51,6 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
confirmButton = bottomBar.findViewById(R.id.share_confirm) confirmButton = bottomBar.findViewById(R.id.share_confirm)
selectedList = bottomBar.findViewById(R.id.selected_list) selectedList = bottomBar.findViewById(R.id.selected_list)
backgroundHelper = bottomBar.findViewById(R.id.background_helper)
divider = bottomBar.findViewById(R.id.divider) divider = bottomBar.findViewById(R.id.divider)
val adapter = ShareSelectionAdapter() val adapter = ShareSelectionAdapter()
@ -75,7 +73,7 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
addSection( addSection(
ContactSearchConfiguration.Section.Groups( ContactSearchConfiguration.Section.Groups(
includeHeader = false, includeHeader = false,
returnAsGroupStories = true, shortSummary = true,
sortOrder = ContactSearchSortOrder.RECENCY sortOrder = ContactSearchSortOrder.RECENCY
) )
) )
@ -86,7 +84,7 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
mediator.getSelectionState().observe(viewLifecycleOwner) { state -> mediator.getSelectionState().observe(viewLifecycleOwner) { state ->
adapter.submitList( adapter.submitList(
state.filterIsInstance(ContactSearchKey.RecipientSearchKey.Story::class.java) state.filterIsInstance(ContactSearchKey.RecipientSearchKey.KnownRecipient::class.java)
.map { it.recipientId } .map { it.recipientId }
.mapIndexed { index, recipientId -> .mapIndexed { index, recipientId ->
ShareSelectionMappingModel( ShareSelectionMappingModel(
@ -118,9 +116,8 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
animatorSet?.cancel() animatorSet?.cancel()
animatorSet = AnimatorSet().apply { animatorSet = AnimatorSet().apply {
playTogether( playTogether(
ObjectAnimator.ofFloat(confirmButton, View.ALPHA, 1f), ObjectAnimator.ofFloat(confirmButton, View.TRANSLATION_Y, 0f),
ObjectAnimator.ofFloat(selectedList, View.TRANSLATION_Y, 0f), ObjectAnimator.ofFloat(selectedList, View.TRANSLATION_Y, 0f),
ObjectAnimator.ofFloat(backgroundHelper, View.TRANSLATION_Y, 0f),
ObjectAnimator.ofFloat(divider, View.TRANSLATION_Y, 0f) ObjectAnimator.ofFloat(divider, View.TRANSLATION_Y, 0f)
) )
start() start()
@ -128,14 +125,13 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
} }
private fun animateOutBottomBar() { private fun animateOutBottomBar() {
val translationY = DimensionUnit.DP.toPixels(48f) val translationY = DimensionUnit.SP.toPixels(64f)
animatorSet?.cancel() animatorSet?.cancel()
animatorSet = AnimatorSet().apply { animatorSet = AnimatorSet().apply {
playTogether( playTogether(
ObjectAnimator.ofFloat(confirmButton, View.ALPHA, 0f), ObjectAnimator.ofFloat(confirmButton, View.TRANSLATION_Y, translationY),
ObjectAnimator.ofFloat(selectedList, View.TRANSLATION_Y, translationY), ObjectAnimator.ofFloat(selectedList, View.TRANSLATION_Y, translationY),
ObjectAnimator.ofFloat(backgroundHelper, View.TRANSLATION_Y, translationY),
ObjectAnimator.ofFloat(divider, View.TRANSLATION_Y, translationY) ObjectAnimator.ofFloat(divider, View.TRANSLATION_Y, translationY)
) )
start() start()
@ -150,7 +146,7 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
RESULT_SET, RESULT_SET,
ArrayList( ArrayList(
mediator.getSelectedContacts() mediator.getSelectedContacts()
.filterIsInstance(ContactSearchKey.RecipientSearchKey.Story::class.java) .filterIsInstance(ContactSearchKey.RecipientSearchKey.KnownRecipient::class.java)
.map { it.recipientId } .map { it.recipientId }
) )
) )

View file

@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.components.settings.conversation.preferences.L
import org.thoughtcrime.securesms.util.fragments.requireListener import org.thoughtcrime.securesms.util.fragments.requireListener
class ChooseStoryTypeBottomSheet : DSLSettingsBottomSheetFragment( class ChooseStoryTypeBottomSheet : DSLSettingsBottomSheetFragment(
layoutId = R.layout.dsl_settings_bottom_sheet_no_handle layoutId = R.layout.dsl_settings_bottom_sheet
) { ) {
override fun bindAdapter(adapter: DSLSettingsAdapter) { override fun bindAdapter(adapter: DSLSettingsAdapter) {
LargeIconClickPreference.register(adapter) LargeIconClickPreference.register(adapter)
@ -24,7 +24,7 @@ class ChooseStoryTypeBottomSheet : DSLSettingsBottomSheetFragment(
textPref( textPref(
title = DSLSettingsText.from( title = DSLSettingsText.from(
stringId = R.string.ChooseStoryTypeBottomSheet__choose_your_story_type, stringId = R.string.ChooseStoryTypeBottomSheet__choose_your_story_type,
DSLSettingsText.CenterModifier, DSLSettingsText.Body1BoldModifier, DSLSettingsText.BoldModifier DSLSettingsText.CenterModifier, DSLSettingsText.TitleMediumModifier
) )
) )
@ -37,11 +37,11 @@ class ChooseStoryTypeBottomSheet : DSLSettingsBottomSheetFragment(
stringId = R.string.ChooseStoryTypeBottomSheet__visible_only_to stringId = R.string.ChooseStoryTypeBottomSheet__visible_only_to
), ),
icon = DSLSettingsIcon.from( icon = DSLSettingsIcon.from(
R.drawable.ic_plus_24, iconId = R.drawable.ic_plus_24,
R.color.signal_icon_tint_primary, iconTintId = R.color.signal_colorOnSurface,
R.drawable.circle_tintable, backgroundId = R.drawable.circle_tintable,
R.color.signal_button_secondary_ripple, backgroundTint = R.color.signal_colorSurface5,
DimensionUnit.DP.toPixels(8f).toInt() insetPx = DimensionUnit.DP.toPixels(8f).toInt()
), ),
onClick = { onClick = {
dismissAllowingStateLoss() dismissAllowingStateLoss()
@ -59,11 +59,11 @@ class ChooseStoryTypeBottomSheet : DSLSettingsBottomSheetFragment(
stringId = R.string.ChooseStoryTypeBottomSheet__share_to_an_existing_group stringId = R.string.ChooseStoryTypeBottomSheet__share_to_an_existing_group
), ),
icon = DSLSettingsIcon.from( icon = DSLSettingsIcon.from(
R.drawable.ic_group_outline_24, iconId = R.drawable.ic_group_outline_24,
R.color.signal_icon_tint_primary, iconTintId = R.color.signal_colorOnSurface,
R.drawable.circle_tintable, backgroundId = R.drawable.circle_tintable,
R.color.signal_button_secondary_ripple, backgroundTint = R.color.signal_colorSurface5,
DimensionUnit.DP.toPixels(8f).toInt() insetPx = DimensionUnit.DP.toPixels(8f).toInt()
), ),
onClick = { onClick = {
dismissAllowingStateLoss() dismissAllowingStateLoss()

View file

@ -15,7 +15,7 @@
<layer-list> <layer-list>
<item> <item>
<shape android:shape="oval"> <shape android:shape="oval">
<solid android:color="@color/core_ultramarine" /> <solid android:color="@color/signal_colorPrimary" />
</shape> </shape>
</item> </item>
<item android:drawable="@drawable/ic_check_outline_22" /> <item android:drawable="@drawable/ic_check_outline_22" />

View file

@ -15,7 +15,7 @@
<layer-list> <layer-list>
<item> <item>
<shape android:shape="oval"> <shape android:shape="oval">
<solid android:color="@color/core_ultramarine" /> <solid android:color="@color/signal_colorPrimary" />
</shape> </shape>
</item> </item>
<item android:drawable="@drawable/ic_check_outline_22" /> <item android:drawable="@drawable/ic_check_outline_22" />

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="@color/signal_background_secondary"/>
<corners android:radius="22dp"/>
</shape>

View file

@ -10,23 +10,11 @@
<View <View
android:id="@+id/divider" android:id="@+id/divider"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="4dp"
android:background="@color/signal_divider_major" android:background="@drawable/bottom_toolbar_shadow"
android:translationY="48dp" android:translationY="64sp"
app:layout_constraintBottom_toBottomOf="@id/share_confirm" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="@id/share_confirm" />
<View
android:id="@+id/background_helper"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/signal_background_dialog"
android:translationY="48dp"
app:layout_constraintBottom_toBottomOf="@id/selected_list"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/selected_list"
tools:translationY="0dp" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/selected_list" android:id="@+id/selected_list"
@ -37,27 +25,29 @@
android:orientation="horizontal" android:orientation="horizontal"
android:paddingStart="@dimen/dsl_settings_gutter" android:paddingStart="@dimen/dsl_settings_gutter"
android:paddingEnd="78dp" android:paddingEnd="78dp"
android:translationY="48dp" android:translationY="64sp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
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/divider" app:layout_constraintTop_toBottomOf="@id/divider"
app:layout_constraintBottom_toBottomOf="parent"
tools:listitem="@layout/share_contact_selection_item" /> tools:listitem="@layout/share_contact_selection_item" />
<com.google.android.material.floatingactionbutton.FloatingActionButton <ImageView
android:id="@+id/share_confirm" android:id="@+id/share_confirm"
android:layout_width="56dp" android:layout_width="40dp"
android:layout_height="56dp" android:layout_height="40dp"
android:layout_marginEnd="16dp" android:layout_margin="16dp"
android:layout_marginBottom="16dp"
android:alpha="0"
android:contentDescription="@string/ShareActivity__share" android:contentDescription="@string/ShareActivity__share"
app:backgroundTint="@color/signal_accent_primary" android:background="@drawable/circle_tintable"
app:layout_constraintBottom_toBottomOf="@id/divider" android:padding="6dp"
android:translationY="64sp"
app:backgroundTint="@color/signal_colorPrimary"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:srcCompat="@drawable/ic_check_24" app:srcCompat="@drawable/ic_check_24"
app:tint="@color/core_white" app:tint="@color/signal_colorOnPrimary"
tools:alpha="1" /> tools:alpha="1" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -22,8 +22,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:gravity="center" android:gravity="center"
android:text="@string/ChooseGroupStoryBottomSheet__choose_groups" android:text="@string/ChooseGroupStoryBottomSheet__choose_groups"
android:textAppearance="@style/Signal.Text.Body" android:textAppearance="@style/Signal.Text.TitleMedium" />
android:textStyle="bold" />
<org.thoughtcrime.securesms.components.emoji.EmojiEditText <org.thoughtcrime.securesms.components.emoji.EmojiEditText
android:id="@+id/search_field" android:id="@+id/search_field"
@ -33,12 +32,13 @@
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="12dp" android:layout_marginBottom="12dp"
android:background="@drawable/rounded_rectangle_secondary_18" android:background="@drawable/rounded_rectangle_secondary_22"
android:hint="@string/TextStoryPostSendFragment__search" android:hint="@string/TextStoryPostSendFragment__search"
android:minHeight="44dp" android:minHeight="44dp"
android:paddingHorizontal="16dp" android:paddingHorizontal="16dp"
android:textAppearance="@style/Signal.Text.Body" android:textAppearance="@style/Signal.Text.Body"
app:backgroundTint="@color/signal_background_dialog_secondary" /> android:textColor="@color/signal_colorOnSurfaceVariant"
app:backgroundTint="@color/signal_colorSurface5" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/contact_recycler" android:id="@+id/contact_recycler"

View file

@ -5112,6 +5112,11 @@
<item quantity="one">Group story · %1$d viewer</item> <item quantity="one">Group story · %1$d viewer</item>
<item quantity="other">Group story · %1$d viewers</item> <item quantity="other">Group story · %1$d viewers</item>
</plurals> </plurals>
<!-- Label under name for groups -->
<plurals name="ContactSearchItems__group_d_members">
<item quantity="one">%1$d member</item>
<item quantity="other">%1$d members</item>
</plurals>
<!-- Label under name for my story --> <!-- Label under name for my story -->
<plurals name="ContactSearchItems__my_story_s_dot_d_viewers"> <plurals name="ContactSearchItems__my_story_s_dot_d_viewers">
<item quantity="one">%1$s · %2$d viewer</item> <item quantity="one">%1$s · %2$d viewer</item>