QOL improvements & friendsSessionsDAOstuff
This commit is contained in:
		
							parent
							
								
									10c86c9bf0
								
							
						
					
					
						commit
						a814bd74d7
					
				
					 9 changed files with 154 additions and 46 deletions
				
			
		|  | @ -0,0 +1,44 @@ | |||
| package be.ugent.sel.studeez.common.composable | ||||
| 
 | ||||
| import androidx.compose.foundation.background | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.size | ||||
| import androidx.compose.foundation.shape.CircleShape | ||||
| import androidx.compose.material.Icon | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.Person | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import be.ugent.sel.studeez.R | ||||
| import be.ugent.sel.studeez.ui.theme.StudeezTheme | ||||
| 
 | ||||
| @Composable | ||||
| fun ProfilePicture() { | ||||
|     Box( | ||||
|         modifier = Modifier | ||||
|             .size(40.dp) | ||||
|             .background(MaterialTheme.colors.primary, CircleShape) | ||||
|     ) { | ||||
|         Icon( | ||||
|             imageVector = Icons.Default.Person, | ||||
|             contentDescription = stringResource(id = R.string.username), | ||||
|             modifier = Modifier | ||||
|                 .size(30.dp) | ||||
|                 .align(Alignment.Center), | ||||
|             tint = MaterialTheme.colors.onPrimary | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun ProfilePicturePreview() { | ||||
|     StudeezTheme { | ||||
|         ProfilePicture() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| package be.ugent.sel.studeez.data.remote | ||||
| 
 | ||||
| object FirebaseSessionReport { | ||||
|     const val STUDYTIME: String = "studyTime" | ||||
|     const val ENDTIME: String = "endTime" | ||||
| } | ||||
|  | @ -1,12 +1,19 @@ | |||
| package be.ugent.sel.studeez.domain | ||||
| 
 | ||||
| import be.ugent.sel.studeez.data.local.models.SessionReport | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| 
 | ||||
| interface SessionDAO { | ||||
| 
 | ||||
|     fun getSessions(): Flow<List<SessionReport>> | ||||
|     suspend fun getSessionsOfUser(userId: String): List<SessionReport> | ||||
| 
 | ||||
|     /** | ||||
|      * Return a list of pairs, containing the username and all the studysessions of that user. | ||||
|      */ | ||||
|     fun getFriendsSessions(): Flow<List<Pair<String,List<SessionReport>>>> | ||||
| 
 | ||||
|     fun saveSession(newSessionReport: SessionReport) | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,6 +27,10 @@ interface UserDAO { | |||
|         userId: String | ||||
|     ): Flow<User> | ||||
| 
 | ||||
|     suspend fun getUsername( | ||||
|         userId: String | ||||
|     ): String | ||||
| 
 | ||||
|     /** | ||||
|      * @return information on the currently logged in user. | ||||
|      */ | ||||
|  |  | |||
|  | @ -1,19 +1,33 @@ | |||
| package be.ugent.sel.studeez.domain.implementation | ||||
| 
 | ||||
| import be.ugent.sel.studeez.data.local.models.SessionReport | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseSessionReport | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.ENDTIME | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.STUDYTIME | ||||
| import be.ugent.sel.studeez.domain.AccountDAO | ||||
| import be.ugent.sel.studeez.domain.FriendshipDAO | ||||
| import be.ugent.sel.studeez.domain.SessionDAO | ||||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.SESSION_COLLECTION | ||||
| import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.USER_COLLECTION | ||||
| import com.google.firebase.Timestamp | ||||
| import com.google.firebase.firestore.CollectionReference | ||||
| import com.google.firebase.firestore.FirebaseFirestore | ||||
| import com.google.firebase.firestore.ktx.getField | ||||
| import com.google.firebase.firestore.ktx.snapshots | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.emptyFlow | ||||
| import kotlinx.coroutines.flow.map | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class FirebaseSessionDAO @Inject constructor( | ||||
|     private val firestore: FirebaseFirestore, | ||||
|     private val auth: AccountDAO | ||||
|     private val auth: AccountDAO, | ||||
|     private val userDAO: UserDAO, | ||||
|     private val friendshipDAO: FriendshipDAO | ||||
| ) : SessionDAO { | ||||
| 
 | ||||
|     override fun getSessions(): Flow<List<SessionReport>> { | ||||
|  | @ -22,6 +36,34 @@ class FirebaseSessionDAO @Inject constructor( | |||
|             .map { it.toObjects(SessionReport::class.java) } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getSessionsOfUser(userId: String): List<SessionReport> { | ||||
|         val collection = firestore.collection(USER_COLLECTION) | ||||
|             .document(userId) | ||||
|             .collection(SESSION_COLLECTION) | ||||
|             .get().await() | ||||
|         val list: MutableList<SessionReport> = mutableListOf() | ||||
|         for (document in collection) { | ||||
|             val id = document.id | ||||
|             val studyTime: Int = document.getField<Int>(STUDYTIME)!! | ||||
|             val endTime: Timestamp = document.getField<Timestamp>(ENDTIME)!! | ||||
|             list.add(SessionReport(id, studyTime, endTime)) | ||||
|         } | ||||
|         return list | ||||
|     } | ||||
| 
 | ||||
|     override fun getFriendsSessions(): Flow<List<Pair<String, List<SessionReport>>>> { | ||||
|         return friendshipDAO.getAllFriendships(auth.currentUserId) | ||||
|             .map { friendships -> | ||||
|                 friendships.map { friendship -> | ||||
|                     val userId: String = friendship.friendId | ||||
|                     val username = userDAO.getUsername(userId) | ||||
|                     val userSessions = getSessionsOfUser(userId) | ||||
| 
 | ||||
|                     Pair(username, userSessions) | ||||
|                 } | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     override fun saveSession(newSessionReport: SessionReport) { | ||||
|         currentUserSessionsCollection().add(newSessionReport) | ||||
|     } | ||||
|  | @ -31,7 +73,7 @@ class FirebaseSessionDAO @Inject constructor( | |||
|     } | ||||
| 
 | ||||
|     private fun currentUserSessionsCollection(): CollectionReference = | ||||
|         firestore.collection(FirebaseCollections.USER_COLLECTION) | ||||
|         firestore.collection(USER_COLLECTION) | ||||
|             .document(auth.currentUserId) | ||||
|             .collection(FirebaseCollections.SESSION_COLLECTION) | ||||
|             .collection(SESSION_COLLECTION) | ||||
| } | ||||
|  | @ -61,6 +61,13 @@ class FirebaseUserDAO @Inject constructor( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getUsername(userId: String): String { | ||||
|         val user = firestore.collection(USER_COLLECTION) | ||||
|             .document(userId) | ||||
|             .get().await() | ||||
|         return user.getString(USERNAME)!! | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getLoggedInUser(): User { | ||||
|         val userDocument = currentUserDocument().get().await() | ||||
|         return User( | ||||
|  |  | |||
|  | @ -14,7 +14,6 @@ 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 | ||||
|  | @ -23,6 +22,7 @@ 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.ProfilePicture | ||||
| 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 | ||||
|  | @ -162,29 +162,21 @@ fun FriendsEntry( | |||
|     viewProfile: (String) -> Unit, | ||||
|     removeFriend: (Friendship) -> Unit | ||||
| ) { | ||||
|     // TODO Styling | ||||
|     Row ( | ||||
|         modifier = Modifier | ||||
|             .fillMaxWidth() | ||||
|             .padding(horizontal = 15.dp, vertical = 7.dp), | ||||
|     ) { | ||||
|         Box( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth(0.15f) | ||||
|                 .background(MaterialTheme.colors.primary, CircleShape) | ||||
|                 .padding(vertical = 4.dp) | ||||
|         ) { | ||||
|             Icon( | ||||
|                 painter = painterResource(id = R.drawable.ic_visibility_on), | ||||
|                 contentDescription = null, | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxHeight() | ||||
|                     .align(Alignment.Center), | ||||
|                 tint = MaterialTheme.colors.onPrimary | ||||
|             ) | ||||
|             ProfilePicture() | ||||
|         } | ||||
| 
 | ||||
|         Box ( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth(0.65f) | ||||
|                 .fillMaxWidth() | ||||
|         ) { | ||||
|             Column ( | ||||
|                 modifier = Modifier | ||||
|  | @ -203,10 +195,10 @@ fun FriendsEntry( | |||
|                     overflow = TextOverflow.Ellipsis | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|             Box( | ||||
|             modifier = Modifier.fillMaxWidth(0.15f) | ||||
|                 modifier = Modifier.fillMaxWidth(), | ||||
|                 contentAlignment = Alignment.CenterEnd | ||||
|             ) { | ||||
|                 FriendsOverviewDropDown( | ||||
|                     friendship = friendship, | ||||
|  | @ -216,6 +208,7 @@ fun FriendsEntry( | |||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ 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 | ||||
|  | @ -21,12 +20,14 @@ import androidx.compose.ui.tooling.preview.Preview | |||
| 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.ProfilePicture | ||||
| import be.ugent.sel.studeez.common.composable.SearchField | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerEntry | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.resources | ||||
| import be.ugent.sel.studeez.ui.theme.StudeezTheme | ||||
| import kotlinx.coroutines.flow.* | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| data class SearchFriendsActions( | ||||
|  | @ -153,25 +154,19 @@ fun UserEntry( | |||
|     Row( | ||||
|         modifier = Modifier | ||||
|             .fillMaxWidth() | ||||
|             .padding(horizontal = 15.dp, vertical = 7.dp), | ||||
|         horizontalArrangement = Arrangement.spacedBy(15.dp) | ||||
|     ) { | ||||
|         Box( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth(0.15f) | ||||
|                 .background(MaterialTheme.colors.primary, CircleShape) | ||||
|                 .padding(vertical = 4.dp) | ||||
|         ) { | ||||
|             Icon( | ||||
|                 painter = painterResource(id = R.drawable.ic_visibility_on), | ||||
|                 contentDescription = null, | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxHeight() | ||||
|                     .align(Alignment.Center), | ||||
|                 tint = MaterialTheme.colors.onPrimary | ||||
|             ) | ||||
|             ProfilePicture() | ||||
|         } | ||||
| 
 | ||||
|         Box ( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth(0.65f) | ||||
|                 .fillMaxWidth() | ||||
|         ) { | ||||
|             Column ( | ||||
|                 modifier = Modifier | ||||
|  | @ -190,10 +185,10 @@ fun UserEntry( | |||
|                     overflow = TextOverflow.Ellipsis | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|             Box( | ||||
|             modifier = Modifier.fillMaxWidth(0.15f) | ||||
|                 modifier = Modifier.fillMaxWidth(), | ||||
|                 contentAlignment = Alignment.CenterEnd | ||||
|             ) { | ||||
|                 SearchFriendsDropDown( | ||||
|                     user = user, | ||||
|  | @ -202,6 +197,7 @@ fun UserEntry( | |||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ 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.filter | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| @HiltViewModel | ||||
|  | @ -43,8 +44,16 @@ class SearchFriendsViewModel @Inject constructor( | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get all users, except for the current user. | ||||
|      */ | ||||
|     fun getAllUsers(): Flow<List<User>> { | ||||
|         return userDAO.getAllUsers() | ||||
|             .filter { users -> | ||||
|                 users.any { user -> | ||||
|                     user.id != userDAO.getCurrentUserId() | ||||
|                 } | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     fun goToProfile( | ||||
|  |  | |||
		Reference in a new issue