import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:generp/Notifiers/loginNotifier.dart'; import 'package:provider/provider.dart'; import 'package:share_plus/share_plus.dart'; import 'package:super_tooltip/super_tooltip.dart'; import '../Utils/app_colors.dart'; import '../Utils/commonServices.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late ScrollController _scrollController; late SuperTooltipController tooltipcontroller; final List logos = [ 'assets/images/logo_1.png', 'assets/images/logo_2.png', 'assets/images/logo_3.png', 'assets/images/logo_4.png', 'assets/images/logo_5.png', 'assets/images/logo_6.png', 'assets/images/logo_7.png', ]; TextEditingController password = TextEditingController(); TextEditingController email = TextEditingController(); String platformname = ""; late FocusNode _emailFocusNode; late FocusNode _passwordFocusNode; bool _isTextFieldFocused = false; KeyboardVisibilityController _keyboardVisibilityController = KeyboardVisibilityController(); @override void initState() { super.initState(); Future.microtask(() { final prov = Provider.of(context, listen: false); if (Platform.isAndroid) { prov.initAndroidId(); } else if (Platform.isIOS) { prov.getDevId(); } }); tooltipcontroller = SuperTooltipController(); _scrollController = ScrollController(); _controller = AnimationController( vsync: this, duration: const Duration(seconds: 75), // Adjust speed of scroll )..addListener(() { _scrollController.jumpTo(_controller.value * 10000); if (_controller.value == 1.0) { _controller.repeat(); _scrollController.jumpTo(0); } }); _controller.repeat(); _emailFocusNode = FocusNode(); _passwordFocusNode = FocusNode(); if (!mounted) return; _emailFocusNode.addListener(() { setState(() { _isTextFieldFocused = _emailFocusNode.hasFocus || _passwordFocusNode.hasFocus; }); }); _passwordFocusNode.addListener(() { setState(() { _isTextFieldFocused = _emailFocusNode.hasFocus || _passwordFocusNode.hasFocus; }); }); _keyboardVisibilityController.onChange.listen((bool visible) { if (visible) { setState(() { _isTextFieldFocused = true; }); // print("Keyboard is visible${visibility}"); } else { setState(() { _isTextFieldFocused = false; }); // print("Keyboard is not visible${visibility}"); } }); } @override void dispose() { _controller.dispose(); _scrollController.dispose(); super.dispose(); } Future onBackPressed() async { return await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Are you sure?'), content: const Text('Do you want to exit the App'), actions: [ TextButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.white), overlayColor: MaterialStateProperty.all(Colors.white), ), onPressed: () => Navigator.of(context).pop(false), child: Text( "NO", style: TextStyle(fontWeight: FontWeight.w500), ), ), const SizedBox(height: 16), TextButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.white), overlayColor: MaterialStateProperty.all(Colors.white70), ), onPressed: () => SystemChannels.platform.invokeMethod( 'SystemNavigator.pop', ), child: Text( "YES", style: TextStyle(fontWeight: FontWeight.w500), ), ), ], elevation: 30.0, ), barrierDismissible: false, ) ?? false; } @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; double screenHeight = MediaQuery.of(context).size.height; return Consumer( builder: (context, loginProv, child) { return WillPopScope( onWillPop: onBackPressed, child: SafeArea( top: false, bottom: Platform.isIOS ? false : true, child: Scaffold( resizeToAvoidBottomInset: true, backgroundColor: AppColors.scaffold_bg_color, body: KeyboardVisibilityProvider( controller: _keyboardVisibilityController, child: Stack( alignment: Alignment.center, children: [ // Background scrolling logos ListView.builder( controller: _scrollController, itemBuilder: (context, index) { int logoIndex = index % logos.length; return Padding( padding: const EdgeInsets.all(3.0), child: CustomGridRow( logos: logos, logoIndex: logoIndex, ), ); }, ), AnimatedPositioned( bottom: 0, left: 0, right: 0, duration: Duration(milliseconds: 300), child: Container( clipBehavior: Clip.antiAlias, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment(-0.00, -1.00), end: Alignment(0, 1), colors: [ Colors.white.withOpacity(0.0), // Fully transparent at the very top Colors.white.withOpacity(0.3), // Light fade-in Colors.white.withOpacity(0.6), // Mid fade Colors.white, // Solid white for the rest ], stops: [0.0, 0.05, 0.1, 0.15], ), ), child: SingleChildScrollView( child: Stack( alignment: Alignment.center, children: [ Container( alignment: Alignment.center, padding: EdgeInsets.symmetric( horizontal: 15, vertical: 10, ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedContainer( duration: const Duration( milliseconds: 1200, ), curve: Curves.easeInOut, child: _isTextFieldFocused ? Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( flex: 1, child: SizedBox(width: 10), ), Expanded( flex: 2, child: Image.asset( "assets/images/gen_logo.png", ), ), const SizedBox(width: 10), Expanded( flex: 3, child: Image.asset( "assets/images/gen_logo_grad.png", ), ), Expanded( flex: 1, child: SizedBox(width: 10), ), ], ) : Column( children: [ Container( width: 180, height: 120, child: Image.asset( "assets/images/gen_logo.png", ), ), Image.asset( "assets/images/gen_logo_grad.png", width: 150, ), ], ), ), SizedBox(height: 10), Text( "Login to enter", style: TextStyle( fontSize: 14, fontFamily: "JakartaMedium", color: AppColors.app_blue, ), ), Container( padding: EdgeInsets.only( left: 10, bottom: 5, ), alignment: Alignment.topLeft, child: Text( "Email ID", style: TextStyle( color: AppColors.semi_black, fontFamily: "JakartaMedium", fontSize: 14, ), ), ), Container( height: 48, alignment: Alignment.center, decoration: BoxDecoration( color: AppColors.text_field_color, borderRadius: BorderRadius.circular(14), border: _emailFocusNode.hasFocus ? Border.all( color: AppColors.app_blue, width: 0.5, ) : null, ), // alignment: Alignment.center, margin: EdgeInsets.only( left: 5.0, right: 5.0, ), child: Padding( padding: const EdgeInsets.fromLTRB( 10.0, 0.0, 15, 0, ), child: TextField( controller: email, keyboardType: TextInputType.emailAddress, minLines: 1, focusNode: _emailFocusNode, style: TextStyle(fontSize: 14), onChanged: (value) { loginProv.updateEmail(email.text); }, onTapOutside: (event) { // Handle onTapOutside FocusScope.of(context).unfocus(); }, decoration: InputDecoration( isDense: true, hintStyle: TextStyle( fontWeight: FontWeight.w400, fontSize: 14, color: Color(0xFF818181), ), //contentPadding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0), enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, hintText: 'Enter Your ID', ), ), ), ), if (loginProv.emailError != null) ...[ Container( alignment: Alignment.topLeft, margin: EdgeInsets.only( top: 2.5, bottom: 2.5, left: 25, ), child: Text( loginProv.emailError, textAlign: TextAlign.start, style: TextStyle(color: Colors.red), ), ), ] else ...[ SizedBox(height: 10.0), ], Container( padding: EdgeInsets.only( left: 10, bottom: 5, ), alignment: Alignment.topLeft, child: Text( "Password", style: TextStyle( color: AppColors.semi_black, fontFamily: "JakartaMedium", fontSize: 14, ), ), ), Container( height: 48, alignment: Alignment.center, decoration: BoxDecoration( color: AppColors.text_field_color, borderRadius: BorderRadius.circular(14), border: _passwordFocusNode.hasFocus ? Border.all( color: AppColors.app_blue, width: 0.5, ) : null, ), // alignment: Alignment.center, margin: EdgeInsets.only( left: 5.0, right: 5.0, ), child: Padding( padding: const EdgeInsets.fromLTRB( 10.0, 0.0, 0, 0, ), child: TextField( controller: password, focusNode: _passwordFocusNode, obscureText: !loginProv.pwdVisible, keyboardType: TextInputType.visiblePassword, style: TextStyle(fontSize: 14), onChanged: (value) { loginProv.updatePassword( password.text, ); }, onEditingComplete: () {}, decoration: InputDecoration( contentPadding: EdgeInsets.fromLTRB( 0, 10, 0, 0, ), hintText: "Enter Password", suffixIcon: IconButton( iconSize: 30, icon: loginProv.pwdVisible ? SvgPicture.asset( width: 35, height: 35, "assets/svg/password_visible.svg", ) : SvgPicture.asset( width: 35, height: 35, "assets/svg/password_invisible.svg", ), onPressed: () { loginProv.visibility_ov(); }, ), hintStyle: TextStyle( fontSize: 14, color: Color(0xFF818181), fontWeight: FontWeight.w400, ), isDense: true, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, ), ), ), ), if (loginProv.passwordError != null) ...[ Container( alignment: Alignment.topLeft, margin: EdgeInsets.only( top: 2.5, bottom: 2.5, left: 25, ), child: Text( loginProv.passwordError, textAlign: TextAlign.start, style: TextStyle(color: Colors.red), ), ), ] else ...[ SizedBox(height: 25.0), ], Container( child: InkWell( onTap: loginProv.isLoading ? null : () { // LoginApiFunction(); loginProv.isLoading = true; loginProv.LoginApiFunction( context, email.text, password.text, ); var f = FocusScope.of( context, ); if (!f.hasPrimaryFocus) { f.unfocus(); } // Navigator.push(context,MaterialPageRoute(builder: (context)=>Profile())); }, child: Container( alignment: Alignment.center, height: 45, width: screenWidth, margin: EdgeInsets.only( left: 5.0, right: 5.0, ), decoration: BoxDecoration( color: loginProv.isButtonEnabled ? AppColors.app_blue : AppColors.button_disabled, //1487C9 borderRadius: BorderRadius.circular( 15.0, ), ), child: Center( child: loginProv.isLoading ? CircularProgressIndicator.adaptive( padding: EdgeInsets.all( 5, ), valueColor: AlwaysStoppedAnimation( Colors.white, ), ) : Text( "Login", textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontFamily: "JakartaRegular", ), ), ), ), ), ), ], ), ), ], ), ), ), ), Positioned( top: 50, right: 20, child: InkResponse( child: GestureDetector( onTap: () async { await tooltipcontroller.showTooltip(); }, child: SuperTooltip( controller: tooltipcontroller, popupDirection: TooltipDirection.down, backgroundColor: Colors.white, borderColor: Colors.white, showCloseButton: true, left: 50, right: 30, barrierColor: Colors.transparent, arrowTipDistance: 20.0, minimumOutsideMargin: 120, arrowBaseWidth: 20.0, arrowLength: 20.0, borderWidth: 2.0, constraints: const BoxConstraints( minHeight: 0.0, maxHeight: 100, minWidth: 0.0, maxWidth: 100, ), touchThroughAreaShape: ClipAreaShape.rectangle, touchThroughAreaCornerRadius: 30, content: Container( height: 100, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "Device ID", style: TextStyle( fontSize: 16, fontFamily: "JakartaMedium", color: AppColors.app_blue, ), ), SizedBox(height: 15), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Container( height: 50, padding: EdgeInsets.symmetric( horizontal: 10, vertical: 10, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular( 18, ), color: AppColors.text_field_color, ), child: Row( children: [ Container( width: 180, height: 45, alignment: Alignment.center, margin: EdgeInsets.only( right: 5.0, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10.0), ), child: Text( '${loginProv.deviceId}', style: TextStyle( fontSize: 16, color: AppColors.semi_black, ), ), ), Container( child: InkWell( onTap: () async { Clipboard.setData( ClipboardData( text: loginProv.deviceId .trim(), ), ); toast( context, "Device ID has been copied!", ); }, child: SvgPicture.asset( "assets/svg/copy_ic.svg", ), ), ), ], ), ), Spacer(), Container( width: 60, height: 50, decoration: BoxDecoration( color: AppColors.app_blue, borderRadius: BorderRadius.circular( 18, ), ), child: InkWell( onTap: () { // Share.share("${loginProv.deviceId}"); Share.share( "Your device ID is: ${loginProv.deviceId}", ); }, child: SvgPicture.asset( "assets/svg/share_ic.svg", height: 25, width: 25, fit: BoxFit.scaleDown, ), ), ), ], ), ], ), ), child: Align( alignment: Alignment.topRight, child: Container( width: 100, padding: EdgeInsets.symmetric( horizontal: 10, vertical: 5, ), decoration: BoxDecoration( color: AppColors.overlay_box_color, borderRadius: BorderRadius.circular(8), border: Border.all( color: AppColors.app_blue, width: 0.5, ), ), child: Center( child: Text( "Device ID", textAlign: TextAlign.center, style: TextStyle( color: AppColors.app_blue, fontSize: 14, ), ), ), ), ), ), ), ), ), ], ), ), // bottomNavigationBar: , ), ), ); }, ); } } class CustomGridRow extends StatelessWidget { final List logos; final int logoIndex; const CustomGridRow({ super.key, required this.logos, required this.logoIndex, }); @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ LogoWidget(imagePath: logos[logoIndex % logos.length]), LogoWidget(imagePath: logos[(logoIndex + 1) % logos.length]), LogoWidget(imagePath: logos[(logoIndex + 2) % logos.length]), LogoWidget(imagePath: logos[(logoIndex + 3) % logos.length]), ], ); } } class LogoWidget extends StatelessWidget { final String imagePath; const LogoWidget({super.key, required this.imagePath}); @override Widget build(BuildContext context) { return Container( width: MediaQuery.of(context).size.width / 4.5, height: MediaQuery.of(context).size.width / 4.5, padding: imagePath == "assets/images/logo_7.png"?EdgeInsets.symmetric(horizontal: 5):null, decoration: BoxDecoration( color: imagePath == "assets/images/logo_7.png"?Colors.white:Colors.transparent, borderRadius: BorderRadius.circular(25), image: DecorationImage( image: AssetImage(imagePath), fit: imagePath == "assets/images/logo_7.png" ? BoxFit.scaleDown : BoxFit.cover, ), ), ); } }