From 87fe4767245571119e97c98ec2020a23c481b831 Mon Sep 17 00:00:00 2001 From: tdpeuter Date: Sun, 14 May 2023 13:10:32 +0200 Subject: [PATCH] Basic friends overview screen --- .../screens/friend/FriendsOverviewScreen.kt | 218 ++++++++++++++++++ .../friend/FriendsOverviewViewModel.kt | 41 ++++ .../main/res/drawable/ic_more_horizontal.xml | 5 + app/src/main/res/values/strings.xml | 2 + 4 files changed, 266 insertions(+) create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewScreen.kt create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewViewModel.kt create mode 100644 app/src/main/res/drawable/ic_more_horizontal.xml 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/friend/FriendsOverviewScreen.kt new file mode 100644 index 0000000..c9e80f5 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewScreen.kt @@ -0,0 +1,218 @@ +package be.ugent.sel.studeez.screens.friend + +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.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.vectorResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +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.ext.basicButton +import be.ugent.sel.studeez.data.local.models.Friendship +import be.ugent.sel.studeez.data.local.models.User +import be.ugent.sel.studeez.resources +import be.ugent.sel.studeez.ui.theme.StudeezTheme +import com.google.firebase.Timestamp +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow +import be.ugent.sel.studeez.R.string as AppText + +data class FriendsOverviewActions( + val getFriendsFlow: () -> Flow>>, + val searchFriends: () -> Unit +) + +fun getFriendsOverviewActions( + viewModel: FriendsOverviewViewModel, + open: (String) -> Unit +): FriendsOverviewActions { + return FriendsOverviewActions( + getFriendsFlow = viewModel::getAllFriends, + searchFriends = { viewModel.searchFriends(open) } + ) +} + +@Composable +fun FriendsOveriewRoute( + open: (String) -> Unit, + popUp: () -> Unit, + viewModel: FriendsOverviewViewModel +) { + FriendsOverviewScreen( + friendsOverviewActions = getFriendsOverviewActions( + viewModel = viewModel, + open = open + ), + popUp = popUp + ) +} + +@Composable +fun FriendsOverviewScreen( + friendsOverviewActions: FriendsOverviewActions, + popUp: () -> Unit +) { + val friends = friendsOverviewActions.getFriendsFlow().collectAsState(initial = emptyList()) + + SecondaryScreenTemplate( + title = "TODO there needs to be a search field here", // TODO + popUp = popUp + ) { + LazyColumn { + if (friends.value.isEmpty()) { + // Show a quick button to search friends when the user does not have any friends yet. + item { + BasicButton( + text = AppText.no_friends, + modifier = Modifier.basicButton() + ) { + friendsOverviewActions.searchFriends() + } + } + } + + items(friends.value) { friend -> + FriendsEntry( + user = friend.first, + friendship = friend.second + ) + } + } + } +} + +@Preview +@Composable +fun FriendsOverviewPreview() { + StudeezTheme { + FriendsOverviewScreen( + friendsOverviewActions = FriendsOverviewActions( + getFriendsFlow = { emptyFlow() }, + searchFriends = {} + ), + popUp = {} + ) + } +} + +@Composable +fun FriendsEntry( + user: User, + friendship: Friendship +) { + // TODO Styling + Row ( + modifier = Modifier + .fillMaxWidth() + ) { + Box( + modifier = Modifier + .fillMaxWidth(0.15f) + .background(MaterialTheme.colors.primary, CircleShape) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_visibility_on), + contentDescription = null, + modifier = Modifier + .fillMaxHeight() + .align(Alignment.Center), + tint = MaterialTheme.colors.onPrimary + ) + } + + Box ( + modifier = Modifier + .fillMaxWidth(0.65f) + ) { + Column ( + modifier = Modifier + .padding(vertical = 4.dp) + ) { + Text( + text = user.username, + fontSize = 16.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = "${resources().getString(AppText.app_name)} ${resources().getString(AppText.friend)}", + fontSize = 14.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + + Box( + modifier = Modifier.fillMaxWidth(0.15f) + ) { + ThreeDots(friendship = friendship) + } + } +} + +@Preview +@Composable +fun FriendsEntryPreview() { + StudeezTheme { + FriendsEntry( + user = User( + id = "", + username = "Tibo De Peuter", + biography = "short bio" + ), + friendship = Friendship( + id = "", + friendId = "someId", + friendsSince = Timestamp.now(), + accepted = true + ) + ) + } +} + +@Composable +fun ThreeDots( + friendship: Friendship +) { + IconButton( + onClick = { /* TODO Open dropdown */ } + ) { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_more_horizontal), + contentDescription = resources().getString(AppText.view_more), + modifier = Modifier.fillMaxSize() + ) + } +} + +@Preview +@Composable +fun ThreeDotsPreview() { + StudeezTheme { + ThreeDots( + friendship = Friendship( + id = "", + friendId = "someId", + friendsSince = Timestamp.now(), + accepted = true + ) + ) + } +} \ 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/friend/FriendsOverviewViewModel.kt new file mode 100644 index 0000000..0dec506 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/friend/FriendsOverviewViewModel.kt @@ -0,0 +1,41 @@ +package be.ugent.sel.studeez.screens.friend + +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 +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.flow.combine +import kotlinx.coroutines.flow.flatMapConcat +import javax.inject.Inject + +@HiltViewModel +class FriendsOverviewViewModel @Inject constructor( + private val userDAO: UserDAO, + private val friendshipDAO: FriendshipDAO, + logService: LogService +) : StudeezViewModel(logService) { + + fun getAllFriends(): Flow>> { + return friendshipDAO.getAllFriendships() + .flatMapConcat { friendships -> + val userFlows = friendships.map { friendship -> + userDAO.getUserDetails(friendship.friendId) + } + combine(userFlows) { users -> + friendships.zip(users) { friendship, user -> + Pair(user, friendship) + } + } + } + } + + fun searchFriends(open: (String) -> Unit) { + open(StudeezDestinations.SEARCH_FRIENDS_SCREEN) + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_more_horizontal.xml b/app/src/main/res/drawable/ic_more_horizontal.xml new file mode 100644 index 0000000..afbe22d --- /dev/null +++ b/app/src/main/res/drawable/ic_more_horizontal.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f370b35..1ae1bc8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ Go back Next Start + View more Success! @@ -112,6 +113,7 @@ %d Friends Adding friends still needs to be implemented. Hang on tight! + You don\'t have any friends yet. Add one!