Move friends overview to new package and new stuff
This commit is contained in:
		
							parent
							
								
									71b9550bd0
								
							
						
					
					
						commit
						bc7753fce5
					
				
					 3 changed files with 155 additions and 35 deletions
				
			
		|  | @ -1,20 +1,21 @@ | ||||||
| package be.ugent.sel.studeez.screens.friend | package be.ugent.sel.studeez.screens.friends.friends_overview | ||||||
| 
 | 
 | ||||||
| import androidx.compose.foundation.background | import androidx.compose.foundation.background | ||||||
| import androidx.compose.foundation.layout.* | import androidx.compose.foundation.layout.* | ||||||
| import androidx.compose.foundation.lazy.LazyColumn | import androidx.compose.foundation.lazy.LazyColumn | ||||||
| import androidx.compose.foundation.lazy.items | import androidx.compose.foundation.lazy.items | ||||||
| import androidx.compose.foundation.shape.CircleShape | import androidx.compose.foundation.shape.CircleShape | ||||||
| import androidx.compose.material.Icon | import androidx.compose.material.* | ||||||
| import androidx.compose.material.IconButton | import androidx.compose.material.icons.Icons | ||||||
| import androidx.compose.material.MaterialTheme | import androidx.compose.material.icons.filled.ArrowBack | ||||||
| import androidx.compose.material.Text | import androidx.compose.material.icons.filled.Delete | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.material.icons.filled.Person | ||||||
| import androidx.compose.runtime.collectAsState | import androidx.compose.runtime.* | ||||||
| import androidx.compose.ui.Alignment | import androidx.compose.ui.Alignment | ||||||
| import androidx.compose.ui.Modifier | import androidx.compose.ui.Modifier | ||||||
| import androidx.compose.ui.graphics.vector.ImageVector | import androidx.compose.ui.graphics.vector.ImageVector | ||||||
| import androidx.compose.ui.res.painterResource | import androidx.compose.ui.res.painterResource | ||||||
|  | import androidx.compose.ui.res.stringResource | ||||||
| import androidx.compose.ui.res.vectorResource | import androidx.compose.ui.res.vectorResource | ||||||
| import androidx.compose.ui.text.style.TextOverflow | import androidx.compose.ui.text.style.TextOverflow | ||||||
| import androidx.compose.ui.tooling.preview.Preview | import androidx.compose.ui.tooling.preview.Preview | ||||||
|  | @ -22,7 +23,8 @@ import androidx.compose.ui.unit.dp | ||||||
| import androidx.compose.ui.unit.sp | import androidx.compose.ui.unit.sp | ||||||
| import be.ugent.sel.studeez.R | import be.ugent.sel.studeez.R | ||||||
| import be.ugent.sel.studeez.common.composable.BasicButton | import be.ugent.sel.studeez.common.composable.BasicButton | ||||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | import be.ugent.sel.studeez.common.composable.SearchField | ||||||
|  | import be.ugent.sel.studeez.common.composable.drawer.DrawerEntry | ||||||
| import be.ugent.sel.studeez.common.ext.basicButton | import be.ugent.sel.studeez.common.ext.basicButton | ||||||
| import be.ugent.sel.studeez.data.local.models.Friendship | import be.ugent.sel.studeez.data.local.models.Friendship | ||||||
| import be.ugent.sel.studeez.data.local.models.User | import be.ugent.sel.studeez.data.local.models.User | ||||||
|  | @ -35,7 +37,11 @@ import be.ugent.sel.studeez.R.string as AppText | ||||||
| 
 | 
 | ||||||
| data class FriendsOverviewActions( | data class FriendsOverviewActions( | ||||||
|     val getFriendsFlow: () -> Flow<List<Pair<User, Friendship>>>, |     val getFriendsFlow: () -> Flow<List<Pair<User, Friendship>>>, | ||||||
|     val searchFriends: () -> Unit |     val searchFriends: () -> Unit, | ||||||
|  |     val onQueryStringChange: (String) -> Unit, | ||||||
|  |     val onSubmit: () -> Unit, | ||||||
|  |     val viewProfile: (String) -> Unit, | ||||||
|  |     val removeFriend: (Friendship) -> Unit | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| fun getFriendsOverviewActions( | fun getFriendsOverviewActions( | ||||||
|  | @ -44,7 +50,13 @@ fun getFriendsOverviewActions( | ||||||
| ): FriendsOverviewActions { | ): FriendsOverviewActions { | ||||||
|     return FriendsOverviewActions( |     return FriendsOverviewActions( | ||||||
|         getFriendsFlow = viewModel::getAllFriends, |         getFriendsFlow = viewModel::getAllFriends, | ||||||
|         searchFriends = { viewModel.searchFriends(open) } |         searchFriends = { viewModel.searchFriends(open) }, | ||||||
|  |         onQueryStringChange = viewModel::onQueryStringChange, | ||||||
|  |         onSubmit = { viewModel.onSubmit(open) }, | ||||||
|  |         viewProfile = { userId -> | ||||||
|  |             viewModel.viewProfile(userId, open) | ||||||
|  |         }, | ||||||
|  |         removeFriend = viewModel::removeFriend | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -54,27 +66,52 @@ fun FriendsOveriewRoute( | ||||||
|     popUp: () -> Unit, |     popUp: () -> Unit, | ||||||
|     viewModel: FriendsOverviewViewModel |     viewModel: FriendsOverviewViewModel | ||||||
| ) { | ) { | ||||||
|  |     val uiState by viewModel.uiState | ||||||
|     FriendsOverviewScreen( |     FriendsOverviewScreen( | ||||||
|  |         popUp = popUp, | ||||||
|  |         uiState = uiState, | ||||||
|         friendsOverviewActions = getFriendsOverviewActions( |         friendsOverviewActions = getFriendsOverviewActions( | ||||||
|             viewModel = viewModel, |             viewModel = viewModel, | ||||||
|             open = open |             open = open | ||||||
|         ), |         ) | ||||||
|         popUp = popUp |  | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Composable | @Composable | ||||||
| fun FriendsOverviewScreen( | fun FriendsOverviewScreen( | ||||||
|     friendsOverviewActions: FriendsOverviewActions, |     popUp: () -> Unit, | ||||||
|     popUp: () -> Unit |     uiState: FriendsOverviewUiState, | ||||||
|  |     friendsOverviewActions: FriendsOverviewActions | ||||||
| ) { | ) { | ||||||
|     val friends = friendsOverviewActions.getFriendsFlow().collectAsState(initial = emptyList()) |     val friends = friendsOverviewActions.getFriendsFlow().collectAsState(initial = emptyList()) | ||||||
| 
 | 
 | ||||||
|     SecondaryScreenTemplate( |     Scaffold( | ||||||
|         title = "TODO there needs to be a search field here", // TODO |         topBar = { | ||||||
|         popUp = popUp |             TopAppBar( | ||||||
|     ) { |                 title = { | ||||||
|         LazyColumn { |                     // TODO Link to each other | ||||||
|  |                     SearchField( | ||||||
|  |                         value = uiState.queryString, | ||||||
|  |                         onValueChange = friendsOverviewActions.onQueryStringChange, | ||||||
|  |                         onSubmit = friendsOverviewActions.onSubmit, | ||||||
|  |                         label = AppText.search_friends | ||||||
|  |                     ) | ||||||
|  |                 }, | ||||||
|  |                 navigationIcon = { | ||||||
|  |                     IconButton(onClick = popUp) { | ||||||
|  |                         Icon( | ||||||
|  |                             imageVector = Icons.Default.ArrowBack, | ||||||
|  |                             contentDescription = resources().getString(R.string.go_back) | ||||||
|  |                         ) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 // TODO Add inbox action | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |     ) { paddingValues -> | ||||||
|  |         LazyColumn ( | ||||||
|  |             modifier = Modifier.padding(paddingValues) | ||||||
|  |         ) { | ||||||
|             if (friends.value.isEmpty()) { |             if (friends.value.isEmpty()) { | ||||||
|                 // Show a quick button to search friends when the user does not have any friends yet. |                 // Show a quick button to search friends when the user does not have any friends yet. | ||||||
|                 item { |                 item { | ||||||
|  | @ -90,7 +127,9 @@ fun FriendsOverviewScreen( | ||||||
|             items(friends.value) { friend -> |             items(friends.value) { friend -> | ||||||
|                 FriendsEntry( |                 FriendsEntry( | ||||||
|                     user = friend.first, |                     user = friend.first, | ||||||
|                     friendship = friend.second |                     friendship = friend.second, | ||||||
|  |                     viewProfile = { userId -> friendsOverviewActions.viewProfile(userId) }, | ||||||
|  |                     removeFriend = friendsOverviewActions.removeFriend | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -102,11 +141,16 @@ fun FriendsOverviewScreen( | ||||||
| fun FriendsOverviewPreview() { | fun FriendsOverviewPreview() { | ||||||
|     StudeezTheme { |     StudeezTheme { | ||||||
|         FriendsOverviewScreen( |         FriendsOverviewScreen( | ||||||
|  |             popUp = {}, | ||||||
|  |             uiState = FriendsOverviewUiState(""), | ||||||
|             friendsOverviewActions = FriendsOverviewActions( |             friendsOverviewActions = FriendsOverviewActions( | ||||||
|                 getFriendsFlow = { emptyFlow() }, |                 getFriendsFlow = { emptyFlow() }, | ||||||
|                 searchFriends = {} |                 searchFriends = {}, | ||||||
|             ), |                 onQueryStringChange = {}, | ||||||
|             popUp = {} |                 onSubmit = {}, | ||||||
|  |                 viewProfile = {}, | ||||||
|  |                 removeFriend = {} | ||||||
|  |             ) | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -114,7 +158,9 @@ fun FriendsOverviewPreview() { | ||||||
| @Composable | @Composable | ||||||
| fun FriendsEntry( | fun FriendsEntry( | ||||||
|     user: User, |     user: User, | ||||||
|     friendship: Friendship |     friendship: Friendship, | ||||||
|  |     viewProfile: (String) -> Unit, | ||||||
|  |     removeFriend: (Friendship) -> Unit | ||||||
| ) { | ) { | ||||||
|     // TODO Styling |     // TODO Styling | ||||||
|     Row ( |     Row ( | ||||||
|  | @ -162,7 +208,11 @@ fun FriendsEntry( | ||||||
|         Box( |         Box( | ||||||
|             modifier = Modifier.fillMaxWidth(0.15f) |             modifier = Modifier.fillMaxWidth(0.15f) | ||||||
|         ) { |         ) { | ||||||
|             ThreeDots(friendship = friendship) |             FriendsOverviewDropDown( | ||||||
|  |                 friendship = friendship, | ||||||
|  |                 viewProfile = viewProfile, | ||||||
|  |                 removeFriend = removeFriend | ||||||
|  |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -182,17 +232,23 @@ fun FriendsEntryPreview() { | ||||||
|                 friendId = "someId", |                 friendId = "someId", | ||||||
|                 friendsSince = Timestamp.now(), |                 friendsSince = Timestamp.now(), | ||||||
|                 accepted = true |                 accepted = true | ||||||
|             ) |             ), | ||||||
|  |             viewProfile = {}, | ||||||
|  |             removeFriend = {} | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Composable | @Composable | ||||||
| fun ThreeDots( | fun FriendsOverviewDropDown( | ||||||
|     friendship: Friendship |     friendship: Friendship, | ||||||
|  |     viewProfile: (String) -> Unit, | ||||||
|  |     removeFriend: (Friendship) -> Unit | ||||||
| ) { | ) { | ||||||
|  |     var expanded by remember { mutableStateOf(false) } | ||||||
|  | 
 | ||||||
|     IconButton( |     IconButton( | ||||||
|         onClick = { /* TODO Open dropdown */ } |         onClick = { expanded = true } | ||||||
|     ) { |     ) { | ||||||
|         Icon( |         Icon( | ||||||
|             imageVector = ImageVector.vectorResource(id = R.drawable.ic_more_horizontal), |             imageVector = ImageVector.vectorResource(id = R.drawable.ic_more_horizontal), | ||||||
|  | @ -200,19 +256,40 @@ fun ThreeDots( | ||||||
|             modifier = Modifier.fillMaxSize() |             modifier = Modifier.fillMaxSize() | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     DropdownMenu( | ||||||
|  |         expanded = expanded, | ||||||
|  |         onDismissRequest = { expanded = false } | ||||||
|  |     ) { | ||||||
|  |         DrawerEntry( | ||||||
|  |             icon = Icons.Default.Person, | ||||||
|  |             text = stringResource(id = AppText.show_profile) | ||||||
|  |         ) { | ||||||
|  |             viewProfile(friendship.friendId) | ||||||
|  |         } | ||||||
|  |         DrawerEntry( | ||||||
|  |             icon = Icons.Default.Delete, | ||||||
|  |             text = stringResource(id = AppText.remove_friend) | ||||||
|  |         ) { | ||||||
|  |             removeFriend(friendship) | ||||||
|  |             expanded = false | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Preview | @Preview | ||||||
| @Composable | @Composable | ||||||
| fun ThreeDotsPreview() { | fun FriendsOverviewDropDownPreview() { | ||||||
|     StudeezTheme { |     StudeezTheme { | ||||||
|         ThreeDots( |         FriendsOverviewDropDown( | ||||||
|             friendship = Friendship( |             friendship = Friendship( | ||||||
|                 id = "", |                 id = "", | ||||||
|                 friendId = "someId", |                 friendId = "someId", | ||||||
|                 friendsSince = Timestamp.now(), |                 friendsSince = Timestamp.now(), | ||||||
|                 accepted = true |                 accepted = true | ||||||
|             ) |             ), | ||||||
|  |             viewProfile = {}, | ||||||
|  |             removeFriend = { } | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | package be.ugent.sel.studeez.screens.friends.friends_overview | ||||||
|  | 
 | ||||||
|  | data class FriendsOverviewUiState( | ||||||
|  |     val userId: String, | ||||||
|  |     val queryString: String = "" | ||||||
|  | ) | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| package be.ugent.sel.studeez.screens.friend | package be.ugent.sel.studeez.screens.friends.friends_overview | ||||||
| 
 | 
 | ||||||
|  | import androidx.compose.runtime.mutableStateOf | ||||||
| import be.ugent.sel.studeez.data.local.models.Friendship | import be.ugent.sel.studeez.data.local.models.Friendship | ||||||
| import be.ugent.sel.studeez.data.local.models.User | import be.ugent.sel.studeez.data.local.models.User | ||||||
| import be.ugent.sel.studeez.domain.FriendshipDAO | import be.ugent.sel.studeez.domain.FriendshipDAO | ||||||
|  | @ -7,6 +8,7 @@ import be.ugent.sel.studeez.domain.LogService | ||||||
| import be.ugent.sel.studeez.domain.UserDAO | import be.ugent.sel.studeez.domain.UserDAO | ||||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | import be.ugent.sel.studeez.screens.StudeezViewModel | ||||||
|  | import be.ugent.sel.studeez.screens.profile.public_profile.SelectedProfileState | ||||||
| import dagger.hilt.android.lifecycle.HiltViewModel | import dagger.hilt.android.lifecycle.HiltViewModel | ||||||
| import kotlinx.coroutines.flow.Flow | import kotlinx.coroutines.flow.Flow | ||||||
| import kotlinx.coroutines.flow.combine | import kotlinx.coroutines.flow.combine | ||||||
|  | @ -17,11 +19,19 @@ import javax.inject.Inject | ||||||
| class FriendsOverviewViewModel @Inject constructor( | class FriendsOverviewViewModel @Inject constructor( | ||||||
|     private val userDAO: UserDAO, |     private val userDAO: UserDAO, | ||||||
|     private val friendshipDAO: FriendshipDAO, |     private val friendshipDAO: FriendshipDAO, | ||||||
|  |     private val selectedProfileState: SelectedProfileState, | ||||||
|     logService: LogService |     logService: LogService | ||||||
| ) : StudeezViewModel(logService) { | ) : StudeezViewModel(logService) { | ||||||
| 
 | 
 | ||||||
|  |     var uiState = mutableStateOf(FriendsOverviewUiState( | ||||||
|  |         userId = selectedProfileState.selectedUserId | ||||||
|  |     )) | ||||||
|  |         private set | ||||||
|  | 
 | ||||||
|     fun getAllFriends(): Flow<List<Pair<User, Friendship>>> { |     fun getAllFriends(): Flow<List<Pair<User, Friendship>>> { | ||||||
|         return friendshipDAO.getAllFriendships() |         return friendshipDAO.getAllFriendships( | ||||||
|  |                 userId = uiState.value.userId | ||||||
|  |             ) | ||||||
|             .flatMapConcat { friendships -> |             .flatMapConcat { friendships -> | ||||||
|                 val userFlows = friendships.map { friendship -> |                 val userFlows = friendships.map { friendship -> | ||||||
|                     userDAO.getUserDetails(friendship.friendId) |                     userDAO.getUserDetails(friendship.friendId) | ||||||
|  | @ -38,4 +48,31 @@ class FriendsOverviewViewModel @Inject constructor( | ||||||
|         open(StudeezDestinations.SEARCH_FRIENDS_SCREEN) |         open(StudeezDestinations.SEARCH_FRIENDS_SCREEN) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fun onQueryStringChange(newValue: String) { | ||||||
|  |         uiState.value = uiState.value.copy( | ||||||
|  |             queryString = newValue | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun onSubmit(open: (String) -> Unit) { | ||||||
|  |         val query = uiState.value.queryString // TODO Pass as argument | ||||||
|  |         open(StudeezDestinations.SEARCH_FRIENDS_SCREEN) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun viewProfile( | ||||||
|  |         userId: String, | ||||||
|  |         open: (String) -> Unit | ||||||
|  |     ) { | ||||||
|  |         selectedProfileState.selectedUserId = userId | ||||||
|  |         open(StudeezDestinations.PUBLIC_PROFILE_SCREEN) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun removeFriend( | ||||||
|  |         friendship: Friendship | ||||||
|  |     ) { | ||||||
|  |         friendshipDAO.removeFriendship( | ||||||
|  |             friendship = friendship | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
		Reference in a new issue