@@ -24,12 +24,16 @@ import androidx.compose.foundation.lazy.LazyColumn
2424import androidx.compose.foundation.lazy.itemsIndexed
2525import androidx.compose.foundation.shape.RoundedCornerShape
2626import androidx.compose.material.CircularProgressIndicator
27+ import androidx.compose.material.ExperimentalMaterialApi
2728import androidx.compose.material.Icon
2829import androidx.compose.material.MaterialTheme
2930import androidx.compose.material.Scaffold
3031import androidx.compose.material.Text
3132import androidx.compose.material.icons.Icons
3233import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos
34+ import androidx.compose.material.pullrefresh.PullRefreshIndicator
35+ import androidx.compose.material.pullrefresh.pullRefresh
36+ import androidx.compose.material.pullrefresh.rememberPullRefreshState
3337import androidx.compose.material.rememberScaffoldState
3438import androidx.compose.runtime.Composable
3539import androidx.compose.runtime.collectAsState
@@ -92,8 +96,8 @@ class DatesFragment : Fragment() {
9296 viewModel.onSettingsClick(requireActivity().supportFragmentManager)
9397 }
9498
95- DatesViewActions .ReloadData -> {
96-
99+ DatesViewActions .SwipeRefresh -> {
100+ viewModel.refreshData()
97101 }
98102
99103 is DatesViewActions .OpenEvent -> {
@@ -108,6 +112,7 @@ class DatesFragment : Fragment() {
108112
109113}
110114
115+ @OptIn(ExperimentalMaterialApi ::class )
111116@Composable
112117private fun DatesScreen (
113118 uiState : DatesUIState ,
@@ -124,10 +129,15 @@ private fun DatesScreen(
124129 )
125130 )
126131 }
132+ val pullRefreshState = rememberPullRefreshState(
133+ refreshing = uiState.isRefreshing,
134+ onRefresh = { onAction(DatesViewActions .SwipeRefresh ) }
135+ )
127136
128137 Scaffold (
129138 scaffoldState = scaffoldState,
130- modifier = Modifier .fillMaxSize(),
139+ modifier = Modifier
140+ .fillMaxSize(),
131141 backgroundColor = MaterialTheme .appColors.background,
132142 topBar = {
133143 MainScreenTitle (
@@ -141,58 +151,71 @@ private fun DatesScreen(
141151 )
142152 },
143153 content = { paddingValues ->
144- HandleUIMessage (uiMessage = uiMessage, scaffoldState = scaffoldState)
145-
146- if (uiState.isLoading) {
147- Box (
148- modifier = Modifier .fillMaxSize(),
149- contentAlignment = Alignment .Center
150- ) {
151- CircularProgressIndicator (color = MaterialTheme .appColors.primary)
152- }
153- } else if (uiState.dates.isEmpty()) {
154- EmptyState ()
155- } else {
156- Box (
157- modifier = Modifier
158- .fillMaxSize()
159- .displayCutoutForLandscape()
160- .padding(paddingValues)
161- .padding(horizontal = 16 .dp),
162- contentAlignment = Alignment .TopCenter
163- ) {
164- LazyColumn (
165- modifier = contentWidth,
166- contentPadding = PaddingValues (bottom = 20 .dp)
154+ Box (
155+ modifier = Modifier
156+ .fillMaxSize()
157+ .pullRefresh(pullRefreshState)
158+ ) {
159+ if (uiState.isLoading) {
160+ Box (
161+ modifier = Modifier .fillMaxSize(),
162+ contentAlignment = Alignment .Center
167163 ) {
168- uiState.dates.keys.forEach { dueDateCategory ->
169- val dates = uiState.dates[dueDateCategory] ? : emptyList()
170- if (dates.isNotEmpty()) {
171- item {
172- Text (
173- modifier = Modifier
174- .fillMaxWidth()
175- .padding(bottom = 8 .dp, top = 20 .dp),
176- text = stringResource(id = dueDateCategory.label),
177- color = MaterialTheme .appColors.textDark,
178- style = MaterialTheme .appTypography.titleMedium,
179- )
180- }
181- itemsIndexed(dates) { index, date ->
182- val itemPosition = ListItemPosition .detectPosition(index, dates)
183- DateItem (
184- date = date,
185- lineColor = dueDateCategory.color,
186- itemPosition = itemPosition,
187- onClick = {
188- onAction(DatesViewActions .OpenEvent ())
189- }
190- )
164+ CircularProgressIndicator (color = MaterialTheme .appColors.primary)
165+ }
166+ } else if (uiState.dates.isEmpty()) {
167+ EmptyState ()
168+ } else {
169+ Box (
170+ modifier = Modifier
171+ .fillMaxSize()
172+ .displayCutoutForLandscape()
173+ .padding(paddingValues)
174+ .padding(horizontal = 16 .dp),
175+ contentAlignment = Alignment .TopCenter
176+ ) {
177+ LazyColumn (
178+ modifier = contentWidth,
179+ contentPadding = PaddingValues (bottom = 20 .dp)
180+ ) {
181+ uiState.dates.keys.forEach { dueDateCategory ->
182+ val dates = uiState.dates[dueDateCategory] ? : emptyList()
183+ if (dates.isNotEmpty()) {
184+ item {
185+ Text (
186+ modifier = Modifier
187+ .fillMaxWidth()
188+ .padding(bottom = 8 .dp, top = 20 .dp),
189+ text = stringResource(id = dueDateCategory.label),
190+ color = MaterialTheme .appColors.textDark,
191+ style = MaterialTheme .appTypography.titleMedium,
192+ )
193+ }
194+ itemsIndexed(dates) { index, date ->
195+ val itemPosition =
196+ ListItemPosition .detectPosition(index, dates)
197+ DateItem (
198+ date = date,
199+ lineColor = dueDateCategory.color,
200+ itemPosition = itemPosition,
201+ onClick = {
202+ onAction(DatesViewActions .OpenEvent ())
203+ }
204+ )
205+ }
191206 }
192207 }
193208 }
194209 }
195210 }
211+
212+ HandleUIMessage (uiMessage = uiMessage, scaffoldState = scaffoldState)
213+
214+ PullRefreshIndicator (
215+ uiState.isRefreshing,
216+ pullRefreshState,
217+ Modifier .align(Alignment .TopCenter )
218+ )
196219 }
197220 }
198221 )
0 commit comments