Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@ import android.os.Bundle
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView.Adapter
import org.wordpress.android.ui.layoutpicker.LayoutCategoryViewType.DEFAULT
import org.wordpress.android.ui.layoutpicker.LayoutCategoryViewType.RECOMMENDED

enum class LayoutCategoryViewType {
DEFAULT,
RECOMMENDED,
}

/**
* Renders the layout categories
*/
class LayoutCategoryAdapter(
private var nestedScrollStates: Bundle,
private val thumbDimensionProvider: ThumbDimensionProvider
private val thumbDimensionProvider: ThumbDimensionProvider,
private val recommendedDimensionProvider: ThumbDimensionProvider? = null,
private val showRowDividers: Boolean = true
) : Adapter<LayoutsItemViewHolder>() {
private var items: List<LayoutCategoryUiState> = listOf()

Expand All @@ -31,6 +40,10 @@ class LayoutCategoryAdapter(
holder.bind(items[position])
}

override fun getItemViewType(position: Int): Int {
return if (items[position].isRecommended) RECOMMENDED.ordinal else DEFAULT.ordinal
}

override fun onViewRecycled(holder: LayoutsItemViewHolder) {
super.onViewRecycled(holder)
holder.onRecycled()
Expand All @@ -40,7 +53,9 @@ class LayoutCategoryAdapter(
LayoutsItemViewHolder(
parent = parent,
nestedScrollStates = nestedScrollStates,
thumbDimensionProvider = thumbDimensionProvider
thumbDimensionProvider = thumbDimensionProvider,
recommendedDimensionProvider = recommendedDimensionProvider,
showRowDividers = showRowDividers
)

fun onRestoreInstanceState(savedInstanceState: Bundle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ class LayoutCategoryDiffCallback(
) : Callback() {
object Payload
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return newList[newItemPosition].slug == oldList[oldItemPosition].slug
return newList[newItemPosition].isRecommended == oldList[oldItemPosition].isRecommended &&
newList[newItemPosition].slug == oldList[oldItemPosition].slug
}

override fun getOldListSize(): Int = oldList.size

override fun getNewListSize(): Int = newList.size

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return newList[newItemPosition].layouts == oldList[oldItemPosition].layouts
return newList[newItemPosition].isRecommended == oldList[oldItemPosition].isRecommended &&
newList[newItemPosition].layouts == oldList[oldItemPosition].layouts
}

override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import org.wordpress.android.fluxc.network.rest.wpcom.theme.StarterDesignCategor
@SuppressLint("ParcelCreator")
class LayoutCategoryModel(
private val starterDesignCategory: StarterDesignCategory? = null,
private val blockLayoutCategory: GutenbergLayoutCategory? = null
private val blockLayoutCategory: GutenbergLayoutCategory? = null,
val isRecommended: Boolean = false
) : Parcelable {
val slug: String
get() = starterDesignCategory?.slug ?: blockLayoutCategory?.slug ?: ""
Expand All @@ -23,7 +24,8 @@ class LayoutCategoryModel(
}

@JvmName("starterDesignToLayoutCategories")
fun List<StarterDesignCategory>.toLayoutCategories() = map { LayoutCategoryModel(starterDesignCategory = it) }
fun List<StarterDesignCategory>.toLayoutCategories(recommended: Boolean = false) =
map { LayoutCategoryModel(starterDesignCategory = it, isRecommended = recommended) }

@JvmName("gutenbergLayoutToLayoutCategories")
fun List<GutenbergLayoutCategory>.toLayoutCategories() = map { LayoutCategoryModel(blockLayoutCategory = it) }
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ package org.wordpress.android.ui.layoutpicker
* @param title the layout category title
* @param description the layout category description
* @param layouts the layouts list
* @param isRecommended defines if the category is recommended (optional with default `false`)
*/
data class LayoutCategoryUiState(
val slug: String,
val title: String,
val description: String,
val layouts: List<LayoutListItemUiState>
val layouts: List<LayoutListItemUiState>,
val isRecommended: Boolean = false
)
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ abstract class LayoutPickerViewModel(
category.slug,
category.title,
category.description,
layouts
layouts,
category.isRecommended
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,54 @@ package org.wordpress.android.ui.layoutpicker
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import org.wordpress.android.R
import org.wordpress.android.util.extensions.setVisible

/**
* Modal Layout Picker layouts view holder
*/
class LayoutsItemViewHolder(
parent: ViewGroup,
private val prefetchItemCount: Int = 4,
private val showRowDividers: Boolean,
private var nestedScrollStates: Bundle,
private val thumbDimensionProvider: ThumbDimensionProvider
private val thumbDimensionProvider: ThumbDimensionProvider,
private val recommendedDimensionProvider: ThumbDimensionProvider?
) : RecyclerView.ViewHolder(
LayoutInflater.from(
parent.context
).inflate(R.layout.modal_layout_picker_layouts_row, parent, false)
) {
private val title: TextView = itemView.findViewById(R.id.title)
private val subtitle: TextView = itemView.findViewById(R.id.subtitle)
private var currentItem: LayoutCategoryUiState? = null

private val recycler: RecyclerView by lazy {
val dimensionProvider = if (currentItem?.isRecommended == true && recommendedDimensionProvider != null) {
recommendedDimensionProvider
} else {
thumbDimensionProvider
}
itemView.updateLayoutParams {
height = thumbDimensionProvider.rowHeight
height = dimensionProvider.rowHeight
}
itemView.findViewById<View>(R.id.layouts_row_separator_line).isVisible = showRowDividers
itemView.findViewById<RecyclerView>(R.id.layouts_recycler_view).apply {
layoutManager = LinearLayoutManager(
context,
RecyclerView.HORIZONTAL,
false
).apply { initialPrefetchItemCount = prefetchItemCount }
setRecycledViewPool(RecyclerView.RecycledViewPool())
adapter = LayoutsAdapter(parent.context, thumbDimensionProvider)
adapter = LayoutsAdapter(parent.context, dimensionProvider)

addOnScrollListener(object : OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
Expand All @@ -54,6 +66,7 @@ class LayoutsItemViewHolder(
currentItem = category

title.text = category.description
subtitle.setVisible(category.isRecommended)
(recycler.adapter as LayoutsAdapter).setData(category.layouts)
restoreScrollState(recycler, category.title)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.wordpress.android.ui.layoutpicker
interface ThumbDimensionProvider {
val previewWidth: Int
val previewHeight: Int
val scale: Double
val rowHeight: Int
val scale: Double
get() = 1.0 // Passing 1.0 and the rendered pixels per device in previewWidth
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ class ModalLayoutPickerDimensionProvider @Inject constructor(private val context
override val previewHeight: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.mlp_layout_card_height)

override val scale: Double = 1.0 // Passing 1.0 and the rendered pixels per device in previewWidth

override val rowHeight: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.mlp_layouts_row_height)
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class HomePagePickerFragment : Fragment() {
@Inject lateinit var siteNameFeatureConfig: SiteNameFeatureConfig
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
@Inject lateinit var thumbDimensionProvider: SiteDesignPickerDimensionProvider
@Inject lateinit var recommendedDimensionProvider: SiteDesignRecommendedDimensionProvider
private lateinit var viewModel: HomePagePickerViewModel

override fun onAttach(context: Context) {
Expand All @@ -64,7 +65,12 @@ class HomePagePickerFragment : Fragment() {
categoriesRecyclerView.isGone = true
layoutsRecyclerView.apply {
layoutManager = LinearLayoutManager(requireActivity())
adapter = LayoutCategoryAdapter(viewModel.nestedScrollStates, thumbDimensionProvider)
adapter = LayoutCategoryAdapter(
viewModel.nestedScrollStates,
thumbDimensionProvider,
recommendedDimensionProvider,
showRowDividers = false
)
}

setupUi()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import org.wordpress.android.R
import org.wordpress.android.fluxc.Dispatcher
import org.wordpress.android.fluxc.network.rest.wpcom.theme.StarterDesignCategory
import org.wordpress.android.modules.BG_THREAD
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.layoutpicker.LayoutCategoryModel
import org.wordpress.android.ui.sitecreation.misc.SiteCreationErrorType.INTERNET_UNAVAILABLE_ERROR
import org.wordpress.android.ui.sitecreation.misc.SiteCreationErrorType.UNKNOWN
import org.wordpress.android.ui.sitecreation.misc.SiteCreationTracker
Expand All @@ -18,6 +20,7 @@ import org.wordpress.android.ui.layoutpicker.toLayoutCategories
import org.wordpress.android.ui.layoutpicker.toLayoutModels
import org.wordpress.android.ui.sitecreation.usecases.FetchHomePageLayoutsUseCase
import org.wordpress.android.util.NetworkUtilsWrapper
import org.wordpress.android.viewmodel.ResourceProvider
import org.wordpress.android.viewmodel.SingleLiveEvent
import javax.inject.Inject
import javax.inject.Named
Expand All @@ -32,7 +35,8 @@ class HomePagePickerViewModel @Inject constructor(
private val fetchHomePageLayoutsUseCase: FetchHomePageLayoutsUseCase,
private val analyticsTracker: SiteCreationTracker,
@Named(BG_THREAD) override val bgDispatcher: CoroutineDispatcher,
@Named(UI_THREAD) override val mainDispatcher: CoroutineDispatcher
@Named(UI_THREAD) override val mainDispatcher: CoroutineDispatcher,
private val resourceProvider: ResourceProvider
) : LayoutPickerViewModel(mainDispatcher, bgDispatcher, networkUtils, analyticsTracker) {
private val _onDesignActionPressed = SingleLiveEvent<DesignSelectionAction>()
val onDesignActionPressed: LiveData<DesignSelectionAction> = _onDesignActionPressed
Expand Down Expand Up @@ -81,12 +85,21 @@ class HomePagePickerViewModel @Inject constructor(
analyticsTracker.trackErrorShown(ERROR_CONTEXT, UNKNOWN, "Error fetching designs")
updateUiState(Error())
} else {
handleResponse(event.designs.toLayoutModels(), event.categories.toLayoutCategories())
handleResponse(event.designs.toLayoutModels(), categoriesWithRecommendations(event.categories))
}
}
}
}

private fun categoriesWithRecommendations(categories: List<StarterDesignCategory>): List<LayoutCategoryModel> {
val defaultVertical = resourceProvider.getString(R.string.hpp_recommended_default_vertical)
val recommendedVertical = resourceProvider.getString(R.string.hpp_recommended_title, defaultVertical)
// TODO: The link with the selected vertical and actual fallback recommendations will be implemented separately
val recommendedCategory = categories.first { it.slug == "blog" }
.copy(title = recommendedVertical, description = recommendedVertical)
return listOf(recommendedCategory).toLayoutCategories(true) + categories.toLayoutCategories()
}

override fun onLayoutTapped(layoutSlug: String) {
(uiState.value as? Content)?.let {
if (it.loadedThumbnailSlugs.contains(layoutSlug)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ class SiteDesignPickerDimensionProvider @Inject constructor(private val contextP
override val previewHeight: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.hpp_layout_card_height)

override val scale: Double = 1.0 // Passing 1.0 and the rendered pixels per device in previewWidth

override val rowHeight: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.hpp_layouts_row_height)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.wordpress.android.ui.sitecreation.theme

import org.wordpress.android.R.dimen
import org.wordpress.android.ui.layoutpicker.ThumbDimensionProvider
import org.wordpress.android.viewmodel.ContextProvider
import javax.inject.Inject

class SiteDesignRecommendedDimensionProvider @Inject constructor(private val contextProvider: ContextProvider) :
ThumbDimensionProvider {
override val previewWidth: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.hpp_recommended_card_width)

override val previewHeight: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.hpp_recommended_card_height)

override val rowHeight: Int
get() = contextProvider.getContext().resources.getDimensionPixelSize(dimen.hpp_recommended_row_height)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@
android:layout_height="@dimen/mlp_layouts_row_height"
android:orientation="vertical">

<View style="@style/ModalLayoutPickerLayoutsSeparatorLine" />
<View
android:id="@+id/layouts_row_separator_line"
style="@style/ModalLayoutPickerLayoutsSeparatorLine" />

<TextView
android:id="@+id/subtitle"
style="@style/ModalLayoutPickerLayoutsSubtitle"
android:layout_marginStart="@dimen/mlp_layout_card_margin_start"
android:text="@string/hpp_recommended_subtitle" />
<TextView
android:id="@+id/title"
style="@style/ModalLayoutPickerLayoutsTitle"
Expand Down
3 changes: 3 additions & 0 deletions WordPress/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,9 @@
<dimen name="hpp_layout_card_height">260dp</dimen>
<dimen name="hpp_layout_card_width">200dp</dimen>
<dimen name="hpp_layouts_row_height">330dp</dimen>
<dimen name="hpp_recommended_card_height">420dp</dimen>
<dimen name="hpp_recommended_card_width">320dp</dimen>
<dimen name="hpp_recommended_row_height">500dp</dimen>

<!-- Site Intent Question -->
<dimen name="siq_title_padding_start">@dimen/margin_extra_extra_large</dimen>
Expand Down
3 changes: 3 additions & 0 deletions WordPress/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3379,6 +3379,9 @@
<string name="hpp_error_subtitle">Tap retry when you\'re back online.</string>
<string name="hpp_retry_error">Please Check your internet connection and retry.</string>
<string name="hpp_choose_error">There was an error while selecting the theme.</string>
<string name="hpp_recommended_title">Best for %s</string>
<string name="hpp_recommended_subtitle">Picked for you</string>
<string name="hpp_recommended_default_vertical">Blogging</string>

<!-- Stories -->
<string name="dialog_edit_story_limited_title">Limited Story Editing</string>
Expand Down
8 changes: 8 additions & 0 deletions WordPress/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,14 @@
<item name="android:textAppearance">?attr/textAppearanceHeadline5</item>
<item name="fontFamily">serif</item>
</style>
<style name="ModalLayoutPickerLayoutsSubtitle" parent="ModalLayoutPickerText">
<item name="android:textAlignment">viewStart</item>
<item name="android:layout_gravity">top</item>
<item name="android:textSize">@dimen/text_sz_small</item>
<item name="android:textStyle">bold</item>
<item name="android:textAppearance">?attr/textAppearanceCaption</item>
<item name="fontFamily">serif</item>
</style>

<style name="ModalLayoutPickerLayoutsSeparatorLine">
<item name="android:background">?attr/mlpDividerColor</item>
Expand Down
Loading