Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into topic-review-low…
Browse files Browse the repository at this point in the history
…-fi-part-1
  • Loading branch information
Rajat Talesra committed Oct 14, 2019
2 parents 3d4183a + f1ec4bf commit f863f6e
Show file tree
Hide file tree
Showing 15 changed files with 576 additions and 24 deletions.
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/OppiaTheme">
<activity android:name="org.oppia.app.topic.conceptcard.testing.ConceptCardFragmentTestActivity"/>
<activity android:name="org.oppia.app.player.state.testing.StateFragmentTestActivity"/>
<activity android:name=".player.exploration.ExplorationActivity"/>
<activity android:name=".topic.questionplayer.QuestionPlayerActivity"/>
<activity android:name=".topic.review.ReviewActivity"/>
<activity android:name=".topic.TopicActivity"/>

<activity android:name="org.oppia.app.player.state.testing.StateFragmentTestActivity"/>
<activity android:name="org.oppia.app.home.HomeActivity">
<intent-filter>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/oppia/app/activity/ActivityComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import dagger.Subcomponent
import org.oppia.app.fragment.FragmentComponent
import org.oppia.app.home.HomeActivity
import org.oppia.app.player.exploration.ExplorationActivity
import org.oppia.app.topic.conceptcard.testing.ConceptCardFragmentTestActivity
import org.oppia.app.player.state.testing.StateFragmentTestActivity
import org.oppia.app.testing.BindableAdapterTestActivity
import org.oppia.app.topic.TopicActivity
Expand All @@ -28,6 +29,7 @@ interface ActivityComponent {
fun inject(bindableAdapterTestActivity: BindableAdapterTestActivity)
fun inject(explorationActivity: ExplorationActivity)
fun inject(homeActivity: HomeActivity)
fun inject(conceptCardFragmentTestActivity: ConceptCardFragmentTestActivity)
fun inject(questionPlayerActivity: QuestionPlayerActivity)
fun inject(reviewActivity: ReviewActivity)
fun inject(topicActivity: TopicActivity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,26 @@ import org.oppia.app.R
import org.oppia.app.fragment.InjectableDialogFragment
import javax.inject.Inject

private const val KEY_SKILL_ID = "SKILL_ID"

/* Fragment that displays a fullscreen dialog for concept cards */
class ConceptCardFragment : InjectableDialogFragment() {

companion object {
/**
* Creates a new instance of a DialogFragment to display content
* @param skillId Used in TopicController to get correct concept card data.
* @return [ConceptCardFragment]: DialogFragment
*/
fun newInstance(skillId: String): ConceptCardFragment {
val conceptCardFrag = ConceptCardFragment()
val args = Bundle()
args.putString(KEY_SKILL_ID, skillId)
conceptCardFrag.arguments = args
return conceptCardFrag
}
}

@Inject lateinit var conceptCardPresenter: ConceptCardPresenter

override fun onAttach(context: Context?) {
Expand All @@ -25,7 +43,9 @@ class ConceptCardFragment : InjectableDialogFragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return conceptCardPresenter.handleCreateView(inflater, container)
val args = checkNotNull(arguments) { "Expected arguments to be passed to ConceptCardFragment" }
val skillId = checkNotNull(args.getString(KEY_SKILL_ID)) { "Expected skillId to be passed to ConceptCardFragment" }
return conceptCardPresenter.handleCreateView(inflater, container, skillId)
}

override fun onStart() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import org.oppia.app.R
import org.oppia.app.databinding.ConceptcardFragmentBinding
import org.oppia.app.databinding.ConceptCardExampleViewBinding
import org.oppia.app.databinding.ConceptCardFragmentBinding
import org.oppia.app.fragment.FragmentScope
import org.oppia.app.model.SubtitledHtml
import org.oppia.app.recyclerview.BindableAdapter
import org.oppia.app.viewmodel.ViewModelProvider
import javax.inject.Inject

Expand All @@ -17,21 +20,37 @@ class ConceptCardPresenter @Inject constructor(
private val fragment: Fragment,
private val viewModelProvider: ViewModelProvider<ConceptCardViewModel>
){
fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
val binding = ConceptcardFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)

/** Sets up data binding and adapter for RecyclerView */
fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?, skillId: String): View? {
val viewModel = getConceptCardViewModel()
viewModel.setSkillId(skillId)
val binding = ConceptCardFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
binding.conceptCardToolbar.setNavigationIcon(R.drawable.ic_close_white_24dp)
binding.conceptCardToolbar.setNavigationOnClickListener {
(fragment as? DialogFragment)?.dismiss()
}
binding.workedExamples.apply {
adapter = createRecyclerViewAdapter()
}

binding.let {
it.viewModel = getConceptCardViewModel()
it.viewModel = viewModel
it.lifecycleOwner = fragment
}

return binding.root
}

private fun getConceptCardViewModel(): ConceptCardViewModel {
return viewModelProvider.getForFragment(fragment, ConceptCardViewModel::class.java)
}

private fun createRecyclerViewAdapter(): BindableAdapter<SubtitledHtml> {
return BindableAdapter.Builder
.newBuilder<SubtitledHtml>()
.registerViewDataBinder(
inflateDataBinding = ConceptCardExampleViewBinding::inflate,
setViewModel = ConceptCardExampleViewBinding::setSubtitledHtml)
.build()
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,63 @@
package org.oppia.app.topic.conceptcard

import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel
import org.oppia.app.fragment.FragmentScope
import org.oppia.app.model.ConceptCard
import org.oppia.app.model.SubtitledHtml
import org.oppia.domain.topic.TopicController
import org.oppia.util.data.AsyncResult
import org.oppia.util.logging.Logger
import javax.inject.Inject

/** [ViewModel] for concept card, providing rich text and worked examples */
@FragmentScope
class ConceptCardViewModel @Inject constructor() : ViewModel() {
fun getDummyText() = "hello world"
}
class ConceptCardViewModel @Inject constructor(
private val topicController: TopicController,
private val logger: Logger
) : ViewModel() {

private lateinit var skillId: String

/** Live Data for concept card explanation */
val conceptCardLiveData: LiveData<ConceptCard> by lazy {
processConceptCardLiveData()
}

/** Live Data for concept card worked examples. */
val workedExamplesLiveData: LiveData<List<SubtitledHtml>> by lazy {
processWorkedExamplesLiveData()
}

/** Sets the value of skillId. Must be called before setting ViewModel to binding. */
fun setSkillId(id: String) {
skillId = id
}

private val conceptCardResultLiveData: LiveData<AsyncResult<ConceptCard>> by lazy {
topicController.getConceptCard(skillId)
}

private fun processConceptCardLiveData(): LiveData<ConceptCard> {
return Transformations.map(conceptCardResultLiveData, ::processConceptCardResult)
}

private fun processWorkedExamplesLiveData(): LiveData<List<SubtitledHtml>> {
return Transformations.map(conceptCardResultLiveData, ::processConceptCardWorkExamples)
}

private fun processConceptCardResult(conceptCardResult: AsyncResult<ConceptCard>): ConceptCard {
if (conceptCardResult.isFailure()) {
logger.e("ConceptCardFragment", "Failed to retrieve Concept Card: " + conceptCardResult.getErrorOrNull())
}
return conceptCardResult.getOrDefault(ConceptCard.getDefaultInstance())
}

private fun processConceptCardWorkExamples(conceptCardResult: AsyncResult<ConceptCard>): List<SubtitledHtml> {
if (conceptCardResult.isFailure()) {
logger.e("ConceptCardFragment", "Failed to retrieve Concept Card: " + conceptCardResult.getErrorOrNull())
}
return conceptCardResult.getOrDefault(ConceptCard.getDefaultInstance()).workedExampleList
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.oppia.app.topic.conceptcard.testing

import android.os.Bundle
import org.oppia.app.activity.InjectableAppCompatActivity
import javax.inject.Inject

/** Test Activity used for testing ConceptCardFragment */
class ConceptCardFragmentTestActivity : InjectableAppCompatActivity() {

@Inject lateinit var conceptCardFragmentTestActivityController: ConceptCardFragmentTestActivityPresenter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityComponent.inject(this)
conceptCardFragmentTestActivityController.handleOnCreate()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.oppia.app.topic.conceptcard.testing

import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.concept_card_fragment_test_activity.*
import org.oppia.app.R
import org.oppia.app.topic.conceptcard.ConceptCardFragment
import org.oppia.domain.topic.TEST_SKILL_ID_1
import org.oppia.domain.topic.TEST_SKILL_ID_2
import javax.inject.Inject

private const val TAG_CONCEPT_CARD_DIALOG = "CONCEPT_CARD_DIALOG"

/** The presenter for [ConceptCardFragmentTestActivity] */
class ConceptCardFragmentTestActivityPresenter @Inject constructor(private val activity: AppCompatActivity) {
fun handleOnCreate() {
activity.setContentView(R.layout.concept_card_fragment_test_activity)
activity.open_dialog_1.setOnClickListener {
val frag = ConceptCardFragment.newInstance(TEST_SKILL_ID_1)
frag.showNow(activity.supportFragmentManager, TAG_CONCEPT_CARD_DIALOG)
}
activity.open_dialog_2.setOnClickListener {
val frag = ConceptCardFragment.newInstance(TEST_SKILL_ID_2)
frag.showNow(activity.supportFragmentManager, TAG_CONCEPT_CARD_DIALOG)
}
}
}
22 changes: 22 additions & 0 deletions app/src/main/res/layout/concept_card_example_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="subtitledHtml"
type="org.oppia.app.model.SubtitledHtml" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:text="@{subtitledHtml.getHtml()}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
<import type="android.view.View"/>
<variable
name="viewModel"
type="org.oppia.app.topic.conceptcard.ConceptCardViewModel"/>
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent"
android:layout_width="match_parent"

android:background="@color/colorConceptCardBackground">
<androidx.appcompat.widget.Toolbar
android:id="@+id/concept_card_toolbar"
Expand All @@ -28,13 +26,26 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:id="@+id/rich_text_card"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:text="@{viewModel.getDummyText()}" />
android:orientation="vertical"
android:paddingTop="10dp">
<TextView
android:id="@+id/explanation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:gravity="center"
android:visibility="@{viewModel.conceptCardLiveData.hasExplanation() ? View.VISIBLE : View.GONE}"
android:text="@{viewModel.conceptCardLiveData.explanation.getHtml()}" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/worked_examples"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:data="@{viewModel.workedExamplesLiveData}" />
</LinearLayout>
</ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
</layout>
14 changes: 14 additions & 0 deletions app/src/main/res/layout/concept_card_fragment_test_activity.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/open_dialog_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/open_dialog_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Loading

0 comments on commit f863f6e

Please sign in to comment.