Skip to content

Commit

Permalink
feat(users): Add blocking feature (#22)
Browse files Browse the repository at this point in the history
* FEATURE(AUTH-CROSS): Implement the sign up screen with its components (#2)

* refactor(widget_test): correct app name

* feat(ui): add Palette class for managing colors

* style(ui): modified Palette class

* feat(auth): add signup route

* feat(auth): add signup-ui

* style(auth): add authTheme

* refactor(auth): add auth widgets

* refactor(auth): add dimensions and sizes classes

* refactor(auth): change app name to telware

* refactor(auth): add circle_button widget

* style(auth): switch to dimensions and sizes classes

* feat(auth): secure the password field

* feat(auth): adding validations

* chore(auth): adding shake and vibration packages

* refactor(auth): correcting title name

* refactor(auth): removing redundant import

* refactor(auth): rename the theme

* refactor(auth): convert to StatefulWidget and add TextButton

* refactor(auth): convert to appTheme

* refactor(auth): add extra dimension

* refactor(auth): remove redundant condition

* refactor(auth): remove redundant code and convert to StatefulWidget

* FEAT(AUTH-CROSS): Initiate the basic structure of the model and view-model (#3)

* fix: correct app name to telware

* feat(login-flow): create an enum for the different states of authentication

* feat(auth): create a token provider

* feat: initialize custom_lints

* feat(auth): create the local repository for authentication

* feat(auth): create the authentication view model

* feat(auth): initialize the authentication process in the TelWare widget

* doc(auth): add a todo to create the user provider

* feat(auth): open Hive box for auth tokens

* feat(auth): create the splash screen

---------

Co-authored-by: Marwan Alhameedy <[email protected]>

* refactor(auth): simplify the sign-up screen code (#4)

* FEAT(AUTH-CROSS): Build the UI for the Log In screen (#5)

* refactor(auth): simplify the sign-up screen code

* chor(auth-cross): add the social media login icons

* feat: add new routes

* feat(auth-cross): build login screen ui

* refactor(auth-cross): move the social login widget to a separate file

* feat(auth-cross): add forget password button to login screen

* feat(auth-cross): make a widget for the auth floating action button

---------

Co-authored-by: Marwan Alhameedy <[email protected]>

* FEATURE(AUTH-CROSS): Implement sign up logic (#7)

* feat(auth): add userModel

* feat(auth): create user provider

* refactor(auth): remove redundant import

* feat(auth): create app error class

* feat(auth): add user model to local repository

* feat(auth): create remote repository

* feat(auth): add signUp logic to auth-view-model

* fix(auth): add null check

* feat(auth): create dio base options

* feat(auth): update signUp logic and convert to ConsumerStatefulWidget

* refactor(auth): remove dummy files

* refactor(auth): remove todo comments

* feat(auth): open user model hive box

* fix(auth): correct the image path

* fix(auth): register the user model to hive

* fix(auth): remove password field

* fix(auth): syntax error

* FEAT(AUTH-CROSS): Verification-UI (#8)

* feat(auth): add action to on press function

* refactor(auth): make the code more modular

* chore(auth): add package for code verification

* refactor(auth): modify names and input parameters for better usage.

* feat(auth): add verification length

* feat(auth): add verification screen ui

* feat(auth): add confirmation dialog

* refactor(auth): remove redundant code

* refactor(auth): remove verification from login logic

* chore(auth): add phone_form_field package

* style(auth): enhancing the parameters for better usage

* feat(auth): add phone field widget

* refactor(auth): modify the input values

* refactor(auth): improve ui styles

* FEATURE(AUTH):  Implement log in logic (#9)

* feat(auth-cross): use the initial route property

* fix(auth): remove unnecessary import

* ref: add todo's to marwan

* feat(auth): implement the log in functionality

* feat(auth): implement log in and forgot password logic

* feat(auth): update auth state to a class

* feat(auth): add show toast and snack bar utils

* feat(auth): add delete token or user functionalities to the authentication local repository

* fix(auth): fix used status code in the log in logic

* feat(auth): add the success state to the AuthStateType

* feat(auth): connect the ui with the logic for the log in feature

* feat(auth): add the log out functionality

* fix(auth): handle different states for the forgot password method

* fix(auth): recompile generated files

---------

Co-authored-by: marwan2232004 <[email protected]>

* feat(auth): add testing keys to the log in (#10)

specify the type of the keys

* feat(auth): handle log in without being verified scenario (#11)

* FEAT: Change the app icon and Splash screen icon (#12)

* feat: create app icon

* feat: update the splash screen with the logo and app name

* fix: correctly check success status codes

* feat: update user model to match api documentation

* fix: user correct key names in initialization

* feat: change get user method name to get me

* FIX: correctly validate passowrds and send email to verificatoin screen

feat(auth): add password validator

feat: add password validator and send the email to the verification screen

* feat(user): add profile info submission and validation

* feat(user): add profile info submission and validation

* feat(user): add profile info submission and validation

* feat(user): add profile header with animation

* feat(user): add profile info submission and validation

* feat(user): add profile info submission and validation

* refact: Refactor main.dart and core files

* feat(user): add change number option for the user

* feat(auth): blocked users screen

* refactor(auth): generalize the widgets

* refactor(auth): generalize the widgets

* feat(auth): blocked users section

* style(user-profile): reformat code

* refactor(user-profile): add new color

* refactor(user-profile): optimize code

* chore(user-profile): add lottie package

* refactor(user-profile): add height to trailing

* feat(user-profile): block user screen #turn  1

* feat(user-profile): easter duck tgs

* feat(user-profile): modify settings widget

* chore(user-profile): add dependencies

* refactor(user-profile): optimize code.

* feat(user-profile): add block users colors.

* feat(user-profile): enhance ```formatPhoneNumber```, add getRandomColor.

* feat(user-profile): add contacts hive box

* feat(user-profile): put permission for reading contacts.

* feat(user-profile): add contact model.

* feat(user-profile): read and store contacts in hive.

* feat(user-profile): add displaying image from memory or an avatar

* feat(user-profile): empty chat screen widget

* feat(user-profile): avatar generator from name initials

* feat(user-profile): reading contacts from hive, adding tabBar

* feat(user-profile): block user confirmation dialog.

* feat(user-profile): block user navigations.

* feat(block-users): solve testing problem.

* feat(block-users): solve testing problem.

---------

Co-authored-by: Ahmed Aladdin Mohamed <[email protected]>
Co-authored-by: Ahmed Aladdin <[email protected]>
Co-authored-by: Mo2Hefny <[email protected]>
  • Loading branch information
4 people authored Oct 29, 2024
1 parent 8ce3b38 commit 7aaf3ae
Show file tree
Hide file tree
Showing 19 changed files with 799 additions and 220 deletions.
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Expand Down
44 changes: 44 additions & 0 deletions lib/core/contact_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/cupertino.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:fast_contacts/fast_contacts.dart';
import 'package:hive/hive.dart';
import 'package:telware_cross_platform/core/models/contact_model.dart';
import 'package:telware_cross_platform/core/utils.dart';

class ContactService {
Future<void> fetchAndStoreContacts() async {
bool isPermissionGranted = await Permission.contacts.isGranted;
if (!isPermissionGranted) {
await Permission.contacts.request();
}
if (await Permission.contacts.isGranted) {
final contacts = await FastContacts.getAllContacts();

// for (var contact in contacts) {
// contact.toMap().forEach((key, value) {
// debugPrint('$key: $value');
// });
// }

var box = await Hive.openBox<ContactModelBlock>("contacts-block");
await box.clear();
// Store contacts in Hive
for (var contact in contacts) {
if (contact.phones.isEmpty || contact.displayName.isEmpty) continue;
final thumbnail = await FastContacts.getContactImage(contact.id);
final email =
contact.emails.isNotEmpty ? contact.emails[0].toString() : "";
final phone = formatPhoneNumber(contact.phones[0].number);
box.put(
contact.id,
ContactModelBlock(
name: contact.displayName,
email: email,
phone: phone,
photo: thumbnail,
lastSeen: ""),
);
}
}
}
}
91 changes: 91 additions & 0 deletions lib/core/models/contact_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:typed_data';

import 'package:hive/hive.dart';

part 'contact_model.g.dart';

@HiveType(typeId: 3)
class ContactModelBlock {
@HiveField(0)
final String name;
@HiveField(1)
final String? email;
@HiveField(2)
final Uint8List? photo;
@HiveField(3)
final String phone;
@HiveField(4)
final String lastSeen;

//<editor-fold desc="Data Methods">
const ContactModelBlock({
required this.name,
this.email,
this.photo,
required this.phone,
required this.lastSeen,
});

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is ContactModelBlock &&
runtimeType == other.runtimeType &&
name == other.name &&
email == other.email &&
photo == other.photo &&
phone == other.phone &&
lastSeen == other.lastSeen);

@override
int get hashCode =>
name.hashCode ^
email.hashCode ^
photo.hashCode ^
phone.hashCode ^
lastSeen.hashCode;

@override
String toString() {
return 'ContactModelBlock{ name: $name, email: $email, photo: $photo, phone: $phone, lastSeen: $lastSeen,}';
}

ContactModelBlock copyWith({
String? name,
String? email,
Uint8List? photo,
String? phone,
String? lastSeen,
}) {
return ContactModelBlock(
name: name ?? this.name,
email: email ?? this.email,
photo: photo ?? this.photo,
phone: phone ?? this.phone,
lastSeen: lastSeen ?? this.lastSeen,
);
}

Map<String, dynamic> toMap() {
return {
'name': name,
'email': email,
'photo': photo,
'phone': phone,
'lastSeen': lastSeen,
};
}

factory ContactModelBlock.fromMap(Map<String, dynamic> map) {
return ContactModelBlock(
name: map['name'] as String,
email: map['email'] as String,
photo: map['photo'] as Uint8List,
phone: map['phone'] as String,
lastSeen: map['lastSeen'] as String,
);
}

//</editor-fold>
}
53 changes: 53 additions & 0 deletions lib/core/models/contact_model.g.dart

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

2 changes: 2 additions & 0 deletions lib/core/theme/palette.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class Palette {
static const Color secondary = Color.fromRGBO(29, 39, 51, 1);
static const Color trinary = Color.fromRGBO(33, 45, 59, 1.0);
static const Color quaternary = Color.fromRGBO(41, 56, 73, 1);
static const Color tabBar = Color.fromRGBO(36, 45, 57, 1.0);
static const Color scrollBar = Color.fromRGBO(61, 74, 89, 1.0);
static const Color accent = Color.fromRGBO(110, 178, 239, 1);
static const Color primaryText = Color.fromRGBO(255, 255, 255, 1);
static const Color accentText = Color.fromRGBO(125, 139, 153, 1);
Expand Down
2 changes: 1 addition & 1 deletion lib/core/theme/sizes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ class Sizes {
static const double infoText = 12;
static const double iconSize = 22;
static const double circleButtonRadius = 16;
}
}
22 changes: 19 additions & 3 deletions lib/core/utils.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// common utility functions are added here

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';

Expand Down Expand Up @@ -67,15 +67,31 @@ void showToastMessage(String message) async {
}

String formatPhoneNumber(String phoneNumber) {
// Ensure the input has the right length and starts with the correct prefix.
if (phoneNumber.length == 13 && phoneNumber.startsWith("+20")) {
// remove all spaces
phoneNumber = phoneNumber.replaceAll(" ", "");

if (!phoneNumber.startsWith("+20")) {
phoneNumber = "+20${phoneNumber.substring(1)}";
}
if (phoneNumber.length == 13) {
return "${phoneNumber.substring(0, 3)} " // +20
"${phoneNumber.substring(3, 6)} " // 109
"${phoneNumber.substring(6)}"; // 3401932
}
return phoneNumber; // Return the original if it doesn't match the format.
}

// Helper function to generate random pastel-like colors
Color getRandomColor() {
final Random random = Random();
return Color.fromARGB(
255,
50 + random.nextInt(100), // Red (200-255)
50 + random.nextInt(100), // Green (200-255)
50 + random.nextInt(100), // Blue (200-255)
);
}

String toKebabCase(String input) {
// Convert to lowercase and replace spaces with hyphens
String kebabCased = input.toLowerCase().replaceAll(RegExp(r'[\s]+'), '-');
Expand Down
5 changes: 3 additions & 2 deletions lib/features/auth/view/screens/sign_up_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,9 @@ class _SignUpScreenState extends ConsumerState<SignUpScreen> {
if (someNotFilled) {
vibrate();
} else {
showConfirmationDialog(
context, emailController, _controllerPlus, signUp, onEdit);
// todo show the dialog (marwan)
// showConfirmationDialog(
// context, emailController, _controllerPlus, signUp, onEdit);
}
}

Expand Down
4 changes: 3 additions & 1 deletion lib/features/auth/view/widget/auth_sub_text_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ class AuthSubTextButton extends StatelessWidget {
this.padding = const EdgeInsets.all(0),
this.fontSize = Sizes.infoText,
this.buttonKey,
this.color,
});

final VoidCallback onPressed;
final GlobalKey<State>? buttonKey;
final String label;
final EdgeInsetsGeometry padding;
final double fontSize;
final Color? color;

@override
Widget build(BuildContext context) {
Expand All @@ -31,7 +33,7 @@ class AuthSubTextButton extends StatelessWidget {
),
child: TitleElement(
name: label,
color: Palette.accent,
color: color ?? Palette.accent,
fontSize: fontSize,
fontWeight: FontWeight.bold,
padding: padding,
Expand Down
Loading

0 comments on commit 7aaf3ae

Please sign in to comment.