Skip to content

Commit

Permalink
Merge pull request #236 from SwEnt-Group13/fix/search-offline
Browse files Browse the repository at this point in the history
Make search bars work (at normal speed) in offline mode
  • Loading branch information
Romainhir authored Dec 4, 2024
2 parents 7c6c95a + 9f8ccb0 commit 35469ca
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package com.android.unio.model.association
import com.android.unio.model.authentication.registerAuthStateListener
import com.android.unio.model.firestore.FirestorePaths.ASSOCIATION_PATH
import com.android.unio.model.firestore.performFirestoreOperation
import com.android.unio.model.firestore.registerSnapshotListener
import com.android.unio.model.firestore.transform.hydrate
import com.android.unio.model.firestore.transform.serialize
import com.google.firebase.Firebase
import com.google.firebase.auth.auth
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.MetadataChanges
import com.google.firebase.firestore.QuerySnapshot
import javax.inject.Inject

Expand Down Expand Up @@ -67,16 +69,32 @@ class AssociationRepositoryFirestore @Inject constructor(private val db: Firebas
onFailure = { exception -> onFailure(exception) })
}

/**
* Fetches an [Association] object from Firestore using the provided [id]. Here, instead of using
* success and failure listener directly, we use a Snapshot Listener that call directly the
* callback when a read/write are made on the local (cache) database.
*
* @param id [String] : The id of the [Association] to fetch.
* @param onSuccess [(Association) -> Unit] : The callback to call when the [Association] is
* fetched.
* @param onFailure [(Exception) -> Unit] : The callback to call when the fetch fails.
*/
override fun getAssociationWithId(
id: String,
onSuccess: (Association) -> Unit,
onFailure: (Exception) -> Unit
) {
getAssociationRef(id)
.get()
.performFirestoreOperation(
onSuccess = { document -> onSuccess(hydrate(document.data)) },
onFailure = { exception -> onFailure(exception) })
getAssociationRef(id).registerSnapshotListener(MetadataChanges.EXCLUDE) {
documentSnapshot,
exception ->
if (exception != null) {
onFailure(exception)
return@registerSnapshotListener
}
if (documentSnapshot != null && documentSnapshot.exists()) {
onSuccess(hydrate(documentSnapshot.data))
}
}
}

override fun saveAssociation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package com.android.unio.model.event
import com.android.unio.model.authentication.registerAuthStateListener
import com.android.unio.model.firestore.FirestorePaths.EVENT_PATH
import com.android.unio.model.firestore.performFirestoreOperation
import com.android.unio.model.firestore.registerSnapshotListener
import com.android.unio.model.firestore.transform.hydrate
import com.android.unio.model.firestore.transform.serialize
import com.google.firebase.Firebase
import com.google.firebase.Timestamp
import com.google.firebase.auth.auth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.MetadataChanges
import javax.inject.Inject

class EventRepositoryFirestore @Inject constructor(private val db: FirebaseFirestore) :
Expand Down Expand Up @@ -38,17 +40,31 @@ class EventRepositoryFirestore @Inject constructor(private val db: FirebaseFires
onFailure = { exception -> onFailure(exception) })
}

/**
* Gets the event with the given id. Here, instead of using success and failure listener directly,
* we use a Snapshot Listener that call directly the callback when a read/write are made on the
* local (cache) database.
*
* @param id [String] : the id of the event to get.
* @param onSuccess [(Event) -> Unit] : the callback to call when the event is found.
* @param onFailure [(Exception) -> Unit] : the callback to call when an error occurs.
*/
override fun getEventWithId(
id: String,
onSuccess: (Event) -> Unit,
onFailure: (Exception) -> Unit
) {
db.collection(EVENT_PATH)
.document(id)
.get()
.performFirestoreOperation(
onSuccess = { document -> onSuccess(hydrate(document.data)) },
onFailure = { exception -> onFailure(exception) })
db.collection(EVENT_PATH).document(id).registerSnapshotListener(MetadataChanges.EXCLUDE) {
documentSnapshot,
exception ->
if (exception != null) {
onFailure(exception)
return@registerSnapshotListener
}
if (documentSnapshot != null && documentSnapshot.exists()) {
onSuccess(hydrate(documentSnapshot.data))
}
}
}

override fun getNextEventsFromDateToDate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,32 @@ package com.android.unio.model.firestore

import android.util.Log
import com.google.android.gms.tasks.Task
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.EventListener
import com.google.firebase.firestore.ListenerRegistration
import com.google.firebase.firestore.MetadataChanges

private val snapshotListeners = mutableListOf<ListenerRegistration>()

/**
* Extension function that registers a snapshot listener for a [DocumentReference] and adds it to
* the [snapshotListeners] list. This is useful for unregistering all snapshot listeners at once,
* for example when logging out.
*/
fun DocumentReference.registerSnapshotListener(
metadata: MetadataChanges,
callback: EventListener<DocumentSnapshot>
) {
val listener = this.addSnapshotListener(metadata, callback)
snapshotListeners.add(listener)
}

/** Unregisters and remove all snapshot listeners in the [snapshotListeners] list. */
fun unregisterAllSnapshotListeners() {
snapshotListeners.forEach { it.remove() }
snapshotListeners.clear()
}

/**
* Extension function that performs a Firestore operation and calls the appropriate callback based
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ fun AssociationSearchBar(
.testTag(
ExploreContentTestTags.ASSOCIATION_EXPLORE_RESULT +
association.name),
headlineContent = { Text(association.name) },
)
headlineContent = { Text(association.name) })
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import com.google.firebase.functions.FirebaseFunctionsException
import com.google.firebase.functions.functions
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserClaimAssociationPresidentialRightsScreen(
associationViewModel: AssociationViewModel,
Expand Down Expand Up @@ -181,8 +180,6 @@ fun UserClaimAssociationPresidentialRightsScreenScaffold(
.user_claim_association_presidential_rights_unexpected_error),
e)
}
} else {
// it works !
}
}
}
Expand Down Expand Up @@ -300,6 +297,7 @@ fun UserClaimAssociationPresidentialRightsScreenScaffold(
.user_claim_association_presidential_rights_verified_successfully),
Toast.LENGTH_SHORT)
.show()

navigationAction.navigateTo(Screen.MY_PROFILE)
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/android/unio/ui/user/UserProfile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import com.android.unio.R
import com.android.unio.model.association.AssociationViewModel
import com.android.unio.model.firestore.unregisterAllSnapshotListeners
import com.android.unio.model.strings.test_tags.UserProfileTestTags
import com.android.unio.model.user.User
import com.android.unio.model.user.UserViewModel
Expand Down Expand Up @@ -341,6 +342,7 @@ fun UserProfileBottomSheet(
TextButton(
modifier = Modifier.fillMaxWidth().testTag(UserProfileTestTags.SIGN_OUT),
onClick = {
unregisterAllSnapshotListeners()
Firebase.auth.signOut()
scope.launch {
sheetState.hide()
Expand Down
Loading

0 comments on commit 35469ca

Please sign in to comment.