Skip to content

Commit 0ef9a6f

Browse files
authored
Merge pull request #14827 from wordpress-mobile/feature/14705-day-selection-screen-part-two
Feature/14705 day selection screen part two
2 parents e9b7741 + b7c8438 commit 0ef9a6f

26 files changed

+646
-208
lines changed

WordPress/src/main/java/org/wordpress/android/ui/bloggingreminders/BloggingReminderBottomSheetFragment.kt

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,68 @@ import android.view.View
77
import android.view.ViewGroup
88
import androidx.lifecycle.ViewModelProvider
99
import androidx.recyclerview.widget.LinearLayoutManager
10+
import androidx.recyclerview.widget.RecyclerView
11+
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
1012
import com.google.android.material.bottomsheet.BottomSheetBehavior
1113
import com.google.android.material.bottomsheet.BottomSheetDialog
1214
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
1315
import org.wordpress.android.R
1416
import org.wordpress.android.WordPress
15-
import org.wordpress.android.databinding.RecyclerViewBottomSheetBinding
17+
import org.wordpress.android.databinding.RecyclerViewPrimaryButtonBottomSheetBinding
18+
import org.wordpress.android.ui.utils.UiHelpers
1619
import javax.inject.Inject
1720

1821
class BloggingReminderBottomSheetFragment : BottomSheetDialogFragment() {
1922
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
2023
@Inject lateinit var adapter: BloggingRemindersAdapter
24+
@Inject lateinit var uiHelpers: UiHelpers
2125
private lateinit var viewModel: BloggingRemindersViewModel
2226

2327
override fun onCreateView(
2428
inflater: LayoutInflater,
2529
container: ViewGroup?,
2630
savedInstanceState: Bundle?
2731
): View? {
28-
return inflater.inflate(R.layout.recycler_view_bottom_sheet, container)
32+
return inflater.inflate(R.layout.recycler_view_primary_button_bottom_sheet, container)
2933
}
3034

3135
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
3236
super.onViewCreated(view, savedInstanceState)
3337

34-
with(RecyclerViewBottomSheetBinding.bind(view)) {
38+
with(RecyclerViewPrimaryButtonBottomSheetBinding.bind(view)) {
3539
contentRecyclerView.layoutManager = LinearLayoutManager(requireActivity())
3640
contentRecyclerView.adapter = adapter
37-
41+
contentRecyclerView.addOnScrollListener(object : OnScrollListener() {
42+
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
43+
super.onScrolled(recyclerView, dx, dy)
44+
if (recyclerView.canScrollVertically(1)) {
45+
// Show shadow when not at the bottom
46+
bottomShadow.animate().alpha(1.0f).start()
47+
} else {
48+
// Hide shadow at the bottom
49+
bottomShadow.animate().alpha(0.0f).start()
50+
}
51+
}
52+
})
3853
viewModel =
39-
ViewModelProvider(requireActivity(), viewModelFactory).get(BloggingRemindersViewModel::class.java)
40-
viewModel.uiState.observe(this@BloggingReminderBottomSheetFragment) {
41-
(contentRecyclerView.adapter as? BloggingRemindersAdapter)?.update(it ?: listOf())
54+
ViewModelProvider(requireActivity(), viewModelFactory).get(BloggingRemindersViewModel::class.java)
55+
viewModel.uiState.observe(this@BloggingReminderBottomSheetFragment) { uiState ->
56+
(contentRecyclerView.adapter as? BloggingRemindersAdapter)?.update(uiState?.uiItems ?: listOf())
57+
if (uiState?.primaryButton != null) {
58+
primaryButton.visibility = View.VISIBLE
59+
uiHelpers.setTextOrHide(primaryButton, uiState.primaryButton.text)
60+
primaryButton.setOnClickListener { uiState.primaryButton.onClick.click() }
61+
primaryButton.isEnabled = uiState.primaryButton.enabled
62+
} else {
63+
primaryButton.visibility = View.GONE
64+
}
4265
}
4366

4467
savedInstanceState?.let { viewModel.restoreState(it) }
4568

4669
(dialog as? BottomSheetDialog)?.apply {
4770
behavior.state = BottomSheetBehavior.STATE_EXPANDED
71+
behavior.skipCollapsed = true
4872
}
4973
}
5074
}

WordPress/src/main/java/org/wordpress/android/ui/bloggingreminders/BloggingRemindersAdapter.kt

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,25 @@ package org.wordpress.android.ui.bloggingreminders
33
import android.view.ViewGroup
44
import androidx.recyclerview.widget.DiffUtil
55
import androidx.recyclerview.widget.RecyclerView.Adapter
6+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersDiffCallback.DayButtonsPayload
67
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.DayButtons
8+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.HighEmphasisText
79
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Illustration
810
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.MediumEmphasisText
9-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.PrimaryButton
10-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.HighEmphasisText
11+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Tip
1112
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Title
1213
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type
1314
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.DAY_BUTTONS
15+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.HIGH_EMPHASIS_TEXT
1416
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.ILLUSTRATION
1517
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.LOW_EMPHASIS_TEXT
16-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.PRIMARY_BUTTON
17-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.HIGH_EMPHASIS_TEXT
18+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.TIP
1819
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.TITLE
1920
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.DayButtonsViewHolder
21+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.HighEmphasisTextViewHolder
2022
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.IllustrationViewHolder
2123
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.MediumEmphasisTextViewHolder
22-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.PrimaryButtonViewHolder
23-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.HighEmphasisTextViewHolder
24+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.TipViewHolder
2425
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewHolder.TitleViewHolder
2526
import org.wordpress.android.ui.utils.UiHelpers
2627
import javax.inject.Inject
@@ -44,14 +45,18 @@ class BloggingRemindersAdapter
4445
override fun getItemCount(): Int = items.size
4546

4647
override fun onBindViewHolder(holder: BloggingRemindersViewHolder<*>, position: Int) {
48+
onBindViewHolder(holder, position, listOf())
49+
}
50+
51+
override fun onBindViewHolder(holder: BloggingRemindersViewHolder<*>, position: Int, payloads: List<Any>) {
4752
val item = items[position]
4853
when (holder) {
4954
is IllustrationViewHolder -> holder.onBind(item as Illustration)
5055
is TitleViewHolder -> holder.onBind(item as Title)
5156
is HighEmphasisTextViewHolder -> holder.onBind(item as HighEmphasisText)
5257
is MediumEmphasisTextViewHolder -> holder.onBind(item as MediumEmphasisText)
53-
is PrimaryButtonViewHolder -> holder.onBind(item as PrimaryButton)
54-
is DayButtonsViewHolder -> holder.onBind(item as DayButtons)
58+
is DayButtonsViewHolder -> holder.onBind(item as DayButtons, payloads.firstOrNull() as? DayButtonsPayload)
59+
is TipViewHolder -> holder.onBind(item as Tip)
5560
}
5661
}
5762

@@ -61,8 +66,8 @@ class BloggingRemindersAdapter
6166
ILLUSTRATION -> IllustrationViewHolder(parent)
6267
HIGH_EMPHASIS_TEXT -> HighEmphasisTextViewHolder(parent, uiHelpers)
6368
LOW_EMPHASIS_TEXT -> MediumEmphasisTextViewHolder(parent, uiHelpers)
64-
PRIMARY_BUTTON -> PrimaryButtonViewHolder(parent, uiHelpers)
6569
DAY_BUTTONS -> DayButtonsViewHolder(parent, uiHelpers)
70+
TIP -> TipViewHolder(parent, uiHelpers)
6671
}
6772
}
6873

WordPress/src/main/java/org/wordpress/android/ui/bloggingreminders/BloggingRemindersDiffCallback.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.wordpress.android.ui.bloggingreminders
22

33
import androidx.recyclerview.widget.DiffUtil.Callback
4+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.DayButtons
45

56
class BloggingRemindersDiffCallback(
67
private val oldList: List<BloggingRemindersItem>,
@@ -21,4 +22,17 @@ class BloggingRemindersDiffCallback(
2122
val newItem = newList[newItemPosition]
2223
return oldItem == newItem
2324
}
25+
26+
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
27+
val oldItem = oldList[oldItemPosition]
28+
val newItem = newList[newItemPosition]
29+
if (oldItem is DayButtons && newItem is DayButtons) {
30+
return DayButtonsPayload(oldItem.dayItems.mapIndexed { index, dayItem ->
31+
dayItem != newItem.dayItems[index]
32+
}.toList())
33+
}
34+
return super.getChangePayload(oldItemPosition, newItemPosition)
35+
}
36+
37+
data class DayButtonsPayload(val changedDays: List<Boolean>)
2438
}

WordPress/src/main/java/org/wordpress/android/ui/bloggingreminders/BloggingRemindersItem.kt

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,41 @@ import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.DAY
66
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.HIGH_EMPHASIS_TEXT
77
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.ILLUSTRATION
88
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.LOW_EMPHASIS_TEXT
9-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.PRIMARY_BUTTON
9+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.TIP
1010
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Type.TITLE
1111
import org.wordpress.android.ui.utils.ListItemInteraction
1212
import org.wordpress.android.ui.utils.UiString
1313

1414
sealed class BloggingRemindersItem(val type: Type) {
1515
enum class Type {
16-
ILLUSTRATION, TITLE, HIGH_EMPHASIS_TEXT, LOW_EMPHASIS_TEXT, PRIMARY_BUTTON, DAY_BUTTONS
16+
ILLUSTRATION, TITLE, HIGH_EMPHASIS_TEXT, LOW_EMPHASIS_TEXT, DAY_BUTTONS, TIP
1717
}
1818

1919
data class Illustration(@DrawableRes val illustration: Int) : BloggingRemindersItem(ILLUSTRATION)
2020
data class Title(val text: UiString) : BloggingRemindersItem(TITLE)
21-
data class HighEmphasisText(val text: UiString) : BloggingRemindersItem(HIGH_EMPHASIS_TEXT)
22-
data class MediumEmphasisText(val text: UiString) : BloggingRemindersItem(LOW_EMPHASIS_TEXT)
21+
data class HighEmphasisText(val text: EmphasizedText) : BloggingRemindersItem(
22+
HIGH_EMPHASIS_TEXT
23+
) {
24+
constructor(uiString: UiString) : this(EmphasizedText(uiString))
25+
}
26+
27+
data class MediumEmphasisText(val text: EmphasizedText?, val isInvisible: Boolean = false) : BloggingRemindersItem(
28+
LOW_EMPHASIS_TEXT
29+
) {
30+
constructor(uiString: UiString) : this(EmphasizedText(uiString, false))
31+
}
32+
33+
data class EmphasizedText(val text: UiString, val emphasizeTextParams: Boolean = true)
34+
2335
data class DayButtons(val dayItems: List<DayItem>) : BloggingRemindersItem(DAY_BUTTONS) {
2436
init {
2537
assert(dayItems.size == BloggingRemindersModel.Day.values().size) {
2638
"7 days need to be defined"
2739
}
2840
}
41+
2942
data class DayItem(val text: UiString, val isSelected: Boolean, val onClick: ListItemInteraction)
3043
}
31-
data class PrimaryButton(val text: UiString, val enabled: Boolean, val onClick: ListItemInteraction) :
32-
BloggingRemindersItem(PRIMARY_BUTTON)
44+
45+
data class Tip(val title: UiString, val message: UiString) : BloggingRemindersItem(TIP)
3346
}

WordPress/src/main/java/org/wordpress/android/ui/bloggingreminders/BloggingRemindersViewHolder.kt

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
package org.wordpress.android.ui.bloggingreminders
22

3+
import android.graphics.Typeface
4+
import android.text.Spannable
5+
import android.text.SpannableString
6+
import android.text.style.StyleSpan
7+
import android.view.View
38
import android.view.ViewGroup
49
import android.widget.TextView
510
import androidx.recyclerview.widget.RecyclerView
611
import androidx.viewbinding.ViewBinding
712
import org.wordpress.android.databinding.BloggingRemindersDayButtonsBinding
813
import org.wordpress.android.databinding.BloggingRemindersIllustrationBinding
9-
import org.wordpress.android.databinding.BloggingRemindersPrimaryButtonBinding
1014
import org.wordpress.android.databinding.BloggingRemindersTextHighEmphasisBinding
1115
import org.wordpress.android.databinding.BloggingRemindersTextMediumEmphasisBinding
16+
import org.wordpress.android.databinding.BloggingRemindersTipBinding
1217
import org.wordpress.android.databinding.BloggingRemindersTitleBinding
18+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersDiffCallback.DayButtonsPayload
1319
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.DayButtons
1420
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.DayButtons.DayItem
15-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Illustration
16-
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.PrimaryButton
21+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.EmphasizedText
1722
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.HighEmphasisText
23+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Illustration
1824
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.MediumEmphasisText
25+
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Tip
1926
import org.wordpress.android.ui.bloggingreminders.BloggingRemindersItem.Title
2027
import org.wordpress.android.ui.utils.UiHelpers
28+
import org.wordpress.android.ui.utils.UiString.UiStringResWithParams
2129
import org.wordpress.android.util.viewBinding
2230

2331
sealed class BloggingRemindersViewHolder<T : ViewBinding>(protected val binding: T) :
@@ -51,7 +59,7 @@ sealed class BloggingRemindersViewHolder<T : ViewBinding>(protected val binding:
5159
)
5260
) {
5361
fun onBind(item: HighEmphasisText) = with(binding) {
54-
uiHelpers.setTextOrHide(text, item.text)
62+
text.drawEmphasizedText(uiHelpers, item.text)
5563
}
5664
}
5765

@@ -62,22 +70,37 @@ sealed class BloggingRemindersViewHolder<T : ViewBinding>(protected val binding:
6270
)
6371
) {
6472
fun onBind(item: MediumEmphasisText) = with(binding) {
65-
uiHelpers.setTextOrHide(text, item.text)
73+
if (item.isInvisible) {
74+
text.visibility = View.INVISIBLE
75+
} else {
76+
if (item.text != null) {
77+
text.drawEmphasizedText(uiHelpers, item.text)
78+
}
79+
text.visibility = View.VISIBLE
80+
}
6681
}
6782
}
6883

69-
class PrimaryButtonViewHolder(parentView: ViewGroup, private val uiHelpers: UiHelpers) :
70-
BloggingRemindersViewHolder<BloggingRemindersPrimaryButtonBinding>(
71-
parentView.viewBinding(
72-
BloggingRemindersPrimaryButtonBinding::inflate
73-
)
74-
) {
75-
fun onBind(item: PrimaryButton) = with(binding) {
76-
uiHelpers.setTextOrHide(primaryButton, item.text)
77-
primaryButton.setOnClickListener {
78-
item.onClick.click()
84+
fun TextView.drawEmphasizedText(uiHelpers: UiHelpers, text: EmphasizedText) {
85+
val message = text.text
86+
if (text.emphasizeTextParams && message is UiStringResWithParams) {
87+
val params = message.params.map { uiHelpers.getTextOfUiString(this.context, it) as String }
88+
val textOfUiString = uiHelpers.getTextOfUiString(this.context, message)
89+
val spannable = SpannableString(textOfUiString)
90+
var index = 0
91+
for (param in params) {
92+
val indexOfParam = textOfUiString.indexOf(param, index)
93+
spannable.setSpan(
94+
StyleSpan(Typeface.BOLD),
95+
indexOfParam,
96+
indexOfParam + param.length,
97+
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
98+
)
99+
index = textOfUiString.indexOf(param)
79100
}
80-
primaryButton.isEnabled = item.enabled
101+
this.text = spannable
102+
} else {
103+
uiHelpers.setTextOrHide(this, message)
81104
}
82105
}
83106

@@ -87,7 +110,7 @@ sealed class BloggingRemindersViewHolder<T : ViewBinding>(protected val binding:
87110
BloggingRemindersDayButtonsBinding::inflate
88111
)
89112
) {
90-
fun onBind(item: DayButtons) = with(binding) {
113+
fun onBind(item: DayButtons, payload: DayButtonsPayload?) = with(binding) {
91114
listOf(
92115
dayOne,
93116
dayTwo,
@@ -96,7 +119,13 @@ sealed class BloggingRemindersViewHolder<T : ViewBinding>(protected val binding:
96119
dayFive,
97120
daySix,
98121
daySeven
99-
).forEachIndexed { index, day -> day.initDay(item.dayItems[index]) }
122+
).forEachIndexed { index, day ->
123+
if (payload == null) {
124+
day.initDay(item.dayItems[index])
125+
} else if (payload.changedDays[index]) {
126+
day.isSelected = item.dayItems[index].isSelected
127+
}
128+
}
100129
}
101130

102131
private fun TextView.initDay(dayItem: DayItem) {
@@ -105,4 +134,16 @@ sealed class BloggingRemindersViewHolder<T : ViewBinding>(protected val binding:
105134
isSelected = dayItem.isSelected
106135
}
107136
}
137+
138+
class TipViewHolder(parentView: ViewGroup, private val uiHelpers: UiHelpers) :
139+
BloggingRemindersViewHolder<BloggingRemindersTipBinding>(
140+
parentView.viewBinding(
141+
BloggingRemindersTipBinding::inflate
142+
)
143+
) {
144+
fun onBind(item: Tip) = with(binding) {
145+
uiHelpers.setTextOrHide(title, item.title)
146+
uiHelpers.setTextOrHide(message, item.message)
147+
}
148+
}
108149
}

0 commit comments

Comments
 (0)