#63 Add getFriendshipCount and add to profile screen
This commit is contained in:
parent
bb64875bad
commit
3b50054ff5
7 changed files with 111 additions and 9 deletions
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -220,6 +220,10 @@ fun StudeezNavGraph(
|
|||
}
|
||||
|
||||
// Friends flow
|
||||
composable(StudeezDestinations.FRIENDS_OVERVIEW_SCREEN) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SEARCH_FRIENDS_SCREEN) {
|
||||
// TODO
|
||||
}
|
||||
|
|
|
@ -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) { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
|
@ -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 ========== -->
|
||||
|
|
Reference in a new issue