import ' dart:convert ' ;
import ' dart:io ' ;
import ' dart:typed_data ' ;
import ' package:easy_localization/easy_localization.dart ' ;
import ' package:flutter/cupertino.dart ' ;
import ' package:flutter/material.dart ' ;
import ' package:flutter_svg/flutter_svg.dart ' ;
import ' package:google_api_availability/google_api_availability.dart ' ;
import ' package:mohem_flutter_app/app_state/app_state.dart ' ;
import ' package:mohem_flutter_app/classes/colors.dart ' ;
import ' package:mohem_flutter_app/config/routes.dart ' ;
import ' package:mohem_flutter_app/exceptions/api_exception.dart ' ;
import ' package:mohem_flutter_app/extensions/int_extensions.dart ' ;
import ' package:mohem_flutter_app/extensions/string_extensions.dart ' ;
import ' package:mohem_flutter_app/extensions/widget_extensions.dart ' ;
import ' package:mohem_flutter_app/generated/locale_keys.g.dart ' ;
import ' package:mohem_flutter_app/provider/chat_provider_model.dart ' ;
import ' package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart ' ;
import ' package:mohem_flutter_app/widgets/loading_dialog.dart ' ;
import ' package:mohem_flutter_app/widgets/toast/app_toast.dart ' ;
import ' package:nfc_manager/nfc_manager.dart ' ;
import ' package:nfc_manager/platform_tags.dart ' ;
import ' package:shared_preferences/shared_preferences.dart ' ;
import ' package:mohem_flutter_app/ui/profile/mazaya_access_result_screen.dart ' ;
// ignore_for_file: avoid_annotating_with_dynamic
class Utils {
static bool _isLoadingVisible = false ;
static bool get isLoading = > _isLoadingVisible ;
// longDuration is accepted but no longer varies the duration - every caller already used the
// default (true), so AppToast.plainSeconds covers both cases with one fixed value.
static void showToast ( String message , { bool longDuration = true } ) {
AppToast . show ( message , seconds: AppToast . plainSeconds , showIcon: false , showCountdownText: false ) ;
}
static dynamic getNotNullValue ( List < dynamic > list , int index ) {
try {
return list [ index ] ;
} catch ( ex ) {
return null ;
}
}
static int stringToHex ( String colorCode ) {
try {
return int . parse ( colorCode . replaceAll ( " # " , " 0xff " ) ) ;
} catch ( ex ) {
return ( 0xff000000 ) ;
}
}
static Future delay ( int millis ) async {
return await Future . delayed ( Duration ( milliseconds: millis ) ) ;
}
static void showLoading ( BuildContext context ) {
WidgetsBinding . instance . addPostFrameCallback ( ( _ ) {
_isLoadingVisible = true ;
showDialog ( context: context , barrierColor: Colors . black . withOpacity ( 0.5 ) , useRootNavigator: false , builder: ( BuildContext context ) = > LoadingDialog ( ) ) . then ( ( value ) {
_isLoadingVisible = false ;
} ) ;
} ) ;
}
static void hideLoading ( BuildContext context ) {
if ( _isLoadingVisible ) {
_isLoadingVisible = false ;
Navigator . of ( context ) . pop ( ) ;
}
_isLoadingVisible = false ;
}
static Future < String > getStringFromPrefs ( String key ) async {
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
return prefs . getString ( key ) ? ? " " ;
}
static Future < bool > removeStringFromPrefs ( String key ) async {
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
return prefs . remove ( key ) ;
}
static Future < bool > saveStringFromPrefs ( String key , String value ) async {
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
return await prefs . setString ( key , value ) ;
}
static bool isMazayaAccessRevoked ( dynamic error ) {
if ( error = = null ) return false ;
String str = " " ;
if ( error is APIException & & error . error ! = null ) {
String errCode = error . error ? . errorCode ? . toString ( ) ? ? " " ;
String errMsg = error . error ? . errorMessage ? . toString ( ) ? ? " " ;
str = " $ errCode $ errMsg ${ error . message } " ;
if ( errCode . trim ( ) . toUpperCase ( ) = = " E4 " ) {
return true ;
}
} else {
str = error . toString ( ) ;
}
String lower = str . toLowerCase ( ) ;
if ( lower . contains ( " no active grant " ) | |
lower . contains ( " grant request " ) | |
lower . contains ( " grant was found " ) | |
lower . contains ( " grant_request " ) | |
lower . contains ( " e4: " ) | |
lower . contains ( " e4 - " ) | |
lower . contains ( " e4 : " ) ) {
return true ;
}
if ( str . contains ( " طلب منح " ) | | str . contains ( " منح نشط " ) | | str . contains ( " لا يوجد طلب منح " ) | | str . contains ( " تم إلغاء وصول مزايا " ) | | str . contains ( " إلغاء مزايا " ) ) {
return true ;
}
return false ;
}
static void handleException ( dynamic exception , cxt , Function ( String ) ? onErrorMessage ) {
if ( isMazayaAccessRevoked ( exception ) ) {
String depName = AppState ( ) . dependentName ? ? " " ;
if ( depName . isEmpty ) {
depName = AppState ( ) . walaplusDepInfoModel ? . pDependentName ? ? " " ;
}
if ( cxt ! = null ) {
Navigator . push ( cxt , MaterialPageRoute ( builder: ( context ) = > MazayaAccessResultScreen ( isGranted: false , dependentName: depName ) ) ) ;
return ;
}
}
String errorMessage ;
if ( exception is APIException & & exception . error ? . errorType = = 4 ) {
Navigator . pushNamedAndRemoveUntil ( cxt , AppRoutes . appUpdateScreen , ( _ ) = > false , arguments: exception . error ? . errorMessage ) ;
} else {
if ( exception is APIException ) {
if ( exception . message = = APIException . UNAUTHORIZED ) {
return ;
} else {
errorMessage = exception . error ? . errorMessage ? ? exception . message ;
}
} else {
errorMessage = APIException . UNKNOWN ;
}
if ( onErrorMessage ! = null ) {
onErrorMessage ( errorMessage ) ;
} else {
if ( ! AppState ( ) . isAuthenticated ) {
AppToast . show (
errorMessage ,
seconds: AppToast . actionSeconds ,
onComplete: ( ) {
Navigator . pushNamedAndRemoveUntil ( cxt , AppRoutes . login , ( Route < dynamic > route ) = > false ) ;
} ,
) ;
} else {
if ( cxt ! = null ) {
confirmDialog ( cxt , errorMessage ) ;
} else {
showToast ( errorMessage ) ;
}
}
}
}
}
static Future showErrorDialog ( { required BuildContext context , required VoidCallback onOkTapped , required String message , VoidCallback ? onCloseTap } ) async {
return showDialog ( context: context , builder: ( BuildContext context ) = > ConfirmDialog ( message: message , onTap: onOkTapped , onCloseTap: onCloseTap ) ) ;
}
static void confirmDialog ( cxt , String message , { VoidCallback ? onTap } ) {
// No onTap means there's nothing to confirm - it's a plain notice, so a self-dismissing
// toast replaces the old "OK just closes" dialog instead of requiring a tap.
if ( onTap = = null ) {
AppToast . show ( message ) ;
} else {
showDialog ( context: cxt , builder: ( BuildContext cxt ) = > ConfirmDialog ( message: message , onTap: onTap ) ) ;
}
}
static Widget getNoDataWidget ( BuildContext context ) {
return Column (
mainAxisAlignment: MainAxisAlignment . center ,
crossAxisAlignment: CrossAxisAlignment . center ,
children: [ SvgPicture . asset ( ' assets/images/not_found.svg ' , width: 110.0 , height: 110.0 ) , LocaleKeys . noDataAvailable . tr ( ) . toText16 ( ) . paddingOnly ( top: 15 ) ] ,
) . center ;
}
static Widget getNoChatWidget ( BuildContext context ) {
return Column (
mainAxisAlignment: MainAxisAlignment . center ,
crossAxisAlignment: CrossAxisAlignment . center ,
children: [ SvgPicture . asset ( ' assets/images/not_found.svg ' , width: 110.0 , height: 110.0 ) , LocaleKeys . noDataAvailable . tr ( ) . toText16 ( ) . paddingOnly ( top: 15 ) ] ,
) . center ;
}
static Uint8List getPostBytes ( img ) {
try {
var b64 = img . replaceFirst ( ' data:image/png;base64, ' , ' ' ) ;
if ( img ! = null & & Utils . isBase64 ( b64 ) ) return Utils . dataFromBase64String ( b64 ) ;
} catch ( e ) { }
return Uint8List . fromList ( [ ] ) ;
}
static String getBase64FromJpeg ( img ) {
try {
var b64 = img . replaceFirst ( ' data:image/jpeg;base64, ' , ' ' ) ;
return b64 ;
} catch ( e ) { }
return " " ;
}
static bool isBase64 ( String str ) {
RegExp _base64 = RegExp ( r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$' ) ;
return _base64 . hasMatch ( str ) ;
}
static Uint8List dataFromBase64String ( String base64String ) {
return base64Decode ( base64String ) ;
}
static Widget tableColumnTitle ( String ? text , { bool showDivider = true , bool alignCenter = false } ) {
text ? ? = " " ;
return Column (
crossAxisAlignment: CrossAxisAlignment . start ,
mainAxisSize: MainAxisSize . min ,
children: [ 6. height , alignCenter ? text . toText12 ( ) . center : text . toText12 ( ) , 5. height , if ( showDivider ) const Divider ( height: 1 , color: Color ( 0xff2E303A ) , thickness: 1 ) ] ,
) ;
}
static Decoration containerRadius ( Color background , double radius ) {
return BoxDecoration (
color: background ,
border: Border . all (
width: 1 , //
color: background , // <--- border width here
) ,
borderRadius: BorderRadius . circular ( radius ) ,
) ;
}
static Widget mHeight ( double h ) {
return Container ( height: h ) ;
}
static Widget mDivider ( Color color ) {
return Divider (
// width: double.infinity,
height: 1 ,
color: color ,
) ;
}
static Widget tableColumnValue ( String text , { bool isCapitable = true , bool alignCenter = false } ) {
return Column (
crossAxisAlignment: CrossAxisAlignment . start ,
mainAxisSize: MainAxisSize . min ,
children: [
12. height ,
if ( alignCenter )
( isCapitable ? text . toLowerCase ( ) . capitalizeFirstofEach : text ) . toText12 ( color: MyColors . normalTextColor ) . center
else
( isCapitable ? text . toLowerCase ( ) . capitalizeFirstofEach : text ) . toText12 ( color: MyColors . normalTextColor ) ,
12. height ,
] ,
) ;
}
/// EIT Forms date formats
static String getMonthNamedFormat ( DateTime date ) {
/// it will return like "29-Sep-2022"
return DateFormat ( ' dd-MMM-yyyy ' , " en_US " ) . format ( date ) ;
}
static String reverseFormatDate ( String date ) {
String formattedDate ;
if ( date . isNotEmpty ) {
formattedDate = date . replaceAll ( ' / ' , ' - ' ) ;
formattedDate = formattedDate . replaceAll ( ' 00:00:00 ' , ' ' ) ;
} else {
formattedDate = date ;
}
return formattedDate ;
}
static String formatStandardDate ( String date ) {
String formattedDate ;
if ( date . isNotEmpty ) {
formattedDate = date . replaceAll ( ' - ' , ' / ' ) ;
} else {
formattedDate = date ;
}
return formattedDate ;
}
static String reverseFormatStandardDate ( String date ) {
String formattedDate ;
if ( date . isNotEmpty ) {
formattedDate = date . replaceAll ( ' / ' , ' - ' ) ;
} else {
formattedDate = date ;
}
return formattedDate ;
}
static String formatDate ( String date ) {
String formattedDate ;
if ( date . isNotEmpty ) {
date = date . substring ( 0 , 10 ) ;
formattedDate = date . replaceAll ( ' - ' , ' / ' ) ;
formattedDate = formattedDate + ' 00:00:00 ' ;
} else {
formattedDate = date ;
}
return formattedDate ;
}
static String formatDateNew ( String date ) {
String formattedDate ;
if ( date . isNotEmpty ) {
formattedDate = date . split ( ' T ' ) [ 0 ] ;
if ( ! formattedDate . contains ( " 00:00:00 " ) ) {
formattedDate = formattedDate + ' 00:00:00 ' ;
}
} else {
formattedDate = date ;
}
return formattedDate ;
}
static String formatDateDefault ( String date ) {
if ( date . isNotEmpty ) {
if ( date . toLowerCase ( ) . contains ( " t " ) ) {
date = date . toLowerCase ( ) . split ( " t " ) [ 0 ] ;
if ( ! date . contains ( " 00:00:00 " ) ) {
date = date + ' 00:00:00 ' ;
}
return date ;
} else {
if ( date . toLowerCase ( ) . split ( " - " ) [ 1 ] . length = = 3 ) {
return DateFormat ( ' dd-MM-yyyy ' , " en_US " ) . format ( DateFormat ( ' dd-MMM-yyyy ' , " en_US " ) . parseLoose ( date ) ) ;
} else {
return DateFormat ( ' dd-MM-yyyy ' , " en_US " ) . format ( DateFormat ( ' yyyy-MM-dd ' , " en_US " ) . parseLoose ( date ) ) ;
}
// return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
}
} else {
return date ;
}
}
static Future < DateTime > selectDate ( BuildContext context , DateTime selectedDate ) async {
if ( ! Platform . isIOS ) {
await showCupertinoModalPopup (
context: context ,
builder:
( BuildContext cxt ) = > Container (
height: 250 ,
color: Colors . white ,
child: CupertinoDatePicker (
backgroundColor: Colors . white ,
mode: CupertinoDatePickerMode . date ,
onDateTimeChanged: ( DateTime value ) {
if ( value ! = null & & value ! = selectedDate ) {
selectedDate = value ;
}
} ,
initialDateTime: selectedDate ,
) ,
) ,
) ;
} else {
DateTime ? picked = await showDatePicker ( context: context , initialDate: selectedDate , initialEntryMode: DatePickerEntryMode . calendarOnly , firstDate: DateTime ( 2015 , 8 ) , lastDate: DateTime ( 2101 ) ) ;
if ( picked ! = null & & picked ! = selectedDate ) {
selectedDate = picked ;
}
}
return selectedDate ;
}
static void readNFc ( { required Function ( String ) onRead } ) {
NfcManager . instance
. startSession (
onDiscovered: ( NfcTag tag ) async {
MifareUltralight f ;
if ( Platform . isAndroid ) {
print ( tag ) ;
f = MifareUltralight ( tag: tag , identifier: tag . data [ " nfca " ] [ " identifier " ] , type: 2 , maxTransceiveLength: 252 , timeout: 22 ) ;
} else {
f = MifareUltralight ( tag: tag , identifier: tag . data [ " mifare " ] [ " identifier " ] , type: 2 , maxTransceiveLength: 252 , timeout: 22 ) ;
}
String identifier = f . identifier . map ( ( e ) = > e . toRadixString ( 16 ) . padLeft ( 2 , ' 0 ' ) ) . join ( ' ' ) ;
NfcManager . instance . stopSession ( ) ;
onRead ( identifier ) ;
} ,
pollingOptions: { NfcPollingOption . iso14443 } ,
)
. catchError ( ( err ) {
print ( err ) ;
} ) ;
}
//HUAWEI DECISION MAKING
static Future < bool > isGoogleServicesAvailable ( ) async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability . instance . checkGooglePlayServicesAvailability ( ) ;
String status = availability . toString ( ) . split ( ' . ' ) . last ;
if ( status = = " success " ) {
return true ;
}
return false ;
}
static bool isDate ( String input , String format ) {
try {
DateTime d = DateFormat ( format ) . parseStrict ( input ) ;
//print(d);
return true ;
} catch ( e ) {
//print(e);
return false ;
}
}
static Future < void > performLogout ( BuildContext ? context , ChatProviderModel ? chatData ) async {
AppState ( ) . isAuthenticated = false ;
AppState ( ) . isLogged = false ;
AppState ( ) . setPostParamsInitConfig ( ) ;
if ( chatData ! = null ) {
try {
chatData . disposeData ( ) ;
} catch ( e ) { }
}
// SharedPreferences prefs = await SharedPreferences.getInstance();
// await prefs.clear();
Navigator . pushNamedAndRemoveUntil ( context ! , AppRoutes . login , ( Route < dynamic > route ) = > false , arguments: null ) ;
}
}