Add public profile
This commit is contained in:
		
							parent
							
								
									bc7753fce5
								
							
						
					
					
						commit
						a6a5fb5e95
					
				
					 4 changed files with 255 additions and 0 deletions
				
			
		|  | @ -0,0 +1,178 @@ | |||
| package be.ugent.sel.studeez.screens.profile.public_profile | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.* | ||||
| import androidx.compose.foundation.lazy.LazyColumn | ||||
| import androidx.compose.material.* | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.MailOutline | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.vector.ImageVector | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.res.vectorResource | ||||
| import androidx.compose.ui.text.style.TextAlign | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import be.ugent.sel.studeez.R | ||||
| import be.ugent.sel.studeez.common.composable.Headline | ||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerEntry | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.resources | ||||
| import be.ugent.sel.studeez.screens.profile.AmountOfFriendsButton | ||||
| import be.ugent.sel.studeez.ui.theme.StudeezTheme | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| data class PublicProfileActions( | ||||
|     val getUserDetails: () -> Flow<User>, | ||||
|     val getAmountOfFriends: () -> Flow<Int>, | ||||
|     val onViewFriendsClick: () -> Unit, | ||||
|     val sendFriendRequest: () -> Boolean | ||||
| ) | ||||
| 
 | ||||
| fun getPublicProfileActions( | ||||
|     viewModel: PublicProfileViewModel, | ||||
|     open: (String) -> Unit | ||||
| ): PublicProfileActions { | ||||
|     return PublicProfileActions( | ||||
|         getUserDetails = { viewModel.getUserDetails(viewModel.uiState.value.userId) }, | ||||
|         getAmountOfFriends = { viewModel.getAmountOfFriends( | ||||
|             userId = viewModel.uiState.value.userId | ||||
|         ) }, | ||||
|         onViewFriendsClick = { viewModel.onViewFriendsClick(open) }, | ||||
|         sendFriendRequest = { viewModel.sendFriendRequest( | ||||
|             userId = viewModel.uiState.value.userId | ||||
|         ) } | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun PublicProfileRoute( | ||||
|     popUp: () -> Unit, | ||||
|     open: (String) -> Unit, | ||||
|     viewModel: PublicProfileViewModel | ||||
| ) { | ||||
|     PublicProfileScreen( | ||||
|         publicProfileActions = getPublicProfileActions( | ||||
|             viewModel = viewModel, | ||||
|             open = open | ||||
|         ), | ||||
|         popUp = popUp | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun PublicProfileScreen( | ||||
|     publicProfileActions: PublicProfileActions, | ||||
|     popUp: () -> Unit | ||||
| ) { | ||||
|     val user = publicProfileActions.getUserDetails().collectAsState(initial = User()) | ||||
|     val amountOfFriends = publicProfileActions.getAmountOfFriends().collectAsState(initial = 0) | ||||
| 
 | ||||
|     SecondaryScreenTemplate( | ||||
|         title = stringResource(id = AppText.profile), | ||||
|         popUp = popUp, | ||||
|         barAction = { | ||||
|             PublicProfileEllipsis( | ||||
|                 sendFriendRequest = publicProfileActions.sendFriendRequest | ||||
|             ) | ||||
|         } | ||||
|     ) { | ||||
|         LazyColumn( | ||||
|             verticalArrangement = Arrangement.spacedBy(15.dp) | ||||
|         ) { | ||||
|             item { | ||||
|                 Headline(text = user.value.username) | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Row( | ||||
|                     horizontalArrangement = Arrangement.spacedBy(5.dp), | ||||
|                     modifier = Modifier | ||||
|                         .fillMaxWidth() | ||||
|                         .wrapContentWidth(align = Alignment.CenterHorizontally) | ||||
|                 ) { | ||||
|                     AmountOfFriendsButton( | ||||
|                         amountOfFriends = amountOfFriends.value | ||||
|                     ) { | ||||
|                         publicProfileActions.onViewFriendsClick() | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Text( | ||||
|                     text = user.value.biography, | ||||
|                     textAlign = TextAlign.Center, | ||||
|                     modifier = Modifier.padding(48.dp, 0.dp) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun PublicProfilePreview() { | ||||
|     StudeezTheme { | ||||
|         PublicProfileScreen( | ||||
|             publicProfileActions = PublicProfileActions( | ||||
|                 getUserDetails = { | ||||
|                     flowOf(User( | ||||
|                         id = "someid", | ||||
|                         username = "Maxime De Poorter", | ||||
|                         biography = "I am a different student and this is my public profile" | ||||
|                     )) | ||||
|                 }, | ||||
|                 getAmountOfFriends = { flowOf(113) }, | ||||
|                 onViewFriendsClick = {}, | ||||
|                 sendFriendRequest = { true } | ||||
|             ), | ||||
|             popUp = {} | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun PublicProfileEllipsis( | ||||
|     sendFriendRequest: () -> Boolean | ||||
| ) { | ||||
|     var expanded by remember { mutableStateOf(false) } | ||||
| 
 | ||||
|     IconButton( | ||||
|         onClick = { expanded = true } | ||||
|     ) { | ||||
|         Icon( | ||||
|             imageVector = ImageVector.vectorResource(id = R.drawable.ic_more_horizontal), | ||||
|             contentDescription = resources().getString(AppText.view_more), | ||||
|             modifier = Modifier.fillMaxSize() | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     DropdownMenu( | ||||
|         expanded = expanded, | ||||
|         onDismissRequest = { expanded = false } | ||||
|     ) { | ||||
|         DropdownMenuItem(onClick = { expanded = false }) { | ||||
|             DrawerEntry( | ||||
|                 icon = Icons.Default.MailOutline, | ||||
|                 text = stringResource(id = AppText.send_friend_request) | ||||
|             ) { | ||||
|                 sendFriendRequest() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun PublicProfileEllipsisPreview() { | ||||
|     StudeezTheme { | ||||
|         PublicProfileEllipsis( | ||||
|             sendFriendRequest = { true } | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| package be.ugent.sel.studeez.screens.profile.public_profile | ||||
| 
 | ||||
| data class PublicProfileUiState( | ||||
|     var userId: String = "" | ||||
| ) | ||||
|  | @ -0,0 +1,60 @@ | |||
| package be.ugent.sel.studeez.screens.profile.public_profile | ||||
| 
 | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.domain.FriendshipDAO | ||||
| import be.ugent.sel.studeez.domain.LogService | ||||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| 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.selects.select | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| @HiltViewModel | ||||
| class PublicProfileViewModel @Inject constructor( | ||||
|     private val userDAO: UserDAO, | ||||
|     private val friendshipDAO: FriendshipDAO, | ||||
|     selectedProfileState: SelectedProfileState, | ||||
|     logService: LogService | ||||
| ): StudeezViewModel(logService) { | ||||
| 
 | ||||
|     val uiState = mutableStateOf( | ||||
|         PublicProfileUiState( | ||||
|             userId = selectedProfileState.selectedUserId | ||||
|         ) | ||||
|     ) | ||||
| 
 | ||||
|     fun getUserDetails( | ||||
|         userId: String | ||||
|     ): Flow<User> { | ||||
|         uiState.value = uiState.value.copy( | ||||
|             userId = userId | ||||
|         ) | ||||
|         return userDAO.getUserDetails( | ||||
|             userId = uiState.value.userId | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fun getAmountOfFriends( | ||||
|         userId: String | ||||
|     ): Flow<Int> { | ||||
|         return friendshipDAO.getFriendshipCount( | ||||
|             userId = userId | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fun onViewFriendsClick( | ||||
|         open: (String) -> Unit | ||||
|     ) { | ||||
|         open(StudeezDestinations.FRIENDS_OVERVIEW_SCREEN) | ||||
|     } | ||||
| 
 | ||||
|     fun sendFriendRequest( | ||||
|         userId: String | ||||
|     ): Boolean { | ||||
|         return friendshipDAO.sendFriendshipRequest(userId) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| package be.ugent.sel.studeez.screens.profile.public_profile | ||||
| 
 | ||||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| import javax.inject.Inject | ||||
| import javax.inject.Singleton | ||||
| 
 | ||||
| @Singleton | ||||
| class SelectedProfileState @Inject constructor( | ||||
|     userDAO: UserDAO | ||||
| ) { | ||||
|     var selectedUserId: String = userDAO.getCurrentUserId() | ||||
| } | ||||
		Reference in a new issue