flutterfirebasegoogle-cloud-firestoreiconbutton

Flutter call to firebase works from one location but not the next


I have an odd bug I cant seem to work out. I am working on friend request system for my app and when a request is made it generates a "RequestTile" for each user, The user that sent the request shows one version of the RequestTile while the person getting the request sees a different version.

The sent request tile Shows the user name and an Iconbutton with a cancel icon that triggers a call to the database to remove the request from 2 locations.

The received request tile shows the user name and 2 IconButtons, one for accepting the request and the other to cancel the request.

Both cancel icons for both users trigger the cancel method to the database. The problem is that only one of them does what its supposed to. The sender can click the IconButton and it removes the Tile for both users screens like it should, but when the receiver presses the IconButton it does indeed run the method as I added log entries for each step but the calls to database dont run for some reason.

Here is my button code...

!isSentRequest
                ? IconButton(
                    onPressed: () {
                      Utilities.logWarning('Cancelling Requests Received from $requestersId');
                      _db.cancelFriendRequest(requestersId);
                    },
                    icon: Icon(
                      Icons.thumb_down_alt,
                      color: Colors.red,
                      size: 30.r,
                    ),
                  )
                : Container(),
            SizedBox(width: 10.w),
            !isSentRequest
                ? IconButton(
                    onPressed: () {
                      Utilities.logWarning('Accepting Request Received from $requestersId');
                      _db.acceptFriendRequest(requestersId);
                    },
                    icon: Icon(
                      Icons.thumb_up_alt,
                      color: Colors.green,
                      size: 30.r,
                    ),
                  )
                : IconButton(
                    onPressed: () {
                      Utilities.logWarning('Cancelling Requests Sent to $requestersId');
                      _db.cancelFriendRequest(requestersId);
                    },
                    icon: Icon(
                      Icons.cancel,
                      color: Colors.red,
                      size: 30.r,
                    ),
                  ),

And here is the database method to cancel the request which both buttons use...

  Future<void> cancelFriendRequest(String _friendUID) async {
// Remove friend request from users received collection
await _db
    .collection(USER_COLLECTION)
    .doc(_auth.getCurrentUID())
    .collection(requestsSent)
    .doc(_friendUID)
    .delete();
Utilities.logWarning('Removed friend request from users received collection');

// Remove user from requested friends sent collection
await _db
    .collection(USER_COLLECTION)
    .doc(_friendUID)
    .collection(requestsReceived)
    .doc(_auth.getCurrentUID())
    .delete();
Utilities.logWarning('Removed user from requested friends sent collection');

}

As you can see in the database method there are 2 logs which do display in the console when I press the button from either users viewpoint.

Im hoping someone can shed some light on why it runs the method from one button properly but not the other button

EDIT Updated the Logs before the _db method call is made to show me each users requesterID to make sure they were proper according to which user device it was being called from.

Here are the log output when I press the deny button for the receiver request to cancel...

Receiver output when deny button pressed

Here are the log output when I press the cancel button for the senders request to cancel...

Senders output when cancelling

As you can see both button presses show all 3 steps, before method called, first call to DB and after second call to DB yet only when the sender presses does it actually remove entry from database,

Senders Collection breadcrumb... Senders FireStore Collection

Receivers Collection breadcrumb... Receivers Firestore Collection

Corrected Methods for anyone finding this Question

  Future<void> denyReceivedFriendRequest(String _friendUID) async {
// Remove friend request from users received collection
_db.collection(USER_COLLECTION).doc(_auth.getCurrentUID()).collection(requestsReceived).doc(_friendUID).delete();
Utilities.logWarning('Removed friend request from ${_auth.getCurrentUID()} receieved collection');

// Remove user from requested friends sent collection
_db.collection(USER_COLLECTION).doc(_friendUID).collection(requestsSent).doc(_auth.getCurrentUID()).delete();
Utilities.logWarning('Removed friend request from $_friendUID sent collection');



  Future<void> cancelSentFriendRequest(String _friendUID) async {
// Remove friend request from users received collection
_db.collection(USER_COLLECTION).doc(_auth.getCurrentUID()).collection(requestsSent).doc(_friendUID).delete();
Utilities.logWarning('Removed friend request from ${_auth.getCurrentUID()} sent collection');

// Remove user from requested friends sent collection
_db.collection(USER_COLLECTION).doc(_friendUID).collection(requestsReceived).doc(_auth.getCurrentUID()).delete();
Utilities.logWarning('Removed friend request from $_friendUID received collection');

Solution

  • Just a suggestion, when a user(sender) sends a request then its saved in the requests sent collection. So when the reciever wants to delete this the method to delete should be different where you access request send of friend and request received of receiver

    Future<void> cancelFriendRequest(String _friendUID) async {
    // Remove friend request from users received collection
    await _db
        .collection(USER_COLLECTION)
        .doc(_friendUID)
        .collection(requestsSent)
        .doc(_auth.getCurrentUID())
        .delete();
    Utilities.logWarning('Removed friend request from users received collection');
    
    // Remove user from requested friends sent collection
    await _db
        .collection(USER_COLLECTION)
        .doc(_auth.getCurrentUID())
        .collection(requestsReceived)
        .doc(_friendUID)
        .delete();
    

    Please note that the doc has been interchanged here. For the receiver you are first fetching the friendID doc then checking request sent collection then getting the receivers doc and deleting it. Then getting the receiver's doc accessing the request received collection then deleting the friend(sender's) ID and deleting it.

    So for a sender the method should be different and for the receiver the method should be different I think.

    Further Explanation

    User sends a request. The collection is created like this

    doc("UserID")->collection("requestSent")->doc("user2")
    

    Now when user 1 is fetching this doc it has to be

    doc(UserID)->collection("requestSent")->doc(friendID) - delete
    

    when user 2 is fetching the same doc it has to be

    doc(friendID)->collection("requestSent")->doc(UserID) - delete
    

    If you notice the doc in which you are accessing the same data has different values(UserID and friendID) based on who's accessing the document.