Skip to content

Commit

Permalink
Fix part of oppia#3600: Add tablet UI for FAQs and Third-party Depend…
Browse files Browse the repository at this point in the history
…encies (oppia#3671)

* Create ThirdPartyActivity

* Fix lints

* Fix actionbar issue

* Add tests

* Add KDocs

* Add LicenseListActivity to Manifest

* Fix LicenseListFragment

* Add test cases

* Add LicenseTextViewerFragment

* Pass index to LicenseListFragment

* Fix all the bugs

* Fix lints

* Add tests files for all activities and fragments

* Fix lints

* Add viewModels to BUILD.bazel

* Correct path of files in exemptions file

* Add suggested changes

* Add suggested changes

* Remove unused imports

* Correct styles in xml

* Optimize layouts

* fix lints

* Correct layout width

* Add test cases for all files

* Add an extra test case

* Add more test cases

* revert changes in ktlint_lint_check.sh

* Add suggested changes

* Add marquee effect

* Try setting text directly from fragment.

* Add code to preserve text format

* Add more test cases in LicenseTextViewerFragmentTest.kt

* Add label for LicenseTextViewerActivity

* Add suggested changes

* Use direct import for isRoot()

* Add KDocs for TestApplicationComponent in Test files

* Remove unused imports

* Correct imports order

* Fix Kdocs check

* Add suggested changes

* Add suggested changes

* Fix failing test cases

* Add interfaces to load fragments

* Remove extra Kdocs and add test files to Kdoc exemptions

* Add suggested changes

* Replace original dependencies name with dummy text

* create helplist item viewmodel

* Add support for new UIs for FAQList and ThirdPartyDependencyList in tablets

* Delete unwanted files

* Fix nits

* Add Listeners and ViewModels to BUILD.bazel

* Add test cases and add test exemptions

* Correct Bug

* Correct import

* Fix crashing after clicking item

* Add suggested changes

* Correct test case

* Hide Back arrow by default

* Correct test case

* Add TAG suffix to fragment tags

* Add suggested changes

* Add minHeight

* Add suggested changes

* Add punctuation in KDoc

* Correct name in test_file_exemptions.textproto
  • Loading branch information
prayutsu committed Aug 18, 2021
1 parent a55f808 commit 0b7ce5e
Show file tree
Hide file tree
Showing 15 changed files with 552 additions and 20 deletions.
3 changes: 3 additions & 0 deletions app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ LISTENERS = [
"src/main/java/org/oppia/android/app/devoptions/RouteToMarkTopicsCompletedListener.kt",
"src/main/java/org/oppia/android/app/devoptions/RouteToViewEventLogsListener.kt",
"src/main/java/org/oppia/android/app/drawer/RouteToProfileProgressListener.kt",
"src/main/java/org/oppia/android/app/help/LoadFaqListFragmentListener.kt",
"src/main/java/org/oppia/android/app/help/LoadThirdPartyDependencyListFragmentListener.kt",
"src/main/java/org/oppia/android/app/help/RouteToFAQListListener.kt",
"src/main/java/org/oppia/android/app/help/RouteToThirdPartyDependencyListListener.kt",
"src/main/java/org/oppia/android/app/help/faq/RouteToFAQSingleListener.kt",
Expand Down Expand Up @@ -200,6 +202,7 @@ VIEW_MODELS = [
"src/main/java/org/oppia/android/app/help/faq/faqItemViewModel/FAQHeaderViewModel.kt",
"src/main/java/org/oppia/android/app/help/faq/faqItemViewModel/FAQItemViewModel.kt",
"src/main/java/org/oppia/android/app/help/HelpItems.kt",
"src/main/java/org/oppia/android/app/help/HelpViewModel.kt",
"src/main/java/org/oppia/android/app/help/thirdparty/LicenseItemViewModel.kt",
"src/main/java/org/oppia/android/app/help/thirdparty/ThirdPartyDependencyItemViewModel.kt",
"src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionItemViewModel.kt",
Expand Down
73 changes: 71 additions & 2 deletions app/src/main/java/org/oppia/android/app/help/HelpActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,56 @@ package org.oppia.android.app.help
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.TextView
import org.oppia.android.R
import org.oppia.android.app.activity.InjectableAppCompatActivity
import org.oppia.android.app.drawer.NAVIGATION_PROFILE_ID_ARGUMENT_KEY
import org.oppia.android.app.help.faq.FAQListActivity
import org.oppia.android.app.help.faq.RouteToFAQSingleListener
import org.oppia.android.app.help.faq.faqsingle.FAQSingleActivity
import org.oppia.android.app.help.thirdparty.LicenseListActivity
import org.oppia.android.app.help.thirdparty.LicenseTextViewerActivity
import org.oppia.android.app.help.thirdparty.RouteToLicenseListListener
import org.oppia.android.app.help.thirdparty.RouteToLicenseTextListener
import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity
import javax.inject.Inject

private const val HELP_OPTIONS_TITLE_SAVED_KEY = "HelpActivity.help_options_title"
private const val SELECTED_FRAGMENT_SAVED_KEY = "HelpActivity.selected_fragment"
const val FAQ_LIST_FRAGMENT_TAG = "FAQListFragment.tag"
const val THIRD_PARTY_DEPENDENCY_LIST_FRAGMENT_TAG = "ThirdPartyDependencyListFragment.tag"

/** The help page activity for FAQs and third-party dependencies. */
class HelpActivity :
InjectableAppCompatActivity(),
RouteToFAQListListener,
RouteToThirdPartyDependencyListListener {
RouteToFAQSingleListener,
RouteToThirdPartyDependencyListListener,
RouteToLicenseTextListener,
RouteToLicenseListListener,
LoadFaqListFragmentListener,
LoadThirdPartyDependencyListFragmentListener {

@Inject
lateinit var helpActivityPresenter: HelpActivityPresenter

private lateinit var selectedFragment: String

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityComponent.inject(this)
val isFromNavigationDrawer = intent.getBooleanExtra(
BOOL_IS_FROM_NAVIGATION_DRAWER_EXTRA_KEY,
/* defaultValue= */ false
)
helpActivityPresenter.handleOnCreate(isFromNavigationDrawer)
selectedFragment =
savedInstanceState?.getString(SELECTED_FRAGMENT_SAVED_KEY) ?: FAQ_LIST_FRAGMENT_TAG
val extraHelpOptionsTitle = savedInstanceState?.getString(HELP_OPTIONS_TITLE_SAVED_KEY)
helpActivityPresenter.handleOnCreate(
extraHelpOptionsTitle,
isFromNavigationDrawer,
selectedFragment
)
title = getString(R.string.menu_help)
}

Expand Down Expand Up @@ -56,4 +82,47 @@ class HelpActivity :
val intent = ThirdPartyDependencyListActivity.createThirdPartyDependencyListActivityIntent(this)
startActivity(intent)
}

override fun loadFaqListFragment() {
selectedFragment = FAQ_LIST_FRAGMENT_TAG
helpActivityPresenter.handleLoadFAQListFragment()
}

override fun loadThirdPartyDependencyListFragment() {
selectedFragment = THIRD_PARTY_DEPENDENCY_LIST_FRAGMENT_TAG
helpActivityPresenter.handleLoadThirdPartyDependencyListFragment()
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val titleTextView = findViewById<TextView>(R.id.help_multipane_options_title_textview)
if (titleTextView != null) {
outState.putString(HELP_OPTIONS_TITLE_SAVED_KEY, titleTextView.text.toString())
}
outState.putString(SELECTED_FRAGMENT_SAVED_KEY, selectedFragment)
}

override fun onRouteToLicenseText(dependencyIndex: Int, licenseIndex: Int) {
startActivity(
LicenseTextViewerActivity.createLicenseTextViewerActivityIntent(
this,
dependencyIndex,
licenseIndex
)
)
}

override fun onRouteToLicenseList(dependencyIndex: Int) {
startActivity(
LicenseListActivity
.createLicenseListActivityIntent(
context = this,
dependencyIndex = dependencyIndex
)
)
}

override fun onRouteToFAQSingle(question: String, answer: String) {
startActivity(FAQSingleActivity.createFAQSingleActivityIntent(this, question, answer))
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package org.oppia.android.app.help

import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityScope
import org.oppia.android.app.drawer.NavigationDrawerFragment
import org.oppia.android.app.help.faq.FAQListFragment
import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListFragment
import javax.inject.Inject

/** The presenter for [HelpActivity]. */
Expand All @@ -15,7 +20,11 @@ class HelpActivityPresenter @Inject constructor(private val activity: AppCompatA
private lateinit var navigationDrawerFragment: NavigationDrawerFragment
private lateinit var toolbar: Toolbar

fun handleOnCreate(isFromNavigationDrawer: Boolean) {
fun handleOnCreate(
extraHelpOptionsTitle: String?,
isFromNavigationDrawer: Boolean,
selectedFragment: String
) {
if (isFromNavigationDrawer) {
activity.setContentView(R.layout.help_activity)
setUpToolbar()
Expand All @@ -28,12 +37,53 @@ class HelpActivityPresenter @Inject constructor(private val activity: AppCompatA
activity.finish()
}
}
if (getHelpFragment() == null) {
activity.supportFragmentManager.beginTransaction().add(
R.id.help_fragment_placeholder,
HelpFragment()
).commitNow()
val titleTextView =
activity.findViewById<TextView>(R.id.options_activity_selected_options_title)
if (titleTextView != null) {
setMultipaneContainerTitle(extraHelpOptionsTitle!!)
}
val isMultipane = activity.findViewById<FrameLayout>(R.id.multipane_options_container) != null
if (isMultipane) {
loadMultipaneFragment(selectedFragment)
}
val previousFragment = getHelpFragment()
if (previousFragment != null) {
activity.supportFragmentManager.beginTransaction().remove(previousFragment).commitNow()
}
activity.supportFragmentManager.beginTransaction().add(
R.id.help_fragment_placeholder,
HelpFragment.newInstance(isMultipane)
).commitNow()
}

/** Loads [ThirdPartyDependencyListFragment] in tablet devices. */
fun handleLoadThirdPartyDependencyListFragment() {
setMultipaneContainerTitle(
activity.getString(R.string.third_party_dependency_list_activity_title)
)
getMultipaneOptionsFragment()?.let {
activity.supportFragmentManager.beginTransaction().remove(
it
).commit()
}
val thirdPartyDependencyListFragment = ThirdPartyDependencyListFragment.newInstance()
activity.supportFragmentManager.beginTransaction().add(
R.id.multipane_options_container,
thirdPartyDependencyListFragment
).commitNow()
}

/** Loads [FAQListFragment] in tablet devices. */
fun handleLoadFAQListFragment() {
setMultipaneContainerTitle(activity.getString(R.string.faq_activity_title))
getMultipaneOptionsFragment()?.let {
activity.supportFragmentManager.beginTransaction().remove(it)
.commit()
}
activity.supportFragmentManager.beginTransaction().add(
R.id.multipane_options_container,
FAQListFragment()
).commitNow()
}

private fun setUpToolbar() {
Expand All @@ -59,4 +109,19 @@ class HelpActivityPresenter @Inject constructor(private val activity: AppCompatA
.supportFragmentManager
.findFragmentById(R.id.help_fragment_placeholder) as HelpFragment?
}

private fun loadMultipaneFragment(selectedFragment: String) {
when (selectedFragment) {
FAQ_LIST_FRAGMENT_TAG -> handleLoadFAQListFragment()
THIRD_PARTY_DEPENDENCY_LIST_FRAGMENT_TAG -> handleLoadThirdPartyDependencyListFragment()
}
}

private fun setMultipaneContainerTitle(title: String) {
activity.findViewById<TextView>(R.id.help_multipane_options_title_textview).text = title
}

private fun getMultipaneOptionsFragment(): Fragment? {
return activity.supportFragmentManager.findFragmentById(R.id.multipane_options_container)
}
}
19 changes: 18 additions & 1 deletion app/src/main/java/org/oppia/android/app/help/HelpFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,24 @@ import android.view.ViewGroup
import org.oppia.android.app.fragment.InjectableFragment
import javax.inject.Inject

private const val IS_MULTIPANE_KEY = "HelpFragment.bool_is_multipane"

/** Fragment that contains help in the app. */
class HelpFragment : InjectableFragment() {
@Inject
lateinit var helpFragmentPresenter: HelpFragmentPresenter

companion object {
/** Returns instance of [HelpFragment]. */
fun newInstance(isMultipane: Boolean): HelpFragment {
val args = Bundle()
args.putBoolean(IS_MULTIPANE_KEY, isMultipane)
val fragment = HelpFragment()
fragment.arguments = args
return fragment
}
}

override fun onAttach(context: Context) {
super.onAttach(context)
fragmentComponent.inject(this)
Expand All @@ -23,6 +36,10 @@ class HelpFragment : InjectableFragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return helpFragmentPresenter.handleCreateView(inflater, container)
val args = checkNotNull(arguments) {
"Expected arguments to be passed to HelpFragment"
}
val isMultipane = args.getBoolean(IS_MULTIPANE_KEY)
return helpFragmentPresenter.handleCreateView(inflater, container, isMultipane)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ class HelpFragmentPresenter @Inject constructor(
) {
private lateinit var binding: HelpFragmentBinding

fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
fun handleCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
isMultipane: Boolean
): View? {
val viewModel = getHelpListViewModel()
viewModel.isMultipane.set(isMultipane)

binding = HelpFragmentBinding.inflate(
inflater,
Expand Down
24 changes: 18 additions & 6 deletions app/src/main/java/org/oppia/android/app/help/HelpItemViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,30 @@ import org.oppia.android.app.viewmodel.ObservableViewModel
/** [ObservableViewModel] for the recycler view of HelpActivity. */
class HelpItemViewModel(
val activity: AppCompatActivity,
val title: String
val title: String,
val isMultipane: Boolean
) : ObservableViewModel() {
fun onClick(title: String) {
when (title) {
activity.getString(R.string.frequently_asked_questions_FAQ) -> {
val routeToFAQListener = activity as RouteToFAQListListener
routeToFAQListener.onRouteToFAQList()
if (isMultipane) {
val loadFaqListFragmentListener = activity as LoadFaqListFragmentListener
loadFaqListFragmentListener.loadFaqListFragment()
} else {
val routeToFAQListener = activity as RouteToFAQListListener
routeToFAQListener.onRouteToFAQList()
}
}
activity.getString(R.string.third_party_dependency_list_activity_title) -> {
val routeToThirdPartyDependencyListListener = activity
as RouteToThirdPartyDependencyListListener
routeToThirdPartyDependencyListListener.onRouteToThirdPartyDependencyList()
if (isMultipane) {
val loadThirdPartyDependencyListFragmentListener = activity as
LoadThirdPartyDependencyListFragmentListener
loadThirdPartyDependencyListFragmentListener.loadThirdPartyDependencyListFragment()
} else {
val routeToThirdPartyDependencyListListener = activity
as RouteToThirdPartyDependencyListListener
routeToThirdPartyDependencyListListener.onRouteToThirdPartyDependencyList()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ package org.oppia.android.app.help

import androidx.appcompat.app.AppCompatActivity
import org.oppia.android.R
import org.oppia.android.app.viewmodel.ObservableViewModel
import javax.inject.Inject

/** View model in [HelpFragment]. */
class HelpListViewModel @Inject constructor(
val activity: AppCompatActivity
) : ObservableViewModel() {
) : HelpViewModel() {
private val arrayList = ArrayList<HelpItemViewModel>()

val helpItemList: List<HelpItemViewModel> by lazy {
Expand All @@ -22,11 +21,11 @@ class HelpListViewModel @Inject constructor(
when (item) {
HelpItems.FAQ -> {
category = activity.getString(R.string.frequently_asked_questions_FAQ)
helpItemViewModel = HelpItemViewModel(activity, category)
helpItemViewModel = HelpItemViewModel(activity, category, isMultipane.get()!!)
}
HelpItems.THIRD_PARTY -> {
category = activity.getString(R.string.third_party_dependency_list_activity_title)
helpItemViewModel = HelpItemViewModel(activity, category)
helpItemViewModel = HelpItemViewModel(activity, category, isMultipane.get()!!)
}
}
arrayList.add(helpItemViewModel)
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/org/oppia/android/app/help/HelpViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.oppia.android.app.help

import androidx.databinding.ObservableField
import org.oppia.android.app.viewmodel.ObservableViewModel

/** Option items view model for the recyclerView in [HelpFragment]. */
abstract class HelpViewModel : ObservableViewModel() {
/** Indicates whether the device in use has a large screen & should be multi-pane. */
val isMultipane = ObservableField<Boolean>(false)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.oppia.android.app.help

/** Listener for when a selection should result to [FAQListFragment] in tablet devices. */
interface LoadFaqListFragmentListener {
/** Called when the user wants to open the list of FAQs in tablet devices. */
fun loadFaqListFragment()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.oppia.android.app.help

/**
* Listener for when a selection should result to [ThirdPartyDependencyListFragment] in tablet
* devices.
*/
interface LoadThirdPartyDependencyListFragmentListener {
/** Called when the user wants to open the list of third-party dependencies in tablet devices. */
fun loadThirdPartyDependencyListFragment()
}
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/ic_arrow_back_black_24_dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<vector
xmlns:android="http:https://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:autoMirrored="true"
android:viewportHeight="24.0">
<path
android:fillColor="#333333"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
Loading

0 comments on commit 0b7ce5e

Please sign in to comment.