Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #161: Exploration player contentcard supports rich-text part [Blocked: #205] #245

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
89a0da9
Update AndroidManifest.xml
veena14cs Oct 19, 2019
a5b6bef
added contentcard
veena14cs Oct 19, 2019
79103a9
removed extra spaces
veena14cs Oct 19, 2019
df2bfa1
Update StateFragmentPresenter.kt
veena14cs Oct 19, 2019
210b7ef
Create StateFragmentContentCardTest.kt
veena14cs Oct 21, 2019
955bd17
Merge branch 'develop' into content-card
veena14cs Oct 21, 2019
6646147
Create RecyclerViewMatcher.kt
veena14cs Oct 21, 2019
2dec064
Update RecyclerViewMatcher.kt
veena14cs Oct 21, 2019
e3b3c41
Update StateFragmentContentCardTest.kt
veena14cs Oct 21, 2019
7cdcd16
update test
veena14cs Oct 21, 2019
1a8e43f
Update CellularDataDialogFragmentTest.kt
veena14cs Oct 21, 2019
ad22bd2
Update StateFragmentContentCardTest.kt
veena14cs Oct 21, 2019
1bb75a9
Update StateFragmentContentCardTest.kt
veena14cs Oct 21, 2019
d3e3ae6
Update StateFragmentContentCardTest.kt
veena14cs Oct 22, 2019
15ca36f
Update StateFragmentContentCardTest.kt
veena14cs Oct 24, 2019
aa2e2c7
added qualifier
veena14cs Oct 24, 2019
90ee2b0
added Kdoc
veena14cs Oct 24, 2019
d186a1a
Merge branch 'merge-fix' into content-card
veena14cs Oct 25, 2019
c28e84b
fixed conflicts
veena14cs Oct 25, 2019
68a0961
Update AndroidManifest.xml
veena14cs Oct 25, 2019
92791d6
Update AndroidManifest.xml
veena14cs Oct 25, 2019
7eed350
Merge branch 'merge-fix' into content-card
veena14cs Oct 25, 2019
2dd5203
fixing conflicts
veena14cs Oct 25, 2019
399a5cc
Merge branch 'merge-fix' into content-card
veena14cs Oct 25, 2019
eb95575
Update QuestionPlayerActivity.kt
veena14cs Oct 25, 2019
103a822
Merge branch 'merge-fix' into content-card
veena14cs Oct 25, 2019
a0fc0d0
Merge branch 'merge-fix' into content-card
veena14cs Oct 25, 2019
df93486
Update BindableAdapterTest.kt
veena14cs Oct 25, 2019
f6663ae
Update TopicTrainFragmentTest.kt
veena14cs Oct 25, 2019
028224f
Create QuestionPlayerActivityTest.kt
veena14cs Oct 25, 2019
bada6ad
Update TopicActivityTest.kt
veena14cs Oct 25, 2019
01821d5
fixes
veena14cs Oct 25, 2019
12f6975
Update StateFragmentContentCardTest.kt
veena14cs Oct 25, 2019
2bd32c9
fixes
veena14cs Oct 25, 2019
e084804
Update StateAdapter.kt
veena14cs Oct 25, 2019
2eb4fde
fixes
veena14cs Oct 25, 2019
cb90be5
Update StateFragmentContentCardTest.kt
veena14cs Oct 25, 2019
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
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@
android:theme="@style/SplashScreenTheme" />
<activity android:name=".testing.BindableAdapterTestActivity" />
</application>
</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Application
import dagger.BindsInstance
import dagger.Component
import org.oppia.app.activity.ActivityComponent
import org.oppia.util.parser.HtmlParserEntityTypeModule
import org.oppia.data.backends.gae.NetworkModule
import org.oppia.domain.classify.InteractionsModule
import org.oppia.domain.classify.rules.continueinteraction.ContinueModule
Expand All @@ -28,7 +29,8 @@ import javax.inject.Singleton
ApplicationModule::class, DispatcherModule::class, NetworkModule::class, LoggerModule::class,
ContinueModule::class, FractionInputModule::class, ItemSelectionInputModule::class, MultipleChoiceInputModule::class,
NumberWithUnitsRuleModule::class, NumericInputRuleModule::class, TextInputRuleModule::class, InteractionsModule::class,
GcsResourceModule::class, ImageParsingModule::class, HtmlParsingModule::class, ImageLoaderModule::class
GcsResourceModule::class, ImageParsingModule::class, HtmlParsingModule::class, ImageLoaderModule::class,
HtmlParserEntityTypeModule::class
])
interface ApplicationComponent {
@Component.Builder
Expand Down
26 changes: 19 additions & 7 deletions app/src/main/java/org/oppia/app/player/state/StateAdapter.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.oppia.app.player.state

import android.text.Spannable
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
Expand All @@ -14,6 +15,7 @@ import org.oppia.app.player.state.itemviewmodel.StateButtonViewModel
import org.oppia.app.player.state.listener.ButtonInteractionListener
import org.oppia.app.databinding.StateButtonItemBinding
import org.oppia.app.player.state.itemviewmodel.ContentViewModel
import org.oppia.util.parser.HtmlParser

@Suppress("unused")
private const val VIEW_TYPE_CONTENT = 1
Expand All @@ -28,7 +30,10 @@ private const val VIEW_TYPE_STATE_BUTTON = 5
/** Adapter to inflate different items/views inside [RecyclerView]. The itemList consists of various ViewModels. */
class StateAdapter(
private val itemList: MutableList<Any>,
private val buttonInteractionListener: ButtonInteractionListener
private val buttonInteractionListener: ButtonInteractionListener,
private val htmlParserFactory: HtmlParser.Factory,
private val entityType: String,
veena14cs marked this conversation as resolved.
Show resolved Hide resolved
private val explorationId: String
) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {

Expand All @@ -47,14 +52,15 @@ class StateAdapter(
/* attachToParent= */false
)
StateButtonViewHolder(binding, buttonInteractionListener)
} VIEW_TYPE_CONTENT -> {
}
VIEW_TYPE_CONTENT -> {
val inflater = LayoutInflater.from(parent.context)
val binding =
DataBindingUtil.inflate<ContentItemBinding>(
inflater,
R.layout.content_item,
parent,
/* attachToParent= */false
/* attachToParent= */ false
)
ContentViewHolder(binding)
}
veena14cs marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -68,8 +74,8 @@ class StateAdapter(
(holder as StateButtonViewHolder).bind(itemList[position] as StateButtonViewModel)
}
VIEW_TYPE_CONTENT -> {
(holder as ContentViewHolder).bind((itemList[position] as ContentViewModel).htmlContent)
}
(holder as ContentViewHolder).bind((itemList[position] as ContentViewModel).htmlContent)
}
}
}

Expand All @@ -87,13 +93,19 @@ class StateAdapter(
override fun getItemCount(): Int {
return itemList.size
}

inner class ContentViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root) {
internal fun bind(rawString: String?) {
internal fun bind(rawString: String) {
binding.setVariable(BR.htmlContent, rawString)
binding.executePendingBindings()
binding.root.content_text_view.text = rawString
val htmlResult: Spannable = htmlParserFactory.create(entityType, explorationId).parseOppiaHtml(
rawString,
binding.root.content_text_view
)
binding.root.content_text_view.text = htmlResult
}
}

private class StateButtonViewHolder(
val binding: ViewDataBinding,
private val buttonInteractionListener: ButtonInteractionListener
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import org.oppia.domain.exploration.ExplorationDataController
import org.oppia.domain.exploration.ExplorationProgressController
import org.oppia.util.data.AsyncResult
import org.oppia.util.logging.Logger
import org.oppia.util.parser.ExplorationHtmlParserEntityType
import org.oppia.util.parser.HtmlParser
import javax.inject.Inject

const val STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY = "STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY"
Expand All @@ -54,14 +56,16 @@ private const val DEFAULT_CONTINUE_INTERACTION_TEXT_ANSWER = "Please continue."
/** The presenter for [StateFragment]. */
@FragmentScope
class StateFragmentPresenter @Inject constructor(
@ExplorationHtmlParserEntityType private val entityType: String,
private val activity: AppCompatActivity,
private val fragment: Fragment,
private val cellularDialogController: CellularDialogController,
private val stateButtonViewModelProvider: ViewModelProvider<StateButtonViewModel>,
private val viewModelProvider: ViewModelProvider<StateViewModel>,
private val explorationDataController: ExplorationDataController,
private val explorationProgressController: ExplorationProgressController,
private val logger: Logger
private val logger: Logger,
private val htmlParserFactory: HtmlParser.Factory
) : ButtonInteractionListener {

veena14cs marked this conversation as resolved.
Show resolved Hide resolved
private var showCellularDataDialog = true
Expand Down Expand Up @@ -92,8 +96,9 @@ class StateFragmentPresenter @Inject constructor(
useCellularData = prefs.useCellularData
}
})
explorationId = fragment.arguments!!.getString(STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY)!!

stateAdapter = StateAdapter(itemList, this as ButtonInteractionListener)
stateAdapter = StateAdapter(itemList, this as ButtonInteractionListener, htmlParserFactory, entityType, explorationId)

veena14cs marked this conversation as resolved.
Show resolved Hide resolved
binding = StateFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
binding.stateRecyclerView.apply {
Expand All @@ -103,7 +108,6 @@ class StateFragmentPresenter @Inject constructor(
it.stateFragment = fragment as StateFragment
it.viewModel = getStateViewModel()
}
explorationId = checkNotNull(fragment.arguments!!.getString(STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY))

subscribeToCurrentState()

Expand Down Expand Up @@ -331,7 +335,7 @@ class StateFragmentPresenter @Inject constructor(
}
}
private fun checkAndAddContentItem() {
if (currentEphemeralState!!.state.hasContent()) {
if (currentEphemeralState.state.hasContent()) {
addContentItem()
} else {
logger.e("StateFragment", "checkAndAddContentItem: State does not have content.")
Expand All @@ -340,7 +344,7 @@ class StateFragmentPresenter @Inject constructor(

private fun addContentItem() {
val contentViewModel = ContentViewModel()
val contentSubtitledHtml: SubtitledHtml = currentEphemeralState!!.state.content
val contentSubtitledHtml: SubtitledHtml = currentEphemeralState.state.content
if (contentSubtitledHtml.contentId != "") {
contentViewModel.contentId = contentSubtitledHtml.contentId
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.oppia.app.player.state

import android.app.Activity
import android.content.Intent
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import org.junit.After
import org.junit.Before
import org.junit.Rule
veena14cs marked this conversation as resolved.
Show resolved Hide resolved
import org.junit.Test
import org.junit.runner.RunWith
import org.oppia.app.R
import org.oppia.app.home.HomeActivity
import org.oppia.app.recyclerview.RecyclerViewMatcher.Companion.atPosition

// TODO(#205): Add test case for image parsing once PR #205 is merged.
/** Tests for [VIEW_TYPE_CONTENT]. */
@RunWith(AndroidJUnit4::class)
class StateFragmentContentCardTest {
veena14cs marked this conversation as resolved.
Show resolved Hide resolved

@Test
fun testContentCard_forDemoExploration_withCustomOppiaTags_displaysParsedHtml() {
ActivityScenario.launch(HomeActivity::class.java).use {
onView(withId(R.id.play_exploration_button)).perform(click())
val htmlResult = "Hi, welcome to Oppia! is a tool that helps you create interactive learning activities that can be continually improved over time.\n\n" +
"Incidentally, do you know where the name 'Oppia' comes from?\n\n"
onView(atPosition(R.id.state_recycler_view, 0)).check(matches(hasDescendant(withText(htmlResult))))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.oppia.util.parser

import javax.inject.Qualifier

/** Qualifier for injecting the entity type for exploration. */
@Qualifier
annotation class ExplorationHtmlParserEntityType
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.oppia.util.parser

import dagger.Module
import dagger.Provides

/** Provides Html parsing entity type dependencies. */
@Module
class HtmlParserEntityTypeModule {
@Provides
@ExplorationHtmlParserEntityType
fun provideExplorationHtmlParserEntityType(): String {
return "exploration"
}
}