Skip to content

Commit 60c7e13

Browse files
refactor: dynamic main menu
1 parent 17a464f commit 60c7e13

File tree

13 files changed

+126
-123
lines changed

13 files changed

+126
-123
lines changed

app/src/main/java/org/openedx/app/MainFragment.kt

Lines changed: 72 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.openedx.app
22

33
import android.os.Bundle
4+
import android.view.Menu
45
import android.view.View
56
import androidx.core.os.bundleOf
67
import androidx.core.view.forEach
@@ -41,33 +42,69 @@ class MainFragment : Fragment(R.layout.fragment_main) {
4142

4243
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
4344
super.onViewCreated(view, savedInstanceState)
44-
if (!viewModel.isDownloadsFragmentEnabled) {
45-
binding.bottomNavView.menu.removeItem(R.id.fragmentDownloads)
45+
46+
requireArguments().apply {
47+
getString(ARG_COURSE_ID).takeIf { it.isNullOrBlank().not() }?.let { courseId ->
48+
val infoType = getString(ARG_INFO_TYPE)
49+
if (viewModel.isDiscoveryTypeWebView && infoType != null) {
50+
router.navigateToCourseInfo(parentFragmentManager, courseId, infoType)
51+
} else {
52+
router.navigateToCourseDetail(parentFragmentManager, courseId)
53+
}
54+
putString(ARG_COURSE_ID, "")
55+
putString(ARG_INFO_TYPE, "")
56+
}
4657
}
4758

48-
initViewPager()
59+
val openTabArg = requireArguments().getString(ARG_OPEN_TAB, HomeTab.LEARN.name)
60+
val learnFragment = LearnFragment.newInstance(
61+
openTab = if (openTabArg == HomeTab.PROGRAMS.name) {
62+
LearnTab.PROGRAMS.name
63+
} else {
64+
LearnTab.COURSES.name
65+
}
66+
)
67+
val tabList = mutableListOf<Pair<Int, Fragment>>().apply {
68+
add(R.id.fragmentLearn to learnFragment)
69+
add(R.id.fragmentDiscover to viewModel.getDiscoveryFragment)
70+
if (viewModel.isDownloadsFragmentEnabled) {
71+
add(R.id.fragmentDownloads to DownloadsFragment())
72+
}
73+
add(R.id.fragmentProfile to ProfileFragment())
74+
}
4975

50-
binding.bottomNavView.setOnItemSelectedListener {
51-
when (it.itemId) {
52-
R.id.fragmentLearn -> {
53-
viewModel.logLearnTabClickedEvent()
54-
binding.viewPager.setCurrentItem(0, false)
55-
}
76+
val menu = binding.bottomNavView.menu
77+
menu.clear()
78+
val tabTitles = mapOf(
79+
R.id.fragmentLearn to resources.getString(R.string.app_navigation_learn),
80+
R.id.fragmentDiscover to resources.getString(R.string.app_navigation_discovery),
81+
R.id.fragmentDownloads to resources.getString(R.string.app_navigation_downloads),
82+
R.id.fragmentProfile to resources.getString(R.string.app_navigation_profile),
83+
)
84+
val tabIcons = mapOf(
85+
R.id.fragmentLearn to R.drawable.app_ic_rows,
86+
R.id.fragmentDiscover to R.drawable.app_ic_home,
87+
R.id.fragmentDownloads to R.drawable.app_ic_download_cloud,
88+
R.id.fragmentProfile to R.drawable.app_ic_profile
89+
)
90+
for ((id, _) in tabList) {
91+
val menuItem = menu.add(Menu.NONE, id, Menu.NONE, tabTitles[id] ?: "")
92+
tabIcons[id]?.let { menuItem.setIcon(it) }
93+
}
5694

57-
R.id.fragmentDiscover -> {
58-
viewModel.logDiscoveryTabClickedEvent()
59-
binding.viewPager.setCurrentItem(1, false)
60-
}
95+
initViewPager(tabList)
6196

62-
R.id.fragmentDownloads -> {
63-
viewModel.logDownloadsTabClickedEvent()
64-
binding.viewPager.setCurrentItem(2, false)
65-
}
97+
val menuIdToIndex = tabList.mapIndexed { index, pair -> pair.first to index }.toMap()
6698

67-
R.id.fragmentProfile -> {
68-
viewModel.logProfileTabClickedEvent()
69-
binding.viewPager.setCurrentItem(3, false)
70-
}
99+
binding.bottomNavView.setOnItemSelectedListener { menuItem ->
100+
when (menuItem.itemId) {
101+
R.id.fragmentLearn -> viewModel.logLearnTabClickedEvent()
102+
R.id.fragmentDiscover -> viewModel.logDiscoveryTabClickedEvent()
103+
R.id.fragmentDownloads -> viewModel.logDownloadsTabClickedEvent()
104+
R.id.fragmentProfile -> viewModel.logProfileTabClickedEvent()
105+
}
106+
menuIdToIndex[menuItem.itemId]?.let { index ->
107+
binding.viewPager.setCurrentItem(index, false)
71108
}
72109
true
73110
}
@@ -84,59 +121,27 @@ class MainFragment : Fragment(R.layout.fragment_main) {
84121
}
85122
}
86123

87-
requireArguments().apply {
88-
getString(ARG_COURSE_ID).takeIf { it.isNullOrBlank().not() }?.let { courseId ->
89-
val infoType = getString(ARG_INFO_TYPE)
90-
91-
if (viewModel.isDiscoveryTypeWebView && infoType != null) {
92-
router.navigateToCourseInfo(parentFragmentManager, courseId, infoType)
93-
} else {
94-
router.navigateToCourseDetail(parentFragmentManager, courseId)
95-
}
96-
97-
// Clear arguments after navigation
98-
putString(ARG_COURSE_ID, "")
99-
putString(ARG_INFO_TYPE, "")
100-
}
101-
102-
when (requireArguments().getString(ARG_OPEN_TAB, "")) {
103-
HomeTab.LEARN.name,
104-
HomeTab.PROGRAMS.name -> {
105-
binding.bottomNavView.selectedItemId = R.id.fragmentLearn
106-
}
107-
108-
HomeTab.DISCOVER.name -> {
109-
binding.bottomNavView.selectedItemId = R.id.fragmentDiscover
110-
}
111-
112-
HomeTab.DOWNLOADS.name -> {
113-
binding.bottomNavView.selectedItemId = R.id.fragmentDownloads
114-
}
115-
116-
HomeTab.PROFILE.name -> {
117-
binding.bottomNavView.selectedItemId = R.id.fragmentProfile
118-
}
119-
}
120-
requireArguments().remove(ARG_OPEN_TAB)
124+
val initialMenuId = when (openTabArg) {
125+
HomeTab.LEARN.name, HomeTab.PROGRAMS.name -> R.id.fragmentLearn
126+
HomeTab.DISCOVER.name -> R.id.fragmentDiscover
127+
HomeTab.DOWNLOADS.name -> if (viewModel.isDownloadsFragmentEnabled) R.id.fragmentDownloads else R.id.fragmentLearn
128+
HomeTab.PROFILE.name -> R.id.fragmentProfile
129+
else -> R.id.fragmentLearn
121130
}
131+
binding.bottomNavView.selectedItemId = initialMenuId
132+
133+
requireArguments().remove(ARG_OPEN_TAB)
122134
}
123135

124136
@Suppress("MagicNumber")
125-
private fun initViewPager() {
137+
private fun initViewPager(tabList: List<Pair<Int, Fragment>>) {
126138
binding.viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
127-
binding.viewPager.offscreenPageLimit = 4
139+
binding.viewPager.offscreenPageLimit = tabList.size
128140

129-
val openTab = requireArguments().getString(ARG_OPEN_TAB, HomeTab.LEARN.name)
130-
val learnTab = if (openTab == HomeTab.PROGRAMS.name) {
131-
LearnTab.PROGRAMS
132-
} else {
133-
LearnTab.COURSES
134-
}
135141
adapter = NavigationFragmentAdapter(this).apply {
136-
addFragment(LearnFragment.newInstance(openTab = learnTab.name))
137-
addFragment(viewModel.getDiscoveryFragment)
138-
addFragment(DownloadsFragment())
139-
addFragment(ProfileFragment())
142+
tabList.forEach { (_, fragment) ->
143+
addFragment(fragment)
144+
}
140145
}
141146
binding.viewPager.adapter = adapter
142147
binding.viewPager.isUserInputEnabled = false

app/src/main/java/org/openedx/app/di/ScreenModule.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import org.openedx.auth.presentation.signin.SignInViewModel
1313
import org.openedx.auth.presentation.signup.SignUpViewModel
1414
import org.openedx.core.Validator
1515
import org.openedx.core.domain.interactor.CalendarInteractor
16-
import org.openedx.core.domain.interactor.ICourseInteractor
1716
import org.openedx.core.presentation.dialog.selectorbottomsheet.SelectDialogViewModel
1817
import org.openedx.core.presentation.settings.video.VideoQualityViewModel
1918
import org.openedx.core.repository.CalendarRepository
@@ -233,7 +232,7 @@ val screenModule = module {
233232

234233
single { CourseRepository(get(), get(), get(), get(), get()) }
235234
factory { CourseInteractor(get()) }
236-
single<ICourseInteractor> { get<CourseInteractor>() }
235+
single<org.openedx.core.domain.interactor.CourseInteractor> { get<CourseInteractor>() }
237236

238237
viewModel { (pathId: String, infoType: String) ->
239238
CourseInfoViewModel(
@@ -497,11 +496,6 @@ val screenModule = module {
497496
)
498497
}
499498

500-
single {
501-
DownloadInteractor(
502-
repository = get()
503-
)
504-
}
505499
single {
506500
DownloadRepository(
507501
api = get(),
@@ -510,6 +504,11 @@ val screenModule = module {
510504
courseDao = get()
511505
)
512506
}
507+
single {
508+
DownloadInteractor(
509+
repository = get()
510+
)
511+
}
513512
viewModel {
514513
DownloadsViewModel(
515514
downloadsRouter = get(),
File renamed without changes.

app/src/main/res/layout/fragment_main.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
app:layout_constraintBottom_toBottomOf="parent"
2626
app:layout_constraintEnd_toEndOf="parent"
2727
app:layout_constraintHorizontal_bias="0.5"
28-
app:layout_constraintStart_toStartOf="parent"
29-
app:menu="@menu/bottom_view_menu" />
28+
app:layout_constraintStart_toStartOf="parent" />
3029

3130
</androidx.constraintlayout.widget.ConstraintLayout>

app/src/main/res/menu/bottom_view_menu.xml

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<item type="id" name="fragmentLearn" />
4+
<item type="id" name="fragmentDiscover" />
5+
<item type="id" name="fragmentDownloads" />
6+
<item type="id" name="fragmentProfile" />
7+
</resources>

core/src/main/java/org/openedx/core/domain/interactor/ICourseInteractor.kt renamed to core/src/main/java/org/openedx/core/domain/interactor/CourseInteractor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package org.openedx.core.domain.interactor
33
import org.openedx.core.domain.model.CourseStructure
44
import org.openedx.core.module.db.DownloadModel
55

6-
interface ICourseInteractor {
6+
interface CourseInteractor {
77
suspend fun getCourseStructure(
88
courseId: String,
99
isNeedRefresh: Boolean = false
@@ -12,4 +12,4 @@ interface ICourseInteractor {
1212
suspend fun getCourseStructureFromCache(courseId: String): CourseStructure
1313

1414
suspend fun getAllDownloadModels(): List<DownloadModel>
15-
}
15+
}

core/src/main/java/org/openedx/core/presentation/dialog/downloaddialog/DownloadDialogManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
77
import kotlinx.coroutines.launch
88
import org.openedx.core.BlockType
99
import org.openedx.core.data.storage.CorePreferences
10-
import org.openedx.core.domain.interactor.ICourseInteractor
10+
import org.openedx.core.domain.interactor.CourseInteractor
1111
import org.openedx.core.domain.model.Block
1212
import org.openedx.core.module.DownloadWorkerController
1313
import org.openedx.core.module.db.DownloadModel
@@ -17,7 +17,7 @@ import org.openedx.core.system.connection.NetworkConnection
1717
class DownloadDialogManager(
1818
private val networkConnection: NetworkConnection,
1919
private val corePreferences: CorePreferences,
20-
private val interactor: ICourseInteractor,
20+
private val interactor: CourseInteractor,
2121
private val workerController: DownloadWorkerController
2222
) {
2323

course/src/main/java/org/openedx/course/domain/interactor/CourseInteractor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package org.openedx.course.domain.interactor
22

33
import kotlinx.coroutines.flow.Flow
44
import org.openedx.core.BlockType
5-
import org.openedx.core.domain.interactor.ICourseInteractor
5+
import org.openedx.core.domain.interactor.CourseInteractor
66
import org.openedx.core.domain.model.Block
77
import org.openedx.core.domain.model.CourseEnrollmentDetails
88
import org.openedx.core.domain.model.CourseStructure
@@ -11,7 +11,7 @@ import org.openedx.course.data.repository.CourseRepository
1111
@Suppress("TooManyFunctions")
1212
class CourseInteractor(
1313
private val repository: CourseRepository
14-
) : ICourseInteractor {
14+
) : CourseInteractor {
1515

1616
suspend fun getCourseStructureFlow(
1717
courseId: String,

course/src/main/java/org/openedx/course/presentation/ui/CourseVideosUI.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ fun CourseVideosScreen(
140140
viewModel.removeAllDownloadModels()
141141
} else {
142142
viewModel.saveAllDownloadModels(
143-
fileUtil.getExternalAppDir().path, viewModel.courseId
143+
fileUtil.getExternalAppDir().path,
144+
viewModel.courseId
144145
)
145146
}
146147
},

0 commit comments

Comments
 (0)