Move friends overview to new package and new stuff

This commit is contained in:
Tibo De Peuter 2023-05-15 14:11:28 +02:00
parent 71b9550bd0
commit bc7753fce5
3 changed files with 155 additions and 35 deletions

View file

@ -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 = { }
) )
} }
} }

View file

@ -0,0 +1,6 @@
package be.ugent.sel.studeez.screens.friends.friends_overview
data class FriendsOverviewUiState(
val userId: String,
val queryString: String = ""
)

View file

@ -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
)
}
} }