refactor feed to use UiState.Loading
This commit is contained in:
		
							parent
							
								
									d31276ef81
								
							
						
					
					
						commit
						6ba0018765
					
				
					 8 changed files with 131 additions and 101 deletions
				
			
		|  | @ -0,0 +1,99 @@ | |||
| package be.ugent.sel.studeez.common.composable.feed | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.* | ||||
| import androidx.compose.foundation.lazy.LazyColumn | ||||
| import androidx.compose.foundation.lazy.items | ||||
| import androidx.compose.material.CircularProgressIndicator | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.text.font.FontWeight | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import androidx.compose.ui.unit.sp | ||||
| import be.ugent.sel.studeez.common.composable.DateText | ||||
| import be.ugent.sel.studeez.data.local.models.FeedEntry | ||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| 
 | ||||
| data class FeedActions( | ||||
|     val getFeedEntries: () -> Flow<Map<String, List<FeedEntry>>>, | ||||
|     val continueTask: (String, String) -> Unit, | ||||
| ) | ||||
| 
 | ||||
| fun getFeedActions( | ||||
|     viewmodel: FeedViewModel, | ||||
|     open: (String) -> Unit, | ||||
| ): FeedActions { | ||||
|     return FeedActions( | ||||
|         getFeedEntries = viewmodel::getFeedEntries, | ||||
|         continueTask = { subjectId, taskId -> | ||||
|             viewmodel.continueTask( | ||||
|                 open, | ||||
|                 subjectId, | ||||
|                 taskId, | ||||
|             ) | ||||
|         }, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun Feed( | ||||
|     feedActions: FeedActions, | ||||
|     uiState: FeedUiState, | ||||
| ) { | ||||
|     when (uiState) { | ||||
|         FeedUiState.Loading -> { | ||||
|             Column( | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .fillMaxHeight(), | ||||
|                 verticalArrangement = Arrangement.Center, | ||||
|                 horizontalAlignment = Alignment.CenterHorizontally | ||||
|             ) { | ||||
|                 CircularProgressIndicator(color = MaterialTheme.colors.onBackground) | ||||
|             } | ||||
|         } | ||||
|         is FeedUiState.Succes -> { | ||||
| //            val feedEntries = feedActions.getFeedEntries().collectAsState(initial = emptyMap()) | ||||
|             val feedEntries = uiState.feedEntries | ||||
|             LazyColumn { | ||||
|                 items(feedEntries.toList()) { (date, feedEntries) -> | ||||
|                     Row( | ||||
|                         horizontalArrangement = Arrangement.SpaceBetween, | ||||
|                         modifier = Modifier | ||||
|                             .fillMaxWidth() | ||||
|                             .padding(10.dp), | ||||
|                         verticalAlignment = Alignment.CenterVertically | ||||
|                     ) { | ||||
|                         val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } | ||||
|                         DateText(date = date) | ||||
|                         Text( | ||||
|                             text = "${HoursMinutesSeconds(totalDayStudyTime)}", | ||||
|                             fontSize = 15.sp, | ||||
|                             fontWeight = FontWeight.Bold | ||||
|                         ) | ||||
|                     } | ||||
|                     feedEntries.forEach { feedEntry -> | ||||
|                         FeedEntry(feedEntry = feedEntry) { | ||||
|                             feedActions.continueTask(feedEntry.subjectId, feedEntry.taskId) | ||||
|                         } | ||||
|                     } | ||||
|                     Spacer(modifier = Modifier.height(20.dp)) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun FeedPreview() { | ||||
|     Feed( | ||||
|         feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }), | ||||
|         uiState = FeedUiState.Loading, | ||||
|     ) | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package be.ugent.sel.studeez.screens.home | ||||
| package be.ugent.sel.studeez.common.composable.feed | ||||
| 
 | ||||
| import androidx.compose.foundation.background | ||||
| import androidx.compose.foundation.layout.* | ||||
|  | @ -0,0 +1,8 @@ | |||
| package be.ugent.sel.studeez.common.composable.feed | ||||
| 
 | ||||
| import be.ugent.sel.studeez.data.local.models.FeedEntry | ||||
| 
 | ||||
| sealed interface FeedUiState { | ||||
|     object Loading : FeedUiState | ||||
|     data class Succes(val feedEntries: Map<String, List<FeedEntry>>) : FeedUiState | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package be.ugent.sel.studeez.screens.home | ||||
| package be.ugent.sel.studeez.common.composable.feed | ||||
| 
 | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import be.ugent.sel.studeez.data.SelectedTask | ||||
|  | @ -9,13 +9,13 @@ import be.ugent.sel.studeez.domain.TaskDAO | |||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | ||||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.* | ||||
| import kotlinx.coroutines.launch | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| @HiltViewModel | ||||
| class FeedViewModel @Inject constructor( | ||||
|     private val feedDAO: FeedDAO, | ||||
|     feedDAO: FeedDAO, | ||||
|     private val taskDAO: TaskDAO, | ||||
|     private val selectedTask: SelectedTask, | ||||
|     logService: LogService | ||||
|  | @ -23,6 +23,14 @@ class FeedViewModel @Inject constructor( | |||
| 
 | ||||
|     private val entries: Flow<Map<String, List<FeedEntry>>> = feedDAO.getFeedEntries() | ||||
| 
 | ||||
|     val uiState: StateFlow<FeedUiState> = feedDAO.getFeedEntries() | ||||
|         .map { FeedUiState.Succes(it) } | ||||
|         .stateIn( | ||||
|             scope = viewModelScope, | ||||
|             initialValue = FeedUiState.Loading, | ||||
|             started = SharingStarted.Eagerly, | ||||
|         ) | ||||
| 
 | ||||
|     fun getFeedEntries(): Flow<Map<String, List<FeedEntry>>> { | ||||
|         return entries | ||||
|     } | ||||
|  | @ -15,7 +15,6 @@ import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions | |||
| import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel | ||||
| import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions | ||||
| import be.ugent.sel.studeez.screens.home.HomeRoute | ||||
| import be.ugent.sel.studeez.screens.home.getFeedActions | ||||
| import be.ugent.sel.studeez.screens.log_in.LoginRoute | ||||
| import be.ugent.sel.studeez.screens.profile.EditProfileRoute | ||||
| import be.ugent.sel.studeez.screens.profile.ProfileRoute | ||||
|  | @ -66,10 +65,9 @@ fun StudeezNavGraph( | |||
|         composable(StudeezDestinations.HOME_SCREEN) { | ||||
|             HomeRoute( | ||||
|                 open, | ||||
|                 viewModel = hiltViewModel(), | ||||
|                 drawerActions = drawerActions, | ||||
|                 navigationBarActions = navigationBarActions, | ||||
|                 feedActions = getFeedActions(hiltViewModel(), open), | ||||
|                 feedViewModel = hiltViewModel(), | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,70 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.home | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.* | ||||
| import androidx.compose.foundation.lazy.LazyColumn | ||||
| import androidx.compose.foundation.lazy.items | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.collectAsState | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.text.font.FontWeight | ||||
| import androidx.compose.ui.unit.dp | ||||
| import androidx.compose.ui.unit.sp | ||||
| import be.ugent.sel.studeez.common.composable.DateText | ||||
| import be.ugent.sel.studeez.data.local.models.FeedEntry | ||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| 
 | ||||
| data class FeedActions( | ||||
|     val getFeedEntries: () -> Flow<Map<String, List<FeedEntry>>>, | ||||
|     val continueTask: (String, String) -> Unit, | ||||
| ) | ||||
| 
 | ||||
| fun getFeedActions( | ||||
|     viewmodel: FeedViewModel, | ||||
|     open: (String) -> Unit, | ||||
| ): FeedActions { | ||||
|     return FeedActions( | ||||
|         getFeedEntries = viewmodel::getFeedEntries, | ||||
|         continueTask = { subjectId, taskId -> | ||||
|             viewmodel.continueTask( | ||||
|                 open, | ||||
|                 subjectId, | ||||
|                 taskId, | ||||
|             ) | ||||
|         }, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun Feed( | ||||
|     feedActions: FeedActions, | ||||
| ) { | ||||
|     val feedEntries = feedActions.getFeedEntries().collectAsState(initial = emptyMap()) | ||||
|     LazyColumn { | ||||
|         items(feedEntries.value.toList()) { (date, feedEntries) -> | ||||
|             Row( | ||||
|                 horizontalArrangement = Arrangement.SpaceBetween, | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .padding(10.dp), | ||||
|                 verticalAlignment = Alignment.CenterVertically | ||||
|             ) { | ||||
|                 val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } | ||||
|                 DateText(date = date) | ||||
|                 Text( | ||||
|                     text = "${HoursMinutesSeconds(totalDayStudyTime)}", | ||||
|                     fontSize = 15.sp, | ||||
|                     fontWeight = FontWeight.Bold | ||||
|                 ) | ||||
|             } | ||||
|             feedEntries.forEach { feedEntry -> | ||||
|                 FeedEntry(feedEntry = feedEntry) { | ||||
|                     feedActions.continueTask(feedEntry.subjectId, feedEntry.taskId) | ||||
|                 } | ||||
|             } | ||||
|             Spacer(modifier = Modifier.height(20.dp)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -5,10 +5,13 @@ import androidx.compose.material.IconButton | |||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.Person | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.collectAsState | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import be.ugent.sel.studeez.R | ||||
| import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerActions | ||||
| import be.ugent.sel.studeez.common.composable.feed.* | ||||
| import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions | ||||
| import be.ugent.sel.studeez.resources | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
|  | @ -16,16 +19,17 @@ import kotlinx.coroutines.flow.flowOf | |||
| @Composable | ||||
| fun HomeRoute( | ||||
|     open: (String) -> Unit, | ||||
|     viewModel: HomeViewModel, | ||||
|     drawerActions: DrawerActions, | ||||
|     navigationBarActions: NavigationBarActions, | ||||
|     feedActions: FeedActions, | ||||
|     feedViewModel: FeedViewModel, | ||||
| ) { | ||||
|     val feedUiState by feedViewModel.uiState.collectAsState() | ||||
|     HomeScreen( | ||||
|         drawerActions = drawerActions, | ||||
|         open = open, | ||||
|         navigationBarActions = navigationBarActions, | ||||
|         feedActions = feedActions, | ||||
|         feedActions = getFeedActions(feedViewModel, open), | ||||
|         feedUiState = feedUiState, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
|  | @ -35,6 +39,7 @@ fun HomeScreen( | |||
|     drawerActions: DrawerActions, | ||||
|     navigationBarActions: NavigationBarActions, | ||||
|     feedActions: FeedActions, | ||||
|     feedUiState: FeedUiState, | ||||
| ) { | ||||
|     PrimaryScreenTemplate( | ||||
|         title = resources().getString(R.string.home), | ||||
|  | @ -42,7 +47,7 @@ fun HomeScreen( | |||
|         navigationBarActions = navigationBarActions, | ||||
|         // TODO barAction = { FriendsAction() } | ||||
|     ) { | ||||
|         Feed(feedActions) | ||||
|         Feed(feedActions, feedUiState) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -63,6 +68,7 @@ fun HomeScreenPreview() { | |||
|         drawerActions = DrawerActions({}, {}, {}, {}, {}), | ||||
|         navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), | ||||
|         open = {}, | ||||
|         feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }) | ||||
|         feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }), | ||||
|         feedUiState = FeedUiState.Loading, | ||||
|     ) | ||||
| } | ||||
|  |  | |||
|  | @ -1,19 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.home | ||||
| 
 | ||||
| import be.ugent.sel.studeez.domain.AccountDAO | ||||
| import be.ugent.sel.studeez.domain.LogService | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | ||||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| @HiltViewModel | ||||
| class HomeViewModel @Inject constructor( | ||||
|     private val accountDAO: AccountDAO, | ||||
|     logService: LogService | ||||
| ) : StudeezViewModel(logService) { | ||||
| 
 | ||||
|     fun onStartSessionClick(open: (String) -> Unit) { | ||||
|         open(StudeezDestinations.TIMER_SELECTION_SCREEN) | ||||
|     } | ||||
| } | ||||
		Reference in a new issue
	
	 brreynie
						brreynie