From c735bb36e3a29aa4d72acbbd66e17854af389953 Mon Sep 17 00:00:00 2001 From: Rajat Talesra Date: Fri, 7 Aug 2020 09:06:23 +0530 Subject: [PATCH] Fix #1152: LessonThumbnailImageView (#1554) * LessonThumbnail Image View * Draft approach for Lesson thumbnail * Possible fix for Glide not liking custom models bound into views. * Working implementation * Added thumbnail support to Recently played screen, subtopics * StoryTestHelper * Profile Progress items * Updated json files * Reset progress test file * Nit changes * Nit changes * Added thumbnail to new files * Added todo Co-authored-by: Rajat Talesra Co-authored-by: Ben Henning --- .../CompletedStoryItemViewModel.kt | 5 +- .../CompletedStoryListViewModel.kt | 6 +- .../customview/LessonThumbnailImageView.kt | 150 +++++++++++++++++ .../oppia/app/home/HomeFragmentPresenter.kt | 16 +- .../recentlyplayed/OngoingStoryViewModel.kt | 1 + .../RecentlyPlayedFragmentPresenter.kt | 16 +- .../home/topiclist/PromotedStoryViewModel.kt | 3 +- .../home/topiclist/TopicSummaryViewModel.kt | 1 + .../OngoingTopicItemViewModel.kt | 2 +- .../OngoingTopicListViewModel.kt | 6 +- .../ProfileProgressViewModel.kt | 6 +- .../RecentlyPlayedStorySummaryViewModel.kt | 6 +- .../org/oppia/app/story/StoryViewModel.kt | 7 +- .../StoryChapterSummaryViewModel.kt | 3 +- .../app/topic/info/TopicInfoViewModel.kt | 4 +- .../topic/revision/TopicRevisionViewModel.kt | 6 +- .../TopicRevisionItemViewModel.kt | 2 + .../revisioncard/RevisionCardViewModel.kt | 4 +- .../java/org/oppia/app/view/ViewComponent.kt | 2 + .../res/layout-land/completed_story_item.xml | 23 +-- .../res/layout-land/ongoing_story_card.xml | 6 +- .../res/layout-land/ongoing_topic_item.xml | 13 +- ...le_progress_recently_played_story_card.xml | 6 +- .../res/layout-land/promoted_story_card.xml | 32 ++-- .../topic_revision_summary_view.xml | 26 +-- .../res/layout-land/topic_summary_view.xml | 27 ++-- .../completed_story_item.xml | 23 +-- .../ongoing_story_card.xml | 8 +- .../ongoing_topic_item.xml | 13 +- .../promoted_story_card.xml | 32 ++-- .../topic_info_fragment.xml | 8 +- .../topic_revision_summary_view.xml | 24 +-- .../topic_summary_view.xml | 9 +- .../completed_story_item.xml | 19 +-- .../ongoing_story_card.xml | 8 +- .../ongoing_topic_item.xml | 9 +- .../promoted_story_card.xml | 32 ++-- .../topic_info_fragment.xml | 11 +- .../topic_revision_summary_view.xml | 23 +-- .../main/res/layout/completed_story_item.xml | 153 +++++++++--------- .../main/res/layout/ongoing_story_card.xml | 6 +- .../main/res/layout/ongoing_topic_item.xml | 9 +- ...le_progress_recently_played_story_card.xml | 6 +- .../main/res/layout/promoted_story_card.xml | 26 +-- .../main/res/layout/story_chapter_view.xml | 7 +- .../main/res/layout/topic_info_fragment.xml | 9 +- .../layout/topic_revision_summary_view.xml | 23 +-- .../main/res/layout/topic_summary_view.xml | 27 ++-- .../org/oppia/domain/topic/TopicController.kt | 4 +- .../parser/ExplorationHtmlParserEntityType.kt | 6 +- .../org/oppia/util/parser/GlideImageLoader.kt | 6 +- .../util/parser/HtmlParserEntityTypeModule.kt | 8 +- .../java/org/oppia/util/parser/ImageLoader.kt | 4 +- .../util/parser/ImageParsingAnnotations.kt | 3 + .../oppia/util/parser/ImageParsingModule.kt | 7 + .../util/parser/RepositoryGlideModule.kt | 4 +- .../util/parser/SvgDrawableTranscoder.kt | 8 +- .../org/oppia/util/parser/UrlImageParser.kt | 5 +- 58 files changed, 589 insertions(+), 330 deletions(-) create mode 100644 app/src/main/java/org/oppia/app/customview/LessonThumbnailImageView.kt diff --git a/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryItemViewModel.kt b/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryItemViewModel.kt index ddc0a425fd6..3c0655cbf6b 100644 --- a/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryItemViewModel.kt +++ b/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryItemViewModel.kt @@ -4,4 +4,7 @@ import androidx.lifecycle.ViewModel import org.oppia.app.model.CompletedStory /** Completed story view model for the recycler view in [CompletedStoryListFragment]. */ -class CompletedStoryItemViewModel(val completedStory: CompletedStory) : ViewModel() +class CompletedStoryItemViewModel( + val completedStory: CompletedStory, + val entityType: String +) : ViewModel() diff --git a/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryListViewModel.kt b/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryListViewModel.kt index 2693d042973..bf4c709d36b 100644 --- a/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryListViewModel.kt +++ b/app/src/main/java/org/oppia/app/completedstorylist/CompletedStoryListViewModel.kt @@ -9,13 +9,15 @@ import org.oppia.app.model.ProfileId import org.oppia.domain.topic.TopicController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.StoryHtmlParserEntityType import javax.inject.Inject /** The ViewModel for [CompletedStoryListFragment]. */ @FragmentScope class CompletedStoryListViewModel @Inject constructor( private val topicController: TopicController, - private val logger: ConsoleLogger + private val logger: ConsoleLogger, + @StoryHtmlParserEntityType private val entityType: String ) : ViewModel() { /** [internalProfileId] needs to be set before any of the live data members can be accessed. */ private var internalProfileId: Int = -1 @@ -57,7 +59,7 @@ class CompletedStoryListViewModel @Inject constructor( val itemViewModelList: MutableList = mutableListOf() itemViewModelList.addAll( completedStoryList.completedStoryList.map { completedStory -> - CompletedStoryItemViewModel(completedStory) + CompletedStoryItemViewModel(completedStory, entityType) } ) return itemViewModelList diff --git a/app/src/main/java/org/oppia/app/customview/LessonThumbnailImageView.kt b/app/src/main/java/org/oppia/app/customview/LessonThumbnailImageView.kt new file mode 100644 index 00000000000..b21fc34a62a --- /dev/null +++ b/app/src/main/java/org/oppia/app/customview/LessonThumbnailImageView.kt @@ -0,0 +1,150 @@ +package org.oppia.app.customview + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatImageView +import androidx.fragment.app.FragmentManager +import org.oppia.app.R +import org.oppia.app.fragment.InjectableFragment +import org.oppia.app.model.LessonThumbnail +import org.oppia.app.model.LessonThumbnailGraphic +import org.oppia.util.gcsresource.DefaultResourceBucketName +import org.oppia.util.parser.DefaultGcsPrefix +import org.oppia.util.parser.ImageLoader +import org.oppia.util.parser.ImageViewTarget +import org.oppia.util.parser.ThumbnailDownloadUrlTemplate +import javax.inject.Inject + +/** A custom [AppCompatImageView] used to show lesson thumbnails. */ +class LessonThumbnailImageView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatImageView(context, attrs, defStyleAttr) { + + private val imageView = this + private lateinit var lessonThumbnail: LessonThumbnail + private lateinit var entityId: String + private lateinit var entityType: String + + @Inject + lateinit var imageLoader: ImageLoader + + @Inject + @field:DefaultResourceBucketName + lateinit var resourceBucketName: String + + // TODO(#1571): Investigate this issue to fix the initialization error. + @Inject + @field:ThumbnailDownloadUrlTemplate + lateinit var thumbnailDownloadUrlTemplate: String + + @Inject + @field:DefaultGcsPrefix + lateinit var gcsPrefix: String + + fun setEntityId(entityId: String) { + this.entityId = entityId + checkIfLoadingIsPossible() + } + + fun setEntityType(entityType: String) { + this.entityType = entityType + checkIfLoadingIsPossible() + } + + fun setLessonThumbnail(lessonThumbnail: LessonThumbnail) { + this.lessonThumbnail = lessonThumbnail + checkIfLoadingIsPossible() + } + + private fun checkIfLoadingIsPossible() { + if (::entityId.isInitialized && + ::entityType.isInitialized && + ::lessonThumbnail.isInitialized && + ::thumbnailDownloadUrlTemplate.isInitialized && + ::resourceBucketName.isInitialized && + ::gcsPrefix.isInitialized && + ::imageLoader.isInitialized + ) { + loadLessonThumbnail() + } + } + + private fun loadLessonThumbnail() { + if (lessonThumbnail.thumbnailFilename.isNotEmpty()) { + loadImage(lessonThumbnail.thumbnailFilename) + } else { + imageView.setImageResource(getLessonDrawableResource(lessonThumbnail)) + } + imageView.setBackgroundColor(lessonThumbnail.backgroundColorRgb) + } + + /** Loads an image using Glide from [filename]. */ + private fun loadImage(filename: String) { + val imageName = String.format( + thumbnailDownloadUrlTemplate, + entityType, + entityId, + filename + ) + val imageUrl = "$gcsPrefix/$resourceBucketName/$imageName" + if (imageUrl.endsWith("svg", ignoreCase = true)) { + imageLoader.loadSvg(imageUrl, ImageViewTarget(this)) + } else { + imageLoader.loadBitmap(imageUrl, ImageViewTarget(this)) + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + FragmentManager.findFragment(this) + .createViewComponent(this) + .inject(this) + } + + private fun getLessonDrawableResource(lessonThumbnail: LessonThumbnail): Int { + return when (lessonThumbnail.thumbnailGraphic) { + LessonThumbnailGraphic.BAKER -> + R.drawable.lesson_thumbnail_graphic_baker + LessonThumbnailGraphic.CHILD_WITH_BOOK -> + R.drawable.lesson_thumbnail_graphic_child_with_book + LessonThumbnailGraphic.CHILD_WITH_CUPCAKES -> + R.drawable.lesson_thumbnail_graphic_child_with_cupcakes + LessonThumbnailGraphic.CHILD_WITH_FRACTIONS_HOMEWORK -> + R.drawable.lesson_thumbnail_graphic_child_with_fractions_homework + LessonThumbnailGraphic.DUCK_AND_CHICKEN -> + R.drawable.lesson_thumbnail_graphic_duck_and_chicken + LessonThumbnailGraphic.PERSON_WITH_PIE_CHART -> + R.drawable.lesson_thumbnail_graphic_person_with_pie_chart + LessonThumbnailGraphic.IDENTIFYING_THE_PARTS_OF_A_FRACTION -> + R.drawable.topic_fractions_01 + LessonThumbnailGraphic.WRITING_FRACTIONS -> + R.drawable.topic_fractions_02 + LessonThumbnailGraphic.EQUIVALENT_FRACTIONS -> + R.drawable.topic_fractions_03 + LessonThumbnailGraphic.MIXED_NUMBERS_AND_IMPROPER_FRACTIONS -> + R.drawable.topic_fractions_04 + LessonThumbnailGraphic.COMPARING_FRACTIONS -> + R.drawable.topic_fractions_05 + LessonThumbnailGraphic.ADDING_AND_SUBTRACTING_FRACTIONS -> + R.drawable.topic_fractions_06 + LessonThumbnailGraphic.MULTIPLYING_FRACTIONS -> + R.drawable.topic_fractions_07 + LessonThumbnailGraphic.DIVIDING_FRACTIONS -> + R.drawable.topic_fractions_08 + LessonThumbnailGraphic.DERIVE_A_RATIO -> + R.drawable.topic_ratios_01 + LessonThumbnailGraphic.WHAT_IS_A_FRACTION -> + R.drawable.topic_fractions_01 + LessonThumbnailGraphic.FRACTION_OF_A_GROUP -> + R.drawable.topic_fractions_02 + LessonThumbnailGraphic.ADDING_FRACTIONS -> + R.drawable.topic_fractions_03 + LessonThumbnailGraphic.MIXED_NUMBERS -> + R.drawable.topic_fractions_04 + else -> + R.drawable.topic_fractions_01 + } + } +} diff --git a/app/src/main/java/org/oppia/app/home/HomeFragmentPresenter.kt b/app/src/main/java/org/oppia/app/home/HomeFragmentPresenter.kt index 1cc4876facf..04724cc9c33 100644 --- a/app/src/main/java/org/oppia/app/home/HomeFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/app/home/HomeFragmentPresenter.kt @@ -31,6 +31,8 @@ import org.oppia.domain.topic.TopicListController import org.oppia.util.data.AsyncResult import org.oppia.util.datetime.DateTimeUtil import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.StoryHtmlParserEntityType +import org.oppia.util.parser.TopicHtmlParserEntityType import org.oppia.util.system.OppiaClock import javax.inject.Inject @@ -43,7 +45,9 @@ class HomeFragmentPresenter @Inject constructor( private val topicListController: TopicListController, private val oppiaClock: OppiaClock, private val logger: ConsoleLogger, - private val oppiaLogger: OppiaLogger + private val oppiaLogger: OppiaLogger, + @TopicHtmlParserEntityType private val topicEntityType: String, + @StoryHtmlParserEntityType private val storyEntityType: String ) { private val routeToTopicListener = activity as RouteToTopicListener private val itemList: MutableList = ArrayList() @@ -142,7 +146,11 @@ class HomeFragmentPresenter @Inject constructor( Observer { result -> for (topicSummary in result.topicSummaryList) { val topicSummaryViewModel = - TopicSummaryViewModel(topicSummary, fragment as TopicSummaryClickListener) + TopicSummaryViewModel( + topicSummary, + topicEntityType, + fragment as TopicSummaryClickListener + ) itemList.add(topicSummaryViewModel) } topicListAdapter.notifyDataSetChanged() @@ -183,14 +191,14 @@ class HomeFragmentPresenter @Inject constructor( promotedStoryList.clear() if (it.recentStoryCount != 0) { it.recentStoryList.take(limit).forEach { promotedStory -> - val recentStory = PromotedStoryViewModel(activity, internalProfileId) + val recentStory = PromotedStoryViewModel(activity, internalProfileId, storyEntityType) recentStory.setPromotedStory(promotedStory) promotedStoryList.add(recentStory) } } else { // TODO(#936): Optimise this as part of recommended stories. it.olderStoryList.take(limit).forEach { promotedStory -> - val oldStory = PromotedStoryViewModel(activity, internalProfileId) + val oldStory = PromotedStoryViewModel(activity, internalProfileId, storyEntityType) oldStory.setPromotedStory(promotedStory) promotedStoryList.add(oldStory) } diff --git a/app/src/main/java/org/oppia/app/home/recentlyplayed/OngoingStoryViewModel.kt b/app/src/main/java/org/oppia/app/home/recentlyplayed/OngoingStoryViewModel.kt index c9275366d01..680bc16ce63 100755 --- a/app/src/main/java/org/oppia/app/home/recentlyplayed/OngoingStoryViewModel.kt +++ b/app/src/main/java/org/oppia/app/home/recentlyplayed/OngoingStoryViewModel.kt @@ -9,6 +9,7 @@ import org.oppia.app.model.PromotedStory /** [ViewModel] for displaying a promoted story. */ class OngoingStoryViewModel( val ongoingStory: PromotedStory, + val entityType: String, private val ongoingStoryClickListener: OngoingStoryClickListener ) : RecentlyPlayedItemViewModel() { fun clickOnOngoingStoryTile(@Suppress("UNUSED_PARAMETER") v: View) { diff --git a/app/src/main/java/org/oppia/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt b/app/src/main/java/org/oppia/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt index 57d2fb0cfad..2160b91e4fe 100755 --- a/app/src/main/java/org/oppia/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt @@ -22,6 +22,7 @@ import org.oppia.domain.exploration.ExplorationDataController import org.oppia.domain.topic.TopicListController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.StoryHtmlParserEntityType import javax.inject.Inject /** The presenter for [RecentlyPlayedFragment]. */ @@ -31,7 +32,8 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( private val fragment: Fragment, private val logger: ConsoleLogger, private val explorationDataController: ExplorationDataController, - private val topicListController: TopicListController + private val topicListController: TopicListController, + @StoryHtmlParserEntityType private val entityType: String ) { private val routeToExplorationListener = activity as RouteToExplorationListener @@ -81,7 +83,11 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( itemList.add(recentSectionTitleViewModel) for (promotedStory in it.recentStoryList) { val ongoingStoryViewModel = - OngoingStoryViewModel(promotedStory, fragment as OngoingStoryClickListener) + OngoingStoryViewModel( + promotedStory, + entityType, + fragment as OngoingStoryClickListener + ) itemList.add(ongoingStoryViewModel) } } @@ -96,7 +102,11 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( itemList.add(olderSectionTitleViewModel) for (promotedStory in it.olderStoryList) { val ongoingStoryViewModel = - OngoingStoryViewModel(promotedStory, fragment as OngoingStoryClickListener) + OngoingStoryViewModel( + promotedStory, + entityType, + fragment as OngoingStoryClickListener + ) itemList.add(ongoingStoryViewModel) } } diff --git a/app/src/main/java/org/oppia/app/home/topiclist/PromotedStoryViewModel.kt b/app/src/main/java/org/oppia/app/home/topiclist/PromotedStoryViewModel.kt index 738a910905c..6d202dc4a91 100755 --- a/app/src/main/java/org/oppia/app/home/topiclist/PromotedStoryViewModel.kt +++ b/app/src/main/java/org/oppia/app/home/topiclist/PromotedStoryViewModel.kt @@ -14,7 +14,8 @@ import org.oppia.app.viewmodel.ObservableViewModel /** [ViewModel] for displaying a promoted story. */ class PromotedStoryViewModel( private val activity: AppCompatActivity, - private val internalProfileId: Int + private val internalProfileId: Int, + val entityType: String ) : ObservableViewModel(), RouteToTopicPlayStoryListener { diff --git a/app/src/main/java/org/oppia/app/home/topiclist/TopicSummaryViewModel.kt b/app/src/main/java/org/oppia/app/home/topiclist/TopicSummaryViewModel.kt index 6feef5d168e..50cf202fd08 100755 --- a/app/src/main/java/org/oppia/app/home/topiclist/TopicSummaryViewModel.kt +++ b/app/src/main/java/org/oppia/app/home/topiclist/TopicSummaryViewModel.kt @@ -15,6 +15,7 @@ const val DARKEN_SATURATION_MULTIPLIER: Float = 1.2f /** The view model corresponding to topic summaries in the topic summary RecyclerView. */ class TopicSummaryViewModel( val topicSummary: TopicSummary, + val entityType: String, private val topicSummaryClickListener: TopicSummaryClickListener ) : HomeItemViewModel() { val name: String = topicSummary.name diff --git a/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicItemViewModel.kt b/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicItemViewModel.kt index 9753c21cd72..0d67f1fba64 100644 --- a/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicItemViewModel.kt +++ b/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicItemViewModel.kt @@ -4,4 +4,4 @@ import androidx.lifecycle.ViewModel import org.oppia.app.model.Topic /** [ViewModel] for displaying topic item in [OngoingTopicListActivity]. */ -class OngoingTopicItemViewModel(val topic: Topic) : ViewModel() +class OngoingTopicItemViewModel(val topic: Topic, val entityType: String) : ViewModel() diff --git a/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicListViewModel.kt b/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicListViewModel.kt index e159f77925e..a9e843ad1c7 100644 --- a/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicListViewModel.kt +++ b/app/src/main/java/org/oppia/app/ongoingtopiclist/OngoingTopicListViewModel.kt @@ -9,13 +9,15 @@ import org.oppia.app.model.ProfileId import org.oppia.domain.topic.TopicController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.TopicHtmlParserEntityType import javax.inject.Inject /** The ViewModel for [OngoingTopicListFragment]. */ @FragmentScope class OngoingTopicListViewModel @Inject constructor( private val topicController: TopicController, - private val logger: ConsoleLogger + private val logger: ConsoleLogger, + @TopicHtmlParserEntityType private val entityType: String ) : ViewModel() { /** [internalProfileId] needs to be set before any of the live data members can be accessed. */ private var internalProfileId: Int = -1 @@ -57,7 +59,7 @@ class OngoingTopicListViewModel @Inject constructor( val itemViewModelList: MutableList = mutableListOf() itemViewModelList.addAll( ongoingTopicList.topicList.map { topic -> - OngoingTopicItemViewModel(topic) + OngoingTopicItemViewModel(topic, entityType) } ) return itemViewModelList diff --git a/app/src/main/java/org/oppia/app/profileprogress/ProfileProgressViewModel.kt b/app/src/main/java/org/oppia/app/profileprogress/ProfileProgressViewModel.kt index c2fd8419f57..dfa4b256f96 100644 --- a/app/src/main/java/org/oppia/app/profileprogress/ProfileProgressViewModel.kt +++ b/app/src/main/java/org/oppia/app/profileprogress/ProfileProgressViewModel.kt @@ -17,6 +17,7 @@ import org.oppia.domain.topic.TopicController import org.oppia.domain.topic.TopicListController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.StoryHtmlParserEntityType import javax.inject.Inject /** The [ViewModel] for [ProfileProgressFragment]. */ @@ -27,7 +28,8 @@ class ProfileProgressViewModel @Inject constructor( private val profileManagementController: ProfileManagementController, private val topicController: TopicController, private val topicListController: TopicListController, - private val logger: ConsoleLogger + private val logger: ConsoleLogger, + @StoryHtmlParserEntityType private val entityType: String ) : ViewModel() { /** [internalProfileId] needs to be set before any of the live data members can be accessed. */ private var internalProfileId: Int = -1 @@ -109,7 +111,7 @@ class ProfileProgressViewModel @Inject constructor( } itemViewModelList.addAll( itemList.map { story -> - RecentlyPlayedStorySummaryViewModel(story) as ProfileProgressItemViewModel + RecentlyPlayedStorySummaryViewModel(story, entityType) } ) return itemViewModelList diff --git a/app/src/main/java/org/oppia/app/profileprogress/RecentlyPlayedStorySummaryViewModel.kt b/app/src/main/java/org/oppia/app/profileprogress/RecentlyPlayedStorySummaryViewModel.kt index b12750004fb..0909f806bb5 100644 --- a/app/src/main/java/org/oppia/app/profileprogress/RecentlyPlayedStorySummaryViewModel.kt +++ b/app/src/main/java/org/oppia/app/profileprogress/RecentlyPlayedStorySummaryViewModel.kt @@ -3,5 +3,7 @@ package org.oppia.app.profileprogress import org.oppia.app.model.PromotedStory /** Recently played item [ViewModel] for the recycler view in [ProfileProgressFragment]. */ -class RecentlyPlayedStorySummaryViewModel(val promotedStory: PromotedStory) : - ProfileProgressItemViewModel() +class RecentlyPlayedStorySummaryViewModel( + val promotedStory: PromotedStory, + val entityType: String +) : ProfileProgressItemViewModel() diff --git a/app/src/main/java/org/oppia/app/story/StoryViewModel.kt b/app/src/main/java/org/oppia/app/story/StoryViewModel.kt index 459498ed27a..a2db4863150 100644 --- a/app/src/main/java/org/oppia/app/story/StoryViewModel.kt +++ b/app/src/main/java/org/oppia/app/story/StoryViewModel.kt @@ -16,6 +16,7 @@ import org.oppia.domain.exploration.ExplorationDataController import org.oppia.domain.topic.TopicController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.StoryHtmlParserEntityType import javax.inject.Inject /** The ViewModel for [StoryFragment]. */ @@ -24,7 +25,8 @@ class StoryViewModel @Inject constructor( private val fragment: Fragment, private val topicController: TopicController, private val explorationDataController: ExplorationDataController, - private val logger: ConsoleLogger + private val logger: ConsoleLogger, + @StoryHtmlParserEntityType val entityType: String ) : ViewModel() { private var internalProfileId: Int = -1 private lateinit var topicId: String @@ -106,7 +108,8 @@ class StoryViewModel @Inject constructor( internalProfileId, topicId, storyId, - chapter + chapter, + entityType ) } ) diff --git a/app/src/main/java/org/oppia/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt b/app/src/main/java/org/oppia/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt index a2828487ccc..bd2098ec8ab 100644 --- a/app/src/main/java/org/oppia/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt +++ b/app/src/main/java/org/oppia/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt @@ -22,7 +22,8 @@ class StoryChapterSummaryViewModel( val internalProfileId: Int, val topicId: String, val storyId: String, - val chapterSummary: ChapterSummary + val chapterSummary: ChapterSummary, + val entityType: String ) : StoryItemViewModel() { val explorationId: String = chapterSummary.explorationId val name: String = chapterSummary.name diff --git a/app/src/main/java/org/oppia/app/topic/info/TopicInfoViewModel.kt b/app/src/main/java/org/oppia/app/topic/info/TopicInfoViewModel.kt index eea525eb552..e26ffc56fd8 100644 --- a/app/src/main/java/org/oppia/app/topic/info/TopicInfoViewModel.kt +++ b/app/src/main/java/org/oppia/app/topic/info/TopicInfoViewModel.kt @@ -7,12 +7,14 @@ import org.oppia.app.R import org.oppia.app.fragment.FragmentScope import org.oppia.app.model.Topic import org.oppia.app.viewmodel.ObservableViewModel +import org.oppia.util.parser.TopicHtmlParserEntityType import javax.inject.Inject /** [ViewModel] for showing topic info details. */ @FragmentScope class TopicInfoViewModel @Inject constructor( - private val context: Context + private val context: Context, + @TopicHtmlParserEntityType val entityType: String ) : ObservableViewModel() { val topic = ObservableField(Topic.getDefaultInstance()) diff --git a/app/src/main/java/org/oppia/app/topic/revision/TopicRevisionViewModel.kt b/app/src/main/java/org/oppia/app/topic/revision/TopicRevisionViewModel.kt index fbbfac45145..27101c0eadf 100755 --- a/app/src/main/java/org/oppia/app/topic/revision/TopicRevisionViewModel.kt +++ b/app/src/main/java/org/oppia/app/topic/revision/TopicRevisionViewModel.kt @@ -11,6 +11,7 @@ import org.oppia.app.topic.revision.revisionitemviewmodel.TopicRevisionItemViewM import org.oppia.domain.topic.TopicController import org.oppia.util.data.AsyncResult import org.oppia.util.logging.ConsoleLogger +import org.oppia.util.parser.TopicHtmlParserEntityType import javax.inject.Inject /** [ViewModel] for [TopicRevisionFragment]. */ @@ -18,7 +19,8 @@ import javax.inject.Inject class TopicRevisionViewModel @Inject constructor( private val topicController: TopicController, private val logger: ConsoleLogger, - val fragment: Fragment + val fragment: Fragment, + @TopicHtmlParserEntityType private val entityType: String ) : ViewModel() { private lateinit var profileId: ProfileId private lateinit var topicId: String @@ -39,7 +41,7 @@ class TopicRevisionViewModel @Inject constructor( private fun processTopic(topic: Topic): List { subtopicList.addAll( topic.subtopicList.map { - TopicRevisionItemViewModel(it, revisionSubtopicSelector) + TopicRevisionItemViewModel(topicId, it, entityType, revisionSubtopicSelector) } ) return subtopicList diff --git a/app/src/main/java/org/oppia/app/topic/revision/revisionitemviewmodel/TopicRevisionItemViewModel.kt b/app/src/main/java/org/oppia/app/topic/revision/revisionitemviewmodel/TopicRevisionItemViewModel.kt index a157f78ac7c..3882ad1c300 100644 --- a/app/src/main/java/org/oppia/app/topic/revision/revisionitemviewmodel/TopicRevisionItemViewModel.kt +++ b/app/src/main/java/org/oppia/app/topic/revision/revisionitemviewmodel/TopicRevisionItemViewModel.kt @@ -7,6 +7,8 @@ import org.oppia.app.topic.revision.TopicRevisionFragment /** [ViewModel] for child views of recycler view present in the [TopicRevisionFragment]. */ class TopicRevisionItemViewModel( + val topicId: String, val subtopic: Subtopic, + val entityType: String, val onRevisionItemPressed: RevisionSubtopicSelector ) : ViewModel() diff --git a/app/src/main/java/org/oppia/app/topic/revisioncard/RevisionCardViewModel.kt b/app/src/main/java/org/oppia/app/topic/revisioncard/RevisionCardViewModel.kt index a84e2fdb7fd..3d028ad46d0 100755 --- a/app/src/main/java/org/oppia/app/topic/revisioncard/RevisionCardViewModel.kt +++ b/app/src/main/java/org/oppia/app/topic/revisioncard/RevisionCardViewModel.kt @@ -13,7 +13,7 @@ import org.oppia.util.data.AsyncResult import org.oppia.util.gcsresource.DefaultResourceBucketName import org.oppia.util.logging.ConsoleLogger import org.oppia.util.parser.HtmlParser -import org.oppia.util.parser.RevisionCardHtmlParserEntityType +import org.oppia.util.parser.TopicHtmlParserEntityType import javax.inject.Inject /** [ViewModel] for revision card, providing rich text and worked examples */ @@ -24,7 +24,7 @@ class RevisionCardViewModel @Inject constructor( private val logger: ConsoleLogger, private val htmlParserFactory: HtmlParser.Factory, @DefaultResourceBucketName private val resourceBucketName: String, - @RevisionCardHtmlParserEntityType private val entityType: String + @TopicHtmlParserEntityType private val entityType: String ) : ViewModel() { private lateinit var topicId: String private var subtopicId: Int = 0 diff --git a/app/src/main/java/org/oppia/app/view/ViewComponent.kt b/app/src/main/java/org/oppia/app/view/ViewComponent.kt index 9f488ce964c..d31e5702813 100644 --- a/app/src/main/java/org/oppia/app/view/ViewComponent.kt +++ b/app/src/main/java/org/oppia/app/view/ViewComponent.kt @@ -3,6 +3,7 @@ package org.oppia.app.view import android.view.View import dagger.BindsInstance import dagger.Subcomponent +import org.oppia.app.customview.LessonThumbnailImageView import org.oppia.app.player.state.DragDropSortInteractionView import org.oppia.app.player.state.ImageRegionSelectionInteractionView import org.oppia.app.player.state.SelectionInteractionView @@ -22,4 +23,5 @@ interface ViewComponent { fun inject(selectionInteractionView: SelectionInteractionView) fun inject(dragDropSortInteractionView: DragDropSortInteractionView) fun inject(imageRegionSelectionInteractionView: ImageRegionSelectionInteractionView) + fun inject(lessonThumbnailImageView: LessonThumbnailImageView) } diff --git a/app/src/main/res/layout-land/completed_story_item.xml b/app/src/main/res/layout-land/completed_story_item.xml index 41d892978ef..65795f3ce8e 100755 --- a/app/src/main/res/layout-land/completed_story_item.xml +++ b/app/src/main/res/layout-land/completed_story_item.xml @@ -19,8 +19,8 @@ android:layout_marginTop="12dp" android:layout_marginEnd="16dp" android:layout_marginBottom="12dp" - app:cardElevation="4dp" - app:cardCornerRadius="4dp"> + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.completedStory.lessonThumbnail}" /> diff --git a/app/src/main/res/layout-land/ongoing_story_card.xml b/app/src/main/res/layout-land/ongoing_story_card.xml index a10e3902558..56f4a4fe472 100755 --- a/app/src/main/res/layout-land/ongoing_story_card.xml +++ b/app/src/main/res/layout-land/ongoing_story_card.xml @@ -26,18 +26,20 @@ android:focusable="true" android:onClick="@{viewModel::clickOnOngoingStoryTile}"> - + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> - + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.promotedStoryObservable.lessonThumbnail}" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="18sp" /> @@ -88,14 +90,14 @@ android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" - android:maxLines="1" android:ellipsize="end" - android:paddingBottom="8dp" android:fontFamily="sans-serif-light" + android:maxLines="1" + android:paddingBottom="8dp" android:text="@{viewModel.promotedStoryObservable.topicName}" android:textAllCaps="true" - android:textSize="14sp" - android:textColor="@color/oppiaPrimaryText" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="14sp" /> diff --git a/app/src/main/res/layout-land/topic_revision_summary_view.xml b/app/src/main/res/layout-land/topic_revision_summary_view.xml index 724506e5060..20f67ab3d18 100755 --- a/app/src/main/res/layout-land/topic_revision_summary_view.xml +++ b/app/src/main/res/layout-land/topic_revision_summary_view.xml @@ -3,12 +3,14 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - - + + + + + - + app:cardMaxElevation="4dp"> - - - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.subtopic.subtopicThumbnail}" /> diff --git a/app/src/main/res/layout-land/topic_summary_view.xml b/app/src/main/res/layout-land/topic_summary_view.xml index dcb0af0c80a..20917052c1a 100755 --- a/app/src/main/res/layout-land/topic_summary_view.xml +++ b/app/src/main/res/layout-land/topic_summary_view.xml @@ -18,22 +18,23 @@ + android:focusable="true" + android:onClick="@{(v) -> viewModel.clickOnSummaryTile()}"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topicSummary.topicThumbnail}" /> diff --git a/app/src/main/res/layout-sw600dp-land/completed_story_item.xml b/app/src/main/res/layout-sw600dp-land/completed_story_item.xml index 41d892978ef..65795f3ce8e 100644 --- a/app/src/main/res/layout-sw600dp-land/completed_story_item.xml +++ b/app/src/main/res/layout-sw600dp-land/completed_story_item.xml @@ -19,8 +19,8 @@ android:layout_marginTop="12dp" android:layout_marginEnd="16dp" android:layout_marginBottom="12dp" - app:cardElevation="4dp" - app:cardCornerRadius="4dp"> + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.completedStory.lessonThumbnail}" /> diff --git a/app/src/main/res/layout-sw600dp-land/ongoing_story_card.xml b/app/src/main/res/layout-sw600dp-land/ongoing_story_card.xml index 41c733b6448..74e2d00bdc9 100644 --- a/app/src/main/res/layout-sw600dp-land/ongoing_story_card.xml +++ b/app/src/main/res/layout-sw600dp-land/ongoing_story_card.xml @@ -26,18 +26,20 @@ android:focusable="true" android:onClick="@{viewModel::clickOnOngoingStoryTile}"> - diff --git a/app/src/main/res/layout-sw600dp-land/ongoing_topic_item.xml b/app/src/main/res/layout-sw600dp-land/ongoing_topic_item.xml index 86006eaab7b..014cba7906f 100644 --- a/app/src/main/res/layout-sw600dp-land/ongoing_topic_item.xml +++ b/app/src/main/res/layout-sw600dp-land/ongoing_topic_item.xml @@ -21,8 +21,8 @@ android:layout_marginTop="12dp" android:layout_marginEnd="16dp" android:layout_marginBottom="12dp" - app:cardElevation="4dp" - app:cardCornerRadius="4dp"> + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.promotedStoryObservable.lessonThumbnail}" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="18sp" /> @@ -87,14 +89,14 @@ android:layout_marginStart="16dp" android:layout_marginTop="4dp" android:layout_marginEnd="16dp" - android:maxLines="1" android:ellipsize="end" - android:paddingBottom="8dp" android:fontFamily="sans-serif-light" + android:maxLines="1" + android:paddingBottom="8dp" android:text="@{viewModel.promotedStoryObservable.topicName}" android:textAllCaps="true" - android:textSize="14sp" - android:textColor="@color/oppiaPrimaryText" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="14sp" /> diff --git a/app/src/main/res/layout-sw600dp-land/topic_info_fragment.xml b/app/src/main/res/layout-sw600dp-land/topic_info_fragment.xml index c52213d76cc..ec4a44e7c56 100644 --- a/app/src/main/res/layout-sw600dp-land/topic_info_fragment.xml +++ b/app/src/main/res/layout-sw600dp-land/topic_info_fragment.xml @@ -122,19 +122,21 @@ app:layout_constraintStart_toStartOf="@+id/guideline6" app:layout_constraintTop_toTopOf="parent"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> diff --git a/app/src/main/res/layout-sw600dp-land/topic_revision_summary_view.xml b/app/src/main/res/layout-sw600dp-land/topic_revision_summary_view.xml index 7926e4acc1a..6a3a0ba30f2 100644 --- a/app/src/main/res/layout-sw600dp-land/topic_revision_summary_view.xml +++ b/app/src/main/res/layout-sw600dp-land/topic_revision_summary_view.xml @@ -3,12 +3,14 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - - + + + + + - - + app:cardMaxElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.subtopic.subtopicThumbnail}" /> diff --git a/app/src/main/res/layout-sw600dp-land/topic_summary_view.xml b/app/src/main/res/layout-sw600dp-land/topic_summary_view.xml index 5531ed68fb7..987b49e088f 100644 --- a/app/src/main/res/layout-sw600dp-land/topic_summary_view.xml +++ b/app/src/main/res/layout-sw600dp-land/topic_summary_view.xml @@ -22,18 +22,19 @@ android:focusable="true" android:onClick="@{(v) -> viewModel.clickOnSummaryTile()}"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topicSummary.topicThumbnail}" /> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.completedStory.lessonThumbnail}" /> diff --git a/app/src/main/res/layout-sw600dp-port/ongoing_story_card.xml b/app/src/main/res/layout-sw600dp-port/ongoing_story_card.xml index 41c733b6448..74e2d00bdc9 100644 --- a/app/src/main/res/layout-sw600dp-port/ongoing_story_card.xml +++ b/app/src/main/res/layout-sw600dp-port/ongoing_story_card.xml @@ -26,18 +26,20 @@ android:focusable="true" android:onClick="@{viewModel::clickOnOngoingStoryTile}"> - diff --git a/app/src/main/res/layout-sw600dp-port/ongoing_topic_item.xml b/app/src/main/res/layout-sw600dp-port/ongoing_topic_item.xml index 5698a435f4a..5f3893fa1f8 100644 --- a/app/src/main/res/layout-sw600dp-port/ongoing_topic_item.xml +++ b/app/src/main/res/layout-sw600dp-port/ongoing_topic_item.xml @@ -29,18 +29,19 @@ android:clickable="true" android:focusable="true"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.promotedStoryObservable.lessonThumbnail}" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="18sp" /> @@ -87,14 +89,14 @@ android:layout_marginStart="16dp" android:layout_marginTop="4dp" android:layout_marginEnd="16dp" - android:maxLines="1" android:ellipsize="end" - android:paddingBottom="8dp" android:fontFamily="sans-serif-light" + android:maxLines="1" + android:paddingBottom="8dp" android:text="@{viewModel.promotedStoryObservable.topicName}" android:textAllCaps="true" - android:textSize="14sp" - android:textColor="@color/oppiaPrimaryText" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="14sp" /> diff --git a/app/src/main/res/layout-sw600dp-port/topic_info_fragment.xml b/app/src/main/res/layout-sw600dp-port/topic_info_fragment.xml index fcbcc3e4096..b236524649a 100644 --- a/app/src/main/res/layout-sw600dp-port/topic_info_fragment.xml +++ b/app/src/main/res/layout-sw600dp-port/topic_info_fragment.xml @@ -21,16 +21,17 @@ android:layout_height="wrap_content" android:paddingBottom="112dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> - - + + + + + - + app:cardMaxElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.subtopic.subtopicThumbnail}" /> diff --git a/app/src/main/res/layout/completed_story_item.xml b/app/src/main/res/layout/completed_story_item.xml index 499d62cf1c1..0acbd7bc3ba 100755 --- a/app/src/main/res/layout/completed_story_item.xml +++ b/app/src/main/res/layout/completed_story_item.xml @@ -1,94 +1,95 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - + - + - - + + - - - - - + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginTop="12dp" + android:layout_marginEnd="8dp" + android:layout_marginBottom="12dp" + app:cardCornerRadius="4dp"> + android:layout_height="match_parent" + android:clickable="true" + android:focusable="true"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.completedStory.lessonThumbnail}" /> - + app:layout_constraintTop_toBottomOf="@id/completed_story_lesson_thumbnail"> + + + + + - - + diff --git a/app/src/main/res/layout/ongoing_story_card.xml b/app/src/main/res/layout/ongoing_story_card.xml index 25b688cce7a..74e2d00bdc9 100755 --- a/app/src/main/res/layout/ongoing_story_card.xml +++ b/app/src/main/res/layout/ongoing_story_card.xml @@ -26,18 +26,20 @@ android:focusable="true" android:onClick="@{viewModel::clickOnOngoingStoryTile}"> - - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> - + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.promotedStoryObservable.lessonThumbnail}" /> @@ -74,9 +76,9 @@ android:layout_marginStart="16dp" android:layout_marginTop="4dp" android:layout_marginEnd="16dp" - android:maxLines="1" android:ellipsize="end" android:fontFamily="sans-serif" + android:maxLines="1" android:text="@{viewModel.promotedStoryObservable.storyName}" android:textColor="@color/oppiaPrimaryText" android:textSize="16sp" /> @@ -88,14 +90,14 @@ android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" - android:maxLines="1" android:ellipsize="end" - android:paddingBottom="8dp" android:fontFamily="sans-serif-light" + android:maxLines="1" + android:paddingBottom="8dp" android:text="@{viewModel.promotedStoryObservable.topicName}" android:textAllCaps="true" - android:textSize="14sp" - android:textColor="@color/oppiaPrimaryText" /> + android:textColor="@color/oppiaPrimaryText" + android:textSize="14sp" /> diff --git a/app/src/main/res/layout/story_chapter_view.xml b/app/src/main/res/layout/story_chapter_view.xml index e0805694098..fe0babbcf5d 100644 --- a/app/src/main/res/layout/story_chapter_view.xml +++ b/app/src/main/res/layout/story_chapter_view.xml @@ -35,17 +35,18 @@ android:clipToPadding="true" android:contentDescription="@{viewModel.name}"> - + app:lessonThumbnail="@{viewModel.chapterThumbnail}" /> - + app:lessonThumbnail="@{viewModel.topic.topicThumbnail}" /> - - + + + + + - + app:cardMaxElevation="4dp"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.subtopic.subtopicThumbnail}" /> diff --git a/app/src/main/res/layout/topic_summary_view.xml b/app/src/main/res/layout/topic_summary_view.xml index dcb0af0c80a..20917052c1a 100755 --- a/app/src/main/res/layout/topic_summary_view.xml +++ b/app/src/main/res/layout/topic_summary_view.xml @@ -18,22 +18,23 @@ + android:focusable="true" + android:onClick="@{(v) -> viewModel.clickOnSummaryTile()}"> - + app:layout_constraintTop_toTopOf="parent" + app:lessonThumbnail="@{viewModel.topicSummary.topicThumbnail}" /> diff --git a/domain/src/main/java/org/oppia/domain/topic/TopicController.kt b/domain/src/main/java/org/oppia/domain/topic/TopicController.kt index ea426ae7487..2c128c4103d 100755 --- a/domain/src/main/java/org/oppia/domain/topic/TopicController.kt +++ b/domain/src/main/java/org/oppia/domain/topic/TopicController.kt @@ -754,11 +754,9 @@ class TopicController @Inject constructor( private fun createChapterThumbnail(chapterJsonObject: JSONObject): LessonThumbnail { val explorationId = chapterJsonObject.optString("exploration_id") val thumbnailBgColor = chapterJsonObject - .optJSONObject("exp_summary_dict") .optString("thumbnail_bg_color") val thumbnailFilename = chapterJsonObject - .optJSONObject("exp_summary_dict") - .optString("thumbnail_icon_url") + .optString("thumbnail_filename") return if (thumbnailFilename.isNotEmpty() && thumbnailBgColor.isNotEmpty()) { LessonThumbnail.newBuilder() diff --git a/utility/src/main/java/org/oppia/util/parser/ExplorationHtmlParserEntityType.kt b/utility/src/main/java/org/oppia/util/parser/ExplorationHtmlParserEntityType.kt index 283af99b4ec..7207433af77 100644 --- a/utility/src/main/java/org/oppia/util/parser/ExplorationHtmlParserEntityType.kt +++ b/utility/src/main/java/org/oppia/util/parser/ExplorationHtmlParserEntityType.kt @@ -12,4 +12,8 @@ annotation class ConceptCardHtmlParserEntityType /** Qualifier for injecting the entity type for review card. */ @Qualifier -annotation class RevisionCardHtmlParserEntityType +annotation class TopicHtmlParserEntityType + +/** Qualifier for injecting the entity type for story. */ +@Qualifier +annotation class StoryHtmlParserEntityType diff --git a/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt b/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt index f4c151d113a..41d92d171af 100644 --- a/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt +++ b/utility/src/main/java/org/oppia/util/parser/GlideImageLoader.kt @@ -2,7 +2,7 @@ package org.oppia.util.parser import android.content.Context import android.graphics.Bitmap -import android.graphics.Picture +import android.graphics.drawable.PictureDrawable import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder import com.bumptech.glide.load.engine.DiskCacheStrategy @@ -32,7 +32,7 @@ class GlideImageLoader @Inject constructor( .intoTarget(target) } - override fun loadSvg(imageUrl: String, target: ImageTarget) { + override fun loadSvg(imageUrl: String, target: ImageTarget) { val model: Any = if (cacheAssetsLocally) { object : ImageAssetFetcher { override fun fetchImage(): ByteArray = assetRepository.loadRemoteBinaryAsset(imageUrl)() @@ -43,7 +43,7 @@ class GlideImageLoader @Inject constructor( // TODO(#45): Ensure the image caching flow is properly hooked up. Glide.with(context) - .`as`(Picture::class.java) + .`as`(PictureDrawable::class.java) .fitCenter() .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE)) .load(model) diff --git a/utility/src/main/java/org/oppia/util/parser/HtmlParserEntityTypeModule.kt b/utility/src/main/java/org/oppia/util/parser/HtmlParserEntityTypeModule.kt index ce81ac5fe14..d9fe77785fb 100755 --- a/utility/src/main/java/org/oppia/util/parser/HtmlParserEntityTypeModule.kt +++ b/utility/src/main/java/org/oppia/util/parser/HtmlParserEntityTypeModule.kt @@ -19,8 +19,14 @@ class HtmlParserEntityTypeModule { } @Provides - @RevisionCardHtmlParserEntityType + @TopicHtmlParserEntityType fun provideReviewCardHtmlParserEntityType(): String { return "topic" } + + @Provides + @StoryHtmlParserEntityType + fun provideStoryHtmlParserEntityType(): String { + return "story" + } } diff --git a/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt b/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt index 90c6aa2f83a..4d32837cc2b 100644 --- a/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt +++ b/utility/src/main/java/org/oppia/util/parser/ImageLoader.kt @@ -1,7 +1,7 @@ package org.oppia.util.parser import android.graphics.Bitmap -import android.graphics.Picture +import android.graphics.drawable.PictureDrawable /** Loads an image from the provided URL into the specified target, optionally caching it. */ interface ImageLoader { @@ -17,5 +17,5 @@ interface ImageLoader { * is an asynchronous operation, and may take a while if the image needs to be downloaded from the * internet. */ - fun loadSvg(imageUrl: String, target: ImageTarget) + fun loadSvg(imageUrl: String, target: ImageTarget) } diff --git a/utility/src/main/java/org/oppia/util/parser/ImageParsingAnnotations.kt b/utility/src/main/java/org/oppia/util/parser/ImageParsingAnnotations.kt index 64e2f7fd338..8d8526141eb 100644 --- a/utility/src/main/java/org/oppia/util/parser/ImageParsingAnnotations.kt +++ b/utility/src/main/java/org/oppia/util/parser/ImageParsingAnnotations.kt @@ -7,3 +7,6 @@ import javax.inject.Qualifier /** Corresponds to the default Image Download Url Template. */ @Qualifier annotation class ImageDownloadUrlTemplate + +/** Corresponds to the default Thumbnail Download Url Template. */ +@Qualifier annotation class ThumbnailDownloadUrlTemplate diff --git a/utility/src/main/java/org/oppia/util/parser/ImageParsingModule.kt b/utility/src/main/java/org/oppia/util/parser/ImageParsingModule.kt index d691e970aec..f0a72f40170 100755 --- a/utility/src/main/java/org/oppia/util/parser/ImageParsingModule.kt +++ b/utility/src/main/java/org/oppia/util/parser/ImageParsingModule.kt @@ -20,4 +20,11 @@ class ImageParsingModule { fun provideImageDownloadUrlTemplate(): String { return "%s/%s/assets/image/%s" } + + @Provides + @ThumbnailDownloadUrlTemplate + @Singleton + fun provideThumbnailDownloadUrlTemplate(): String { + return "%s/%s/assets/thumbnail/%s" + } } diff --git a/utility/src/main/java/org/oppia/util/parser/RepositoryGlideModule.kt b/utility/src/main/java/org/oppia/util/parser/RepositoryGlideModule.kt index 6de29e49d6d..e63db7422f3 100644 --- a/utility/src/main/java/org/oppia/util/parser/RepositoryGlideModule.kt +++ b/utility/src/main/java/org/oppia/util/parser/RepositoryGlideModule.kt @@ -1,7 +1,7 @@ package org.oppia.util.parser import android.content.Context -import android.graphics.Picture +import android.graphics.drawable.PictureDrawable import com.bumptech.glide.Glide import com.bumptech.glide.Registry import com.bumptech.glide.annotation.GlideModule @@ -15,7 +15,7 @@ import java.io.InputStream class RepositoryGlideModule : AppGlideModule() { override fun registerComponents(context: Context, glide: Glide, registry: Registry) { // TODO(#1039): Introduce custom type OppiaImage for rendering Bitmap and Svg. - registry.register(SVG::class.java, Picture::class.java, SvgDrawableTranscoder()) + registry.register(SVG::class.java, PictureDrawable::class.java, SvgDrawableTranscoder()) .append(InputStream::class.java, SVG::class.java, SvgDecoder()) .append( ImageAssetFetcher::class.java, diff --git a/utility/src/main/java/org/oppia/util/parser/SvgDrawableTranscoder.kt b/utility/src/main/java/org/oppia/util/parser/SvgDrawableTranscoder.kt index b9dfa26e6fd..f30a5464898 100644 --- a/utility/src/main/java/org/oppia/util/parser/SvgDrawableTranscoder.kt +++ b/utility/src/main/java/org/oppia/util/parser/SvgDrawableTranscoder.kt @@ -1,6 +1,6 @@ package org.oppia.util.parser -import android.graphics.Picture +import android.graphics.drawable.PictureDrawable import com.bumptech.glide.load.Options import com.bumptech.glide.load.engine.Resource import com.bumptech.glide.load.resource.SimpleResource @@ -8,13 +8,13 @@ import com.bumptech.glide.load.resource.transcode.ResourceTranscoder import com.caverock.androidsvg.SVG /** SvgDrawableTranscoder converts SVG to PictureDrawable. */ -class SvgDrawableTranscoder : ResourceTranscoder { +class SvgDrawableTranscoder : ResourceTranscoder { override fun transcode( toTranscode: Resource, options: Options - ): Resource? { + ): Resource? { val svg: SVG = toTranscode.get() val picture = svg.renderToPicture() - return SimpleResource(picture) + return SimpleResource(PictureDrawable(picture)) } } diff --git a/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt b/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt index 0dddb2d8602..1e5539e24e0 100644 --- a/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt +++ b/utility/src/main/java/org/oppia/util/parser/UrlImageParser.kt @@ -3,7 +3,6 @@ package org.oppia.util.parser import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas -import android.graphics.Picture import android.graphics.Rect import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable @@ -54,8 +53,8 @@ class UrlImageParser private constructor( urlDrawable, { resource -> BitmapDrawable(context.resources, resource) } ) - private inner class SvgTarget(urlDrawable: UrlDrawable) : CustomImageTarget( - urlDrawable, { resource -> PictureDrawable(resource) } + private inner class SvgTarget(urlDrawable: UrlDrawable) : CustomImageTarget( + urlDrawable, { it } ) private open inner class CustomImageTarget(