Skip to content

Commit 04c3eaa

Browse files
committed
add setting to show nav bar at the bottom
1 parent 77e76ef commit 04c3eaa

File tree

35 files changed

+100
-3
lines changed

35 files changed

+100
-3
lines changed

core/src/main/java/com/example/util/simpletimetracker/core/viewData/SettingsBlock.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum class SettingsBlock {
4949
DisplayEnablePomodoroMode,
5050
DisplayPomodoroModeActivities,
5151
DisplayGoalsOnSeparateTabs,
52+
DisplayNavBarAtTheBottom,
5253
DisplayKeepScreenOn,
5354
DisplayWidgetBackground,
5455
DisplayMilitaryFormat,

data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/PrefsRepoImpl.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ class PrefsRepoImpl @Inject constructor(
290290
KEY_DEFAULT_TYPES_HIDDEN, false,
291291
)
292292

293+
override var isNavBarAtTheBottom: Boolean by prefs.delegate(
294+
KEY_IS_NAV_BAR_AT_THE_BOTTOM, false,
295+
)
296+
293297
override fun setWidget(widgetId: Int, recordType: Long) {
294298
val key = KEY_WIDGET + widgetId
295299
logPrefsDataAccess("set $key")
@@ -556,6 +560,7 @@ class PrefsRepoImpl @Inject constructor(
556560
private const val KEY_REPEAT_BUTTON_TYPE = "repeatButtonType"
557561
private const val KEY_WIDGET_TRANSPARENCY_PERCENT = "widgetTransparencyPercent"
558562
private const val KEY_DEFAULT_TYPES_HIDDEN = "defaultTypesHidden"
563+
private const val KEY_IS_NAV_BAR_AT_THE_BOTTOM = "isNavBarAtTheBottom"
559564
private const val KEY_WIDGET = "widget_"
560565
private const val KEY_STATISTICS_WIDGET_FILTERED_TYPES = "statistics_widget_filtered_types_"
561566
private const val KEY_STATISTICS_WIDGET_FILTERED_CATEGORIES = "statistics_widget_filtered_categories_"

domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/PrefsInteractor.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,14 @@ class PrefsInteractor @Inject constructor(
667667
prefsRepo.defaultTypesHidden = value
668668
}
669669

670+
suspend fun getIsNavBarAtTheBottom(): Boolean = withContext(Dispatchers.IO) {
671+
prefsRepo.isNavBarAtTheBottom
672+
}
673+
674+
suspend fun setIsNavBarAtTheBottom(value: Boolean) = withContext(Dispatchers.IO) {
675+
prefsRepo.isNavBarAtTheBottom = value
676+
}
677+
670678
suspend fun clear() = withContext(Dispatchers.IO) {
671679
prefsRepo.clear()
672680
}

domain/src/main/java/com/example/util/simpletimetracker/domain/repo/PrefsRepo.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ interface PrefsRepo {
133133

134134
var defaultTypesHidden: Boolean
135135

136+
var isNavBarAtTheBottom: Boolean
137+
136138
fun setWidget(widgetId: Int, recordType: Long)
137139

138140
fun getWidget(widgetId: Int): Long

features/feature_main/src/main/java/com/example/util/simpletimetracker/feature_main/view/MainFragment.kt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.view.LayoutInflater
55
import android.view.ViewGroup
66
import androidx.activity.OnBackPressedCallback
77
import androidx.annotation.AttrRes
8+
import androidx.constraintlayout.widget.ConstraintSet
89
import androidx.core.graphics.BlendModeColorFilterCompat
910
import androidx.core.graphics.BlendModeCompat
1011
import androidx.fragment.app.activityViewModels
@@ -17,11 +18,11 @@ import com.example.util.simpletimetracker.core.sharedViewModel.MainTabsViewModel
1718
import com.example.util.simpletimetracker.core.utils.SHORTCUT_NAVIGATION_KEY
1819
import com.example.util.simpletimetracker.core.view.SafeFragmentStateAdapter
1920
import com.example.util.simpletimetracker.domain.extension.orZero
20-
import com.example.util.simpletimetracker.feature_views.extension.getThemedAttr
2121
import com.example.util.simpletimetracker.feature_main.R
2222
import com.example.util.simpletimetracker.feature_main.adapter.MainContentAdapter
2323
import com.example.util.simpletimetracker.feature_main.provider.MainTabsProvider
2424
import com.example.util.simpletimetracker.feature_main.viewModel.MainViewModel
25+
import com.example.util.simpletimetracker.feature_views.extension.getThemedAttr
2526
import com.google.android.material.tabs.TabLayout
2627
import com.google.android.material.tabs.TabLayoutMediator
2728
import dagger.hilt.android.AndroidEntryPoint
@@ -61,6 +62,7 @@ class MainFragment : BaseFragment<Binding>() {
6162

6263
override fun initViewModel() {
6364
viewModel.initialize
65+
viewModel.isNavBatAtTheBottom.observe(::updateNavBarPosition)
6466
}
6567

6668
private fun setupPager() = with(binding) {
@@ -107,6 +109,29 @@ class MainFragment : BaseFragment<Binding>() {
107109
mainPager.setCurrentItem(mainPagePosition, false)
108110
}
109111

112+
private fun updateNavBarPosition(isAtTheBottom: Boolean) = with(binding) {
113+
val set = ConstraintSet()
114+
set.clone(binding.containerMain)
115+
if (isAtTheBottom) {
116+
set.clear(R.id.mainTabs, ConstraintSet.TOP)
117+
set.connect(R.id.mainTabs, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
118+
set.connect(R.id.mainPager, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
119+
set.connect(R.id.mainPager, ConstraintSet.BOTTOM, R.id.mainTabs, ConstraintSet.TOP)
120+
} else {
121+
set.clear(R.id.mainTabs, ConstraintSet.BOTTOM)
122+
set.connect(R.id.mainTabs, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
123+
set.connect(R.id.mainPager, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
124+
set.connect(R.id.mainPager, ConstraintSet.TOP, R.id.mainTabs, ConstraintSet.BOTTOM)
125+
}
126+
set.applyTo(binding.containerMain)
127+
128+
if (isAtTheBottom) {
129+
TabLayout.INDICATOR_GRAVITY_TOP
130+
} else {
131+
TabLayout.INDICATOR_GRAVITY_BOTTOM
132+
}.let(mainTabs::setSelectedTabIndicatorGravity)
133+
}
134+
110135
private fun getOnBackPressedCallback(): OnBackPressedCallback {
111136
return object : OnBackPressedCallback(false) {
112137
override fun handleOnBackPressed() {

features/feature_main/src/main/java/com/example/util/simpletimetracker/feature_main/viewModel/MainViewModel.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.example.util.simpletimetracker.feature_main.viewModel
22

3-
import androidx.lifecycle.ViewModel
3+
import androidx.lifecycle.LiveData
44
import androidx.lifecycle.viewModelScope
5+
import com.example.util.simpletimetracker.core.base.BaseViewModel
6+
import com.example.util.simpletimetracker.core.extension.lazySuspend
57
import com.example.util.simpletimetracker.domain.interactor.NotificationTypeInteractor
8+
import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor
69
import com.example.util.simpletimetracker.domain.interactor.WearInteractor
710
import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor
811
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -14,9 +17,11 @@ class MainViewModel @Inject constructor(
1417
private val notificationTypeInteractor: NotificationTypeInteractor,
1518
private val widgetInteractor: WidgetInteractor,
1619
private val wearInteractor: WearInteractor,
17-
) : ViewModel() {
20+
private val prefsInteractor: PrefsInteractor,
21+
) : BaseViewModel() {
1822

1923
val initialize: Unit by lazy { syncState() }
24+
val isNavBatAtTheBottom: LiveData<Boolean> by lazySuspend { loadIsNavBatAtTheBottom() }
2025

2126
private fun syncState() {
2227
viewModelScope.launch {
@@ -25,4 +30,8 @@ class MainViewModel @Inject constructor(
2530
wearInteractor.update()
2631
}
2732
}
33+
34+
private suspend fun loadIsNavBatAtTheBottom(): Boolean {
35+
return prefsInteractor.getIsNavBarAtTheBottom()
36+
}
2837
}

features/feature_main/src/main/res/layout/main_fragment.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:id="@+id/containerMain"
45
android:layout_width="match_parent"
56
android:layout_height="match_parent">
67

@@ -12,10 +13,12 @@
1213
app:tabIndicatorColor="?appTabSelectedColor"
1314
app:tabRippleColor="@color/tab_ripple" />
1415

16+
<!-- Small margin is added to prevent shared transition going under new screen -->
1517
<androidx.viewpager2.widget.ViewPager2
1618
android:id="@+id/mainPager"
1719
android:layout_width="match_parent"
1820
android:layout_height="0dp"
21+
android:layout_marginTop="0.1dp"
1922
app:layout_constraintBottom_toBottomOf="parent"
2023
app:layout_constraintTop_toBottomOf="@id/mainTabs" />
2124

features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/interactor/SettingsDisplayViewDataInteractor.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ class SettingsDisplayViewDataInteractor @Inject constructor(
156156
bottomSpaceIsVisible = true,
157157
dividerIsVisible = true,
158158
)
159+
result += SettingsCheckboxViewData(
160+
block = SettingsBlock.DisplayNavBarAtTheBottom,
161+
title = resourceRepo.getString(R.string.settings_show_nav_bar_at_the_bottom),
162+
subtitle = "",
163+
isChecked = prefsInteractor.getIsNavBarAtTheBottom(),
164+
bottomSpaceIsVisible = true,
165+
dividerIsVisible = true,
166+
)
159167
result += SettingsCheckboxViewData(
160168
block = SettingsBlock.DisplayKeepScreenOn,
161169
title = resourceRepo.getString(R.string.settings_keep_screen_on),

features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/SettingsViewModel.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ class SettingsViewModel @Inject constructor(
179179
displayDelegate.onAllowMultipleActivityFiltersClicked()
180180
SettingsBlock.DisplayGoalsOnSeparateTabs ->
181181
displayDelegate.onShowGoalsSeparatelyClicked()
182+
SettingsBlock.DisplayNavBarAtTheBottom ->
183+
displayDelegate.onShowNavBarAtTheBottomClicked()
182184
SettingsBlock.DisplayKeepScreenOn ->
183185
displayDelegate.onKeepScreenOnClicked()
184186
SettingsBlock.DisplayMilitaryFormat ->

features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/delegate/SettingsDisplayViewModelDelegate.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,15 @@ class SettingsDisplayViewModelDelegate @Inject constructor(
253253
}
254254
}
255255

256+
fun onShowNavBarAtTheBottomClicked() {
257+
delegateScope.launch {
258+
val newValue = !prefsInteractor.getIsNavBarAtTheBottom()
259+
prefsInteractor.setIsNavBarAtTheBottom(newValue)
260+
parent?.updateContent()
261+
router.restartApp()
262+
}
263+
}
264+
256265
fun onUseMilitaryTimeClicked() {
257266
delegateScope.launch {
258267
val newValue = !prefsInteractor.getUseMilitaryTimeFormat()

0 commit comments

Comments
 (0)