@@ -2,28 +2,48 @@ package ui
2
2
3
3
import androidx.compose.foundation.layout.PaddingValues
4
4
import androidx.compose.foundation.layout.fillMaxSize
5
+ import androidx.compose.foundation.layout.padding
6
+ import androidx.compose.material.icons.Icons
7
+ import androidx.compose.material.icons.rounded.Add
8
+ import androidx.compose.material3.ExperimentalMaterial3Api
9
+ import androidx.compose.material3.FloatingActionButton
10
+ import androidx.compose.material3.Icon
11
+ import androidx.compose.material3.Scaffold
12
+ import androidx.compose.material3.Text
13
+ import androidx.compose.material3.TopAppBar
5
14
import androidx.compose.runtime.Composable
6
15
import androidx.compose.runtime.getValue
16
+ import androidx.compose.runtime.mutableStateOf
17
+ import androidx.compose.runtime.remember
18
+ import androidx.compose.runtime.setValue
7
19
import androidx.compose.ui.Modifier
8
20
import androidx.compose.ui.unit.dp
9
21
import androidx.navigation.compose.NavHost
10
22
import androidx.navigation.compose.composable
23
+ import androidx.navigation.compose.currentBackStackEntryAsState
11
24
import androidx.navigation.compose.rememberNavController
12
25
import data.EditExpensePane
13
26
import data.EditExpensePane.Companion.getArgExpenseId
14
27
import data.HomePane
15
28
import data.SettingsPane
16
29
import data.UpcomingPane
17
30
import model.database.UserPreferencesRepository
31
+ import org.jetbrains.compose.resources.stringResource
18
32
import org.koin.compose.KoinContext
19
33
import org.koin.compose.koinInject
20
34
import org.koin.compose.viewmodel.koinViewModel
35
+ import recurringexpensetracker.app.generated.resources.Res
36
+ import recurringexpensetracker.app.generated.resources.edit_expense_button_add
37
+ import recurringexpensetracker.app.generated.resources.home_title
38
+ import recurringexpensetracker.app.generated.resources.upcoming_title
21
39
import toCurrencyString
22
40
import ui.editexpense.EditRecurringExpenseScreen
23
41
import ui.upcomingexpenses.UpcomingPaymentsScreen
42
+ import viewmodel.MainNavigationViewModel
24
43
import viewmodel.RecurringExpenseViewModel
25
44
import viewmodel.UpcomingPaymentsViewModel
26
45
46
+ @OptIn(ExperimentalMaterial3Api ::class )
27
47
@Suppress(" ktlint:compose:vm-forwarding-check" )
28
48
@Composable
29
49
fun MainContent (
@@ -41,88 +61,165 @@ fun MainContent(
41
61
updateWidget : () -> Unit ,
42
62
modifier : Modifier = Modifier ,
43
63
startRoute : String = HomePane .ROUTE ,
64
+ mainNavigationViewModel : MainNavigationViewModel = koinViewModel<MainNavigationViewModel >(),
44
65
recurringExpenseViewModel : RecurringExpenseViewModel = koinViewModel<RecurringExpenseViewModel >(),
45
66
upcomingPaymentsViewModel : UpcomingPaymentsViewModel = koinViewModel<UpcomingPaymentsViewModel >(),
46
67
userPreferencesRepository : UserPreferencesRepository = koinInject(),
47
68
) {
48
69
val navController = rememberNavController()
70
+ val backStackEntry = navController.currentBackStackEntryAsState()
49
71
val currencyCode by userPreferencesRepository.defaultCurrency.collectAsState()
50
72
51
73
KoinContext {
52
- NavHost (
53
- navController = navController,
54
- startDestination = startRoute,
55
- modifier = modifier.fillMaxSize(),
56
- ) {
57
- composable(HomePane .ROUTE ) {
58
- val weeklyExpense =
59
- recurringExpenseViewModel.currencyPrefix +
60
- recurringExpenseViewModel.weeklyExpense.toCurrencyString(currencyCode)
61
- val monthlyExpense =
62
- recurringExpenseViewModel.currencyPrefix +
63
- recurringExpenseViewModel.monthlyExpense.toCurrencyString(currencyCode)
64
- val yearlyExpense =
65
- recurringExpenseViewModel.currencyPrefix +
66
- recurringExpenseViewModel.yearlyExpense.toCurrencyString(currencyCode)
67
-
68
- RecurringExpenseOverview (
69
- weeklyExpense = weeklyExpense,
70
- monthlyExpense = monthlyExpense,
71
- yearlyExpense = yearlyExpense,
72
- recurringExpenseData = recurringExpenseViewModel.recurringExpenseData,
73
- isGridMode = isGridMode,
74
- onToggleGridMode = toggleGridMode,
75
- navController = navController,
76
- contentPadding =
77
- PaddingValues (
78
- top = 8 .dp,
79
- start = 16 .dp,
80
- end = 16 .dp,
81
- ),
82
- )
83
- }
84
- composable(UpcomingPane .ROUTE ) {
85
- UpcomingPaymentsScreen (
86
- upcomingPaymentsViewModel = upcomingPaymentsViewModel,
87
- isGridMode = isGridMode,
88
- onToggleGridMode = toggleGridMode,
89
- navController = navController,
90
- contentPadding =
91
- PaddingValues (
92
- top = 8 .dp,
93
- start = 16 .dp,
94
- end = 16 .dp,
95
- ),
96
- )
97
- }
98
- composable(SettingsPane .ROUTE ) {
99
- SettingsScreen (
100
- biometricsChecked = biometricSecurity,
101
- onClickBackup = onClickBackup,
102
- onClickRestore = onClickRestore,
103
- onBiometricCheckedChange = onBiometricSecurityChange,
104
- canUseBiometric = canUseBiometric,
105
- canUseNotifications = canUseNotifications,
106
- hasNotificationPermission = hasNotificationPermission,
107
- requestNotificationPermission = requestNotificationPermission,
108
- navigateToPermissionsSettings = navigateToPermissionsSettings,
74
+ Scaffold (
75
+ modifier = modifier,
76
+ topBar = {
77
+ mainNavigationViewModel.topAppBar()
78
+ },
79
+ bottomBar = {
80
+ if (backStackEntry.value?.destination?.route in
81
+ listOf (HomePane .ROUTE , UpcomingPane .ROUTE , SettingsPane .ROUTE )
82
+ ) {
83
+ BottomNavBar (navController = navController)
84
+ }
85
+ },
86
+ floatingActionButton = {
87
+ if (backStackEntry.value?.destination?.route in listOf (HomePane .ROUTE , UpcomingPane .ROUTE )) {
88
+ FloatingActionButton (
89
+ onClick = {
90
+ navController.navigate(EditExpensePane ().destination)
91
+ },
92
+ ) {
93
+ Icon (
94
+ imageVector = Icons .Rounded .Add ,
95
+ contentDescription =
96
+ stringResource(Res .string.edit_expense_button_add),
97
+ )
98
+ }
99
+ }
100
+ },
101
+ content = { paddingValues ->
102
+ NavHost (
109
103
navController = navController,
110
- )
111
- }
112
- composable(
113
- route = EditExpensePane .ROUTE ,
114
- arguments = EditExpensePane .navArguments,
115
- ) { backStackEntry ->
116
- EditRecurringExpenseScreen (
117
- expenseId = backStackEntry.getArgExpenseId(),
118
- canUseNotifications = canUseNotifications,
119
- onDismiss = {
120
- navController.navigateUp()
121
- updateWidget()
122
- },
123
- )
124
- }
125
- }
104
+ startDestination = startRoute,
105
+ modifier = Modifier .fillMaxSize(),
106
+ ) {
107
+ composable(HomePane .ROUTE ) {
108
+ mainNavigationViewModel.topAppBar = {
109
+ TopAppBar (
110
+ title = {
111
+ Text (
112
+ text = stringResource(Res .string.home_title),
113
+ )
114
+ },
115
+ actions = {
116
+ ToggleGridModeButton (
117
+ onToggleGridMode = toggleGridMode,
118
+ isGridMode = isGridMode,
119
+ )
120
+ },
121
+ )
122
+ }
123
+
124
+ val weeklyExpense =
125
+ recurringExpenseViewModel.currencyPrefix +
126
+ recurringExpenseViewModel.weeklyExpense.toCurrencyString(currencyCode)
127
+ val monthlyExpense =
128
+ recurringExpenseViewModel.currencyPrefix +
129
+ recurringExpenseViewModel.monthlyExpense.toCurrencyString(currencyCode)
130
+ val yearlyExpense =
131
+ recurringExpenseViewModel.currencyPrefix +
132
+ recurringExpenseViewModel.yearlyExpense.toCurrencyString(currencyCode)
133
+
134
+ RecurringExpenseOverview (
135
+ weeklyExpense = weeklyExpense,
136
+ monthlyExpense = monthlyExpense,
137
+ yearlyExpense = yearlyExpense,
138
+ recurringExpenseData = recurringExpenseViewModel.recurringExpenseData,
139
+ isGridMode = isGridMode,
140
+ navController = navController,
141
+ contentPadding =
142
+ PaddingValues (
143
+ top = 8 .dp,
144
+ start = 16 .dp,
145
+ end = 16 .dp,
146
+ ),
147
+ modifier = Modifier .padding(paddingValues),
148
+ )
149
+ }
150
+ composable(UpcomingPane .ROUTE ) {
151
+ mainNavigationViewModel.topAppBar = {
152
+ TopAppBar (
153
+ title = {
154
+ Text (
155
+ text = stringResource(Res .string.upcoming_title),
156
+ )
157
+ },
158
+ actions = {
159
+ ToggleGridModeButton (
160
+ onToggleGridMode = toggleGridMode,
161
+ isGridMode = isGridMode,
162
+ )
163
+ },
164
+ )
165
+ }
166
+
167
+ UpcomingPaymentsScreen (
168
+ upcomingPaymentsViewModel = upcomingPaymentsViewModel,
169
+ isGridMode = isGridMode,
170
+ navController = navController,
171
+ contentPadding =
172
+ PaddingValues (
173
+ top = 8 .dp,
174
+ start = 16 .dp,
175
+ end = 16 .dp,
176
+ ),
177
+ modifier = Modifier .padding(paddingValues),
178
+ )
179
+ }
180
+ composable(SettingsPane .ROUTE ) {
181
+ var topAppBar by remember { mutableStateOf< @Composable () -> Unit > ({}) }
182
+ SettingsScreen (
183
+ biometricsChecked = biometricSecurity,
184
+ onClickBackup = onClickBackup,
185
+ onClickRestore = onClickRestore,
186
+ onBiometricCheckedChange = onBiometricSecurityChange,
187
+ canUseBiometric = canUseBiometric,
188
+ canUseNotifications = canUseNotifications,
189
+ hasNotificationPermission = hasNotificationPermission,
190
+ requestNotificationPermission = requestNotificationPermission,
191
+ navigateToPermissionsSettings = navigateToPermissionsSettings,
192
+ setTopAppBar = {
193
+ mainNavigationViewModel.topAppBar = it
194
+ topAppBar = it
195
+ },
196
+ modifier = Modifier .padding(paddingValues),
197
+ )
198
+ mainNavigationViewModel.topAppBar = topAppBar
199
+ }
200
+ composable(
201
+ route = EditExpensePane .ROUTE ,
202
+ arguments = EditExpensePane .navArguments,
203
+ ) { backStackEntry ->
204
+ var topAppBar by remember { mutableStateOf< @Composable () -> Unit > ({}) }
205
+ EditRecurringExpenseScreen (
206
+ expenseId = backStackEntry.getArgExpenseId(),
207
+ canUseNotifications = canUseNotifications,
208
+ onDismiss = {
209
+ navController.navigateUp()
210
+ updateWidget()
211
+ },
212
+ setTopAppBar = {
213
+ mainNavigationViewModel.topAppBar = it
214
+ topAppBar = it
215
+ },
216
+ modifier = Modifier .padding(paddingValues),
217
+ )
218
+ mainNavigationViewModel.topAppBar = topAppBar
219
+ }
220
+ }
221
+ },
222
+ )
126
223
}
127
224
}
128
225
0 commit comments