-
Notifications
You must be signed in to change notification settings - Fork 554
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…nctionality (#4699) <!-- READ ME FIRST: Please fill in the explanation section below and check off every point from the Essential Checklist! --> ## Explanation <!-- - Explain what your PR does. If this PR fixes an existing bug, please include - "Fixes #bugnum:" in the explanation so that GitHub can auto-close the issue - when this PR is merged. --> fixes #4452 fixes #4453 fixes #4454 fixes #4455 fixes #4456 fixes #4457 fixes #4458 fixes #4459 This PR introduces the SpotlightFragment into the codebase, which is essentially a powerful, robust API that can highlight or 'spotlight' certain parts of the UI to create an onboarding experience for the same. We introduce the [Spotlight library](https://github.com/TakuSemba/Spotlight) into the codebase handles the highlighting of certain elements on screen. The work done in this PR augments the functionality of the library, by dynamically adding arrows and hints which create an over-all Spotlight onboarding experience to the app, beautifully surfacing some functionalities of the app to a new user. We also work on making sure that the spotlight is only shown to a user only once - the protocol buffers are used to save which spotlight has already been seen. The purpose of this PR is to introduce an API that the future contributors can use to seamlessly integrate spotlights onto UI elements as and when needed, with minimal coding. This PR also implements spotlights for the onboarding, home, topic and exploration screens that are required at this time. For accessibility, the content descriptions of all the elements on which spotlights are required today are updated. If talkback is turned on, the spotlights will not show up. The entire spotlight functionality is also gated behind a feature flag. This entire PR is backed by tests. ## Essential Checklist <!-- Please tick the relevant boxes by putting an "x" in them. --> - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only <!-- Delete these section if this PR does not include UI-related changes. --> If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-(A11y)-Guide)) - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing Co-authored-by: Ben Henning <[email protected]> Co-authored-by: madhurgera2 <[email protected]> Co-authored-by: JishnuGoyal <[email protected]>
- Loading branch information
1 parent
3059cc7
commit 642a7bd
Showing
76 changed files
with
2,628 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
.../main/java/org/oppia/android/app/customview/ChapterNotStartedContainerConstraintLayout.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package org.oppia.android.app.customview | ||
|
||
import android.content.Context | ||
import android.util.AttributeSet | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.FragmentManager | ||
import org.oppia.android.R | ||
import org.oppia.android.app.model.Spotlight | ||
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.view.ViewComponentFactory | ||
import org.oppia.android.app.view.ViewComponentImpl | ||
import javax.inject.Inject | ||
|
||
/** Custom view that represents an incomplete chapter. */ | ||
class ChapterNotStartedContainerConstraintLayout @JvmOverloads constructor( | ||
context: Context, | ||
attrs: AttributeSet? = null, | ||
defStyleAttr: Int = 0 | ||
) : ConstraintLayout(context, attrs, defStyleAttr) { | ||
|
||
private var index: Int = -1 | ||
private var isSpotlit = false | ||
|
||
@Inject | ||
lateinit var fragment: Fragment | ||
|
||
@Inject | ||
lateinit var resourceHandler: AppLanguageResourceHandler | ||
|
||
/** Sets the index of the story of which this custom view is a part of. */ | ||
fun setStoryIndex(index: Int) { | ||
// Only spotlight the first chapter of the "first" story. We know for sure that for a new user, | ||
// the first chapter shall be a type of not started chapter view. The index tells which story | ||
// are we on. | ||
this.index = index | ||
} | ||
|
||
private fun getSpotlightFragment(): SpotlightManager? { | ||
return fragment.requireActivity().supportFragmentManager.findFragmentByTag( | ||
SpotlightManager.SPOTLIGHT_FRAGMENT_TAG | ||
) as? SpotlightManager | ||
} | ||
|
||
override fun onAttachedToWindow() { | ||
super.onAttachedToWindow() | ||
|
||
val viewComponentFactory = | ||
FragmentManager.findFragment<Fragment>(this) as ViewComponentFactory | ||
val viewComponent = viewComponentFactory.createViewComponent(this) as ViewComponentImpl | ||
viewComponent.inject(this) | ||
|
||
if (!isSpotlit) { | ||
isSpotlit = true | ||
val spotlightTarget = SpotlightTarget( | ||
this, | ||
resourceHandler.getStringInLocale(R.string.first_chapter_spotlight_hint), | ||
feature = Spotlight.FeatureCase.FIRST_CHAPTER | ||
) | ||
if (index == 0) { | ||
checkNotNull(getSpotlightFragment()).requestSpotlightViewWithDelayedLayout(spotlightTarget) | ||
} | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
app/src/main/java/org/oppia/android/app/customview/PromotedStoryCardView.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.oppia.android.app.customview | ||
|
||
import android.content.Context | ||
import android.util.AttributeSet | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.FragmentManager | ||
import com.google.android.material.card.MaterialCardView | ||
import org.oppia.android.R | ||
import org.oppia.android.app.model.Spotlight | ||
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.view.ViewComponentFactory | ||
import org.oppia.android.app.view.ViewComponentImpl | ||
import javax.inject.Inject | ||
|
||
/** [MaterialCardView] that represents stories promoted to the learner. */ | ||
class PromotedStoryCardView @JvmOverloads constructor( | ||
context: Context, | ||
attrs: AttributeSet? = null, | ||
defStyleAttr: Int = 0 | ||
) : MaterialCardView(context, attrs, defStyleAttr) { | ||
|
||
@Inject | ||
lateinit var fragment: Fragment | ||
|
||
@Inject | ||
lateinit var resourceHandler: AppLanguageResourceHandler | ||
|
||
private var isSpotlit = false | ||
|
||
/** Sets the index at which this custom view is located inside the recycler view. */ | ||
fun setPromotedStoryIndex(index: Int) { | ||
// This view can get attached multiple times and we must make sure that the spotlight is | ||
// requested only once. Only spotlight the item at the first index of the recycler view. | ||
if (!isSpotlit && index == 0) { | ||
isSpotlit = true | ||
val spotlightTarget = SpotlightTarget( | ||
this, | ||
resourceHandler.getStringInLocale(R.string.promoted_story_spotlight_hint), | ||
feature = Spotlight.FeatureCase.PROMOTED_STORIES | ||
) | ||
checkNotNull(getSpotlightFragment()).requestSpotlightViewWithDelayedLayout(spotlightTarget) | ||
} | ||
} | ||
|
||
private fun getSpotlightFragment(): SpotlightManager? { | ||
return fragment.requireActivity().supportFragmentManager.findFragmentByTag( | ||
SpotlightManager.SPOTLIGHT_FRAGMENT_TAG | ||
) as? SpotlightManager | ||
} | ||
|
||
override fun onAttachedToWindow() { | ||
super.onAttachedToWindow() | ||
val viewComponentFactory = | ||
FragmentManager.findFragment<Fragment>(this) as ViewComponentFactory | ||
val viewComponent = viewComponentFactory.createViewComponent(this) as ViewComponentImpl | ||
viewComponent.inject(this) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.