Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import org.junit.*
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.verify

class ImagePreviewDialogTest {

Expand Down Expand Up @@ -111,7 +109,7 @@ class ImagePreviewDialogTest {
assert(dialogDismissed)
}

@Test
/*@Test
fun testStarClickCallsUpdatePost() {
// Set the Compose content to ImagePreviewDialog
composeTestRule.setContent {
Expand All @@ -124,7 +122,7 @@ class ImagePreviewDialogTest {

// Verify that updatePost was called in the postsViewModel
verify(postsRepository).updatePost(eq(testPost), any(), any())
}
}*/

/*@Test
fun testStarClickCallsUpdateUserProfile() {
Expand All @@ -141,15 +139,12 @@ class ImagePreviewDialogTest {
}*/

@Test
fun testStarIsDisplayed() {
fun testStarIsNotDisplayed() {
composeTestRule.setContent {
ImagePreviewDialog(
post = testPost, username = "User1", onDismiss = {}, testStarStates, onRatingChanged = {})
}
// Perform click on the first star icon of a post with uid "1"
composeTestRule
.onNodeWithTag("Star_1_1")
.assertIsDisplayed()
.performClick() // Click on the first star
composeTestRule.onNodeWithTag("Star_1_1").assertIsNotDisplayed() // Click on the first star
}
}
116 changes: 39 additions & 77 deletions app/src/main/java/com/github/lookupgroup27/lookup/ui/feed/Feed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,9 @@ fun FeedScreen(
onDispose { activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED }
}

// Fetch user profile
LaunchedEffect(Unit) {
Log.d("FeedScreen", "Fetching user profile")
profileViewModel.fetchUserProfile()
}

// User-related state

profileViewModel.fetchUserProfile()
val profile by profileViewModel.userProfile.collectAsState()
val user = FirebaseAuth.getInstance().currentUser
val isUserLoggedIn = user != null
Expand Down Expand Up @@ -256,30 +252,50 @@ fun FeedScreen(
postRatings[post.uid] ?: List(NUMBER_OF_STARS) { false },
onRatingChanged = { newRating ->
val oldPostRatings =
postRatings[post.uid] ?: List(NUMBER_OF_STARS) { false }
postRatings[post.uid] ?: mutableListOf(false, false, false)
val oldStarCounts = oldPostRatings.count { it }
// Directly modify the existing starStates list to avoid
// creating a new list
postRatings[post.uid] = newRating.toList()
// Update the stars count based on the new rating
val starsCount = newRating.count { it }

// Update user profile ratings
val newProfile =
updateProfileRatings(
currentProfile = profile,
postUid = post.uid,
starsCount = starsCount,
// Update user profile with the new rating count
val updatedRatings = profile?.ratings?.toMutableMap()
updatedRatings?.set(post.uid, starsCount)
val newProfile: UserProfile =
profile?.copy(
username = username,
bio = bio,
email = email)
email = email,
ratings = updatedRatings ?: emptyMap())
?: UserProfile(
username = username,
bio = bio,
email = email,
ratings = updatedRatings ?: emptyMap())
profileViewModel.updateUserProfile(newProfile)

// Update post details
val updatedPost =
calculatePostUpdates(
post = post,
userEmail = userEmail,
starsCount = starsCount,
oldStarCounts = oldStarCounts)
postsViewModel.updatePost(updatedPost)
val isReturningUser = post.ratedBy.contains(userEmail)
val newStarsCount =
if (isReturningUser)
post.starsCount - oldStarCounts + starsCount
else post.starsCount + starsCount
val newUsersNumber =
if (isReturningUser) post.usersNumber
else post.usersNumber + 1
val newAvg = newStarsCount.toDouble() / newUsersNumber

postsViewModel.updatePost(
post.copy(
averageStars = newAvg,
starsCount = newStarsCount,
usersNumber = newUsersNumber,
ratedBy =
if (!isReturningUser) {
post.ratedBy + userEmail
} else {
post.ratedBy
}))
},
onAddressClick = { clickedPost ->
val selectedMarker =
Expand All @@ -301,57 +317,3 @@ fun FeedScreen(
}
}
}
/**
* Updates the user's profile ratings.
*
* @param currentProfile The current user profile.
* @param postUid The unique identifier of the post being rated.
* @param starsCount The number of stars given to the post.
* @param username The user's username.
* @param bio The user's bio.
* @param email The user's email.
* @return An updated [UserProfile] with the new rating.
*/
fun updateProfileRatings(
currentProfile: UserProfile?,
postUid: String,
starsCount: Int,
username: String,
bio: String,
email: String
): UserProfile {
val updatedRatings =
currentProfile?.ratings?.toMutableMap()?.apply { this[postUid] = starsCount }
?: mutableMapOf(postUid to starsCount)

return currentProfile?.copy(
username = username, bio = bio, email = email, ratings = updatedRatings)
?: UserProfile(username = username, bio = bio, email = email, ratings = updatedRatings)
}

/**
* Calculates the updated state of a post after a user rates it.
*
* @param post The original post.
* @param userEmail The email of the user rating the post.
* @param starsCount The number of stars the user has given.
* @param oldStarCounts The previous number of stars the user had given.
* @return An updated [Post] with recalculated ratings and user counts.
*/
fun calculatePostUpdates(post: Post, userEmail: String, starsCount: Int, oldStarCounts: Int): Post {
val isReturningUser = post.ratedBy.contains(userEmail)
val newStarsCount =
if (isReturningUser) {
post.starsCount - oldStarCounts + starsCount
} else {
post.starsCount + starsCount
}
val newUsersNumber = if (isReturningUser) post.usersNumber else post.usersNumber + 1
val newAvg = newStarsCount.toDouble() / newUsersNumber

return post.copy(
averageStars = newAvg,
starsCount = newStarsCount,
usersNumber = newUsersNumber,
ratedBy = if (!isReturningUser) post.ratedBy + userEmail else post.ratedBy)
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fun PostItem(
onImageClick: (imageUrl: String, username: String, description: String) -> Unit,
color: Color = Color.White,
textForUsername: String = post.username,
showStars: Boolean = true,
showAverage: Boolean = true,
showAddress: Boolean = true
) {
Expand Down Expand Up @@ -100,39 +101,40 @@ fun PostItem(
style = MaterialTheme.typography.bodyMedium.copy(color = Color.White),
modifier = Modifier.testTag("DescriptionTag_${post.uid}"))
}

// Rating Row
Row(
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier.fillMaxWidth()) {
starStates.forEachIndexed { index, isFilled ->
IconButton(
onClick = {
val newRating = starStates.mapIndexed { i, _ -> i <= index }
onRatingChanged(newRating)
},
modifier =
Modifier.size(36.dp).testTag("Star_${index + 1}_${post.uid}")) {
Image(
painter =
painterResource(
id =
if (isFilled) R.drawable.full_star2
else R.drawable.empty_star2),
contentDescription = "Star")
}
}
Spacer(modifier = Modifier.weight(1f))
if (showAverage) {
Text(
text = "Avg: ${"%.1f".format(post.averageStars)}",
style =
MaterialTheme.typography.bodyMedium.copy(
fontWeight = FontWeight.Medium, color = color),
modifier = Modifier.testTag("AverageRatingTag_${post.uid}"))
if (showStars) {
// Rating Row
Row(
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier.fillMaxWidth()) {
starStates.forEachIndexed { index, isFilled ->
IconButton(
onClick = {
val newRating = starStates.mapIndexed { i, _ -> i <= index }
onRatingChanged(newRating)
},
modifier =
Modifier.size(36.dp).testTag("Star_${index + 1}_${post.uid}")) {
Image(
painter =
painterResource(
id =
if (isFilled) R.drawable.full_star2
else R.drawable.empty_star2),
contentDescription = "Star")
}
}
Spacer(modifier = Modifier.weight(1f))
if (showAverage) {
Text(
text = "Avg: ${"%.1f".format(post.averageStars)}",
style =
MaterialTheme.typography.bodyMedium.copy(
fontWeight = FontWeight.Medium, color = color),
modifier = Modifier.testTag("AverageRatingTag_${post.uid}"))
}
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import com.github.lookupgroup27.lookup.R
import com.github.lookupgroup27.lookup.model.location.LocationProviderSingleton
import com.github.lookupgroup27.lookup.model.profile.UserProfile
import com.github.lookupgroup27.lookup.ui.googlemap.components.*
import com.github.lookupgroup27.lookup.ui.navigation.*
import com.github.lookupgroup27.lookup.ui.post.PostsViewModel
Expand Down Expand Up @@ -188,31 +187,6 @@ fun GoogleMapScreen(
locationProvider.currentLocation.value,
autoCenteringEnabled,
allPosts,
userEmail,
updateProfile = { profile, updatedRatings ->
val newProfile: UserProfile =
profile?.copy(
username = username,
bio = bio,
email = email,
ratings = updatedRatings ?: emptyMap())
?: UserProfile(
username = username,
bio = bio,
email = email,
ratings = updatedRatings ?: emptyMap())
profileViewModel.updateUserProfile(newProfile)
},
profile = profile,
updatePost = { post, newAvg, newStarsCount, newUsersNumber, newRatedBy ->
postsViewModel.updatePost(
post.copy(
averageStars = newAvg,
starsCount = newStarsCount,
usersNumber = newUsersNumber,
ratedBy = newRatedBy))
},
postRatings = postRatings,
highlightedPost = highlightedPost)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import com.github.lookupgroup27.lookup.model.post.Post
import com.github.lookupgroup27.lookup.model.profile.UserProfile
import com.github.lookupgroup27.lookup.ui.image.ImagePreviewDialog
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.model.LatLng
Expand Down Expand Up @@ -34,11 +33,6 @@ fun MapView(
location: Location?,
autoCenteringEnabled: Boolean,
posts: List<Post>,
userEmail: String,
updateProfile: (UserProfile?, MutableMap<String, Int>?) -> Unit,
profile: UserProfile?,
updatePost: (Post, Double, Int, Int, List<String>) -> Unit,
postRatings: MutableMap<String, List<Boolean>>,
highlightedPost: SelectedPostMarker?
) {

Expand Down Expand Up @@ -70,14 +64,6 @@ fun MapView(
}
}

LaunchedEffect(profile, posts) {
posts.forEach { post ->
val starsCount = postRatings[post.uid]?.count { it } ?: 0
val avg = if (post.usersNumber == 0) 0.0 else starsCount.toDouble() / post.usersNumber
updatePost(post, avg, starsCount, post.usersNumber, post.ratedBy)
}
}

LaunchedEffect(highlightedPost) {
highlightedPost?.let { post ->
// Zoom to highlighted marker position with zoom level 15f
Expand Down Expand Up @@ -110,33 +96,8 @@ fun MapView(
post = it,
username = it.username,
onDismiss = { selectedPost = null },
starStates = postRatings[it.uid] ?: mutableListOf(false, false, false),
onRatingChanged = { newRating ->
val oldPostRatings = postRatings[it.uid] ?: mutableListOf(false, false, false)
val oldStarCounts = oldPostRatings.count { it }
// Directly modify the existing starStates list to avoid creating a new list
postRatings[it.uid] = newRating.toList()
// Update the stars count based on the new rating
val starsCount = newRating.count { it }
// Update user profile with the new rating count
val updatedRatings = profile?.ratings?.toMutableMap()
updatedRatings?.set(it.uid, starsCount)
updateProfile(profile, updatedRatings)

val isReturningUser = it.ratedBy.contains(userEmail)
val newStarsCount =
if (isReturningUser) it.starsCount - oldStarCounts + starsCount
else it.starsCount + starsCount
val newUsersNumber = if (isReturningUser) it.usersNumber else it.usersNumber + 1
val newAvg = newStarsCount.toDouble() / newUsersNumber
val newRatedBy =
if (!isReturningUser) {
it.ratedBy + userEmail
} else {
it.ratedBy
}
updatePost(it, newAvg, newStarsCount, newUsersNumber, newRatedBy)
})
starStates = mutableListOf(false, false, false),
onRatingChanged = {})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fun ImagePreviewDialog(
onRatingChanged: (List<Boolean>) -> Unit
) {
if (post != null) {

Dialog(onDismissRequest = onDismiss) {
Surface(
modifier = Modifier.padding(16.dp).testTag("imagePreviewDialog"),
Expand All @@ -49,6 +50,7 @@ fun ImagePreviewDialog(
onImageClick = { _, _, _ -> }, // No-op for dialog preview
color = Color.White,
textForUsername = "Posted by: $username",
showStars = false,
showAverage = false,
showAddress = false)
Spacer(modifier = Modifier.height(16.dp))
Expand Down
Loading