diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 84c1850..b4650a9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -10,15 +10,15 @@ + android:icon="@mipmap/ic_launcher" + android:label="QLine"> + + android:exported="false"> @@ -28,24 +28,23 @@ + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" /> - - + + - - + + diff --git a/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/BootReceiver.kt b/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/BootReceiver.kt index def5588..431d890 100644 --- a/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/BootReceiver.kt +++ b/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/BootReceiver.kt @@ -1,14 +1,19 @@ package com.example.hmg_qline.hmg_qline import android.content.BroadcastReceiver -import android.content.Context; -import android.content.Intent; +import android.content.Context +import android.content.Intent +import android.util.Log -class BootReceiver : BroadcastReceiver() { +class BootBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - if (intent.action == Intent.ACTION_BOOT_COMPLETED) { + if (intent.action == Intent.ACTION_BOOT_COMPLETED || + intent.action == "android.intent.action.QUICKBOOT_POWERON" + ) { + + // Launch the app automatically on boot val i = Intent(context, MainActivity::class.java) - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // Start activity outside of an existing task context.startActivity(i) } } diff --git a/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/MainActivity.kt b/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/MainActivity.kt index 710d8bb..27d014e 100644 --- a/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/hmg_qline/hmg_qline/MainActivity.kt @@ -1,5 +1,19 @@ package com.example.hmg_qline.hmg_qline +import android.os.Build +import android.os.Bundle import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) +// var REQUEST_OVERLAY_PERMISSIONS = 100 +// if (!Settings.canDrawOverlays(applicationContext)) { +// val myIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) +// val uri: Uri = Uri.fromParts("package", packageName, null) +// myIntent.data = uri +// startActivityForResult(myIntent, REQUEST_OVERLAY_PERMISSIONS) +// return +// } + } +} \ No newline at end of file diff --git a/assets/tones/call_tone.mp3 b/assets/tones/call_tone.mp3 index d79a046..dcb06ff 100644 Binary files a/assets/tones/call_tone.mp3 and b/assets/tones/call_tone.mp3 differ diff --git a/lib/main.dart b/lib/main.dart index e522e57..48a80ff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,7 +25,8 @@ class MyApp extends StatelessWidget { builder: (context, constraints) { return OrientationBuilder(builder: (context, orientation) { SizeConfig().init(constraints, orientation); - SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => getIt.get()), diff --git a/lib/models/global_config_model.dart b/lib/models/global_config_model.dart index d32f45d..9751527 100644 --- a/lib/models/global_config_model.dart +++ b/lib/models/global_config_model.dart @@ -44,7 +44,7 @@ class GlobalConfigurationsModel { dynamic editedOn; bool isToneReq = false; bool isVoiceReq = false; - int orientationType = 1; + ScreenOrientationEnum orientationTypeEnum = ScreenOrientationEnum.portraitUp; bool? isTurnOn; int? waitingAreaType; int? gender; @@ -99,7 +99,7 @@ class GlobalConfigurationsModel { this.editedOn, this.isToneReq = false, this.isVoiceReq = false, - this.orientationType = 1, + this.orientationTypeEnum = ScreenOrientationEnum.portraitUp, this.isTurnOn, this.waitingAreaType, this.gender, @@ -157,7 +157,7 @@ class GlobalConfigurationsModel { isVoiceReq = json['isVoiceReq'] ?? false; // isToneReq = true; // isVoiceReq = true; - orientationType = json['orientationType'] ?? 1; + orientationTypeEnum = ((json['orientationType'] ?? 1) as int).toScreenOrientationEnum(); isTurnOn = json['isTurnOn']; waitingAreaType = json['waitingAreaType']; gender = json['gender']; diff --git a/lib/models/ticket_model.dart b/lib/models/ticket_model.dart index aa08057..145f10c 100644 --- a/lib/models/ticket_model.dart +++ b/lib/models/ticket_model.dart @@ -34,6 +34,8 @@ class TicketData { String? patientEmail; int? preferredLang; LanguageEnum voiceLanguageEnum = LanguageEnum.english; + String ticketNoText = "Ticket Number"; + String postVoiceText = "Please Visit Counter"; int? patientGender; String? roomNo; bool? isActive; @@ -55,6 +57,9 @@ class TicketData { this.mobileNo, this.patientEmail, this.preferredLang, + this.voiceLanguageEnum = LanguageEnum.english, + this.ticketNoText = "Ticket Number", + this.postVoiceText = "Please Visit Counter", this.patientGender, this.roomNo, this.isActive, @@ -77,7 +82,9 @@ class TicketData { mobileNo = json['mobileNo']; patientEmail = json['patientEmail']; preferredLang = (json['preferredLang'] != null && json['preferredLang'].trim() != "") ? int.parse(json['preferredLang']) : 1; - voiceLanguageEnum = (json['preferredLang'] != null && json['preferredLang'].trim() != "") ? (json['preferredLang'] as int).toLanguageEnum() : LanguageEnum.english; + voiceLanguageEnum = (json['preferredLang'] != null && json['preferredLang'].trim() != "") ? (int.parse(json['preferredLang'])).toLanguageEnum() : LanguageEnum.english; + ticketNoText = json['ticketNoText'] ?? "Ticket Number"; + postVoiceText = json['pleaseVisitCounterText'] ?? "Please Visit Counter"; patientGender = json['patientGender'] ?? 1; roomNo = json['roomNo'].toString(); isActive = json['isActive']; diff --git a/lib/services/text_to_speech_service.dart b/lib/services/text_to_speech_service.dart index b204c12..8b2da7f 100644 --- a/lib/services/text_to_speech_service.dart +++ b/lib/services/text_to_speech_service.dart @@ -13,6 +13,8 @@ abstract class TextToSpeechService { required GlobalConfigurationsModel globalConfigurationsModel, }); + Future speechTextTest(String test); + void listenToTextToSpeechEvents({required Function() onVoiceCompleted}); } @@ -25,6 +27,14 @@ class TextToSpeechServiceImp implements TextToSpeechService { double pitch = 0.6; double rate = 0.2; + @override + Future speechTextTest(String test) async { + await textToSpeechInstance.setLanguage(LanguageEnum.english.enumToString()); + textToSpeechInstance.setSpeechRate(0.37); + textToSpeechInstance.setPitch(0.8); + await textToSpeechInstance.speak(test); + } + @override Future speechText({ required TicketDetailsModel ticket, @@ -33,7 +43,7 @@ class TextToSpeechServiceImp implements TextToSpeechService { const ttsGoogleEngine = 'com.google.android.tts'; // const ttsFlyTecEngine = 'com.iflytek.speechcloud'; - LanguageEnum langEnum = globalConfigurationsModel.voiceLanguageEnum; + LanguageEnum langEnum = ticket.ticketModel!.voiceLanguageEnum; List engines = await textToSpeechInstance.getEngines; if (engines.contains(ttsGoogleEngine)) { await textToSpeechInstance.setEngine(ttsGoogleEngine); @@ -51,9 +61,9 @@ class TextToSpeechServiceImp implements TextToSpeechService { textToSpeechInstance.setPitch(0.85); } // String postVoice = globalConfigurationsModel.postVoiceText; - // String preVoice = globalConfigurationsModel.ticketNoText; + // String preVoice = ticket.ticketModel!.ticketNoText; - String postVoice = globalConfigurationsModel.postVoiceText; + String postVoice = ticket.ticketModel!.postVoiceText; String preVoice = ''; String roomNo = ''; if (ticket.ticketModel!.roomNo != null && ticket.ticketModel!.roomNo!.isNotEmpty) { @@ -97,9 +107,9 @@ class TextToSpeechServiceImp implements TextToSpeechService { textToSpeechInstance.setLanguage(LanguageEnum.english.enumToString()); await textToSpeechInstance.speak(" $patientAlpha .. $patientNumeric .. "); await textToSpeechInstance.setLanguage(langEnum.enumToString()); - await textToSpeechInstance.speak(" $postVoice "); + await textToSpeechInstance.speak(" $postVoice $roomNo"); } else { - await textToSpeechInstance.speak("$preVoice $patientAlpha .. .. $patientNumeric .. .. $postVoice"); + await textToSpeechInstance.speak("$preVoice $patientAlpha .. .. $patientNumeric .. .. $postVoice $roomNo"); } } diff --git a/lib/view_models/queuing_view_model.dart b/lib/view_models/queuing_view_model.dart index 9b35c54..17affbc 100644 --- a/lib/view_models/queuing_view_model.dart +++ b/lib/view_models/queuing_view_model.dart @@ -142,6 +142,11 @@ class QueuingViewModel extends ChangeNotifier { notifyListeners(); } + Future testSpeech() async { + audioService.playTone(path: AppAssets.callTone); + textToSpeechService.speechTextTest("Hello Qamar?"); + } + Future voiceCallTicket({required TicketData? ticketData}) async { if (ticketData == null) return; GlobalConfigurationsModel globalConfigurationsModel = getIt.get().globalConfigurationsModel; diff --git a/lib/view_models/screen_config_view_model.dart b/lib/view_models/screen_config_view_model.dart index 001cfb2..9c5df9b 100644 --- a/lib/view_models/screen_config_view_model.dart +++ b/lib/view_models/screen_config_view_model.dart @@ -27,7 +27,6 @@ class ScreenConfigViewModel extends ChangeNotifier { }); Future initializeScreenConfigVM() async { - await getCurrentScreenIP(); await getGlobalConfigurationsByIP(); await getInfoWidgetsDetailsFromServer(); await getLastTimeUpdatedFromCache(); @@ -35,6 +34,17 @@ class ScreenConfigViewModel extends ChangeNotifier { getTheWidgetsConfigurationsEveryMidnight(); } + Future waitForIPAndInitializeConfigVM() async { + while (currentScreenIP == "") { + await getCurrentScreenIP(); + if (currentScreenIP != "") { + initializeScreenConfigVM(); + } else { + await Future.delayed(const Duration(seconds: 2)); + } + } + } + bool isInternetConnected = true; updateIsInternetConnected(bool value) { @@ -56,10 +66,8 @@ class ScreenConfigViewModel extends ChangeNotifier { notifyListeners(); } - ScreenOrientationEnum currentScreenRotation = ScreenOrientationEnum.portraitUp; - updateCurrentScreenRotation(ScreenOrientationEnum value) { - currentScreenRotation = value; + globalConfigurationsModel.orientationTypeEnum = value; notifyListeners(); } @@ -82,6 +90,7 @@ class ScreenConfigViewModel extends ChangeNotifier { currentScreenIP = AppConstants.testIP; } else { currentScreenIP = await connectivityService.getCurrentScreenIP(); + log("currentScreenIP: $currentScreenIP"); } } @@ -269,8 +278,7 @@ class ScreenConfigViewModel extends ChangeNotifier { } } - Future createAutoTickets() async { - int numOfTicketsToCreate = 20; + Future createAutoTickets({required int numOfTicketsToCreate}) async { int startTicket = 123456920; for (int i = 0; i < numOfTicketsToCreate; i++) { @@ -281,5 +289,7 @@ class ScreenConfigViewModel extends ChangeNotifier { return; } } + + log("last ticket is: $startTicket "); } } diff --git a/lib/views/common_widgets/app_footer.dart b/lib/views/common_widgets/app_footer.dart index 0e5573f..1486be6 100644 --- a/lib/views/common_widgets/app_footer.dart +++ b/lib/views/common_widgets/app_footer.dart @@ -79,7 +79,7 @@ class AppFooter extends StatelessWidget { const SizedBox(width: 10), InkWell( onTap: () { - // context.read().createAutoTickets(); + // context.read().createAutoTickets(numOfTicketsToCreate: 20); }, child: Image.asset( AppAssets.cloudLogo, diff --git a/lib/views/common_widgets/app_header.dart b/lib/views/common_widgets/app_header.dart index 680db43..04874a3 100644 --- a/lib/views/common_widgets/app_header.dart +++ b/lib/views/common_widgets/app_header.dart @@ -64,7 +64,7 @@ class AppHeader extends StatelessWidget implements PreferredSizeWidget { children: [ Container( alignment: Alignment.center, - height: SizeConfig.getHeightMultiplier() * 0.8, + height: SizeConfig.getHeightMultiplier() * 0.65, padding: const EdgeInsets.only(left: 20, right: 20), decoration: BoxDecoration(color: AppColors.redColor), child: Directionality( diff --git a/lib/views/main_queue_screen/main_queue_screen.dart b/lib/views/main_queue_screen/main_queue_screen.dart index d95c734..50ac8a1 100644 --- a/lib/views/main_queue_screen/main_queue_screen.dart +++ b/lib/views/main_queue_screen/main_queue_screen.dart @@ -22,7 +22,7 @@ class MainQueueScreen extends StatelessWidget { return const SizedBox.shrink(); } return Container( - height: (screenConfigViewModel.currentScreenRotation == ScreenOrientationEnum.portraitUp || screenConfigViewModel.currentScreenRotation == ScreenOrientationEnum.portraitDown) + height: (screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitUp || screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitDown) ? SizeConfig.getHeightMultiplier() * 2 : SizeConfig.getHeightMultiplier() * 0.9, padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), @@ -66,7 +66,7 @@ class MainQueueScreen extends StatelessWidget { } return SizedBox( child: Container( - height: (screenConfigViewModel.currentScreenRotation == ScreenOrientationEnum.portraitUp || screenConfigViewModel.currentScreenRotation == ScreenOrientationEnum.portraitDown) + height: (screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitUp || screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitDown) ? SizeConfig.getHeightMultiplier() * 2 : SizeConfig.getHeightMultiplier() * 0.9, padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), @@ -147,7 +147,7 @@ class MainQueueScreen extends StatelessWidget { widget = PriorityTicketsSidelist( tickets: queuingViewModel.currentTickets, globalConfigurationsModel: screenConfigViewModel.globalConfigurationsModel, - screenOrientationEnum: screenConfigViewModel.currentScreenRotation, + screenOrientationEnum: screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum, ); } else { widget = PriorityTickets( @@ -165,13 +165,13 @@ class MainQueueScreen extends StatelessWidget { int flex = 1; if (screenConfigVM.currentScreenTypeEnum == ScreenTypeEnum.roomLevelScreen) { - if (screenConfigVM.currentScreenRotation == ScreenOrientationEnum.portraitUp || screenConfigVM.currentScreenRotation == ScreenOrientationEnum.portraitDown) { + if (screenConfigVM.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitUp || screenConfigVM.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitDown) { flex = 2; } else { flex = 3; } } else { - if (screenConfigVM.currentScreenRotation == ScreenOrientationEnum.portraitUp || screenConfigVM.currentScreenRotation == ScreenOrientationEnum.portraitDown) { + if (screenConfigVM.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitUp || screenConfigVM.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitDown) { flex = 2; } else { flex = 1; @@ -216,7 +216,7 @@ class MainQueueScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Selector( - selector: (context, screenConfigViewModel) => screenConfigViewModel.currentScreenRotation, + selector: (context, screenConfigViewModel) => screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum, builder: (BuildContext context, ScreenOrientationEnum screenOrientationEnum, Widget? child) { //TODO: For Testing Only // context.read().voiceCallTicket(ticketData: context.read().currentTickets.first.ticketModel); diff --git a/lib/views/splash_screen/splash_screen.dart b/lib/views/splash_screen/splash_screen.dart index 4193d2d..c0a8d97 100644 --- a/lib/views/splash_screen/splash_screen.dart +++ b/lib/views/splash_screen/splash_screen.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:hmg_qline/config/routes.dart'; -import 'package:hmg_qline/constants/app_constants.dart'; import 'package:hmg_qline/utilities/extensions.dart'; import 'package:hmg_qline/view_models/queuing_view_model.dart'; import 'package:hmg_qline/view_models/screen_config_view_model.dart'; @@ -12,7 +11,7 @@ class SplashScreen extends StatelessWidget { Future _loadData(BuildContext context) async { final screenConfigViewModel = context.read(); final queuingViewModel = context.read(); - await screenConfigViewModel.initializeScreenConfigVM(); + await screenConfigViewModel.waitForIPAndInitializeConfigVM(); await queuingViewModel.initializeQueueingVM(); }