456 lines
18 KiB
Dart
456 lines
18 KiB
Dart
import 'dart:io';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:news/cubits/Auth/authCubit.dart';
|
|
import 'package:news/cubits/Auth/registerTokenCubit.dart';
|
|
import 'package:news/cubits/appLocalizationCubit.dart';
|
|
import 'package:news/cubits/appSystemSettingCubit.dart';
|
|
import 'package:news/cubits/privacyTermsCubit.dart';
|
|
import 'package:news/cubits/settingCubit.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/bottomComBtn.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/fieldFocusChange.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setConfimPass.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setDivider.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setEmail.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setForgotPass.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setLoginAndSignUpBtn.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setName.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setPassword.dart';
|
|
import 'package:news/ui/screens/auth/Widgets/setTermPolicy.dart';
|
|
import 'package:news/ui/styles/colors.dart';
|
|
import 'package:news/ui/widgets/SnackBarWidget.dart';
|
|
|
|
import 'package:news/ui/widgets/customTextBtn.dart';
|
|
import 'package:news/ui/widgets/customTextLabel.dart';
|
|
import 'package:news/utils/constant.dart';
|
|
import 'package:news/utils/internetConnectivity.dart';
|
|
import 'package:news/utils/uiUtils.dart';
|
|
import 'package:news/app/routes.dart';
|
|
import 'package:news/cubits/Auth/socialSignUpCubit.dart';
|
|
import 'package:news/utils/validators.dart';
|
|
|
|
class LoginScreen extends StatefulWidget {
|
|
final bool? isFromApp;
|
|
const LoginScreen({super.key, this.isFromApp});
|
|
|
|
@override
|
|
LoginScreenState createState() => LoginScreenState();
|
|
|
|
static Route route(RouteSettings routeSettings) {
|
|
if (routeSettings.arguments == null) {
|
|
return CupertinoPageRoute(builder: (_) => const LoginScreen());
|
|
} else {
|
|
final arguments = routeSettings.arguments as Map<String, dynamic>;
|
|
return CupertinoPageRoute(builder: (_) => LoginScreen(isFromApp: arguments['isFromApp'] ?? false));
|
|
}
|
|
}
|
|
}
|
|
|
|
class LoginScreenState extends State<LoginScreen> with TickerProviderStateMixin {
|
|
final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
|
|
TabController? _tabController;
|
|
FocusNode emailFocus = FocusNode();
|
|
FocusNode passFocus = FocusNode();
|
|
FocusNode nameFocus = FocusNode();
|
|
FocusNode emailSFocus = FocusNode();
|
|
FocusNode passSFocus = FocusNode();
|
|
FocusNode confPassFocus = FocusNode();
|
|
TextEditingController? emailC, passC, sEmailC, sPassC, sNameC, sConfPassC;
|
|
String? name, email, pass, mobile, profile, confPass;
|
|
bool isPolicyAvailable = false;
|
|
bool isObscure = true; //setPassword widget
|
|
|
|
@override
|
|
void initState() {
|
|
Future.delayed(Duration.zero, () {
|
|
context.read<PrivacyTermsCubit>().getPrivacyTerms(langId: context.read<AppLocalizationCubit>().state.id);
|
|
});
|
|
|
|
_tabController = TabController(length: 2, vsync: this, initialIndex: 0);
|
|
assignAllTextController();
|
|
_tabController!.addListener(() {
|
|
FocusScope.of(context).unfocus(); //dismiss keyboard
|
|
clearLoginTextFields();
|
|
clearSignUpTextFields();
|
|
});
|
|
super.initState();
|
|
}
|
|
|
|
assignAllTextController() {
|
|
emailC = TextEditingController();
|
|
passC = TextEditingController();
|
|
sEmailC = TextEditingController();
|
|
sPassC = TextEditingController();
|
|
sNameC = TextEditingController();
|
|
sConfPassC = TextEditingController();
|
|
}
|
|
|
|
clearSignUpTextFields() {
|
|
setState(() {
|
|
sNameC!.clear();
|
|
sEmailC!.clear();
|
|
sPassC!.clear();
|
|
sConfPassC!.clear();
|
|
});
|
|
}
|
|
|
|
clearLoginTextFields() {
|
|
setState(() {
|
|
emailC!.clear();
|
|
passC!.clear();
|
|
});
|
|
}
|
|
|
|
disposeAllTextController() {
|
|
emailC!.dispose();
|
|
passC!.dispose();
|
|
sEmailC!.dispose();
|
|
sPassC!.dispose();
|
|
sNameC!.dispose();
|
|
sConfPassC!.dispose();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tabController?.dispose();
|
|
disposeAllTextController();
|
|
|
|
super.dispose();
|
|
}
|
|
|
|
showContent() {
|
|
return BlocConsumer<SocialSignUpCubit, SocialSignUpState>(
|
|
bloc: context.read<SocialSignUpCubit>(),
|
|
listener: (context, state) async {
|
|
if (state is SocialSignUpFailure) {
|
|
showSnackBar(state.errorMessage, context);
|
|
}
|
|
if (state is SocialSignUpSuccess) {
|
|
context.read<AuthCubit>().checkAuthStatus();
|
|
if (state.authModel.status == "0") {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'deactiveMsg'), context);
|
|
} else {
|
|
FirebaseMessaging.instance.getToken().then((token) async {
|
|
if (token != null) {
|
|
context.read<RegisterTokenCubit>().registerToken(fcmId: token, context: context);
|
|
if (token != context.read<SettingsCubit>().getSettings().token) {
|
|
context.read<SettingsCubit>().changeFcmToken(token);
|
|
}
|
|
if (state.authModel.isFirstLogin != null && state.authModel.isFirstLogin!.isNotEmpty && state.authModel.isFirstLogin == "0" && state.authModel.type != loginApple) {
|
|
Navigator.of(context).pushNamedAndRemoveUntil(Routes.editUserProfile, (route) => false, arguments: {"from": "login"});
|
|
} else if (widget.isFromApp == true) {
|
|
Navigator.pop(context);
|
|
} else {
|
|
Navigator.pushNamedAndRemoveUntil(context, Routes.home, (route) => false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
return Form(
|
|
key: _formkey,
|
|
child: Stack(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsetsDirectional.only(top: 30.0, bottom: 5.0, start: 20.0, end: 20.0),
|
|
width: MediaQuery.of(context).size.width,
|
|
child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[skipBtn(), showTabs(), showTabBarView()]),
|
|
),
|
|
if (state is SocialSignUpProgress) UiUtils.showCircularProgress(true, Theme.of(context).primaryColor),
|
|
],
|
|
));
|
|
});
|
|
}
|
|
|
|
skipBtn() {
|
|
return Align(
|
|
alignment: AlignmentDirectional.topEnd,
|
|
child: CustomTextButton(
|
|
onTap: () {
|
|
Navigator.of(context).pushReplacementNamed(Routes.home, arguments: false);
|
|
},
|
|
text: UiUtils.getTranslatedLabel(context, 'skip'),
|
|
color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.7),
|
|
));
|
|
}
|
|
|
|
showTabs() {
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: DefaultTabController(
|
|
length: 2,
|
|
child: Container(
|
|
padding: const EdgeInsetsDirectional.only(start: 10.0),
|
|
child: TabBar(
|
|
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
|
controller: _tabController,
|
|
labelStyle: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600, letterSpacing: 0.5),
|
|
labelPadding: EdgeInsets.zero,
|
|
labelColor: backgroundColor,
|
|
unselectedLabelColor: UiUtils.getColorScheme(context).primaryContainer,
|
|
indicator: BoxDecoration(borderRadius: BorderRadius.circular(50), color: UiUtils.getColorScheme(context).secondaryContainer),
|
|
tabs: [Tab(text: UiUtils.getTranslatedLabel(context, 'signInTab')), Tab(text: UiUtils.getTranslatedLabel(context, 'signupBtn'))])),
|
|
));
|
|
}
|
|
|
|
bool validateAndSave() {
|
|
final form = _formkey.currentState;
|
|
form!.save();
|
|
|
|
if (!isPolicyAvailable) {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'addTCFirst'), context);
|
|
return false;
|
|
}
|
|
|
|
return form.validate();
|
|
}
|
|
|
|
Widget setPassword({required FocusNode currFocus, FocusNode? nextFocus, required TextEditingController passC, required String pass, required double topPad, required bool isLogin}) {
|
|
return Padding(
|
|
padding: EdgeInsets.only(top: topPad),
|
|
child: TextFormField(
|
|
focusNode: currFocus,
|
|
textInputAction: isLogin ? TextInputAction.done : TextInputAction.next,
|
|
controller: passC,
|
|
obscureText: isObscure,
|
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
color: UiUtils.getColorScheme(context).primaryContainer,
|
|
),
|
|
validator: (val) => Validators.passValidation(val!, context),
|
|
onFieldSubmitted: (v) {
|
|
if (!isLogin) {
|
|
fieldFocusChange(context, currFocus, nextFocus!);
|
|
}
|
|
},
|
|
onChanged: (String value) {
|
|
pass = value;
|
|
setState(() {});
|
|
},
|
|
decoration: InputDecoration(
|
|
hintText: UiUtils.getTranslatedLabel(context, 'passLbl'),
|
|
hintStyle: Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.5),
|
|
),
|
|
suffixIcon: Padding(
|
|
padding: const EdgeInsetsDirectional.only(end: 12.0),
|
|
child: IconButton(
|
|
icon: isObscure
|
|
? Icon(Icons.visibility_rounded, size: 20, color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.6))
|
|
: Icon(Icons.visibility_off_rounded, size: 20, color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.6)),
|
|
splashColor: Colors.transparent,
|
|
onPressed: () {
|
|
setState(() => isObscure = !isObscure);
|
|
},
|
|
)),
|
|
filled: true,
|
|
fillColor: Theme.of(context).colorScheme.surface,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 25, vertical: 17),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(color: UiUtils.getColorScheme(context).outline.withOpacity(0.7)),
|
|
borderRadius: BorderRadius.circular(10.0),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderSide: BorderSide.none,
|
|
borderRadius: BorderRadius.circular(10.0),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
showTabBarView() {
|
|
return Expanded(
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
height: MediaQuery.of(context).size.height * 1.0,
|
|
child: TabBarView(
|
|
controller: _tabController,
|
|
dragStartBehavior: DragStartBehavior.start,
|
|
children: [
|
|
//Login
|
|
SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
|
child: Column(children: [
|
|
loginTxt(),
|
|
SetEmail(currFocus: emailFocus, nextFocus: passFocus, emailC: emailC!, email: email ?? '', topPad: 20),
|
|
SetPassword(currFocus: passFocus, passC: passC!, pass: pass ?? '', topPad: 20, isLogin: true),
|
|
setForgotPass(context),
|
|
SetLoginAndSignUpBtn(
|
|
onTap: () async {
|
|
FocusScope.of(context).unfocus(); //dismiss keyboard
|
|
if (validateAndSave()) {
|
|
if (await InternetConnectivity.isNetworkAvailable()) {
|
|
context.read<SocialSignUpCubit>().socialSignUpUser(email: emailC!.text.trim(), password: passC!.text, authProvider: AuthProviders.email, context: context);
|
|
} else {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'internetmsg'), context);
|
|
}
|
|
}
|
|
},
|
|
text: 'loginTxt',
|
|
topPad: 20),
|
|
SetDividerOR(),
|
|
bottomBtn(),
|
|
BlocConsumer<PrivacyTermsCubit, PrivacyTermsState>(listener: (context, state) {
|
|
if (state is PrivacyTermsFetchSuccess) {
|
|
isPolicyAvailable = true;
|
|
}
|
|
if (state is PrivacyTermsFetchFailure) {
|
|
isPolicyAvailable = false;
|
|
}
|
|
}, builder: (context, state) {
|
|
return (state is PrivacyTermsFetchSuccess) ? setTermPolicyTxt(context, state) : const SizedBox.shrink();
|
|
})
|
|
]),
|
|
)),
|
|
//SignUp
|
|
SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
|
child: Column(
|
|
children: [
|
|
signUpTxt(),
|
|
SetName(currFocus: nameFocus, nextFocus: emailSFocus, nameC: sNameC!, name: sNameC!.text),
|
|
SetEmail(currFocus: emailSFocus, nextFocus: passSFocus, emailC: sEmailC!, email: sEmailC!.text, topPad: 20),
|
|
setPassword(currFocus: passSFocus, nextFocus: confPassFocus, passC: sPassC!, pass: sPassC!.text, topPad: 20, isLogin: false),
|
|
SetConfirmPass(currFocus: confPassFocus, confPassC: sConfPassC!, confPass: sConfPassC!.text, pass: sPassC!.text),
|
|
SetLoginAndSignUpBtn(
|
|
onTap: () async {
|
|
FocusScope.of(context).unfocus(); //dismiss keyboard
|
|
final form = _formkey.currentState;
|
|
if (form!.validate()) {
|
|
form.save();
|
|
if (await InternetConnectivity.isNetworkAvailable()) {
|
|
registerWithEmailPassword(sEmailC!.text.trim(), sPassC!.text.trim());
|
|
} else {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'internetmsg'), context);
|
|
}
|
|
}
|
|
},
|
|
text: 'signupBtn',
|
|
topPad: 25)
|
|
],
|
|
),
|
|
))
|
|
],
|
|
)),
|
|
);
|
|
}
|
|
|
|
registerWithEmailPassword(String email, String password) async {
|
|
try {
|
|
final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
|
|
User? user = credential.user;
|
|
user!.updateDisplayName(sNameC!.text.trim()).then((value) => debugPrint("updated name is - ${user.displayName}"));
|
|
user.reload();
|
|
|
|
user.sendEmailVerification().then((value) => showSnackBar('${UiUtils.getTranslatedLabel(context, 'verifSentMail')} $email', context));
|
|
clearSignUpTextFields();
|
|
_tabController!.animateTo(0);
|
|
FocusScope.of(context).requestFocus(emailFocus);
|
|
} on FirebaseAuthException catch (e) {
|
|
if (e.code == 'weakPassword') {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'weakPassword'), context);
|
|
}
|
|
if (e.code == 'email-already-in-use') {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'emailAlreadyInUse'), context);
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
loginTxt() {
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Padding(
|
|
padding: const EdgeInsetsDirectional.only(top: 20.0, start: 10.0),
|
|
child: CustomTextLabel(
|
|
text: 'loginDescr',
|
|
textStyle: Theme.of(context).textTheme.headlineSmall?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer, fontWeight: FontWeight.w800, letterSpacing: 0.5),
|
|
textAlign: TextAlign.left,
|
|
),
|
|
));
|
|
}
|
|
|
|
signUpTxt() {
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Padding(
|
|
padding: const EdgeInsetsDirectional.only(top: 35.0, start: 10.0),
|
|
child: CustomTextLabel(
|
|
text: 'signupDescr',
|
|
textStyle: Theme.of(context).textTheme.headlineSmall?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer, fontWeight: FontWeight.w800, letterSpacing: 0.5),
|
|
textAlign: TextAlign.left,
|
|
),
|
|
));
|
|
}
|
|
|
|
bottomBtn() {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(top: 20.0),
|
|
child: Column(
|
|
mainAxisAlignment: (fblogInEnabled) ? MainAxisAlignment.spaceBetween : MainAxisAlignment.spaceAround,
|
|
children: [
|
|
BottomCommButton(
|
|
btnCaption: 'google',
|
|
onTap: () {
|
|
if (!isPolicyAvailable) {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'addTCFirst'), context);
|
|
} else {
|
|
context.read<SocialSignUpCubit>().socialSignUpUser(authProvider: AuthProviders.gmail, context: context);
|
|
}
|
|
},
|
|
img: 'google_button'),
|
|
if (fblogInEnabled)
|
|
BottomCommButton(
|
|
onTap: () {
|
|
if (!isPolicyAvailable) {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'addTCFirst'), context);
|
|
} else {
|
|
context.read<SocialSignUpCubit>().socialSignUpUser(authProvider: AuthProviders.fb, context: context);
|
|
}
|
|
},
|
|
img: 'facebook_button',
|
|
btnCaption: 'fb'),
|
|
if (Platform.isIOS)
|
|
BottomCommButton(
|
|
onTap: () {
|
|
if (!isPolicyAvailable) {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'addTCFirst'), context);
|
|
} else {
|
|
context.read<SocialSignUpCubit>().socialSignUpUser(authProvider: AuthProviders.apple, context: context);
|
|
}
|
|
},
|
|
img: 'apple_logo',
|
|
btnCaption: 'apple',
|
|
btnColor: UiUtils.getColorScheme(context).primaryContainer),
|
|
if (context.read<AppConfigurationCubit>().getMobileLoginMode() != "" && context.read<AppConfigurationCubit>().getMobileLoginMode() != "0")
|
|
BottomCommButton(
|
|
onTap: () {
|
|
if (!isPolicyAvailable) {
|
|
showSnackBar(UiUtils.getTranslatedLabel(context, 'addTCFirst'), context);
|
|
} else {
|
|
Navigator.of(context).pushNamed(Routes.requestOtp);
|
|
}
|
|
},
|
|
img: 'phone_button',
|
|
btnCaption: 'mobileLbl',
|
|
btnColor: UiUtils.getColorScheme(context).primaryContainer)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: showContent(),
|
|
);
|
|
}
|
|
}
|