Skip to content

Commit c726a71

Browse files
Merge pull request #495 from M4dhav/dev
2 parents ed0de10 + c2c7326 commit c726a71

20 files changed

+876
-189
lines changed

analysis_options.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
# packages, and plugins designed to encourage good coding practices.
1010
include: package:flutter_lints/flutter.yaml
1111

12+
analyzer:
13+
errors:
14+
invalid_annotation_target: ignore
1215
linter:
16+
1317
# The lint rules applied to this project can be customized in the
1418
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
1519
# included above or to enable additional rules. A list of all available lints

lib/controllers/auth_state_controller.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class AuthStateController extends GetxController {
3131
late String? userName;
3232
late bool? isUserProfileComplete;
3333
late bool? isEmailVerified;
34+
late double ratingTotal;
35+
late int ratingCount;
3436
late User appwriteUser;
3537

3638
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
@@ -145,6 +147,8 @@ class AuthStateController extends GetxController {
145147
profileImageUrl = userDataDoc.data["profileImageUrl"];
146148
profileImageID = userDataDoc.data["profileImageID"];
147149
userName = userDataDoc.data["username"] ?? "unavailable";
150+
ratingTotal = userDataDoc.data["ratingTotal"].toDouble() ?? 5;
151+
ratingCount = userDataDoc.data["ratingCount"] ?? 1;
148152
}
149153

150154
update();

lib/controllers/pair_chat_controller.dart

Lines changed: 139 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
import 'dart:async';
12
import 'dart:developer';
23

34
import 'package:appwrite/appwrite.dart';
45
import 'package:appwrite/models.dart';
56
import 'package:get/get.dart';
67
import 'package:livekit_client/livekit_client.dart';
78
import 'package:resonate/controllers/auth_state_controller.dart';
9+
import 'package:resonate/models/resonate_user.dart';
810
import 'package:resonate/routes/app_routes.dart';
911
import 'package:resonate/services/appwrite_service.dart';
1012
import 'package:resonate/services/room_service.dart';
1113
import 'package:resonate/utils/constants.dart';
14+
import 'package:resonate/views/widgets/rating_sheet.dart';
1215

1316
import '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
}

lib/l10n/app_en.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,5 +519,9 @@
519519
"lengthMinutes": "min",
520520
"requiredField": "Required field",
521521
"clickPictureUsingCamera": "Click picture using camera",
522-
"pickImageFromGallery": "Pick image from gallery"
522+
"pickImageFromGallery": "Pick image from gallery",
523+
"onlineUsers": "Online Users",
524+
"noOnlineUsers": "No users currently online",
525+
"chooseUser": "Choose User to chat with",
526+
"quickMatch": "Quick Match"
523527
}

lib/l10n/app_hi.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,5 +520,9 @@
520520
"lengthMinutes": "मिनट",
521521
"requiredField": "आवश्यक फील्ड",
522522
"clickPictureUsingCamera": "कैमरा से फोटो लें",
523-
"pickImageFromGallery": "गैलरी से फोटो चुनें"
523+
"pickImageFromGallery": "गैलरी से फोटो चुनें",
524+
"onlineUsers": "ऑनलाइन यूज़र्स",
525+
"noOnlineUsers": "कोई यूज़र अभी ऑनलाइन नहीं है",
526+
"chooseUser": "चैट करने के लिए यूज़र चुनें",
527+
"quickMatch": "झटपट मैच"
524528
}

lib/l10n/app_localizations.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,6 +1946,30 @@ abstract class AppLocalizations {
19461946
/// In en, this message translates to:
19471947
/// **'Pick image from gallery'**
19481948
String get pickImageFromGallery;
1949+
1950+
/// No description provided for @onlineUsers.
1951+
///
1952+
/// In en, this message translates to:
1953+
/// **'Online Users'**
1954+
String get onlineUsers;
1955+
1956+
/// No description provided for @noOnlineUsers.
1957+
///
1958+
/// In en, this message translates to:
1959+
/// **'No users currently online'**
1960+
String get noOnlineUsers;
1961+
1962+
/// No description provided for @chooseUser.
1963+
///
1964+
/// In en, this message translates to:
1965+
/// **'Choose User to chat with'**
1966+
String get chooseUser;
1967+
1968+
/// No description provided for @quickMatch.
1969+
///
1970+
/// In en, this message translates to:
1971+
/// **'Quick Match'**
1972+
String get quickMatch;
19491973
}
19501974

19511975
class _AppLocalizationsDelegate

lib/l10n/app_localizations_en.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,4 +1053,16 @@ class AppLocalizationsEn extends AppLocalizations {
10531053

10541054
@override
10551055
String get pickImageFromGallery => 'Pick image from gallery';
1056+
1057+
@override
1058+
String get onlineUsers => 'Online Users';
1059+
1060+
@override
1061+
String get noOnlineUsers => 'No users currently online';
1062+
1063+
@override
1064+
String get chooseUser => 'Choose User to chat with';
1065+
1066+
@override
1067+
String get quickMatch => 'Quick Match';
10561068
}

lib/l10n/app_localizations_hi.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,4 +1058,16 @@ class AppLocalizationsHi extends AppLocalizations {
10581058

10591059
@override
10601060
String get pickImageFromGallery => 'गैलरी से फोटो चुनें';
1061+
1062+
@override
1063+
String get onlineUsers => 'ऑनलाइन यूज़र्स';
1064+
1065+
@override
1066+
String get noOnlineUsers => 'कोई यूज़र अभी ऑनलाइन नहीं है';
1067+
1068+
@override
1069+
String get chooseUser => 'चैट करने के लिए यूज़र चुनें';
1070+
1071+
@override
1072+
String get quickMatch => 'झटपट मैच';
10611073
}

lib/models/resonate_user.dart

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
import 'package:freezed_annotation/freezed_annotation.dart';
2+
23
part 'resonate_user.freezed.dart';
34
part 'resonate_user.g.dart';
45

56
@freezed
6-
class ResonateUser with _$ResonateUser {
7+
abstract class ResonateUser with _$ResonateUser {
78
const factory ResonateUser({
89
String? uid,
9-
String? userName,
10+
@JsonKey(name: 'userName') String? userName,
1011
String? profileImageUrl,
11-
String? gender,
12-
String? dateOfBirth,
12+
String? name,
13+
String? email,
14+
@JsonKey(name: 'dob') String? dateOfBirth,
15+
String? docId,
16+
@JsonKey(fromJson: _toDouble) double? userRating,
1317
}) = _ResonateUser;
1418

1519
factory ResonateUser.fromJson(Map<String, dynamic> json) =>
1620
_$ResonateUserFromJson(json);
1721
}
22+
23+
double? _toDouble(dynamic value) {
24+
if (value == null) return null;
25+
if (value is int) return value.toDouble();
26+
return null;
27+
}

0 commit comments

Comments
 (0)