Skip to content

Commit

Permalink
Add member via contact (#97)
Browse files Browse the repository at this point in the history
* fetch contact and confirm number

* use http callable

* refactor logs

* minor change

* change field

* fix not a function error

* allow non null value

* allow non null value

* change to list

* change start and end threshold

* change region

* change log

* change log

* workflow run on main
  • Loading branch information
cp-sidhdhi-p authored Sep 23, 2024
1 parent 827becd commit 3f054cc
Show file tree
Hide file tree
Showing 40 changed files with 1,981 additions and 118 deletions.
44 changes: 23 additions & 21 deletions data/.flutter-plugins
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
# This is a generated file; do not edit or check into version control.
cloud_firestore=/home/mayank/.pub-cache/hosted/pub.dev/cloud_firestore-5.2.0/
cloud_firestore_web=/home/mayank/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.1.0/
device_info_plus=/home/mayank/.pub-cache/hosted/pub.dev/device_info_plus-10.1.1/
firebase_auth=/home/mayank/.pub-cache/hosted/pub.dev/firebase_auth-5.1.3/
firebase_auth_web=/home/mayank/.pub-cache/hosted/pub.dev/firebase_auth_web-5.12.5/
firebase_core=/home/mayank/.pub-cache/hosted/pub.dev/firebase_core-3.3.0/
firebase_core_web=/home/mayank/.pub-cache/hosted/pub.dev/firebase_core_web-2.17.4/
firebase_messaging=/home/mayank/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.4/
firebase_messaging_web=/home/mayank/.pub-cache/hosted/pub.dev/firebase_messaging_web-3.8.12/
firebase_storage=/home/mayank/.pub-cache/hosted/pub.dev/firebase_storage-12.1.2/
firebase_storage_web=/home/mayank/.pub-cache/hosted/pub.dev/firebase_storage_web-3.9.12/
flutter_timezone=/home/mayank/.pub-cache/hosted/pub.dev/flutter_timezone-2.1.0/
package_info_plus=/home/mayank/.pub-cache/hosted/pub.dev/package_info_plus-8.0.1/
path_provider_linux=/home/mayank/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
path_provider_windows=/home/mayank/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/
shared_preferences=/home/mayank/.pub-cache/hosted/pub.dev/shared_preferences-2.3.1/
shared_preferences_android=/home/mayank/.pub-cache/hosted/pub.dev/shared_preferences_android-2.3.0/
shared_preferences_foundation=/home/mayank/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.0/
shared_preferences_linux=/home/mayank/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.0/
shared_preferences_web=/home/mayank/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/
shared_preferences_windows=/home/mayank/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.0/
cloud_firestore=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/cloud_firestore-5.0.2/
cloud_firestore_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.0.2/
cloud_functions=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/cloud_functions-5.1.1/
cloud_functions_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/cloud_functions_web-4.10.0/
device_info_plus=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/
firebase_auth=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_auth-5.1.1/
firebase_auth_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_auth_web-5.13.0/
firebase_core=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_core-3.4.1/
firebase_core_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_core_web-2.18.0/
firebase_messaging=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.2/
firebase_messaging_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_messaging_web-3.9.0/
firebase_storage=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_storage-12.1.0/
firebase_storage_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/firebase_storage_web-3.10.0/
flutter_timezone=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/flutter_timezone-2.0.1/
package_info_plus=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/package_info_plus-8.0.2/
path_provider_linux=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
path_provider_windows=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/
shared_preferences=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/
shared_preferences_android=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.3/
shared_preferences_foundation=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.4.0/
shared_preferences_linux=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.3.2/
shared_preferences_web=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/shared_preferences_web-2.2.1/
shared_preferences_windows=/Users/sidhdhi.p/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.3.2/
2 changes: 1 addition & 1 deletion data/.flutter-plugins-dependencies

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions data/lib/api/network/client.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,71 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../errors/app_error.dart';
import '../../service/auth/auth_service.dart';
import '../../utils/constant/firestore_constant.dart';

import 'package:http/http.dart' as http;

import 'endpoint.dart';
import 'interceptor/auth_client.dart';

final httpProvider = Provider((ref) {
final client = http.Client();
return AuthHttpClient(client, ref.read(firebaseAuthProvider));
});

final rawDioProvider = Provider((ref) {
return Dio()
..options.connectTimeout = const Duration(seconds: 30)
..options.sendTimeout = const Duration(seconds: 30)
..options.receiveTimeout = const Duration(seconds: 30);
});

extension HttpExtensions on http.Client {
Future<http.Response> req(Endpoint endpoint) async {

final request = http.Request(
endpoint.method.name,
Uri.parse('${DataConfig.instance.apiBaseUrl}${endpoint.path}'),
)..headers.addAll(endpoint.headers);

if (endpoint.data != null) {
request.headers['content-type'] = 'application/json';
request.body = jsonEncode(endpoint.data);
}

http.Response response;

try {
response = await http.Response.fromStream(await send(request));

if (response.statusCode >= 200 && response.statusCode < 300) {
return response;
}
} catch (error) {
if (error is SocketException) {
throw const NoConnectionError();
} else if (error is TimeoutException) {
throw const NoConnectionError();
} else {
rethrow;
}
}

throw SomethingWentWrongError(
statusCode: response.statusCode.toString(),
message: response.body,
);
}
}

extension HttpResponseExtensions on http.Response {
Map<String, dynamic> get data {
return body.isNotEmpty ? jsonDecode(utf8.decode(bodyBytes)) : {};
}
}
22 changes: 22 additions & 0 deletions data/lib/api/network/endpoint.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:flutter/material.dart';

enum HttpMethod { get, post, put, delete, patch }

@immutable
abstract class Endpoint {
HttpMethod get method => HttpMethod.get;

String get path;

Map<String, String>? get queryParameters => null;

Map<String, String> get headers => const {};

dynamic get data => null;

bool get needsAuth => true;

String? get baseUrl => null;

String? get contentType => null;
}
23 changes: 23 additions & 0 deletions data/lib/api/network/interceptor/auth_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'dart:async';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:http/http.dart' as http;

class AuthHttpClient extends http.BaseClient {
final http.Client inner;
final FirebaseAuth firebaseAuth;

AuthHttpClient(this.inner, this.firebaseAuth);

@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
final user = firebaseAuth.currentUser;

if (user != null) {
final idToken = await user.getIdToken();
request.headers['Authorization'] = 'Bearer $idToken';
}

return inner.send(request);
}
}
2 changes: 1 addition & 1 deletion data/lib/errors/app_error.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AppError implements Exception {
} else if (error is TypeError) {
return SomethingWentWrongError(
message: error.toString(),
stackTrace: error.stackTrace,
stackTrace: stack,
);
} else if (error is LargeAttachmentUploadError) {
return const LargeAttachmentUploadError();
Expand Down
4 changes: 3 additions & 1 deletion data/lib/service/auth/auth_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../api/user/user_models.dart';

final firebaseAuthProvider = Provider((ref) => FirebaseAuth.instance);

final authServiceProvider = Provider((ref) {
return AuthService(
FirebaseAuth.instance,
ref.read(firebaseAuthProvider),
ref.read(userServiceProvider),
ref.read(currentUserJsonPod.notifier),
ref.read(currentUserSessionJsonPod.notifier),
Expand Down
20 changes: 20 additions & 0 deletions data/lib/service/user/user_endpoint.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import '../../api/network/endpoint.dart';

class CreateUserEndpoint extends Endpoint {
final String phone;
final String name;

CreateUserEndpoint({
required this.phone,
required this.name,
});

@override
String get path => 'user/create';

@override
HttpMethod get method => HttpMethod.post;

@override
dynamic get data => {"phone": phone, "name": name};
}
39 changes: 39 additions & 0 deletions data/lib/service/user/user_service.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:http/http.dart' as http;
import '../../errors/app_error.dart';
import '../../extensions/list_extensions.dart';
import '../../api/network/client.dart';
import '../device/device_service.dart';
import '../../utils/constant/firestore_constant.dart';
import '../../utils/dummy_deactivated_account.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../api/user/user_models.dart';
import '../../storage/app_preferences.dart';
import 'user_endpoint.dart';

final userServiceProvider = Provider((ref) {
final service = UserService(
ref.read(currentUserPod),
FirebaseFirestore.instance,
ref.read(httpProvider),
ref.read(deviceServiceProvider),
);

Expand All @@ -24,11 +28,13 @@ class UserService {
UserModel? _currentUser;

final FirebaseFirestore firestore;
final http.Client client;
final DeviceService deviceService;

UserService(
this._currentUser,
this.firestore,
this.client,
this.deviceService,
);

Expand Down Expand Up @@ -90,6 +96,24 @@ class UserService {
}
}

Future<UserModel> createNewUser(
String phoneNumber,
String displayName,
) async {
try {
final response = await client.req(
CreateUserEndpoint(
name: displayName,
phone: phoneNumber,
),
);

return UserModel.fromJson(response.data);
} catch (error, stack) {
throw AppError.fromError(error, stack);
}
}

Future<void> updateUser(UserModel user) async {
try {
final userRef = _userRef.doc(user.id);
Expand Down Expand Up @@ -117,6 +141,21 @@ class UserService {
}
}

Future<UserModel?> getUserByPhoneNumber(String number) async {
try {
final snapshot = await _userRef
.where(FireStoreConst.phone, isEqualTo: number)
.get();
if (snapshot.docs.isNotEmpty) {
return snapshot.docs.first.data();
} else {
return null;
}
} catch (error, stack) {
throw AppError.fromError(error, stack);
}
}

Future<List<UserModel>> getUsersByIds(List<String> ids) async {
final List<UserModel> users = [];
try {
Expand Down
19 changes: 19 additions & 0 deletions data/lib/utils/constant/firestore_constant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ class FireStoreConst {
static const String nameLowercase = "name_lowercase";
static const String profileImageUrl = "profile_img_url";

// users field const
static const String deviceFcmToken = "device_fcm_token";
static const String notifications = "notifications";
static const String phone = "phone";
static const String name = "name";
}

class DataConfig {
static late DataConfig _instance;

static DataConfig get instance => _instance;

static void init(DataConfig dataConfig) {
_instance = dataConfig;
}

final String apiBaseUrl;

DataConfig({
required this.apiBaseUrl,
});
}
2 changes: 2 additions & 0 deletions data/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ dependencies:
firebase_auth: ^5.0.0

# io
http: ^1.2.1
dio: ^5.0.2
cloud_functions: ^5.1.1
json_annotation: ^4.9.0
json_serializable: ^6.7.1
freezed_annotation: ^2.4.1
Expand Down
2 changes: 2 additions & 0 deletions khelo/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

<application
android:label="khelo"
Expand Down
12 changes: 12 additions & 0 deletions khelo/assets/locales/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
"add_team_add_as_member_description_text": "Add me as a team member",
"add_team_enter_team_name_placeholder_text": "Enter team name",
"add_team_player_role_title": "Playing role",
"add_team_player_add_via_contact_title": "Add via Contact",
"add_team_players_text": "Players",
"add_team_add_hint_text": "Added user will be shown here, tap on '+' button to add team member.",
"add_team_member_screen_title": "Add team member",
Expand All @@ -166,6 +167,17 @@
}
},

"contact_selection_contact_title": "Contact",
"contact_selection_empty_contact": "No Contacts Found",
"contact_selection_empty_contact_description": "We didn't find any contacts, will be shown here as soon as we get it.",
"contact_selection_access_permission": "Allow contact access",
"contact_selection_access_permission_description": "Allow contact access to add member via contacts.",
"contact_selection_allow_title": "Allow",
"contact_selection_already_added": "Member already added",

"confirm_number_confirm_phone_title": "Confirm phone number",
"confirm_number_confirm_title": "Confirm",

"team_list_add_members_title": "Add Members",
"team_list_all_teams_title": "All teams",
"team_list_created_by_me_title": "Created by me",
Expand Down
1 change: 1 addition & 0 deletions khelo/functions/build/.last_build_id
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
f0f7b7c74e0cb0abb7131f886e5ff844
Loading

0 comments on commit 3f054cc

Please sign in to comment.