-
Notifications
You must be signed in to change notification settings - Fork 527
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 #153/#154 : MultipleChoice/ItemSelection Interaction #258
Closed
Closed
Changes from 60 commits
Commits
Show all changes
75 commits
Select commit
Hold shift + click to select a range
453e858
customization_args issues fix
nikitamarysolomanpvt 8130312
nit
nikitamarysolomanpvt 2f378ef
nit
nikitamarysolomanpvt 296e868
nit
nikitamarysolomanpvt ba0ba3c
nit
nikitamarysolomanpvt e65da93
Merge branch 'customization-args-fixes' into merge-fix
veena14cs f227ed5
Update StateFragmentPresenter.kt
veena14cs e7b7124
added xmls
veena14cs 0e67155
Update RecyclerViewMatcher.kt
veena14cs 4167caf
Update RecyclerViewMatcher.kt
veena14cs 92e6a80
working on interaction
veena14cs 5e27966
added interactions
veena14cs e5bdc57
working on text case
veena14cs 2de2d66
Merge branch 'content-card' into multiple-single-input-interaction
veena14cs fb62097
run test case
veena14cs b588d7c
nit
veena14cs 0008d5a
renamed views.
veena14cs ffba169
Update InteractionAdapter.kt
veena14cs 7c4e694
Update StateAdapter.kt
veena14cs b1a0101
java doc comments.
veena14cs f19829c
Update RecyclerViewMatcher.kt
veena14cs 18d1672
Update AndroidManifest.xml
veena14cs 46aef2d
Update InteractionAdapter.kt
veena14cs 79a2366
Update InteractionAdapter.kt
veena14cs d0a4aa6
Update InteractionAdapter.kt
veena14cs 99184b2
Update InteractionAdapter.kt
veena14cs 40a1f6a
Update SelectionInteractionViewModel.kt
veena14cs eab1559
nit
veena14cs 381da01
Update selection_interaction_item.xml
veena14cs b143f7b
nit
veena14cs 0562b61
Update StateAdapter.kt
veena14cs 7ea8db0
Update StateAdapter.kt
veena14cs 4c92057
Update StateFragmentPresenter.kt
veena14cs 4c38a3d
Delete SelectionContentViewModel.kt
veena14cs 29273ae
Update InteractionAdapter.kt
veena14cs 50bfbdd
Update InteractionAdapter.kt
veena14cs 6b35a81
Update StateAdapter.kt
veena14cs a08a2d1
Update StateAdapter.kt
veena14cs 5bdd1ba
fixed issues
veena14cs ebdb637
Fixed issues.
veena14cs 69c91fc
update
veena14cs 90c4635
Merge branch 'content-card' into multiple-single-input-interaction
veena14cs 01ad3a4
Update welcome.json
veena14cs 1dd48a2
Update selection_interaction_item.xml
veena14cs e566dbb
Update multiple_choice_interaction_items.xml
veena14cs 0d180cb
Update item_selection_interaction_items.xml
veena14cs ef7117b
update Kdoc
veena14cs b52e96f
Update InteractionAdapter.kt
veena14cs d7b130a
Merge branch 'content-card' into multiple-single-input-interaction
veena14cs e6531b7
Update StateAdapter.kt
veena14cs 92e1216
working on test
veena14cs a638a08
Merge branch 'content-card' into multiple-single-input-interaction
veena14cs c3c03cd
add new exploration
veena14cs 03aaa69
adding test id
veena14cs 979ebda
Update InteractionAdapter.kt
veena14cs 04852e9
Update InteractionAdapter.kt
veena14cs 5c48a97
Update InteractionAdapter.kt
veena14cs 2ba69b7
fixes
veena14cs 5e74aaf
updated
veena14cs 3e8dce7
udated kdoc
veena14cs 5e9abab
Update StateAdapter.kt
veena14cs c0626a5
Update StateAdapter.kt
veena14cs 19740a9
Update StateAdapter.kt
veena14cs cf55bc4
Update StateFragmentPresenter.kt
veena14cs d9a4c23
Update StateFragmentPresenter.kt
veena14cs df1941c
Update StateFragmentPresenter.kt
veena14cs d6ffa52
Update StateFragmentPresenter.kt
veena14cs 37989b9
Update StateFragmentPresenter.kt
veena14cs 7bb49c2
Update StateFragmentPresenter.kt
veena14cs 21da67f
update
veena14cs 54a37d1
fixes
veena14cs 224b073
Update StateAdapter.kt
veena14cs 72f677b
Update StateSelectionInteractionTest.kt
veena14cs 4fbeef3
created custom selectionview
veena14cs 7772fa2
update
veena14cs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
167 changes: 167 additions & 0 deletions
167
app/src/main/java/org/oppia/app/player/state/InteractionAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package org.oppia.app.player.state | ||
|
||
import android.text.Spannable | ||
import android.util.Log | ||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.databinding.DataBindingUtil | ||
import androidx.databinding.ViewDataBinding | ||
import androidx.databinding.library.baseAdapters.BR | ||
import androidx.recyclerview.widget.RecyclerView | ||
import kotlinx.android.synthetic.main.item_selection_interaction_items.view.item_selection_contents_text_view | ||
import kotlinx.android.synthetic.main.item_selection_interaction_items.view.checkbox_container | ||
import kotlinx.android.synthetic.main.item_selection_interaction_items.view.item_selection_checkbox | ||
import kotlinx.android.synthetic.main.multiple_choice_interaction_items.view.multiple_choice_content_text_view | ||
import kotlinx.android.synthetic.main.multiple_choice_interaction_items.view.multiple_choice_radio_button | ||
import kotlinx.android.synthetic.main.multiple_choice_interaction_items.view.radio_container | ||
import org.oppia.app.R | ||
import org.oppia.app.databinding.ItemSelectionInteractionItemsBinding | ||
import org.oppia.app.databinding.MultipleChoiceInteractionItemsBinding | ||
import org.oppia.app.model.InteractionObject | ||
import org.oppia.app.model.StringList | ||
import org.oppia.app.player.state.itemviewmodel.CustomizationArgsInteractionViewModel | ||
import org.oppia.app.player.state.itemviewmodel.SelectionContentViewModel | ||
import org.oppia.app.player.state.listener.InteractionAnswerRetriever | ||
import org.oppia.util.parser.HtmlParser | ||
|
||
private const val VIEW_TYPE_RADIO_BUTTONS = 1 | ||
private const val VIEW_TYPE_CHECKBOXES = 2 | ||
private const val INTERACTION_ADAPTER_TAG = "Interaction Adapter" | ||
|
||
/** | ||
* Adapter to bind the interactions to the [RecyclerView]. It handles MultipleChoiceInput | ||
* and ItemSelectionInput interaction views. | ||
* */ | ||
class InteractionAdapter( | ||
private val htmlParserFactory: HtmlParser.Factory, | ||
private val entityType: String, | ||
private val explorationId: String, | ||
private val itemList: MutableList<SelectionContentViewModel>, | ||
private val customizationArgs: CustomizationArgsInteractionViewModel | ||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), InteractionAnswerRetriever { | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private var itemSelectedPosition = -1 | ||
private var selectedAnswerIndex = -1 | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private var selectedHtmlStringList = mutableListOf<String>() | ||
|
||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||
return when (viewType) { | ||
VIEW_TYPE_RADIO_BUTTONS -> { | ||
val inflater = LayoutInflater.from(parent.context) | ||
val binding = | ||
DataBindingUtil.inflate<MultipleChoiceInteractionItemsBinding>( | ||
inflater, | ||
R.layout.multiple_choice_interaction_items, | ||
parent, | ||
/* attachToParent= */ false | ||
) | ||
MultipleChoiceViewHolder(binding) | ||
} | ||
VIEW_TYPE_CHECKBOXES -> { | ||
val inflater = LayoutInflater.from(parent.context) | ||
val binding = | ||
DataBindingUtil.inflate<ItemSelectionInteractionItemsBinding>( | ||
inflater, | ||
R.layout.item_selection_interaction_items, | ||
parent, | ||
/* attachToParent= */ false | ||
) | ||
ItemSelectionViewHolder(binding) | ||
} | ||
else -> throw IllegalArgumentException("Invalid view type") | ||
} | ||
} | ||
|
||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||
when (holder.itemViewType) { | ||
VIEW_TYPE_RADIO_BUTTONS -> (holder as MultipleChoiceViewHolder).bind( | ||
itemList[position].htmlContent, | ||
position, | ||
itemSelectedPosition | ||
) | ||
VIEW_TYPE_CHECKBOXES -> (holder as ItemSelectionViewHolder).bind( | ||
itemList[position] | ||
) | ||
} | ||
} | ||
|
||
// Determines the appropriate ViewType according to the interaction type. | ||
override fun getItemViewType(position: Int): Int { | ||
return if (customizationArgs.interactionId == "ItemSelectionInput") { | ||
if (customizationArgs.maxAllowableSelectionCount > 1) { | ||
VIEW_TYPE_CHECKBOXES | ||
} else { | ||
VIEW_TYPE_RADIO_BUTTONS | ||
} | ||
} else { | ||
VIEW_TYPE_RADIO_BUTTONS | ||
} | ||
} | ||
|
||
override fun getItemCount(): Int { | ||
return itemList.size | ||
} | ||
|
||
private inner class ItemSelectionViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root) { | ||
internal fun bind(selectionContentViewModel: SelectionContentViewModel) { | ||
binding.setVariable(BR.htmlContent, selectionContentViewModel.htmlContent) | ||
binding.executePendingBindings() | ||
val htmlResult: Spannable = htmlParserFactory.create(entityType, explorationId).parseOppiaHtml( | ||
selectionContentViewModel.htmlContent, | ||
binding.root.item_selection_contents_text_view | ||
) | ||
binding.root.item_selection_contents_text_view.text = htmlResult | ||
binding.root.item_selection_checkbox.isChecked = selectionContentViewModel.isAnswerSelected | ||
binding.root.checkbox_container.setOnClickListener { | ||
if (binding.root.item_selection_checkbox.isChecked) { | ||
itemList[adapterPosition].isAnswerSelected = false | ||
selectedHtmlStringList.remove(binding.root.item_selection_contents_text_view.text.toString()) | ||
} else { | ||
if (selectedHtmlStringList.size != customizationArgs.maxAllowableSelectionCount) { | ||
itemList[adapterPosition].isAnswerSelected = true | ||
selectedHtmlStringList.add(binding.root.item_selection_contents_text_view.text.toString()) | ||
} else { | ||
Log.d( | ||
INTERACTION_ADAPTER_TAG, | ||
"You cannot select more than ${customizationArgs.maxAllowableSelectionCount} options" | ||
) | ||
} | ||
} | ||
notifyDataSetChanged() | ||
} | ||
} | ||
} | ||
|
||
private inner class MultipleChoiceViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root) { | ||
internal fun bind(rawString: String, position: Int, selectedPosition: Int) { | ||
binding.setVariable(BR.htmlContent, rawString) | ||
binding.executePendingBindings() | ||
val htmlResult: Spannable = htmlParserFactory.create(entityType, explorationId).parseOppiaHtml( | ||
rawString, | ||
binding.root.multiple_choice_content_text_view | ||
) | ||
binding.root.multiple_choice_content_text_view.text = htmlResult | ||
binding.root.multiple_choice_radio_button.isChecked = selectedPosition == position | ||
binding.root.radio_container.setOnClickListener { | ||
itemSelectedPosition = adapterPosition | ||
selectedAnswerIndex = adapterPosition | ||
notifyDataSetChanged() | ||
} | ||
} | ||
} | ||
|
||
override fun getPendingAnswer(): InteractionObject { | ||
val interactionObjectBuilder = InteractionObject.newBuilder() | ||
if (customizationArgs.interactionId == "ItemSelectionInput") { | ||
if (selectedHtmlStringList.size >= 0) { | ||
interactionObjectBuilder.setOfHtmlString = StringList.newBuilder().addAllHtml(selectedHtmlStringList).build() | ||
} else { | ||
if (selectedAnswerIndex >= 0) { | ||
interactionObjectBuilder.nonNegativeInt = selectedAnswerIndex | ||
} | ||
|
||
} | ||
} | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return interactionObjectBuilder.build() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import org.oppia.app.player.audio.AudioFragment | |
import org.oppia.app.player.audio.CellularDataDialogFragment | ||
import org.oppia.app.player.exploration.ExplorationActivity | ||
import org.oppia.app.player.state.itemviewmodel.ContentViewModel | ||
import org.oppia.app.player.state.itemviewmodel.CustomizationArgsInteractionViewModel | ||
import org.oppia.app.player.state.itemviewmodel.StateButtonViewModel | ||
import org.oppia.app.player.state.listener.ButtonInteractionListener | ||
import org.oppia.app.viewmodel.ViewModelProvider | ||
|
@@ -37,6 +38,7 @@ import javax.inject.Inject | |
const val STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY = "STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY" | ||
private const val TAG_CELLULAR_DATA_DIALOG = "CELLULAR_DATA_DIALOG" | ||
private const val TAG_AUDIO_FRAGMENT = "AUDIO_FRAGMENT" | ||
private const val TAG_STATE_FRAGMENT = "STATE_FRAGMENT" | ||
|
||
private const val CONTINUE = "Continue" | ||
private const val END_EXPLORATION = "EndExploration" | ||
|
@@ -176,6 +178,7 @@ class StateFragmentPresenter @Inject constructor( | |
itemList.clear() | ||
currentEphemeralState = result | ||
checkAndAddContentItem() | ||
checkAndAddInteraction() | ||
updateDummyStateName() | ||
|
||
val interactionId = result.state.interaction.id | ||
|
@@ -352,6 +355,46 @@ class StateFragmentPresenter @Inject constructor( | |
itemList.add(contentViewModel) | ||
stateAdapter.notifyDataSetChanged() | ||
} | ||
private fun checkAndAddInteraction() { | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (currentEphemeralState.stateTypeCase.number == EphemeralState.PENDING_STATE_FIELD_NUMBER) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check the enum directly: if (currentEphemeralState.stateTypeCase == EphemeralState.TypeCase.PENDING_STATE) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is giving error to TypeCase as unresolved reference. |
||
when (currentEphemeralState.state.interaction.id) { | ||
MULTIPLE_CHOICE_INPUT -> { | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
addMultipleChoiceInputItem() | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
ITEM_SELECT_INPUT -> { | ||
addMultipleChoiceInputItem() | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun addMultipleChoiceInputItem() { | ||
val customizationArgsMap: Map<String, InteractionObject> = | ||
currentEphemeralState.state.interaction.customizationArgsMap | ||
val multipleChoiceInputInteractionViewModel = CustomizationArgsInteractionViewModel() | ||
val allKeys: Set<String> = customizationArgsMap.keys | ||
|
||
for (key in allKeys) { | ||
logger.d(TAG_STATE_FRAGMENT, key) | ||
} | ||
when { | ||
customizationArgsMap.contains("choices") -> { | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
when { | ||
customizationArgsMap.contains("maxAllowableSelectionCount") -> { | ||
multipleChoiceInputInteractionViewModel.maxAllowableSelectionCount = | ||
currentEphemeralState.state.interaction.customizationArgsMap["maxAllowableSelectionCount"]!!.signedInt | ||
multipleChoiceInputInteractionViewModel.minAllowableSelectionCount = | ||
currentEphemeralState.state.interaction.customizationArgsMap["minAllowableSelectionCount"]!!.signedInt | ||
} | ||
} | ||
multipleChoiceInputInteractionViewModel.interactionId = currentEphemeralState.state.interaction.id | ||
multipleChoiceInputInteractionViewModel.choiceItems = | ||
currentEphemeralState.state.interaction.customizationArgsMap["choices"]!!.setOfHtmlString.htmlList | ||
} | ||
} | ||
itemList.add(multipleChoiceInputInteractionViewModel) | ||
stateAdapter.notifyDataSetChanged() | ||
} | ||
|
||
private fun updateNavigationButtonVisibility( | ||
interactionId: String, | ||
|
15 changes: 15 additions & 0 deletions
15
...in/java/org/oppia/app/player/state/itemviewmodel/CustomizationArgsInteractionViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.oppia.app.player.state.itemviewmodel | ||
|
||
import androidx.lifecycle.ViewModel | ||
import org.oppia.app.fragment.FragmentScope | ||
import javax.inject.Inject | ||
|
||
/** [ViewModel] for multiple or item-selection input choice list. */ | ||
@FragmentScope | ||
class CustomizationArgsInteractionViewModel : ViewModel() { | ||
|
||
var choiceItems: MutableList<String>? = null | ||
var interactionId: String = "" | ||
var maxAllowableSelectionCount: Int = 0 | ||
var minAllowableSelectionCount: Int = 0 | ||
} |
12 changes: 12 additions & 0 deletions
12
app/src/main/java/org/oppia/app/player/state/itemviewmodel/SelectionContentViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.oppia.app.player.state.itemviewmodel | ||
|
||
import androidx.lifecycle.ViewModel | ||
import org.oppia.app.fragment.FragmentScope | ||
import javax.inject.Inject | ||
|
||
/** [ViewModel] for MultipleChoiceInput values or ItemSelectionInput values. */ | ||
@FragmentScope | ||
class SelectionContentViewModel : ViewModel() { | ||
var htmlContent: String ="" | ||
veena14cs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var isAnswerSelected = false | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stopPlayingExploration()
is added to test with different exploration.