Skip to content

Commit

Permalink
Merge branch 'main' into feature/signin-persistence-offline
Browse files Browse the repository at this point in the history
  • Loading branch information
loggerz authored Dec 20, 2024
2 parents c226edf + 6ec56e3 commit 79684cd
Show file tree
Hide file tree
Showing 19 changed files with 256 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class NotificationItemTest {
@Before
fun setUp() {

FirebaseApp.initializeApp(ApplicationProvider.getApplicationContext())
FirebaseApp.initializeApp(ApplicationProvider.getApplicationContext())

travelRepository = mock(TravelRepository::class.java)
notificationRepository = mock(NotificationRepository::class.java)
Expand All @@ -98,7 +98,6 @@ class NotificationItemTest {
activityViewModel = ActivityViewModel(activityRepository)
documentViewModel = DocumentViewModel(documentRepository, documentsManager, mock())
eventViewModel = EventViewModel(eventRepository)

}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ class NotificationScreenTest {

composeTestRule.onNodeWithText("DECLINE").performClick()
verify(profileRepository, never()).addFriend(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
verify(notificationRepository).addNotification(anyOrNull())
verify(notificationRepository).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}

// Chat-GPT was helpful in this test because he helped me understand how to separate the capture
Expand Down Expand Up @@ -395,6 +395,6 @@ class NotificationScreenTest {
verify(secondLayerTask).addOnSuccessListener(onCompleteListenerCaptor.capture())
composeTestRule.runOnIdle { onCompleteListenerCaptor.firstValue.onSuccess(null) }

verify(notificationRepository).addNotification(anyOrNull())
verify(notificationRepository).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class ProfileEditTest {
// piece of code is executed from the argument captor
composeTestRule.runOnIdle { onCompleteListenerCaptor2.firstValue.onSuccess(mockQuerySnapshot) }

verify(notificationRepository).addNotification(anyOrNull())
verify(notificationRepository).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ class ParticipantListScreenTest {

// Verify interactions with the repositories
verify(profileRepository).getFsUidByEmail(anyOrNull(), anyOrNull(), anyOrNull())
verify(notificationRepository, never()).addNotification(anyOrNull())
verify(notificationRepository, never()).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}

@Test
Expand Down Expand Up @@ -471,7 +471,7 @@ class ParticipantListScreenTest {

composeTestRule.onNodeWithTag("addUserButton").performClick()
verify(profileRepository).getFsUidByEmail(anyOrNull(), anyOrNull(), anyOrNull())
verify(notificationRepository, never()).addNotification(anyOrNull())
verify(notificationRepository, never()).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}

@Test
Expand Down Expand Up @@ -550,7 +550,7 @@ class ParticipantListScreenTest {
composeTestRule.onNodeWithTag("addUserButton").performClick()

verify(profileRepository).getFsUidByEmail(anyOrNull(), anyOrNull(), anyOrNull())
verify(notificationRepository, never()).addNotification(anyOrNull())
verify(notificationRepository, never()).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}

@Test
Expand Down Expand Up @@ -672,7 +672,8 @@ class ParticipantListScreenTest {
.updateTravel(any(), any(), anyOrNull(), any(), any(), anyOrNull())
composeTestRule.onNodeWithTag("addUserButton").performClick()
verify(profileRepository).getFsUidByEmail(anyOrNull(), anyOrNull(), anyOrNull())
verify(notificationRepository, atLeastOnce()).addNotification(anyOrNull())
verify(notificationRepository, atLeastOnce())
.addNotification(anyOrNull(), anyOrNull(), anyOrNull())
// throw impossible exception
doAnswer { invocation ->
val email = invocation.getArgument<String>(0)
Expand All @@ -697,7 +698,7 @@ class ParticipantListScreenTest {
.updateTravel(any(), any(), anyOrNull(), any(), any(), anyOrNull())
doThrow(RuntimeException("Impossible Exception"))
.`when`(notificationRepository)
.addNotification(anyOrNull())
.addNotification(anyOrNull(), anyOrNull(), anyOrNull())
composeTestRule.onNodeWithTag("addUserFab").performClick()
val randomEmail2 = "[email protected]"
composeTestRule.onNodeWithTag("addUserEmailField").performScrollTo()
Expand Down Expand Up @@ -787,7 +788,7 @@ class ParticipantListScreenTest {
composeTestRule.onNodeWithTag("friendCard").assertIsDisplayed()
composeTestRule.onNodeWithTag("friendCard").assertTextContains("[email protected]")
composeTestRule.onNodeWithTag("friendCard").performClick()
verify(notificationRepository).addNotification(anyOrNull())
verify(notificationRepository).addNotification(anyOrNull(), anyOrNull(), anyOrNull())
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class MainActivity : ComponentActivity() {
}
}
}
FirebaseApp.initializeApp(this)
FirebaseApp.initializeApp(this)
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ interface NotificationRepository {

fun getNewUid(): String

fun addNotification(notification: Notification)
fun addNotification(
notification: Notification,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
)

fun fetchNotificationsForUser(
userId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,21 @@ class NotificationRepositoryFirestore(private val firestore: FirebaseFirestore)
*
* @param notification The notification to be added.
*/
override fun addNotification(notification: Notification) {
override fun addNotification(
notification: Notification,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
firestore
.collection(FirebasePaths.notifications)
.document(notification.notificationUid)
.set(notification)
.addOnSuccessListener { Log.d("NotificationRepository", "Notification added successfully") }
.addOnSuccessListener {
onSuccess()
Log.d("NotificationRepository", "Notification added successfully")
}
.addOnFailureListener { e ->
onFailure(Exception("An error occurred. Could not send the notification"))
Log.e("NotificationRepository", "Error adding notification", e)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.github.se.travelpouch.model.notifications

import android.util.Log
import androidx.lifecycle.ViewModel
import com.google.firebase.Firebase
import com.google.firebase.functions.FirebaseFunctions
import com.google.firebase.functions.functions
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down Expand Up @@ -57,8 +56,12 @@ constructor(private val notificationRepository: NotificationRepository) : ViewMo
*
* @param notification The notification to be sent.
*/
fun sendNotification(notification: Notification) {
notificationRepository.addNotification(notification)
fun sendNotification(
notification: Notification,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
notificationRepository.addNotification(notification, onSuccess, onFailure)
}

/**
Expand All @@ -80,19 +83,16 @@ constructor(private val notificationRepository: NotificationRepository) : ViewMo
}

fun sendNotificationToUser(userId: String, notificationContent: NotificationContent) {
val data = hashMapOf(
"userId" to userId,
"message" to notificationContent.toDisplayString(),
)
val data =
hashMapOf(
"userId" to userId,
"message" to notificationContent.toDisplayString(),
)

functions
.getHttpsCallable("sendNotification")
.call(data)
.addOnSuccessListener { result ->
Log.d("Notification", "Success: ${result.data}")
}
.addOnFailureListener { e ->
Log.e("Notification", "Error: ${e.message}")
}
.getHttpsCallable("sendNotification")
.call(data)
.addOnSuccessListener { result -> Log.d("Notification", "Success: ${result.data}") }
.addOnFailureListener { e -> Log.e("Notification", "Error: ${e.message}") }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import com.google.firebase.messaging.RemoteMessage

class PushNotificationService : FirebaseMessagingService() {

@Override
override fun onNewToken(token: String) {
super.onNewToken(token)
}
@Override
override fun onNewToken(token: String) {
super.onNewToken(token)
}

@Override
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
}
}
@Override
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ class ProfileModelView @Inject constructor(private val repository: ProfileReposi
private val profile_ = MutableStateFlow<Profile>(ErrorProfile.errorProfile)
val profile: StateFlow<Profile> = profile_.asStateFlow()

private var _isTokenUpdated = mutableStateOf(false)
val isTokenUpdated: Boolean get() = _isTokenUpdated.value
private var _isTokenUpdated = mutableStateOf(false)
val isTokenUpdated: Boolean
get() = _isTokenUpdated.value

/** The initialisation function of the profile model view. It fetches the profile of the user */
suspend fun initAfterLogin(onSuccess: () -> Unit) {
Expand Down Expand Up @@ -91,20 +92,20 @@ class ProfileModelView @Inject constructor(private val repository: ProfileReposi
})
}

private fun addNotificationTokenToProfile(token: String) {
repository.addNotificationTokenToProfile(token, profile_.value.fsUid, {
Log.d("Notification token added", "Notification token added")
}, {
Log.e(onFailureTag, "Failed to add notification token", it)
})
}
private fun addNotificationTokenToProfile(token: String) {
repository.addNotificationTokenToProfile(
token,
profile_.value.fsUid,
{ Log.d("Notification token added", "Notification token added") },
{ Log.e(onFailureTag, "Failed to add notification token", it) })
}

fun updateNotificationTokenIfNeeded(token: String) {
if (!_isTokenUpdated.value) {
addNotificationTokenToProfile(token)
_isTokenUpdated.value = true // Mark the token as updated for this session
}
fun updateNotificationTokenIfNeeded(token: String) {
if (!_isTokenUpdated.value) {
addNotificationTokenToProfile(token)
_isTokenUpdated.value = true // Mark the token as updated for this session
}
}

/**
* This function sends to notification to add a friend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,22 @@ interface ProfileRepository {
onFailure: (Exception) -> Unit
)

/**
* Adds a notification token to the user's profile in the Firestore database.
*
* @param token The notification token to be added to the profile.
* @param user The user identifier to whom the token belongs.
* @param onSuccess A callback function that is invoked when the token is successfully added.
* @param onFailure A callback function that is invoked with an Exception if an error occurs during the operation.
*/
fun addNotificationTokenToProfile(
token: String,
user: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
)

/**
* Adds a notification token to the user's profile in the Firestore database.
*
* @param token The notification token to be added to the profile.
* @param user The user identifier to whom the token belongs.
* @param onSuccess A callback function that is invoked when the token is successfully added.
* @param onFailure A callback function that is invoked with an Exception if an error occurs
* during the operation.
*/
fun addNotificationTokenToProfile(
token: String,
user: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
)

/**
* This function sends to notification to add a friend
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,28 +330,28 @@ class ProfileRepositoryFirebase(private val db: FirebaseFirestore) : ProfileRepo
}
}

/**
* Adds a notification token to the user's profile in the Firestore database.
*
* @param token The notification token to be added to the profile.
* @param user The user identifier to whom the token belongs.
* @param onSuccess A callback function that is invoked when the token is successfully added.
* @param onFailure A callback function that is invoked with an Exception if an error occurs during the operation.
*/
override fun addNotificationTokenToProfile(
token: String,
user: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
performFirestoreOperation(
db.collection(collectionPath)
.document(user)
.update("notificationTokens", FieldValue.arrayUnion(token)),
onSuccess,
onFailure
)
}
/**
* Adds a notification token to the user's profile in the Firestore database.
*
* @param token The notification token to be added to the profile.
* @param user The user identifier to whom the token belongs.
* @param onSuccess A callback function that is invoked when the token is successfully added.
* @param onFailure A callback function that is invoked with an Exception if an error occurs
* during the operation.
*/
override fun addNotificationTokenToProfile(
token: String,
user: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
performFirestoreOperation(
db.collection(collectionPath)
.document(user)
.update("notificationTokens", FieldValue.arrayUnion(token)),
onSuccess,
onFailure)
}
}

/** This class is used to convert a document to a profile, across the project */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ class ProfileRepositoryMock : ProfileRepository {
TODO("Not yet implemented")
}

override fun addNotificationTokenToProfile(
token: String,
user: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
TODO("Not yet implemented")
}
override fun addNotificationTokenToProfile(
token: String,
user: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
TODO("Not yet implemented")
}

override fun sendFriendNotification(
email: String,
onSuccess: (String) -> Unit,
Expand Down
Loading

0 comments on commit 79684cd

Please sign in to comment.