Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration: integrate the login functionality with the back-end #29

Merged
merged 14 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading