#63 Add getFriendshipCount and add to profile screen

This commit is contained in:
Tibo De Peuter 2023-05-14 12:07:56 +02:00
parent bb64875bad
commit 3b50054ff5
7 changed files with 111 additions and 9 deletions

View file

@ -31,7 +31,11 @@ import be.ugent.sel.studeez.common.ext.defaultButtonShape
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun BasicTextButton(@StringRes text: Int, modifier: Modifier, action: () -> Unit) {
fun BasicTextButton(
@StringRes text: Int,
modifier: Modifier,
action: () -> Unit
) {
TextButton(
onClick = action,
modifier = modifier

View file

@ -1,5 +1,6 @@
package be.ugent.sel.studeez.domain.implementation
import be.ugent.sel.studeez.common.snackbar.SnackbarManager
import be.ugent.sel.studeez.data.local.models.Friendship
import be.ugent.sel.studeez.domain.AccountDAO
import be.ugent.sel.studeez.domain.FriendshipDAO
@ -7,8 +8,14 @@ import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.snapshots
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import be.ugent.sel.studeez.R.string as AppText
class FirebaseFriendshipDAO @Inject constructor(
private val firestore: FirebaseFirestore,
@ -27,7 +34,22 @@ class FirebaseFriendshipDAO @Inject constructor(
}
override fun getFriendshipCount(): Flow<Int> {
TODO("Not yet implemented")
return flow {
val friendshipCount = suspendCoroutine { continuation ->
currentUserDocument()
.collection(FirebaseCollections.FRIENDS_COLLECTION)
.get()
.addOnSuccessListener { querySnapshot ->
continuation.resume(querySnapshot.size())
}
.addOnFailureListener { exception ->
continuation.resumeWithException(exception)
}
}
emit(friendshipCount)
}.catch {
SnackbarManager.showMessage(AppText.generic_error)
}
}
override fun getFriendshipDetails(id: String): Friendship {

View file

@ -30,6 +30,7 @@ object StudeezDestinations {
const val EDIT_TASK_FORM = "edit_task"
// Friends flow
const val FRIENDS_OVERVIEW_SCREEN = "friends_overview"
const val SEARCH_FRIENDS_SCREEN = "search_friends"
// Create & edit screens

View file

@ -220,6 +220,10 @@ fun StudeezNavGraph(
}
// Friends flow
composable(StudeezDestinations.FRIENDS_OVERVIEW_SCREEN) {
// TODO
}
composable(StudeezDestinations.SEARCH_FRIENDS_SCREEN) {
// TODO
}

View file

@ -1,30 +1,38 @@
package be.ugent.sel.studeez.screens.profile
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Button
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.Headline
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.ext.defaultButtonShape
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import be.ugent.sel.studeez.R.string as AppText
data class ProfileActions(
val getUsername: suspend CoroutineScope.() -> String?,
val getBiography: suspend CoroutineScope.() -> String?,
val onEditProfileClick: () -> Unit
val getAmountOfFriends: () -> Flow<Int>,
val onEditProfileClick: () -> Unit,
val onViewFriendsClick: () -> Unit
)
fun getProfileActions(
@ -34,7 +42,9 @@ fun getProfileActions(
return ProfileActions(
getUsername = { viewModel.getUsername() },
getBiography = { viewModel.getBiography() },
onEditProfileClick = { viewModel.onEditProfileClick(open) }
getAmountOfFriends = { viewModel.getAmountOfFriends() },
onEditProfileClick = { viewModel.onEditProfileClick(open) },
onViewFriendsClick = { viewModel.onViewFriendsClick(open) }
)
}
@ -60,6 +70,8 @@ fun ProfileScreen(
) {
var username: String? by remember { mutableStateOf("") }
var biography: String? by remember { mutableStateOf("") }
val amountOfFriends = profileActions.getAmountOfFriends().collectAsState(initial = 0)
LaunchedEffect(key1 = Unit) {
username = profileActions.getUsername(this)
biography = profileActions.getBiography(this)
@ -76,6 +88,21 @@ fun ProfileScreen(
item {
Headline(text = username ?: resources().getString(AppText.no_username))
}
item {
Row(
horizontalArrangement = Arrangement.spacedBy(5.dp),
modifier = Modifier.fillMaxWidth()
.wrapContentWidth(align = Alignment.CenterHorizontally)
) {
AmountOfFriendsButton(
amountOfFriends = amountOfFriends.value
) {
profileActions.onViewFriendsClick()
}
}
}
item {
Text(
text = biography ?: "",
@ -96,7 +123,6 @@ fun EditAction(
imageVector = Icons.Default.Edit,
contentDescription = resources().getString(AppText.edit_profile)
)
}
}
@ -104,8 +130,38 @@ fun EditAction(
@Composable
fun ProfileScreenPreview() {
ProfileScreen(
profileActions = ProfileActions({ null }, { null }, {}),
profileActions = ProfileActions({ null }, { null }, { emptyFlow() }, {}, {}),
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {})
)
}
@Composable
fun AmountOfFriendsButton(
amountOfFriends: Int,
onClick: () -> Unit
){
Button(
onClick = onClick,
shape = defaultButtonShape()
) {
Text(
text = resources().getQuantityString(
/* id = */ R.plurals.friends_amount,
/* quantity = */ amountOfFriends,
/* ...formatArgs = */ amountOfFriends
)
)
}
}
@Preview
@Composable
fun AmountOfFriendsButtonPreview() {
StudeezTheme {
Column {
AmountOfFriendsButton(amountOfFriends = 1) { }
AmountOfFriendsButton(amountOfFriends = 100) { }
}
}
}

View file

@ -1,15 +1,18 @@
package be.ugent.sel.studeez.screens.profile
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 javax.inject.Inject
@HiltViewModel
class ProfileViewModel @Inject constructor(
private val userDAO: UserDAO,
private val friendshipDAO: FriendshipDAO,
logService: LogService
) : StudeezViewModel(logService) {
@ -21,8 +24,16 @@ class ProfileViewModel @Inject constructor(
return userDAO.getLoggedInUser().biography
}
fun getAmountOfFriends(): Flow<Int> {
return friendshipDAO.getFriendshipCount()
}
fun onEditProfileClick(open: (String) -> Unit) {
open(StudeezDestinations.EDIT_PROFILE_SCREEN)
}
fun onViewFriendsClick(open: (String) -> Unit) {
open(StudeezDestinations.FRIENDS_OVERVIEW_SCREEN)
}
}

View file

@ -20,7 +20,7 @@
<!-- Messages -->
<string name="success">Success!</string>
<string name="try_again">Try again</string>
<string name="generic_error">Something wrong happened. Please try again.</string>
<string name="generic_error">Something went wrong. Please try again.</string>
<string name="email_error">Please insert a valid email.</string>
<!-- ========== NavBar ========== -->
@ -107,6 +107,10 @@
<string name="friends">Friends</string>
<string name="friend">Friend</string>
<plurals name="friends_amount">
<item quantity="one">%d Friend</item>
<item quantity="other">%d Friends</item>
</plurals>
<string name="add_friend_not_possible_yet">Adding friends still needs to be implemented. Hang on tight!</string> <!-- TODO Remove this description line once implemented. -->
<!-- ========== Create & edit screens ========== -->