From b200e6d5d6a7905d2f4566f58084d9ca3adc3fca Mon Sep 17 00:00:00 2001 From: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com> Date: Wed, 19 Apr 2023 01:12:39 +0300 Subject: [PATCH] Revert "Fix part of #632: Move PromotedStoryListAdapter to BindableAdater (#4874)" This reverts commit 7fd290d68f0440d926f2d443dbd7bfb28ab20547. --- app/BUILD.bazel | 1 - .../databinding/MarginBindingAdapters.java | 43 +++- .../PromotedStoryListAdapter.kt | 110 +++++++++ .../RecentlyPlayedFragmentPresenter.kt | 227 ++++++++++++++---- .../recentlyplayed/RecentlyPlayedViewModel.kt | 172 ------------- .../res/layout/recently_played_fragment.xml | 10 +- scripts/assets/test_file_exemptions.textproto | 1 - 7 files changed, 323 insertions(+), 241 deletions(-) create mode 100644 app/src/main/java/org/oppia/android/app/home/recentlyplayed/PromotedStoryListAdapter.kt delete mode 100644 app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedViewModel.kt diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 03228b87d56..807971798d3 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -209,7 +209,6 @@ VIEW_MODELS_WITH_RESOURCE_IMPORTS = [ "src/main/java/org/oppia/android/app/home/promotedlist/PromotedStoryListViewModel.kt", "src/main/java/org/oppia/android/app/home/promotedlist/PromotedStoryViewModel.kt", "src/main/java/org/oppia/android/app/home/recentlyplayed/PromotedStoryViewModel.kt", - "src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedViewModel.kt", "src/main/java/org/oppia/android/app/home/topiclist/TopicSummaryViewModel.kt", "src/main/java/org/oppia/android/app/onboarding/OnboadingSlideViewModel.kt", "src/main/java/org/oppia/android/app/onboarding/OnboardingViewModel.kt", diff --git a/app/src/main/java/org/oppia/android/app/databinding/MarginBindingAdapters.java b/app/src/main/java/org/oppia/android/app/databinding/MarginBindingAdapters.java index e8ea574edfb..5c336d0c05c 100644 --- a/app/src/main/java/org/oppia/android/app/databinding/MarginBindingAdapters.java +++ b/app/src/main/java/org/oppia/android/app/databinding/MarginBindingAdapters.java @@ -3,7 +3,7 @@ import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import androidx.annotation.NonNull; -import androidx.core.view.MarginLayoutParamsCompat; +import androidx.core.view.ViewCompat; import androidx.databinding.BindingAdapter; /** Holds all custom binding adapters that set margin values. */ @@ -14,7 +14,12 @@ public final class MarginBindingAdapters { public static void setLayoutMarginStart(@NonNull View view, float marginStart) { if (view.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); - MarginLayoutParamsCompat.setMarginStart(params, (int) marginStart); + float marginEnd = params.getMarginEnd(); + if (isRtlLayout(view)) { + setLayoutDirectionalMargins(view, (int) marginEnd, (int) marginStart); + } else { + setLayoutDirectionalMargins(view, (int) marginStart, (int) marginEnd); + } view.requestLayout(); } } @@ -24,17 +29,36 @@ public static void setLayoutMarginStart(@NonNull View view, float marginStart) { public static void setLayoutMarginEnd(@NonNull View view, float marginEnd) { if (view.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); - MarginLayoutParamsCompat.setMarginEnd(params, (int) marginEnd); + float marginStart = params.getMarginStart(); + if (isRtlLayout(view)) { + setLayoutDirectionalMargins(view, (int) marginEnd, (int) marginStart); + } else { + setLayoutDirectionalMargins(view, (int) marginStart, (int) marginEnd); + } view.requestLayout(); } } + private static void setLayoutDirectionalMargins( + @NonNull View view, + int marginStart, + int marginEnd + ) { + MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); + params.setMargins(marginStart, params.topMargin, marginEnd, params.bottomMargin); + } + /** Used to set a margin-top for views. */ @BindingAdapter("app:layoutMarginTop") public static void setLayoutMarginTop(@NonNull View view, float marginTop) { if (view.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); - params.topMargin = (int) marginTop; + params.setMargins( + params.getMarginStart(), + (int) marginTop, + params.getMarginEnd(), + params.bottomMargin + ); view.requestLayout(); } } @@ -44,7 +68,12 @@ public static void setLayoutMarginTop(@NonNull View view, float marginTop) { public static void setLayoutMarginBottom(@NonNull View view, float marginBottom) { if (view.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); - params.bottomMargin = (int) marginBottom; + params.setMargins( + params.getMarginStart(), + params.topMargin, + params.getMarginEnd(), + (int) marginBottom + ); view.requestLayout(); } } @@ -63,4 +92,8 @@ public static void setLayoutMargin(@NonNull View view, float margin) { view.requestLayout(); } } + + private static boolean isRtlLayout(View view) { + return ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL; + } } diff --git a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/PromotedStoryListAdapter.kt b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/PromotedStoryListAdapter.kt new file mode 100644 index 00000000000..61bcf6bf5e6 --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/PromotedStoryListAdapter.kt @@ -0,0 +1,110 @@ +package org.oppia.android.app.home.recentlyplayed + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.oppia.android.databinding.RecentlyPlayedStoryCardBinding +import org.oppia.android.databinding.SectionTitleBinding + +private const val VIEW_TYPE_SECTION_TITLE_TEXT = 1 +private const val VIEW_TYPE_SECTION_STORY_ITEM = 2 + +/** + * Adapter to inflate different items/views inside [RecyclerView] for Ongoing Story List. + * + * @property itemList the items that may be displayed in [RecentlyPlayedFragment]'s recycler view + */ +class PromotedStoryListAdapter( + private val itemList: MutableList +) : RecyclerView.Adapter() { + + private var titleIndex: Int = 0 + private var storyGridPosition: Int = 0 + private var spanCount = 0 + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + // TODO(#632): Generalize this binding to make adding future items easier. + VIEW_TYPE_SECTION_TITLE_TEXT -> { + val inflater = LayoutInflater.from(parent.context) + val binding = + SectionTitleBinding.inflate( + inflater, + parent, + /* attachToParent= */ false + ) + SectionTitleViewHolder(binding) + } + VIEW_TYPE_SECTION_STORY_ITEM -> { + val inflater = LayoutInflater.from(parent.context) + val binding = + RecentlyPlayedStoryCardBinding.inflate( + inflater, + parent, + /* attachToParent= */ false + ) + PromotedStoryViewHolder(binding) + } + else -> throw IllegalArgumentException("Invalid view type: $viewType") + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) = + when (holder.itemViewType) { + VIEW_TYPE_SECTION_TITLE_TEXT -> { + titleIndex = position + (holder as SectionTitleViewHolder).bind(itemList[position] as SectionTitleViewModel) + } + VIEW_TYPE_SECTION_STORY_ITEM -> { + storyGridPosition = position - titleIndex + (holder as PromotedStoryViewHolder).bind(itemList[position] as PromotedStoryViewModel) + } + else -> throw IllegalArgumentException("Invalid item view type: ${holder.itemViewType}") + } + + override fun getItemViewType(position: Int): Int { + return when (itemList[position]) { + is SectionTitleViewModel -> { + VIEW_TYPE_SECTION_TITLE_TEXT + } + is PromotedStoryViewModel -> { + VIEW_TYPE_SECTION_STORY_ITEM + } + else -> throw IllegalArgumentException( + "Invalid type of data $position with item ${itemList[position]}" + ) + } + } + + override fun getItemCount(): Int { + return itemList.size + } + +/** + * Specifies the number of columns of recently played stories shown in the recently played stories + * list. + * + * @param spanCount specifies the number of spaces this item should occupy, based on screen size + */ + fun setSpanCount(spanCount: Int) { + this.spanCount = spanCount + } + + private class SectionTitleViewHolder( + val binding: SectionTitleBinding + ) : RecyclerView.ViewHolder(binding.root) { + /** Binds the view model that sets section titles. */ + fun bind(sectionTitleViewModel: SectionTitleViewModel) { + binding.viewModel = sectionTitleViewModel + } + } + + private class PromotedStoryViewHolder( + val binding: RecentlyPlayedStoryCardBinding + ) : RecyclerView.ViewHolder(binding.root) { + /** Binds the view model that sets recently played items. */ + fun bind(promotedStoryViewModel: PromotedStoryViewModel) { + binding.viewModel = promotedStoryViewModel + } + } +} diff --git a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt index 22cfb0c5e40..11ace445d1e 100755 --- a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt @@ -5,7 +5,9 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment +import androidx.lifecycle.LiveData import androidx.lifecycle.Observer +import androidx.lifecycle.Transformations import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import org.oppia.android.R @@ -15,17 +17,19 @@ import org.oppia.android.app.model.ChapterPlayState import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId +import org.oppia.android.app.model.PromotedActivityList import org.oppia.android.app.model.PromotedStory -import org.oppia.android.app.recyclerview.BindableAdapter import org.oppia.android.app.topic.RouteToResumeLessonListener +import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.databinding.RecentlyPlayedFragmentBinding -import org.oppia.android.databinding.RecentlyPlayedStoryCardBinding -import org.oppia.android.databinding.SectionTitleBinding import org.oppia.android.domain.exploration.ExplorationDataController import org.oppia.android.domain.exploration.lightweightcheckpointing.ExplorationCheckpointController import org.oppia.android.domain.oppialogger.OppiaLogger +import org.oppia.android.domain.topic.TopicListController +import org.oppia.android.domain.translation.TranslationController import org.oppia.android.util.data.AsyncResult import org.oppia.android.util.data.DataProviders.Companion.toLiveData +import org.oppia.android.util.parser.html.StoryHtmlParserEntityType import javax.inject.Inject /** The presenter for [RecentlyPlayedFragment]. */ @@ -35,50 +39,189 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( private val fragment: Fragment, private val oppiaLogger: OppiaLogger, private val explorationDataController: ExplorationDataController, + private val topicListController: TopicListController, private val explorationCheckpointController: ExplorationCheckpointController, - private val multiTypeBuilderFactory: BindableAdapter.MultiTypeBuilder.Factory, - private val recentlyPlayedViewModelFactory: RecentlyPlayedViewModel.Factory + @StoryHtmlParserEntityType private val entityType: String, + private val resourceHandler: AppLanguageResourceHandler, + private val translationController: TranslationController ) { private val routeToResumeLessonListener = activity as RouteToResumeLessonListener private val routeToExplorationListener = activity as RouteToExplorationListener - - private lateinit var profileId: ProfileId + private var internalProfileId: Int = -1 private lateinit var binding: RecentlyPlayedFragmentBinding + private lateinit var promotedStoryListAdapter: PromotedStoryListAdapter + private val itemList: MutableList = ArrayList() fun handleCreateView( inflater: LayoutInflater, container: ViewGroup?, - profileId: Int + internalProfileId: Int ): View? { - this.profileId = ProfileId.newBuilder().setInternalId(profileId).build() - val recentlyPlayedViewModel = recentlyPlayedViewModelFactory.create( + binding = RecentlyPlayedFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) + + this.internalProfileId = internalProfileId + + promotedStoryListAdapter = PromotedStoryListAdapter(itemList) + binding.ongoingStoryRecyclerView.apply { + adapter = promotedStoryListAdapter + } + binding.lifecycleOwner = fragment + + subscribeToPromotedStoryList() + return binding.root + } + + private val promotedStoryListSummaryResultLiveData: + LiveData> + by lazy { + topicListController.getPromotedActivityList( + ProfileId.newBuilder().setInternalId(internalProfileId).build() + ).toLiveData() + } + + private fun subscribeToPromotedStoryList() { + getAssumedSuccessfulPromotedActivityList().observe( + fragment, + { + if (it.promotedStoryList.recentlyPlayedStoryList.isNotEmpty()) { + addRecentlyPlayedStoryListSection(it.promotedStoryList.recentlyPlayedStoryList) + } + + if (it.promotedStoryList.olderPlayedStoryList.isNotEmpty()) { + addOlderStoryListSection(it.promotedStoryList.olderPlayedStoryList) + } + + if (it.promotedStoryList.suggestedStoryList.isNotEmpty()) { + addRecommendedStoryListSection(it.promotedStoryList.suggestedStoryList) + } + + binding.ongoingStoryRecyclerView.layoutManager = + createLayoutManager( + it.promotedStoryList.recentlyPlayedStoryCount, + it.promotedStoryList.olderPlayedStoryCount, + it.promotedStoryList.suggestedStoryCount + ) + promotedStoryListAdapter.notifyDataSetChanged() + } + ) + } + + private fun addRecentlyPlayedStoryListSection( + recentlyPlayedStoryList: MutableList + ) { + itemList.clear() + val recentSectionTitleViewModel = + SectionTitleViewModel( + resourceHandler.getStringInLocale(R.string.ongoing_story_last_week), false + ) + itemList.add(recentSectionTitleViewModel) + recentlyPlayedStoryList.forEachIndexed { index, promotedStory -> + val ongoingStoryViewModel = createOngoingStoryViewModel(promotedStory, index) + itemList.add(ongoingStoryViewModel) + } + } + + private fun createOngoingStoryViewModel( + promotedStory: PromotedStory, + index: Int + ): RecentlyPlayedItemViewModel { + return PromotedStoryViewModel( + activity, + promotedStory, + entityType, fragment as PromotedStoryClickListener, - this.profileId + index, + resourceHandler, + translationController ) - binding = - RecentlyPlayedFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false).apply { - lifecycleOwner = fragment - viewModel = recentlyPlayedViewModel - val adapter = createRecyclerViewAdapter() - ongoingStoryRecyclerView.layoutManager = createLayoutManager(adapter) - ongoingStoryRecyclerView.adapter = adapter - } + } - return binding.root + private fun addOlderStoryListSection(olderPlayedStoryList: List) { + val showDivider = itemList.isNotEmpty() + val olderSectionTitleViewModel = + SectionTitleViewModel( + resourceHandler.getStringInLocale(R.string.ongoing_story_last_month), + showDivider + ) + itemList.add(olderSectionTitleViewModel) + olderPlayedStoryList.forEachIndexed { index, promotedStory -> + val ongoingStoryViewModel = createOngoingStoryViewModel(promotedStory, index) + itemList.add(ongoingStoryViewModel) + } + } + + private fun addRecommendedStoryListSection(suggestedStoryList: List) { + val showDivider = itemList.isNotEmpty() + val recommendedSectionTitleViewModel = + SectionTitleViewModel( + resourceHandler.getStringInLocale(R.string.recommended_stories), + showDivider + ) + itemList.add(recommendedSectionTitleViewModel) + suggestedStoryList.forEachIndexed { index, suggestedStory -> + val ongoingStoryViewModel = createOngoingStoryViewModel(suggestedStory, index) + itemList.add(ongoingStoryViewModel) + } + } + + private fun getAssumedSuccessfulPromotedActivityList(): LiveData { + return Transformations.map(promotedStoryListSummaryResultLiveData) { + when (it) { + // If there's an error loading the data, assume the default. + is AsyncResult.Failure, is AsyncResult.Pending -> PromotedActivityList.getDefaultInstance() + is AsyncResult.Success -> it.value + } + } } private fun createLayoutManager( - adapter: BindableAdapter + recentStoryCount: Int, + oldStoryCount: Int, + suggestedStoryCount: Int ): RecyclerView.LayoutManager { + val sectionTitle0Position = if (recentStoryCount == 0) { + // If recent story count is 0, that means that section title 0 will not be visible. + -1 + } else { + 0 + } + val sectionTitle1Position = if (oldStoryCount == 0) { + // If old story count is 0, that means that section title 1 will not be visible. + -1 + } else if (recentStoryCount == 0) { + 0 + } else { + recentStoryCount + 1 + } + val sectionTitle2Position = when { + suggestedStoryCount == 0 -> { + -1 // If suggested story count is 0, that means that section title 1 will not be visible. + } + oldStoryCount == 0 && recentStoryCount == 0 -> { + 0 + } + oldStoryCount > 0 && recentStoryCount > 0 -> { + recentStoryCount + oldStoryCount + 2 + } + else -> { + recentStoryCount + oldStoryCount + 1 + } + } + val spanCount = activity.resources.getInteger(R.integer.recently_played_span_count) + promotedStoryListAdapter.setSpanCount(spanCount) + val layoutManager = GridLayoutManager(activity.applicationContext, spanCount) layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { override fun getSpanSize(position: Int): Int { - return if (adapter.getItemViewType(position) == ViewType.VIEW_TYPE_TITLE.ordinal) { - spanCount - } else { - 1 + return when (position) { + sectionTitle0Position, sectionTitle1Position, sectionTitle2Position -> { + /* number of spaces this item should occupy = */ spanCount + } + else -> { + /* number of spaces this item should occupy = */ 1 + } } } } @@ -86,6 +229,9 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( } fun promotedStoryClicked(promotedStory: PromotedStory) { + val profileId = ProfileId.newBuilder().apply { + internalId = internalProfileId + }.build() val canHavePartialProgressSaved = when (promotedStory.chapterPlayState) { ChapterPlayState.IN_PROGRESS_SAVED, ChapterPlayState.IN_PROGRESS_NOT_SAVED, @@ -136,31 +282,6 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( } } - private enum class ViewType { - VIEW_TYPE_TITLE, - VIEW_TYPE_PROMOTED_STORY - } - - private fun createRecyclerViewAdapter(): BindableAdapter { - return multiTypeBuilderFactory.create { viewModel -> - when (viewModel) { - is PromotedStoryViewModel -> ViewType.VIEW_TYPE_PROMOTED_STORY - is SectionTitleViewModel -> ViewType.VIEW_TYPE_TITLE - else -> throw IllegalArgumentException("Encountered unexpected view model: $viewModel") - } - }.registerViewDataBinder( - viewType = ViewType.VIEW_TYPE_TITLE, - inflateDataBinding = SectionTitleBinding::inflate, - setViewModel = SectionTitleBinding::setViewModel, - transformViewModel = { it as SectionTitleViewModel } - ).registerViewDataBinder( - viewType = ViewType.VIEW_TYPE_PROMOTED_STORY, - inflateDataBinding = RecentlyPlayedStoryCardBinding::inflate, - setViewModel = RecentlyPlayedStoryCardBinding::setViewModel, - transformViewModel = { it as PromotedStoryViewModel } - ).build() - } - private fun playExploration( topicId: String, storyId: String, @@ -174,13 +295,13 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( // cases, lessons played from this fragment are known to be in progress, and that progress // can't be resumed here (hence the restart). explorationDataController.restartExploration( - profileId.internalId, topicId, storyId, explorationId + internalProfileId, topicId, storyId, explorationId ) } else { // The only lessons that can't have their progress saved are those that were already // completed. explorationDataController.replayExploration( - profileId.internalId, topicId, storyId, explorationId + internalProfileId, topicId, storyId, explorationId ) } startPlayingProvider.toLiveData().observe(fragment) { result -> @@ -191,7 +312,7 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( is AsyncResult.Success -> { oppiaLogger.d("RecentlyPlayedFragment", "Successfully loaded exploration") routeToExplorationListener.routeToExploration( - profileId, + ProfileId.newBuilder().apply { internalId = internalProfileId }.build(), topicId, storyId, explorationId, diff --git a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedViewModel.kt b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedViewModel.kt deleted file mode 100644 index a21c65a1cba..00000000000 --- a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedViewModel.kt +++ /dev/null @@ -1,172 +0,0 @@ -package org.oppia.android.app.home.recentlyplayed - -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations -import org.oppia.android.R -import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.model.PromotedActivityList -import org.oppia.android.app.model.PromotedStory -import org.oppia.android.app.translation.AppLanguageResourceHandler -import org.oppia.android.domain.topic.TopicListController -import org.oppia.android.domain.translation.TranslationController -import org.oppia.android.util.data.AsyncResult -import org.oppia.android.util.data.DataProviders.Companion.toLiveData -import org.oppia.android.util.parser.html.StoryHtmlParserEntityType -import javax.inject.Inject - -/** View model for [RecentlyPlayedFragment]. */ -class RecentlyPlayedViewModel private constructor( - private val activity: AppCompatActivity, - private val topicListController: TopicListController, - @StoryHtmlParserEntityType private val entityType: String, - private val resourceHandler: AppLanguageResourceHandler, - private val translationController: TranslationController, - private val promotedStoryClickListener: PromotedStoryClickListener, - private val profileId: ProfileId, -) { - - /** Factory of RecentlyPlayedViewModel. */ - class Factory @Inject constructor( - private val activity: AppCompatActivity, - private val topicListController: TopicListController, - @StoryHtmlParserEntityType private val entityType: String, - private val resourceHandler: AppLanguageResourceHandler, - private val translationController: TranslationController, - ) { - - /** Creates an instance of [RecentlyPlayedViewModel] */ - fun create( - promotedStoryClickListener: PromotedStoryClickListener, - profileId: ProfileId - ): RecentlyPlayedViewModel { - return RecentlyPlayedViewModel( - activity, - topicListController, - entityType, - resourceHandler, - translationController, - promotedStoryClickListener, - profileId, - ) - } - } - - /** - * [LiveData] with the list of recently played items for a ProfileId, organized in sections. - */ - val recentlyPlayedItems: LiveData> by lazy { - Transformations.map(promotedActivityListLiveData, ::processPromotedStoryList) - } - - private val promotedActivityListLiveData: LiveData by lazy { - getAssumedSuccessfulPromotedActivityList() - } - - private val promotedStoryListSummaryResultLiveData: - LiveData> - by lazy { - topicListController.getPromotedActivityList(profileId).toLiveData() - } - - private fun getAssumedSuccessfulPromotedActivityList(): LiveData { - return Transformations.map(promotedStoryListSummaryResultLiveData) { - when (it) { - // If there's an error loading the data, assume the default. - is AsyncResult.Failure, is AsyncResult.Pending -> PromotedActivityList.getDefaultInstance() - is AsyncResult.Success -> it.value - } - } - } - - private fun processPromotedStoryList( - promotedActivityList: PromotedActivityList - ): List { - val itemList: MutableList = mutableListOf() - if (promotedActivityList.promotedStoryList.recentlyPlayedStoryList.isNotEmpty()) { - addRecentlyPlayedStoryListSection( - promotedActivityList.promotedStoryList.recentlyPlayedStoryList, - itemList - ) - } - - if (promotedActivityList.promotedStoryList.olderPlayedStoryList.isNotEmpty()) { - addOlderStoryListSection( - promotedActivityList.promotedStoryList.olderPlayedStoryList, - itemList - ) - } - - if (promotedActivityList.promotedStoryList.suggestedStoryList.isNotEmpty()) { - addRecommendedStoryListSection( - promotedActivityList.promotedStoryList.suggestedStoryList, - itemList - ) - } - return itemList - } - - private fun addRecentlyPlayedStoryListSection( - recentlyPlayedStoryList: MutableList, - itemList: MutableList - ) { - val recentSectionTitleViewModel = - SectionTitleViewModel( - resourceHandler.getStringInLocale(R.string.ongoing_story_last_week), false - ) - itemList.add(recentSectionTitleViewModel) - recentlyPlayedStoryList.forEachIndexed { index, promotedStory -> - val ongoingStoryViewModel = createOngoingStoryViewModel(promotedStory, index) - itemList.add(ongoingStoryViewModel) - } - } - - private fun addOlderStoryListSection( - olderPlayedStoryList: List, - itemList: MutableList - ) { - val showDivider = itemList.isNotEmpty() - val olderSectionTitleViewModel = - SectionTitleViewModel( - resourceHandler.getStringInLocale(R.string.ongoing_story_last_month), - showDivider - ) - itemList.add(olderSectionTitleViewModel) - olderPlayedStoryList.forEachIndexed { index, promotedStory -> - val ongoingStoryViewModel = createOngoingStoryViewModel(promotedStory, index) - itemList.add(ongoingStoryViewModel) - } - } - - private fun addRecommendedStoryListSection( - suggestedStoryList: List, - itemList: MutableList - ) { - val showDivider = itemList.isNotEmpty() - val recommendedSectionTitleViewModel = - SectionTitleViewModel( - resourceHandler.getStringInLocale(R.string.recommended_stories), - showDivider - ) - itemList.add(recommendedSectionTitleViewModel) - suggestedStoryList.forEachIndexed { index, suggestedStory -> - val ongoingStoryViewModel = createOngoingStoryViewModel(suggestedStory, index) - itemList.add(ongoingStoryViewModel) - } - } - - private fun createOngoingStoryViewModel( - promotedStory: PromotedStory, - index: Int - ): RecentlyPlayedItemViewModel { - return PromotedStoryViewModel( - activity, - promotedStory, - entityType, - promotedStoryClickListener, - index, - resourceHandler, - translationController - ) - } -} diff --git a/app/src/main/res/layout/recently_played_fragment.xml b/app/src/main/res/layout/recently_played_fragment.xml index 3c61fcc166d..e4877a7cbc8 100644 --- a/app/src/main/res/layout/recently_played_fragment.xml +++ b/app/src/main/res/layout/recently_played_fragment.xml @@ -2,13 +2,6 @@ - - - - - + android:scrollbars="none" />