diff --git a/lib/constants/app_constants.dart b/lib/constants/app_constants.dart index 7523999..9223e46 100644 --- a/lib/constants/app_constants.dart +++ b/lib/constants/app_constants.dart @@ -167,7 +167,7 @@ class AppConstants { static String apiKey = 'EE17D21C7943485D9780223CCE55DCE5'; static String testIP = '12.4.5.1'; // projectID.QlineType.ScreenType.AnyNumber (1 to 10) static int thresholdForListUI = 5; - static double currentBuildVersion = 9.1; + static double currentBuildVersion = 9.2; static double clearLogsHoursThreshold = 48; // Maximum log file size in bytes before rotation/clearing. Default 2 MB. static int maxLogFileSizeBytes = 2 * 1024 * 1024; @@ -196,11 +196,9 @@ class ApiConstants { static String ticketAcknowledgementInsert = '$baseUrlApi/Common/TicketQueueAck_Insert'; // AppointmentSpecific - static String ticketCallRequestUpdate = "$baseUrlApiPatientCall/CallRequest_QueueUpdate"; // Signal R Constants - static String sendQLinePatientCall = "SendQLinePatientCall"; static String sendQLineConfig = "SendQLineConfig"; } diff --git a/lib/main.dart b/lib/main.dart index 56adf5e..ade9940 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,15 +14,12 @@ import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:hmg_qline/services/crash_handler_service.dart'; void main() { - // Run all initialization inside the same Zone used by runApp to avoid zone mismatch warnings. runZonedGuarded(() async { WidgetsFlutterBinding.ensureInitialized(); try { await AppDependencies.addDependencies(); // initialize crash handler after DI setup - if (getIt.isRegistered()) { - getIt.get().setupGlobalErrorHandlers(); - } + getIt.get().setupGlobalErrorHandlers(); await WakelockPlus.enable(); } catch (e) { log('Initialization error: $e'); @@ -31,11 +28,7 @@ void main() { runApp(const MyApp()); }, (error, stack) async { try { - if (getIt.isRegistered()) { - await getIt.get().handleCrash(error: error, stackTrace: stack, context: 'runZonedGuarded'); - } else { - log('Uncaught error before DI initialized: $error'); - } + await getIt.get().handleCrash(error: error, stackTrace: stack, context: 'runZonedGuarded'); } catch (e) { log('Error in runZonedGuarded handler: $e'); } diff --git a/lib/models/global_config_model.dart b/lib/models/global_config_model.dart index 3a95e8d..60820db 100644 --- a/lib/models/global_config_model.dart +++ b/lib/models/global_config_model.dart @@ -77,6 +77,9 @@ class GlobalConfigurationsModel { List? kioskQueueList; List? kioskLanguageConfigList; + // Indicates whether the screen belongs to Takhasusi main (based on its IP) + bool isFromTakhasusiMain = false; + String vitalSignTextEng = "Vital Sign"; String doctorTextEng = "Doctor"; String procedureTextEng = "Procedure"; @@ -168,6 +171,7 @@ class GlobalConfigurationsModel { this.cityKey, this.kioskQueueList, this.kioskLanguageConfigList, + this.isFromTakhasusiMain = false, this.vitalSignTextEng = "Vital Sign", this.doctorTextEng = "Doctor", this.procedureTextEng = "Procedure", @@ -270,6 +274,8 @@ class GlobalConfigurationsModel { } else { kioskLanguageConfigList = []; } + // Default to false; actual value (based on device IP) is set in ViewModel after loading config + isFromTakhasusiMain = false; vitalSignTextEng = json['vitalSignText']; doctorTextEng = json['doctorText']; procedureTextEng = json['procedureText']; @@ -295,6 +301,6 @@ class GlobalConfigurationsModel { @override String toString() { - return 'GlobalConfigurationsModel{id: $id, configType: $configType, description: $description, counterStart: $counterStart, counterEnd: $counterEnd, concurrentCallDelaySec: $concurrentCallDelaySec, voiceType: $voiceType, voiceTypeText: $voiceTypeText, screenLanguageEnum: $screenLanguageEnum, screenLanguageText: $screenLanguageText, textDirection: $textDirection, voiceLanguageEnum: $voiceLanguageEnum, voiceLanguageText: $voiceLanguageText, screenMaxDisplayPatients: $screenMaxDisplayPatients, isNotiReq: $isNotiReq, prioritySMS: $prioritySMS, priorityWhatsApp: $priorityWhatsApp, priorityEmail: $priorityEmail, ticketNoText: $ticketNoText, postVoiceText: $postVoiceText, roomText: $roomTextEng, roomNo: $roomNo, isRoomNoRequired: $isRoomNoRequired, counterText: $counterTextEng, queueNoText: $queueNoTextEng, callForText: $callForTextEng, currentServeTextArb: $currentServeTextArb,, currentServeTextEng: $currentServeTextEng, maxText: $maxText, minText: $minText, nextPrayerTextEng: $nextPrayerTextEng, nextPrayerTextArb: $nextPrayerTextArb, weatherText: $weatherText, fajarText: $fajarTextEng, dhuhrText: $dhuhrTextEng, asarText: $asarTextEng, maghribText: $maghribTextEng, ishaText: $ishaTextEng, isActive: $isActive, createdBy: $createdBy, createdOn: $createdOn, editedBy: $editedBy, editedOn: $editedOn, isToneReq: $isToneReq, isVoiceReq: $isVoiceReq, orientationTypeEnum: $orientationTypeEnum, isTurnOn: $isTurnOn, waitingAreaType: $waitingAreaType, gender: $gender, isWeatherReq: $isWeatherReq, isPrayerTimeReq: $isPrayerTimeReq, isRssFeedReq: $isRssFeedReq, qTypeEnum: $qTypeEnum, screenTypeEnum: $screenTypeEnum, projectID: $projectID, projectLatitude: $projectLatitude, projectLongitude: $projectLongitude, cityKey: $cityKey, kioskQueueList: $kioskQueueList, kioskLanguageConfigList: $kioskLanguageConfigList, vitalSignText: $vitalSignTextEng, doctorText: $doctorTextEng, procedureText: $procedureTextEng, vaccinationText: $vaccinationTextEng, nebulizationText: $nebulizationTextEng, callForVitalSignText: $callForVitalSignTextEng, callForDoctorText: $callForDoctorTextEng, callForProcedureText: $callForProcedureTextEng, callForVaccinationText: $callForVaccinationTextEng, callForNebulizationText: $callForNebulizationTextEng, vitalSignTextArb: $vitalSignTextArb, doctorTextArb: $doctorTextArb, procedureTextArb: $procedureTextArb, vaccinationTextArb: $vaccinationTextArb, nebulizationTextArb: $nebulizationTextArb, callForVitalSignTextArb: $callForVitalSignTextArb, callForDoctorTextArb: $callForDoctorTextArb, callForProcedureTextArb: $callForProcedureTextArb, callForVaccinationTextArb: $callForVaccinationTextArb, callForNebulizationTextArb: $callForNebulizationTextArb}'; + return 'GlobalConfigurationsModel{id: $id, isFromTakhasusiMain: $isFromTakhasusiMain, configType: $configType, description: $description, counterStart: $counterStart, counterEnd: $counterEnd, concurrentCallDelaySec: $concurrentCallDelaySec, voiceType: $voiceType, voiceTypeText: $voiceTypeText, screenLanguageEnum: $screenLanguageEnum, screenLanguageText: $screenLanguageText, textDirection: $textDirection, voiceLanguageEnum: $voiceLanguageEnum, voiceLanguageText: $voiceLanguageText, screenMaxDisplayPatients: $screenMaxDisplayPatients, isNotiReq: $isNotiReq, prioritySMS: $prioritySMS, priorityWhatsApp: $priorityWhatsApp, priorityEmail: $priorityEmail, ticketNoText: $ticketNoText, postVoiceText: $postVoiceText, roomText: $roomTextEng, roomNo: $roomNo, isRoomNoRequired: $isRoomNoRequired, counterText: $counterTextEng, queueNoText: $queueNoTextEng, callForText: $callForTextEng, currentServeTextArb: $currentServeTextArb,, currentServeTextEng: $currentServeTextEng, maxText: $maxText, minText: $minText, nextPrayerTextEng: $nextPrayerTextEng, nextPrayerTextArb: $nextPrayerTextArb, weatherText: $weatherText, fajarText: $fajarTextEng, dhuhrText: $dhuhrTextEng, asarText: $asarTextEng, maghribText: $maghribTextEng, ishaText: $ishaTextEng, isActive: $isActive, createdBy: $createdBy, createdOn: $createdOn, editedBy: $editedBy, editedOn: $editedOn, isToneReq: $isToneReq, isVoiceReq: $isVoiceReq, orientationTypeEnum: $orientationTypeEnum, isTurnOn: $isTurnOn, waitingAreaType: $waitingAreaType, gender: $gender, isWeatherReq: $isWeatherReq, isPrayerTimeReq: $isPrayerTimeReq, isRssFeedReq: $isRssFeedReq, qTypeEnum: $qTypeEnum, screenTypeEnum: $screenTypeEnum, projectID: $projectID, projectLatitude: $projectLatitude, projectLongitude: $projectLongitude, cityKey: $cityKey, kioskQueueList: $kioskQueueList, kioskLanguageConfigList: $kioskLanguageConfigList, vitalSignText: $vitalSignTextEng, doctorText: $doctorTextEng, procedureText: $procedureTextEng, vaccinationText: $vaccinationTextEng, nebulizationText: $nebulizationTextEng, callForVitalSignText: $callForVitalSignTextEng, callForDoctorText: $callForDoctorTextEng, callForProcedureText: $callForProcedureTextEng, callForVaccinationText: $callForVaccinationTextEng, callForNebulizationText: $callForNebulizationTextEng, vitalSignTextArb: $vitalSignTextArb, doctorTextArb: $doctorTextArb, procedureTextArb: $procedureTextArb, vaccinationTextArb: $vaccinationTextArb, nebulizationTextArb: $nebulizationTextArb, callForVitalSignTextArb: $callForVitalSignTextArb, callForDoctorTextArb: $callForDoctorTextArb, callForProcedureTextArb: $callForProcedureTextArb, callForVaccinationTextArb: $callForVaccinationTextArb, callForNebulizationTextArb: $callForNebulizationTextArb}'; } } diff --git a/lib/services/logger_service.dart b/lib/services/logger_service.dart index 8571192..24cb012 100644 --- a/lib/services/logger_service.dart +++ b/lib/services/logger_service.dart @@ -100,8 +100,7 @@ class LoggerServiceImp implements LoggerService { final errorMsg = error.toString(); final stack = stackTrace?.toString() ?? 'No stack trace available'; - final crashMessage = - '$sep\n[$timestamp]\nCONTEXT: $contextStr\nERROR: $errorMsg\nSTACKTRACE:\n$stack\n$sep\n'; + final crashMessage = '$sep\n[$timestamp]\nCONTEXT: $contextStr\nERROR: $errorMsg\nSTACKTRACE:\n$stack\n$sep\n'; final baseDir = await getExternalStorageDirectory(); final logDir = Directory('${baseDir!.path}/logs'); diff --git a/lib/utilities/extensions.dart b/lib/utilities/extensions.dart index 42b45ec..859567f 100644 --- a/lib/utilities/extensions.dart +++ b/lib/utilities/extensions.dart @@ -59,6 +59,20 @@ extension ScreenOrientationExt on ScreenOrientationEnum { return 4; } } + + int getTurnsByOrientationForOlderVersions() { + log("this: $this"); + switch (this) { + case ScreenOrientationEnum.portraitUp: + return 0; + case ScreenOrientationEnum.portraitDown: + return 2; + case ScreenOrientationEnum.landscapeRight: + return 1; + case ScreenOrientationEnum.landscapeLeft: + return 3; + } + } } extension QTypeEnumExtension on int { diff --git a/lib/view_models/screen_config_view_model.dart b/lib/view_models/screen_config_view_model.dart index 026e0e7..d5c8665 100644 --- a/lib/view_models/screen_config_view_model.dart +++ b/lib/view_models/screen_config_view_model.dart @@ -154,7 +154,19 @@ class ScreenConfigViewModel extends ChangeNotifier { } void updateGlobalConfigurationsModel({required var value, bool needNotify = false, bool shouldUpdateNextPrayer = false}) { - globalConfigurationsModel = value; + // Ensure the incoming value is the GlobalConfigurationsModel and set the Takhasusi flag based on current IP + if (value is GlobalConfigurationsModel) { + // IPs that belong to Takhasusi main + const takhasusiMainIPs = ['10.70.194.105', '10.70.194.87']; + try { + value.isFromTakhasusiMain = takhasusiMainIPs.contains(currentScreenIP); + } catch (_) { + value.isFromTakhasusiMain = false; + } + globalConfigurationsModel = value; + } else { + globalConfigurationsModel = value; + } if (needNotify) { notifyListeners(); diff --git a/lib/views/common_widgets/app_header.dart b/lib/views/common_widgets/app_header.dart index be01996..68bd294 100644 --- a/lib/views/common_widgets/app_header.dart +++ b/lib/views/common_widgets/app_header.dart @@ -34,6 +34,7 @@ class AppHeader extends StatelessWidget implements PreferredSizeWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ InkWell( + onTap: () { // getIt.get().triggerOOM(); }, diff --git a/lib/views/main_queue_screen/components/priority_tickets.dart b/lib/views/main_queue_screen/components/priority_tickets.dart index 2eef8e4..6547a3b 100644 --- a/lib/views/main_queue_screen/components/priority_tickets.dart +++ b/lib/views/main_queue_screen/components/priority_tickets.dart @@ -57,14 +57,14 @@ class PriorityTickets extends StatelessWidget { case 2: return [ Expanded(child: _buildPrimaryTicket(context, tickets[0], isHalf: true)), - SizedBox(height: SizeConfig.getHeightMultiplier()! * 0.5), + globalConfigurationsModel.isFromTakhasusiMain ? SizedBox(height: SizeConfig.getHeightMultiplier()! * 0.2) : SizedBox(height: SizeConfig.getHeightMultiplier()! * 0.5), Expanded(child: _buildSecondaryTicket(context, tickets[1], isHalf: true)), ]; case 3: case 4: return [ Expanded(child: _buildPrimaryTicket(context, tickets[0], isHalf: true)), - SizedBox(height: SizeConfig.getHeightMultiplier()! * 0.5), + globalConfigurationsModel.isFromTakhasusiMain ? SizedBox(height: SizeConfig.getHeightMultiplier()! * 0.2) : SizedBox(height: SizeConfig.getHeightMultiplier()! * 0.5), Expanded(child: _buildOtherTicketsRow(context, noOfTicketsToSkipFromStart: 1, isHalf: true)), ]; @@ -186,7 +186,11 @@ class PriorityTickets extends StatelessWidget { // Helper methods to reduce repetition double _getTicketScale() { - return globalConfigurationsModel.screenTypeEnum == ScreenTypeEnum.roomLevelScreen ? 2.0 : 1.2; + return globalConfigurationsModel.screenTypeEnum == ScreenTypeEnum.roomLevelScreen + ? 2.0 + : globalConfigurationsModel.isFromTakhasusiMain + ? 0.8 + : 1.2; } String _getRoomText() { diff --git a/lib/views/main_queue_screen/main_queue_screen.dart b/lib/views/main_queue_screen/main_queue_screen.dart index a4fa336..1915e2d 100644 --- a/lib/views/main_queue_screen/main_queue_screen.dart +++ b/lib/views/main_queue_screen/main_queue_screen.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:hmg_qline/constants/app_constants.dart'; import 'package:hmg_qline/utilities/enums.dart'; @@ -181,6 +183,8 @@ class _MainQueueScreenState extends State { @override Widget build(BuildContext context) { + final globalConfigurationsModel = context.read().globalConfigurationsModel; + log("isFromTakhasusiMain: ${globalConfigurationsModel.isFromTakhasusiMain}"); return Selector( selector: (context, screenConfigViewModel) => screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum, builder: (BuildContext context, ScreenOrientationEnum screenOrientationEnum, Widget? child) { @@ -188,7 +192,7 @@ class _MainQueueScreenState extends State { // context.read().createAutoTickets(numOfTicketsToCreate: 20); // context.read().testSpeech(); return RotatedBox( - quarterTurns: screenOrientationEnum.getTurnsByOrientation(), + quarterTurns: globalConfigurationsModel.isFromTakhasusiMain ? screenOrientationEnum.getTurnsByOrientationForOlderVersions() : screenOrientationEnum.getTurnsByOrientation(), child: AppScaffold( backgroundColor: AppColors.backgroundColor, appBar: const AppHeader(),