elCaribe app - customization and branding

This commit is contained in:
2025-12-12 19:09:42 -04:00
parent 9e5d0d8ebf
commit ba7deac9f3
402 changed files with 31833 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
import 'package:hive/hive.dart';
import 'package:news/utils/constant.dart';
import 'package:news/utils/hiveBoxKeys.dart';
//AuthLocalDataSource will communicate with local database (hive)
class AuthLocalDataSource {
bool? checkIsAuth() {
return Hive.box(authBoxKey).get(isLogInKey, defaultValue: false) ?? false;
}
String? getId() {
return Hive.box(authBoxKey).get(userIdKey, defaultValue: "0");
}
Future<void> setId(String? id) async {
Hive.box(authBoxKey).put(userIdKey, id);
}
String? getName() {
return Hive.box(authBoxKey).get(userNameKey, defaultValue: "");
}
Future<void> setName(String? name) async {
Hive.box(authBoxKey).put(userNameKey, name);
}
String? getEmail() {
return Hive.box(authBoxKey).get(userEmailKey, defaultValue: "");
}
Future<void> setEmail(String? email) async {
Hive.box(authBoxKey).put(userEmailKey, email);
}
String? getMobile() {
return Hive.box(authBoxKey).get(userMobKey, defaultValue: "");
}
Future<void> setMobile(String? mobile) async {
Hive.box(authBoxKey).put(userMobKey, mobile);
}
String? getType() {
return Hive.box(authBoxKey).get(userTypeKey, defaultValue: "");
}
Future<void> setType(String? type) async {
Hive.box(authBoxKey).put(userTypeKey, type);
}
String? getProfile() {
return Hive.box(authBoxKey).get(userProfileKey, defaultValue: "");
}
Future<void> setProfile(String? image) async {
Hive.box(authBoxKey).put(userProfileKey, image);
}
String? getStatus() {
return Hive.box(authBoxKey).get(userStatusKey, defaultValue: "");
}
Future<void> setStatus(String? status) async {
Hive.box(authBoxKey).put(userStatusKey, status);
}
String getJWTtoken() {
return Hive.box(authBoxKey).get(jwtTokenKey, defaultValue: "");
}
Future<void> setJWTtoken(String? jwtToken) async {
Hive.box(authBoxKey).put(jwtTokenKey, jwtToken);
}
Future<void> changeAuthStatus(bool? authStatus) async {
Hive.box(authBoxKey).put(isLogInKey, authStatus);
}
String? getAuthorWhatsappLink() {
return Hive.box(authBoxKey).get(authorWhatsappLinkKey, defaultValue: "");
}
String? getAuthorFacebookLink() {
return Hive.box(authBoxKey).get(authorfacebookLinkKey, defaultValue: "");
}
String? getAuthorTelegramLink() {
return Hive.box(authBoxKey).get(authorTelegramLinkKey, defaultValue: "");
}
String? getAuthorLinkedInLink() {
return Hive.box(authBoxKey).get(authorLinkedInLinkKey, defaultValue: "");
}
Future<void> setSocialMediaLinks(String? whatsappLink, facebookLink, telegramLink, linkedInLink) async {
Hive.box(authBoxKey).put(authorWhatsappLinkKey, whatsappLink);
Hive.box(authBoxKey).put(authorfacebookLinkKey, facebookLink);
Hive.box(authBoxKey).put(authorTelegramLinkKey, telegramLink);
Hive.box(authBoxKey).put(authorLinkedInLinkKey, linkedInLink);
}
String getAuthorBio() {
return Hive.box(authBoxKey).get(authorBioKey, defaultValue: "");
}
Future<void> setAuthorBio(String? authorBio) async {
Hive.box(authBoxKey).put(authorBioKey, authorBio);
}
AuthorStatus getAuthorStatus() {
final value = Hive.box(authBoxKey).get(authorStatusKey, defaultValue: AuthorStatus.rejected.name);
return AuthorStatus.values.byName(value);
}
Future<void> setAuthorStatus(AuthorStatus authorStatus) async {
Hive.box(authBoxKey).put(authorStatusKey, authorStatus.name);
}
}

View File

@@ -0,0 +1,299 @@
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_login_facebook/flutter_login_facebook.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:news/cubits/appLocalizationCubit.dart';
import 'package:news/data/repositories/Settings/settingsLocalDataRepository.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:news/cubits/Auth/authCubit.dart';
import 'package:news/ui/widgets/SnackBarWidget.dart';
import 'package:news/utils/uiUtils.dart';
import 'package:news/utils/api.dart';
import 'package:news/utils/strings.dart';
class AuthRemoteDataSource {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn(scopes: ["profile", "email"]);
final _facebookSignin = FacebookLogin();
Future<dynamic> loginAuth({
required String firebaseId,
required String name,
required String email,
required String type,
required String profile,
required String mobile,
}) async {
try {
final Map<String, String> body = {FIREBASE_ID: firebaseId, NAME: name, TYPE: type, EMAIL: email};
if (profile != "") body[PROFILE] = profile;
if (mobile != "") body[MOBILE] = mobile;
var result = await Api.sendApiRequest(body: body, url: Api.getUserSignUpApi);
return result;
} catch (e) {
throw ApiMessageAndCodeException(errorMessage: e.toString());
}
}
Future<dynamic> deleteUserAcc() async {
try {
final result = await Api.sendApiRequest(body: {}, url: Api.userDeleteApi);
return result;
} catch (e) {
throw ApiMessageAndCodeException(errorMessage: e.toString());
}
}
//to update fcmId of user's
Future<dynamic> updateUserData(
{String? name, String? mobile, String? email, String? filePath, String? authorBio, String? whatsappLink, String? facebookLink, String? telegramLink, String? linkedInLink}) async {
try {
Map<String, dynamic> body = {};
Map<String, dynamic> result = {};
if (name != null) body[NAME] = name;
if (mobile != null) body[MOBILE] = mobile;
if (email != null) body[EMAIL] = email;
if (filePath != null && filePath.isNotEmpty) body[PROFILE] = await MultipartFile.fromFile(filePath);
if (authorBio != null) body[AUTHOR_BIO] = authorBio;
if (whatsappLink != null) body[AUTHOR_WHATSAPP_LINK] = whatsappLink;
if (telegramLink != null) body[AUTHOR_TELEGRAM_LINK] = telegramLink;
if (facebookLink != null) body[AUTHOR_FACEBOOK_LINK] = facebookLink;
if (linkedInLink != null) body[AUTHOR_LINKEDIN_LINK] = linkedInLink;
result = await Api.sendApiRequest(body: body, url: Api.setUpdateProfileApi);
return result;
} catch (e) {
throw ApiMessageAndCodeException(errorMessage: e.toString());
}
}
Future<dynamic> registerToken({required String fcmId, required BuildContext context}) async {
try {
final body = {TOKEN: fcmId, LANGUAGE_ID: context.read<AppLocalizationCubit>().state.id}; //Pass languageId for specific language Notifications
String latitude = SettingsLocalDataRepository().getLocationCityValues().first;
String longitude = SettingsLocalDataRepository().getLocationCityValues().last;
if (latitude != '' && latitude != "null") body[LATITUDE] = latitude;
if (longitude != '' && longitude != "null") body[LONGITUDE] = longitude;
final result = await Api.sendApiRequest(body: body, url: Api.setRegisterToken);
return result;
} on SocketException catch (e) {
throw SocketException(e.toString());
} catch (e) {
throw ApiMessageAndCodeException(errorMessage: e.toString());
}
}
Future<Map<String, dynamic>> socialSignInUser({required AuthProviders authProvider, required BuildContext context, String? email, String? password, String? otp, String? verifiedId}) async {
Map<String, dynamic> result = {};
try {
switch (authProvider) {
case AuthProviders.gmail:
UserCredential? userCredential = await signInWithGoogle(context);
if (userCredential != null) {
result['user'] = userCredential.user!;
return result;
} else {
throw ApiMessageAndCodeException(errorMessage: UiUtils.getTranslatedLabel(context, 'somethingMSg'));
}
case AuthProviders.mobile:
UserCredential? userCredential = await signInWithPhone(context: context, otp: otp!, verifiedId: verifiedId!);
if (userCredential != null) {
result['user'] = userCredential.user!;
return result;
} else {
throw ApiMessageAndCodeException(errorMessage: UiUtils.getTranslatedLabel(context, 'somethingMSg'));
}
case AuthProviders.fb:
final faceBookAuthResult = await signInWithFacebook();
if (faceBookAuthResult != null) {
result['user'] = faceBookAuthResult.user!;
return result;
} else {
throw ApiMessageAndCodeException(errorMessage: UiUtils.getTranslatedLabel(context, 'somethingMSg'));
}
case AuthProviders.apple:
UserCredential? userCredential = await signInWithApple(context);
if (userCredential != null) {
result['user'] = userCredential.user!;
return result;
} else {
throw ApiMessageAndCodeException(errorMessage: UiUtils.getTranslatedLabel(context, 'somethingMSg'));
}
case AuthProviders.email:
final userCredential = await signInWithEmailPassword(email: email!, password: password!, context: context);
if (userCredential != null) {
result['user'] = userCredential.user!;
return result;
} else {
return {};
}
}
} on SocketException catch (_) {
throw ApiMessageAndCodeException(errorMessage: UiUtils.getTranslatedLabel(context, 'internetmsg'));
} on FirebaseAuthException catch (e) {
throw ApiMessageAndCodeException(errorMessage: e.toString());
} catch (e) {
throw ApiMessageAndCodeException(errorMessage: e.toString());
}
}
Future<UserCredential?> signInWithPhone({required BuildContext context, required String otp, required String verifiedId}) async {
String code = otp.trim();
if (code.length == 6) {
//As OTP is of Fixed length 6
try {
final PhoneAuthCredential credential = PhoneAuthProvider.credential(verificationId: verifiedId, smsCode: otp);
final UserCredential authResult = await _firebaseAuth.signInWithCredential(credential);
final User? user = authResult.user;
if (user != null) {
assert(!user.isAnonymous);
final User? currentUser = _firebaseAuth.currentUser;
assert(user.uid == currentUser?.uid);
showSnackBar(UiUtils.getTranslatedLabel(context, 'otpMsg'), context);
return authResult;
} else {
showSnackBar(UiUtils.getTranslatedLabel(context, 'otpError'), context);
return null;
}
} on FirebaseAuthException catch (authError) {
if (authError.code == 'invalidVerificationCode') {
showSnackBar(UiUtils.getTranslatedLabel(context, 'invalidVerificationCode'), context);
return null;
} else {
showSnackBar(authError.message.toString(), context);
return null;
}
} on FirebaseException catch (e) {
showSnackBar(e.message.toString(), context);
return null;
} catch (e) {
showSnackBar(e.toString(), context);
return null;
}
} else {
showSnackBar(UiUtils.getTranslatedLabel(context, 'enterOtpTxt'), context);
return null;
}
}
//sign in with email and password in firebase
Future<UserCredential?> signInWithEmailPassword({required String email, required String password, required BuildContext context}) async {
try {
final UserCredential userCredential = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
return userCredential;
} on FirebaseAuthException catch (authError) {
if (authError.code == 'userNotFound') {
showSnackBar(UiUtils.getTranslatedLabel(context, 'userNotFound'), context);
} else if (authError.code == 'wrongPassword') {
showSnackBar(UiUtils.getTranslatedLabel(context, 'wrongPassword'), context);
} else {
throw ApiMessageAndCodeException(errorMessage: authError.message!);
}
} on FirebaseException catch (e) {
showSnackBar(e.toString(), context);
} catch (e) {
String errorMessage = e.toString();
showSnackBar(errorMessage, context);
}
return null;
}
//signIn using google account
Future<UserCredential?> signInWithGoogle(BuildContext context) async {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
ApiMessageAndCodeException(errorMessage: UiUtils.getTranslatedLabel(context, 'somethingMSg'));
return null;
}
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(accessToken: googleAuth.accessToken, idToken: googleAuth.idToken);
final UserCredential userCredential = await _firebaseAuth.signInWithCredential(credential);
return userCredential;
}
Future<UserCredential?> signInWithFacebook() async {
final res = await _facebookSignin.logIn(permissions: [FacebookPermission.publicProfile, FacebookPermission.email]);
// Check result status
switch (res.status) {
case FacebookLoginStatus.success:
// Send access token to server for validation and auth
final FacebookAccessToken? accessToken = res.accessToken;
AuthCredential authCredential = FacebookAuthProvider.credential(accessToken!.token);
final UserCredential userCredential = await _firebaseAuth.signInWithCredential(authCredential);
return userCredential;
case FacebookLoginStatus.cancel:
return null;
case FacebookLoginStatus.error:
return null;
}
}
String sha256ofString(String input) {
final bytes = utf8.encode(input);
final digest = sha256.convert(bytes);
return digest.toString();
}
Future<UserCredential?> signInWithApple(BuildContext context) async {
try {
final rawNonce = generateNonce();
final nonce = sha256ofString(rawNonce);
final appleCredential = await SignInWithApple.getAppleIDCredential(scopes: [AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName], nonce: nonce);
final oauthCredential = OAuthProvider("apple.com").credential(idToken: appleCredential.identityToken, rawNonce: rawNonce, accessToken: appleCredential.authorizationCode);
final UserCredential authResult = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
return authResult;
} on FirebaseAuthException catch (authError) {
showSnackBar(authError.message!, context);
return null;
} on FirebaseException catch (e) {
showSnackBar(e.toString(), context);
return null;
} catch (e) {
String errorMessage = e.toString();
if (errorMessage == "Null check operator used on a null value") {
//if user goes back from selecting Account
//in case of User gmail not selected & back to Login screen
showSnackBar(UiUtils.getTranslatedLabel(context, 'cancelLogin'), context);
return null;
} else {
showSnackBar(errorMessage, context);
return null;
}
}
}
Future<void> signOut(AuthProviders? authProvider) async {
_firebaseAuth.signOut();
if (authProvider == AuthProviders.gmail) {
_googleSignIn.signOut();
} else if (authProvider == AuthProviders.fb) {
_facebookSignin.logOut();
} else {
_firebaseAuth.signOut();
}
}
}

View File

@@ -0,0 +1,171 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:news/data/models/authorModel.dart';
import 'package:news/utils/api.dart';
import 'package:news/utils/constant.dart';
import 'package:news/utils/hiveBoxKeys.dart';
import 'package:news/utils/uiUtils.dart';
import 'package:news/cubits/Auth/authCubit.dart';
import 'package:news/utils/strings.dart';
import 'package:news/data/repositories/Auth/authLocalDataSource.dart';
import 'package:news/data/repositories/Auth/authRemoteDataSource.dart';
class AuthRepository {
static final AuthRepository _authRepository = AuthRepository._internal();
late AuthLocalDataSource _authLocalDataSource;
late AuthRemoteDataSource _authRemoteDataSource;
factory AuthRepository() {
_authRepository._authLocalDataSource = AuthLocalDataSource();
_authRepository._authRemoteDataSource = AuthRemoteDataSource();
return _authRepository;
}
AuthRepository._internal();
AuthLocalDataSource get authLocalDataSource => _authLocalDataSource;
//to get auth detials stored in hive box
getLocalAuthDetails() {
return {
"isLogIn": _authLocalDataSource.checkIsAuth(),
ID: _authLocalDataSource.getId(),
NAME: _authLocalDataSource.getName(),
EMAIL: _authLocalDataSource.getEmail(),
MOBILE: _authLocalDataSource.getMobile(),
TYPE: _authLocalDataSource.getType(),
PROFILE: _authLocalDataSource.getProfile(),
STATUS: _authLocalDataSource.getStatus(),
TOKEN: _authLocalDataSource.getJWTtoken(),
AUTHOR_BIO: _authLocalDataSource.getAuthorBio(),
AUTHOR_STATUS: _authLocalDataSource.getAuthorStatus().name,
AUTHOR_WHATSAPP_LINK: _authLocalDataSource.getAuthorWhatsappLink(),
AUTHOR_FACEBOOK_LINK: _authLocalDataSource.getAuthorFacebookLink(),
AUTHOR_TELEGRAM_LINK: _authLocalDataSource.getAuthorTelegramLink(),
AUTHOR_LINKEDIN_LINK: _authLocalDataSource.getAuthorLinkedInLink()
};
}
setLocalAuthDetails(
{required bool authStatus,
required String id,
required String name,
required String email,
required String mobile,
required String type,
required String profile,
required String status,
required String role,
required String jwtToken,
required int isAuthor,
Author? authorDetails}) {
_authLocalDataSource.changeAuthStatus(authStatus);
_authLocalDataSource.setId(id);
_authLocalDataSource.setName(name);
_authLocalDataSource.setEmail(email);
_authLocalDataSource.setMobile(mobile);
_authLocalDataSource.setType(type);
_authLocalDataSource.setProfile(profile);
_authLocalDataSource.setStatus(status);
_authLocalDataSource.setJWTtoken(jwtToken);
_authLocalDataSource.setAuthorStatus((authorDetails != null) ? authorDetails.status! : AuthorStatus.rejected);
_authLocalDataSource.setAuthorBio((authorDetails != null) ? authorDetails.bio : "");
_authLocalDataSource.setSocialMediaLinks((authorDetails != null) ? authorDetails.whatsappLink : "", (authorDetails != null) ? authorDetails.facebookLink : "",
(authorDetails != null) ? authorDetails.telegramLink : "", (authorDetails != null) ? authorDetails.linkedinLink : "");
}
//First we signin user with given provider then add user details
Future<Map<String, dynamic>> signInUser({required BuildContext context, required AuthProviders authProvider, String? email, String? password, String? otp, String? verifiedId}) async {
try {
final result = await _authRemoteDataSource.socialSignInUser(context: context, authProvider: authProvider, email: email, password: password, verifiedId: verifiedId, otp: otp);
final user = result['user'] as User;
var providerData = user.providerData[0];
if (authProvider == AuthProviders.email && !user.emailVerified) {
throw ApiException(UiUtils.getTranslatedLabel(context, 'verifyEmailMsg'));
}
Map<String, dynamic> userDataTest = await _authRemoteDataSource.loginAuth(
mobile: providerData.phoneNumber ?? "",
email: providerData.email ?? "",
firebaseId: user.uid,
name: providerData.displayName ?? "",
profile: providerData.photoURL ?? "",
type: authProvider.name);
if (!userDataTest[ERROR]) {
if (userDataTest[DATA][STATUS].toString() != "0") {
setLocalAuthDetails(
type: userDataTest[DATA][TYPE] ?? "",
profile: userDataTest[DATA][PROFILE] ?? "",
name: userDataTest[DATA][NAME] ?? "",
email: userDataTest[DATA][EMAIL] ?? "",
authStatus: true,
id: (userDataTest[DATA][ID].toString() != "") ? userDataTest[DATA][ID].toString() : "0",
mobile: userDataTest[DATA][MOBILE] ?? "",
role: userDataTest[DATA][ROLE].toString(),
status: userDataTest[DATA][STATUS].toString(),
jwtToken: userDataTest[DATA][TOKEN] ?? "",
isAuthor: userDataTest[DATA][IS_AUTHOR] ?? 0,
authorDetails: (userDataTest[DATA][IS_AUTHOR] == 1 && userDataTest[DATA][AUTHOR] != null) ? Author.fromJson(userDataTest[DATA][AUTHOR]) : null);
}
return userDataTest;
} else {
signOut(authProvider);
throw ApiMessageAndCodeException(errorMessage: userDataTest[MESSAGE]);
}
} catch (e) {
signOut(authProvider);
throw ApiMessageAndCodeException(errorMessage: e.toString());
}
}
Future<dynamic> updateUserData(
{String? name, String? mobile, String? email, String? filePath, String? authorBio, String? whatsappLink, String? facebookLink, String? telegramLink, String? linkedInLink}) async {
final result = await _authRemoteDataSource.updateUserData(
email: email,
name: name,
mobile: mobile,
filePath: filePath,
authorBio: authorBio,
whatsappLink: whatsappLink,
facebookLink: facebookLink,
telegramLink: telegramLink,
linkedInLink: linkedInLink);
if (name != null) _authLocalDataSource.setName(name);
if (mobile != null) _authLocalDataSource.setMobile(mobile);
if (email != null) _authLocalDataSource.setEmail(email);
if (filePath != null && filePath.isNotEmpty) _authLocalDataSource.setProfile(result[PROFILE]);
if (authorBio != null) _authLocalDataSource.setAuthorBio(authorBio);
if (whatsappLink != null || facebookLink != null || telegramLink != null || linkedInLink != null) _authLocalDataSource.setSocialMediaLinks(whatsappLink, facebookLink, telegramLink, linkedInLink);
return result;
}
Future<Map<String, dynamic>> registerToken({required String fcmId, required BuildContext context}) async {
final result = await _authRemoteDataSource.registerToken(fcmId: fcmId, context: context);
return result;
}
//to delete my account
Future<dynamic> deleteUser() async {
final result = await _authRemoteDataSource.deleteUserAcc();
return result;
}
Future<void> signOut(AuthProviders authProvider) async {
_authRemoteDataSource.signOut(authProvider);
await _authLocalDataSource.changeAuthStatus(false);
await _authLocalDataSource.setId("0");
await _authLocalDataSource.setName("");
await _authLocalDataSource.setEmail("");
await _authLocalDataSource.setMobile("");
await _authLocalDataSource.setType("");
await _authLocalDataSource.setProfile("");
await _authLocalDataSource.setStatus("");
await _authLocalDataSource.setJWTtoken("");
await _authLocalDataSource.setAuthorBio("");
await _authLocalDataSource.setAuthorStatus(AuthorStatus.rejected);
await _authLocalDataSource.setSocialMediaLinks("", "", "", "");
await Hive.box(authBoxKey).clear();
}
}