From bc7753fce53475fbe2e214e4f68e4fc1d2fdf7a9 Mon Sep 17 00:00:00 2001 From: tdpeuter Date: Mon, 15 May 2023 14:11:28 +0200 Subject: [PATCH] Move friends overview to new package and new stuff --- .../FriendsOverviewScreen.kt | 143 ++++++++++++++---- .../FriendsOverviewUiState.kt | 6 + .../FriendsOverviewViewModel.kt | 41 ++++- 3 files changed, 155 insertions(+), 35 deletions(-) rename app/src/main/java/be/ugent/sel/studeez/screens/{friend => friends/friends_overview}/FriendsOverviewScreen.kt (57%) create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewUiState.kt rename app/src/main/java/be/ugent/sel/studeez/screens/{friend => friends/friends_overview}/FriendsOverviewViewModel.kt (53%) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewScreen.kt similarity index 57% rename from app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewScreen.kt index c9e80f5..7e2462d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewScreen.kt @@ -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.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.Person +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.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -22,7 +23,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import be.ugent.sel.studeez.R 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.data.local.models.Friendship 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( val getFriendsFlow: () -> Flow>>, - val searchFriends: () -> Unit + val searchFriends: () -> Unit, + val onQueryStringChange: (String) -> Unit, + val onSubmit: () -> Unit, + val viewProfile: (String) -> Unit, + val removeFriend: (Friendship) -> Unit ) fun getFriendsOverviewActions( @@ -44,7 +50,13 @@ fun getFriendsOverviewActions( ): FriendsOverviewActions { return FriendsOverviewActions( 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, viewModel: FriendsOverviewViewModel ) { + val uiState by viewModel.uiState FriendsOverviewScreen( + popUp = popUp, + uiState = uiState, friendsOverviewActions = getFriendsOverviewActions( viewModel = viewModel, open = open - ), - popUp = popUp + ) ) } @Composable fun FriendsOverviewScreen( - friendsOverviewActions: FriendsOverviewActions, - popUp: () -> Unit + popUp: () -> Unit, + uiState: FriendsOverviewUiState, + friendsOverviewActions: FriendsOverviewActions ) { val friends = friendsOverviewActions.getFriendsFlow().collectAsState(initial = emptyList()) - - SecondaryScreenTemplate( - title = "TODO there needs to be a search field here", // TODO - popUp = popUp - ) { - LazyColumn { + + Scaffold( + topBar = { + TopAppBar( + title = { + // 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()) { // Show a quick button to search friends when the user does not have any friends yet. item { @@ -90,7 +127,9 @@ fun FriendsOverviewScreen( items(friends.value) { friend -> FriendsEntry( 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() { StudeezTheme { FriendsOverviewScreen( + popUp = {}, + uiState = FriendsOverviewUiState(""), friendsOverviewActions = FriendsOverviewActions( getFriendsFlow = { emptyFlow() }, - searchFriends = {} - ), - popUp = {} + searchFriends = {}, + onQueryStringChange = {}, + onSubmit = {}, + viewProfile = {}, + removeFriend = {} + ) ) } } @@ -114,7 +158,9 @@ fun FriendsOverviewPreview() { @Composable fun FriendsEntry( user: User, - friendship: Friendship + friendship: Friendship, + viewProfile: (String) -> Unit, + removeFriend: (Friendship) -> Unit ) { // TODO Styling Row ( @@ -162,7 +208,11 @@ fun FriendsEntry( Box( modifier = Modifier.fillMaxWidth(0.15f) ) { - ThreeDots(friendship = friendship) + FriendsOverviewDropDown( + friendship = friendship, + viewProfile = viewProfile, + removeFriend = removeFriend + ) } } } @@ -182,17 +232,23 @@ fun FriendsEntryPreview() { friendId = "someId", friendsSince = Timestamp.now(), accepted = true - ) + ), + viewProfile = {}, + removeFriend = {} ) } } @Composable -fun ThreeDots( - friendship: Friendship +fun FriendsOverviewDropDown( + friendship: Friendship, + viewProfile: (String) -> Unit, + removeFriend: (Friendship) -> Unit ) { + var expanded by remember { mutableStateOf(false) } + IconButton( - onClick = { /* TODO Open dropdown */ } + onClick = { expanded = true } ) { Icon( imageVector = ImageVector.vectorResource(id = R.drawable.ic_more_horizontal), @@ -200,19 +256,40 @@ fun ThreeDots( 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 @Composable -fun ThreeDotsPreview() { +fun FriendsOverviewDropDownPreview() { StudeezTheme { - ThreeDots( + FriendsOverviewDropDown( friendship = Friendship( id = "", friendId = "someId", friendsSince = Timestamp.now(), accepted = true - ) + ), + viewProfile = {}, + removeFriend = { } ) } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewUiState.kt new file mode 100644 index 0000000..8672814 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewUiState.kt @@ -0,0 +1,6 @@ +package be.ugent.sel.studeez.screens.friends.friends_overview + +data class FriendsOverviewUiState( + val userId: String, + val queryString: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewViewModel.kt similarity index 53% rename from app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewViewModel.kt index 0dec506..ce0c5af 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/friends/friends_overview/FriendsOverviewViewModel.kt @@ -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.User 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.navigation.StudeezDestinations import be.ugent.sel.studeez.screens.StudeezViewModel +import be.ugent.sel.studeez.screens.profile.public_profile.SelectedProfileState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine @@ -17,11 +19,19 @@ import javax.inject.Inject class FriendsOverviewViewModel @Inject constructor( private val userDAO: UserDAO, private val friendshipDAO: FriendshipDAO, + private val selectedProfileState: SelectedProfileState, logService: LogService ) : StudeezViewModel(logService) { + var uiState = mutableStateOf(FriendsOverviewUiState( + userId = selectedProfileState.selectedUserId + )) + private set + fun getAllFriends(): Flow>> { - return friendshipDAO.getAllFriendships() + return friendshipDAO.getAllFriendships( + userId = uiState.value.userId + ) .flatMapConcat { friendships -> val userFlows = friendships.map { friendship -> userDAO.getUserDetails(friendship.friendId) @@ -38,4 +48,31 @@ class FriendsOverviewViewModel @Inject constructor( 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 + ) + } + } \ No newline at end of file