diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 9389c372c45..730a3ac2151 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -209,6 +209,7 @@ VIEW_MODELS_WITH_RESOURCE_IMPORTS = [ "src/main/java/org/oppia/android/app/onboarding/OnboadingSlideViewModel.kt", "src/main/java/org/oppia/android/app/onboarding/OnboardingViewModel.kt", "src/main/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicItemViewModel.kt", + "src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt", "src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt", "src/main/java/org/oppia/android/app/parser/FractionParsingUiError.kt", "src/main/java/org/oppia/android/app/parser/StringToNumberParser.kt", @@ -298,7 +299,6 @@ VIEW_MODELS = [ "src/main/java/org/oppia/android/app/options/OptionsAppLanguageViewModel.kt", "src/main/java/org/oppia/android/app/options/OptionsAudioLanguageViewModel.kt", "src/main/java/org/oppia/android/app/options/OptionsItemViewModel.kt", - "src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt", "src/main/java/org/oppia/android/app/options/ReadingTextSizeSelectionViewModel.kt", "src/main/java/org/oppia/android/app/player/exploration/ExplorationViewModel.kt", "src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt", @@ -679,6 +679,7 @@ kt_android_library( "//domain/src/main/java/org/oppia/android/domain/clipboard:clipboard_controller", "//domain/src/main/java/org/oppia/android/domain/onboarding:state_controller", "//domain/src/main/java/org/oppia/android/domain/profile:profile_management_controller", + "//model/src/main/proto:arguments_java_proto_lite", "//third_party:androidx_core_core", "//third_party:androidx_databinding_databinding-common", "//third_party:androidx_databinding_databinding-runtime", diff --git a/app/src/main/java/org/oppia/android/app/home/RouteToExplorationListener.kt b/app/src/main/java/org/oppia/android/app/home/RouteToExplorationListener.kt index 80614517973..3c8081a3152 100755 --- a/app/src/main/java/org/oppia/android/app/home/RouteToExplorationListener.kt +++ b/app/src/main/java/org/oppia/android/app/home/RouteToExplorationListener.kt @@ -1,13 +1,16 @@ package org.oppia.android.app.home +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ProfileId + /** Listener for when an activity should route to a exploration. */ interface RouteToExplorationListener { fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) } diff --git a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedActivity.kt b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedActivity.kt index d3e139f5d61..f16686ae092 100644 --- a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedActivity.kt +++ b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedActivity.kt @@ -8,6 +8,7 @@ import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.ActivityIntentFactories import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity @@ -48,42 +49,42 @@ class RecentlyPlayedActivity : } override fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( ExplorationActivity.createExplorationActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) } override fun routeToResumeLesson( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { startActivity( ResumeLessonActivity.createResumeLessonActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, explorationCheckpoint ) ) diff --git a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt index 386d5ddcd0a..9c00b790290 100755 --- a/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedFragmentPresenter.kt @@ -14,6 +14,7 @@ import org.oppia.android.R import org.oppia.android.app.fragment.FragmentScope import org.oppia.android.app.home.RouteToExplorationListener import org.oppia.android.app.model.ChapterPlayState +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.PromotedActivityList @@ -237,6 +238,9 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( } fun onOngoingStoryClicked(promotedStory: PromotedStory) { + val profileId = ProfileId.newBuilder().apply { + internalId = internalProfileId + }.build() val canHavePartialProgressSaved = when (promotedStory.chapterPlayState) { ChapterPlayState.IN_PROGRESS_SAVED, ChapterPlayState.IN_PROGRESS_NOT_SAVED, @@ -248,10 +252,7 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( if (promotedStory.chapterPlayState == ChapterPlayState.IN_PROGRESS_SAVED) { val explorationCheckpointLiveData = explorationCheckpointController.retrieveExplorationCheckpoint( - ProfileId.newBuilder().apply { - internalId = internalProfileId - }.build(), - promotedStory.explorationId + profileId, promotedStory.explorationId ).toLiveData() explorationCheckpointLiveData.observe( @@ -261,11 +262,11 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( if (it is AsyncResult.Success) { explorationCheckpointLiveData.removeObserver(this) routeToResumeLessonListener.routeToResumeLesson( - internalProfileId, + profileId, promotedStory.topicId, promotedStory.storyId, promotedStory.explorationId, - backflowScreen = null, + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, explorationCheckpoint = it.value ) } else if (it is AsyncResult.Failure) { @@ -320,11 +321,11 @@ class RecentlyPlayedFragmentPresenter @Inject constructor( is AsyncResult.Success -> { oppiaLogger.d("RecentlyPlayedFragment", "Successfully loaded exploration") routeToExplorationListener.routeToExploration( - internalProfileId, + ProfileId.newBuilder().apply { internalId = internalProfileId }.build(), topicId, storyId, explorationId, - backflowScreen = null, + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, isCheckpointingEnabled = canHavePartialProgressSaved ) activity.finish() diff --git a/app/src/main/java/org/oppia/android/app/options/LoadReadingTextSizeListener.kt b/app/src/main/java/org/oppia/android/app/options/LoadReadingTextSizeListener.kt index 66a233a97ac..136616923c3 100644 --- a/app/src/main/java/org/oppia/android/app/options/LoadReadingTextSizeListener.kt +++ b/app/src/main/java/org/oppia/android/app/options/LoadReadingTextSizeListener.kt @@ -1,6 +1,12 @@ package org.oppia.android.app.options +import org.oppia.android.app.model.ReadingTextSize + /** Listener for when an activity should load a [ReadingTextSizeFragment]. */ interface LoadReadingTextSizeListener { - fun loadReadingTextSizeFragment(textSize: String) + /** + * Loads a tablet UI panel for changing the current UI reading text size (with the current text + * size being passed in via [textSize]). + */ + fun loadReadingTextSizeFragment(textSize: ReadingTextSize) } diff --git a/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt b/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt index acb9712e054..9b1b96c564a 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt @@ -12,7 +12,7 @@ import org.oppia.android.app.model.AppLanguage import org.oppia.android.app.model.AudioLanguage import org.oppia.android.app.model.Profile import org.oppia.android.app.model.ProfileId -import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.app.viewmodel.ObservableArrayList import org.oppia.android.domain.oppialogger.OppiaLogger import org.oppia.android.domain.profile.ProfileManagementController @@ -28,7 +28,8 @@ class OptionControlsViewModel @Inject constructor( activity: AppCompatActivity, private val profileManagementController: ProfileManagementController, private val oppiaLogger: OppiaLogger, - @EnableLanguageSelectionUi private val enableLanguageSelectionUi: PlatformParameterValue + @EnableLanguageSelectionUi private val enableLanguageSelectionUi: PlatformParameterValue, + private val resourceHandler: AppLanguageResourceHandler ) : OptionsItemViewModel() { private val itemViewModelList: ObservableList = ObservableArrayList() private lateinit var profileId: ProfileId @@ -84,11 +85,12 @@ class OptionControlsViewModel @Inject constructor( } private fun processProfileList(profile: Profile): List { - itemViewModelList.clear() val optionsReadingTextSizeViewModel = - OptionsReadingTextSizeViewModel(routeToReadingTextSizeListener, loadReadingTextSizeListener) + OptionsReadingTextSizeViewModel( + routeToReadingTextSizeListener, loadReadingTextSizeListener, resourceHandler + ) val optionsAppLanguageViewModel = OptionsAppLanguageViewModel(routeToAppLanguageListListener, loadAppLanguageListListener) val optionAudioViewViewModel = @@ -97,7 +99,7 @@ class OptionControlsViewModel @Inject constructor( loadAudioLanguageListListener ) - optionsReadingTextSizeViewModel.readingTextSize.set(getReadingTextSize(profile.readingTextSize)) + optionsReadingTextSizeViewModel.readingTextSize.set(profile.readingTextSize) optionsAppLanguageViewModel.appLanguage.set(getAppLanguage(profile.appLanguage)) optionAudioViewViewModel.audioLanguage.set(getAudioLanguage(profile.audioLanguage)) @@ -126,15 +128,6 @@ class OptionControlsViewModel @Inject constructor( this.isFirstOpen = isFirstOpen } - fun getReadingTextSize(readingTextSize: ReadingTextSize): String { - return when (readingTextSize) { - ReadingTextSize.SMALL_TEXT_SIZE -> "Small" - ReadingTextSize.MEDIUM_TEXT_SIZE -> "Medium" - ReadingTextSize.LARGE_TEXT_SIZE -> "Large" - else -> "Extra Large" - } - } - fun getAppLanguage(appLanguage: AppLanguage): String { return when (appLanguage) { AppLanguage.ENGLISH_APP_LANGUAGE -> "English" diff --git a/app/src/main/java/org/oppia/android/app/options/OptionsActivity.kt b/app/src/main/java/org/oppia/android/app/options/OptionsActivity.kt index 10c6d366fd4..32898ba060d 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionsActivity.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionsActivity.kt @@ -8,7 +8,10 @@ import org.oppia.android.R import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.drawer.NAVIGATION_PROFILE_ID_ARGUMENT_KEY +import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.app.model.ReadingTextSizeActivityResultBundle import org.oppia.android.app.translation.AppLanguageResourceHandler +import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.extensions.getStringFromBundle import javax.inject.Inject @@ -82,17 +85,23 @@ class OptionsActivity : override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) + checkNotNull(data) { + "Expected data to be passed as an activity result for request: $requestCode." + } when (requestCode) { REQUEST_CODE_TEXT_SIZE -> { - val textSize = data!!.getStringExtra(MESSAGE_READING_TEXT_SIZE_ARGUMENT_KEY) as String - optionActivityPresenter.updateReadingTextSize(textSize) + val textSizeResults = data.getProtoExtra( + MESSAGE_READING_TEXT_SIZE_RESULTS_KEY, + ReadingTextSizeActivityResultBundle.getDefaultInstance() + ) + optionActivityPresenter.updateReadingTextSize(textSizeResults.selectedReadingTextSize) } REQUEST_CODE_APP_LANGUAGE -> { - val appLanguage = data!!.getStringExtra(MESSAGE_APP_LANGUAGE_ARGUMENT_KEY) as String + val appLanguage = data.getStringExtra(MESSAGE_APP_LANGUAGE_ARGUMENT_KEY) as String optionActivityPresenter.updateAppLanguage(appLanguage) } else -> { - val audioLanguage = data!!.getStringExtra(MESSAGE_AUDIO_LANGUAGE_ARGUMENT_KEY) as String + val audioLanguage = data.getStringExtra(MESSAGE_AUDIO_LANGUAGE_ARGUMENT_KEY) as String optionActivityPresenter.updateAudioLanguage(audioLanguage) } } @@ -120,18 +129,14 @@ class OptionsActivity : ) } - override fun routeReadingTextSize(readingTextSize: String?) { + override fun routeReadingTextSize(readingTextSize: ReadingTextSize) { startActivityForResult( - ReadingTextSizeActivity.createReadingTextSizeActivityIntent( - this, - READING_TEXT_SIZE, - readingTextSize - ), + ReadingTextSizeActivity.createReadingTextSizeActivityIntent(this, readingTextSize), REQUEST_CODE_TEXT_SIZE ) } - override fun loadReadingTextSizeFragment(textSize: String) { + override fun loadReadingTextSizeFragment(textSize: ReadingTextSize) { selectedFragment = READING_TEXT_SIZE_FRAGMENT optionActivityPresenter.setExtraOptionTitle( resourceHandler.getStringInLocale(R.string.reading_text_size) diff --git a/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt index 2bce5d2fb5c..6654e2e935e 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt @@ -9,6 +9,7 @@ import androidx.drawerlayout.widget.DrawerLayout import org.oppia.android.R import org.oppia.android.app.activity.ActivityScope import org.oppia.android.app.drawer.NavigationDrawerFragment +import org.oppia.android.app.model.ReadingTextSize import javax.inject.Inject /** The presenter for [OptionsActivity]. */ @@ -79,7 +80,7 @@ class OptionsActivityPresenter @Inject constructor( ) as OptionsFragment? } - fun updateReadingTextSize(textSize: String) { + fun updateReadingTextSize(textSize: ReadingTextSize) { getOptionFragment()?.updateReadingTextSize(textSize) } @@ -91,7 +92,7 @@ class OptionsActivityPresenter @Inject constructor( getOptionFragment()?.updateAudioLanguage(audioLanguage) } - fun loadReadingTextSizeFragment(textSize: String) { + fun loadReadingTextSizeFragment(textSize: ReadingTextSize) { val readingTextSizeFragment = ReadingTextSizeFragment.newInstance(textSize) activity.supportFragmentManager .beginTransaction() diff --git a/app/src/main/java/org/oppia/android/app/options/OptionsFragment.kt b/app/src/main/java/org/oppia/android/app/options/OptionsFragment.kt index 0e11b55bdc5..a573a79027c 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionsFragment.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionsFragment.kt @@ -7,10 +7,11 @@ import android.view.View import android.view.ViewGroup import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment +import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.util.extensions.getStringFromBundle import javax.inject.Inject -const val MESSAGE_READING_TEXT_SIZE_ARGUMENT_KEY = "OptionsFragment.message_reading_text_size" +const val MESSAGE_READING_TEXT_SIZE_RESULTS_KEY = "OptionsFragment.message_reading_text_size" const val MESSAGE_APP_LANGUAGE_ARGUMENT_KEY = "OptionsFragment.message_app_language" const val MESSAGE_AUDIO_LANGUAGE_ARGUMENT_KEY = "OptionsFragment.message_audio_language" const val REQUEST_CODE_TEXT_SIZE = 1 @@ -66,7 +67,7 @@ class OptionsFragment : InjectableFragment() { ) } - fun updateReadingTextSize(textSize: String) { + fun updateReadingTextSize(textSize: ReadingTextSize) { optionsFragmentPresenter.runAfterUIInitialization { optionsFragmentPresenter.updateReadingTextSize(textSize) } diff --git a/app/src/main/java/org/oppia/android/app/options/OptionsFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/options/OptionsFragmentPresenter.kt index 369f0efa623..cf019653dd2 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionsFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionsFragmentPresenter.kt @@ -26,7 +26,6 @@ import org.oppia.android.util.data.DataProviders.Companion.toLiveData import java.security.InvalidParameterException import javax.inject.Inject -const val READING_TEXT_SIZE = "READING_TEXT_SIZE" const val APP_LANGUAGE = "APP_LANGUAGE" const val AUDIO_LANGUAGE = "AUDIO_LANGUAGE" private const val READING_TEXT_SIZE_TAG = "ReadingTextSize" @@ -52,7 +51,6 @@ class OptionsFragmentPresenter @Inject constructor( private lateinit var recyclerViewAdapter: RecyclerView.Adapter<*> private var internalProfileId: Int = -1 private lateinit var profileId: ProfileId - private var readingTextSize = ReadingTextSize.SMALL_TEXT_SIZE private var appLanguage = AppLanguage.ENGLISH_APP_LANGUAGE private var audioLanguage = AudioLanguage.NO_AUDIO private val viewModel = getOptionControlsItemViewModel() @@ -185,86 +183,20 @@ class OptionsFragmentPresenter @Inject constructor( VIEW_TYPE_AUDIO_LANGUAGE } - fun updateReadingTextSize(textSize: String) { - when (textSize) { - getOptionControlsItemViewModel().getReadingTextSize(ReadingTextSize.SMALL_TEXT_SIZE) -> { - profileManagementController.updateReadingTextSize( - profileId, - ReadingTextSize.SMALL_TEXT_SIZE - ).toLiveData().observe( - fragment, - Observer { - when (it) { - is AsyncResult.Success -> readingTextSize = ReadingTextSize.SMALL_TEXT_SIZE - is AsyncResult.Failure -> { - oppiaLogger.e( - READING_TEXT_SIZE_TAG, "$READING_TEXT_SIZE_ERROR: small text size", it.error - ) - } - is AsyncResult.Pending -> {} // Wait for a result. - } - } - ) - } - getOptionControlsItemViewModel().getReadingTextSize(ReadingTextSize.MEDIUM_TEXT_SIZE) -> { - profileManagementController.updateReadingTextSize( - profileId, - ReadingTextSize.MEDIUM_TEXT_SIZE - ).toLiveData().observe( - fragment, - Observer { - when (it) { - is AsyncResult.Success -> readingTextSize = ReadingTextSize.MEDIUM_TEXT_SIZE - is AsyncResult.Failure -> { - oppiaLogger.e( - READING_TEXT_SIZE_TAG, "$READING_TEXT_SIZE_ERROR: medium text size", it.error - ) - } - is AsyncResult.Pending -> {} // Wait for a result. - } - } - ) - } - getOptionControlsItemViewModel().getReadingTextSize(ReadingTextSize.LARGE_TEXT_SIZE) -> { - profileManagementController.updateReadingTextSize( - profileId, - ReadingTextSize.LARGE_TEXT_SIZE - ).toLiveData().observe( - fragment, - Observer { - when (it) { - is AsyncResult.Success -> readingTextSize = ReadingTextSize.LARGE_TEXT_SIZE - is AsyncResult.Failure -> { - oppiaLogger.e( - READING_TEXT_SIZE_TAG, "$READING_TEXT_SIZE_ERROR: large text size", it.error - ) - } - is AsyncResult.Pending -> {} // Wait for a result. - } - } - ) - } - getOptionControlsItemViewModel() - .getReadingTextSize(ReadingTextSize.EXTRA_LARGE_TEXT_SIZE) -> { - profileManagementController.updateReadingTextSize( - profileId, - ReadingTextSize.EXTRA_LARGE_TEXT_SIZE - ).toLiveData().observe( - fragment, - Observer { - when (it) { - is AsyncResult.Success -> readingTextSize = ReadingTextSize.EXTRA_LARGE_TEXT_SIZE - is AsyncResult.Failure -> { - oppiaLogger.e( - READING_TEXT_SIZE_TAG, "$READING_TEXT_SIZE_ERROR: extra large text size", it.error - ) - } - is AsyncResult.Pending -> {} // Wait for a result. - } + fun updateReadingTextSize(textSize: ReadingTextSize) { + profileManagementController.updateReadingTextSize(profileId, textSize).toLiveData().observe( + fragment, + { + when (it) { + is AsyncResult.Failure -> { + oppiaLogger.e( + READING_TEXT_SIZE_TAG, "$READING_TEXT_SIZE_ERROR: updating to $textSize", it.error + ) } - ) + else -> {} // Nothing needs to be done unless the update failed. + } } - } + ) recyclerViewAdapter.notifyItemChanged(0) } diff --git a/app/src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt b/app/src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt index 39014f849de..626069bec7f 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt @@ -1,17 +1,29 @@ package org.oppia.android.app.options import androidx.databinding.ObservableField +import org.oppia.android.R +import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.app.translation.AppLanguageResourceHandler /** ReadingTextSize settings view model for the recycler view in [OptionsFragment]. */ class OptionsReadingTextSizeViewModel( private val routeToReadingTextSizeListener: RouteToReadingTextSizeListener, - private val loadReadingTextSizeListener: LoadReadingTextSizeListener + private val loadReadingTextSizeListener: LoadReadingTextSizeListener, + private val resourceHandler: AppLanguageResourceHandler ) : OptionsItemViewModel() { - val readingTextSize = ObservableField("") - - fun setReadingTextSize(readingTextSizeValue: String) { - readingTextSize.set(readingTextSizeValue) - } + val readingTextSize = ObservableField(ReadingTextSize.TEXT_SIZE_UNSPECIFIED) + val textSizeName: String + get() { + return when (readingTextSize.get()!!) { + ReadingTextSize.SMALL_TEXT_SIZE -> + resourceHandler.getStringInLocale(R.string.reading_text_size_small) + ReadingTextSize.MEDIUM_TEXT_SIZE -> + resourceHandler.getStringInLocale(R.string.reading_text_size_medium) + ReadingTextSize.LARGE_TEXT_SIZE -> + resourceHandler.getStringInLocale(R.string.reading_text_size_large) + else -> resourceHandler.getStringInLocale(R.string.reading_text_size_extra_large) + } + } fun loadReadingTextSizeFragment() { loadReadingTextSizeListener.loadReadingTextSizeFragment(readingTextSize.get()!!) @@ -21,7 +33,7 @@ class OptionsReadingTextSizeViewModel( if (isMultipane.get()!!) { loadReadingTextSizeListener.loadReadingTextSizeFragment(readingTextSize.get()!!) } else { - routeToReadingTextSizeListener.routeReadingTextSize(readingTextSize.get()) + routeToReadingTextSizeListener.routeReadingTextSize(readingTextSize.get()!!) } } } diff --git a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivity.kt b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivity.kt index ada56a940b2..9b6658567e8 100644 --- a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivity.kt +++ b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivity.kt @@ -5,8 +5,19 @@ import android.content.Intent import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity +import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.app.model.ReadingTextSizeActivityParams +import org.oppia.android.app.model.ReadingTextSizeActivityResultBundle +import org.oppia.android.app.model.ReadingTextSizeActivityStateBundle +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.getProtoExtra +import org.oppia.android.util.extensions.putProto +import org.oppia.android.util.extensions.putProtoExtra import javax.inject.Inject +private const val ACTIVITY_PARAMS_KEY = "ReadingTextSizeActivity.params" +private const val ACTIVITY_SAVED_STATE_KEY = "ReadingTextSizeActivity.saved_state" + /** The activity to change the text size of the reading content in the app. */ class ReadingTextSizeActivity : InjectableAppCompatActivity() { @@ -16,54 +27,53 @@ class ReadingTextSizeActivity : InjectableAppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) - val prefSummaryValue = ( - if (savedInstanceState != null) { - savedInstanceState.get(KEY_READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE) - } else { - intent.getStringExtra(KEY_READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE) - } - ) as String - readingTextSizeActivityPresenter.handleOnCreate(prefSummaryValue) + + val readingTextSize = + savedInstanceState?.retrieveStateBundle()?.selectedReadingTextSize + ?: retrieveActivityParams().readingTextSize + readingTextSizeActivityPresenter.handleOnCreate(readingTextSize) } companion object { - internal const val KEY_READING_TEXT_SIZE_PREFERENCE_TITLE = "READING_TEXT_SIZE_PREFERENCE" - const val KEY_READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE = - "READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE" /** Returns a new [Intent] to route to [ReadingTextSizeActivity]. */ fun createReadingTextSizeActivityIntent( context: Context, - prefKey: String, - summaryValue: String? + initialReadingTextSize: ReadingTextSize ): Intent { - val intent = Intent(context, ReadingTextSizeActivity::class.java) - intent.putExtra(KEY_READING_TEXT_SIZE_PREFERENCE_TITLE, prefKey) - intent.putExtra(KEY_READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE, summaryValue) - return intent - } - - fun getKeyReadingTextSizePreferenceTitle(): String { - return KEY_READING_TEXT_SIZE_PREFERENCE_TITLE - } - - fun getKeyReadingTextSizePreferenceSummaryValue(): String { - return KEY_READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE + val params = ReadingTextSizeActivityParams.newBuilder().apply { + readingTextSize = initialReadingTextSize + }.build() + return Intent(context, ReadingTextSizeActivity::class.java).apply { + putProtoExtra(ACTIVITY_PARAMS_KEY, params) + } } } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - outState.putString( - KEY_READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE, - readingTextSizeActivityPresenter.getSelectedReadingTextSize() - ) + val stateBundle = ReadingTextSizeActivityStateBundle.newBuilder().apply { + selectedReadingTextSize = readingTextSizeActivityPresenter.getSelectedReadingTextSize() + }.build() + outState.putProto(ACTIVITY_SAVED_STATE_KEY, stateBundle) } override fun onBackPressed() { - val message = readingTextSizeActivityPresenter.getSelectedReadingTextSize() - val intent = Intent() - intent.putExtra(MESSAGE_READING_TEXT_SIZE_ARGUMENT_KEY, message) + val resultBundle = ReadingTextSizeActivityResultBundle.newBuilder().apply { + selectedReadingTextSize = readingTextSizeActivityPresenter.getSelectedReadingTextSize() + }.build() + val intent = Intent().apply { + putProtoExtra(MESSAGE_READING_TEXT_SIZE_RESULTS_KEY, resultBundle) + } setResult(REQUEST_CODE_TEXT_SIZE, intent) finish() } + + private fun retrieveActivityParams() = + intent.getProtoExtra(ACTIVITY_PARAMS_KEY, ReadingTextSizeActivityParams.getDefaultInstance()) + + private fun Bundle.retrieveStateBundle(): ReadingTextSizeActivityStateBundle { + return getProto( + ACTIVITY_SAVED_STATE_KEY, ReadingTextSizeActivityStateBundle.getDefaultInstance() + ) + } } diff --git a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivityPresenter.kt index 8039a711f2e..3ab661a3ced 100644 --- a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivityPresenter.kt @@ -4,6 +4,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import org.oppia.android.R import org.oppia.android.app.activity.ActivityScope +import org.oppia.android.app.model.ReadingTextSize import javax.inject.Inject /** The presenter for [ReadingTextSizeActivity]. */ @@ -11,14 +12,14 @@ import javax.inject.Inject class ReadingTextSizeActivityPresenter @Inject constructor( private val activity: AppCompatActivity ) { - private lateinit var fontSize: String + private lateinit var fontSize: ReadingTextSize - fun handleOnCreate(prefSummaryValue: String) { + fun handleOnCreate(preferredTextSize: ReadingTextSize) { activity.setContentView(R.layout.reading_text_size_activity) setToolbar() - fontSize = prefSummaryValue + fontSize = preferredTextSize if (getReadingTextSizeFragment() == null) { - val readingTextSizeFragment = ReadingTextSizeFragment.newInstance(prefSummaryValue) + val readingTextSizeFragment = ReadingTextSizeFragment.newInstance(preferredTextSize) activity.supportFragmentManager.beginTransaction() .add(R.id.reading_text_size_container, readingTextSizeFragment).commitNow() } @@ -31,11 +32,11 @@ class ReadingTextSizeActivityPresenter @Inject constructor( } } - fun setSelectedReadingTextSize(fontSize: String) { + fun setSelectedReadingTextSize(fontSize: ReadingTextSize) { this.fontSize = fontSize } - fun getSelectedReadingTextSize(): String { + fun getSelectedReadingTextSize(): ReadingTextSize { return fontSize } diff --git a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragment.kt b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragment.kt index 3547a7362e8..1cdae8c8578 100644 --- a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragment.kt +++ b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragment.kt @@ -7,12 +7,15 @@ import android.view.View import android.view.ViewGroup import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment +import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.app.model.ReadingTextSizeFragmentArguments +import org.oppia.android.app.model.ReadingTextSizeFragmentStateBundle +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.putProto import javax.inject.Inject -private const val READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE_ARGUMENT_KEY = - "ReadingTextSizeFragment.reading_text_size_preference_summary_value" -private const val SELECTED_READING_TEXT_SIZE_SAVED_KEY = - "ReadingTextSizeFragment.selected_text_size" +private const val FRAGMENT_ARGUMENTS_KEY = "ReadingTextSizeFragment.arguments" +private const val FRAGMENT_SAVED_STATE_KEY = "ReadingTextSizeFragment.saved_state" /** The fragment to change the text size of the reading content in the app. */ class ReadingTextSizeFragment : InjectableFragment(), TextSizeRadioButtonListener { @@ -20,12 +23,15 @@ class ReadingTextSizeFragment : InjectableFragment(), TextSizeRadioButtonListene lateinit var readingTextSizeFragmentPresenter: ReadingTextSizeFragmentPresenter companion object { - fun newInstance(readingTextSize: String): ReadingTextSizeFragment { - val args = Bundle() - args.putString(READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE_ARGUMENT_KEY, readingTextSize) - val fragment = ReadingTextSizeFragment() - fragment.arguments = args - return fragment + fun newInstance(readingTextSize: ReadingTextSize): ReadingTextSizeFragment { + val protoArguments = ReadingTextSizeFragmentArguments.newBuilder().apply { + this.readingTextSize = readingTextSize + }.build() + return ReadingTextSizeFragment().apply { + arguments = Bundle().apply { + putProto(FRAGMENT_ARGUMENTS_KEY, protoArguments) + } + } } } @@ -39,25 +45,33 @@ class ReadingTextSizeFragment : InjectableFragment(), TextSizeRadioButtonListene container: ViewGroup?, savedInstanceState: Bundle? ): View? { - val args = - checkNotNull(arguments) { "Expected arguments to be passed to ReadingTextSizeFragment" } - val readingTextSize = if (savedInstanceState == null) { - args.get(READING_TEXT_SIZE_PREFERENCE_SUMMARY_VALUE_ARGUMENT_KEY) as String - } else { - savedInstanceState.get(SELECTED_READING_TEXT_SIZE_SAVED_KEY) as String - } + val readingTextSize = + savedInstanceState?.retrieveStateBundle()?.selectedReadingTextSize + ?: retrieveFragmentArguments().readingTextSize return readingTextSizeFragmentPresenter.handleOnCreateView(inflater, container, readingTextSize) } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - outState.putString( - SELECTED_READING_TEXT_SIZE_SAVED_KEY, - readingTextSizeFragmentPresenter.getTextSizeSelected() - ) + val stateBundle = ReadingTextSizeFragmentStateBundle.newBuilder().apply { + selectedReadingTextSize = readingTextSizeFragmentPresenter.getTextSizeSelected() + }.build() + outState.putProto(FRAGMENT_SAVED_STATE_KEY, stateBundle) } - override fun onTextSizeSelected(selectedTextSize: String) { + override fun onTextSizeSelected(selectedTextSize: ReadingTextSize) { readingTextSizeFragmentPresenter.onTextSizeSelected(selectedTextSize) } + + private fun retrieveFragmentArguments(): ReadingTextSizeFragmentArguments { + return checkNotNull(arguments) { + "Expected arguments to be passed to ReadingTextSizeFragment" + }.getProto(FRAGMENT_ARGUMENTS_KEY, ReadingTextSizeFragmentArguments.getDefaultInstance()) + } + + private fun Bundle.retrieveStateBundle(): ReadingTextSizeFragmentStateBundle { + return getProto( + FRAGMENT_SAVED_STATE_KEY, ReadingTextSizeFragmentStateBundle.getDefaultInstance() + ) + } } diff --git a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragmentPresenter.kt index 79fb3be6870..1331a2577c3 100644 --- a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragmentPresenter.kt @@ -4,9 +4,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import org.oppia.android.R +import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.app.recyclerview.BindableAdapter -import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.databinding.ReadingTextSizeFragmentBinding import org.oppia.android.databinding.TextSizeItemsBinding import javax.inject.Inject @@ -14,17 +13,12 @@ import javax.inject.Inject /** The presenter for [ReadingTextSizeFragment]. */ class ReadingTextSizeFragmentPresenter @Inject constructor( private val fragment: Fragment, - private val readingTextSizeSelectionViewModel: ReadingTextSizeSelectionViewModel, - resourceHandler: AppLanguageResourceHandler + private val readingTextSizeSelectionViewModel: ReadingTextSizeSelectionViewModel ) { - private var fontSize: String = resourceHandler.getStringInLocale( - R.string.reading_text_size_medium - ) - fun handleOnCreateView( inflater: LayoutInflater, container: ViewGroup?, - readingTextSize: String + readingTextSize: ReadingTextSize ): View? { val binding = ReadingTextSizeFragmentBinding.inflate( inflater, @@ -32,20 +26,17 @@ class ReadingTextSizeFragmentPresenter @Inject constructor( /* attachToRoot= */ false ) - fontSize = readingTextSize - updateTextSize(fontSize) + updateTextSize(readingTextSize) binding.viewModel = readingTextSizeSelectionViewModel - readingTextSizeSelectionViewModel.selectedTextSize.value = fontSize + readingTextSizeSelectionViewModel.selectedTextSize = readingTextSize binding.textSizeRecyclerView.apply { adapter = createRecyclerViewAdapter() } return binding.root } - fun getTextSizeSelected(): String? { - return readingTextSizeSelectionViewModel.selectedTextSize.value - } + fun getTextSizeSelected(): ReadingTextSize? = readingTextSizeSelectionViewModel.selectedTextSize private fun createRecyclerViewAdapter(): BindableAdapter { return BindableAdapter.SingleTypeBuilder @@ -57,7 +48,7 @@ class ReadingTextSizeFragmentPresenter @Inject constructor( ).build() } - private fun updateTextSize(textSize: String) { + private fun updateTextSize(textSize: ReadingTextSize) { // The first branch of (when) will be used in the case of multipane when (val parentActivity = fragment.activity) { is OptionsActivity -> parentActivity.optionActivityPresenter.updateReadingTextSize(textSize) @@ -66,8 +57,8 @@ class ReadingTextSizeFragmentPresenter @Inject constructor( } } - fun onTextSizeSelected(selectedTextSize: String) { - readingTextSizeSelectionViewModel.selectedTextSize.value = selectedTextSize + fun onTextSizeSelected(selectedTextSize: ReadingTextSize) { + readingTextSizeSelectionViewModel.selectedTextSize = selectedTextSize updateTextSize(selectedTextSize) } } diff --git a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeSelectionViewModel.kt b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeSelectionViewModel.kt index fb8ea3fac19..a18fceedc3c 100644 --- a/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeSelectionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/ReadingTextSizeSelectionViewModel.kt @@ -12,45 +12,46 @@ import javax.inject.Inject @FragmentScope class ReadingTextSizeSelectionViewModel @Inject constructor( fragment: Fragment, - private val resourceHandler: AppLanguageResourceHandler + resourceHandler: AppLanguageResourceHandler ) : ObservableViewModel() { private val resourceBundle = fragment.requireContext().resources - val selectedTextSize = MutableLiveData() + private val changeableSelectedTextSize = MutableLiveData() private val textSizeRadioButtonListener = fragment as TextSizeRadioButtonListener + var selectedTextSize: ReadingTextSize? + get() = changeableSelectedTextSize.value + set(value) { changeableSelectedTextSize.value = value } - private val textSizeList = listOf( + private val textSizeList = listOf( TextSizeItemViewModel( resourceBundle, ReadingTextSize.SMALL_TEXT_SIZE, - selectedTextSize, + changeableSelectedTextSize, textSizeRadioButtonListener, resourceHandler ), TextSizeItemViewModel( resourceBundle, ReadingTextSize.MEDIUM_TEXT_SIZE, - selectedTextSize, + changeableSelectedTextSize, textSizeRadioButtonListener, resourceHandler ), TextSizeItemViewModel( resourceBundle, ReadingTextSize.LARGE_TEXT_SIZE, - selectedTextSize, + changeableSelectedTextSize, textSizeRadioButtonListener, resourceHandler ), TextSizeItemViewModel( resourceBundle, ReadingTextSize.EXTRA_LARGE_TEXT_SIZE, - selectedTextSize, + changeableSelectedTextSize, textSizeRadioButtonListener, resourceHandler ), ) - val recyclerViewTextSizeList: List by lazy { - textSizeList - } + val recyclerViewTextSizeList: List by lazy { textSizeList } } diff --git a/app/src/main/java/org/oppia/android/app/options/RouteToReadingTextSizeListener.kt b/app/src/main/java/org/oppia/android/app/options/RouteToReadingTextSizeListener.kt index c1ad1c9db86..58d3c8a7902 100644 --- a/app/src/main/java/org/oppia/android/app/options/RouteToReadingTextSizeListener.kt +++ b/app/src/main/java/org/oppia/android/app/options/RouteToReadingTextSizeListener.kt @@ -1,6 +1,12 @@ package org.oppia.android.app.options +import org.oppia.android.app.model.ReadingTextSize + /** Listener for when an activity should route to a [ReadingTextSizeActivity]. */ interface RouteToReadingTextSizeListener { - fun routeReadingTextSize(readingTextSize: String?) + /** + * Loads a standalone UI for changing the current UI reading text size (with the current text size + * being passed in via [readingTextSize]). + */ + fun routeReadingTextSize(readingTextSize: ReadingTextSize) } diff --git a/app/src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt index a8e240609c8..1b3fda584af 100644 --- a/app/src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt @@ -15,9 +15,9 @@ private const val EXTRA_LARGE_TEXT_SIZE_SCALE = 1.4f /** Text Size item view model for the recycler view in [ReadingTextSizeFragment]. */ class TextSizeItemViewModel( - val resources: Resources, + private val resources: Resources, val readingTextSize: ReadingTextSize, - private val selectedTextSize: LiveData, + private val selectedTextSize: LiveData, val textSizeRadioButtonListener: TextSizeRadioButtonListener, private val resourceHandler: AppLanguageResourceHandler ) : ObservableViewModel() { @@ -44,6 +44,6 @@ class TextSizeItemViewModel( } } val isTextSizeSelected: LiveData by lazy { - Transformations.map(selectedTextSize) { it == textSizeName } + Transformations.map(selectedTextSize) { it == readingTextSize } } } diff --git a/app/src/main/java/org/oppia/android/app/options/TextSizeRadioButtonListener.kt b/app/src/main/java/org/oppia/android/app/options/TextSizeRadioButtonListener.kt index 821bcf3d78d..7f4daeaff10 100644 --- a/app/src/main/java/org/oppia/android/app/options/TextSizeRadioButtonListener.kt +++ b/app/src/main/java/org/oppia/android/app/options/TextSizeRadioButtonListener.kt @@ -1,6 +1,9 @@ package org.oppia.android.app.options +import org.oppia.android.app.model.ReadingTextSize + /** Listener for when the reading text size is selected from the [ReadingTextSizeFragment]. */ interface TextSizeRadioButtonListener { - fun onTextSizeSelected(selectedTextSize: String) + /** Called when the user selects a new [ReadingTextSize]. */ + fun onTextSizeSelected(selectedTextSize: ReadingTextSize) } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt index 29c46c4c7bf..0bb946fad35 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt @@ -12,7 +12,9 @@ import org.oppia.android.app.hintsandsolution.HintsAndSolutionDialogFragment import org.oppia.android.app.hintsandsolution.HintsAndSolutionListener import org.oppia.android.app.hintsandsolution.RevealHintListener import org.oppia.android.app.hintsandsolution.RevealSolutionInterface +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.HelpIndex +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.app.model.State import org.oppia.android.app.model.WrittenTranslationContext @@ -21,6 +23,8 @@ import org.oppia.android.app.player.state.listener.RouteToHintsAndSolutionListen import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener import org.oppia.android.app.player.stopplaying.StopStatePlayingSessionWithSavedProgressListener import org.oppia.android.app.topic.conceptcard.ConceptCardListener +import org.oppia.android.util.extensions.getProtoExtra +import org.oppia.android.util.extensions.putProtoExtra import javax.inject.Inject const val TAG_HINTS_AND_SOLUTION_DIALOG = "HINTS_AND_SOLUTION_DIALOG" @@ -39,80 +43,63 @@ class ExplorationActivity : HintsAndSolutionExplorationManagerListener, ConceptCardListener { - @Inject - lateinit var explorationActivityPresenter: ExplorationActivityPresenter - private var internalProfileId: Int = -1 - private lateinit var topicId: String - private lateinit var storyId: String - private lateinit var explorationId: String + @Inject lateinit var explorationActivityPresenter: ExplorationActivityPresenter + private lateinit var state: State private lateinit var writtenTranslationContext: WrittenTranslationContext - private var backflowScreen: Int? = null - private var isCheckpointingEnabled: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) - internalProfileId = intent.getIntExtra(EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, -1) - topicId = checkNotNull(intent.getStringExtra(EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY)) { - "Expected $EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY to be in intent extras." - } - storyId = checkNotNull(intent.getStringExtra(EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY)) { - "Expected $EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY to be in intent extras." - } - explorationId = checkNotNull( - intent.getStringExtra( - EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY - ) - ) { - "Expected EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY to be in intent extras." - } - backflowScreen = intent.getIntExtra(EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, -1) - isCheckpointingEnabled = - intent.getBooleanExtra(EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, false) + + val params = intent.getProtoExtra(PARAMS_KEY, ExplorationActivityParams.getDefaultInstance()) explorationActivityPresenter.handleOnCreate( this, - internalProfileId, - topicId, - storyId, - explorationId, - backflowScreen, - isCheckpointingEnabled + params.profileId, + params.topicId, + params.storyId, + params.explorationId, + params.parentScreen, + params.isCheckpointingEnabled ) } // TODO(#1655): Re-restrict access to fields in tests post-Gradle. companion object { - /** Returns a new [Intent] to route to [ExplorationActivity] for a specified exploration. */ - - const val EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY = - "ExplorationActivity.profile_id" - const val EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY = "ExplorationActivity.topic_id" - const val EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY = "ExplorationActivity.story_id" - const val EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY = - "ExplorationActivity.exploration_id" - const val EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY = - "ExplorationActivity.backflow_screen" - const val EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY = - "ExplorationActivity.is_checkpointing_enabled_key" + private const val PARAMS_KEY = "ExplorationActivity.params" + /** + * A convenience function for creating a new [ExplorationActivity] intent by prefilling common + * params needed by the activity. + */ fun createExplorationActivityIntent( context: Context, - profileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ): Intent { - val intent = Intent(context, ExplorationActivity::class.java) - intent.putExtra(EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, profileId) - intent.putExtra(EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, topicId) - intent.putExtra(EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, storyId) - intent.putExtra(EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, explorationId) - intent.putExtra(EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, backflowScreen) - intent.putExtra(EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, isCheckpointingEnabled) - return intent + val params = ExplorationActivityParams.newBuilder().apply { + this.profileId = profileId + this.topicId = topicId + this.storyId = storyId + this.explorationId = explorationId + this.parentScreen = parentScreen + this.isCheckpointingEnabled = isCheckpointingEnabled + }.build() + return createExplorationActivityIntent(context, params) + } + + /** Returns a new [Intent] open an [ExplorationActivity] with the specified [params]. */ + fun createExplorationActivityIntent( + context: Context, + params: ExplorationActivityParams + ): Intent { + return Intent(context, ExplorationActivity::class.java).apply { + putProtoExtra(PARAMS_KEY, params) + } } } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt index de940a8518e..fd8126dc548 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt @@ -1,7 +1,6 @@ package org.oppia.android.app.player.exploration import android.content.Context -import android.os.Bundle import android.view.MenuItem import android.view.inputmethod.EditorInfo import android.widget.TextView @@ -16,6 +15,7 @@ import org.oppia.android.app.activity.ActivityScope import org.oppia.android.app.help.HelpActivity import org.oppia.android.app.model.CheckpointState import org.oppia.android.app.model.EphemeralExploration +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.app.options.OptionsActivity @@ -56,29 +56,24 @@ class ExplorationActivityPresenter @Inject constructor( private lateinit var storyId: String private lateinit var explorationId: String private lateinit var context: Context - private var backflowScreen: Int? = null + private lateinit var parentScreen: ExplorationActivityParams.ParentScreen private var isCheckpointingEnabled: Boolean = false private lateinit var oldestCheckpointExplorationId: String private lateinit var oldestCheckpointExplorationTitle: String - enum class ParentActivityForExploration(val value: Int) { - BACKFLOW_SCREEN_LESSONS(0), - BACKFLOW_SCREEN_STORY(1); - } - private val exploreViewModel by lazy { getExplorationViewModel() } fun handleOnCreate( context: Context, - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { val binding = DataBindingUtil.setContentView( @@ -106,12 +101,12 @@ class ExplorationActivityPresenter @Inject constructor( getExplorationFragment()?.handlePlayAudio() } - profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + this.profileId = profileId this.topicId = topicId this.storyId = storyId this.explorationId = explorationId this.context = context - this.backflowScreen = backflowScreen + this.parentScreen = parentScreen this.isCheckpointingEnabled = isCheckpointingEnabled updateToolbarTitle(explorationId) @@ -119,16 +114,9 @@ class ExplorationActivityPresenter @Inject constructor( subscribeToOldestSavedExplorationDetails() if (getExplorationManagerFragment() == null) { - val explorationManagerFragment = ExplorationManagerFragment() - val args = Bundle() - args.putInt( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ) - explorationManagerFragment.arguments = args activity.supportFragmentManager.beginTransaction().add( R.id.exploration_fragment_placeholder, - explorationManagerFragment, + ExplorationManagerFragment.createNewInstance(profileId), TAG_EXPLORATION_MANAGER_FRAGMENT ).commitNow() } @@ -139,11 +127,7 @@ class ExplorationActivityPresenter @Inject constructor( activity.supportFragmentManager.beginTransaction().add( R.id.exploration_fragment_placeholder, ExplorationFragment.newInstance( - topicId = topicId, - internalProfileId = profileId.internalId, - storyId = storyId, - readingTextSize = readingTextSize.name, - explorationId = explorationId + profileId, topicId, storyId, explorationId, readingTextSize ), TAG_EXPLORATION_FRAGMENT ).commitNow() @@ -167,7 +151,7 @@ class ExplorationActivityPresenter @Inject constructor( profileId.internalId, /* isFromNavigationDrawer= */ false ) - fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE.name) + fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE) context.startActivity(intent) true } @@ -176,7 +160,7 @@ class ExplorationActivityPresenter @Inject constructor( activity, profileId.internalId, /* isFromNavigationDrawer= */false ) - fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE.name) + fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE) context.startActivity(intent) true } @@ -235,7 +219,7 @@ class ExplorationActivityPresenter @Inject constructor( } fun stopExploration(isCompletion: Boolean) { - fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE.name) + fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE) explorationDataController.stopPlayingExploration(isCompletion).toLiveData() .observe( activity, @@ -246,7 +230,7 @@ class ExplorationActivityPresenter @Inject constructor( oppiaLogger.e("ExplorationActivity", "Failed to stop exploration", it.error) is AsyncResult.Success -> { oppiaLogger.d("ExplorationActivity", "Successfully stopped exploration") - backPressActivitySelector(backflowScreen) + backPressActivitySelector() (activity as ExplorationActivity).finish() } } @@ -331,17 +315,17 @@ class ExplorationActivityPresenter @Inject constructor( } } - private fun backPressActivitySelector(backflowScreen: Int?) { - when (backflowScreen) { - ParentActivityForExploration.BACKFLOW_SCREEN_STORY.value -> activity.finish() - ParentActivityForExploration.BACKFLOW_SCREEN_LESSONS.value -> activity.finish() - else -> activity.startActivity( - TopicActivity.createTopicActivityIntent( - context, - profileId.internalId, - topicId + private fun backPressActivitySelector() { + when (parentScreen) { + ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB, + ExplorationActivityParams.ParentScreen.STORY_SCREEN -> activity.finish() + ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, + ExplorationActivityParams.ParentScreen.UNRECOGNIZED -> { + // Default to the topic activity. + activity.startActivity( + TopicActivity.createTopicActivityIntent(context, profileId.internalId, topicId) ) - ) + } } } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt index ddf88f38cd1..b72f2f0da61 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt @@ -7,8 +7,10 @@ import android.view.View import android.view.ViewGroup import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment -import org.oppia.android.app.utility.FontScaleConfigurationUtil -import org.oppia.android.util.extensions.getStringFromBundle +import org.oppia.android.app.model.ExplorationFragmentArguments +import org.oppia.android.app.model.ProfileId +import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.util.extensions.putProto import javax.inject.Inject /** Fragment that contains displays single exploration. */ @@ -16,81 +18,45 @@ class ExplorationFragment : InjectableFragment() { @Inject lateinit var explorationFragmentPresenter: ExplorationFragmentPresenter - @Inject - lateinit var fontScaleConfigurationUtil: FontScaleConfigurationUtil - companion object { - internal const val INTERNAL_PROFILE_ID_ARGUMENT_KEY = - "ExplorationFragment.internal_profile_id" - internal const val TOPIC_ID_ARGUMENT_KEY = "ExplorationFragment.topic_id" - internal const val STORY_ID_ARGUMENT_KEY = "ExplorationFragment.story_id" - internal const val STORY_DEFAULT_FONT_SIZE_ARGUMENT_KEY = - "ExplorationFragment.story_default_font_size" - internal const val EXPLORATION_ID_ARGUMENT_KEY = - "ExplorationFragment.exploration_id" - - /** Returns a new [ExplorationFragment] to pass the profileId, topicId, storyId, readingTextSize and explorationId. */ + /** Returns a new [ExplorationFragment] with the corresponding fragment parameters. */ fun newInstance( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, - readingTextSize: String, - explorationId: String + explorationId: String, + readingTextSize: ReadingTextSize ): ExplorationFragment { - val explorationFragment = ExplorationFragment() - val args = Bundle() - args.putInt( - INTERNAL_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ) - args.putString(TOPIC_ID_ARGUMENT_KEY, topicId) - args.putString(STORY_ID_ARGUMENT_KEY, storyId) - args.putString( - STORY_DEFAULT_FONT_SIZE_ARGUMENT_KEY, - readingTextSize - ) - args.putString( - EXPLORATION_ID_ARGUMENT_KEY, - explorationId - ) - explorationFragment.arguments = args - return explorationFragment + val args = ExplorationFragmentArguments.newBuilder().apply { + this.profileId = profileId + this.topicId = topicId + this.storyId = storyId + this.explorationId = explorationId + this.readingTextSize = readingTextSize + }.build() + return ExplorationFragment().apply { + arguments = Bundle().apply { + putProto(ExplorationFragmentPresenter.ARGUMENTS_KEY, args) + } + } } } override fun onAttach(context: Context) { super.onAttach(context) (fragmentComponent as FragmentComponentImpl).inject(this) - val readingTextSize = - arguments!!.getStringFromBundle(STORY_DEFAULT_FONT_SIZE_ARGUMENT_KEY) - checkNotNull(readingTextSize) { "ExplorationFragment must be created with a reading text size" } - fontScaleConfigurationUtil.adjustFontScale(context, readingTextSize) + explorationFragmentPresenter.handleAttach(context) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - val profileId = - arguments!!.getInt(INTERNAL_PROFILE_ID_ARGUMENT_KEY, -1) - val topicId = - arguments!!.getStringFromBundle(TOPIC_ID_ARGUMENT_KEY) - checkNotNull(topicId) { "StateFragment must be created with an topic ID" } - val storyId = - arguments!!.getStringFromBundle(STORY_ID_ARGUMENT_KEY) - checkNotNull(storyId) { "StateFragment must be created with an story ID" } - val explorationId = - arguments!!.getStringFromBundle(EXPLORATION_ID_ARGUMENT_KEY) - checkNotNull(explorationId) { "StateFragment must be created with an exploration ID" } - return explorationFragmentPresenter.handleCreateView( - inflater, - container, - profileId, - topicId, - storyId, - explorationId - ) + ): View = explorationFragmentPresenter.handleCreateView(inflater, container) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + explorationFragmentPresenter.handleViewCreated() } fun handlePlayAudio() = explorationFragmentPresenter.handlePlayAudio() diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt index 1085a5536d5..99f12480320 100755 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt @@ -1,34 +1,48 @@ package org.oppia.android.app.player.exploration +import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import org.oppia.android.R import org.oppia.android.app.fragment.FragmentScope +import org.oppia.android.app.model.ExplorationFragmentArguments +import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.app.player.state.StateFragment +import org.oppia.android.app.utility.FontScaleConfigurationUtil import org.oppia.android.databinding.ExplorationFragmentBinding import org.oppia.android.domain.oppialogger.OppiaLogger +import org.oppia.android.domain.profile.ProfileManagementController +import org.oppia.android.util.data.AsyncResult +import org.oppia.android.util.data.DataProviders.Companion.toLiveData +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.putProto import javax.inject.Inject /** The presenter for [ExplorationFragment]. */ @FragmentScope class ExplorationFragmentPresenter @Inject constructor( private val fragment: Fragment, - private val oppiaLogger: OppiaLogger + private val oppiaLogger: OppiaLogger, + private val fontScaleConfigurationUtil: FontScaleConfigurationUtil, + private val profileManagementController: ProfileManagementController ) { - fun handleCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - profileId: Int, - topicId: String, - storyId: String, - explorationId: String - ): View? { + /** Handles the [Fragment.onAttach] portion of [ExplorationFragment]'s lifecycle. */ + fun handleAttach(context: Context) { + fontScaleConfigurationUtil.adjustFontScale(context, retrieveArguments().readingTextSize) + } + + /** Handles the [Fragment.onCreateView] portion of [ExplorationFragment]'s lifecycle. */ + fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View { + val args = retrieveArguments() val binding = ExplorationFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false).root - val stateFragment = StateFragment.newInstance(profileId, topicId, storyId, explorationId) - logPracticeFragmentEvent(topicId, storyId, explorationId) + val stateFragment = + StateFragment.newInstance( + args.profileId.internalId, args.topicId, args.storyId, args.explorationId + ) + logPracticeFragmentEvent(args.topicId, args.storyId, args.explorationId) if (getStateFragment() == null) { fragment.childFragmentManager.beginTransaction().add( R.id.state_fragment_placeholder, @@ -38,6 +52,24 @@ class ExplorationFragmentPresenter @Inject constructor( return binding } + /** Handles the [Fragment.onViewCreated] portion of [ExplorationFragment]'s lifecycle. */ + fun handleViewCreated() { + val profileDataProvider = profileManagementController.getProfile(retrieveArguments().profileId) + profileDataProvider.toLiveData().observe( + fragment, + { result -> + val readingTextSize = retrieveArguments().readingTextSize + if (result is AsyncResult.Success && result.value.readingTextSize != readingTextSize) { + selectNewReadingTextSize(result.value.readingTextSize) + + // Since text views are based on sp for sizing, the activity needs to be recreated so that + // sp can be correctly recomputed. + fragment.requireActivity().recreate() + } + } + ) + } + fun handlePlayAudio() { getStateFragment()?.handlePlayAudio() } @@ -76,4 +108,28 @@ class ExplorationFragmentPresenter @Inject constructor( oppiaLogger.createOpenExplorationActivityContext(topicId, storyId, explorationId) ) } + + private fun selectNewReadingTextSize(readingTextSize: ReadingTextSize) { + updateArguments( + retrieveArguments().toBuilder().apply { + this.readingTextSize = readingTextSize + }.build() + ) + fontScaleConfigurationUtil.adjustFontScale(fragment.requireActivity(), readingTextSize) + } + + private fun retrieveArguments(): ExplorationFragmentArguments { + return fragment.requireArguments().getProto( + ARGUMENTS_KEY, ExplorationFragmentArguments.getDefaultInstance() + ) + } + + private fun updateArguments(updatedArgs: ExplorationFragmentArguments) { + fragment.requireArguments().putProto(ARGUMENTS_KEY, updatedArgs) + } + + companion object { + /** The fragment arguments key for all proto-held arguments for [ExplorationFragment]. */ + const val ARGUMENTS_KEY = "ExplorationFragment.arguments" + } } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragment.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragment.kt index 5697b9eed99..a7775707373 100644 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragment.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragment.kt @@ -4,6 +4,9 @@ import android.content.Context import android.os.Bundle import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment +import org.oppia.android.app.model.ProfileId +import org.oppia.android.util.extensions.getProto +import org.oppia.android.util.extensions.putProto import javax.inject.Inject /** @@ -21,11 +24,25 @@ class ExplorationManagerFragment : InjectableFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val internalProfileId = - arguments!!.getInt( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - /* defaultValue= */ -1 - ) - explorationManagerFragmentPresenter.handleCreate(internalProfileId) + val profileId = checkNotNull(arguments) { + "Expected arguments to be provided for fragment." + }.getProto(PROFILE_ID_ARGUMENT_KEY, ProfileId.getDefaultInstance()) + explorationManagerFragmentPresenter.handleCreate(profileId) + } + + companion object { + private const val PROFILE_ID_ARGUMENT_KEY = "ExplorationManagerFragment.profile_id" + + /** + * Returns a new instance of [ExplorationManagerFragment] corresponding to the specified + * [profileId]. + */ + fun createNewInstance(profileId: ProfileId): ExplorationManagerFragment { + return ExplorationManagerFragment().apply { + arguments = Bundle().apply { + putProto(PROFILE_ID_ARGUMENT_KEY, profileId) + } + } + } } } diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragmentPresenter.kt index 4df78475693..86dd9d370e5 100644 --- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationManagerFragmentPresenter.kt @@ -3,7 +3,6 @@ package org.oppia.android.app.player.exploration import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.lifecycle.LiveData -import androidx.lifecycle.Observer import androidx.lifecycle.Transformations import org.oppia.android.app.fragment.FragmentScope import org.oppia.android.app.model.Profile @@ -25,11 +24,11 @@ class ExplorationManagerFragmentPresenter @Inject constructor( ) { private lateinit var profileId: ProfileId - fun handleCreate(internalProfileId: Int) { - this.profileId = ProfileId.newBuilder().setInternalId(internalProfileId).build() + fun handleCreate(profileId: ProfileId) { + this.profileId = profileId retrieveReadingTextSize().observe( fragment, - Observer { result -> + { result -> (activity as DefaultFontSizeStateListener).onDefaultFontSizeLoaded(result) } ) diff --git a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivity.kt b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivity.kt index 47c11242da2..9f134a0ad4b 100644 --- a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivity.kt +++ b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivity.kt @@ -6,121 +6,89 @@ import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId +import org.oppia.android.app.model.ResumeLessonActivityParams import org.oppia.android.app.player.exploration.ExplorationActivity +import org.oppia.android.util.extensions.getProtoExtra +import org.oppia.android.util.extensions.putProtoExtra import javax.inject.Inject /** Activity that allows the user to resume a saved exploration. */ class ResumeLessonActivity : InjectableAppCompatActivity(), RouteToExplorationListener { - - @Inject - lateinit var resumeLessonActivityPresenter: ResumeLessonActivityPresenter - private var internalProfileId: Int = -1 - private lateinit var topicId: String - private lateinit var storyId: String - private lateinit var explorationId: String - private lateinit var explorationCheckpoint: ExplorationCheckpoint - private var backflowScreen: Int = -1 + @Inject lateinit var resumeLessonActivityPresenter: ResumeLessonActivityPresenter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) - internalProfileId = - intent.getIntExtra(RESUME_LESSON_ACTIVITY_INTERNAL_PROFILE_ID_ARGUMENT_KEY, -1) - topicId = - checkNotNull(intent.getStringExtra(RESUME_LESSON_ACTIVITY_TOPIC_ID_ARGUMENT_KEY)) { - "Expected topic ID to be included in intent for ResumeLessonActivity." - } - storyId = - checkNotNull(intent.getStringExtra(RESUME_LESSON_ACTIVITY_STORY_ID_ARGUMENT_KEY)) { - "Expected story ID to be included in intent for ResumeLessonActivity." - } - explorationId = - checkNotNull(intent.getStringExtra(RESUME_LESSON_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY)) { - "Expected exploration ID to be included in intent for ResumeLessonActivity." - } - backflowScreen = intent.getIntExtra(RESUME_LESSON_ACTIVITY_BACKFLOW_SCREEN_KEY, -1) - explorationCheckpoint = ExplorationCheckpoint.parseFrom( - intent.getByteArrayExtra(RESUME_LESSON_ACTIVITY_EXPLORATION_CHECKPOINT_ARGUMENT_KEY) - ) + + val params = intent.getProtoExtra(PARAMS_KEY, ResumeLessonActivityParams.getDefaultInstance()) resumeLessonActivityPresenter.handleOnCreate( - internalProfileId, - topicId, - storyId, - explorationId, - backflowScreen, - explorationCheckpoint + params.profileId, + params.topicId, + params.storyId, + params.explorationId, + params.parentScreen, + params.checkpoint ) } // TODO(#1655): Re-restrict access to fields in tests post-Gradle. companion object { - /** Argument key for internal profile ID in [ResumeLessonActivity] */ - const val RESUME_LESSON_ACTIVITY_INTERNAL_PROFILE_ID_ARGUMENT_KEY = - "ResumeLessonActivity.internal_profile_id" - - /** Argument key for topic ID in [ResumeLessonActivity] */ - const val RESUME_LESSON_ACTIVITY_TOPIC_ID_ARGUMENT_KEY = - "ResumeLessonActivity.topic_id" - - /** Argument key for story ID in [ResumeLessonActivity] */ - const val RESUME_LESSON_ACTIVITY_STORY_ID_ARGUMENT_KEY = - "ResumeLessonActivity.story_id" - - /** Argument key for exploration ID in [ResumeLessonActivity] */ - const val RESUME_LESSON_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY = - "ResumeLessonActivity.exploration_id" - - /** Argument key for backflow screen in [ResumeLessonActivity] */ - const val RESUME_LESSON_ACTIVITY_BACKFLOW_SCREEN_KEY = - "ResumeLessonActivity.backflow_screen" - - /** Argument key for exploration checkpoint in [ResumeLessonActivity] */ - const val RESUME_LESSON_ACTIVITY_EXPLORATION_CHECKPOINT_ARGUMENT_KEY = - "ResumeLessonActivity.exploration_checkpoint" + private const val PARAMS_KEY = "ResumeLessonActivity.params" /** - * Returns a new [Intent] to route to [ResumeLessonActivity] for a specified exploration. + * A convenience function for creating a new [ResumeLessonActivity] intent by prefilling common + * params needed by the activity. */ fun createResumeLessonActivityIntent( context: Context, - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, - explorationCheckpoint: ExplorationCheckpoint + parentScreen: ExplorationActivityParams.ParentScreen, + checkpoint: ExplorationCheckpoint ): Intent { - val intent = Intent(context, ResumeLessonActivity::class.java) - intent.putExtra(RESUME_LESSON_ACTIVITY_INTERNAL_PROFILE_ID_ARGUMENT_KEY, internalProfileId) - intent.putExtra(RESUME_LESSON_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, topicId) - intent.putExtra(RESUME_LESSON_ACTIVITY_STORY_ID_ARGUMENT_KEY, storyId) - intent.putExtra(RESUME_LESSON_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, explorationId) - intent.putExtra(RESUME_LESSON_ACTIVITY_BACKFLOW_SCREEN_KEY, backflowScreen) - intent.putExtra( - RESUME_LESSON_ACTIVITY_EXPLORATION_CHECKPOINT_ARGUMENT_KEY, - explorationCheckpoint.toByteArray() - ) - return intent + val params = ResumeLessonActivityParams.newBuilder().apply { + this.profileId = profileId + this.topicId = topicId + this.storyId = storyId + this.explorationId = explorationId + this.parentScreen = parentScreen + this.checkpoint = checkpoint + }.build() + return createResumeLessonActivityIntent(context, params) + } + + /** Returns a new [Intent] open an [ResumeLessonActivity] with the specified [params]. */ + fun createResumeLessonActivityIntent( + context: Context, + params: ResumeLessonActivityParams + ): Intent { + return Intent(context, ResumeLessonActivity::class.java).apply { + putProtoExtra(PARAMS_KEY, params) + } } } override fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( ExplorationActivity.createExplorationActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) diff --git a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivityPresenter.kt index f05a71dd66d..4064708069e 100644 --- a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonActivityPresenter.kt @@ -3,7 +3,9 @@ package org.oppia.android.app.resumelesson import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import org.oppia.android.R +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId import org.oppia.android.databinding.ResumeLessonActivityBinding import javax.inject.Inject @@ -16,11 +18,11 @@ class ResumeLessonActivityPresenter @Inject constructor( /** Handles onCreate() method of the [ResumeLessonActivity] */ fun handleOnCreate( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { val binding = DataBindingUtil.setContentView( @@ -36,11 +38,11 @@ class ResumeLessonActivityPresenter @Inject constructor( if (getResumeLessonFragment() == null) { val resumeLessonFragment = ResumeLessonFragment.newInstance( - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, explorationCheckpoint ) activity.supportFragmentManager.beginTransaction().add( diff --git a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragment.kt b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragment.kt index 89cfcc69210..10a05914af6 100644 --- a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragment.kt +++ b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragment.kt @@ -7,53 +7,41 @@ import android.view.View import android.view.ViewGroup import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId +import org.oppia.android.app.model.ResumeLessonFragmentArguments import org.oppia.android.util.extensions.getProto -import org.oppia.android.util.extensions.getStringFromBundle import org.oppia.android.util.extensions.putProto import javax.inject.Inject /** Fragment that allows the user to resume a saved exploration. */ class ResumeLessonFragment : InjectableFragment() { - companion object { - private const val RESUME_LESSON_FRAGMENT_INTERNAL_PROFILE_ID_KEY = - "ResumeExplorationFragmentPresenter.resume_exploration_fragment_internal_profile_id" - private const val RESUME_LESSON_FRAGMENT_TOPIC_ID_KEY = - "ResumeExplorationFragmentPresenter.resume_exploration_fragment_topic_id" - private const val RESUME_LESSON_FRAGMENT_STORY_ID_KEY = - "ResumeExplorationFragmentPresenter.resume_exploration_fragment_story_id" - private const val RESUME_LESSON_FRAGMENT_EXPLORATION_ID_KEY = - "ResumeExplorationFragmentPresenter.resume_Lesson_fragment_exploration_id" - private const val RESUME_LESSON_FRAGMENT_BACKFLOW_SCREEN_KEY = - "ResumeLessonFragmentPresenter.resume_lesson_fragment_backflow_screen" - private const val RESUME_LESSON_FRAGMENT_EXPLORATION_CHECKPOINT_KEY = - "ResumeExplorationFragmentPresenter.resume_Lesson_fragment_exploration_checkpoint" + private const val ARGUMENTS_KEY = "ResumeExplorationFragment.arguments" - /** - * Creates new instance of [ResumeLessonFragment]. - * - * @param internalProfileId is used by the ResumeLessonFragment to retrieve saved checkpoint - * @param explorationId is used by the ResumeLessonFragment to retrieve saved checkpoint - */ + /** Creates new instance of [ResumeLessonFragment] for the provided parameters. */ fun newInstance( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int, - explorationCheckpoint: ExplorationCheckpoint + parentScreen: ExplorationActivityParams.ParentScreen, + checkpoint: ExplorationCheckpoint ): ResumeLessonFragment { - val resumeLessonFragment = ResumeLessonFragment() - val args = Bundle() - args.putInt(RESUME_LESSON_FRAGMENT_INTERNAL_PROFILE_ID_KEY, internalProfileId) - args.putString(RESUME_LESSON_FRAGMENT_TOPIC_ID_KEY, topicId) - args.putString(RESUME_LESSON_FRAGMENT_STORY_ID_KEY, storyId) - args.putString(RESUME_LESSON_FRAGMENT_EXPLORATION_ID_KEY, explorationId) - args.putInt(RESUME_LESSON_FRAGMENT_BACKFLOW_SCREEN_KEY, backflowScreen) - args.putProto(RESUME_LESSON_FRAGMENT_EXPLORATION_CHECKPOINT_KEY, explorationCheckpoint) - resumeLessonFragment.arguments = args - return resumeLessonFragment + val args = ResumeLessonFragmentArguments.newBuilder().apply { + this.profileId = profileId + this.topicId = topicId + this.storyId = storyId + this.explorationId = explorationId + this.parentScreen = parentScreen + this.checkpoint = checkpoint + }.build() + return ResumeLessonFragment().apply { + arguments = Bundle().apply { + putProto(ARGUMENTS_KEY, args) + } + } } } @@ -70,42 +58,18 @@ class ResumeLessonFragment : InjectableFragment() { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - val internalProfileId = - checkNotNull(arguments?.getInt(RESUME_LESSON_FRAGMENT_INTERNAL_PROFILE_ID_KEY, -1)) { - "Expected profile ID to be included in arguments for ResumeLessonFragment." - } - val topicId = - checkNotNull(arguments?.getStringFromBundle(RESUME_LESSON_FRAGMENT_TOPIC_ID_KEY)) { - "Expected topic ID to be included in arguments for ResumeLessonFragment." - } - val storyId = - checkNotNull(arguments?.getStringFromBundle(RESUME_LESSON_FRAGMENT_STORY_ID_KEY)) { - "Expected story ID to be included in arguments for ResumeLessonFragment." - } - val explorationId = - checkNotNull(arguments?.getStringFromBundle(RESUME_LESSON_FRAGMENT_EXPLORATION_ID_KEY)) { - "Expected exploration ID to be included in arguments for ResumeLessonFragment." - } - val backflowScreen = arguments?.getInt(RESUME_LESSON_FRAGMENT_BACKFLOW_SCREEN_KEY, -1) - val explorationCheckpoint = - checkNotNull( - arguments?.getProto( - RESUME_LESSON_FRAGMENT_EXPLORATION_CHECKPOINT_KEY, - ExplorationCheckpoint.getDefaultInstance() - ) - ) { - "Expected exploration checkpoint to be included in arguments for ResumeLessonFragment." - } - + val args = checkNotNull(arguments) { + "Expected arguments to be provided for fragment." + }.getProto(ARGUMENTS_KEY, ResumeLessonFragmentArguments.getDefaultInstance()) return resumeLessonFragmentPresenter.handleOnCreate( inflater, container, - internalProfileId, - topicId, - storyId, - explorationId, - backflowScreen, - explorationCheckpoint + args.profileId, + args.topicId, + args.storyId, + args.explorationId, + args.parentScreen, + args.checkpoint ) } } diff --git a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentPresenter.kt index 3454050cd3f..89173f4c236 100644 --- a/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentPresenter.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import org.oppia.android.app.home.RouteToExplorationListener import org.oppia.android.app.model.EphemeralChapterSummary +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId import org.oppia.android.app.translation.AppLanguageResourceHandler @@ -59,21 +60,20 @@ class ResumeLessonFragmentPresenter @Inject constructor( fun handleOnCreate( inflater: LayoutInflater, container: ViewGroup?, - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, - explorationCheckpoint: ExplorationCheckpoint + parentScreen: ExplorationActivityParams.ParentScreen, + checkpoint: ExplorationCheckpoint ): View? { - binding = ResumeLessonFragmentBinding.inflate( inflater, container, /* attachToRoot= */ false ) - this.profileId = ProfileId.newBuilder().setInternalId(internalProfileId).build() + this.profileId = profileId this.topicId = topicId this.storyId = storyId this.explorationId = explorationId @@ -83,28 +83,28 @@ class ResumeLessonFragmentPresenter @Inject constructor( it.viewModel = resumeLessonViewModel } - resumeLessonViewModel.explorationCheckpoint.set(explorationCheckpoint) + resumeLessonViewModel.explorationCheckpoint.set(checkpoint) subscribeToChapterSummary() binding.resumeLessonContinueButton.setOnClickListener { playExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, resumeLessonViewModel.explorationCheckpoint.get()!!, - backflowScreen + parentScreen ) } binding.resumeLessonStartOverButton.setOnClickListener { playExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, ExplorationCheckpoint.getDefaultInstance(), - backflowScreen + parentScreen ) } @@ -174,20 +174,20 @@ class ResumeLessonFragmentPresenter @Inject constructor( } private fun playExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, checkpoint: ExplorationCheckpoint, - backflowScreen: Int? + parentScreen: ExplorationActivityParams.ParentScreen ) { val startPlayingProvider = if (checkpoint == ExplorationCheckpoint.getDefaultInstance()) { explorationDataController.restartExploration( - internalProfileId, topicId, storyId, explorationId + profileId.internalId, topicId, storyId, explorationId ) } else { explorationDataController.resumeExploration( - internalProfileId, topicId, storyId, explorationId, checkpoint + profileId.internalId, topicId, storyId, explorationId, checkpoint ) } startPlayingProvider.toLiveData().observe(fragment) { result -> @@ -198,11 +198,11 @@ class ResumeLessonFragmentPresenter @Inject constructor( is AsyncResult.Success -> { oppiaLogger.d("ResumeLessonFragment", "Successfully loaded exploration") routeToExplorationListener.routeToExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, // Checkpointing is enabled be default because stating lesson from // ResumeLessonFragment implies that learner has not completed the lesson. isCheckpointingEnabled = true diff --git a/app/src/main/java/org/oppia/android/app/story/ExplorationSelectionListener.kt b/app/src/main/java/org/oppia/android/app/story/ExplorationSelectionListener.kt index c8667d2a992..8f42436a7c0 100644 --- a/app/src/main/java/org/oppia/android/app/story/ExplorationSelectionListener.kt +++ b/app/src/main/java/org/oppia/android/app/story/ExplorationSelectionListener.kt @@ -1,18 +1,20 @@ package org.oppia.android.app.story +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId /** Listener for cases when the user taps on a specific chapter/exploration to play. */ interface ExplorationSelectionListener { /** Called when an exploration has been selected by the user. */ fun selectExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, canExplorationBeResumed: Boolean, canHavePartialProgressSaved: Boolean, - backflowId: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) } diff --git a/app/src/main/java/org/oppia/android/app/story/StoryActivity.kt b/app/src/main/java/org/oppia/android/app/story/StoryActivity.kt index 65fc4f809da..c02942e29d4 100644 --- a/app/src/main/java/org/oppia/android/app/story/StoryActivity.kt +++ b/app/src/main/java/org/oppia/android/app/story/StoryActivity.kt @@ -6,7 +6,9 @@ import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity import org.oppia.android.app.resumelesson.ResumeLessonActivity import org.oppia.android.app.topic.RouteToResumeLessonListener @@ -37,42 +39,42 @@ class StoryActivity : } override fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( ExplorationActivity.createExplorationActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) } override fun routeToResumeLesson( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { startActivity( ResumeLessonActivity.createResumeLessonActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, explorationCheckpoint ) ) diff --git a/app/src/main/java/org/oppia/android/app/story/StoryFragment.kt b/app/src/main/java/org/oppia/android/app/story/StoryFragment.kt index 9d059264948..0d4187b132b 100644 --- a/app/src/main/java/org/oppia/android/app/story/StoryFragment.kt +++ b/app/src/main/java/org/oppia/android/app/story/StoryFragment.kt @@ -7,7 +7,9 @@ import android.view.View import android.view.ViewGroup import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId import org.oppia.android.util.extensions.getStringFromBundle import javax.inject.Inject @@ -65,23 +67,23 @@ class StoryFragment : InjectableFragment(), ExplorationSelectionListener, StoryF } override fun selectExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, canExplorationBeResumed: Boolean, canHavePartialProgressSaved: Boolean, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { storyFragmentPresenter.handleSelectExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, canExplorationBeResumed, canHavePartialProgressSaved, - backflowScreen, + parentScreen, explorationCheckpoint ) } diff --git a/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt index b1dee626bcf..ff4037415af 100644 --- a/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt @@ -21,7 +21,9 @@ import androidx.recyclerview.widget.RecyclerView import org.oppia.android.R import org.oppia.android.app.home.RouteToExplorationListener import org.oppia.android.app.model.ChapterPlayState +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.recyclerview.BindableAdapter import org.oppia.android.app.story.storyitemviewmodel.StoryChapterSummaryViewModel import org.oppia.android.app.story.storyitemviewmodel.StoryHeaderViewModel @@ -104,32 +106,32 @@ class StoryFragmentPresenter @Inject constructor( } fun handleSelectExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, canExplorationBeResumed: Boolean, canHavePartialProgressSaved: Boolean, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { if (canExplorationBeResumed) { routeToResumeLessonListener.routeToResumeLesson( - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, explorationCheckpoint ) } else { playExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, canHavePartialProgressSaved, - backflowScreen + parentScreen ) } } @@ -251,22 +253,22 @@ class StoryFragmentPresenter @Inject constructor( } private fun playExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, canHavePartialProgressSaved: Boolean, - backflowScreen: Int? + parentScreen: ExplorationActivityParams.ParentScreen ) { // If there's no existing progress, this is either playing a new exploration or replaying an old // one. val startPlayingProvider = if (canHavePartialProgressSaved) { explorationDataController.startPlayingNewExploration( - internalProfileId, topicId, storyId, explorationId + profileId.internalId, topicId, storyId, explorationId ) } else { explorationDataController.replayExploration( - internalProfileId, topicId, storyId, explorationId + profileId.internalId, topicId, storyId, explorationId ) } startPlayingProvider.toLiveData().observe(fragment) { result -> @@ -277,11 +279,11 @@ class StoryFragmentPresenter @Inject constructor( is AsyncResult.Success -> { oppiaLogger.d("Story Fragment", "Successfully loaded exploration: $explorationId") routeToExplorationListener.routeToExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled = canHavePartialProgressSaved ) } diff --git a/app/src/main/java/org/oppia/android/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt b/app/src/main/java/org/oppia/android/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt index e5e84976d60..746af71c90b 100644 --- a/app/src/main/java/org/oppia/android/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/story/storyitemviewmodel/StoryChapterSummaryViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.Observer import org.oppia.android.R import org.oppia.android.app.model.ChapterPlayState import org.oppia.android.app.model.EphemeralChapterSummary +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.LessonThumbnail import org.oppia.android.app.model.ProfileId @@ -45,6 +46,9 @@ class StoryChapterSummaryViewModel( ) } val chapterPlayState: ChapterPlayState = chapterSummary.chapterPlayState + private val profileId by lazy { + ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + } fun onExplorationClicked() { val canHavePartialProgressSaved = @@ -71,25 +75,25 @@ class StoryChapterSummaryViewModel( if (it is AsyncResult.Success) { explorationCheckpointLiveData.removeObserver(this) explorationSelectionListener.selectExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, canExplorationBeResumed = true, canHavePartialProgressSaved, - backflowId = 1, + parentScreen = ExplorationActivityParams.ParentScreen.STORY_SCREEN, explorationCheckpoint = it.value ) } else if (it is AsyncResult.Failure) { explorationCheckpointLiveData.removeObserver(this) explorationSelectionListener.selectExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, canExplorationBeResumed = false, canHavePartialProgressSaved, - backflowId = 1, + parentScreen = ExplorationActivityParams.ParentScreen.STORY_SCREEN, explorationCheckpoint = ExplorationCheckpoint.getDefaultInstance() ) } @@ -98,13 +102,13 @@ class StoryChapterSummaryViewModel( ) } else { explorationSelectionListener.selectExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, canExplorationBeResumed = false, canHavePartialProgressSaved, - backflowId = 1, + parentScreen = ExplorationActivityParams.ParentScreen.STORY_SCREEN, explorationCheckpoint = ExplorationCheckpoint.getDefaultInstance() ) } diff --git a/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivity.kt b/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivity.kt index 0eab42a60a2..8c47b60e056 100644 --- a/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivity.kt +++ b/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivity.kt @@ -4,6 +4,8 @@ import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity import org.oppia.android.app.topic.TopicFragment import org.oppia.android.app.utility.SplitScreenManager @@ -28,21 +30,21 @@ class ExplorationTestActivity : InjectableAppCompatActivity(), RouteToExploratio } override fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( ExplorationActivity.createExplorationActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) diff --git a/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivityPresenter.kt index d57623b188e..f4a4285b28d 100644 --- a/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/testing/ExplorationTestActivityPresenter.kt @@ -9,6 +9,8 @@ import org.oppia.android.app.activity.ActivityScope import org.oppia.android.app.fragment.FragmentComponentImpl import org.oppia.android.app.fragment.InjectableFragment import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.utility.SplitScreenManager import org.oppia.android.domain.exploration.ExplorationDataController import org.oppia.android.domain.oppialogger.OppiaLogger @@ -64,11 +66,11 @@ class ExplorationTestActivityPresenter @Inject constructor( is AsyncResult.Success -> { oppiaLogger.d(TAG_EXPLORATION_TEST_ACTIVITY, "Successfully loaded exploration") routeToExplorationListener.routeToExploration( - INTERNAL_PROFILE_ID, + ProfileId.newBuilder().apply { internalId = INTERNAL_PROFILE_ID }.build(), TOPIC_ID, STORY_ID, EXPLORATION_ID, - backflowScreen = null, + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, isCheckpointingEnabled = false ) } diff --git a/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivity.kt b/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivity.kt index b84f46c6765..7b415d9cf20 100644 --- a/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivity.kt +++ b/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity +import org.oppia.android.app.model.ReadingTextSize import javax.inject.Inject /** Test activity used for testing font scale. */ @@ -16,9 +17,9 @@ class TestFontScaleConfigurationUtilActivity : InjectableAppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) - val readingTextSize = checkNotNull(intent.getStringExtra(FONT_SCALE_EXTRA_KEY)) { - "Expected $FONT_SCALE_EXTRA_KEY to be in intent extras." - } + val readingTextSize = checkNotNull( + intent.getSerializableExtra(FONT_SCALE_EXTRA_KEY) as? ReadingTextSize + ) { "Expected $FONT_SCALE_EXTRA_KEY to be in intent extras." } configUtilActivityPresenter.handleOnCreate(readingTextSize) } @@ -26,7 +27,7 @@ class TestFontScaleConfigurationUtilActivity : InjectableAppCompatActivity() { private const val FONT_SCALE_EXTRA_KEY = "TestFontScaleConfigurationUtilActivity.font_scale" /** Returns a new [TestFontScaleConfigurationUtilActivity] for context and reading text size. */ - fun createFontScaleTestActivity(context: Context, readingTextSize: String): Intent { + fun createFontScaleTestActivity(context: Context, readingTextSize: ReadingTextSize): Intent { val intent = Intent(context, TestFontScaleConfigurationUtilActivity::class.java) intent.putExtra(FONT_SCALE_EXTRA_KEY, readingTextSize) return intent diff --git a/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityPresenter.kt index c46630eb39e..b09b76d15c0 100644 --- a/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityPresenter.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.testing import androidx.appcompat.app.AppCompatActivity import org.oppia.android.R import org.oppia.android.app.activity.ActivityScope +import org.oppia.android.app.model.ReadingTextSize import org.oppia.android.app.utility.FontScaleConfigurationUtil import javax.inject.Inject @@ -12,7 +13,7 @@ class TestFontScaleConfigurationUtilActivityPresenter @Inject constructor( private val activity: AppCompatActivity, private val fontScaleConfigurationUtil: FontScaleConfigurationUtil ) { - fun handleOnCreate(readingTextSize: String) { + fun handleOnCreate(readingTextSize: ReadingTextSize) { fontScaleConfigurationUtil.adjustFontScale(activity, readingTextSize) activity.setContentView(R.layout.font_scale_test_activity) } diff --git a/app/src/main/java/org/oppia/android/app/testing/TopicTestActivity.kt b/app/src/main/java/org/oppia/android/app/testing/TopicTestActivity.kt index eaa6c7a54af..292dbb8138a 100644 --- a/app/src/main/java/org/oppia/android/app/testing/TopicTestActivity.kt +++ b/app/src/main/java/org/oppia/android/app/testing/TopicTestActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity import org.oppia.android.app.story.StoryActivity @@ -58,21 +59,21 @@ class TopicTestActivity : } override fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( ExplorationActivity.createExplorationActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) diff --git a/app/src/main/java/org/oppia/android/app/testing/TopicTestActivityForStory.kt b/app/src/main/java/org/oppia/android/app/testing/TopicTestActivityForStory.kt index b055504b828..a5216c51ec2 100644 --- a/app/src/main/java/org/oppia/android/app/testing/TopicTestActivityForStory.kt +++ b/app/src/main/java/org/oppia/android/app/testing/TopicTestActivityForStory.kt @@ -4,6 +4,7 @@ import android.os.Bundle import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity @@ -63,32 +64,32 @@ class TopicTestActivityForStory : } override fun routeToResumeLesson( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { startActivity( ResumeLessonActivity.createResumeLessonActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, explorationCheckpoint ) ) } override fun routeToExploration( - profileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( @@ -98,7 +99,7 @@ class TopicTestActivityForStory : topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) diff --git a/app/src/main/java/org/oppia/android/app/topic/RouteToResumeLessonListener.kt b/app/src/main/java/org/oppia/android/app/topic/RouteToResumeLessonListener.kt index 5a88a638dc8..babe6ff0d83 100644 --- a/app/src/main/java/org/oppia/android/app/topic/RouteToResumeLessonListener.kt +++ b/app/src/main/java/org/oppia/android/app/topic/RouteToResumeLessonListener.kt @@ -1,16 +1,18 @@ package org.oppia.android.app.topic +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId /** Listener for when an activity should route to a [ResumeLessonActivity]. */ interface RouteToResumeLessonListener { /** Called selects an exploration that can be resumed. */ fun routeToResumeLesson( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) } diff --git a/app/src/main/java/org/oppia/android/app/topic/TopicActivity.kt b/app/src/main/java/org/oppia/android/app/topic/TopicActivity.kt index d3991d3edf8..b087c05c145 100755 --- a/app/src/main/java/org/oppia/android/app/topic/TopicActivity.kt +++ b/app/src/main/java/org/oppia/android/app/topic/TopicActivity.kt @@ -9,6 +9,7 @@ import org.oppia.android.app.activity.ActivityIntentFactories import org.oppia.android.app.activity.InjectableAppCompatActivity import org.oppia.android.app.drawer.NAVIGATION_PROFILE_ID_ARGUMENT_KEY import org.oppia.android.app.home.RouteToExplorationListener +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity @@ -81,42 +82,42 @@ class TopicActivity : } override fun routeToExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, isCheckpointingEnabled: Boolean ) { startActivity( ExplorationActivity.createExplorationActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, isCheckpointingEnabled ) ) } override fun routeToResumeLesson( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, - backflowScreen: Int?, + parentScreen: ExplorationActivityParams.ParentScreen, explorationCheckpoint: ExplorationCheckpoint ) { startActivity( ResumeLessonActivity.createResumeLessonActivityIntent( this, - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen, + parentScreen, explorationCheckpoint ) ) diff --git a/app/src/main/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentPresenter.kt index 9336a1d7db6..55347f05b0e 100644 --- a/app/src/main/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentPresenter.kt @@ -10,6 +10,7 @@ import org.oppia.android.app.fragment.FragmentScope import org.oppia.android.app.home.RouteToExplorationListener import org.oppia.android.app.model.ChapterPlayState import org.oppia.android.app.model.ChapterSummary +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.StorySummary @@ -240,6 +241,9 @@ class TopicLessonsFragmentPresenter @Inject constructor( explorationId: String, chapterPlayState: ChapterPlayState ) { + val profileId = ProfileId.newBuilder().apply { + internalId = internalProfileId + }.build() val canHavePartialProgressSaved = when (chapterPlayState) { ChapterPlayState.IN_PROGRESS_SAVED, ChapterPlayState.IN_PROGRESS_NOT_SAVED, @@ -253,10 +257,7 @@ class TopicLessonsFragmentPresenter @Inject constructor( ChapterPlayState.IN_PROGRESS_SAVED -> { val explorationCheckpointLiveData = explorationCheckpointController.retrieveExplorationCheckpoint( - ProfileId.newBuilder().apply { - internalId = internalProfileId - }.build(), - explorationId + profileId, explorationId ).toLiveData() explorationCheckpointLiveData.observe( fragment, @@ -265,17 +266,17 @@ class TopicLessonsFragmentPresenter @Inject constructor( if (it is AsyncResult.Success) { explorationCheckpointLiveData.removeObserver(this) routeToResumeLessonListener.routeToResumeLesson( - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen = 0, + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB, explorationCheckpoint = it.value ) } else if (it is AsyncResult.Failure) { explorationCheckpointLiveData.removeObserver(this) playExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, @@ -289,7 +290,7 @@ class TopicLessonsFragmentPresenter @Inject constructor( } ChapterPlayState.IN_PROGRESS_NOT_SAVED -> { playExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, @@ -299,7 +300,7 @@ class TopicLessonsFragmentPresenter @Inject constructor( } else -> { playExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, @@ -311,7 +312,7 @@ class TopicLessonsFragmentPresenter @Inject constructor( } private fun playExploration( - internalProfileId: Int, + profileId: ProfileId, topicId: String, storyId: String, explorationId: String, @@ -348,11 +349,11 @@ class TopicLessonsFragmentPresenter @Inject constructor( is AsyncResult.Success -> { oppiaLogger.d("TopicLessonsFragment", "Successfully loaded exploration") routeToExplorationListener.routeToExploration( - internalProfileId, + profileId, topicId, storyId, explorationId, - backflowScreen = 0, + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB, isCheckpointingEnabled = canHavePartialProgressSaved ) } diff --git a/app/src/main/java/org/oppia/android/app/utility/FontScaleConfigurationUtil.kt b/app/src/main/java/org/oppia/android/app/utility/FontScaleConfigurationUtil.kt index f0bcf1bdb9a..78731ab1ce5 100644 --- a/app/src/main/java/org/oppia/android/app/utility/FontScaleConfigurationUtil.kt +++ b/app/src/main/java/org/oppia/android/app/utility/FontScaleConfigurationUtil.kt @@ -9,11 +9,11 @@ import javax.inject.Inject /** Utility to change the scale of font for the entire app. */ class FontScaleConfigurationUtil @Inject constructor() { - /** This method updates font scale. */ - fun adjustFontScale( - context: Context, - readingTextSize: String - ) { + /** + * Updates the specified [context]'s current configuration to scale text size according to the + * provided [readingTextSize]. + */ + fun adjustFontScale(context: Context, readingTextSize: ReadingTextSize) { val configuration = context.resources.configuration configuration.fontScale = getReadingTextSizeConfigurationUtil(readingTextSize) val metrics: DisplayMetrics = context.resources.displayMetrics @@ -24,13 +24,12 @@ class FontScaleConfigurationUtil @Inject constructor() { context.resources.displayMetrics.setTo(metrics) } - /** This method returns font scale by reading text size. */ - private fun getReadingTextSizeConfigurationUtil(readingTextSize: String): Float { + private fun getReadingTextSizeConfigurationUtil(readingTextSize: ReadingTextSize): Float { return when (readingTextSize) { - ReadingTextSize.SMALL_TEXT_SIZE.name -> .8f - ReadingTextSize.MEDIUM_TEXT_SIZE.name -> 1.0f - ReadingTextSize.LARGE_TEXT_SIZE.name -> 1.2f - ReadingTextSize.EXTRA_LARGE_TEXT_SIZE.name -> 1.4f + ReadingTextSize.SMALL_TEXT_SIZE -> .8f + ReadingTextSize.MEDIUM_TEXT_SIZE -> 1.0f + ReadingTextSize.LARGE_TEXT_SIZE -> 1.2f + ReadingTextSize.EXTRA_LARGE_TEXT_SIZE -> 1.4f else -> 1.0f } } diff --git a/app/src/main/res/layout-sw600dp/option_story_text_size.xml b/app/src/main/res/layout-sw600dp/option_story_text_size.xml index 42b3b719afd..88ad2e2a54f 100644 --- a/app/src/main/res/layout-sw600dp/option_story_text_size.xml +++ b/app/src/main/res/layout-sw600dp/option_story_text_size.xml @@ -45,7 +45,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:fontFamily="sans-serif" - android:text="@{viewModel.readingTextSize}" + android:text="@{viewModel.textSizeName}" android:textColor="@color/component_color_option_activity_sub_heading_text_color" android:textSize="14sp" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/option_story_text_size.xml b/app/src/main/res/layout/option_story_text_size.xml index 076b3aeb84a..62bb2d69369 100644 --- a/app/src/main/res/layout/option_story_text_size.xml +++ b/app/src/main/res/layout/option_story_text_size.xml @@ -41,7 +41,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:fontFamily="sans-serif" - android:text="@{viewModel.readingTextSize}" + android:text="@{viewModel.textSizeName}" android:textColor="@color/component_color_option_activity_sub_heading_text_color" android:textSize="14sp" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/text_size_items.xml b/app/src/main/res/layout/text_size_items.xml index 55cf9284ae8..4fe186aa4d9 100644 --- a/app/src/main/res/layout/text_size_items.xml +++ b/app/src/main/res/layout/text_size_items.xml @@ -14,7 +14,7 @@ android:background="@drawable/general_item_background_border_light" android:gravity="center_vertical" android:minHeight="48dp" - android:onClick="@{() -> viewModel.textSizeRadioButtonListener.onTextSizeSelected(viewModel.textSizeName)}" + android:onClick="@{() -> viewModel.textSizeRadioButtonListener.onTextSizeSelected(viewModel.readingTextSize)}" android:importantForAccessibility="yes" android:orientation="horizontal"> diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt index fc5a5ec42ee..ebc402da273 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/RecentlyPlayedFragmentTest.kt @@ -28,11 +28,15 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.rule.ActivityTestRule import com.google.common.truth.Truth.assertThat +import com.google.protobuf.MessageLite import dagger.Component +import org.hamcrest.Description +import org.hamcrest.Matcher import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.instanceOf import org.hamcrest.Matchers.not +import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Rule @@ -51,7 +55,10 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedActivity import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedFragment +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId +import org.oppia.android.app.model.ResumeLessonActivityParams import org.oppia.android.app.player.exploration.ExplorationActivity import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView @@ -112,6 +119,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -822,28 +830,23 @@ class RecentlyPlayedFragmentTest { ) ).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ResumeLessonActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED + checkpoint = ExplorationCheckpoint.newBuilder().apply { + explorationTitle = "What is a Fraction?" + explorationVersion = 85 + pendingStateName = "Introduction" + timestampOfFirstCheckpoint = 102 + }.build() + }.build() intended( allOf( - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_INTERNAL_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ null - ), + hasProtoExtra("ResumeLessonActivity.params", expectedParams), hasComponent(ResumeLessonActivity::class.java.name) ) ) @@ -880,32 +883,18 @@ class RecentlyPlayedFragmentTest { ) ).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = true + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ true - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ null - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -933,32 +922,18 @@ class RecentlyPlayedFragmentTest { ) ).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = true + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ true - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ null - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -991,32 +966,18 @@ class RecentlyPlayedFragmentTest { ) ).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = true + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ true - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ null - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -1475,13 +1436,27 @@ class RecentlyPlayedFragmentTest { } } - fun setUpTestFragment(activity: RecentlyPlayedActivity) { + private fun setUpTestFragment(activity: RecentlyPlayedActivity) { activity.supportFragmentManager .beginTransaction() .add(testFragment, TEST_FRAGMENT_TAG) .commitNow() } + private fun hasProtoExtra(keyName: String, expectedProto: T): Matcher { + val defaultProto = expectedProto.newBuilderForType().build() + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Intent with extra: $keyName and proto value: $expectedProto") + } + + override fun matchesSafely(intent: Intent): Boolean { + return intent.hasExtra(keyName) && + intent.getProtoExtra(keyName, defaultProto) == expectedProto + } + } + } + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton @Component( diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt index 40b61b95c6d..3496ad87adb 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/OptionsFragmentTest.kt @@ -24,8 +24,12 @@ 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 com.google.protobuf.MessageLite import dagger.Component +import org.hamcrest.Description +import org.hamcrest.Matcher import org.hamcrest.Matchers.allOf +import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Rule @@ -42,6 +46,8 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ReadingTextSize +import org.oppia.android.app.model.ReadingTextSizeActivityParams import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -89,6 +95,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -425,12 +432,13 @@ class OptionsFragmentTest { targetViewId = R.id.reading_text_size_text_view ) ).perform(click()) + + val expectedParams = ReadingTextSizeActivityParams.newBuilder().apply { + readingTextSize = ReadingTextSize.MEDIUM_TEXT_SIZE + }.build() intended( allOf( - hasExtra( - ReadingTextSizeActivity.getKeyReadingTextSizePreferenceSummaryValue(), - "Medium" - ), + hasProtoExtra("ReadingTextSizeActivity.params", expectedParams), hasComponent(ReadingTextSizeActivity::class.java.name) ) ) @@ -453,16 +461,13 @@ class OptionsFragmentTest { targetViewId = R.id.reading_text_size_text_view ) ).perform(click()) + + val expectedParams = ReadingTextSizeActivityParams.newBuilder().apply { + readingTextSize = ReadingTextSize.MEDIUM_TEXT_SIZE + }.build() intended( allOf( - hasExtra( - ReadingTextSizeActivity.getKeyReadingTextSizePreferenceTitle(), - READING_TEXT_SIZE - ), - hasExtra( - ReadingTextSizeActivity.getKeyReadingTextSizePreferenceSummaryValue(), - "Medium" - ), + hasProtoExtra("ReadingTextSizeActivity.params", expectedParams), hasComponent(ReadingTextSizeActivity::class.java.name) ) ) @@ -629,6 +634,20 @@ class OptionsFragmentTest { testCoroutineDispatchers.runCurrent() } + private fun hasProtoExtra(keyName: String, expectedProto: T): Matcher { + val defaultProto = expectedProto.newBuilderForType().build() + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Intent with extra: $keyName and proto value: $expectedProto") + } + + override fun matchesSafely(intent: Intent): Boolean { + return intent.hasExtra(keyName) && + intent.getProtoExtra(keyName, defaultProto) == expectedProto + } + } + } + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton @Component( diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt index b4e3196e763..3b67326052c 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeActivityTest.kt @@ -2,7 +2,6 @@ package org.oppia.android.app.options import android.app.Application import android.content.Context -import android.content.Intent import androidx.appcompat.app.AppCompatActivity import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -24,6 +23,7 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ReadingTextSize.MEDIUM_TEXT_SIZE import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -102,10 +102,7 @@ class ReadingTextSizeActivityTest { ReadingTextSizeActivity::class.java, /* initialTouchMode= */ true, /* launchActivity= */ false ) - @Inject - lateinit var context: Context - - private val summaryValue = "Medium" + @Inject lateinit var context: Context @Before fun setUp() { @@ -118,24 +115,16 @@ class ReadingTextSizeActivityTest { @Test fun testReadingTextSizeActivity_hasCorrectActivityLabel() { - activityTestRule.launchActivity( - createReadingTextSizeActivityIntent( - summaryValue - ) - ) + activityTestRule.launchActivity(createReadingTextSizeActivityIntent()) + val title = activityTestRule.activity.title // Verify that the activity label is correct as a proxy to verify TalkBack will announce the // correct string when it's read out. assertThat(title).isEqualTo(context.getString(R.string.reading_text_size_activity_title)) } - private fun createReadingTextSizeActivityIntent(summaryValue: String): Intent { - return ReadingTextSizeActivity.createReadingTextSizeActivityIntent( - ApplicationProvider.getApplicationContext(), - READING_TEXT_SIZE, - summaryValue - ) - } + private fun createReadingTextSizeActivityIntent() = + ReadingTextSizeActivity.createReadingTextSizeActivityIntent(context, MEDIUM_TEXT_SIZE) // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt index c0a5a36a26e..0e75dac607e 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/ReadingTextSizeFragmentTest.kt @@ -37,6 +37,7 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ReadingTextSize.SMALL_TEXT_SIZE import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView import org.oppia.android.app.shim.ViewBindingShimModule @@ -153,7 +154,7 @@ class ReadingTextSizeFragmentTest { @Test fun testTextSize_changeTextSizeToLarge_changeConfiguration_checkTextSizeLargeIsSelected() { - launch(createReadingTextSizeActivityIntent("Small")).use { + launch(createReadingTextSizeActivityIntent()).use { verifyItemIsCheckedInTextSizeRecyclerView(SMALL_TEXT_SIZE_INDEX) clickOnTextSizeRecyclerViewItem(LARGE_TEXT_SIZE_INDEX) rotateToLandscape() @@ -163,7 +164,7 @@ class ReadingTextSizeFragmentTest { @Test fun testTextSize_checkTextSizeOfAllFourItems_textSizeMatchedCorrectly() { - launch(createReadingTextSizeActivityIntent("Small")).use { + launch(createReadingTextSizeActivityIntent()).use { matchTextSizeOfTextSizeRecyclerViewItem( SMALL_TEXT_SIZE_INDEX, defaultTextSizeInFloat * SMALL_TEXT_SIZE_SCALE ) @@ -189,13 +190,8 @@ class ReadingTextSizeFragmentTest { } } - private fun createReadingTextSizeActivityIntent(summaryValue: String): Intent { - return ReadingTextSizeActivity.createReadingTextSizeActivityIntent( - ApplicationProvider.getApplicationContext(), - READING_TEXT_SIZE, - summaryValue - ) - } + private fun createReadingTextSizeActivityIntent() = + ReadingTextSizeActivity.createReadingTextSizeActivityIntent(context, SMALL_TEXT_SIZE) private fun createOptionActivityIntent( internalProfileId: Int, diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt index 9830902e90c..724353f1f76 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt @@ -69,6 +69,7 @@ import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.help.HelpActivity +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.OppiaLanguage import org.oppia.android.app.model.ProfileId import org.oppia.android.app.model.WrittenTranslationLanguageSelection @@ -1725,11 +1726,11 @@ class ExplorationActivityTest { ): Intent { return ExplorationActivity.createExplorationActivityIntent( ApplicationProvider.getApplicationContext(), - internalProfileId, + ProfileId.newBuilder().apply { internalId = internalProfileId }.build(), topicId, storyId, explorationId, - /* backflowScreen= */ null, + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, shouldSavePartialProgress ) } diff --git a/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonActivityTest.kt index e39f45da2b8..8fca32d6d39 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonActivityTest.kt @@ -37,7 +37,9 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -113,8 +115,6 @@ class ResumeLessonActivityTest { @get:Rule val initializeDefaultLocaleRule = InitializeDefaultLocaleRule() - private val internalProfileId: Int = 1 - @Inject lateinit var testCoroutineDispatchers: TestCoroutineDispatchers @@ -192,12 +192,12 @@ class ResumeLessonActivityTest { private fun createResumeLessonActivityIntent(): Intent { return ResumeLessonActivity.createResumeLessonActivityIntent( context, - internalProfileId, + ProfileId.newBuilder().apply { internalId = 1 }.build(), FRACTIONS_TOPIC_ID, FRACTIONS_STORY_ID_0, FRACTIONS_EXPLORATION_ID_0, - backflowScreen = null, - explorationCheckpoint = ExplorationCheckpoint.getDefaultInstance() + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, + checkpoint = ExplorationCheckpoint.getDefaultInstance() ) } diff --git a/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentTest.kt index 6fe742fa7df..c0b2d3f5698 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/resumelesson/ResumeLessonFragmentTest.kt @@ -36,7 +36,9 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ExplorationActivityParams import org.oppia.android.app.model.ExplorationCheckpoint +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.PracticeTabModule @@ -116,8 +118,6 @@ class ResumeLessonFragmentTest { @get:Rule val initializeDefaultLocaleRule = InitializeDefaultLocaleRule() - private val internalProfileId: Int = 1 - @Inject lateinit var testCoroutineDispatchers: TestCoroutineDispatchers @@ -269,24 +269,24 @@ class ResumeLessonFragmentTest { private fun createResumeLessonActivityIntent(): Intent { return ResumeLessonActivity.createResumeLessonActivityIntent( context, - internalProfileId, + ProfileId.newBuilder().apply { internalId = 1 }.build(), FRACTIONS_TOPIC_ID, FRACTIONS_STORY_ID_0, FRACTIONS_EXPLORATION_ID_0, - backflowScreen = null, - explorationCheckpoint = ExplorationCheckpoint.getDefaultInstance() + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, + checkpoint = ExplorationCheckpoint.getDefaultInstance() ) } private fun createResumeRatiosLessonActivityIntent(): Intent { return ResumeLessonActivity.createResumeLessonActivityIntent( context, - internalProfileId, + ProfileId.newBuilder().apply { internalId = 1 }.build(), RATIOS_TOPIC_ID, RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0, - backflowScreen = null, - explorationCheckpoint = ExplorationCheckpoint.getDefaultInstance() + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, + checkpoint = ExplorationCheckpoint.getDefaultInstance() ) } diff --git a/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt index 0183b1740a5..0a0b70162bc 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/story/StoryActivityTest.kt @@ -19,8 +19,12 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.rule.ActivityTestRule import com.google.common.truth.Truth.assertThat +import com.google.protobuf.MessageLite import dagger.Component -import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.Matchers.allOf +import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Rule @@ -37,6 +41,8 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.exploration.ExplorationActivity import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.shim.ViewBindingShimModule @@ -87,6 +93,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -182,12 +189,17 @@ class StoryActivityTest { ) testCoroutineDispatchers.runCurrent() + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = TEST_EXPLORATION_ID_2 + storyId = TEST_STORY_ID_0 + topicId = TEST_TOPIC_ID_0 + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + parentScreen = ExplorationActivityParams.ParentScreen.STORY_SCREEN + isCheckpointingEnabled = true + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - TEST_EXPLORATION_ID_2 - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -211,6 +223,20 @@ class StoryActivityTest { ) } + private fun hasProtoExtra(keyName: String, expectedProto: T): Matcher { + val defaultProto = expectedProto.newBuilderForType().build() + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Intent with extra: $keyName and proto value: $expectedProto") + } + + override fun matchesSafely(intent: Intent): Boolean { + return intent.hasExtra(keyName) && + intent.getProtoExtra(keyName, defaultProto) == expectedProto + } + } + } + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton @Component( diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt index 5516365c6dd..acdf99c0863 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/testing/TestFontScaleConfigurationUtilActivityTest.kt @@ -115,7 +115,7 @@ class TestFontScaleConfigurationUtilActivityTest { Intents.release() } - private fun createFontScaleTestActivityIntent(readingTextSize: String): Intent { + private fun createFontScaleTestActivityIntent(readingTextSize: ReadingTextSize): Intent { return TestFontScaleConfigurationUtilActivity.createFontScaleTestActivity( context, readingTextSize @@ -125,7 +125,7 @@ class TestFontScaleConfigurationUtilActivityTest { @Test fun testFontScaleConfigurationUtil_smallTextSize_hasCorrectDimension() { launch( - createFontScaleTestActivityIntent(ReadingTextSize.SMALL_TEXT_SIZE.name) + createFontScaleTestActivityIntent(ReadingTextSize.SMALL_TEXT_SIZE) ).use { onView(withId(R.id.font_scale_content_text_view)).check( matches( @@ -140,7 +140,7 @@ class TestFontScaleConfigurationUtilActivityTest { @Test fun testFontScaleConfigurationUtil_mediumTextSize_hasCorrectDimension() { launch( - createFontScaleTestActivityIntent(ReadingTextSize.MEDIUM_TEXT_SIZE.name) + createFontScaleTestActivityIntent(ReadingTextSize.MEDIUM_TEXT_SIZE) ).use { onView(withId(R.id.font_scale_content_text_view)).check( matches( @@ -155,7 +155,7 @@ class TestFontScaleConfigurationUtilActivityTest { @Test fun testFontScaleConfigurationUtil_largeTextSize_hasCorrectDimension() { launch( - createFontScaleTestActivityIntent(ReadingTextSize.LARGE_TEXT_SIZE.name) + createFontScaleTestActivityIntent(ReadingTextSize.LARGE_TEXT_SIZE) ).use { onView(withId(R.id.font_scale_content_text_view)).check( matches( @@ -170,7 +170,7 @@ class TestFontScaleConfigurationUtilActivityTest { @Test fun testFontScaleConfigurationUtil_extraLargeTextSize_hasCorrectDimension() { launch( - createFontScaleTestActivityIntent(ReadingTextSize.EXTRA_LARGE_TEXT_SIZE.name) + createFontScaleTestActivityIntent(ReadingTextSize.EXTRA_LARGE_TEXT_SIZE) ).use { onView(withId(R.id.font_scale_content_text_view)).check( matches( diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt index 9bd4ceb03eb..365674d6a51 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentTest.kt @@ -26,10 +26,14 @@ import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.protobuf.MessageLite import dagger.Component +import org.hamcrest.Description +import org.hamcrest.Matcher import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.not +import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Rule @@ -46,7 +50,10 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.ProfileId +import org.oppia.android.app.model.ResumeLessonActivityParams import org.oppia.android.app.player.exploration.ExplorationActivity import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPosition @@ -112,6 +119,7 @@ import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.accessibility.FakeAccessibilityService import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.logging.EventLoggingConfigurationModule @@ -371,29 +379,24 @@ class TopicLessonsFragmentTest { ) ).check(matches(hasDescendant(withId(R.id.chapter_container)))).perform(click()) testCoroutineDispatchers.runCurrent() - intended(hasComponent(ResumeLessonActivity::class.java.name)) - intended( - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_INTERNAL_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ) - ) - intended( - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ) - ) - intended( - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ) - ) + + val expectedParams = ResumeLessonActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB + checkpoint = ExplorationCheckpoint.newBuilder().apply { + explorationTitle = "What is a Fraction?" + explorationVersion = 85 + pendingStateName = "Introduction" + timestampOfFirstCheckpoint = 102 + }.build() + }.build() intended( - hasExtra( - ResumeLessonActivity.RESUME_LESSON_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 + allOf( + hasProtoExtra("ResumeLessonActivity.params", expectedParams), + hasComponent(ResumeLessonActivity::class.java.name) ) ) } @@ -422,32 +425,18 @@ class TopicLessonsFragmentTest { ) ).check(matches(hasDescendant(withId(R.id.chapter_container)))).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = true + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ true - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ 0 - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -468,32 +457,18 @@ class TopicLessonsFragmentTest { ) ).check(matches(hasDescendant(withId(R.id.chapter_container)))).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = true + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ true - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ 0 - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -519,32 +494,18 @@ class TopicLessonsFragmentTest { ) ).check(matches(hasDescendant(withId(R.id.chapter_container)))).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = true + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ true - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ 0 - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -570,32 +531,18 @@ class TopicLessonsFragmentTest { ) ).check(matches(hasDescendant(withId(R.id.chapter_container)))).perform(click()) testCoroutineDispatchers.runCurrent() + + val expectedParams = ExplorationActivityParams.newBuilder().apply { + explorationId = FRACTIONS_EXPLORATION_ID_0 + storyId = FRACTIONS_STORY_ID_0 + topicId = FRACTIONS_TOPIC_ID + profileId = ProfileId.newBuilder().apply { internalId = internalProfileId }.build() + isCheckpointingEnabled = false + parentScreen = ExplorationActivityParams.ParentScreen.TOPIC_SCREEN_LESSONS_TAB + }.build() intended( allOf( - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_EXPLORATION_ID_ARGUMENT_KEY, - FRACTIONS_EXPLORATION_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_STORY_ID_ARGUMENT_KEY, - FRACTIONS_STORY_ID_0 - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_TOPIC_ID_ARGUMENT_KEY, - FRACTIONS_TOPIC_ID - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_PROFILE_ID_ARGUMENT_KEY, - internalProfileId - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_IS_CHECKPOINTING_ENABLED_KEY, - /* isCheckpointEnabled = */ false - ), - hasExtra( - ExplorationActivity.EXPLORATION_ACTIVITY_BACKFLOW_SCREEN_KEY, - /* backflowScreen = */ 0 - ), + hasProtoExtra("ExplorationActivity.params", expectedParams), hasComponent(ExplorationActivity::class.java.name) ) ) @@ -996,6 +943,20 @@ class TopicLessonsFragmentTest { ).check(matches(withDrawable(R.drawable.ic_check_24dp))) } + private fun hasProtoExtra(keyName: String, expectedProto: T): Matcher { + val defaultProto = expectedProto.newBuilderForType().build() + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Intent with extra: $keyName and proto value: $expectedProto") + } + + override fun matchesSafely(intent: Intent): Boolean { + return intent.hasExtra(keyName) && + intent.getProtoExtra(keyName, defaultProto) == expectedProto + } + } + } + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton @Component( diff --git a/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt b/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt index 84d0d72c555..8b66c19ce27 100644 --- a/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt +++ b/app/src/test/java/org/oppia/android/app/player/exploration/ExplorationActivityLocalTest.kt @@ -25,6 +25,8 @@ import org.oppia.android.app.devoptions.DeveloperOptionsModule import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule import org.oppia.android.app.model.EventLog import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.OPEN_EXPLORATION_ACTIVITY +import org.oppia.android.app.model.ExplorationActivityParams +import org.oppia.android.app.model.ProfileId import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule import org.oppia.android.app.shim.IntentFactoryShimModule import org.oppia.android.app.shim.ViewBindingShimModule @@ -178,11 +180,11 @@ class ExplorationActivityLocalTest { ): Intent { return ExplorationActivity.createExplorationActivityIntent( ApplicationProvider.getApplicationContext(), - internalProfileId, + ProfileId.newBuilder().apply { internalId = internalProfileId }.build(), topicId, storyId, explorationId, - backflowScreen = null, + parentScreen = ExplorationActivityParams.ParentScreen.PARENT_SCREEN_UNSPECIFIED, isCheckpointingEnabled = false ) } diff --git a/model/src/main/proto/BUILD.bazel b/model/src/main/proto/BUILD.bazel index 94372b448ff..51ac9b50795 100644 --- a/model/src/main/proto/BUILD.bazel +++ b/model/src/main/proto/BUILD.bazel @@ -27,7 +27,9 @@ oppia_proto_library( name = "arguments_proto", srcs = ["arguments.proto"], deps = [ + ":exploration_checkpoint_proto", ":exploration_proto", + ":profile_proto", ":translation_proto", ], ) diff --git a/model/src/main/proto/arguments.proto b/model/src/main/proto/arguments.proto index b32af37c70e..2e07098faf0 100644 --- a/model/src/main/proto/arguments.proto +++ b/model/src/main/proto/arguments.proto @@ -3,6 +3,8 @@ syntax = "proto3"; package model; import "exploration.proto"; +import "exploration_checkpoint.proto"; +import "profile.proto"; import "translation.proto"; option java_package = "org.oppia.android.app.model"; @@ -64,6 +66,129 @@ message InputInteractionViewTestActivityParams { } } +// Params required when creating a new ExplorationActivity. +message ExplorationActivityParams { + // The ID of the profile that wants to start an exploration play session. + ProfileId profile_id = 1; + + // The ID of the topic to which the opening exploration belongs. + string topic_id = 2; + + // The ID of the story to which the opening exploration belongs. + string story_id = 3; + + // The exploration being opened for a new play session. + string exploration_id = 4; + + // The screen from which this activity was opened. + ParentScreen parent_screen = 5; + + // Indicates whether checkpointing is enabled to story partial completion state for this session. + bool is_checkpointing_enabled = 6; + + // Different parent screens that can open a new exploration activity instance. + enum ParentScreen { + // Indicates that the originating screen isn't actually known. + PARENT_SCREEN_UNSPECIFIED = 0; + + // Corresponds to the lessons tab on the topic viewer screen. + TOPIC_SCREEN_LESSONS_TAB = 1; + + // Corresponds to the story viewer screen. + STORY_SCREEN = 2; + } +} + +// Arguments that must be passed to a new ExplorationFragment. +message ExplorationFragmentArguments { + // The ID of the profile that wants to start an exploration play session. + ProfileId profile_id = 1; + + // The ID of the topic to which the opening exploration belongs. + string topic_id = 2; + + // The ID of the story to which the opening exploration belongs. + string story_id = 3; + + // The exploration being opened for a new play session. + string exploration_id = 4; + + // The text size at which content in the exploration should be rendered. + ReadingTextSize reading_text_size = 5; +} + +// Params required when creating a new ResumeLessonActivity. +message ResumeLessonActivityParams { + // The ID of the profile that wants to start an exploration play session. + ProfileId profile_id = 1; + + // The ID of the topic to which the opening exploration belongs. + string topic_id = 2; + + // The ID of the story to which the opening exploration belongs. + string story_id = 3; + + // The exploration being opened for a new play session. + string exploration_id = 4; + + // The screen from which this activity was opened. + ExplorationActivityParams.ParentScreen parent_screen = 5; + + // The checkpoint that may be used to resume the exploration play session. + ExplorationCheckpoint checkpoint = 6; +} + +// Arguments that must be passed to a new ResumeLessonFragment. +message ResumeLessonFragmentArguments { + // The ID of the profile that wants to start an exploration play session. + ProfileId profile_id = 1; + + // The ID of the topic to which the opening exploration belongs. + string topic_id = 2; + + // The ID of the story to which the opening exploration belongs. + string story_id = 3; + + // The exploration being opened for a new play session. + string exploration_id = 4; + + // The screen from which this activity was opened. + ExplorationActivityParams.ParentScreen parent_screen = 5; + + // The checkpoint that may be used to resume the exploration play session. + ExplorationCheckpoint checkpoint = 6; +} + +// Params required when creating a new ReadingTextSizeActivity. +message ReadingTextSizeActivityParams { + // The ReadingTextSize previously selected by the user (upon opening the activity). + ReadingTextSize reading_text_size = 1; +} + +// The bundle of properties that are saved upon configuration changes in ReadingTextSizeActivity. +message ReadingTextSizeActivityStateBundle { + // The ReadingTextSize selected by the user. + ReadingTextSize selected_reading_text_size = 1; +} + +// The bundle of properties that are returned by ReadingTextSizeActivity after it's finished. +message ReadingTextSizeActivityResultBundle { + // The ReadingTextSize selected by the user. + ReadingTextSize selected_reading_text_size = 1; +} + +// Arguments required when creating a new ReadingTextSizeFragment. +message ReadingTextSizeFragmentArguments { + // The ReadingTextSize previously selected by the user (upon opening the fragment). + ReadingTextSize reading_text_size = 1; +} + +// The bundle of properties that are saved upon configuration changes in ReadingTextSizeFragment. +message ReadingTextSizeFragmentStateBundle { + // The ReadingTextSize selected by the user. + ReadingTextSize selected_reading_text_size = 1; +} + // Activity Parameters needed to open the policy page. message PoliciesActivityParams { // The specific policy page that should be displayed. diff --git a/scripts/assets/kdoc_validity_exemptions.textproto b/scripts/assets/kdoc_validity_exemptions.textproto index eb430e59c77..189547e027f 100644 --- a/scripts/assets/kdoc_validity_exemptions.textproto +++ b/scripts/assets/kdoc_validity_exemptions.textproto @@ -134,7 +134,6 @@ exempted_file_path: "app/src/main/java/org/oppia/android/app/options/LanguageRad exempted_file_path: "app/src/main/java/org/oppia/android/app/options/LanguageSelectionViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/LoadAppLanguageListListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/LoadAudioLanguageListListener.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/options/LoadReadingTextSizeListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionsActivity.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt" @@ -144,16 +143,13 @@ exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionsFrag exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionsFragmentPresenter.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionsItemViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivity.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/ReadingTextSizeActivityPresenter.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragment.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/ReadingTextSizeFragmentPresenter.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/ReadingTextSizeSelectionViewModel.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/RouteToAppLanguageListListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/RouteToAudioLanguageListListener.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/options/RouteToReadingTextSizeListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt" -exempted_file_path: "app/src/main/java/org/oppia/android/app/options/TextSizeRadioButtonListener.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/parser/StringToNumberParser.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/parser/StringToRatioParser.kt" exempted_file_path: "app/src/main/java/org/oppia/android/app/player/audio/AudioFragmentPresenter.kt"