Repository: cmput301-w25/project-kernelcrew
Pull request #242: Notifications
Author: login: siddhantgoel7
Created: 2025-03-28T16:37:03Z | Merged: 2025-03-29T16:46:55Z

## Summary
 - Implemented Notifications Feature when a user receives a follow request

Resolves: #156
Resolves: #157 

## Testing

- How should a reviewer test this feature, fix, or UI?
     - Build -> Generate Bundle or APKs -> Generate APK
     - Open 2 Emulators
     - Uninstall all existing versions of the app on phone
     - drag and drop this apk onto both android emulators
     - Make sure to go into App info -> turn on/allow notifications on both devices
     - login into 2 different accounts on the 2 devices
     - now, from user 1, go to any mood of user 2 -> their profile page -> click on "follow"
     - now check/verify if user 2's android emulator got any notification stating "{user 1} has requested to follow you"
     - accept request from user 2's account
     - now, verify if user 1 got any notification stating "{user 2} accepted your follow request"

---

## Merge Instructions

- Any considerations that other PR's may need to take into note? 
     - N/A
- Should the reviewer delete the branch on merge? 
     - Yes/No

---

**Checklist**
- [x] Are all relevant issues referenced by this PR?
- [x] Does the app still build (locally)?
- [x] Do all tests pass?
- [x] Does the feature work as expected?
- [x] Does this feature preserve the app’s existing stability?  
- [x] Is the description of the changes correct/present?
- [x] Have new tests been created or existing tests updated as needed?
     - No way to test android notification received or not

---




Diff:
diff --git a/code/app/src/androidTest/java/com/kernelcrew/moodapp/EditMoodEventTest.java b/code/app/src/androidTest/java/com/kernelcrew/moodapp/EditMoodEventTest.java
index 4dd4a8bc99..36f1b3d426 100644
--- a/code/app/src/androidTest/java/com/kernelcrew/moodapp/EditMoodEventTest.java
+++ b/code/app/src/androidTest/java/com/kernelcrew/moodapp/EditMoodEventTest.java
@@ -1,12 +1,12 @@
 package com.kernelcrew.moodapp;
 
-import static androidx.test.espresso.Espresso.*;
-import static androidx.test.espresso.action.ViewActions.*;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.scrollTo;
 import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
-import static androidx.test.espresso.matcher.ViewMatchers.*;
-
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static org.awaitility.Awaitility.await;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 import android.os.SystemClock;
 
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowProvider.java b/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowProvider.java
index 76c11b0e1e..40f4d95810 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowProvider.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowProvider.java
@@ -1,5 +1,7 @@
 package com.kernelcrew.moodapp.data;
 
+import android.util.Log;
+
 import com.google.android.gms.tasks.Task;
 import com.google.android.gms.tasks.Tasks;
 import com.google.firebase.firestore.DocumentSnapshot;
@@ -7,6 +9,8 @@
 import com.google.firebase.firestore.QuerySnapshot;
 import com.google.android.gms.tasks.Tasks;
 import com.google.firebase.firestore.DocumentSnapshot;
+import com.kernelcrew.moodapp.utils.NotificationHelper;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.ArrayList;
@@ -48,6 +52,7 @@ public Task<Void> deleteRequest(String targetUid, String requesterUid) {
     public Task<Void> acceptRequest(String targetUid, String requesterUid) {
         return deleteRequest(targetUid, requesterUid)
                 .addOnSuccessListener(unused -> {
+                    // Add to followers and following as before:
                     db.collection("users").document(targetUid)
                             .collection("followers")
                             .document(requesterUid)
@@ -56,6 +61,23 @@ public Task<Void> acceptRequest(String targetUid, String requesterUid) {
                             .collection("following")
                             .document(targetUid)
                             .set(Collections.emptyMap());
+                    // Write a "followAccepted" notification to the requester's notifications subcollection.
+                    java.util.HashMap<String, Object> notifData = new java.util.HashMap<>();
+                    notifData.put("fromUserId", targetUid);    // The acceptor (User2)
+                    notifData.put("toUserId", requesterUid);    // The original requester (User1)
+                    notifData.put("type", "followAccepted");
+                    notifData.put("timestamp", com.google.firebase.firestore.FieldValue.serverTimestamp());
+
+                    db.collection("users")
+                            .document(requesterUid)
+                            .collection("notifications")
+                            .add(notifData)
+                            .addOnSuccessListener(ref -> {
+                                Log.d("FollowProvider", "Notification written successfully: " + ref.getId());
+                            })
+                            .addOnFailureListener(e -> {
+                                Log.e("FollowProvider", "Failed to write notification", e);
+                            });
                 });
     }
 
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowRequestProvider.java b/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowRequestProvider.java
new file mode 100644
index 0000000000..de62dfe8f1
--- /dev/null
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/data/FollowRequestProvider.java
@@ -0,0 +1,130 @@
+package com.kernelcrew.moodapp.data;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.google.firebase.firestore.DocumentChange;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.ListenerRegistration;
+import com.kernelcrew.moodapp.utils.NotificationHelper;
+
+public class FollowRequestProvider {
+    private final FirebaseFirestore db;
+    private final NotificationHelper notificationHelper;
+
+    public FollowRequestProvider(Context context) {
+        this.db = FirebaseFirestore.getInstance();
+        this.notificationHelper = new NotificationHelper(context);
+    }
+
+    /**
+     * Start listening for follow requests (incoming follow requests).
+     * This method is called in HomeFeed.
+     */
+    public ListenerRegistration listenForFollowRequests(String userId) {
+        return db.collection("users")
+                .document(userId)
+                .collection("followRequests")
+                .addSnapshotListener((snapshots, error) -> {
+                    if (error != null) {
+                        Log.e("FollowRequestProvider", "Error listening to followRequests", error);
+                        return;
+                    }
+                    if (snapshots != null) {
+                        for (DocumentChange dc : snapshots.getDocumentChanges()) {
+                            if (dc.getType() == DocumentChange.Type.ADDED) {
+                                String requesterUid = dc.getDocument().getId();
+                                sendFollowRequestNotification(requesterUid);
+                            }
+                        }
+                    }
+                });
+    }
+
+    /**
+     * Start listening for notifications, such as followAccepted.
+     */
+    public ListenerRegistration listenForFollowAcceptedNotifications(String userId) {
+        return db.collection("users")
+                .document(userId)
+                .collection("notifications")
+                .addSnapshotListener((snapshots, error) -> {
+                    if (error != null) {
+                        Log.e("FollowRequestProvider", "Error listening to notifications", error);
+                        return;
+                    }
+                    if (snapshots != null) {
+                        for (DocumentChange dc : snapshots.getDocumentChanges()) {
+                            if (dc.getType() == DocumentChange.Type.ADDED) {
+                                String docId = dc.getDocument().getId();
+                                String type = dc.getDocument().getString("type");
+                                if ("followAccepted".equals(type)) {
+                                    String fromUserId = dc.getDocument().getString("fromUserId");
+                                    sendFollowAcceptedNotification(fromUserId, docId);
+                                }
+                            }
+                        }
+                    }
+                });
+    }
+
+    /**
+     * Send a follow request notification.
+     */
+    private void sendFollowRequestNotification(String requesterUid) {
+        // Fetch the username from Firestore
+        db.collection("users").document(requesterUid).get()
+                .addOnSuccessListener(doc -> {
+                    String username = requesterUid; // Fallback to requesterUid if username is not found
+                    if (doc.exists()) {
+                        String fetchedName = doc.getString("username");
+                        Log.d("FollowRequest", "Fetched username: " + fetchedName);  // Log the fetched username
+                        if (fetchedName != null && !fetchedName.isEmpty()) {
+                            username = fetchedName;
+                        }
+                    }
+
+                    // Now send the notification with the username + "wants to follow you"
+                    notificationHelper.sendNotification(
+                            "Follow Request",
+                            username + " wants to follow you"
+                    );
+                })
+                .addOnFailureListener(e -> {
+                    Log.e("FollowRequestProvider", "Error fetching username", e);
+                });
+    }
+
+    /**
+     * Send a follow accepted notification and optionally delete the notification.
+     */
+    private void sendFollowAcceptedNotification(String fromUserId, String docId) {
+        // Fetch the username from Firestore
+        db.collection("users").document(fromUserId).get()
+                .addOnSuccessListener(doc -> {
+                    String username = fromUserId; // Fallback to fromUserId if username is not found
+                    if (doc.exists()) {
+                        String fetchedName = doc.getString("username");
+                        if (fetchedName != null && !fetchedName.isEmpty()) {
+                            username = fetchedName;
+                        }
+                    }
+
+                    // Send the notification with the username + "accepted your follow request"
+                    notificationHelper.sendNotification(
+                            "Follow Accepted",
+                            username + " accepted your follow request"
+                    );
+
+                    // Optionally, delete the notification after processing
+                    db.collection("users")
+                            .document(fromUserId)
+                            .collection("notifications")
+                            .document(docId)
+                            .delete();
+                })
+                .addOnFailureListener(e -> {
+                    Log.e("FollowRequestProvider", "Error fetching username", e);
+                });
+    }
+}
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowRequestsFragment.java b/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowRequestsFragment.java
index 17042f3c05..18d7801213 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowRequestsFragment.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowRequestsFragment.java
@@ -19,6 +19,7 @@
 import com.google.firebase.firestore.FirebaseFirestore;
 import com.kernelcrew.moodapp.R;
 import com.kernelcrew.moodapp.data.FollowProvider;
+import com.kernelcrew.moodapp.utils.NotificationHelper;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowersFragment.java b/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowersFragment.java
index 2eda8eaeda..8794eaace8 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowersFragment.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/ui/FollowersFragment.java
@@ -44,7 +44,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
         followersRecyclerView.setAdapter(adapter);
 
         userProvider = UserProvider.getInstance();
-        // Instead of a one-time fetch, set up a snapshot listener
         FirebaseFirestore.getInstance()
                 .collection("users")
                 .document(FirebaseAuth.getInstance().getCurrentUser().getUid())
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java b/code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
index 9ec76ef328..1f4d4052fe 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
@@ -9,7 +9,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentContainerView;
 import androidx.navigation.NavController;
 import androidx.navigation.Navigation;
 import androidx.recyclerview.widget.LinearLayoutManager;
@@ -19,10 +18,9 @@
 import com.google.firebase.auth.FirebaseAuth;
 import com.google.firebase.auth.FirebaseUser;
 import com.google.firebase.firestore.DocumentSnapshot;
-import com.google.firebase.firestore.Query;
 import com.kernelcrew.moodapp.R;
+import com.kernelcrew.moodapp.data.FollowRequestProvider;
 import com.kernelcrew.moodapp.data.MoodEvent;
-import com.kernelcrew.moodapp.data.MoodEventFilter;
 import com.kernelcrew.moodapp.data.MoodEventProvider;
 import com.kernelcrew.moodapp.ui.components.FilterBarFragment;
 
@@ -58,17 +56,31 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
 
         searchNFilterFragment = (FilterBarFragment) getChildFragmentManager().findFragmentById(R.id.filterBarFragment);
 
-        // Setup RecyclerView
         moodRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
         moodAdapter = new MoodAdapter();
 
         moodRecyclerView.setAdapter(moodAdapter);
 
+        if (user != null) {
+            String myUid = user.getUid();
+
+            // Initialize FollowRequestProvider
+            FollowRequestProvider followRequestProvider = new FollowRequestProvider(getContext());
+
+            // Listen for follow requests
+            followRequestProvider.listenForFollowRequests(myUid);
+
+            // Listen for follow accepted notifications
+            followRequestProvider.listenForFollowAcceptedNotifications(myUid);
+        }
+
         if (auth.getCurrentUser() == null) {
             Log.e("Home", "User not authenticated!");
         }
 
-        // Listen for changes in the "moodEvents" collection
+        FollowRequestProvider followRequestProvider = new FollowRequestProvider(getContext());
+
+        // Listener for moodEvents collection
         if (searchNFilterFragment != null) {
             searchNFilterFragment.setOnFilterChangedListener(filter -> {
                 filter.buildQuery()
@@ -77,12 +89,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Log.w("HomeFeed", "Listen failed.", error);
                                 return;
                             }
-
                             if (snapshots == null) {
                                 Log.w("HomeFeed", "No snapshot data received.");
                                 return;
                             }
-
                             List<MoodEvent> moodList = new ArrayList<>();
                             for (DocumentSnapshot doc : snapshots.getDocuments()) {
                                 MoodEvent mood = doc.toObject(MoodEvent.class);
@@ -94,7 +104,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             currentFilteredList = moodList;
                             moodAdapter.setMoods(moodList);
                         });
-
             });
         }
 
@@ -103,7 +112,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
             public void onViewDetails(MoodEvent mood) {
                 Bundle args = new Bundle();
                 args.putString("moodEventId", mood.getId());
-                args.putString("sourceScreen", "home"); // or "filtered"
+                args.putString("sourceScreen", "home");
                 NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
                 navController.navigate(R.id.action_homeFeed_to_moodDetails, args);
             }
@@ -116,11 +125,8 @@ public void onViewComments(MoodEvent mood) {
                 NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
                 navController.navigate(R.id.action_homeFeed_to_moodComments, args);
             }
-
         });
 
-
-
         return view;
     }
 
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/ui/MyProfile.java b/code/app/src/main/java/com/kernelcrew/moodapp/ui/MyProfile.java
index 1066b1c4e5..a150d21054 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/ui/MyProfile.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/ui/MyProfile.java
@@ -3,6 +3,7 @@
 import android.os.Bundle;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.core.app.NotificationManagerCompat;
 import androidx.fragment.app.Fragment;
 import androidx.navigation.Navigation;
 import android.view.LayoutInflater;
@@ -111,6 +112,8 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
     }
 
     private void onClickSignOut(View btnView) {
+        NotificationManagerCompat manager = NotificationManagerCompat.from(requireContext());
+        manager.cancelAll();
         auth.signOut();
         Navigation.findNavController(btnView).navigate(R.id.authHome);
     }
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/ui/OtherUserProfile.java b/code/app/src/main/java/com/kernelcrew/moodapp/ui/OtherUserProfile.java
index a4c5a0534b..ac5d71785a 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/ui/OtherUserProfile.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/ui/OtherUserProfile.java
@@ -26,6 +26,7 @@
 import com.kernelcrew.moodapp.data.FollowProvider;
 import com.kernelcrew.moodapp.data.MoodEvent;
 import com.kernelcrew.moodapp.data.UserProvider;
+import com.kernelcrew.moodapp.utils.NotificationHelper;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -113,14 +114,14 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                                         } else {
                                             followButton.setText("Follow");
                                             followButton.setEnabled(true);
-                                            followButton.setOnClickListener(v ->
-                                                    provider.sendRequest(uidToLoad, currentUid)
-                                                            .addOnSuccessListener(a -> {
-                                                                followButton.setText("Requested");
-                                                                followButton.setEnabled(false);
-                                                            })
-                                                            .addOnFailureListener(e -> Log.e(TAG, "Request failed", e))
-                                            );
+                                            followButton.setOnClickListener(v -> {
+                                                provider.sendRequest(uidToLoad, currentUid)
+                                                        .addOnSuccessListener(a -> {
+                                                            followButton.setText("Requested");
+                                                            followButton.setEnabled(false);
+                                                        })
+                                                        .addOnFailureListener(e -> Log.e(TAG, "Request failed", e));
+                                            });
                                         }
                                     });
                         }
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/ui/RequestFragment.java b/code/app/src/main/java/com/kernelcrew/moodapp/ui/RequestFragment.java
index add5a7eb22..5c03ffb5b7 100644
--- a/code/app/src/main/java/com/kernelcrew/moodapp/ui/RequestFragment.java
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/ui/RequestFragment.java
@@ -15,6 +15,7 @@
 import com.google.firebase.firestore.FirebaseFirestore;
 import com.kernelcrew.moodapp.R;
 import com.kernelcrew.moodapp.data.FollowProvider;
+import com.kernelcrew.moodapp.utils.NotificationHelper;
 
 import java.util.Collections;
 
@@ -47,7 +48,8 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
             requestMessage.setText(username + " is requesting to follow you");
             acceptButton.setOnClickListener(v -> acceptFollowRequest(username));
             denyButton.setOnClickListener(v -> denyFollowRequest(username));
-        } else if ("unfollow_confirmation".equals(requestType)) {
+        }
+        else if ("unfollow_confirmation".equals(requestType)) {
             requestMessage.setText("Are you sure you want to unfollow " + username + "?");
             acceptButton.setOnClickListener(v -> confirmUnfollow(username));
             denyButton.setOnClickListener(v -> Navigation.findNavController(view).popBackStack());
@@ -59,9 +61,11 @@ private void acceptFollowRequest(String username) {
         FollowProvider.getInstance()
                 .acceptRequest(me, username)
                 .addOnSuccessListener(aVoid ->
-                        Navigation.findNavController(requireView()).popBackStack());
+                        Navigation.findNavController(requireView()).popBackStack())
+                .addOnFailureListener(e -> Log.e("RequestFragment", "Accept failed", e));
     }
 
+
     private void denyFollowRequest(String username) {
         String me = FirebaseAuth.getInstance().getCurrentUser().getUid();
         FollowProvider.getInstance()
diff --git a/code/app/src/main/java/com/kernelcrew/moodapp/utils/NotificationHelper.java b/code/app/src/main/java/com/kernelcrew/moodapp/utils/NotificationHelper.java
new file mode 100644
index 0000000000..925f1ad621
--- /dev/null
+++ b/code/app/src/main/java/com/kernelcrew/moodapp/utils/NotificationHelper.java
@@ -0,0 +1,77 @@
+package com.kernelcrew.moodapp.utils;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import com.kernelcrew.moodapp.R;
+import com.kernelcrew.moodapp.ui.HomeFeed;
+
+public class NotificationHelper {
+    private static final String CHANNEL_ID = "follow_request_channel";
+    private static final String CHANNEL_NAME = "Follow Requests";
+    private static final String CHANNEL_DESCRIPTION = "Notifications for follow requests and follow confirmations";
+
+    private Context context;
+    private NotificationManagerCompat notificationManager;
+
+    public NotificationHelper(Context context) {
+        this.context = context;
+        this.notificationManager = NotificationManagerCompat.from(context);
+        createNotificationChannel();
+    }
+
+    // Create the notification channel (for API 26+)
+    private void createNotificationChannel() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            NotificationChannel channel = new NotificationChannel(
+                    CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
+            channel.setDescription(CHANNEL_DESCRIPTION);
+            NotificationManager manager = context.getSystemService(NotificationManager.class);
+            if (manager != null) {
+                manager.createNotificationChannel(channel);
+            }
+        }
+    }
+
+    // Send a notification with the specified title and message
+    public void sendNotification(String title, String message) {
+
+        // For Android 13 check the POST_NOTIFICATIONS permission.
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            if (context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                return;
+            }
+        }
+
+        // Create an intent to launch the HomeFeed when the notification is tapped
+        Intent intent = new Intent(context, HomeFeed.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        PendingIntent pendingIntent = PendingIntent.getActivity(
+                context,
+                0,
+                intent,
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
+        );
+
+        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
+                .setSmallIcon(R.drawable.ic_notifications)
+                .setContentTitle(title)
+                .setContentText(message)
+                .setContentIntent(pendingIntent)
+                .setAutoCancel(true)
+                .setPriority(NotificationCompat.PRIORITY_DEFAULT);
+
+        // Use a unique id for each notification
+        notificationManager.notify((int) System.currentTimeMillis(), builder.build());
+    }
+}


Reviews:
user: login: antonrou
body: @siddhantgoel7 can you add the testing procedure under "Testing" in the description of this pull request? Otherwise I'm not sure how to test this pull request
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T17:34:15Z
user: login: adityadipakpatel
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-28T20:44:40Z
user: login: adityadipakpatel
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T20:47:49Z
user: login: PossiblyAShrub
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T22:24:00Z
user: login: adityadipakpatel
body: This is good but notifications are still not working
state: DISMISSED
author_association: NONE
submitted_at: 2025-03-29T01:15:34Z
user: login: adityadipakpatel
body: Done
Notifications work perfectly now
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-29T03:23:55Z
user: login: adityadipakpatel
state: APPROVED
author_association: NONE
submitted_at: 2025-03-29T04:07:27Z
user: login: TahaKamil
body: We really should be using the user class and UserProvider more. @PossiblyAShrub, should we have someone run through and replace all the usages with UserProvider FollowerProvider? Though we are low in time, so it really isnt priority I guess.
state: APPROVED
author_association: NONE
submitted_at: 2025-03-29T16:46:46Z

Review comments:
diff_hunk: @@ -18,13 +17,14 @@
 import com.google.android.material.navigation.NavigationBarView;
 import com.google.firebase.auth.FirebaseAuth;
 import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentChange;
 import com.google.firebase.firestore.DocumentSnapshot;
-import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.FirebaseFirestore;
path: code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
user: login: adityadipakpatel
body: You changed/removed the "Query"
This might introduce errors, bugs in the home feed mood filters.
created_at: 2025-03-28T20:35:44Z
author_association: NONE
diff_hunk: @@ -54,9 +54,111 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
 
         navBarController = new BottomNavBarController(navigationBar);
 
path: code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
user: login: adityadipakpatel
body: Not sure if this part needs to be moved to a separate notification class or can it stay on the home feed class
@PossiblyAShrub What's your opinion?
created_at: 2025-03-28T20:40:48Z
author_association: NONE
diff_hunk: @@ -93,14 +94,14 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                                         } else {
                                             followButton.setText("Follow");
                                             followButton.setEnabled(true);
-                                            followButton.setOnClickListener(v ->
-                                                    provider.sendRequest(uidToLoad, currentUid)
-                                                            .addOnSuccessListener(a -> {
-                                                                followButton.setText("Requested");
-                                                                followButton.setEnabled(false);
-                                                            })
-                                                            .addOnFailureListener(e -> Log.e(TAG, "Request failed", e))
-                                            );
+                                            followButton.setOnClickListener(v -> {
path: code/app/src/main/java/com/kernelcrew/moodapp/ui/OtherUserProfile.java
user: login: adityadipakpatel
body: I have changed some stuff in this file to add new features in my branch
Can you review my PR, merge that into main and then run "git pull origin main" in your branch?
created_at: 2025-03-28T20:43:53Z
author_association: NONE
diff_hunk: @@ -54,9 +54,111 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
 
         navBarController = new BottomNavBarController(navigationBar);
 
path: code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
user: login: adityadipakpatel
body: @PossiblyAShrub 
Also, is there any way to test using the express androidTest to check functionality/correctness if the user received an android notification or not?
created_at: 2025-03-28T20:47:49Z
author_association: NONE
diff_hunk: @@ -54,9 +54,111 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
 
         navBarController = new BottomNavBarController(navigationBar);
 
path: code/app/src/main/java/com/kernelcrew/moodapp/ui/HomeFeed.java
user: login: PossiblyAShrub
body: > What's your opinion?

Yeah, a separate class is *probably* a good idea. But maybe just a method will do instead.

Although, far more importantly, all the `db.*` stuff should be put inside a relevant provider. No ui class should hold a reference to `FirebaseFirestore`.
created_at: 2025-03-28T22:24:00Z
author_association: NONE

PR comments:
user: login: siddhantgoel7
created_at: 2025-03-28T19:36:03Z
body: > @siddhantgoel7 can you add the testing procedure under "Testing" in the description of this pull request? Otherwise I'm not sure how to test this pull request

updated
author_association: NONE
user: login: adityadipakpatel
created_at: 2025-03-29T03:46:28Z
body: This feature works perfectly now

https://github.com/user-attachments/assets/190c7bdc-3748-4443-b87e-2226a3c4b235

I would appreciate if someone could please review this PR. Thanks :)

author_association: NONE