Skip to content

Commit

Permalink
Integration: integrate the login functionality with the back-end (#29)
Browse files Browse the repository at this point in the history
* fix: modify the api calling code

* feat: use the user real profile data in the drawer

* feat: use user data in the drawer and profile header

* fix: fix wrong range of status code

* REF(Sessions): add update profile pic

* fix: wrong body in the forget password request

* fix: handle wrong spacing in the login and sign up screens

* feat: make the screen name 'No Name' in case of the using not having a name

* fix: merge brackets problem

* Update main.dart

* Update main.dart

* fix: add a missing import in the sign up screen

---------

Co-authored-by: Bishoywadea <[email protected]>
  • Loading branch information
Ahmed-Aladdiin and Bishoywadea authored Nov 1, 2024
1 parent 1493306 commit 2c2b6c4
Show file tree
Hide file tree
Showing 24 changed files with 524 additions and 415 deletions.
4 changes: 4 additions & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
- provider: true
43 changes: 43 additions & 0 deletions lib/core/classes/telware_toast.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';

class TelwareToast{
static String? _message;

static Future<bool?> showToast({
required String msg,
Toast? toastLength,
int timeInSecForIosWeb = 1,
double? fontSize,
String? fontAsset,
ToastGravity? gravity,
Color? backgroundColor,
Color? textColor,
bool webShowClose = false,
webBgColor = "linear-gradient(to right, #00b09b, #96c93d)",
webPosition = "right",
}) async {
_message = msg;
return await Fluttertoast.showToast(
msg: msg,
toastLength: toastLength,
timeInSecForIosWeb: timeInSecForIosWeb,
fontSize: fontSize,
fontAsset: fontAsset,
gravity: gravity,
backgroundColor: backgroundColor,
textColor: textColor,
webShowClose: webShowClose,
webBgColor: webBgColor,
webPosition: webPosition,
);
}

static Future<bool?> cancel() async {
return await Fluttertoast.cancel();
}

static String? get message => _message;

TelwareToast._();
}
10 changes: 8 additions & 2 deletions lib/core/constants/server_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
final String API_URL = dotenv.env['API_URL']!;
final String GOOGLE_AUTH_URL = API_URL + dotenv.env['GOOGLE_AUTH_URL']!;
final String GITHUB_AUTH_URL = API_URL + dotenv.env['GITHUB_AUTH_URL']!;
final BASE_OPTIONS =
BaseOptions(baseUrl: API_URL, contentType: 'application/json');
final BASE_OPTIONS = BaseOptions(
baseUrl: API_URL,
contentType: 'application/json',
connectTimeout: const Duration(seconds: 5), // 5 seconds
receiveTimeout: const Duration(seconds: 3), // 3 seconds
sendTimeout: const Duration(seconds: 3), // 3 seconds
);

6 changes: 3 additions & 3 deletions lib/core/mock/user_mock.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import 'package:telware_cross_platform/core/models/user_model.dart';

const UserModel userMock = UserModel(
final UserModel userMock = UserModel(
username: 'mock.user',
screenName: 'Mocka Mocka',
email: '[email protected]',
status: 'verified',
status: 'online',
bio: 'I am a mocking user',
maxFileSize: 30,
automaticDownloadEnable: true,
lastSeenPrivacy: 'recently',
readReceiptsEnablePrivacy: 'enable',
readReceiptsEnablePrivacy: true,
storiesPrivacy: 'private',
picturePrivacy: 'global',
invitePermissionsPrivacy: 'enable',
Expand Down
97 changes: 57 additions & 40 deletions lib/core/models/user_model.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';
import 'dart:typed_data';

import 'package:hive/hive.dart';
import 'package:telware_cross_platform/features/stories/utils/utils_functions.dart';

part 'user_model.g.dart';

Expand All @@ -26,7 +28,7 @@ class UserModel {
@HiveField(8)
final String lastSeenPrivacy;
@HiveField(9)
final String readReceiptsEnablePrivacy;
final bool readReceiptsEnablePrivacy;
@HiveField(10)
final String storiesPrivacy;
@HiveField(11)
Expand All @@ -35,8 +37,10 @@ class UserModel {
final String invitePermissionsPrivacy;
@HiveField(13)
final String phone;
@HiveField(14)
Uint8List? photoBytes;

const UserModel({
UserModel({
required this.username,
required this.screenName,
required this.email,
Expand All @@ -51,45 +55,50 @@ class UserModel {
required this.picturePrivacy,
required this.invitePermissionsPrivacy,
required this.phone,
});
}) {
_setPhotoBytes();
}

_setPhotoBytes() async {
photoBytes = await downloadImage(photo);
}

@override
bool operator ==(covariant UserModel other) {
if (identical(this, other)) return true;

return
other.username == username &&
other.screenName == screenName &&
other.email == email &&
other.photo == photo &&
other.status == status &&
other.bio == bio &&
other.maxFileSize == maxFileSize &&
other.automaticDownloadEnable == automaticDownloadEnable &&
other.lastSeenPrivacy == lastSeenPrivacy &&
other.readReceiptsEnablePrivacy == readReceiptsEnablePrivacy &&
other.storiesPrivacy == storiesPrivacy &&
other.picturePrivacy == picturePrivacy &&
other.invitePermissionsPrivacy == invitePermissionsPrivacy &&
other.phone == phone;

return other.username == username &&
other.screenName == screenName &&
other.email == email &&
other.photo == photo &&
other.status == status &&
other.bio == bio &&
other.maxFileSize == maxFileSize &&
other.automaticDownloadEnable == automaticDownloadEnable &&
other.lastSeenPrivacy == lastSeenPrivacy &&
other.readReceiptsEnablePrivacy == readReceiptsEnablePrivacy &&
other.storiesPrivacy == storiesPrivacy &&
other.picturePrivacy == picturePrivacy &&
other.invitePermissionsPrivacy == invitePermissionsPrivacy &&
other.phone == phone;
}

@override
int get hashCode {
return username.hashCode ^
screenName.hashCode ^
email.hashCode ^
photo.hashCode ^
status.hashCode ^
bio.hashCode ^
maxFileSize.hashCode ^
automaticDownloadEnable.hashCode ^
lastSeenPrivacy.hashCode ^
readReceiptsEnablePrivacy.hashCode ^
storiesPrivacy.hashCode ^
picturePrivacy.hashCode ^
invitePermissionsPrivacy.hashCode ^
phone.hashCode;
screenName.hashCode ^
email.hashCode ^
photo.hashCode ^
status.hashCode ^
bio.hashCode ^
maxFileSize.hashCode ^
automaticDownloadEnable.hashCode ^
lastSeenPrivacy.hashCode ^
readReceiptsEnablePrivacy.hashCode ^
storiesPrivacy.hashCode ^
picturePrivacy.hashCode ^
invitePermissionsPrivacy.hashCode ^
phone.hashCode;
}

@override
Expand All @@ -107,7 +116,7 @@ class UserModel {
int? maxFileSize,
bool? automaticDownloadEnable,
String? lastSeenPrivacy,
String? readReceiptsEnablePrivacy,
bool? readReceiptsEnablePrivacy,
String? storiesPrivacy,
String? picturePrivacy,
String? invitePermissionsPrivacy,
Expand All @@ -121,12 +130,15 @@ class UserModel {
status: status ?? this.status,
bio: bio ?? this.bio,
maxFileSize: maxFileSize ?? this.maxFileSize,
automaticDownloadEnable: automaticDownloadEnable ?? this.automaticDownloadEnable,
automaticDownloadEnable:
automaticDownloadEnable ?? this.automaticDownloadEnable,
lastSeenPrivacy: lastSeenPrivacy ?? this.lastSeenPrivacy,
readReceiptsEnablePrivacy: readReceiptsEnablePrivacy ?? this.readReceiptsEnablePrivacy,
readReceiptsEnablePrivacy:
readReceiptsEnablePrivacy ?? this.readReceiptsEnablePrivacy,
storiesPrivacy: storiesPrivacy ?? this.storiesPrivacy,
picturePrivacy: picturePrivacy ?? this.picturePrivacy,
invitePermissionsPrivacy: invitePermissionsPrivacy ?? this.invitePermissionsPrivacy,
invitePermissionsPrivacy:
invitePermissionsPrivacy ?? this.invitePermissionsPrivacy,
phone: phone ?? this.phone,
);
}
Expand All @@ -151,25 +163,30 @@ class UserModel {
}

factory UserModel.fromMap(Map<String, dynamic> map) {
String screenName = map['screenName'] as String;
if (screenName.isEmpty) {
screenName = 'No Name';
}
return UserModel(
username: map['username'] as String,
screenName: map['screenName'] as String,
screenName: screenName,
email: map['email'] as String,
photo: map['photo'] != null ? map['photo'] as String : null,
status: map['status'] as String,
bio: map['bio'] as String,
maxFileSize: map['maxFileSize'] as int,
automaticDownloadEnable: map['automaticDownloadEnable'] as bool,
lastSeenPrivacy: map['lastSeenPrivacy'] as String,
readReceiptsEnablePrivacy: map['readReceiptsEnablePrivacy'] as String,
readReceiptsEnablePrivacy: map['readReceiptsEnablePrivacy'] as bool,
storiesPrivacy: map['storiesPrivacy'] as String,
picturePrivacy: map['picturePrivacy'] as String,
invitePermissionsPrivacy: map['invitePermessionsPrivacy'] as String,
phone: map['phone'] as String,
phone: map['phoneNumber'] as String,
);
}

String toJson() => json.encode(toMap());

factory UserModel.fromJson(String source) => UserModel.fromMap(json.decode(source) as Map<String, dynamic>);
factory UserModel.fromJson(String source) =>
UserModel.fromMap(json.decode(source) as Map<String, dynamic>);
}
10 changes: 6 additions & 4 deletions lib/core/models/user_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions lib/core/routes/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import 'package:telware_cross_platform/features/auth/view/screens/verification_s
import 'package:telware_cross_platform/features/auth/view_model/auth_view_model.dart';
import 'package:telware_cross_platform/features/home/view/screens/home_screen.dart';
import 'package:telware_cross_platform/features/home/view/screens/inbox_screen.dart';
import 'package:telware_cross_platform/features/stories/view/screens/add_my_story_screen.dart';
import 'package:telware_cross_platform/features/stories/view/screens/show_taken_story_screen.dart';
import 'package:telware_cross_platform/features/stories/view/screens/add_my_image_screen.dart';
import 'package:telware_cross_platform/features/stories/view/screens/show_taken_image_screen.dart';
import 'package:telware_cross_platform/features/stories/view/screens/story_screen.dart';
import 'package:telware_cross_platform/features/user/view/screens/block_user.dart';
import 'package:telware_cross_platform/features/user/view/screens/blocked_users.dart';
Expand All @@ -34,8 +34,8 @@ class Routes {
static const String verification = VerificationScreen.route;
static const String socialAuthLoading = SocialAuthLoadingScreen.route;
static const String inboxScreen = InboxScreen.route;
static const String addMyStory = AddMyStoryScreen.route;
static const String showTakenStory = ShowTakenStoryScreen.route;
static const String addMyStory = AddMyImageScreen.route;
static const String showTakenStory = ShowTakenImageScreen.route;
static const String storyScreen = StoryScreen.route;
static const String devicesScreen = DevicesScreen.route;
static const String settings = SettingsScreen.route;
Expand Down Expand Up @@ -110,15 +110,15 @@ class Routes {
path: Routes.addMyStory,
pageBuilder: (context, state) => CustomTransitionPage(
key: state.pageKey,
child: const AddMyStoryScreen(),
child: const AddMyImageScreen(),
transitionsBuilder: _slideRightTransitionBuilder,
),
),
GoRoute(
path: Routes.showTakenStory,
pageBuilder: (context, state) => CustomTransitionPage(
key: state.pageKey,
child: ShowTakenStoryScreen(image: state.extra as File),
child: ShowTakenImageScreen(image: state.extra as File),
transitionsBuilder: _slideRightTransitionBuilder,
),
),
Expand Down
30 changes: 18 additions & 12 deletions lib/core/utils.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// common utility functions are added here
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:telware_cross_platform/core/classes/telware_toast.dart';

String? emailValidator(String? value) {
const String emailPattern =
Expand Down Expand Up @@ -29,15 +29,6 @@ String? passwordValidator(String? value) {
return null;
}

String? passwordValidatorLogIn(String? value) {
if (value == null || value.isEmpty) {
return null;
} else if (value.length < 8) {
return 'Password must be at least 8 characters long';
}
return null;
}

// todo(ahmed): update this function to handle more cases
String? confirmPasswordValidation(String? password, String? confirmedPassword) {
if (password!.isEmpty || confirmedPassword!.isEmpty) return null;
Expand All @@ -62,8 +53,8 @@ void showSnackBarMessage(BuildContext context, String message) {
}

void showToastMessage(String message) async {
await Fluttertoast.cancel();
Fluttertoast.showToast(msg: message);
await TelwareToast.cancel();
TelwareToast.showToast(msg: message);
}

String formatPhoneNumber(String phoneNumber) {
Expand Down Expand Up @@ -102,3 +93,18 @@ String toKebabCase(String input) {
// Remove leading or trailing hyphens
return kebabCased.replaceAll(RegExp(r'^-+|-+$'), '');
}

String getInitials(String name) {
if (name.isEmpty) {
return "NN";
}
List<String> nameParts = name.split(' ');
String initials = "";
if (nameParts.isNotEmpty) {
initials = nameParts[0][0];
if (nameParts.length > 1) {
initials += nameParts[1][0];
}
}
return initials.toUpperCase();
}
5 changes: 5 additions & 0 deletions lib/features/auth/models/auth_response_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ class AuthResponseModel {
});

factory AuthResponseModel.fromMap(Map<String, dynamic> map) {
map.forEach(
(key, value) {
print('key: $key, value: $value, value type: ${value.runtimeType}');
},
);
return AuthResponseModel(
user: UserModel.fromMap(map['user'] as Map<String, dynamic>),
token: map['sessionId'] as String,
Expand Down
Loading

0 comments on commit 2c2b6c4

Please sign in to comment.