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

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.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<List<Pair<User, Friendship>>> {
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
)
}
}