profile picture fixed.

dev_sultan
Sultan khan 9 hours ago
parent a0c1e1ffb3
commit 460e7cdcea

@ -33,6 +33,7 @@ import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_mode
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
@ -52,7 +53,6 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
import '../insurance/insurance_view_model.dart';
import '../profile_settings/profile_settings_repo.dart';
import 'models/request_models/get_user_mobile_device_data.dart';
import 'models/request_models/insert_patient_mobile_deviceinfo.dart';
import 'models/request_models/patient_insert_device_imei_request.dart';
@ -1824,6 +1824,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setAppAuthToken = "";
_appState.setUserBloodGroup = "";
_appState.clearProfileImageCache(); // Clear profile image cache
GetIt.instance<ProfileSettingsViewModel>().clearProfileImageCache();
_appState.setSuperUserID = null;
_appState.setIsChildLoggedIn = false;
_appState.setFamilyFileTokenID = "";
@ -1877,43 +1878,16 @@ class AuthenticationViewModel extends ChangeNotifier {
try {
log("Fetching profile image for patient ID: $patientID");
// IMPORTANT: Clear old cache BEFORE fetching new image
// This ensures old data is removed immediately
// Clear old cache before fetching new image
_appState.clearProfileImageCache();
log("🧹 Cleared profile image cache before fetch");
final profileSettingsRepo = GetIt.instance<ProfileSettingsRepo>();
final result = await profileSettingsRepo.getProfileImage(patientID: patientID);
final profileSettingsVM = GetIt.instance<ProfileSettingsViewModel>();
profileSettingsVM.clearProfileImageCache();
result.fold(
(failure) {
// Silently fail - profile image is optional
log("Failed to fetch profile image: ${failure.message}");
// Ensure cache is cleared even on failure
_appState.setProfileImageData = null;
},
(apiResponse) {
if (apiResponse.data != null && apiResponse.data['Patient_GetProfileImageDataList'] != null) {
var imageList = apiResponse.data['Patient_GetProfileImageDataList'];
if (imageList is List && imageList.isNotEmpty) {
String? imageData = imageList[0]['ImageData'];
if (imageData != null && imageData.isNotEmpty) {
// Set new profile image data - this will update cache and notify all listeners
_appState.setProfileImageData = imageData;
log("✅ Profile image loaded and cached successfully for patient: $patientID");
} else {
log("⚠️ Profile image data is empty for patient: $patientID");
_appState.setProfileImageData = null;
}
} else {
log("⚠️ Profile image list is empty for patient: $patientID");
_appState.setProfileImageData = null;
}
} else {
log("⚠️ No profile image data in response for patient: $patientID");
_appState.setProfileImageData = null;
}
},
await profileSettingsVM.getProfileImage(
patientID: patientID,
forceRefresh: true,
);
} catch (e) {
log("❌ Error fetching profile image: $e");

@ -3,6 +3,7 @@ import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
@ -105,7 +106,7 @@ class ProfilePictureViewModel extends ChangeNotifier {
_cachedImageDataHash = null;
_selectedImage = null;
notifyListeners();
safeNotifyListeners();
// Load new user's profile image
_profileSettingsViewModel.getProfileImage(
@ -113,14 +114,25 @@ class ProfilePictureViewModel extends ChangeNotifier {
forceRefresh: true,
onSuccess: (data) {
_tryCacheExistingImage();
notifyListeners();
safeNotifyListeners();
},
onError: (error) {
notifyListeners();
safeNotifyListeners();
},
);
}
/// Safely dispatch notifyListeners to avoid setState() or markNeedsBuild() during build
void safeNotifyListeners() {
if (WidgetsBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
WidgetsBinding.instance.addPostFrameCallback((_) {
notifyListeners();
});
} else {
notifyListeners();
}
}
/// Load profile image from API
void loadProfileImage({bool forceRefresh = false}) {
// Check if profile image is already loaded in AppState (skip if forcing refresh)

@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
@ -351,15 +352,21 @@ class ProfileSettingsViewModel extends ChangeNotifier {
Function(String)? onError,
bool forceRefresh = false, // Add flag to force refresh
}) async {
if (isProfileImageLoading && !forceRefresh) {
print('⏳ Profile image is already loading, skipping duplicate call');
return;
}
print('🌐 Fetching profile image from API for patient: $patientID (forceRefresh: $forceRefresh)');
// IMPORTANT: Always clear old data BEFORE fetching
// Do NOT use cached data - always fetch fresh from API
profileImageData = null;
GetIt.instance<AppState>().setProfileImageData = null;
isProfileImageLoading = true;
profileImageError = null;
notifyListeners(); // Notify to show loading state
safeNotifyListeners(); // Notify to show loading state
final result = await profileSettingsRepo.getProfileImage(patientID: patientID);
@ -371,8 +378,9 @@ class ProfileSettingsViewModel extends ChangeNotifier {
// Ensure data is cleared on failure
profileImageData = null;
GetIt.instance<AppState>().setProfileImageData = null;
notifyListeners();
safeNotifyListeners();
if (onError != null) {
onError(failure.message);
}
@ -387,32 +395,47 @@ class ProfileSettingsViewModel extends ChangeNotifier {
profileImageData = imageList[0]['ImageData'];
if (profileImageData != null && profileImageData!.isNotEmpty) {
// ONLY store in ViewModel - AppState will be updated separately by auth flow
GetIt.instance<AppState>().setProfileImageData = profileImageData;
print('✅ Profile image loaded from API (length: ${profileImageData!.length})');
} else {
profileImageData = null;
GetIt.instance<AppState>().setProfileImageData = null;
print('⚠️ Profile image data is empty in API response');
}
} else {
profileImageData = null;
GetIt.instance<AppState>().setProfileImageData = null;
print('⚠️ Profile image list is empty in API response');
}
} else {
profileImageData = null;
GetIt.instance<AppState>().setProfileImageData = null;
print('⚠️ No profile image data in API response');
}
notifyListeners(); // Notify to update UI with new/null data
safeNotifyListeners(); // Notify to update UI with new/null data
onSuccess?.call(response.data);
},
);
}
/// Safely dispatch notifyListeners to avoid setState() or markNeedsBuild() during build
void safeNotifyListeners() {
if (WidgetsBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
WidgetsBinding.instance.addPostFrameCallback((_) {
notifyListeners();
});
} else {
notifyListeners();
}
}
/// Clear profile image data from ViewModel
void clearProfileImageCache() {
print('🧹 Clearing profile image from ViewModel');
profileImageData = null;
notifyListeners();
GetIt.instance<AppState>().setProfileImageData = null;
safeNotifyListeners();
}
/// Sync profile image data from AppState - DISABLED

@ -150,9 +150,21 @@ class _LandingPageState extends State<LandingPage> {
await authVM.handleNewImeiRegistration(isNavigate: false);
}
if (!mounted) return;
if (appState.isAuthenticated) {
Clarity.setCustomUserId(appState.getAuthenticatedUser()!.patientId.toString());
final profileSettingsVM = context.read<ProfileSettingsViewModel>();
if (profileSettingsVM.profileImageData == null &&
(appState.getProfileImageData == null || appState.getProfileImageData!.isEmpty) &&
!profileSettingsVM.isProfileImageLoading) {
final patientID = appState.getAuthenticatedUser()?.patientId;
if (patientID != null) {
profileSettingsVM.getProfileImage(patientID: patientID);
}
}
// habibWalletVM.initHabibWalletProvider();
// Wallet & Lakum data are fetched lazily when the user unhides the values.
// habibWalletVM.getPatientBalanceAmount();

@ -30,11 +30,12 @@ class _ProfilePictureWidgetState extends State<ProfilePictureWidget> {
void initState() {
super.initState();
// Initialize view model
// Initialize view model synchronously so currentPatientId is immediately set
final profilePictureViewModel = context.read<ProfilePictureViewModel>();
profilePictureViewModel.initialize();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
final profilePictureViewModel = context.read<ProfilePictureViewModel>();
profilePictureViewModel.initialize();
profilePictureViewModel.triggerInitialLoad();
});
}
@ -42,18 +43,24 @@ class _ProfilePictureWidgetState extends State<ProfilePictureWidget> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Check for user switch
final profilePictureViewModel = context.read<ProfilePictureViewModel>();
if (profilePictureViewModel.isInitialLoadTriggered) {
profilePictureViewModel.checkForUserSwitch();
}
// Check for user switch safely after frame build to avoid markNeedsBuild during build
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
final profilePictureViewModel = context.read<ProfilePictureViewModel>();
if (profilePictureViewModel.isInitialLoadTriggered) {
profilePictureViewModel.checkForUserSwitch();
}
});
}
@override
void didUpdateWidget(ProfilePictureWidget oldWidget) {
super.didUpdateWidget(oldWidget);
// Check for user switch
context.read<ProfilePictureViewModel>().checkForUserSwitch();
// Check for user switch safely after frame build to avoid markNeedsBuild during build
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
context.read<ProfilePictureViewModel>().checkForUserSwitch();
});
}
void _pickImage() {

Loading…
Cancel
Save