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