haroon_dev #343

Merged
Haroon6138 merged 4 commits from haroon_dev into master 2 weeks ago

@ -211,10 +211,8 @@ class ApiClientImp implements ApiClient {
} }
// body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
// body['PatientID'] = 1018977; // body['PatientID'] = 2122445;
// body['PatientID'] = 89754444;
// body['PatientID'] = 53320; // body['PatientID'] = 53320;
// body['PatientID'] = 4769748;
// body['PatientTypeID'] = 1; // body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0; // body['PatientOutSA'] = 0;
// body['SessionID'] = "45786230487560q"; // body['SessionID'] = "45786230487560q";

@ -5,7 +5,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class ApiConsts { class ApiConsts {
static const maxSmallScreen = 660; static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat; static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
@ -301,7 +301,7 @@ class ApiConsts {
static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations"; static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations";
// ************ static values for Api **************** // ************ static values for Api ****************
static final double appVersionID = 21.5; static final double appVersionID = 21.6;
// static final double appVersionID = 50.7; // static final double appVersionID = 50.7;
static final int appChannelId = 3; static final int appChannelId = 3;

@ -84,6 +84,7 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/services/notification_service.dart'; import 'package:hmg_patient_app_new/services/notification_service.dart';
import 'package:hmg_patient_app_new/services/permission_service.dart'; import 'package:hmg_patient_app_new/services/permission_service.dart';
import 'package:hmg_patient_app_new/core/services/turnstile_service.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart';
import 'package:local_auth/local_auth.dart'; import 'package:local_auth/local_auth.dart';
@ -155,6 +156,7 @@ class AppDependencies {
); );
getIt.registerLazySingleton<PermissionService>(() => PermissionService()); getIt.registerLazySingleton<PermissionService>(() => PermissionService());
getIt.registerLazySingleton<TurnstileService>(() => TurnstileService(getIt<LoggerService>()));
// Repositories // Repositories
getIt.registerLazySingleton<CommonRepo>(() => CommonRepoImp(loggerService: getIt())); getIt.registerLazySingleton<CommonRepo>(() => CommonRepoImp(loggerService: getIt()));
@ -255,7 +257,8 @@ class AppDependencies {
dialogService: getIt(), dialogService: getIt(),
appState: getIt(), appState: getIt(),
errorHandlerService: getIt(), errorHandlerService: getIt(),
localAuthService: getIt()), localAuthService: getIt(),
turnstileService: getIt()),
); );
getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel( getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel(

@ -0,0 +1,56 @@
import 'dart:async';
import 'package:cloudflare_turnstile/cloudflare_turnstile.dart';
import 'package:flutter/foundation.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
/// Service to handle Cloudflare Turnstile captcha verification
class TurnstileService {
final LoggerService _loggerService;
// Replace with your Cloudflare Turnstile site key
static const String _siteKey = '0x4AAAAAAAkmbvEy63pcxBBt';
TurnstileService(this._loggerService);
/// Get Turnstile token using invisible mode
/// Returns the token on success, null on failure
Future<String?> getTurnstileToken() async {
// Initialize an instance of invisible Cloudflare Turnstile with your site key
final turnstile = CloudflareTurnstile.invisible(
siteKey: _siteKey,
);
try {
// Get the Turnstile token
final token = await turnstile.getToken();
_loggerService.logInfo('Turnstile token retrieved successfully');
return token; // Return the token upon success
} on TurnstileException catch (e) {
// Handle Turnstile failure
_loggerService.logError('Turnstile challenge failed: ${e.message}');
if (kDebugMode) {
print('Challenge failed: ${e.message}');
}
} catch (e) {
// Handle any other exceptions
_loggerService.logError('Unexpected error during Turnstile challenge: $e');
if (kDebugMode) {
print('Unexpected error: $e');
}
} finally {
// Ensure the Turnstile instance is properly disposed of
turnstile.dispose();
}
// Return null if the token couldn't be generated
return null;
}
/// Get the site key for Turnstile widget
String getSiteKey() => _siteKey;
/// Validate if Turnstile is properly configured
bool isConfigured() {
return _siteKey.isNotEmpty && _siteKey != '0x4AAAAAAAkmbvEy63pcxBBt';
}
}

@ -147,6 +147,9 @@ class AuthenticationRepoImp implements AuthenticationRepo {
bool isRegister = false, bool isRegister = false,
bool isFormFamilyFile = false, bool isFormFamilyFile = false,
}) async { }) async {
int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1; int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1;
sendActivationCodeReq.patientOutSA = isOutKsa; sendActivationCodeReq.patientOutSA = isOutKsa;
sendActivationCodeReq.isDentalAllowedBackend = false; sendActivationCodeReq.isDentalAllowedBackend = false;

@ -42,6 +42,7 @@ import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart'; import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/core/services/turnstile_service.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
@ -60,6 +61,7 @@ class AuthenticationViewModel extends ChangeNotifier {
final DialogService _dialogService; final DialogService _dialogService;
final NavigationService _navigationService; final NavigationService _navigationService;
final LocalAuthService _localAuthService; final LocalAuthService _localAuthService;
final TurnstileService _turnstileService;
AuthenticationViewModel({ AuthenticationViewModel({
required AppState appState, required AppState appState,
@ -69,12 +71,14 @@ class AuthenticationViewModel extends ChangeNotifier {
required NavigationService navigationService, required NavigationService navigationService,
required CacheService cacheService, required CacheService cacheService,
required LocalAuthService localAuthService, required LocalAuthService localAuthService,
required TurnstileService turnstileService,
}) : _navigationService = navigationService, }) : _navigationService = navigationService,
_dialogService = dialogService, _dialogService = dialogService,
_errorHandlerService = errorHandlerService, _errorHandlerService = errorHandlerService,
_appState = appState, _appState = appState,
_authenticationRepo = authenticationRepo, _authenticationRepo = authenticationRepo,
_localAuthService = localAuthService {} _localAuthService = localAuthService,
_turnstileService = turnstileService {}
final TextEditingController nationalIdController = TextEditingController(), final TextEditingController nationalIdController = TextEditingController(),
phoneNumberController = TextEditingController(), phoneNumberController = TextEditingController(),
dobController = TextEditingController(), dobController = TextEditingController(),
@ -974,6 +978,15 @@ class AuthenticationViewModel extends ChangeNotifier {
// TODO: GET APP SMS SIGNATURE HERE // TODO: GET APP SMS SIGNATURE HERE
request.sMSSignature = await getSignature(); request.sMSSignature = await getSignature();
// Get Turnstile token if configured
final turnstileToken = await _turnstileService.getTurnstileToken();
if (turnstileToken != null) {
request.turnstileToken = turnstileToken;
} else {
request.turnstileToken = "";
}
if (isNeedLoading) { if (isNeedLoading) {
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
} }

@ -30,6 +30,7 @@ class SendActivationRequest {
int? status; int? status;
int? familyRegionID; int? familyRegionID;
bool? isPatientExcluded; bool? isPatientExcluded;
String? turnstileToken;
SendActivationRequest( SendActivationRequest(
{this.patientMobileNumber, {this.patientMobileNumber,
@ -62,7 +63,8 @@ class SendActivationRequest {
this.responseID, this.responseID,
this.status, this.status,
this.familyRegionID, this.familyRegionID,
this.isPatientExcluded}); this.isPatientExcluded,
this.turnstileToken});
SendActivationRequest.fromJson(Map<String, dynamic> json) { SendActivationRequest.fromJson(Map<String, dynamic> json) {
patientMobileNumber = json['PatientMobileNumber']; patientMobileNumber = json['PatientMobileNumber'];
@ -96,6 +98,7 @@ class SendActivationRequest {
status = json['Status']; status = json['Status'];
familyRegionID = json['FamilyRegionID']; familyRegionID = json['FamilyRegionID'];
isPatientExcluded = json['IsPatientExcluded']; isPatientExcluded = json['IsPatientExcluded'];
turnstileToken = json['TurnstileToken'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -135,6 +138,9 @@ class SendActivationRequest {
data['Status'] = status; data['Status'] = status;
data['FamilyRegionID'] = familyRegionID; data['FamilyRegionID'] = familyRegionID;
data['IsPatientExcluded'] = isPatientExcluded; data['IsPatientExcluded'] = isPatientExcluded;
if (turnstileToken != null) {
data['TurnstileToken'] = turnstileToken;
}
return data; return data;
} }
} }

@ -12,6 +12,7 @@ import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_p
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_response_model.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
class ContactUsViewModel extends ChangeNotifier { class ContactUsViewModel extends ChangeNotifier {
@ -308,7 +309,15 @@ class ContactUsViewModel extends ChangeNotifier {
final result = await contactUsRepo.insertCOCItem(requestInsertCOCItem: requestInsertCOCItem, patientSelectedAppointment: patientFeedbackSelectedAppointment); final result = await contactUsRepo.insertCOCItem(requestInsertCOCItem: requestInsertCOCItem, patientSelectedAppointment: patientFeedbackSelectedAppointment);
result.fold( result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure), (failure) async {
LoaderBottomSheet.hideLoader();
await errorHandlerService.handleError(failure: failure);
},
// (failure) async {
// if(onError != null) {
// onError(failure.toString());
// }
// },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});

@ -53,7 +53,7 @@ abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointmentsForTimeLine(); Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointmentsForTimeLine();
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientDoctorsList(); Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientDoctorsList({bool isTop8 = false});
Future<Either<Failure, GenericApiModel<List<GetFavoriteDoctorsListModel>>>> getFavouriteDoctorsList(); Future<Either<Failure, GenericApiModel<List<GetFavoriteDoctorsListModel>>>> getFavouriteDoctorsList();
@ -514,11 +514,12 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientDoctorsList() async { Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientDoctorsList({bool isTop8 = false}) async {
Map<String, dynamic> mapDevice = { Map<String, dynamic> mapDevice = {
"Top": 0, "Top": 0,
"beforeDays": 0, "beforeDays": 0,
"exludType": 4, "exludType": 4,
"IsTop8": isTop8,
}; };
try { try {

@ -211,6 +211,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
setIsMyDoctorsDataToBeLoaded(bool val) {
isMyDoctorsDataToBeLoaded = val;
notifyListeners();
}
setIsAppointmentDataToBeLoaded(bool val) { setIsAppointmentDataToBeLoaded(bool val) {
if (val) { if (val) {
isMyAppointmentsLoading = true; isMyAppointmentsLoading = true;
@ -675,13 +680,13 @@ class MyAppointmentsViewModel extends ChangeNotifier {
); );
} }
Future<void> getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientMyDoctors({bool isTop8 = false, Function(dynamic)? onSuccess, Function(String)? onError}) async {
if (!isMyDoctorsDataToBeLoaded) return; if (!isMyDoctorsDataToBeLoaded) return;
isPatientMyDoctorsLoading = true; isPatientMyDoctorsLoading = true;
patientMyDoctorsList.clear(); patientMyDoctorsList.clear();
notifyListeners(); notifyListeners();
final result = await myAppointmentsRepo.getPatientDoctorsList(); final result = await myAppointmentsRepo.getPatientDoctorsList(isTop8: isTop8);
result.fold( result.fold(
// (failure) async => await errorHandlerService.handleError(failure: failure), // (failure) async => await errorHandlerService.handleError(failure: failure),

@ -235,11 +235,16 @@ class PrescriptionsViewModel extends ChangeNotifier {
result.fold( result.fold(
(failure) async { (failure) async {
onError!(failure.message); if (onError != null) {
onError(failure.message);
}
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
onError!(apiResponse.errorMessage!); if (onError != null) {
onError(apiResponse.errorMessage ?? "An error occurred while fetching the prescription instructions PDF.");
}
// onError!(apiResponse.errorMessage!);
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
prescriptionInstructionsPDFLink = apiResponse.data; prescriptionInstructionsPDFLink = apiResponse.data;

@ -43,8 +43,10 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
@override @override
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
if (!myAppointmentsViewModel.isMyAppointmentsLoading) {
myAppointmentsViewModel.initAppointmentsViewModel(); myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
}
}); });
super.initState(); super.initState();
} }

@ -39,7 +39,7 @@ class _MyDoctorsPageState extends State<MyDoctorsPage> {
@override @override
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
myAppointmentsViewModel.getPatientMyDoctors(); myAppointmentsViewModel.getPatientMyDoctors(isTop8: false);
}); });
super.initState(); super.initState();
} }

@ -101,7 +101,7 @@ class AppointmentDoctorCard extends StatelessWidget {
Row( Row(
children: [ children: [
Expanded( Expanded(
child: patientAppointmentHistoryResponseModel.doctorNameObj!.toText16( child: (patientAppointmentHistoryResponseModel.doctorNameObj ?? "").toText16(
isBold: true, isBold: true,
isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? ""), isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? ""),
textOverflow: TextOverflow.ellipsis, textOverflow: TextOverflow.ellipsis,

@ -66,14 +66,14 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
// bookAppointmentsViewModel.getLocation(); // bookAppointmentsViewModel.getLocation();
immediateLiveCareViewModel.initImmediateLiveCare(); immediateLiveCareViewModel.initImmediateLiveCare();
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors(); getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors(isTop8: true);
getIt.get<MyAppointmentsViewModel>().getPatientFavouriteDoctors(); getIt.get<MyAppointmentsViewModel>().getPatientFavouriteDoctors();
} }
}); });
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (bookAppointmentsViewModel.selectedTabIndex == 1) { if (bookAppointmentsViewModel.selectedTabIndex == 1) {
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors(); getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors(isTop8: true);
getIt.get<MyAppointmentsViewModel>().getPatientFavouriteDoctors(); getIt.get<MyAppointmentsViewModel>().getPatientFavouriteDoctors();
showUnKnownClinicBottomSheet(); showUnKnownClinicBottomSheet();
} }
@ -166,6 +166,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 14.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 14.h),
], ],
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
myAppointmentsVM.setIsMyDoctorsDataToBeLoaded(true);
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: MyDoctorsPage(), page: MyDoctorsPage(),

@ -544,12 +544,12 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
if (selectedPaymentMethod == "TAMARA") { if (selectedPaymentMethod == "TAMARA") {
if (Platform.isAndroid) { if (Platform.isAndroid) {
Uri uri = new Uri.dataFromString(url); Uri uri = new Uri.dataFromString(url);
tamaraPaymentStatus = uri.queryParameters['status']!; tamaraPaymentStatus = uri.queryParameters['status'] ?? "";
tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!; tamaraOrderID = uri.queryParameters['AuthorizePaymentId'] ?? "";
} else { } else {
Uri uri = new Uri.dataFromString(url); Uri uri = new Uri.dataFromString(url);
tamaraPaymentStatus = uri.queryParameters['paymentStatus']!; tamaraPaymentStatus = uri.queryParameters['paymentStatus'] ?? "";
tamaraOrderID = uri.queryParameters['orderId']!; tamaraOrderID = uri.queryParameters['orderId'] ?? "";
} }
} }

File diff suppressed because one or more lines are too long

@ -181,9 +181,10 @@ class _ExpandableDescriptionText extends StatelessWidget {
static TextStyle get textStyle => TextStyle( static TextStyle get textStyle => TextStyle(
fontSize: 14.f, fontSize: 14.f,
color: AppColors.textColor, // or Colors.black87 color: AppColors.textColorLight,
fontFamily: 'Poppins', // or Colors.black87
fontWeight: FontWeight.w400, // fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
height: 1.4, height: 1.4,
letterSpacing: 0.0, letterSpacing: 0.0,
@ -199,7 +200,7 @@ class _ExpandableDescriptionText extends StatelessWidget {
final readMoreStyle = TextStyle( final readMoreStyle = TextStyle(
fontSize: 12.f, fontSize: 12.f,
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
fontFamily: 'Poppins', // fontFamily: 'Poppins',
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
); );

@ -110,7 +110,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
scheduleMicrotask(() { scheduleMicrotask(() {
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
myAppointmentsViewModel.getPatientMyDoctors(); myAppointmentsViewModel.getPatientMyDoctors(isTop8: true);
prescriptionsViewModel.initPrescriptionsViewModel(); prescriptionsViewModel.initPrescriptionsViewModel();
insuranceViewModel.initInsuranceProvider(); insuranceViewModel.initInsuranceProvider();
medicalFileViewModel.setIsPatientSickLeaveListLoading(true); medicalFileViewModel.setIsPatientSickLeaveListLoading(true);
@ -1046,6 +1046,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
).onPress(() { ).onPress(() {
// myAppointmentsViewModel.getPatientMyDoctors(); // myAppointmentsViewModel.getPatientMyDoctors();
myAppointmentsViewModel.setIsMyDoctorsDataToBeLoaded(true);
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: MyDoctorsPage(), page: MyDoctorsPage(),

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenshot_blocker/flutter_screenshot_blocker.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -20,7 +21,16 @@ class NotificationDetailsPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CollapsingListView( return ScreenshotBlockerWidget(
blockScreenshots: true, // makes this widget appear black in screenshots
detectScreenshots: true, // listen for screenshot attempts
onScreenshotDetected: (event) {
// event.type 'screenshot_taken' or 'screenshot_blocked'
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text('Screenshots are not allowed!')),
// );
},
child: CollapsingListView(
title: LocaleKeys.notificationDetails.tr(), title: LocaleKeys.notificationDetails.tr(),
// trailing: IconButton( // trailing: IconButton(
// icon: Icon( // icon: Icon(
@ -43,6 +53,7 @@ class NotificationDetailsPage extends StatelessWidget {
], ],
).paddingSymmetrical(24.w, 0.h), ).paddingSymmetrical(24.w, 0.h),
), ),
),
); );
} }
@ -123,8 +134,7 @@ class NotificationDetailsPage extends StatelessWidget {
), ),
// Notification image (if MessageType is "image") // Notification image (if MessageType is "image")
if (notification.messageType != null && if (notification.messageType != null && notification.messageType!.toLowerCase() == "image")
notification.messageType!.toLowerCase() == "image")
Builder( Builder(
builder: (context) { builder: (context) {
// Try to get image URL from videoURL or messageTypeData // Try to get image URL from videoURL or messageTypeData
@ -205,10 +215,7 @@ class NotificationDetailsPage extends StatelessWidget {
), ),
child: Center( child: Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null,
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
), ),
), ),
); );
@ -249,7 +256,8 @@ ${notification.message ?? 'Notification'}
Time: ${_formatTime(notification.isSentOn)} Time: ${_formatTime(notification.isSentOn)}
Date: ${_formatDate(notification.isSentOn)} Date: ${_formatDate(notification.isSentOn)}
${notification.notificationType != null ? '\nType: ${notification.notificationType}' : ''} ${notification.notificationType != null ? '\nType: ${notification.notificationType}' : ''}
'''.trim(); '''
.trim();
await Share.share(shareText); await Share.share(shareText);
} }
@ -274,4 +282,3 @@ ${notification.notificationType != null ? '\nType: ${notification.notificationTy
} }
} }
} }

@ -61,7 +61,8 @@ class _NotificationsListPageState extends State<NotificationsListPage> {
child: ListView.builder( child: ListView.builder(
itemCount: notificationsVM.isNotificationsLoading itemCount: notificationsVM.isNotificationsLoading
? 4 ? 4
: notificationsVM.notificationsList.length + (notificationsVM.hasMoreNotifications ? 1 : 0), // : notificationsVM.notificationsList.length + (notificationsVM.hasMoreNotifications ? 1 : 0),
: notificationsVM.notificationsList.length,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsetsGeometry.zero, padding: EdgeInsetsGeometry.zero,

@ -2,8 +2,8 @@ name: hmg_patient_app_new
description: "New HMG Patient App" description: "New HMG Patient App"
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
#version: 0.0.38+37 version: 0.0.39+38
version: 0.0.7+1 #version: 0.0.8+1
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"
@ -108,6 +108,8 @@ dependencies:
clarity_flutter: 1.9.0 clarity_flutter: 1.9.0
flutter_amazonpaymentservices: ^0.0.13 flutter_amazonpaymentservices: ^0.0.13
screen_brightness: ^1.0.1 screen_brightness: ^1.0.1
flutter_screenshot_blocker: ^1.0.4
cloudflare_turnstile: ^3.7.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save