diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 2fd29149..7129fd0b 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -683,11 +683,20 @@
"emrgNo": "رقم جهة الاتصال في حالات الطوارئ",
"modes": "الأوضاع",
"vibration": "اهتزاز عند اللمس",
- "blindModes": "أوضاع للمكفوفين جزئيًا",
+ "blindModes": "وضع للمكفوفين جزئياً",
"invertTheme": "عكس",
"offTheme": "إيقاف",
"dimTheme": "خافت",
"bwTheme": "أسود وأبيض",
+ "highContrastTheme": "تباين عالي",
+ "fontSize": "حجم الخط",
+ "fontSizeSmall": "صغير",
+ "fontSizeMedium": "متوسط",
+ "fontSizeLarge": "كبير",
+ "saveChanges": "حفظ التغييرات",
+ "settingsSavedSuccessfully": "تم حفظ الإعدادات بنجاح",
+ "cardHeading": "عنوان البطاقة",
+ "buttonText": "نص الزر",
"permissions": "إذن",
"cameraPermission": "الكاميرا",
"locationPermission": "الموقع",
@@ -695,7 +704,7 @@
"outOfStockMsg": "لقد أضفت منتجًا غير متوفر حاليًا، يرجى إزالته!",
"noArabicLetters": "لا يُسمح باستخدام الحروف العربية",
"noOffersAvailable": "لا توجد عروض متاحة!",
- "accessibility": "وضع الوصول",
+ "accessibility": "إمكانية الوصول",
"orderStatus": "حالة الطلب",
"findUs": "فروعنا",
"liveChat": "محادثة مباشرة",
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index 43ff1c11..29e5d100 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -673,11 +673,20 @@
"emrgNo": "Emergency Contact Number",
"modes": "Modes",
"vibration": "Vibration Touch Feedback",
- "blindModes": "Modes for Partially Blind",
+ "blindModes": "Mode for partially blind",
"invertTheme": "Invert",
"offTheme": "Off",
"dimTheme": "Dim",
"bwTheme": "Black and White",
+ "highContrastTheme": "High Contrast",
+ "fontSize": "Font Size",
+ "fontSizeSmall": "Small",
+ "fontSizeMedium": "Medium",
+ "fontSizeLarge": "Large",
+ "saveChanges": "Save Changes",
+ "settingsSavedSuccessfully": "Settings saved successfully",
+ "cardHeading": "Card Heading",
+ "buttonText": "Button Text",
"permissions": "Permission",
"cameraPermission": "Camera",
"locationPermission": "Location",
@@ -685,7 +694,7 @@
"outOfStockMsg": "You have added product which is out of stock now, Please remove that!",
"noArabicLetters": "It Is Not Allow to Use Arabic Letters",
"noOffersAvailable": "No Offers Available!",
- "accessibility": "Accessibility Mode",
+ "accessibility": "Accessibility",
"orderStatus": "Order Status",
"findUs": "Find Us",
"liveChat": "Live Chat",
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index 35532d69..9e8a044d 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -26,6 +26,8 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/dialogs/confirm_dialog.dart';
import 'package:hmg_patient_app_new/widgets/loading_dialog.dart';
+import 'package:hmg_patient_app_new/widgets/accessibility/preserve_image_colors.dart';
+import 'package:hmg_patient_app_new/widgets/accessibility/preserve_svg_colors.dart';
import 'package:lottie/lottie.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -120,10 +122,8 @@ class Utils {
// ),
// ));
return !isAddHours
- ? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US")
- .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal())
- : DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US")
- .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add(
+ ? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal())
+ : DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add(
Duration(
hours: isAddHours ? 3 : 0,
),
@@ -356,12 +356,9 @@ class Utils {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: isSmallWidget ? 0.h : 48.h),
- Lottie.asset(AppAnimations.noData,
- repeat: false, reverse: false, frameRate: FrameRate(60), width: width.w, height: height.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.noData, repeat: false, reverse: false, frameRate: FrameRate(60), width: width.w, height: height.h, fit: BoxFit.fill),
SizedBox(height: 16.h),
- (noDataText ?? LocaleKeys.noDataAvailable.tr())
- .toText14(isBold: true, color: AppColors.greyTextColor, isCenter: true)
- .paddingSymmetrical(64.w, 0.h),
+ (noDataText ?? LocaleKeys.noDataAvailable.tr()).toText14(isBold: true, color: AppColors.greyTextColor, isCenter: true).paddingSymmetrical(64.w, 0.h),
SizedBox(height: 16.h),
callToActionButton
],
@@ -373,8 +370,7 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Lottie.asset(AppAnimations.loadingAnimation,
- repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.loadingAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor, isCenter: true, isBold: true),
SizedBox(height: 8.h),
@@ -400,8 +396,7 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Lottie.asset(AppAnimations.errorAnimation,
- repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 8.h),
@@ -502,8 +497,7 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Lottie.asset(AppAnimations.warningAnimation,
- repeat: false, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.warningAnimation, repeat: false, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText15(color: AppColors.blackColor, letterSpacing: 0),
SizedBox(height: 16.h),
@@ -623,10 +617,8 @@ class Utils {
}
// Replace HTML line breaks with newlines
- var withLineBreaks = htmlString
- .replaceAll(RegExp(r'
', multiLine: true), '\n')
- .replaceAll(RegExp(r'<\/p>', multiLine: true), '\n')
- .replaceAll(RegExp(r'', multiLine: true), '\n');
+ var withLineBreaks =
+ htmlString.replaceAll(RegExp(r'
', multiLine: true), '\n').replaceAll(RegExp(r'<\/p>', multiLine: true), '\n').replaceAll(RegExp(r'', multiLine: true), '\n');
// Remove all other HTML tags
var withoutTags = withLineBreaks.replaceAll(RegExp(r'<[^>]*>'), '');
@@ -704,20 +696,7 @@ class Utils {
final year = parts[0];
// Map month number to short month name (Hijri months)
- const hijriMonthNames = [
- 'Muharram',
- 'Safar',
- 'Rabi I',
- 'Rabi II',
- 'Jumada I',
- 'Jumada II',
- 'Rajab',
- 'Sha\'ban',
- 'Ramadan',
- 'Shawwal',
- 'Dhu al-Qi\'dah',
- 'Dhu al-Hijjah'
- ];
+ const hijriMonthNames = ['Muharram', 'Safar', 'Rabi I', 'Rabi II', 'Jumada I', 'Jumada II', 'Rajab', 'Sha\'ban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'];
final monthIndex = int.tryParse(parts[1]) ?? 1;
final month = hijriMonthNames[monthIndex - 1];
@@ -774,21 +753,23 @@ class Utils {
String? errorAsset,
}) {
final Color? resolvedColor = iconColor ?? (applyThemeColor && AppColors.isDarkMode ? AppColors.textColor : null);
- return SvgPicture.asset(
- icon,
- colorFilter: resolvedColor != null ? ColorFilter.mode(isDisabled ? resolvedColor.withOpacity(0.5) : resolvedColor, BlendMode.srcIn) : null,
- width: width,
- height: height,
- fit: fit,
- errorBuilder: errorAsset != null
- ? (context, error, stackTrace) => SvgPicture.asset(
- errorAsset,
- colorFilter: resolvedColor != null ? ColorFilter.mode(isDisabled ? resolvedColor.withOpacity(0.5) : resolvedColor, BlendMode.srcIn) : null,
- width: width,
- height: height,
- fit: fit,
- )
- : null,
+ return PreserveSvgColors(
+ child: SvgPicture.asset(
+ icon,
+ colorFilter: resolvedColor != null ? ColorFilter.mode(isDisabled ? resolvedColor.withValues(alpha: 0.5) : resolvedColor, BlendMode.srcIn) : null,
+ width: width,
+ height: height,
+ fit: fit,
+ errorBuilder: errorAsset != null
+ ? (context, error, stackTrace) => SvgPicture.asset(
+ errorAsset,
+ colorFilter: resolvedColor != null ? ColorFilter.mode(isDisabled ? resolvedColor.withValues(alpha: 0.5) : resolvedColor, BlendMode.srcIn) : null,
+ width: width,
+ height: height,
+ fit: fit,
+ )
+ : null,
+ ),
);
}
@@ -802,14 +783,16 @@ class Utils {
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
- return SvgPicture.network(
- url,
- colorFilter: ColorFilter.mode(
- isDisabled ? iconColor.withOpacity(0.5) : iconColor,
- BlendMode.srcIn,
+ return PreserveSvgColors(
+ child: SvgPicture.network(
+ url,
+ colorFilter: ColorFilter.mode(
+ isDisabled ? iconColor.withValues(alpha: 0.5) : iconColor,
+ BlendMode.srcIn,
+ ),
+ width: iconW,
+ height: iconH,
),
- width: iconW,
- height: iconH,
);
}
@@ -825,14 +808,15 @@ class Utils {
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
- return Container(
- decoration: BoxDecoration(
- border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
- borderRadius: border != null ? BorderRadius.circular(borderRadius ?? 12.r) : null,
+ return PreserveImageColors(
+ child: Container(
+ decoration: BoxDecoration(
+ border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
+ borderRadius: border != null ? BorderRadius.circular(borderRadius ?? 12.r) : null,
+ ),
+ child: Image.asset(icon, width: iconW, height: iconH, fit: fit),
),
- child: Image.asset(icon, width: iconW, height: iconH, fit: fit),
);
- // return Image.asset(icon, width: width, height: height, fit: fit, );
}
static Widget buildImgWithAssetsWithBorderRadius({
@@ -847,21 +831,23 @@ class Utils {
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
- return Container(
- width: iconW,
- height: iconH,
- decoration: BoxDecoration(
- border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
- borderRadius: borderRadius != null ? BorderRadius.circular(borderRadius ?? 12.r) : null,
- image: DecorationImage(
- image: AssetImage(
- icon,
- ),
- fit: fit)),
+ return PreserveImageColors(
+ child: Container(
+ width: iconW,
+ height: iconH,
+ decoration: BoxDecoration(
+ border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
+ borderRadius: BorderRadius.circular(borderRadius ?? 12.r),
+ image: DecorationImage(
+ image: AssetImage(
+ icon,
+ ),
+ fit: fit)),
+ ),
);
}
- /// Widget to build an SVG from network
+ /// Widget to build an image from network - automatically preserves colors in visual modes
static Widget buildImgWithNetwork({
required String url,
required Color iconColor,
@@ -873,16 +859,18 @@ class Utils {
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
- return Image.network(
- url,
- width: iconW,
- height: iconH,
- fit: fit,
- errorBuilder: errorBuilder ??
- (_, __, ___) {
- //todo_section change the error builder icon that it is returning
- return Utils.buildSvgWithAssets(width: iconW, height: iconH, icon: AppAssets.no_visit_icon);
- },
+ return PreserveImageColors(
+ child: Image.network(
+ url,
+ width: iconW,
+ height: iconH,
+ fit: fit,
+ errorBuilder: errorBuilder ??
+ (_, __, ___) {
+ //todo_section change the error builder icon that it is returning
+ return Utils.buildSvgWithAssets(width: iconW, height: iconH, icon: AppAssets.no_visit_icon);
+ },
+ ),
);
}
@@ -891,26 +879,37 @@ class Utils {
spacing: spacing.w,
mainAxisSize: MainAxisSize.max,
children: [
- Image.asset(AppAssets.mada, width: width.h, height: height.h),
- Image.asset(
- AppAssets.tamaraEng,
- width: width.h,
- height: height.h,
- fit: BoxFit.contain,
- errorBuilder: (context, error, stackTrace) {
- debugPrint('Failed to load Tamara PNG in payment methods: $error');
- return Utils.buildSvgWithAssets(icon: AppAssets.tamara, width: 35.h, height: 35.h, fit: BoxFit.contain);
- },
+ PreserveImageColors(
+ child: Image.asset(AppAssets.mada, width: width.h, height: height.h),
+ ),
+ PreserveImageColors(
+ child: Image.asset(
+ AppAssets.tamaraEng,
+ width: width.h,
+ height: height.h,
+ fit: BoxFit.contain,
+ errorBuilder: (context, error, stackTrace) {
+ debugPrint('Failed to load Tamara PNG in payment methods: $error');
+ return Utils.buildSvgWithAssets(icon: AppAssets.tamara, width: 35.h, height: 35.h, fit: BoxFit.contain);
+ },
+ ),
+ ),
+ PreserveImageColors(
+ child: Image.asset(AppAssets.visa, width: width.h, height: height.h),
),
- Image.asset(AppAssets.visa, width: width.h, height: height.h),
- Image.asset(AppAssets.mastercard, width: width.h, height: height.h),
- Platform.isIOS ? Image.asset(AppAssets.applePay, width: width.h, height: height.h) : SizedBox.shrink(),
+ PreserveImageColors(
+ child: Image.asset(AppAssets.mastercard, width: width.h, height: height.h),
+ ),
+ Platform.isIOS
+ ? PreserveImageColors(
+ child: Image.asset(AppAssets.applePay, width: width.h, height: height.h),
+ )
+ : SizedBox.shrink(),
],
);
}
- static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize,
- {bool isSaudiCurrency = true, bool isExpanded = true}) {
+ static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) {
return Row(
mainAxisAlignment: isExpanded ? MainAxisAlignment.spaceBetween : MainAxisAlignment.start,
children: [
@@ -965,13 +964,7 @@ class Utils {
// text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount),
// text: " ${(NumberFormat.decimalPattern().format(habibWalletAmount)).toStringAsFixed(2)}",
text: " ${(NumberFormat.decimalPattern().format(habibWalletAmount))}",
- style: TextStyle(
- color: resolvedTextColor,
- fontSize: fontSize ?? 32.f,
- letterSpacing: letterSpacing ?? -4,
- fontFamily: "Poppins",
- fontWeight: fontWeight ?? FontWeight.w600,
- height: 1),
+ style: TextStyle(color: resolvedTextColor, fontSize: fontSize ?? 32.f, letterSpacing: letterSpacing ?? -4, fontFamily: "Poppins", fontWeight: fontWeight ?? FontWeight.w600, height: 1),
),
],
),
@@ -1035,12 +1028,7 @@ class Utils {
static PatientDoctorAppointmentList? convertToPatientDoctorAppointmentList(HospitalsModel? hospital) {
if (hospital == null) return null;
return PatientDoctorAppointmentList(
- filterName: hospital.name,
- distanceInKMs: hospital.distanceInKilometers?.toString(),
- projectTopName: hospital.name,
- projectBottomName: hospital.name,
- model: hospital,
- isHMC: hospital.isHMC);
+ filterName: hospital.name, distanceInKMs: hospital.distanceInKilometers?.toString(), projectTopName: hospital.name, projectBottomName: hospital.name, model: hospital, isHMC: hospital.isHMC);
}
static HospitalsModel? convertToHospitalsModel(PatientDoctorAppointmentList? item) {
diff --git a/lib/features/book_appointments/models/laser_body_parts_data.dart b/lib/features/book_appointments/models/laser_body_parts_data.dart
index 2f8b32dc..969aa1d0 100644
--- a/lib/features/book_appointments/models/laser_body_parts_data.dart
+++ b/lib/features/book_appointments/models/laser_body_parts_data.dart
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
class LaserBodyParts {
static final LaserBodyParts _instance = LaserBodyParts._internal();
@@ -9,11 +9,11 @@ class LaserBodyParts {
factory LaserBodyParts() => _instance;
static Widget image(String assetUri) {
- return new SvgPicture.asset(assetUri, fit: BoxFit.cover, width: 88, height: 88);
+ return Utils.buildSvgWithAssets(icon: assetUri, fit: BoxFit.cover, width: 88, height: 88, applyThemeColor: false);
}
static Widget imagePng(String assetUri) {
- return Image.asset(assetUri, fit: BoxFit.cover, width: 88, height: 88);
+ return Utils.buildImgWithAssets(icon: assetUri, fit: BoxFit.cover, width: 88, height: 88);
}
Map maleBodyMap = {
diff --git a/lib/features/profile_settings/profile_settings_view_model.dart b/lib/features/profile_settings/profile_settings_view_model.dart
index 02cbc10f..aebdb849 100644
--- a/lib/features/profile_settings/profile_settings_view_model.dart
+++ b/lib/features/profile_settings/profile_settings_view_model.dart
@@ -16,6 +16,8 @@ import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
class ProfileSettingsViewModel extends ChangeNotifier {
static const String _darkModeKey = 'is_dark_mode';
+ static const String _fontSizeStepKey = 'accessibility_font_size_step';
+ static const String _visualModeKey = 'accessibility_visual_mode';
final CacheService _cacheService;
final ProfileSettingsRepo profileSettingsRepo;
@@ -25,6 +27,13 @@ class ProfileSettingsViewModel extends ChangeNotifier {
bool _isDarkMode = false;
bool get isDarkMode => _isDarkMode;
+ // ── Accessibility settings ───────────────────────────────────────────
+ int _fontSizeStep = 2; // 0: Small, 1: Small-Medium, 2: Medium (default), 3: Medium-Large, 4: Large
+ int get fontSizeStep => _fontSizeStep;
+
+ String _visualMode = 'off'; // off, invert, dim, highContrast
+ String get visualMode => _visualMode;
+
// ── Update email state ───────────────────────────────────────────────
bool isUpdateEmailLoading = false;
bool isUpdateEmailSuccess = false;
@@ -163,6 +172,47 @@ class ProfileSettingsViewModel extends ChangeNotifier {
notifyListeners();
}
+ // ── Accessibility settings ───────────────────────────────────────────
+
+ /// Load accessibility settings at app startup
+ void loadAccessibilitySettings() {
+ _fontSizeStep = _cacheService.getInt(key: _fontSizeStepKey) ?? 2;
+ _visualMode = _cacheService.getString(key: _visualModeKey) ?? 'off';
+ // No notifyListeners() here — we are called before build.
+ }
+
+ /// Update font size step and save to cache
+ void setFontSizeStep(int step) {
+ _fontSizeStep = step;
+ _cacheService.saveInt(key: _fontSizeStepKey, value: step);
+ notifyListeners();
+ }
+
+ /// Update visual mode and save to cache
+ void setVisualMode(String mode) {
+ _visualMode = mode;
+ _cacheService.saveString(key: _visualModeKey, value: mode);
+ notifyListeners();
+ }
+
+ /// Get font scale multiplier based on current font size step
+ double getFontScaleMultiplier() {
+ switch (_fontSizeStep) {
+ case 0:
+ return 0.85; // Small
+ case 1:
+ return 0.95; // Small-Medium
+ case 2:
+ return 1.0; // Medium (default)
+ case 3:
+ return 1.15; // Medium-Large
+ case 4:
+ return 1.3; // Large
+ default:
+ return 1.0;
+ }
+ }
+
// ── Update patient info ──────────────────────────────────────────────
Future updatePatientInfo({
diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart
index 51e27211..08a3b905 100644
--- a/lib/generated/locale_keys.g.dart
+++ b/lib/generated/locale_keys.g.dart
@@ -687,6 +687,15 @@ abstract class LocaleKeys {
static const offTheme = 'offTheme';
static const dimTheme = 'dimTheme';
static const bwTheme = 'bwTheme';
+ static const highContrastTheme = 'highContrastTheme';
+ static const fontSize = 'fontSize';
+ static const fontSizeSmall = 'fontSizeSmall';
+ static const fontSizeMedium = 'fontSizeMedium';
+ static const fontSizeLarge = 'fontSizeLarge';
+ static const saveChanges = 'saveChanges';
+ static const settingsSavedSuccessfully = 'settingsSavedSuccessfully';
+ static const cardHeading = 'cardHeading';
+ static const buttonText = 'buttonText';
static const permissions = 'permissions';
static const cameraPermission = 'cameraPermission';
static const locationPermission = 'locationPermission';
@@ -1578,7 +1587,6 @@ abstract class LocaleKeys {
static const waterConsumption = 'waterConsumption';
static const selectNumberOfReminders = 'selectNumberOfReminders';
static const h2oSettings = 'h2oSettings';
- static const settingsSavedSuccessfully = 'settingsSavedSuccessfully';
static const yourName = 'yourName';
static const ageYears = 'ageYears';
static const numberOfRemindersInADay = 'numberOfRemindersInADay';
diff --git a/lib/main.dart b/lib/main.dart
index 0119cd1c..6e3ef8cc 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -134,6 +134,9 @@ Future callInitializations() async {
// Restore persisted dark-mode preference before the first frame.
getIt.get().loadDarkMode();
+
+ // Restore persisted accessibility settings before the first frame.
+ getIt.get().loadAccessibilitySettings();
}
void main() async {
@@ -282,6 +285,55 @@ void main() async {
class MyApp extends StatelessWidget {
const MyApp({super.key});
+ /// Apply visual mode filter to the entire app
+ Widget _applyVisualMode(String visualMode, Widget child) {
+ switch (visualMode) {
+ case 'invert':
+ // Invert colors app-wide (red becomes cyan for colorblind users)
+ return ColorFiltered(
+ colorFilter: const ColorFilter.matrix([
+ -1, 0, 0, 0, 255, // Red channel inverted
+ 0, -1, 0, 0, 255, // Green channel inverted
+ 0, 0, -1, 0, 255, // Blue channel inverted
+ 0, 0, 0, 1, 0, // Alpha channel unchanged
+ ]),
+ child: child,
+ );
+
+ case 'dim':
+ // Apply dim effect with opacity overlay
+ return Stack(
+ children: [
+ child,
+ Positioned.fill(
+ child: IgnorePointer(
+ child: Container(
+ color: Colors.black.withValues(alpha: 0.3), // 30% black overlay for dimming
+ ),
+ ),
+ ),
+ ],
+ );
+
+ case 'highContrast':
+ // Apply desaturation for high contrast (removes colors, leaves black and white)
+ return ColorFiltered(
+ colorFilter: const ColorFilter.matrix([
+ 0.2126, 0.7152, 0.0722, 0, 0, // Red channel (grayscale)
+ 0.2126, 0.7152, 0.0722, 0, 0, // Green channel (grayscale)
+ 0.2126, 0.7152, 0.0722, 0, 0, // Blue channel (grayscale)
+ 0, 0, 0, 1, 0, // Alpha channel unchanged
+ ]),
+ child: child,
+ );
+
+ case 'off':
+ default:
+ // No filter applied
+ return child;
+ }
+ }
+
@override
Widget build(BuildContext context) {
return SafeArea(
@@ -300,13 +352,16 @@ class MyApp extends StatelessWidget {
// title: 'Dr. AlHabib',
title: 'Dr. AlHabib Beta',
builder: (context, mchild) {
- return MediaQuery(
+ Widget child = MediaQuery(
data: MediaQuery.of(context).copyWith(
- textScaler: TextScaler.noScaling,
+ textScaler: TextScaler.linear(profileVm.getFontScaleMultiplier()),
alwaysUse24HourFormat: true,
),
child: mchild!,
);
+
+ // Apply visual mode filters app-wide
+ return _applyVisualMode(profileVm.visualMode, child);
},
showSemanticsDebugger: false,
debugShowCheckedModeBanner: false,
diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart
index ddf9ec86..46fd5209 100644
--- a/lib/presentation/appointments/appointment_details_page.dart
+++ b/lib/presentation/appointments/appointment_details_page.dart
@@ -570,8 +570,9 @@ class _AppointmentDetailsPageState extends State {
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24.r),
// Todo: what is this???? Api Key??? 😲
- child: Image.network(
- "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=${(MediaQuery.of(context).size.width * 1.5).toInt()}x${(MediaQuery.of(context).size.height * 0.35).toInt()}&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}",
+ child: Utils.buildImgWithNetwork(
+ url: "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=${(MediaQuery.of(context).size.width * 1.5).toInt()}x${(MediaQuery.of(context).size.height * 0.35).toInt()}&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}",
+ iconColor: AppColors.transparent,
fit: BoxFit.cover,
width: double.infinity,
),
diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart
index bae7514c..f3aff049 100644
--- a/lib/presentation/appointments/appointment_payment_page.dart
+++ b/lib/presentation/appointments/appointment_payment_page.dart
@@ -112,7 +112,7 @@ class _AppointmentPaymentPageState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.mada, width: 72.h, height: 25.h)
+ Utils.buildImgWithAssets(icon: AppAssets.mada, width: 72.h, height: 25.h)
.toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
SizedBox(height: 16.h),
LocaleKeys.mada.tr(context: context).toText16(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
@@ -230,9 +230,9 @@ class _AppointmentPaymentPageState extends State {
children: [
Row(
children: [
- Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.visa, width: 50.h, height: 50.h),
SizedBox(width: 8.h),
- Image.asset(AppAssets.mastercard, width: 40.h, height: 40.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h),
],
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
SizedBox(height: 16.h),
@@ -352,7 +352,7 @@ class _AppointmentPaymentPageState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.tamaraEng, width: 72.h, height: 25.h)
+ Utils.buildImgWithAssets(icon: AppAssets.tamaraEng, width: 72.h, height: 25.h)
.toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
SizedBox(height: 16.h),
LocaleKeys.tamara.tr(context: context)
diff --git a/lib/presentation/appointments/my_doctors_page.dart b/lib/presentation/appointments/my_doctors_page.dart
index 0c574a4c..9ccf471e 100644
--- a/lib/presentation/appointments/my_doctors_page.dart
+++ b/lib/presentation/appointments/my_doctors_page.dart
@@ -139,8 +139,9 @@ class _MyDoctorsPageState extends State {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
@@ -261,8 +262,9 @@ class _MyDoctorsPageState extends State {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Image.network(
- (doctor?.doctorImageURL ?? doctor?.doctorImage ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png"),
+ Utils.buildImgWithNetwork(
+ url: (doctor?.doctorImageURL ?? doctor?.doctorImage ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png"),
+ iconColor: AppColors.transparent,
width: 24.w,
height: 24.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart
index 03c12c3b..8e871dcb 100644
--- a/lib/presentation/appointments/widgets/appointment_card.dart
+++ b/lib/presentation/appointments/widgets/appointment_card.dart
@@ -227,10 +227,11 @@ class _AppointmentCardState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- widget.isLoading
+ Utils.buildImgWithNetwork(
+ url: widget.isLoading
? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png'
: widget.patientAppointmentHistoryResponseModel.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
@@ -280,8 +281,9 @@ class _AppointmentCardState extends State {
SizedBox(width: 12.w),
(widget.patientAppointmentHistoryResponseModel.doctorNationalityFlagURL != null &&
widget.patientAppointmentHistoryResponseModel.doctorNationalityFlagURL!.isNotEmpty)
- ? Image.network(
- widget.patientAppointmentHistoryResponseModel.doctorNationalityFlagURL ?? "https://hmgwebservices.com/Images/flag/SAU.png",
+ ? Utils.buildImgWithNetwork(
+ url: widget.patientAppointmentHistoryResponseModel.doctorNationalityFlagURL ?? "https://hmgwebservices.com/Images/flag/SAU.png",
+ iconColor: AppColors.transparent,
width: 20.h,
height: 15.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart
index 299c3db9..d064b4e8 100644
--- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart
+++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart
@@ -58,8 +58,9 @@ class AppointmentDoctorCard extends StatelessWidget {
children: [
Column(
children: [
- Image.network(
- patientAppointmentHistoryResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: patientAppointmentHistoryResponseModel.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/appointments/widgets/doctor_row_appointment_rating.dart b/lib/presentation/appointments/widgets/doctor_row_appointment_rating.dart
index 8872f4ea..df15173c 100644
--- a/lib/presentation/appointments/widgets/doctor_row_appointment_rating.dart
+++ b/lib/presentation/appointments/widgets/doctor_row_appointment_rating.dart
@@ -10,6 +10,9 @@ import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'dart:ui' as ui;
+import '../../../core/utils/utils.dart';
+import '../../../theme/colors.dart';
+
class BuildDoctorRowAppointmentRating extends StatelessWidget {
final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
@@ -22,8 +25,9 @@ class BuildDoctorRowAppointmentRating extends StatelessWidget {
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- patientAppointmentHistoryResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: patientAppointmentHistoryResponseModel.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/ask_doctor/doctor_response_page.dart b/lib/presentation/ask_doctor/doctor_response_page.dart
index 922d2fdb..5591d777 100644
--- a/lib/presentation/ask_doctor/doctor_response_page.dart
+++ b/lib/presentation/ask_doctor/doctor_response_page.dart
@@ -86,8 +86,9 @@ class _DoctorResponsePageState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ iconColor: AppColors.blackBgColor,
width: 50.w,
height: 50.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/ask_doctor/widgets/ask_doctor_appointment_card.dart b/lib/presentation/ask_doctor/widgets/ask_doctor_appointment_card.dart
index 4ebd9b74..6eae8870 100644
--- a/lib/presentation/ask_doctor/widgets/ask_doctor_appointment_card.dart
+++ b/lib/presentation/ask_doctor/widgets/ask_doctor_appointment_card.dart
@@ -87,8 +87,9 @@ class AskDoctorAppointmentCard extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- askDoctorAppointmentHistoryList.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: askDoctorAppointmentHistoryList.doctorImageURL!,
+ iconColor: AppColors.blackBgColor,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/ask_doctor/widgets/doctor_response_transactions.dart b/lib/presentation/ask_doctor/widgets/doctor_response_transactions.dart
index 59516d15..1343c36f 100644
--- a/lib/presentation/ask_doctor/widgets/doctor_response_transactions.dart
+++ b/lib/presentation/ask_doctor/widgets/doctor_response_transactions.dart
@@ -28,8 +28,9 @@ class DoctorResponseTransactions extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ iconColor: AppColors.blackBgColor,
width: 50.w,
height: 50.h,
fit: BoxFit.cover,
@@ -85,7 +86,11 @@ class DoctorResponseTransactions extends StatelessWidget {
SizedBox(height: 16.h),
Row(
children: [
- Image.asset(getIt.get().getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, width: 42.w, height: 42.h),
+ Utils.buildImgWithAssets(
+ icon: getIt.get().getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
+ width: 42.w,
+ height: 42.h,
+ ),
SizedBox(width: 8.w),
Container(
padding: EdgeInsets.all(8.w),
@@ -116,10 +121,16 @@ class DoctorResponseTransactions extends StatelessWidget {
borderRadius: BorderRadius.circular(8.r),
),
child: doctorResponseModel.transactions![index].doctorResponse!.toText12(color: AppColors.textColor, isBold: true),
- ),
- SizedBox(width: 8.w),
- Image.network("https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png", fit: BoxFit.cover, width: 42.w, height: 42.h).circle(100.r),
- ],
+ ),
+ SizedBox(width: 8.w),
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ iconColor: AppColors.blackBgColor,
+ fit: BoxFit.cover,
+ width: 42.w,
+ height: 42.h,
+ ).circle(100.r),
+ ],
),
],
);
diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart
index 00a0e5a2..6bbac9ec 100644
--- a/lib/presentation/book_appointment/book_appointment_page.dart
+++ b/lib/presentation/book_appointment/book_appointment_page.dart
@@ -132,8 +132,9 @@ class _BookAppointmentPageState extends State {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 64.h,
height: 64.h,
fit: BoxFit.cover,
@@ -191,8 +192,9 @@ class _BookAppointmentPageState extends State {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 64.h,
height: 64.h,
fit: BoxFit.cover,
@@ -383,8 +385,9 @@ class _BookAppointmentPageState extends State {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- myAppointmentsVM.patientFavouriteDoctorsList[index].doctorImageUrl!,
+ Utils.buildImgWithNetwork(
+ url: myAppointmentsVM.patientFavouriteDoctorsList[index].doctorImageUrl!,
+ iconColor: AppColors.transparent,
width: 64.h,
height: 64.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/book_appointment/doctor_profile_page.dart b/lib/presentation/book_appointment/doctor_profile_page.dart
index 044db504..be097651 100644
--- a/lib/presentation/book_appointment/doctor_profile_page.dart
+++ b/lib/presentation/book_appointment/doctor_profile_page.dart
@@ -83,8 +83,9 @@ class DoctorProfilePage extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- bookAppointmentsViewModel.doctorsProfileResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: bookAppointmentsViewModel.doctorsProfileResponseModel.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
@@ -109,8 +110,9 @@ class DoctorProfilePage extends StatelessWidget {
),
],
),
- Image.network(
- bookAppointmentsViewModel.doctorsProfileResponseModel.nationalityFlagURL!,
+ Utils.buildImgWithNetwork(
+ url: bookAppointmentsViewModel.doctorsProfileResponseModel.nationalityFlagURL!,
+ iconColor: AppColors.transparent,
width: 32.h,
height: 32.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart
index dd8422ee..ed323629 100644
--- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart
+++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart
@@ -66,8 +66,8 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
padding: EdgeInsets.all(16.h),
child: Row(
children: [
- Image.asset(
- appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
+ Utils.buildImgWithAssets(
+ icon: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
width: 52.h,
height: 52.h,
),
diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart
index e2bb0c17..b0f00317 100644
--- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart
+++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart
@@ -106,7 +106,7 @@ class _ImmediateLiveCarePaymentPageState extends State {
children: [
Row(
children: [
- Image.network(
- bookAppointmentsViewModel.selectedDoctor.doctorImageURL ??
+ Utils.buildImgWithNetwork(
+ url: bookAppointmentsViewModel.selectedDoctor.doctorImageURL ??
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ iconColor: AppColors.transparent,
width: 50.h,
height: 50.h,
fit: BoxFit.cover,
@@ -104,9 +105,10 @@ class _ReviewAppointmentPageState extends State {
SizedBox(width: 12.w),
(bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL != null &&
bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL!.isNotEmpty)
- ? Image.network(
- bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL ??
+ ? Utils.buildImgWithNetwork(
+ url: bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL ??
"https://hmgwebservices.com/Images/flag/SAU.png",
+ iconColor: AppColors.transparent,
width: 20.h,
height: 15.h,
fit: BoxFit.cover,
@@ -334,12 +336,10 @@ class _ReviewAppointmentPageState extends State {
// Show default image (no image data or user has no uploaded image)
print('📷 Showing default avatar for user $currentPatientId');
- return Image.asset(
- defaultImage,
- key: ValueKey('default_$currentPatientId'),
+ return Utils.buildImgWithAssets(
+ icon: defaultImage,
width: 52.w,
height: 52.h,
- gaplessPlayback: true,
);
}
diff --git a/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart b/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart
index 95fafe9c..c40c712c 100644
--- a/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart
+++ b/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart
@@ -116,7 +116,7 @@ class _WaitingAppointmentPaymentPageState extends State {
),
child: Row(
children: [
- Image.asset(children[index]['image'], width: 24.h, height: 24.h),
+ Utils.buildImgWithAssets(icon: children[index]['image'], width: 24.h, height: 24.h),
SizedBox(width: 8.w),
Text(
"${children[index]['name']} (${children[index]['gender']})",
diff --git a/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart b/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart
index 06056764..7e7bc613 100644
--- a/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart
+++ b/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart
@@ -282,8 +282,8 @@ class _ComprehensiveCheckupPageState extends State {
final String imagePath = appStateLocal.isArabic() ? AppAssets.comprehensiveCheckupAr : AppAssets.comprehensiveCheckupEn;
return Stack(
children: [
- Image.asset(
- imagePath,
+ Utils.buildImgWithAssets(
+ icon: imagePath,
width: double.infinity,
fit: BoxFit.cover,
).paddingAll(16.w),
diff --git a/lib/presentation/contact_us/feedback_page.dart b/lib/presentation/contact_us/feedback_page.dart
index 00576e9d..32359fef 100644
--- a/lib/presentation/contact_us/feedback_page.dart
+++ b/lib/presentation/contact_us/feedback_page.dart
@@ -259,8 +259,9 @@ class FeedbackPage extends StatelessWidget {
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- contactUsViewModel.patientFeedbackSelectedAppointment!.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: contactUsViewModel.patientFeedbackSelectedAppointment!.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/contact_us/find_us_page.dart b/lib/presentation/contact_us/find_us_page.dart
index 4a68b2aa..379540a3 100644
--- a/lib/presentation/contact_us/find_us_page.dart
+++ b/lib/presentation/contact_us/find_us_page.dart
@@ -16,6 +16,8 @@ import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:provider/provider.dart';
+import '../../core/utils/utils.dart';
+
class FindUsPage extends StatelessWidget {
FindUsPage({super.key});
@@ -120,8 +122,9 @@ class FindUsPage extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/contact_us/live_chat_page.dart b/lib/presentation/contact_us/live_chat_page.dart
index 107f5ba4..718294b4 100644
--- a/lib/presentation/contact_us/live_chat_page.dart
+++ b/lib/presentation/contact_us/live_chat_page.dart
@@ -70,8 +70,9 @@ class LiveChatPage extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/contact_us/widgets/find_us_item_card.dart b/lib/presentation/contact_us/widgets/find_us_item_card.dart
index 1f7f2443..6db34a4d 100644
--- a/lib/presentation/contact_us/widgets/find_us_item_card.dart
+++ b/lib/presentation/contact_us/widgets/find_us_item_card.dart
@@ -78,8 +78,9 @@ class FindUsItemCard extends StatelessWidget {
: SizedBox.shrink(),
Row(
children: [
- Image.network(
- getHMGLocationsModel.projectImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: getHMGLocationsModel.projectImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 40.h,
height: 40.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/covid19test/covid_payment_screen.dart b/lib/presentation/covid19test/covid_payment_screen.dart
index a846828f..db7268c5 100644
--- a/lib/presentation/covid19test/covid_payment_screen.dart
+++ b/lib/presentation/covid19test/covid_payment_screen.dart
@@ -211,7 +211,7 @@ class _CovidPaymentScreenState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mada, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
LocaleKeys.mada.tr(context: context).toText16(isBold: true),
],
@@ -252,9 +252,9 @@ class _CovidPaymentScreenState extends State {
children: [
Row(
children: [
- Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.visa, width: 50.h, height: 50.h),
SizedBox(width: 8.h),
- Image.asset(AppAssets.mastercard, width: 40.h, height: 40.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h),
],
),
SizedBox(height: 16.h),
@@ -296,21 +296,11 @@ class _CovidPaymentScreenState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(
- AppAssets.tamaraEng,
+ Utils.buildImgWithAssets(
+ icon: AppAssets.tamaraEng,
width: 72.h,
height: 25.h,
fit: BoxFit.contain,
- // If PNG fails to load for any reason, log and fallback to SVG asset
- errorBuilder: (context, error, stackTrace) {
- debugPrint('Failed to load Tamara PNG asset: $error');
- return Utils.buildSvgWithAssets(
- icon: AppAssets.tamara,
- width: 72.h,
- height: 25.h,
- fit: BoxFit.contain,
- );
- },
),
SizedBox(height: 16.h),
LocaleKeys.tamara.tr(context: context).toText16(isBold: true),
diff --git a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart
index fca64321..64856226 100644
--- a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart
+++ b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart
@@ -102,7 +102,7 @@ class _ErOnlineCheckinPaymentPageState extends State
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mada, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
LocaleKeys.mada.tr(context: context).toText16(isBold: true),
],
@@ -188,9 +188,9 @@ class _ErOnlineCheckinPaymentPageState extends State
children: [
Row(
children: [
- Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.visa, width: 50.h, height: 50.h),
SizedBox(width: 8.h),
- Image.asset(AppAssets.mastercard, width: 40.h, height: 40.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h),
],
),
SizedBox(height: 16.h),
@@ -277,7 +277,7 @@ class _ErOnlineCheckinPaymentPageState extends State
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.tamaraEng, width: 72.h, height: 25.h),
+ Utils.buildImgWithAssets(icon: AppAssets.tamaraEng, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
LocaleKeys.tamara.tr(context: context).toText16(isBold: true),
],
diff --git a/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart b/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart
index dd3c5ff8..e52e3548 100644
--- a/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart
+++ b/lib/presentation/habib_wallet/wallet_payment_confirm_page.dart
@@ -85,7 +85,7 @@ class _WalletPaymentConfirmPageState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.mada, width: 72.h, height: 25.h).toShimmer2(isShow: false),
+ Utils.buildImgWithAssets(icon: AppAssets.mada, width: 72.h, height: 25.h).toShimmer2(isShow: false),
SizedBox(height: 16.h),
LocaleKeys.mada.tr(context: context).toText16(isBold: true).toShimmer2(isShow: false),
],
@@ -183,9 +183,9 @@ class _WalletPaymentConfirmPageState extends State {
children: [
Row(
children: [
- Image.asset(AppAssets.visa, width: 40.h, height: 40.h),
+ Utils.buildImgWithAssets(icon: AppAssets.visa, width: 40.h, height: 40.h),
SizedBox(width: 8.h),
- Image.asset(AppAssets.mastercard, width: 40.h, height: 40.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h),
],
).toShimmer2(isShow: false),
SizedBox(height: 16.h),
diff --git a/lib/presentation/home/service_info_page.dart b/lib/presentation/home/service_info_page.dart
index 75df9437..00f264b5 100644
--- a/lib/presentation/home/service_info_page.dart
+++ b/lib/presentation/home/service_info_page.dart
@@ -13,6 +13,8 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
+import '../../core/utils/utils.dart';
+
class ServiceInfoPage extends StatelessWidget {
final String serviceName;
final String serviceHeader;
@@ -37,8 +39,8 @@ class ServiceInfoPage extends StatelessWidget {
borderRadius: BorderRadius.circular(24.r),
child: Transform.flip(
flipX: getIt.get().isArabic(),
- child: Image.asset(
- serviceImage,
+ child: Utils.buildImgWithAssets(
+ icon: serviceImage,
fit: BoxFit.fitHeight,
// height: 480.h,
// width: 520.w,
diff --git a/lib/presentation/home/widgets/large_service_card.dart b/lib/presentation/home/widgets/large_service_card.dart
index 72b11ef3..7c037604 100644
--- a/lib/presentation/home/widgets/large_service_card.dart
+++ b/lib/presentation/home/widgets/large_service_card.dart
@@ -56,8 +56,8 @@ class LargeServiceCard extends StatelessWidget {
topLeft: Radius.circular(24.r),
topRight: Radius.circular(24.r),
),
- child: Image.asset(
- serviceCardData.largeCardIcon,
+ child: Utils.buildImgWithAssets(
+ icon: serviceCardData.largeCardIcon,
fit: BoxFit.cover,
width: double.infinity,
height: isFoldable ? 190.h : (isTablet ? 200.h : 180.h),
@@ -72,7 +72,7 @@ class LargeServiceCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
isPNG
- ? Image.asset(serviceCardData.icon, width: 35.h, height: 35.h)
+ ? Utils.buildImgWithAssets(icon: serviceCardData.icon, width: 35.h, height: 35.h)
: Container(
height: 48.h,
width: 48.h,
@@ -204,7 +204,7 @@ class FadedLargeServiceCard extends StatelessWidget {
borderRadius: BorderRadius.circular(24.r),
child: Transform.flip(
flipX: getIt.get().isArabic(),
- child: Image.asset(serviceCardData.largeCardIcon, fit: BoxFit.cover, width: 520.w, height: 250.h)),
+ child: Utils.buildImgWithAssets(icon: serviceCardData.largeCardIcon, fit: BoxFit.cover, width: 520.w, height: 250.h)),
),
Positioned(
top: 0,
@@ -234,7 +234,7 @@ class FadedLargeServiceCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
isPNG
- ? Image.asset(serviceCardData.icon, width: 32.h, height: 32.h).circle(100.h)
+ ? Utils.buildImgWithAssets(icon: serviceCardData.icon, width: 32.h, height: 32.h).circle(100.h)
: Container(
height: 32.h,
width: 32.h,
diff --git a/lib/presentation/home/widgets/welcome_widget.dart b/lib/presentation/home/widgets/welcome_widget.dart
index bdd71b53..039da8c1 100644
--- a/lib/presentation/home/widgets/welcome_widget.dart
+++ b/lib/presentation/home/widgets/welcome_widget.dart
@@ -63,7 +63,7 @@ class WelcomeWidget extends StatelessWidget {
),
imageWidget ??
(imageUrl != null
- ? Image.asset(imageUrl!, width: 40, height: 40)
+ ? Utils.buildImgWithAssets(icon: imageUrl!, width: 40, height: 40)
: SizedBox(width: 40, height: 40)),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
diff --git a/lib/presentation/insurance/insurance_approval_details_page.dart b/lib/presentation/insurance/insurance_approval_details_page.dart
index e3b684bf..b1fce84a 100644
--- a/lib/presentation/insurance/insurance_approval_details_page.dart
+++ b/lib/presentation/insurance/insurance_approval_details_page.dart
@@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
@@ -82,8 +83,9 @@ class InsuranceApprovalDetailsPage extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- insuranceApprovalResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: insuranceApprovalResponseModel.doctorImageURL!,
+ iconColor: AppColors.blackBgColor,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/insurance/widgets/insurance_approval_card.dart b/lib/presentation/insurance/widgets/insurance_approval_card.dart
index 8357a2d9..34662ef4 100644
--- a/lib/presentation/insurance/widgets/insurance_approval_card.dart
+++ b/lib/presentation/insurance/widgets/insurance_approval_card.dart
@@ -106,8 +106,9 @@ class InsuranceApprovalCard extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- isLoading ? "https://hmgwebservices.com/Images/MobileImages/OALAY/1439.png" : insuranceApprovalResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: isLoading ? "https://hmgwebservices.com/Images/MobileImages/OALAY/1439.png" : insuranceApprovalResponseModel.doctorImageURL!,
+ iconColor: AppColors.blackBgColor,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/lab/lab_result_item_view.dart b/lib/presentation/lab/lab_result_item_view.dart
index 554bd8f2..d03c02df 100644
--- a/lib/presentation/lab/lab_result_item_view.dart
+++ b/lib/presentation/lab/lab_result_item_view.dart
@@ -55,8 +55,9 @@ class LabResultItemView extends StatelessWidget {
SizedBox(height: 8.h),
Row(
children: [
- Image.network(
- isLoading ? "" : labOrder!.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: isLoading ? "" : labOrder!.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 24.h,
height: 24.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/lab/lab_result_via_clinic/ai_analysis_widget.dart b/lib/presentation/lab/lab_result_via_clinic/ai_analysis_widget.dart
index ebf802df..b643515f 100644
--- a/lib/presentation/lab/lab_result_via_clinic/ai_analysis_widget.dart
+++ b/lib/presentation/lab/lab_result_via_clinic/ai_analysis_widget.dart
@@ -1,9 +1,9 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_order_response_by_ai_model.dart';
@@ -37,7 +37,13 @@ class AiAnalysisWidget extends StatelessWidget {
Container(
padding: EdgeInsets.all(8.r),
decoration: BoxDecoration(gradient: AppColors.aiLinearGradient, borderRadius: BorderRadius.circular(8.r)),
- child: SvgPicture.asset(AppAssets.aiOverView, colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn), height: 18.r, width: 18.r),
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.aiOverView,
+ iconColor: Colors.white,
+ height: 18.r,
+ width: 18.r,
+ applyThemeColor: false,
+ ),
),
],
),
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index 6bbd5074..81343e42 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -908,8 +908,9 @@ class _MedicalFilePageState extends State {
child: FadeInAnimation(
child: Row(
children: [
- Image.network(
- prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 40.h,
height: 40.h,
fit: BoxFit.cover,
@@ -1059,8 +1060,9 @@ class _MedicalFilePageState extends State {
? Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 64.h,
height: 64.h,
fit: BoxFit.cover,
@@ -1106,8 +1108,9 @@ class _MedicalFilePageState extends State {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Image.network(
- myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 64.h,
height: 64.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/medical_file/patient_sickleaves_list_page.dart b/lib/presentation/medical_file/patient_sickleaves_list_page.dart
index cfdaaa7c..c31d80ac 100644
--- a/lib/presentation/medical_file/patient_sickleaves_list_page.dart
+++ b/lib/presentation/medical_file/patient_sickleaves_list_page.dart
@@ -139,8 +139,9 @@ class _PatientSickleavesListPageState extends State {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Image.network(
- model.patientSickLeaveList[index].doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: model.patientSickLeaveList[index].doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
diff --git a/lib/presentation/medical_file/vaccine_list_page.dart b/lib/presentation/medical_file/vaccine_list_page.dart
index d6c29676..a58802cc 100644
--- a/lib/presentation/medical_file/vaccine_list_page.dart
+++ b/lib/presentation/medical_file/vaccine_list_page.dart
@@ -83,8 +83,9 @@ class _VaccineListPageState extends State {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart b/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
index c0a5492b..5ddf25ea 100644
--- a/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
+++ b/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
@@ -163,9 +163,10 @@ class _MedicalFileAppointmentCardState extends State
children: [
Row(
children: [
- Image.network(
- widget.patientAppointmentHistoryResponseModel.doctorImageURL ??
+ Utils.buildImgWithNetwork(
+ url: widget.patientAppointmentHistoryResponseModel.doctorImageURL ??
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 30.h,
height: 30.h,
fit: BoxFit.fill,
diff --git a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
index 667e1a30..63aac378 100644
--- a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
+++ b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
@@ -56,8 +56,9 @@ class PatientSickLeaveCard extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientSickLeavesResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientSickLeavesResponseModel.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 30.h,
height: 30.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/medical_report/medical_reports_page.dart b/lib/presentation/medical_report/medical_reports_page.dart
index ee287662..e03a53a0 100644
--- a/lib/presentation/medical_report/medical_reports_page.dart
+++ b/lib/presentation/medical_report/medical_reports_page.dart
@@ -241,8 +241,9 @@ class _MedicalReportsPageState extends State {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Image.network(
- report.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: report.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
diff --git a/lib/presentation/medical_report/widgets/patient_medical_report_card.dart b/lib/presentation/medical_report/widgets/patient_medical_report_card.dart
index 49cb0e3a..f074022e 100644
--- a/lib/presentation/medical_report/widgets/patient_medical_report_card.dart
+++ b/lib/presentation/medical_report/widgets/patient_medical_report_card.dart
@@ -42,8 +42,9 @@ class PatientMedicalReportCard extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientMedicalReportResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientMedicalReportResponseModel.doctorImageURL!,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.fill,
diff --git a/lib/presentation/my_invoices/my_invoices_details_page.dart b/lib/presentation/my_invoices/my_invoices_details_page.dart
index 9f0370a0..2b539b24 100644
--- a/lib/presentation/my_invoices/my_invoices_details_page.dart
+++ b/lib/presentation/my_invoices/my_invoices_details_page.dart
@@ -149,8 +149,9 @@ class _MyInvoicesDetailsPageState extends State {
children: [
Column(
children: [
- Image.network(
- widget.getInvoiceDetailsResponseModel.doctorImageURL ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png',
+ Utils.buildImgWithNetwork(
+ url: widget.getInvoiceDetailsResponseModel.doctorImageURL ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png',
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/my_invoices/widgets/invoice_list_card.dart b/lib/presentation/my_invoices/widgets/invoice_list_card.dart
index 1e9aefd8..8fea72fc 100644
--- a/lib/presentation/my_invoices/widgets/invoice_list_card.dart
+++ b/lib/presentation/my_invoices/widgets/invoice_list_card.dart
@@ -102,8 +102,9 @@ class InvoiceListCard extends StatelessWidget {
children: [
Column(
children: [
- Image.network(
- getInvoicesListResponseModel.doctorImageUrl ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png',
+ Utils.buildImgWithNetwork(
+ url: getInvoicesListResponseModel.doctorImageUrl ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png',
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/my_invoices/widgets/pharmacy_invoice_card.dart b/lib/presentation/my_invoices/widgets/pharmacy_invoice_card.dart
index 6d672b38..2aaefcac 100644
--- a/lib/presentation/my_invoices/widgets/pharmacy_invoice_card.dart
+++ b/lib/presentation/my_invoices/widgets/pharmacy_invoice_card.dart
@@ -71,8 +71,9 @@ class PharmacyInvoiceCard extends StatelessWidget {
children: [
Column(
children: [
- Image.network(
- pharmacyInvoice.doctorImageURL ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png',
+ Utils.buildImgWithNetwork(
+ url: pharmacyInvoice.doctorImageURL ?? 'https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png',
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/offers_and_discounts/offer_and_discounts_full_screen_swiper_page.dart b/lib/presentation/offers_and_discounts/offer_and_discounts_full_screen_swiper_page.dart
index 8e7a53cd..4d377462 100644
--- a/lib/presentation/offers_and_discounts/offer_and_discounts_full_screen_swiper_page.dart
+++ b/lib/presentation/offers_and_discounts/offer_and_discounts_full_screen_swiper_page.dart
@@ -84,24 +84,9 @@ class _OfferAndDiscountsFullScreenSwiperPageState extends State().isArabic(),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.r),
- child: Image.asset(
- _promoImages[index],
+ child: Utils.buildImgWithAssets(
+ icon: _promoImages[index],
fit: BoxFit.contain,
- errorBuilder: (context, error, stackTrace) {
- return Container(
- decoration: BoxDecoration(
- color: Colors.white.withValues(alpha: 0.1),
- borderRadius: BorderRadius.circular(16.r),
- ),
- child: Center(
- child: Icon(
- Icons.image_outlined,
- size: 100.h,
- color: Colors.white.withValues(alpha: 0.5),
- ),
- ),
- );
- },
),
),
),
diff --git a/lib/presentation/offers_and_discounts/offers_and_discounts_detailed_page.dart b/lib/presentation/offers_and_discounts/offers_and_discounts_detailed_page.dart
index 86dedbcd..ed78dffb 100644
--- a/lib/presentation/offers_and_discounts/offers_and_discounts_detailed_page.dart
+++ b/lib/presentation/offers_and_discounts/offers_and_discounts_detailed_page.dart
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/offers_and_discounts/models/offers_and_discounts_response_model.dart';
@@ -92,8 +93,9 @@ class OffersAndDiscountsDetailedPage extends StatelessWidget {
children: [
ClipRRect(
borderRadius: BorderRadius.circular(24.h),
- child: Image.network(
- offer.imageUrl!,
+ child: Utils.buildImgWithNetwork(
+ url: offer.imageUrl!,
+ iconColor: AppColors.blackBgColor,
width: double.infinity,
height: 250.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/offers_and_discounts/offers_and_discounts_page.dart b/lib/presentation/offers_and_discounts/offers_and_discounts_page.dart
index a38c7935..2a26ac24 100644
--- a/lib/presentation/offers_and_discounts/offers_and_discounts_page.dart
+++ b/lib/presentation/offers_and_discounts/offers_and_discounts_page.dart
@@ -158,8 +158,9 @@ class _OffersAndDiscountsPageState extends State {
ClipRRect(
borderRadius: BorderRadius.vertical(top: Radius.circular(24.h)),
child: SizedBox.expand(
- child: Image.network(
- offersAndDiscountVM.filteredOffers[index].imageUrl!,
+ child: Utils.buildImgWithNetwork(
+ url: offersAndDiscountVM.filteredOffers[index].imageUrl!,
+ iconColor: AppColors.blackBgColor,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Container(
diff --git a/lib/presentation/offers_and_discounts/widgets/offers_and_discounts.dart b/lib/presentation/offers_and_discounts/widgets/offers_and_discounts.dart
index cfd6a86e..408831be 100644
--- a/lib/presentation/offers_and_discounts/widgets/offers_and_discounts.dart
+++ b/lib/presentation/offers_and_discounts/widgets/offers_and_discounts.dart
@@ -5,6 +5,8 @@ import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offer_and_
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:smooth_corner/smooth_corner.dart';
+import '../../../core/utils/utils.dart';
+
class OffersAndDiscountsCarousel extends StatefulWidget {
const OffersAndDiscountsCarousel({super.key});
@@ -112,19 +114,9 @@ class _OffersAndDiscountsCarouselState extends State
padding: const EdgeInsets.all(2.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(11.r),
- child: Image.asset(
- imagePath,
+ child: Utils.buildImgWithAssets(
+ icon: imagePath,
fit: BoxFit.cover,
- errorBuilder: (context, error, stackTrace) {
- return Container(
- color: AppColors.greyColor,
- child: Icon(
- Icons.image,
- color: AppColors.textColorLight,
- size: 32.h,
- ),
- );
- },
),
),
),
diff --git a/lib/presentation/parking/paking_page.dart b/lib/presentation/parking/paking_page.dart
index 736ef2a0..43b25973 100644
--- a/lib/presentation/parking/paking_page.dart
+++ b/lib/presentation/parking/paking_page.dart
@@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@@ -110,8 +111,8 @@ class _ParkingPageState extends State {
borderRadius: BorderRadius.circular(24.r),
child: Transform.flip(
flipX: getIt.get().isArabic(),
- child: Image.asset(
- AppAssets.carParkingService,
+ child: Utils.buildImgWithAssets(
+ icon: AppAssets.carParkingService,
fit: BoxFit.fitHeight,
height: 480.h,
width: 520.w,
diff --git a/lib/presentation/prescriptions/prescription_delivery_order_summary_page.dart b/lib/presentation/prescriptions/prescription_delivery_order_summary_page.dart
index 4c1b13a8..a5823b4f 100644
--- a/lib/presentation/prescriptions/prescription_delivery_order_summary_page.dart
+++ b/lib/presentation/prescriptions/prescription_delivery_order_summary_page.dart
@@ -61,8 +61,9 @@ class PrescriptionDeliveryOrderSummaryPage extends StatelessWidget {
borderRadius: BorderRadius.all(
Radius.circular(5.r),
),
- child: Image.network(
- prescriptionsViewModel.prescriptionDetailsList[index].imageSRCUrl!,
+ child: Utils.buildImgWithNetwork(
+ url: prescriptionsViewModel.prescriptionDetailsList[index].imageSRCUrl!,
+ iconColor: AppColors.blackBgColor,
fit: BoxFit.cover,
width: 60.w,
height: 70.h,
@@ -99,8 +100,9 @@ class PrescriptionDeliveryOrderSummaryPage extends StatelessWidget {
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(20.r),
- child: Image.network(
- "https://maps.googleapis.com/maps/api/staticmap?center=${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&zoom=15&size=350x165&maptype=roadmap&markers=color:red%7C${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
+ child: Utils.buildImgWithNetwork(
+ url: "https://maps.googleapis.com/maps/api/staticmap?center=${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&zoom=15&size=350x165&maptype=roadmap&markers=color:red%7C${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
+ iconColor: AppColors.blackBgColor,
fit: BoxFit.contain,
),
),
diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart
index 87d51902..802c41c2 100644
--- a/lib/presentation/prescriptions/prescription_detail_page.dart
+++ b/lib/presentation/prescriptions/prescription_detail_page.dart
@@ -125,8 +125,9 @@ class _PrescriptionDetailPageState extends State {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Image.network(
- widget.prescriptionsResponseModel.doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: widget.prescriptionsResponseModel.doctorImageURL!,
+ iconColor: AppColors.blackBgColor,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
diff --git a/lib/presentation/prescriptions/prescription_item_view.dart b/lib/presentation/prescriptions/prescription_item_view.dart
index aaac5b3c..fc607986 100644
--- a/lib/presentation/prescriptions/prescription_item_view.dart
+++ b/lib/presentation/prescriptions/prescription_item_view.dart
@@ -42,8 +42,9 @@ class PrescriptionItemView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
spacing: 8.h,
children: [
- Image.network(
- isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].imageThumbUrl!,
+ Utils.buildImgWithNetwork(
+ url: isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].imageThumbUrl!,
+ iconColor: AppColors.blackBgColor,
width: 60.h,
height: 60.h,
errorBuilder: (cxt, child, tr) {
diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart
index 1291c2da..fcb0b291 100644
--- a/lib/presentation/prescriptions/prescriptions_list_page.dart
+++ b/lib/presentation/prescriptions/prescriptions_list_page.dart
@@ -150,8 +150,9 @@ class _PrescriptionsListPageState extends State {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Image.network(
- model.patientPrescriptionOrders[index].doctorImageURL!,
+ Utils.buildImgWithNetwork(
+ url: model.patientPrescriptionOrders[index].doctorImageURL!,
+ iconColor: AppColors.blackBgColor,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
diff --git a/lib/presentation/profile_settings/accessibility_page.dart b/lib/presentation/profile_settings/accessibility_page.dart
new file mode 100644
index 00000000..b879c025
--- /dev/null
+++ b/lib/presentation/profile_settings/accessibility_page.dart
@@ -0,0 +1,476 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_export.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+import 'package:provider/provider.dart';
+
+enum VisualMode { off, invert, dim, highContrast }
+
+class AccessibilityPage extends StatefulWidget {
+ const AccessibilityPage({super.key});
+
+ @override
+ State createState() => _AccessibilityPageState();
+}
+
+class _AccessibilityPageState extends State {
+ late ProfileSettingsViewModel profileSettingsViewModel;
+ int _currentFontSizeStep = 2; // 0: Small, 1: Small-Medium, 2: Medium (default), 3: Medium-Large, 4: Large
+ VisualMode _selectedMode = VisualMode.off;
+
+ @override
+ void initState() {
+ super.initState();
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (mounted) {
+ profileSettingsViewModel = Provider.of(context, listen: false);
+ // Load saved settings from ViewModel
+ _loadSavedSettings();
+ }
+ });
+ }
+
+ void _loadSavedSettings() {
+ setState(() {
+ _currentFontSizeStep = profileSettingsViewModel.fontSizeStep;
+ _selectedMode = _visualModeFromString(profileSettingsViewModel.visualMode);
+ });
+ }
+
+ VisualMode _visualModeFromString(String mode) {
+ switch (mode) {
+ case 'off':
+ return VisualMode.off;
+ case 'invert':
+ return VisualMode.invert;
+ case 'dim':
+ return VisualMode.dim;
+ case 'highContrast':
+ return VisualMode.highContrast;
+ default:
+ return VisualMode.off;
+ }
+ }
+
+ String _visualModeToString(VisualMode mode) {
+ switch (mode) {
+ case VisualMode.off:
+ return 'off';
+ case VisualMode.invert:
+ return 'invert';
+ case VisualMode.dim:
+ return 'dim';
+ case VisualMode.highContrast:
+ return 'highContrast';
+ }
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ double _getFontSizeForStep(int step) {
+ const double mediumSize = 40.0; // Medium is baseline
+ switch (step) {
+ case 0:
+ return mediumSize * 0.5; // Small: 20.0
+ case 1:
+ return mediumSize * 0.75; // Small-Medium: 30.0
+ case 2:
+ return mediumSize; // Medium (default): 40.0
+ case 3:
+ return mediumSize * 1.5; // Medium-Large: 60.0
+ case 4:
+ return mediumSize * 1.75; // Large: 70.0
+ default:
+ return mediumSize;
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ profileSettingsViewModel = Provider.of(context, listen: false);
+
+ return CollapsingListView(
+ title: LocaleKeys.accessibility.tr(context: context),
+ isClose: true,
+ bottomChild: Container(
+ padding: EdgeInsets.all(24.w),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.r,
+ hasShadow: false,
+ ),
+ child: CustomButton(
+ height: 56.h,
+ icon: AppAssets.checkmark_icon,
+ iconColor: AppColors.whiteColor,
+ text: LocaleKeys.saveChanges.tr(context: context),
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.primaryRedColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 16.f,
+ isBold: true,
+ onPressed: () {
+ // Save accessibility settings to ViewModel
+ profileSettingsViewModel.setFontSizeStep(_currentFontSizeStep);
+ profileSettingsViewModel.setVisualMode(_visualModeToString(_selectedMode));
+
+ // Show success message
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: LocaleKeys.settingsSavedSuccessfully.tr(context: context).toText14(
+ color: AppColors.whiteColor,
+ ),
+ backgroundColor: AppColors.successColor,
+ duration: const Duration(seconds: 2),
+ ),
+ );
+
+ // Pop the page
+ Navigator.pop(context);
+ },
+ ),
+ ),
+ child: SingleChildScrollView(
+ padding: EdgeInsets.only(top: 16.h, bottom: 24.h, left: 24.w, right: 24.w),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Font Size Card
+ _buildFontSizeCard(),
+ SizedBox(height: 24.h),
+
+ // Mode for Partially Blind Card
+ _buildVisualModeCard(),
+ ],
+ ),
+ ),
+ );
+ }
+
+ Widget _buildFontSizeCard() {
+ return Container(
+ padding: EdgeInsets.all(24.w),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.r,
+ hasShadow: false,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Card Label
+ LocaleKeys.fontSize.tr(context: context).toText18(isBold: true),
+ SizedBox(height: 24.h),
+
+ // Center Aa heading that changes size
+ Container(
+ height: 70.h,
+ child: Center(
+ child: AnimatedDefaultTextStyle(
+ duration: const Duration(milliseconds: 300),
+ style: TextStyle(
+ fontSize: _getFontSizeForStep(_currentFontSizeStep),
+ fontWeight: FontWeight.bold,
+ color: AppColors.blackBgColor,
+ ),
+ child: const Text("Aa"),
+ ),
+ ),
+ ),
+ SizedBox(height: 32.h),
+
+ // Stepped slider
+ Column(
+ children: [
+ // Stack to position circles on top of the bar
+ Stack(
+ alignment: Alignment.center,
+ children: [
+ // Grey bar
+ Container(
+ height: 4.h,
+ decoration: BoxDecoration(
+ color: AppColors.greyTextColor.withValues(alpha: 0.2),
+ borderRadius: BorderRadius.circular(2.r),
+ ),
+ ),
+ // Step indicator with dots positioned on top of the bar
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: List.generate(5, (index) {
+ bool isSelected = index == _currentFontSizeStep;
+ return GestureDetector(
+ onTap: () {
+ setState(() {
+ _currentFontSizeStep = index;
+ });
+ },
+ behavior: HitTestBehavior.opaque,
+ child: Padding(
+ padding: EdgeInsets.all(8.w), // Increased tap zone
+ child: Container(
+ width: isSelected ? 20.w : 12.w,
+ height: isSelected ? 20.w : 12.w,
+ decoration: BoxDecoration(
+ color: isSelected ? AppColors.primaryRedColor : Colors.transparent,
+ shape: BoxShape.circle,
+ border: Border.all(
+ color: isSelected ? AppColors.primaryRedColor : AppColors.greyTextColor.withValues(alpha: 0.3),
+ width: 2.w,
+ ),
+ ),
+ ),
+ ),
+ );
+ }),
+ ),
+ ],
+ ),
+ SizedBox(height: 12.h),
+
+ // Labels
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ LocaleKeys.fontSizeSmall.tr(context: context).toText12(color: AppColors.greyTextColor),
+ LocaleKeys.fontSizeMedium.tr(context: context).toText12(color: AppColors.greyTextColor),
+ LocaleKeys.fontSizeLarge.tr(context: context).toText12(color: AppColors.greyTextColor),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildVisualModeCard() {
+ return Container(
+ padding: EdgeInsets.all(24.w),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.r,
+ hasShadow: false,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Card Label
+ LocaleKeys.blindModes.tr(context: context).toText18(isBold: true),
+ SizedBox(height: 24.h),
+
+ // Two columns layout
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Left Column - Radio buttons
+ Expanded(
+ flex: 2,
+ child: Column(
+ children: [
+ _buildRadioOption(VisualMode.off, LocaleKeys.offTheme.tr(context: context)),
+ SizedBox(height: 12.h),
+ _buildRadioOption(VisualMode.invert, LocaleKeys.invertTheme.tr(context: context)),
+ SizedBox(height: 12.h),
+ _buildRadioOption(VisualMode.dim, LocaleKeys.dimTheme.tr(context: context)),
+ SizedBox(height: 12.h),
+ _buildRadioOption(VisualMode.highContrast, LocaleKeys.highContrastTheme.tr(context: context)),
+ ],
+ ),
+ ),
+ SizedBox(width: 16.w),
+
+ // Right Column - Preview Card
+ Expanded(
+ flex: 3,
+ child: _buildPreviewCard(),
+ ),
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildRadioOption(VisualMode mode, String label) {
+ bool isSelected = _selectedMode == mode;
+ return GestureDetector(
+ onTap: () {
+ setState(() {
+ _selectedMode = mode;
+ });
+ },
+ child: Row(
+ children: [
+ Container(
+ width: 20.w,
+ height: 20.w,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ border: Border.all(
+ color: isSelected ? AppColors.primaryRedColor : AppColors.greyTextColor,
+ width: 2.w,
+ ),
+ color: Colors.transparent,
+ ),
+ child: isSelected
+ ? Center(
+ child: Container(
+ width: 10.w,
+ height: 10.w,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: AppColors.primaryRedColor,
+ ),
+ ),
+ )
+ : null,
+ ),
+ SizedBox(width: 8.w),
+ label.toText14(
+ isBold: isSelected,
+ color: isSelected ? AppColors.blackBgColor : AppColors.greyTextColor,
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildPreviewCard() {
+ // Always build preview content with base "Off" mode colors
+ Widget previewContent = Container(
+ padding: EdgeInsets.all(16.w),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.r,
+ isCustomShadow: [
+ BoxShadow(
+ color: const Color(0xff000000).withValues(alpha: 0.1),
+ blurRadius: 16,
+ spreadRadius: 16 * 0.1, // 10% of blur radius
+ offset: const Offset(0, 0), // Uniform shadow on all sides
+ ),
+ ],
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Top row with heading and arrow
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ LocaleKeys.cardHeading.tr(context: context).toText14(
+ isBold: true,
+ color: AppColors.blackBgColor, // Always use base color
+ ),
+ Transform.scale(
+ scaleX: Utils.appState.isArabic() ? -1 : 1,
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.arrow_forward,
+ iconColor: AppColors.blackBgColor, // Always use base color
+ ),
+ ),
+ ],
+ ),
+ SizedBox(height: 16.h),
+
+ // Price with SAR symbol
+ Row(
+ children: [
+ "1234".toText24(
+ isBold: true,
+ color: AppColors.blackBgColor, // Always use base color
+ ),
+ SizedBox(width: 4.w),
+ LocaleKeys.riyal.tr(context: context).toText14(
+ color: AppColors.blackBgColor, // Always use base color
+ ),
+ SizedBox(width: 4.w),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.saudi_riyal_icon,
+ iconColor: AppColors.blackBgColor, // Always use base color
+ width: 16.w,
+ height: 16.w,
+ ),
+ ],
+ ),
+ SizedBox(height: 16.h),
+
+ // Button - always show with base "Off" colors
+ CustomButton(
+ height: 44.h,
+ icon: AppAssets.add_icon,
+ iconColor: AppColors.whiteColor,
+ // Always use base color
+ text: LocaleKeys.buttonText.tr(context: context),
+ backgroundColor: AppColors.primaryRedColor,
+ // Always use base color
+ borderColor: AppColors.primaryRedColor,
+ // Always use base color
+ textColor: AppColors.whiteColor,
+ // Always use base color
+ fontSize: 14.f,
+ onPressed: () {},
+ ),
+ ],
+ ),
+ );
+
+ // Apply visual mode filters to preview
+ switch (_selectedMode) {
+ case VisualMode.invert:
+ return ColorFiltered(
+ colorFilter: const ColorFilter.matrix([
+ -1, 0, 0, 0, 255, // Red channel inverted
+ 0, -1, 0, 0, 255, // Green channel inverted
+ 0, 0, -1, 0, 255, // Blue channel inverted
+ 0, 0, 0, 1, 0, // Alpha channel unchanged
+ ]),
+ child: previewContent,
+ );
+
+ case VisualMode.dim:
+ return Stack(
+ children: [
+ previewContent,
+ Positioned.fill(
+ child: IgnorePointer(
+ child: Container(
+ decoration: BoxDecoration(
+ color: AppColors.blackBgColor.withValues(alpha: 0.3),
+ borderRadius: BorderRadius.circular(20.r),
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+
+ case VisualMode.highContrast:
+ return ColorFiltered(
+ colorFilter: const ColorFilter.matrix([
+ 0.2126, 0.7152, 0.0722, 0, 0, // Red channel (grayscale)
+ 0.2126, 0.7152, 0.0722, 0, 0, // Green channel (grayscale)
+ 0.2126, 0.7152, 0.0722, 0, 0, // Blue channel (grayscale)
+ 0, 0, 0, 1, 0, // Alpha channel unchanged
+ ]),
+ child: previewContent,
+ );
+
+ case VisualMode.off:
+ return previewContent;
+ }
+ }
+}
diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart
index a1b1e367..ee48b95e 100644
--- a/lib/presentation/profile_settings/profile_settings.dart
+++ b/lib/presentation/profile_settings/profile_settings.dart
@@ -23,6 +23,7 @@ import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_v
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart';
+import 'package:hmg_patient_app_new/presentation/profile_settings/accessibility_page.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/profile_picture_widget.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/update_email_widget.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/update_emergency_contact_widget.dart';
@@ -254,6 +255,10 @@ class ProfileSettingsState extends State {
);
},
),
+ 1.divider,
+ actionItem(AppAssets.bell, LocaleKeys.accessibility.tr(context: context), () {
+ Navigator.of(context).push(CustomPageRoute(page: const AccessibilityPage()));
+ }),
],
),
),
@@ -600,7 +605,13 @@ class _FamilyCardWidgetState extends State {
],
).expanded,
// Icon(Icons.qr_code, size: 56.h)
- Image.network("https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${widget.profile.responseId.toString()}", fit: BoxFit.contain, height: 56.h, width: 56.w)
+ Utils.buildImgWithNetwork(
+ url: "https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${widget.profile.responseId.toString()}",
+ iconColor: AppColors.transparent,
+ fit: BoxFit.contain,
+ height: 56.h,
+ width: 56.w,
+ )
],
),
SizedBox(height: 4.h),
diff --git a/lib/presentation/profile_settings/widgets/profile_picture_widget.dart b/lib/presentation/profile_settings/widgets/profile_picture_widget.dart
index b5aa89ee..5fe71e1e 100644
--- a/lib/presentation/profile_settings/widgets/profile_picture_widget.dart
+++ b/lib/presentation/profile_settings/widgets/profile_picture_widget.dart
@@ -128,12 +128,10 @@ class _ProfilePictureWidgetState extends State {
// Show default image (no image data or user has no uploaded image)
print('📷 Showing default avatar for user $currentPatientId');
- return Image.asset(
- defaultImage,
- key: ValueKey('default_$currentPatientId'),
+ return Utils.buildImgWithAssets(
+ icon: defaultImage,
width: 136.w,
height: 136.h,
- gaplessPlayback: true,
);
}
diff --git a/lib/presentation/radiology/radiology_ai_analysis_widget.dart b/lib/presentation/radiology/radiology_ai_analysis_widget.dart
index 8daf53e0..f22bcbd0 100644
--- a/lib/presentation/radiology/radiology_ai_analysis_widget.dart
+++ b/lib/presentation/radiology/radiology_ai_analysis_widget.dart
@@ -10,6 +10,7 @@ import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+import 'package:hmg_patient_app_new/widgets/accessibility/preserve_svg_colors.dart';
class RadiologyAiAnalysisWidget extends StatelessWidget {
final RadiologyAiAnalysisResponse data;
@@ -47,7 +48,7 @@ class RadiologyAiAnalysisWidget extends StatelessWidget {
Container(
padding: EdgeInsets.all(8.r),
decoration: BoxDecoration(gradient: AppColors.aiLinearGradient, borderRadius: BorderRadius.circular(8.r)),
- child: SvgPicture.asset(AppAssets.aiOverView, colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn), height: 18.r, width: 18.r),
+ child: PreserveSvgColors(child: SvgPicture.asset(AppAssets.aiOverView, colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn), height: 18.r, width: 18.r)),
),
],
),
diff --git a/lib/presentation/radiology/radiology_orders_page.dart b/lib/presentation/radiology/radiology_orders_page.dart
index e8c1cedc..3ff500db 100644
--- a/lib/presentation/radiology/radiology_orders_page.dart
+++ b/lib/presentation/radiology/radiology_orders_page.dart
@@ -401,8 +401,9 @@ class _RadiologyOrdersPageState extends State {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- Image.network(
- group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ Utils.buildImgWithNetwork(
+ url: group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ iconColor: AppColors.transparent,
width: 24.w,
height: 24.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/rate_appointment/rate_appointment_clinic.dart b/lib/presentation/rate_appointment/rate_appointment_clinic.dart
index e7e29f67..c8aedea8 100644
--- a/lib/presentation/rate_appointment/rate_appointment_clinic.dart
+++ b/lib/presentation/rate_appointment/rate_appointment_clinic.dart
@@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_rating_view_model.dart';
@@ -96,7 +96,13 @@ class _RateAppointmentClinicState extends State {
});
},
iconSize: 35,
- icon: SvgPicture.asset('assets/images/svg/rate_${index + 1}.svg', colorFilter: getColors(rating)),
+ icon: Utils.buildSvgWithAssets(
+ icon: 'assets/images/svg/rate_${index + 1}.svg',
+ iconColor: getRatingColor(rating),
+ width: 35,
+ height: 35,
+ applyThemeColor: false,
+ ),
),
)
: IconButton(
@@ -106,7 +112,12 @@ class _RateAppointmentClinicState extends State {
});
},
iconSize: 35,
- icon: SvgPicture.asset('assets/images/svg/rate_${index + 1}.svg'),
+ icon: Utils.buildSvgWithAssets(
+ icon: 'assets/images/svg/rate_${index + 1}.svg',
+ width: 35,
+ height: 35,
+ applyThemeColor: false,
+ ),
),
),
],
@@ -181,6 +192,23 @@ class _RateAppointmentClinicState extends State {
);
}
+ Color getRatingColor(int rating) {
+ switch (rating) {
+ case 5:
+ return AppColors.bgGreenColor;
+ case 4:
+ return Colors.greenAccent;
+ case 3:
+ return AppColors.warningLightColor;
+ case 2:
+ return Colors.orange;
+ case 1:
+ return AppColors.primaryRedColor;
+ default:
+ return AppColors.greyColor;
+ }
+ }
+
ColorFilter getColors(int rating){
switch(rating){
diff --git a/lib/presentation/rate_appointment/widget/doctor_row.dart b/lib/presentation/rate_appointment/widget/doctor_row.dart
index 2a139d05..09b6c134 100644
--- a/lib/presentation/rate_appointment/widget/doctor_row.dart
+++ b/lib/presentation/rate_appointment/widget/doctor_row.dart
@@ -9,6 +9,9 @@ import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'dart:ui' as ui;
+import '../../../core/utils/utils.dart';
+import '../../../theme/colors.dart';
+
class BuildDoctorRow extends StatelessWidget {
bool isForClinic = false;
AppointmentDetails? appointmentDetails;
@@ -21,8 +24,9 @@ class BuildDoctorRow extends StatelessWidget {
return Padding(padding: EdgeInsets.all(16),child:Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.network(
- isForClinic ? 'https://hmgwebservices.com/Images/Hospitals/${appointmentDetails!.projectID}.jpg' : appointmentDetails!.doctorImageURL ,
+ Utils.buildImgWithNetwork(
+ url: isForClinic ? 'https://hmgwebservices.com/Images/Hospitals/${appointmentDetails!.projectID}.jpg' : appointmentDetails!.doctorImageURL ,
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/smartwatches/smartwatch_home_page.dart b/lib/presentation/smartwatches/smartwatch_home_page.dart
index 7367af54..3bd8e9f5 100644
--- a/lib/presentation/smartwatches/smartwatch_home_page.dart
+++ b/lib/presentation/smartwatches/smartwatch_home_page.dart
@@ -81,7 +81,7 @@ class SmartwatchHomePage extends StatelessWidget {
),
child: Column(
children: [
- Image.asset("assets/images/png/smartwatches/apple-watch-5.jpg", width: 136.h, height: 136.h).paddingSymmetrical(24.w, 8.h),
+ Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/apple-watch-5.jpg", width: 136.h, height: 136.h).paddingSymmetrical(24.w, 8.h),
"Apple Watch".needTranslation.toText16(isBold: true),
CustomButton(
text: LocaleKeys.selectSmartWatch.tr(context: context),
@@ -115,7 +115,7 @@ class SmartwatchHomePage extends StatelessWidget {
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: Column(
children: [
- Image.asset("assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", fit: BoxFit.contain, width: 136.w, height: 136.h)
+ Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", fit: BoxFit.contain, width: 136.w, height: 136.h)
.paddingSymmetrical(24.w, 8.h),
"Samsung Watch".needTranslation.toText16(isBold: true),
CustomButton(
@@ -153,7 +153,7 @@ class SmartwatchHomePage extends StatelessWidget {
),
child: Column(
children: [
- Image.asset("assets/images/png/smartwatches/Huawei_Watch.png", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h),
+ Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/Huawei_Watch.png", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h),
"Huawei Watch".needTranslation.toText16(isBold: true),
CustomButton(
text: LocaleKeys.selectSmartWatch.tr(context: context),
@@ -187,7 +187,7 @@ class SmartwatchHomePage extends StatelessWidget {
),
child: Column(
children: [
- Image.asset("assets/images/png/smartwatches/Whoop_Watch.png", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h),
+ Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/Whoop_Watch.png", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h),
"Whoop Watch".needTranslation.toText16(isBold: true),
CustomButton(
text: LocaleKeys.selectSmartWatch.tr(context: context),
diff --git a/lib/presentation/smartwatches/smartwatch_instructions_page.dart b/lib/presentation/smartwatches/smartwatch_instructions_page.dart
index a4f6c0c0..7c0d0b97 100644
--- a/lib/presentation/smartwatches/smartwatch_instructions_page.dart
+++ b/lib/presentation/smartwatches/smartwatch_instructions_page.dart
@@ -48,8 +48,8 @@ class SmartwatchInstructionsPage extends StatelessWidget {
mainAxisSize: MainAxisSize.max,
spacing: 18.h,
children: [
- Image.asset(
- smartwatchDetails.watchIcon,
+ Utils.buildImgWithAssets(
+ icon: smartwatchDetails.watchIcon,
fit: BoxFit.contain,
height: 280.h,
width: 280.w,
diff --git a/lib/presentation/smartwatches/widgets/health_metric_card.dart b/lib/presentation/smartwatches/widgets/health_metric_card.dart
index 023f41b7..53ad4705 100644
--- a/lib/presentation/smartwatches/widgets/health_metric_card.dart
+++ b/lib/presentation/smartwatches/widgets/health_metric_card.dart
@@ -1,11 +1,11 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
import 'package:health/health.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/widgets/health_metric.dart';
@@ -53,12 +53,12 @@ class HealthMetricCard extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- SvgPicture.asset(
- metric.svgIcon,
+ Utils.buildSvgWithAssets(
+ icon: metric.svgIcon,
height: 30.h,
width: 30.h,
fit: BoxFit.contain,
- // color: color,
+ applyThemeColor: false,
),
// Icon(
// metric.icon,
diff --git a/lib/presentation/symptoms_checker/widgets/interactive_body_widget.dart b/lib/presentation/symptoms_checker/widgets/interactive_body_widget.dart
index ee2370d1..a32709f9 100644
--- a/lib/presentation/symptoms_checker/widgets/interactive_body_widget.dart
+++ b/lib/presentation/symptoms_checker/widgets/interactive_body_widget.dart
@@ -2,6 +2,8 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/organ_model.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/organ_dot_widget.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/organ_tooltip_widget.dart';
@@ -113,11 +115,21 @@ class _InteractiveBodyWidgetState extends State {
children: [
// Body image
Positioned.fill(
- child: Image.asset(
- widget.bodyImageAsset,
- fit: BoxFit.fill,
- color: widget.isBodyHidden ? Colors.black.withValues(alpha: 0.5) : null,
- ),
+ child: widget.isBodyHidden
+ ? ColorFiltered(
+ colorFilter: ColorFilter.mode(
+ Colors.black.withValues(alpha: 0.5),
+ BlendMode.darken,
+ ),
+ child: Utils.buildImgWithAssets(
+ icon: widget.bodyImageAsset,
+ fit: BoxFit.fill,
+ ),
+ )
+ : Utils.buildImgWithAssets(
+ icon: widget.bodyImageAsset,
+ fit: BoxFit.fill,
+ ),
),
// Organ dots
diff --git a/lib/presentation/tele_consultation/zoom/call_screen.dart b/lib/presentation/tele_consultation/zoom/call_screen.dart
index 82ae6332..64c6c471 100644
--- a/lib/presentation/tele_consultation/zoom/call_screen.dart
+++ b/lib/presentation/tele_consultation/zoom/call_screen.dart
@@ -1779,7 +1779,7 @@ class _CallScreenState extends State {
children: [
IconButton(
onPressed: onPressAudio,
- icon: isMuted.value ? Image.asset("assets/images/png/zoom/unmute@2x.png") : Image.asset("assets/images/png/zoom/mute@2x.png"),
+ icon: isMuted.value ? Utils.buildImgWithAssets(icon: "assets/images/png/zoom/unmute@2x.png") : Utils.buildImgWithAssets(icon: "assets/images/png/zoom/mute@2x.png"),
iconSize: circleButtonSize,
tooltip: isMuted.value == true ? "Unmute" : "Mute",
),
@@ -1791,7 +1791,7 @@ class _CallScreenState extends State {
IconButton(
onPressed: onPressVideo,
iconSize: circleButtonSize,
- icon: isVideoOn.value ? Image.asset("assets/images/png/zoom/video-off@2x.png") : Image.asset("assets/images/png/zoom/video-on@2x.png"),
+ icon: isVideoOn.value ? Utils.buildImgWithAssets(icon: "assets/images/png/zoom/video-off@2x.png") : Utils.buildImgWithAssets(icon: "assets/images/png/zoom/video-on@2x.png"),
),
Column(
children: [
diff --git a/lib/presentation/todo_section/ancillary_order_payment_page.dart b/lib/presentation/todo_section/ancillary_order_payment_page.dart
index e48adeeb..8cdd0c82 100644
--- a/lib/presentation/todo_section/ancillary_order_payment_page.dart
+++ b/lib/presentation/todo_section/ancillary_order_payment_page.dart
@@ -107,7 +107,7 @@ class _AncillaryOrderPaymentPageState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(AppAssets.mada, width: 50.h, height: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mada, width: 50.h, height: 50.h),
SizedBox(height: 16.h),
LocaleKeys.mada.tr(context: context).toText16(isBold: true).toShimmer2(isShow: todoVM.isProcessingPayment),
],
@@ -177,9 +177,9 @@ class _AncillaryOrderPaymentPageState extends State {
children: [
Row(
children: [
- Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.visa, width: 50.h, height: 50.h),
SizedBox(width: 8.h),
- Image.asset(AppAssets.mastercard, width: 40.h, height: 40.h),
+ Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h),
],
).toShimmer2(isShow: todoVM.isProcessingPayment),
SizedBox(height: 16.h),
diff --git a/lib/presentation/todo_section/ancillary_procedures_details_page.dart b/lib/presentation/todo_section/ancillary_procedures_details_page.dart
index 65e1bdaf..fdcdad9a 100644
--- a/lib/presentation/todo_section/ancillary_procedures_details_page.dart
+++ b/lib/presentation/todo_section/ancillary_procedures_details_page.dart
@@ -224,8 +224,8 @@ class _AncillaryOrderDetailsListState extends State {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(
- gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
+ Utils.buildImgWithAssets(
+ icon: gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
width: 56.w,
height: 56.h,
),
diff --git a/lib/presentation/todo_section/widgets/ancillary_orders_list.dart b/lib/presentation/todo_section/widgets/ancillary_orders_list.dart
index 627642ef..cc5bbbb6 100644
--- a/lib/presentation/todo_section/widgets/ancillary_orders_list.dart
+++ b/lib/presentation/todo_section/widgets/ancillary_orders_list.dart
@@ -138,8 +138,9 @@ class AncillaryOrderCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (!isLoading) ...[
- Image.network(
- "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ Utils.buildImgWithNetwork(
+ url: "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
+ iconColor: AppColors.transparent,
width: 63.h,
height: 63.h,
fit: BoxFit.cover,
diff --git a/lib/presentation/vital_sign/vital_sign_page.dart b/lib/presentation/vital_sign/vital_sign_page.dart
index fb3f1a58..826c3971 100644
--- a/lib/presentation/vital_sign/vital_sign_page.dart
+++ b/lib/presentation/vital_sign/vital_sign_page.dart
@@ -235,12 +235,11 @@ class _VitalSignPageState extends State {
child: Stack(
fit: StackFit.expand,
children: [
- Image.asset(
- getIt.get().getAuthenticatedUser()?.gender == 1
+ Utils.buildImgWithAssets(
+ icon: getIt.get().getAuthenticatedUser()?.gender == 1
? AppAssets.bmiFullBody
: AppAssets.bmiFullBodyFemale,
fit: BoxFit.cover,
- alignment: Alignment.topCenter,
),
Align(
alignment: Alignment.bottomCenter,
diff --git a/lib/widgets/buttons/default_button.dart b/lib/widgets/buttons/default_button.dart
index f6a47a1c..9d62ff6f 100644
--- a/lib/widgets/buttons/default_button.dart
+++ b/lib/widgets/buttons/default_button.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
-import 'package:flutter_svg/svg.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
extension WithContainer on Widget {
@@ -63,7 +63,7 @@ class DefaultButton extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (iconData != null) Icon(iconData, color: textColor),
- if (svgIcon != null) SvgPicture.asset(svgIcon ?? ""),
+ if (svgIcon != null) Utils.buildSvgWithAssets(icon: svgIcon ?? "", applyThemeColor: false),
if (!isTextExpanded)
Padding(
padding: EdgeInsets.only(
diff --git a/lib/widgets/chip/app_custom_chip_widget.dart b/lib/widgets/chip/app_custom_chip_widget.dart
index 734ca2cc..00bf6df1 100644
--- a/lib/widgets/chip/app_custom_chip_widget.dart
+++ b/lib/widgets/chip/app_custom_chip_widget.dart
@@ -78,7 +78,7 @@ class AppCustomChipWidget extends StatelessWidget {
? Chip(
avatar: icon.isNotEmpty
? isIconPNG
- ? Image.asset(icon, width: iconS, height: iconS)
+ ? Utils.buildImgWithAssets(icon: icon, width: iconS, height: iconS)
: Utils.buildSvgWithAssets(
icon: icon,
width: iconS,
diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart
index 6ab2b439..4074bd19 100644
--- a/lib/widgets/image_picker.dart
+++ b/lib/widgets/image_picker.dart
@@ -79,7 +79,7 @@ class ImageOptions {
}
},
onFilesTap: () async {
- FilePickerResult? result = await FilePicker.platform.pickFiles(
+ FilePickerResult? result = await FilePicker.pickFiles(
type: FileType.custom,
allowedExtensions: [
'jpg',
diff --git a/lib/widgets/map/location_map_widget.dart b/lib/widgets/map/location_map_widget.dart
index da17b486..f3b57aa3 100644
--- a/lib/widgets/map/location_map_widget.dart
+++ b/lib/widgets/map/location_map_widget.dart
@@ -12,6 +12,8 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:map_launcher/map_launcher.dart';
+import '../../core/utils/utils.dart';
+
/// A reusable location map widget that displays a static map with address and directions button
/// Can be used in any review screen (HHC, CMC, etc.)
class LocationMapWidget extends StatelessWidget {
@@ -127,24 +129,10 @@ class LocationMapWidget extends StatelessWidget {
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24.r),
- child: Image.network(
- staticMapUrl,
+ child: Utils.buildImgWithNetwork(
+ url: staticMapUrl,
+ iconColor: AppColors.transparent,
fit: BoxFit.contain,
- loadingBuilder: (context, child, loadingProgress) {
- if (loadingProgress == null) return child;
- return Container(
- height: 165.h,
- decoration: BoxDecoration(
- color: AppColors.bgScaffoldColor,
- borderRadius: BorderRadius.circular(24.r),
- ),
- child: Center(
- child: CircularProgressIndicator(
- color: AppColors.primaryRedColor,
- ),
- ),
- );
- },
errorBuilder: (context, error, stackTrace) {
return Container(
height: 165.h,
diff --git a/lib/widgets/media_viewer/full_screen_image_viewer.dart b/lib/widgets/media_viewer/full_screen_image_viewer.dart
index 0fb92f0e..ae6d4802 100644
--- a/lib/widgets/media_viewer/full_screen_image_viewer.dart
+++ b/lib/widgets/media_viewer/full_screen_image_viewer.dart
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class FullScreenImageViewer extends StatelessWidget {
@@ -22,8 +22,8 @@ class FullScreenImageViewer extends StatelessWidget {
body: Center(
child: InteractiveViewer(
child: isSvg
- ? SvgPicture.asset(path, width: double.infinity, fit: BoxFit.contain)
- : Image.asset(width: double.infinity, path, fit: BoxFit.contain),
+ ? Utils.buildSvgWithAssets(icon: path, width: double.infinity, fit: BoxFit.contain, applyThemeColor: false)
+ : Utils.buildImgWithAssets(icon: path, width: double.infinity, fit: BoxFit.contain),
),
),
);
diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart
index 0d6c2866..8f983156 100644
--- a/lib/widgets/nfc/nfc_reader_sheet.dart
+++ b/lib/widgets/nfc/nfc_reader_sheet.dart
@@ -3,9 +3,9 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
-import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@@ -93,9 +93,10 @@ class _NfcLayoutState extends State {
SizedBox(
height: 30,
),
- SvgPicture.asset(
- "assets/images/nfc/contactless.svg",
+ Utils.buildSvgWithAssets(
+ icon: "assets/images/nfc/contactless.svg",
height: MediaQuery.of(context).size.width / 3,
+ applyThemeColor: false,
),
SizedBox(
height: 30,
@@ -161,8 +162,8 @@ class _NfcLayoutState extends State {
SizedBox(
height: 30,
),
- Image.asset(
- "assets/images/nfc/ic_done.png",
+ Utils.buildImgWithAssets(
+ icon: "assets/images/nfc/ic_done.png",
height: MediaQuery.of(context).size.width / 3,
),
SizedBox(
diff --git a/lib/widgets/user_avatar_widget.dart b/lib/widgets/user_avatar_widget.dart
index 84499efa..5528531d 100644
--- a/lib/widgets/user_avatar_widget.dart
+++ b/lib/widgets/user_avatar_widget.dart
@@ -4,6 +4,7 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
class UserAvatarWidget extends StatelessWidget {
final double width;
@@ -84,11 +85,11 @@ class UserAvatarWidget extends StatelessWidget {
// If decoding fails, show default image
return ClipRRect(
borderRadius: BorderRadius.circular(effectiveBorderRadius),
- child: Image.asset(
- defaultImage,
+ child: Utils.buildImgWithAssets(
+ icon: defaultImage,
width: width,
height: height,
- fit: fit,
+ fit: fit ?? BoxFit.cover,
),
);
}
@@ -97,11 +98,11 @@ class UserAvatarWidget extends StatelessWidget {
// Show default image with rounded corners
return ClipRRect(
borderRadius: BorderRadius.circular(effectiveBorderRadius),
- child: Image.asset(
- defaultImage,
+ child: Utils.buildImgWithAssets(
+ icon: defaultImage,
width: width,
height: height,
- fit: fit,
+ fit: fit ?? BoxFit.cover,
),
);
}