You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
car_common_app/lib/utils/utils.dart

802 lines
24 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:path/path.dart' as p;
import 'package:fluttertoast/fluttertoast.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/exceptions/api_exception.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/widgets/loading_dialog.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
class Utils {
static bool _isLoadingVisible = false;
static bool get isLoading => _isLoadingVisible;
static void showToast(String message) {
Fluttertoast.showToast(
msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0);
}
static Future<void> openNumberViaCaller({required String phoneNumber}) async {
Uri phoneLaunchUrl = Uri.parse('tel:$phoneNumber');
if (await canLaunchUrl(phoneLaunchUrl)) {
try {
await launchUrl(phoneLaunchUrl);
} catch (e) {
await launchUrl(phoneLaunchUrl);
}
}
}
static Future<void> openEmailViaEmailApp({required String emailAddress}) async {
Uri emailLaunchUrl = Uri.parse('mailto:$emailAddress');
if (await canLaunchUrl(emailLaunchUrl)) {
try {
await launchUrl(emailLaunchUrl);
} catch (e) {
await launchUrl(emailLaunchUrl);
}
}
}
static Future<void> openNumberViaWhatsApp({required String phoneNumber}) async {
final url = 'https://wa.me/$phoneNumber?text=';
await launchUrlString(url, mode: LaunchMode.externalApplication);
}
static Future<String> pickDateFromDatePicker(BuildContext context, {DateTime? initial, DateTime? firstDate, DateTime? lastDate}) async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: initial ?? DateTime.now(), //get today's date
firstDate: firstDate ?? DateTime.now(), //DateTime.now() - not to allow to choose before today.
lastDate: lastDate ?? DateTime(2101));
if (pickedDate == null) {
return "";
}
String formattedDate = DateHelper.formatAsYearMonthDay(pickedDate); // format date in required form here we use yyyy-MM-dd that means time is removed
return formattedDate;
}
static Future<String> pickTime(BuildContext context, {TimeOfDay? initialTime}) async {
TimeOfDay? timeOfDay = await showTimePicker(
context: context,
initialTime: initialTime ?? TimeOfDay.now(),
);
if (timeOfDay == null) {
return "";
}
return ("${timeOfDay.hour.toString().length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute.toString().length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
}
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 void showLoading(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_isLoadingVisible = true;
showDialog(
context: context,
barrierColor: Colors.black.withOpacity(0.5),
builder: (BuildContext context) => LoadingDialog(),
).then((value) {
_isLoadingVisible = false;
});
});
}
static void hideLoading(BuildContext context) {
if (_isLoadingVisible) {
_isLoadingVisible = false;
Navigator.of(context).pop();
}
_isLoadingVisible = false;
}
static void handleException(dynamic exception, Function(String)? onErrorMessage) {
String errorMessage;
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 {
showToast(errorMessage);
}
}
static Color getColorFromHex(String hexColor) {
hexColor = hexColor.toUpperCase().replaceAll('#', '');
if (hexColor.length == 6) {
hexColor = 'FF$hexColor';
}
return Color(int.parse(hexColor, radix: 16));
}
static Widget spacerVertical(double v) {
return SizedBox(
height: v,
width: double.infinity,
);
}
static String convertFileToBase64(File file) {
List<int> imageBytes = file.readAsBytesSync();
return base64Encode(imageBytes);
}
static Future delay(int millis) async {
return await Future.delayed(Duration(milliseconds: millis));
}
static inkWellCorner({double? r}) {
return RoundedRectangleBorder(
borderRadius: BorderRadius.circular(r ?? 4),
);
}
static Widget spacerHorizontal(double v) {
return SizedBox(
height: v,
width: v,
);
}
static Widget mDivider(Color color, {double? h}) {
return Container(
width: double.infinity,
height: h ?? 1,
color: color,
);
}
static Widget mDivider3({double? h}) {
return Container(
width: double.infinity,
height: h ?? 1,
color: borderLightColor!.withOpacity(0.7),
);
}
static Widget mDivider2(Color color, double w) {
return Container(
width: w,
height: 1,
color: color,
);
}
static Color getChipColorByAdStatus(AdPostStatus adPostStatus) {
switch (adPostStatus) {
case AdPostStatus.pendingForReview:
return MyColors.adPendingStatusColor;
case AdPostStatus.pendingForPayment:
return MyColors.submittedColor;
case AdPostStatus.rejected:
return MyColors.adCancelledStatusColor;
case AdPostStatus.cancelled:
return MyColors.adCancelledStatusColor;
case AdPostStatus.pendingForPost:
case AdPostStatus.pendingForActive:
return MyColors.inProgressColor;
case AdPostStatus.active:
return MyColors.greenColor;
case AdPostStatus.expired:
return MyColors.adCancelledStatusColor;
case AdPostStatus.sold:
return MyColors.adSoldStatusColor;
case AdPostStatus.reserved:
return MyColors.primaryColor;
case AdPostStatus.deActive:
return MyColors.textColor;
case AdPostStatus.buyingService:
case AdPostStatus.reserveCancel:
case AdPostStatus.allAds:
return MyColors.greenColor;
}
}
static Color getChipColorByRequestStatus(RequestStatusEnum requestStatus) {
switch (requestStatus) {
case RequestStatusEnum.pending:
return MyColors.pendingColor;
case RequestStatusEnum.submitted:
return MyColors.submittedColor;
case RequestStatusEnum.inProgress:
return MyColors.inProgressColor;
case RequestStatusEnum.completed:
return MyColors.completedColor;
case RequestStatusEnum.cancelled:
return MyColors.cancelledColor;
case RequestStatusEnum.paid:
return MyColors.paidColor;
case RequestStatusEnum.expired:
return MyColors.expiredColor;
case RequestStatusEnum.shipping:
return MyColors.shippingColor;
case RequestStatusEnum.delivery:
return MyColors.deliveryColor;
case RequestStatusEnum.selfPickup:
return MyColors.selfPickupColor;
}
}
static Color getChipColorByRequestOfferStatusEnum(RequestOfferStatusEnum requestOfferStatusEnum) {
switch (requestOfferStatusEnum) {
case RequestOfferStatusEnum.offer:
return MyColors.pendingColor;
case RequestOfferStatusEnum.negotiate:
return MyColors.submittedColor;
case RequestOfferStatusEnum.accepted:
return MyColors.completedColor;
case RequestOfferStatusEnum.rejected:
return MyColors.cancelledColor;
case RequestOfferStatusEnum.cancel:
return MyColors.cancelledColor;
}
}
static String getNameByRequestOfferStatusEnum(RequestOfferStatusEnum requestOfferStatusEnum) {
switch (requestOfferStatusEnum) {
case RequestOfferStatusEnum.offer:
return "Offer";
case RequestOfferStatusEnum.negotiate:
return "Negotiate";
case RequestOfferStatusEnum.accepted:
return "Accepted";
case RequestOfferStatusEnum.rejected:
return "Rejected";
case RequestOfferStatusEnum.cancel:
return "Cancelled";
}
}
static String getNameByShippingRequestStatusEnum(ShippingRequestStatusEnum shippingRequestStatusEnum) {
switch (shippingRequestStatusEnum) {
case ShippingRequestStatusEnum.allRequests:
return "All Requests";
case ShippingRequestStatusEnum.initiated:
return "Initiated";
case ShippingRequestStatusEnum.inTransit:
return "In Transit";
case ShippingRequestStatusEnum.outForDelivery:
return "Out For Delivery";
case ShippingRequestStatusEnum.delivered:
return "Delivered";
case ShippingRequestStatusEnum.pending:
return "Pending";
}
}
static String getNameBySelfPickupRequestStatusEnum(SelfPickupRequestStatusEnum selfPickupRequestStatusEnum) {
switch (selfPickupRequestStatusEnum) {
case SelfPickupRequestStatusEnum.allRequests:
return "All Requests";
case SelfPickupRequestStatusEnum.pending:
return "Pending";
case SelfPickupRequestStatusEnum.preparingToCollect:
return "Preparing To Collect";
case SelfPickupRequestStatusEnum.readyToCollect:
return "Ready To Collect";
case SelfPickupRequestStatusEnum.collected:
return "Collected";
}
}
static Color getChipColorByShippingRequestStatusEnum(ShippingRequestStatusEnum shippingRequestStatusEnum) {
switch (shippingRequestStatusEnum) {
case ShippingRequestStatusEnum.allRequests:
return MyColors.submittedColor;
case ShippingRequestStatusEnum.initiated:
return MyColors.submittedColor;
case ShippingRequestStatusEnum.inTransit:
return MyColors.shippingColor;
case ShippingRequestStatusEnum.outForDelivery:
return MyColors.deliveryColor;
case ShippingRequestStatusEnum.delivered:
return MyColors.greenColor;
case ShippingRequestStatusEnum.pending:
return MyColors.pendingColor;
}
}
static Color getChipColorBySelfPickupRequestStatusEnum(SelfPickupRequestStatusEnum selfPickupRequestStatusEnum) {
switch (selfPickupRequestStatusEnum) {
case SelfPickupRequestStatusEnum.allRequests:
return MyColors.submittedColor;
case SelfPickupRequestStatusEnum.pending:
return MyColors.pendingColor;
case SelfPickupRequestStatusEnum.preparingToCollect:
return MyColors.submittedColor;
case SelfPickupRequestStatusEnum.readyToCollect:
return MyColors.shippingColor;
case SelfPickupRequestStatusEnum.collected:
return MyColors.deliveryColor;
}
}
static Color getChipColorByBranchStatus(BranchStatusEnum branchStatusEnum) {
switch (branchStatusEnum) {
case BranchStatusEnum.pending:
return MyColors.adPendingStatusColor;
case BranchStatusEnum.review:
return MyColors.adPendingStatusColor;
case BranchStatusEnum.rejected:
return MyColors.adCancelledStatusColor;
case BranchStatusEnum.deactivated:
return MyColors.adCancelledStatusColor;
case BranchStatusEnum.blocked:
return MyColors.expiredColor;
case BranchStatusEnum.approvedOrActive:
return MyColors.greenColor;
}
}
static String getChipStatusTextByBranchStatus(BranchStatusEnum branchStatusEnum) {
switch (branchStatusEnum) {
case BranchStatusEnum.pending:
return "Pending Approval";
case BranchStatusEnum.review:
return "In Review";
case BranchStatusEnum.rejected:
return "Rejected";
case BranchStatusEnum.deactivated:
return "Deactivated";
case BranchStatusEnum.blocked:
return "Blocked";
case BranchStatusEnum.approvedOrActive:
return "Active";
}
}
static statusContainerChip({
required String text,
EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 3, horizontal: 6),
Color chipColor = MyColors.greenColor,
Color textColor = MyColors.white,
}) {
return Container(
decoration: BoxDecoration(
color: chipColor,
),
padding: padding,
child: text.toText(fontSize: 10, color: textColor, letterSpacing: -0.50));
}
static InputDecoration txtField(String label) {
return InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
hintText: label,
hintStyle: const TextStyle(color: Colors.grey),
disabledBorder: InputBorder.none,
isDense: false,
contentPadding: const EdgeInsets.only(left: 15, right: 15),
);
}
static Widget mFlex(int f) {
return Flexible(
flex: f,
child: const SizedBox(
width: double.infinity,
height: double.infinity,
),
);
}
static Widget mExp(int f) {
return Expanded(
flex: f,
child: Container(
width: double.infinity,
),
);
}
static String checkFileExt(String path) {
String ex = p.extension(path);
var parts = ex.split('.');
return parts[1]; // '.dart'
}
static spacer() {
return const SizedBox(
height: 8,
);
}
static cardRadius(double radius) {
return RoundedRectangleBorder(
side: const BorderSide(color: Colors.transparent, width: 1),
borderRadius: BorderRadius.circular(radius),
);
}
static cardRadiusWithoutBorder(double radius) {
return RoundedRectangleBorder(
side: const BorderSide(color: Colors.transparent, width: 1),
borderRadius: BorderRadius.circular(radius),
);
}
static Image imageFromBase64String(String base64String) {
return Image.memory(base64Decode(base64String));
}
static Uint8List dataFromBase64String(String base64String) {
return base64Decode(base64String);
}
static String base64String(Uint8List data) {
return base64Encode(data);
}
static Widget overLayWidget({double? width, double? height, List<Color>? color}) {
return Container(
width: width ?? double.infinity,
height: height ?? 60,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: color ??
[
Colors.black.withOpacity(0.2),
Colors.black.withOpacity(0.1),
Colors.black.withOpacity(0.004),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
tileMode: TileMode.clamp,
),
),
);
}
static Decoration containerRadius(Color color, double r) {
return BoxDecoration(
color: color,
borderRadius: BorderRadius.all(Radius.circular(r)),
);
}
static Decoration containerRadiusTop({Color? color, double? r}) {
return BoxDecoration(
color: color ?? Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(r ?? 12), topLeft: Radius.circular(r ?? 12)),
);
}
static Decoration containerRadiusBorder(Color color, double r) {
return BoxDecoration(
color: Colors.transparent,
border: Border.all(color: color, width: 1),
borderRadius: BorderRadius.all(Radius.circular(r)),
);
}
static Decoration containerRadiusBottom(Color color, double r) {
return BoxDecoration(
color: color,
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(r), bottomRight: Radius.circular(r)),
);
}
static ShapeBorder cardRadiusTop(double radius) {
return RoundedRectangleBorder(
side: const BorderSide(color: Colors.transparent, width: 0),
borderRadius: BorderRadius.only(topLeft: Radius.circular(radius), topRight: Radius.circular(radius)),
);
}
static Decoration containerColorRadiusBorderWidth(Color background, double radius, Color color, double w) {
return BoxDecoration(
color: background,
border: Border.all(
width: w, //
color: color // <--- border width here
),
borderRadius: BorderRadius.circular(radius),
);
}
static ShapeBorder cardRadiusTop2(double radius) {
return RoundedRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(radius), topRight: Radius.circular(radius)),
);
}
static ShapeBorder cardRadiusBottom(double radius) {
return RoundedRectangleBorder(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(radius), bottomRight: Radius.circular(radius)),
);
}
static Decoration containerColorRadiusBorder(Color background, double radius, Color color) {
return BoxDecoration(
color: background,
border: Border.all(
width: 1, //
color: color // <--- border width here
),
borderRadius: BorderRadius.circular(radius),
);
}
static bool passwordValidateStructure(String value) {
String pattern = r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{6,}$';
RegExp regExp = RegExp(pattern);
return regExp.hasMatch(value);
}
static bool isEmailValid(String email) {
String p = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = RegExp(p);
return regExp.hasMatch(email);
}
static String getAdsPaymentBrowserForm({required int paymentId, required int adId}) {
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
}
// BOTTOM SHEETS
static void showHelpBottomSheet(BuildContext context) {
return actionConfirmationBottomSheet(
context: context,
title: LocaleKeys.help.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: LocaleKeys.customerCarePrompt.tr(),
isOnlyOneButton: true,
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.callNow.tr(),
fontSize: 18,
onPressed: () {
pop(context);
},
),
),
actionButtonNo: const SizedBox(),
);
}
static Widget buildStatusContainer(String text, {double marginAll = 8, double fontSize = 14}) {
if (text.isEmpty) {
return const SizedBox();
}
return Center(
child: text.toText(color: MyColors.lightTextColor, fontSize: fontSize),
).toContainer(
marginAll: marginAll,
paddingAll: 15,
borderRadius: 8,
width: double.infinity,
backgroundColor: MyColors.grey98Color.withOpacity(0.1),
);
}
static Future<void> openLocationInMaps({required double latitude, required double longitude}) async {
final Uri googleMapsUrl = Uri.parse('https://www.google.com/maps/search/?api=1&query=$latitude,$longitude');
if (await canLaunchUrl(googleMapsUrl)) {
try {
await launchUrl(googleMapsUrl);
} catch (e) {
await launchUrl(googleMapsUrl);
}
}
}
static Future<ShareResult> shareAppInvitation() async {
ShareResult result = await Share.share(GlobalConsts.getAppInvitationLink(), subject: 'Join Mowater');
return result;
}
static Future<void> inviteFriend({required InviteTypeEnum inviteTypeEnum, required String message}) async {
String url;
switch (inviteTypeEnum) {
case InviteTypeEnum.whatsapp:
// WhatsApp requires a phone number and message, format like this:
url = 'https://wa.me/?text=${Uri.encodeComponent(message)}';
break;
case InviteTypeEnum.sms:
// SMS: 'sms:<phone_number>?body=<message>'
// You can add a phone number, or keep it empty to allow the user to input one.
url = 'sms:?body=${Uri.encodeComponent(message)}';
break;
case InviteTypeEnum.email:
// Email: 'mailto:<email>?subject=<subject>&body=<message>'
url = 'mailto:?subject=MowaterInvitation&body=${Uri.encodeComponent(message)}';
break;
}
// Try to launch the URL and catch any exceptions.
if (await canLaunchUrl(Uri.parse(url))) {
try {
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
} catch (e) {
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
}
}
}
static buildProviderContactInfoBottomSheet({required BuildContext context, required String? email, required String? mobileNo}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return InfoBottomSheet(
title: LocaleKeys.contactDetails.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (mobileNo != null && mobileNo.isNotEmpty) ...[
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.call,
size: 20,
color: MyColors.greyColor,
),
titleText: LocaleKeys.phoneNumber.tr(),
subTitle: " $mobileNo",
needBorderBelow: true,
showTrailingArrow: false,
subtitleTextColor: MyColors.greyColor,
onTap: () {
Utils.openNumberViaCaller(phoneNumber: mobileNo);
},
),
],
if (email != null && email.isNotEmpty) ...[
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.email_outlined,
size: 20,
color: MyColors.greyColor,
),
titleText: LocaleKeys.emailAddress.tr(),
subTitle: " $email",
needBorderBelow: false,
showTrailingArrow: false,
subtitleTextColor: MyColors.greyColor,
onTap: () {
Utils.openEmailViaEmailApp(emailAddress: email);
},
),
],
30.height,
],
),
);
},
);
}
}
class NoInternetDialog {
static void show(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
LocaleKeys.connectionProblem.tr(),
textAlign: TextAlign.center,
),
content: Text(
LocaleKeys.pleaseCheckConnection.tr(),
textAlign: TextAlign.center,
),
actions: [
ElevatedButton(
onPressed: () {
// // if (AppState().currentAppType == AppType.provider) {
// Navigator.of(context).pop();
Navigator.of(context).pushNamedAndRemoveUntil(AppRoutes.registerSelection, (Route<dynamic> route) => true);
},
child: const Text(
LocaleKeys.ok,
style: TextStyle(color: Colors.white),
),
),
],
);
},
);
}
}