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 NPS Survey Gating #5356

Merged
merged 19 commits into from
Apr 6, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.appcompat.widget.Toolbar
import androidx.core.view.doOnPreDraw
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.Transformations
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityScope
Expand Down Expand Up @@ -528,42 +529,47 @@ class ExplorationActivityPresenter @Inject constructor(
}

private fun maybeShowSurveyDialog(profileId: ProfileId, topicId: String) {
surveyGatingController.maybeShowSurvey(profileId, topicId).toLiveData()
.observe(
activity
) { gatingResult ->
when (gatingResult) {
is AsyncResult.Pending -> {
oppiaLogger.d("ExplorationActivity", "A gating decision is pending")
}
is AsyncResult.Failure -> {
oppiaLogger.e(
"ExplorationActivity",
"Failed to retrieve gating decision",
gatingResult.error
)
backPressActivitySelector()
}
is AsyncResult.Success -> {
if (gatingResult.value) {
val dialogFragment =
SurveyWelcomeDialogFragment.newInstance(
profileId,
topicId,
explorationId,
SURVEY_QUESTIONS
)
val transaction = activity.supportFragmentManager.beginTransaction()
transaction
.add(dialogFragment, TAG_SURVEY_WELCOME_DIALOG)
.addToBackStack(null)
.commit()
} else {
val liveData = surveyGatingController.maybeShowSurvey(profileId, topicId).toLiveData()
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
liveData.observe(
activity,
object : Observer<AsyncResult<Boolean>> {
override fun onChanged(gatingResult: AsyncResult<Boolean>?) {
when (gatingResult) {
is AsyncResult.Pending -> {
oppiaLogger.d("ExplorationActivity", "A gating decision is pending")
}
is AsyncResult.Failure -> {
oppiaLogger.e(
"ExplorationActivity",
"Failed to retrieve gating decision",
gatingResult.error
)
backPressActivitySelector()
}
is AsyncResult.Success -> {
if (gatingResult.value) {
val dialogFragment =
SurveyWelcomeDialogFragment.newInstance(
profileId,
topicId,
explorationId,
SURVEY_QUESTIONS
)
val transaction = activity.supportFragmentManager.beginTransaction()
transaction
.add(dialogFragment, TAG_SURVEY_WELCOME_DIALOG)
.addToBackStack(null)
.commit()
} else {
backPressActivitySelector()
}
// Changes to underlying DataProviders will update the gating result.
liveData.removeObserver(this)
}
}
}
}
)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ class StateFragmentPresenter @Inject constructor(
fun onReturnToTopicButtonClicked() {
hideKeyboard()
markExplorationCompleted()
maybeShowSurveyDialog(profileId, topicId)
}

private fun showOrHideAudioByState(state: State) {
Expand Down Expand Up @@ -455,13 +454,17 @@ class StateFragmentPresenter @Inject constructor(
fun getExplorationCheckpointState() = explorationCheckpointState

private fun markExplorationCompleted() {
storyProgressController.recordCompletedChapter(
val markStoryCompletedLivedata = storyProgressController.recordCompletedChapter(
profileId,
topicId,
storyId,
explorationId,
oppiaClock.getCurrentTimeMs()
)
).toLiveData()

// Only check gating result when the previous operation has completed because gating depends on
// result of saving the time spent in the exploration, at the end of the exploration.
markStoryCompletedLivedata.observe(activity, { maybeShowSurveyDialog(profileId, topicId) })
}

private fun showHintsAndSolutions(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) {
Expand Down Expand Up @@ -535,10 +538,11 @@ class StateFragmentPresenter @Inject constructor(
}

private fun maybeShowSurveyDialog(profileId: ProfileId, topicId: String) {
surveyGatingController.maybeShowSurvey(profileId, topicId).toLiveData()
.observe(
activity,
{ gatingResult ->
val liveData = surveyGatingController.maybeShowSurvey(profileId, topicId).toLiveData()
liveData.observe(
activity,
object : Observer<AsyncResult<Boolean>> {
override fun onChanged(gatingResult: AsyncResult<Boolean>?) {
when (gatingResult) {
is AsyncResult.Pending -> {
oppiaLogger.d("StateFragment", "A gating decision is pending")
Expand Down Expand Up @@ -569,10 +573,13 @@ class StateFragmentPresenter @Inject constructor(
(activity as StopStatePlayingSessionWithSavedProgressListener)
.deleteCurrentProgressAndStopSession(isCompletion = true)
}
// Changes to underlying DataProviders will update the gating result.
liveData.removeObserver(this)
}
}
}
)
}
)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.player.exploration.HintsAndSolutionExplorationManagerFragment
import org.oppia.android.app.player.exploration.TAG_HINTS_AND_SOLUTION_EXPLORATION_MANAGER
import org.oppia.android.app.player.state.StateFragment
import org.oppia.android.app.player.stopplaying.StopStatePlayingSessionWithSavedProgressListener
import org.oppia.android.app.survey.SurveyWelcomeDialogFragment
import org.oppia.android.app.survey.TAG_SURVEY_WELCOME_DIALOG
import org.oppia.android.app.viewmodel.ViewModelProvider
import org.oppia.android.databinding.StateFragmentTestActivityBinding
import org.oppia.android.domain.exploration.ExplorationDataController
import org.oppia.android.domain.oppialogger.OppiaLogger
import org.oppia.android.domain.survey.SurveyGatingController
import org.oppia.android.domain.topic.TEST_EXPLORATION_ID_2
import org.oppia.android.domain.topic.TEST_STORY_ID_0
import org.oppia.android.domain.topic.TEST_TOPIC_ID_0
Expand All @@ -28,8 +32,9 @@ private const val TEST_ACTIVITY_TAG = "TestActivity"
class StateFragmentTestActivityPresenter @Inject constructor(
private val activity: AppCompatActivity,
private val explorationDataController: ExplorationDataController,
private val surveyGatingController: SurveyGatingController,
private val oppiaLogger: OppiaLogger,
private val viewModelProvider: ViewModelProvider<StateFragmentTestViewModel>
private val viewModelProvider: ViewModelProvider<StateFragmentTestViewModel>,
) {

private var profileId: Int = 1
Expand Down Expand Up @@ -112,6 +117,46 @@ class StateFragmentTestActivityPresenter @Inject constructor(
)
}

private fun maybeShowSurveyDialog(profileId: ProfileId, topicId: String) {
BenHenning marked this conversation as resolved.
Show resolved Hide resolved
val liveData = surveyGatingController.maybeShowSurvey(profileId, topicId).toLiveData()
liveData.observe(
activity,
object : Observer<AsyncResult<Boolean>> {
override fun onChanged(gatingResult: AsyncResult<Boolean>?) {
when (gatingResult) {
is AsyncResult.Pending -> {
oppiaLogger.d("StateFragmentTest", "A gating decision is pending")
}
is AsyncResult.Failure -> {
oppiaLogger.e(
"StateFragmentTest",
"Failed to retrieve gating decision",
gatingResult.error
)
(activity as StopStatePlayingSessionWithSavedProgressListener)
.deleteCurrentProgressAndStopSession(isCompletion = true)
}
is AsyncResult.Success -> {
if (gatingResult.value) {
val surveyPopup = SurveyWelcomeDialogFragment.newInstance(
profileId,
topicId,
explorationId,
listOf()
)
activity.supportFragmentManager.beginTransaction()
.add(R.id.state_fragment_placeholder, surveyPopup, TAG_SURVEY_WELCOME_DIALOG)
.commitNow()
}
// Changes to underlying DataProviders will update the gating result.
liveData.removeObserver(this)
}
}
}
}
)
}

/**
* Initializes fragments that depend on ephemeral state (which isn't valid to do until the play
* session is fully started).
Expand Down Expand Up @@ -142,6 +187,9 @@ class StateFragmentTestActivityPresenter @Inject constructor(
private fun finishExploration(isCompletion: Boolean) {
explorationDataController.stopPlayingExploration(isCompletion)

val userProfileId = ProfileId.newBuilder().setInternalId(profileId).build()
maybeShowSurveyDialog(userProfileId, topicId)

getStateFragment()?.let { fragment ->
activity.supportFragmentManager.beginTransaction().remove(fragment).commitNow()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class SurveyWelcomeDialogFragmentPresenter @Inject constructor(
}

profileManagementController.updateSurveyLastShownTimestamp(profileId)

logSurveyPopUpShownEvent(explorationId, topicId, profileId)

return binding.root
Expand Down
Loading
Loading