0
votes

Slowly getting to grips with Flutter and Dart as my new hobby. Any advice or help you can give is always appreciated! I am trying to implement a simple friend system, where you can search for another user and add them as a friend.

The intended outcome is:

  1. Logged in user goes to profile of friend and clicks 'add friend' button.
  2. Firestore has a users collection. In that collection is a document for each user with profile information, including an array 'friends'. Clicking the 'add friend' button will add the logged in users UID to that second person's 'friends' array.
  3. Then on a Friends screen, I am using a StreamBuilder and Listview.builder to show all users as cards, that have the logged in user's UID in their 'friends' array.

To achieve this, I want to use .where('friends', arrayContains: 'user.uid') in stream of StreamBuilder, to only show those user cards in the list on the screen.

Here is the code I have written:

class friendsList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<User>(context);

    return 
      StreamBuilder(
      stream: Firestore.instance
              .collection('users')
              .where('friends', arrayContains: user.uid).snapshots(),
               builder: (context, documents) {

               if (documents.hasData) {
               return 

               Container(
                    height: 180,
                        child:

                            ListView.builder(
                               scrollDirection: Axis.horizontal,
                               itemCount: 1,
                               itemBuilder: (context, index) {

                               DocumentSnapshot friends = documents.data.documents[index]; 

However, when I go to run my app, it shows error:

`The following RangeError was thrown building:
      RangeError (index): Invalid value: Valid value range is empty: 0

      When the exception was thrown, this was the stack 
        List.[](dart:core-patch/growable_array.dart:149:60)
        friendsList.build.<anonymous closure>.<anonymous closure> 

Notes:

  1. itemCount is hardcoded to 1 right now. I am only expecting 1 user to be returned while I am testing. I will populate Firestore with more users once it is all working.
  2. When I swap arrayContains for something simpler like .where('displayName', isEqualTo: 'My Name').snapshots(), , the app works without errors
  3. user.uid has been tested and does contain the intended string
  4. Arrays are present with values in Firestore (See link at bottom of post)
  5. I have setup an index for the values I am using in 'users'

Does anyone know what I can do about this error and retrieve the documents that have the friends array with the logged in user UID?

Again any advice and help is appreciated. Screenshot of Cloud Firestore is here

2
So quick question.. you're trying to retrieve all the friends of a current user by looking up all users that have this user as a friend?ChiefMalone
It sounds backward, but yes. Unlike SQL, Firestore doesn't support a JOIN, so I can't lookup and display user documents, based on a field from the current users document. To my knowledge, the easiest solution is to store your UID in an array on their document, so that you can query and get back any document that has your UID in their friends array. The problem I am having is that error, which implies that there are 0 documents with the friends' array that have my UID. However, as you can see from the screenshot, I do have documents with that value in the friends array. Any thoughts?Tristan Kay
ChiefMalone - If you had to implement a friend system, how would you approach it? Any advice is welcomed. I'm still learning and open to ideas.Tristan Kay

2 Answers

1
votes

I left my project for two days and rebuilt the app in the last hour. To my surprise, '.where('friends', arrayContains: user.uid)' now works!

When the app starts, I now have a ListView of all users who are a friend of the currently logged in user.

How the complete system works:

  1. On the profile page of each user is a Floating Action Button that when pressed, add's the currently logged in user's UID to a 'friends' array in the document of that friend.

  2. With StreamBuilder and ListView, when the logged in user then goes to their friends page, they see every user that has the logged in user's UID in their 'friends' array

0
votes

It could be the case that you are printing the results of an empty data from firebase.

Stream<List<Model>> fetchStream({@required String userUID}) {
return nestsCollection
    .where("participants", arrayContains: userUID)
    .snapshots()
    .map((snapshot) {
    // print(snapshot.docs[0].data()['nestName']);
  return snapshot.docs
      .map((document) => Model.fromFirestore(document))
      .toList();
 });
}