1+ import 'dart:async' ;
12import 'dart:developer' ;
23
34import 'package:appwrite/appwrite.dart' ;
45import 'package:appwrite/models.dart' ;
56import 'package:get/get.dart' ;
67import 'package:livekit_client/livekit_client.dart' ;
78import 'package:resonate/controllers/auth_state_controller.dart' ;
9+ import 'package:resonate/models/resonate_user.dart' ;
810import 'package:resonate/routes/app_routes.dart' ;
911import 'package:resonate/services/appwrite_service.dart' ;
1012import 'package:resonate/services/room_service.dart' ;
1113import 'package:resonate/utils/constants.dart' ;
14+ import 'package:resonate/views/widgets/rating_sheet.dart' ;
1215
1316import 'livekit_controller.dart' ;
1417
@@ -25,23 +28,30 @@ class PairChatController extends GetxController {
2528
2629 String ? pairUsername;
2730 String ? pairProfileImageUrl;
31+ RxDouble pairRating = 2.5 .obs;
2832
2933 Client client = AppwriteService .getClient ();
3034 final Realtime realtime = AppwriteService .getRealtime ();
3135 final Databases databases = AppwriteService .getDatabases ();
3236 late RealtimeSubscription ? subscription;
37+ late RealtimeSubscription ? userAddedSubscription;
38+ AuthStateController authController = Get .find <AuthStateController >();
39+
40+ RxList <ResonateUser > usersList = < ResonateUser > [].obs;
41+ final RxBool isUserListLoading = true .obs;
3342
3443 void quickMatch () async {
35- String uid = Get . find < AuthStateController >() .uid! ;
36- String userName = Get . find < AuthStateController >() .userName! ;
44+ String uid = authController .uid! ;
45+ String userName = authController .userName! ;
3746
3847 // Open realtime stream to check whether the request is paired
3948 getRealtimeStream ();
4049
4150 Map <String , dynamic > requestData = {
4251 "languageIso" : languageIso,
4352 "isAnonymous" : isAnonymous.value,
44- "uid" : uid
53+ "uid" : uid,
54+ "isRandom" : true ,
4555 };
4656 requestData.addIf (! isAnonymous.value, "userName" , userName);
4757
@@ -57,8 +67,46 @@ class PairChatController extends GetxController {
5767 Get .toNamed (AppRoutes .pairing);
5868 }
5969
70+ void choosePartner () async {
71+ checkForNewUsers ();
72+ getRealtimeStream ();
73+ isAnonymous.value = false ;
74+ Map <String , dynamic > requestData = {
75+ "languageIso" : languageIso,
76+ "isAnonymous" : false ,
77+ "uid" : authController.uid,
78+ "isRandom" : false ,
79+ "profileImageUrl" : authController.profileImageUrl,
80+ "userName" : authController.userName,
81+ "name" : authController.displayName,
82+ "userRating" : authController.ratingTotal / authController.ratingCount,
83+ };
84+
85+ // Add request to pair-request collection
86+ Document requestDoc = await databases.createDocument (
87+ databaseId: masterDatabaseId,
88+ collectionId: pairRequestCollectionId,
89+ documentId: ID .unique (),
90+ data: requestData);
91+ requestDocId = requestDoc.$id;
92+ Get .toNamed (AppRoutes .pairChatUsers);
93+ }
94+
95+ Future <void > convertToRandom () async {
96+ userAddedSubscription? .close ();
97+ getRealtimeStream ();
98+ await databases.updateDocument (
99+ databaseId: masterDatabaseId,
100+ collectionId: pairRequestCollectionId,
101+ documentId: requestDocId! ,
102+ data: {
103+ 'isRandom' : true ,
104+ });
105+ Get .toNamed (AppRoutes .pairing);
106+ }
107+
60108 void getRealtimeStream () {
61- String uid = Get . find < AuthStateController >() .uid! ;
109+ String uid = authController .uid! ;
62110 String channel =
63111 'databases.$masterDatabaseId .collections.$activePairsCollectionId .documents' ;
64112 subscription = realtime.subscribe ([channel]);
@@ -99,15 +147,84 @@ class PairChatController extends GetxController {
99147 }
100148 case 'delete' :
101149 {
102- subscription? .close;
103- Get .offNamedUntil (AppRoutes .tabview, (route) => false );
150+ endChat ();
104151 }
105152 }
106153 }
107154 }
108155 });
109156 }
110157
158+ Future <void > pairWithSelectedUser (ResonateUser user) async {
159+ log ('pairing' );
160+ await databases.createDocument (
161+ databaseId: masterDatabaseId,
162+ collectionId: activePairsCollectionId,
163+ documentId: ID .unique (),
164+ data: {
165+ 'uid1' : authController.uid,
166+ 'uid2' : user.uid,
167+ 'userName1' : authController.userName,
168+ 'userName2' : user.userName,
169+ 'userDocId1' : requestDocId,
170+ 'userDocId2' : user.docId,
171+ });
172+ }
173+
174+ void checkForNewUsers () {
175+ log ('listening for new users' );
176+ String channel =
177+ 'databases.$masterDatabaseId .collections.$pairRequestCollectionId .documents' ;
178+ userAddedSubscription = realtime.subscribe ([channel]);
179+ userAddedSubscription? .stream.listen ((data) async {
180+ final event = data.events.first;
181+ if (data.payload.isNotEmpty) {
182+ if (event.endsWith ('.create' )) {
183+ log ('adding new user' );
184+ // If a new user is added to the pair request collection
185+ final userData = data.payload;
186+ final eventSplit = event.split ('.' );
187+ final docId =
188+ eventSplit[eventSplit.length - 2 ]; // Get the second last
189+ userData['docId' ] = docId; // Add docId to the user
190+ ResonateUser newUser = ResonateUser .fromJson (userData);
191+
192+ usersList.add (newUser);
193+ } else if (event.endsWith ('.delete' )) {
194+ ResonateUser removedUser = ResonateUser .fromJson (data.payload);
195+ usersList.removeWhere ((user) => user.uid == removedUser.uid);
196+ }
197+ }
198+ });
199+ }
200+
201+ Future <void > loadUsers () async {
202+ isUserListLoading.value = true ;
203+ log ("Loading users" );
204+ usersList.clear ();
205+ final result = await databases.listDocuments (
206+ databaseId: masterDatabaseId,
207+ collectionId: pairRequestCollectionId,
208+ queries: [
209+ Query .notEqual ('uid' , authController.uid! ),
210+ Query .notEqual ('isAnonymous' , true ),
211+ Query .limit (100 )
212+ ]);
213+ if (result.documents.isEmpty) {
214+ isUserListLoading.value = false ;
215+ return ;
216+ } else {
217+ usersList.addAll (result.documents.map ((doc) {
218+ final userData = doc.data;
219+ userData['docId' ] = doc.$id; // Add docId to the user data
220+ ResonateUser user = ResonateUser .fromJson (userData);
221+
222+ return user;
223+ }).toList ());
224+ }
225+ isUserListLoading.value = false ;
226+ }
227+
111228 Future <void > joinPairChat (roomId, userId) async {
112229 await RoomService .joinLivekitPairChat (roomId: roomId, userId: userId);
113230 Get .toNamed (AppRoutes .pairChat);
@@ -119,6 +236,7 @@ class PairChatController extends GetxController {
119236 collectionId: pairRequestCollectionId,
120237 documentId: requestDocId! );
121238 subscription? .close ();
239+ userAddedSubscription? .close ();
122240 Get .offNamedUntil (AppRoutes .tabview, (route) => false );
123241 }
124242
@@ -136,12 +254,22 @@ class PairChatController extends GetxController {
136254 }
137255
138256 Future <void > endChat () async {
139- subscription? .close;
140- await databases.deleteDocument (
141- databaseId: masterDatabaseId,
142- collectionId: activePairsCollectionId,
143- documentId: activePairDocId! );
257+ subscription? .close ();
258+ try {
259+ await databases.deleteDocument (
260+ databaseId: masterDatabaseId,
261+ collectionId: activePairsCollectionId,
262+ documentId: activePairDocId! );
263+ } catch (e) {
264+ if (! (e is AppwriteException && e.type == 'document_not_found' )) {
265+ rethrow ;
266+ }
267+ }
144268 await Get .delete <LiveKitController >(force: true );
269+
270+ await Get .bottomSheet (
271+ RatingSheetWidget (),
272+ );
145273 Get .offNamedUntil (AppRoutes .tabview, (route) => false );
146274 }
147275}
0 commit comments