diff --git a/app/src/main/java/org/oppia/android/app/home/HomeFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/home/HomeFragmentPresenter.kt
index b0e38373b8f..5c9e237c630 100644
--- a/app/src/main/java/org/oppia/android/app/home/HomeFragmentPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/home/HomeFragmentPresenter.kt
@@ -21,8 +21,11 @@ import org.oppia.android.app.home.topiclist.TopicSummaryViewModel
import org.oppia.android.app.model.LegacyProfileId
import org.oppia.android.app.model.Profile
import org.oppia.android.app.model.ProfileType
+import org.oppia.android.app.model.Spotlight
import org.oppia.android.app.model.TopicSummary
import org.oppia.android.app.recyclerview.BindableAdapter
+import org.oppia.android.app.spotlight.SpotlightManager
+import org.oppia.android.app.spotlight.SpotlightTarget
import org.oppia.android.app.translation.AppLanguageResourceHandler
import org.oppia.android.app.ui.R
import org.oppia.android.app.utility.datetime.DateTimeUtil
@@ -194,7 +197,24 @@ class HomeFragmentPresenter @Inject constructor(
.registerViewDataBinder(
viewType = ViewType.ALL_TOPICS,
inflateDataBinding = AllTopicsBinding::inflate,
- setViewModel = AllTopicsBinding::setViewModel,
+ setViewModel = { binding, viewModel ->
+ binding.viewModel = viewModel
+ // Request spotlight against the All Topics header for all users.
+ binding.allTopicsTextView.let { headerView ->
+ val manager = activity.supportFragmentManager.findFragmentByTag(
+ SpotlightManager.SPOTLIGHT_FRAGMENT_TAG
+ ) as? SpotlightManager
+ manager?.requestSpotlightViewWithDelayedLayout(
+ SpotlightTarget(
+ anchor = headerView,
+ hint = resourceHandler.getStringInLocale(
+ R.string.home_all_topics_spotlight_hint
+ ),
+ feature = Spotlight.FeatureCase.HOME_ALL_TOPICS_HEADER
+ )
+ )
+ }
+ },
transformViewModel = { it as AllTopicsViewModel }
)
.registerViewDataBinder(
diff --git a/app/src/main/java/org/oppia/android/app/profile/ProfileChooserActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/profile/ProfileChooserActivityPresenter.kt
index 24a3770fbd5..b8650c9624b 100644
--- a/app/src/main/java/org/oppia/android/app/profile/ProfileChooserActivityPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/profile/ProfileChooserActivityPresenter.kt
@@ -6,6 +6,8 @@ import org.oppia.android.app.activity.ActivityScope
import org.oppia.android.app.model.LegacyProfileId
import org.oppia.android.app.model.ProfileChooserActivityParams.ParentScreen
import org.oppia.android.app.model.ProfileChooserFragmentArguments
+import org.oppia.android.app.spotlight.SpotlightFragment
+import org.oppia.android.app.spotlight.SpotlightManager
import org.oppia.android.app.testing.ProfileChooserFragmentTestActivity
import org.oppia.android.app.ui.R
import org.oppia.android.domain.profile.ProfileManagementController
@@ -62,6 +64,15 @@ class ProfileChooserActivityPresenter @Inject constructor(
ProfileChooserFragmentTestActivity.TAG_PROFILE_CHOOSER_FRAGMENT
).commitNow()
}
+
+ // Ensure spotlight fragment is attached similar to HomeActivity.
+ if (getSpotlightFragment() == null) {
+ activity.supportFragmentManager.beginTransaction().add(
+ R.id.profile_spotlight_fragment_placeholder,
+ SpotlightFragment.newInstance(profileId.internalId),
+ SpotlightManager.SPOTLIGHT_FRAGMENT_TAG
+ ).commitNow()
+ }
}
private fun getProfileChooserFragment(): ProfileChooserFragment? {
@@ -71,4 +82,10 @@ class ProfileChooserActivityPresenter @Inject constructor(
R.id.profile_chooser_fragment_placeholder
) as ProfileChooserFragment?
}
+
+ private fun getSpotlightFragment(): SpotlightFragment? {
+ return activity.supportFragmentManager.findFragmentById(
+ R.id.profile_spotlight_fragment_placeholder
+ ) as? SpotlightFragment
+ }
}
diff --git a/app/src/main/java/org/oppia/android/app/profile/ProfileChooserFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/profile/ProfileChooserFragmentPresenter.kt
index f21016afef2..5543c155710 100644
--- a/app/src/main/java/org/oppia/android/app/profile/ProfileChooserFragmentPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/profile/ProfileChooserFragmentPresenter.kt
@@ -24,9 +24,12 @@ import org.oppia.android.app.model.LegacyProfileId
import org.oppia.android.app.model.Profile
import org.oppia.android.app.model.ProfileChooserActivityParams.ParentScreen
import org.oppia.android.app.model.ProfileType
+import org.oppia.android.app.model.Spotlight
import org.oppia.android.app.onboarding.IntroActivity
import org.oppia.android.app.recyclerview.BindableAdapter
import org.oppia.android.app.recyclerview.StartSnapHelper
+import org.oppia.android.app.spotlight.SpotlightManager
+import org.oppia.android.app.spotlight.SpotlightTarget
import org.oppia.android.app.translation.AppLanguageResourceHandler
import org.oppia.android.app.ui.R
import org.oppia.android.domain.oppialogger.OppiaLogger
@@ -112,6 +115,34 @@ class ProfileChooserFragmentPresenter @Inject constructor(
logProfileChooserEvent()
+ // Request admin controls spotlight (use icon as the single anchor) when laid out.
+ binding.profileSelectionSettingIcon.let { iconView ->
+ getSpotlightManager()?.requestSpotlightViewWithDelayedLayout(
+ SpotlightTarget(
+ anchor = iconView,
+ hint = resourceHandler.getStringInLocale(
+ R.string.profile_chooser_spotlight_admin_controls
+ ),
+ feature = Spotlight.FeatureCase.PROFILE_ADMIN_CONTROLS_ITEM
+ )
+ )
+ }
+
+ // Request add-learner FAB spotlight when laid out and visible.
+ binding.addProfileButton.let { fab ->
+ if (fab.visibility == View.VISIBLE) {
+ getSpotlightManager()?.requestSpotlightViewWithDelayedLayout(
+ SpotlightTarget(
+ anchor = fab,
+ hint = resourceHandler.getStringInLocale(
+ R.string.profile_chooser_spotlight_add_learner
+ ),
+ feature = Spotlight.FeatureCase.PROFILE_ADD_LEARNER_FAB
+ )
+ )
+ }
+ }
+
binding.apply {
when (Resources.getSystem().configuration.orientation) {
Configuration.ORIENTATION_PORTRAIT -> setUpPortraitMode()
@@ -257,6 +288,18 @@ class ProfileChooserFragmentPresenter @Inject constructor(
viewModel: ProfileItemViewModel
) {
binding.viewModel = viewModel
+ // Spotlight the admin profile item (first item) using delayed-layout request (avoids View.post).
+ if (viewModel.profile.profileType == ProfileType.SUPERVISOR) {
+ getSpotlightManager()?.requestSpotlightViewWithDelayedLayout(
+ SpotlightTarget(
+ anchor = binding.root,
+ hint = resourceHandler.getStringInLocale(
+ R.string.profile_chooser_spotlight_admin_profile
+ ),
+ feature = Spotlight.FeatureCase.PROFILE_ADMIN_ITEM
+ )
+ )
+ }
}
private fun addProfileButtonClickListener() {
@@ -279,6 +322,12 @@ class ProfileChooserFragmentPresenter @Inject constructor(
}
}
+ private fun getSpotlightManager(): SpotlightManager? {
+ return activity.supportFragmentManager.findFragmentByTag(
+ SpotlightManager.SPOTLIGHT_FRAGMENT_TAG
+ ) as? SpotlightManager
+ }
+
private fun logProfileChooserEvent() {
analyticsController.logImportantEvent(
oppiaLogger.createOpenProfileChooserContext(),
diff --git a/app/src/main/res/layout/profile_chooser_activity.xml b/app/src/main/res/layout/profile_chooser_activity.xml
index e2d3de8424f..641033ed743 100644
--- a/app/src/main/res/layout/profile_chooser_activity.xml
+++ b/app/src/main/res/layout/profile_chooser_activity.xml
@@ -1,7 +1,27 @@
-
+ tools:context=".app.profile.ProfileChooserActivity">
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8ee7f44f8c0..8427619a3ae 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -759,4 +759,10 @@
Type a 5-Digit PIN
Your PIN should be 5 digits long
Please make sure that both PINs match
+
+
+ Click here to explore administrator controls
+ Click here to enter your account and explore lessons as a learner
+ Click here to create a profile for a learner
+ Select a Topic to start learning
diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt
index 211bf66fc2b..005ab1987af 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt
@@ -2079,6 +2079,38 @@ class HomeActivityTest {
testCoroutineDispatchers.runCurrent()
}
+ @Test
+ fun testHomeSpotlight_allTopicsHeader_whenNotSeen_showsHint() {
+ TestPlatformParameterModule.forceEnableSpotlightUi(true)
+ setUpTestApplicationComponent()
+ profileTestHelper.initializeProfiles(autoLogIn = false)
+ // Launch HomeActivity directly for admin profile 0.
+ launch(createHomeActivityIntent(0)).use {
+ testCoroutineDispatchers.runCurrent()
+ onView(withText(R.string.home_all_topics_spotlight_hint)).check(matches(isDisplayed()))
+ }
+ }
+
+ @Test
+ fun testHomeSpotlight_allTopicsHeader_whenMarkedSeen_notShown() {
+ TestPlatformParameterModule.forceEnableSpotlightUi(true)
+ setUpTestApplicationComponent()
+ profileTestHelper.initializeProfiles(autoLogIn = false)
+ val profileId = ProfileId.newBuilder().setInternalId(0).build()
+ dataProviderTestMonitor
+ .waitForNextSuccessfulResult(
+ spotlightStateController.markSpotlightViewed(
+ profileId,
+ Spotlight.FeatureCase.HOME_ALL_TOPICS_HEADER
+ )
+ )
+
+ launch(createHomeActivityIntent(0)).use {
+ testCoroutineDispatchers.runCurrent()
+ onView(withText(R.string.home_all_topics_spotlight_hint)).check(doesNotExist())
+ }
+ }
+
private fun createHomeActivityIntent(internalProfileId: Int): Intent {
val profileId = LegacyProfileId.newBuilder().setInternalId(internalProfileId).build()
return HomeActivity.createHomeActivity(context, profileId)
diff --git a/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserSpotlightTest.kt b/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserSpotlightTest.kt
new file mode 100644
index 00000000000..feb7949a103
--- /dev/null
+++ b/app/src/sharedTest/java/org/oppia/android/app/profile/ProfileChooserSpotlightTest.kt
@@ -0,0 +1,172 @@
+package org.oppia.android.app.profile
+
+import android.app.Activity
+import android.app.Application
+import android.content.Context
+import androidx.test.core.app.ActivityScenario.launch
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import dagger.BindsInstance
+import dagger.Component
+import dagger.Module
+import dagger.Provides
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.oppia.android.app.model.ProfileChooserActivityParams
+import org.oppia.android.app.model.ProfileId
+import org.oppia.android.app.model.Spotlight
+import org.oppia.android.app.ui.R
+import org.oppia.android.domain.spotlight.SpotlightStateController
+import org.oppia.android.testing.TestOppiaClockRule
+import org.oppia.android.testing.data.DataProviderTestMonitor
+import org.oppia.android.testing.espresso.EspressoHelpers.onViewWithText
+import org.oppia.android.testing.junit.InitializeDefaultLocaleRule
+import org.oppia.android.testing.platformparameter.TestPlatformParameterModule
+import org.oppia.android.testing.robolectric.RobolectricModule
+import org.oppia.android.testing.threading.TestCoroutineDispatchers
+import org.oppia.android.testing.threading.TestDispatcherModule
+import org.oppia.android.util.data.DataProvidersInjector
+import org.oppia.android.util.data.DataProvidersInjectorProvider
+import org.oppia.android.util.locale.LocaleProdModule
+import org.oppia.android.util.logging.EnableConsoleLog
+import org.oppia.android.util.logging.EnableFileLog
+import org.oppia.android.util.logging.GlobalLogLevel
+import org.oppia.android.util.logging.LogLevel
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@RunWith(AndroidJUnit4::class)
+@MediumTest
+class ProfileChooserSpotlightTest {
+
+ @get:Rule val initializeDefaultLocaleRule = InitializeDefaultLocaleRule()
+ @get:Rule val oppiaClockRule = TestOppiaClockRule()
+
+ @Inject lateinit var spotlightStateController: SpotlightStateController
+ @Inject lateinit var dataProviderTestMonitor: DataProviderTestMonitor.Factory
+ @Inject lateinit var testCoroutineDispatchers: TestCoroutineDispatchers
+
+ private val adminProfileId: ProfileId = ProfileId.newBuilder().setInternalId(0).build()
+
+ @Before
+ fun setUp() {
+ setUpTestApplicationComponent()
+ // Ensure spotlight UI is enabled for these tests.
+ TestPlatformParameterModule.forceEnableSpotlightUi(true)
+ }
+
+ @Test
+ fun testAdminControlsSpotlight_whenNotSeen_showsHint() {
+ // Ensure state is not seen.
+ // Launch chooser.
+ launchProfileChooser()
+
+ // Verify hint is shown.
+ onViewWithText(R.string.profile_chooser_spotlight_admin_controls).check(matches(isDisplayed()))
+ }
+
+ @Test
+ fun testAdminControlsSpotlight_whenMarkedSeen_notShownOnReopen() {
+ dataProviderTestMonitor.waitForNextSuccessfulResult(
+ spotlightStateController.markSpotlightViewed(
+ adminProfileId, Spotlight.FeatureCase.PROFILE_ADMIN_CONTROLS_ITEM
+ )
+ )
+ // Launch chooser.
+ launchProfileChooser()
+
+ // Hint should not appear.
+ onViewWithText(R.string.profile_chooser_spotlight_admin_controls).check(doesNotExist())
+ }
+
+ @Test
+ fun testAddLearnerFabSpotlight_whenNotSeen_showsHint() {
+ launchProfileChooser()
+ onViewWithText(R.string.profile_chooser_spotlight_add_learner).check(matches(isDisplayed()))
+ }
+
+ @Test
+ fun testAdminProfileItemSpotlight_whenNotSeen_showsHint() {
+ launchProfileChooser()
+ onViewWithText(R.string.profile_chooser_spotlight_admin_profile).check(matches(isDisplayed()))
+ }
+
+ private fun launchProfileChooser(): ActivityScenarioRuleProxy {
+ val context = ApplicationProvider.getApplicationContext()
+ val params = ProfileChooserActivityParams.newBuilder()
+ .setParentScreen(ProfileChooserActivityParams.ParentScreen.SPLASH_SCREEN)
+ .build()
+ val intent = ProfileChooserActivity.createProfileChooserActivity(context).apply {
+ org.oppia.android.util.extensions.putProtoExtra(
+ "ProfileChooserActivity.params", params
+ )
+ }
+ val scenario = launch(intent)
+ testCoroutineDispatchers.runCurrent()
+ return ActivityScenarioRuleProxy(scenario)
+ }
+
+ private fun setUpTestApplicationComponent() {
+ ApplicationProvider.getApplicationContext().inject(this)
+ }
+
+ // Helpers & DI setup
+
+ data class ActivityScenarioRuleProxy(
+ val scenario: androidx.test.core.app.ActivityScenario
+ )
+
+ @Module
+ class TestModule {
+ @Provides
+ @Singleton
+ fun provideContext(application: Application): Context = application
+
+ @EnableConsoleLog
+ @Provides
+ fun provideEnableConsoleLog(): Boolean = true
+
+ @EnableFileLog
+ @Provides
+ fun provideEnableFileLog(): Boolean = false
+
+ @GlobalLogLevel
+ @Provides
+ fun provideGlobalLogLevel(): LogLevel = LogLevel.VERBOSE
+ }
+
+ @Singleton
+ @Component(
+ modules = [
+ RobolectricModule::class,
+ LocaleProdModule::class,
+ TestDispatcherModule::class,
+ TestModule::class,
+ TestPlatformParameterModule::class
+ ]
+ )
+ interface TestApplicationComponent : DataProvidersInjector {
+ @Component.Builder
+ interface Builder {
+ @BindsInstance fun setApplication(application: Application): Builder
+ fun build(): TestApplicationComponent
+ }
+ fun inject(test: ProfileChooserSpotlightTest)
+ }
+
+ class TestApplication : Application(), DataProvidersInjectorProvider {
+ private val component: TestApplicationComponent by lazy {
+ DaggerProfileChooserSpotlightTest_TestApplicationComponent.builder()
+ .setApplication(this)
+ .build()
+ }
+ fun inject(test: ProfileChooserSpotlightTest) = component.inject(test)
+ override fun getDataProvidersInjector(): DataProvidersInjector = component
+ }
+}
diff --git a/domain/src/main/java/org/oppia/android/domain/spotlight/SpotlightStateController.kt b/domain/src/main/java/org/oppia/android/domain/spotlight/SpotlightStateController.kt
index 7b26510ecee..e8049500f44 100644
--- a/domain/src/main/java/org/oppia/android/domain/spotlight/SpotlightStateController.kt
+++ b/domain/src/main/java/org/oppia/android/domain/spotlight/SpotlightStateController.kt
@@ -5,7 +5,11 @@ import org.oppia.android.app.model.LegacyProfileId
import org.oppia.android.app.model.Spotlight
import org.oppia.android.app.model.Spotlight.FeatureCase.FEATURE_NOT_SET
import org.oppia.android.app.model.Spotlight.FeatureCase.FIRST_CHAPTER
+import org.oppia.android.app.model.Spotlight.FeatureCase.HOME_ALL_TOPICS_HEADER
import org.oppia.android.app.model.Spotlight.FeatureCase.LESSONS_BACK_BUTTON
+import org.oppia.android.app.model.Spotlight.FeatureCase.PROFILE_ADD_LEARNER_FAB
+import org.oppia.android.app.model.Spotlight.FeatureCase.PROFILE_ADMIN_CONTROLS_ITEM
+import org.oppia.android.app.model.Spotlight.FeatureCase.PROFILE_ADMIN_ITEM
import org.oppia.android.app.model.Spotlight.FeatureCase.PROMOTED_STORIES
import org.oppia.android.app.model.Spotlight.FeatureCase.TOPIC_LESSON_TAB
import org.oppia.android.app.model.Spotlight.FeatureCase.TOPIC_REVISION_TAB
@@ -92,6 +96,10 @@ class SpotlightStateController @Inject constructor(
LESSONS_BACK_BUTTON -> it.lessonsBackButton
VOICEOVER_PLAY_ICON -> it.voiceoverPlayIcon
VOICEOVER_LANGUAGE_ICON -> it.voiceoverLanguageIcon
+ PROFILE_ADMIN_CONTROLS_ITEM -> it.profileAdminControlsItem
+ PROFILE_ADMIN_ITEM -> it.profileAdminItem
+ PROFILE_ADD_LEARNER_FAB -> it.profileAddLearnerFab
+ HOME_ALL_TOPICS_HEADER -> it.homeAllTopicsHeader
FEATURE_NOT_SET -> {
return@transformAsync AsyncResult.Failure(
SpotlightFeatureNotFoundException("Spotlight feature requested was not found")
@@ -122,6 +130,10 @@ class SpotlightStateController @Inject constructor(
LESSONS_BACK_BUTTON -> this.setLessonsBackButton(viewState)
VOICEOVER_PLAY_ICON -> this.setVoiceoverPlayIcon(viewState)
VOICEOVER_LANGUAGE_ICON -> this.setVoiceoverLanguageIcon(viewState)
+ PROFILE_ADMIN_CONTROLS_ITEM -> this.setProfileAdminControlsItem(viewState)
+ PROFILE_ADMIN_ITEM -> this.setProfileAdminItem(viewState)
+ PROFILE_ADD_LEARNER_FAB -> this.setProfileAddLearnerFab(viewState)
+ HOME_ALL_TOPICS_HEADER -> this.setHomeAllTopicsHeader(viewState)
FEATURE_NOT_SET -> {
throw SpotlightFeatureNotFoundException("Spotlight feature was not found")
}
diff --git a/domain/src/test/java/org/oppia/android/domain/spotlight/SpotlightStateControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/spotlight/SpotlightStateControllerTest.kt
index 9ffd5bdd14f..bfffa4da7c0 100644
--- a/domain/src/test/java/org/oppia/android/domain/spotlight/SpotlightStateControllerTest.kt
+++ b/domain/src/test/java/org/oppia/android/domain/spotlight/SpotlightStateControllerTest.kt
@@ -15,7 +15,11 @@ import org.junit.runner.RunWith
import org.oppia.android.app.model.LegacyProfileId
import org.oppia.android.app.model.Spotlight
import org.oppia.android.app.model.Spotlight.FeatureCase.FIRST_CHAPTER
+import org.oppia.android.app.model.Spotlight.FeatureCase.HOME_ALL_TOPICS_HEADER
import org.oppia.android.app.model.Spotlight.FeatureCase.LESSONS_BACK_BUTTON
+import org.oppia.android.app.model.Spotlight.FeatureCase.PROFILE_ADD_LEARNER_FAB
+import org.oppia.android.app.model.Spotlight.FeatureCase.PROFILE_ADMIN_CONTROLS_ITEM
+import org.oppia.android.app.model.Spotlight.FeatureCase.PROFILE_ADMIN_ITEM
import org.oppia.android.app.model.Spotlight.FeatureCase.PROMOTED_STORIES
import org.oppia.android.app.model.Spotlight.FeatureCase.TOPIC_LESSON_TAB
import org.oppia.android.app.model.Spotlight.FeatureCase.TOPIC_REVISION_TAB
@@ -245,6 +249,74 @@ class SpotlightStateControllerTest {
assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_SEEN)
}
+ @Test
+ fun testRetrieveSpotlightViewState_profileAdminControls_notMarked_returnsNotSeen() {
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, PROFILE_ADMIN_CONTROLS_ITEM)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_NOT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_profileAdminControls_marked_returnsSeen() {
+ markSpotlightSeen(PROFILE_ADMIN_CONTROLS_ITEM)
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, PROFILE_ADMIN_CONTROLS_ITEM)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_profileAdminItem_notMarked_returnsNotSeen() {
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, PROFILE_ADMIN_ITEM)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_NOT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_profileAdminItem_marked_returnsSeen() {
+ markSpotlightSeen(PROFILE_ADMIN_ITEM)
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, PROFILE_ADMIN_ITEM)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_profileAddLearnerFab_notMarked_returnsNotSeen() {
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, PROFILE_ADD_LEARNER_FAB)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_NOT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_profileAddLearnerFab_marked_returnsSeen() {
+ markSpotlightSeen(PROFILE_ADD_LEARNER_FAB)
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, PROFILE_ADD_LEARNER_FAB)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_homeAllTopicsHeader_notMarked_returnsNotSeen() {
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, HOME_ALL_TOPICS_HEADER)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_NOT_SEEN)
+ }
+
+ @Test
+ fun testRetrieveSpotlightViewState_homeAllTopicsHeader_marked_returnsSeen() {
+ markSpotlightSeen(HOME_ALL_TOPICS_HEADER)
+ val provider =
+ spotlightStateController.retrieveSpotlightViewState(profileId0, HOME_ALL_TOPICS_HEADER)
+ val result = dataProviderTestMonitor.waitForNextSuccessfulResult(provider)
+ assertThat(result).isEqualTo(SpotlightViewState.SPOTLIGHT_SEEN)
+ }
+
@Test
fun testRetrieveSpotlightViewState_invalidFeature_returnsFailure() {
val invalidFeature = Spotlight.FeatureCase.FEATURE_NOT_SET
diff --git a/model/src/main/proto/spotlight.proto b/model/src/main/proto/spotlight.proto
index f6bad25532a..3deeb317b0f 100644
--- a/model/src/main/proto/spotlight.proto
+++ b/model/src/main/proto/spotlight.proto
@@ -34,6 +34,18 @@ message Spotlight {
// Corresponds to the voice-over language option in audio player.
SpotlightViewState voiceover_language_icon = 8;
+
+ // Corresponds to the Admin Controls entry on the profile chooser screen (Onboarding V2).
+ SpotlightViewState profile_admin_controls_item = 9;
+
+ // Corresponds to the Admin profile item on the profile chooser screen (Onboarding V2).
+ SpotlightViewState profile_admin_item = 10;
+
+ // Corresponds to the Add Learner Floating Action Button on the profile chooser screen (Onboarding V2).
+ SpotlightViewState profile_add_learner_fab = 11;
+
+ // Corresponds to the All Topics header on the Home screen.
+ SpotlightViewState home_all_topics_header = 12;
}
}
@@ -75,4 +87,16 @@ message SpotlightStateDatabase {
// Corresponds to the voice-over language option in audio player.
SpotlightViewState voiceover_language_icon = 8;
+
+ // Corresponds to the Admin Controls entry on the profile chooser screen (Onboarding V2).
+ SpotlightViewState profile_admin_controls_item = 9;
+
+ // Corresponds to the Admin profile item on the profile chooser screen (Onboarding V2).
+ SpotlightViewState profile_admin_item = 10;
+
+ // Corresponds to the Add Learner Floating Action Button on the profile chooser screen (Onboarding V2).
+ SpotlightViewState profile_add_learner_fab = 11;
+
+ // Corresponds to the All Topics header on the Home screen.
+ SpotlightViewState home_all_topics_header = 12;
}