final touches

faiz_kiosk
FaizHashmiCS22 10 months ago
parent 2aae8ee5e8
commit 6c8ede60d9

@ -10,15 +10,15 @@
</intent> </intent>
</queries> </queries>
<application <application
android:label="QLine"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher"
android:label="QLine">
<!-- Define the BroadcastReceiver that listens to the BOOT_COMPLETED event -->
<receiver <receiver
android:name="BootReceiver" android:name=".BootBroadcastReceiver"
android:enabled="true" android:enabled="true"
android:exported="true" android:exported="false">
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" />
@ -28,24 +28,23 @@
</receiver> </receiver>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true" android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:taskAffinity="" android:taskAffinity=""
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme" />
/>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
@ -61,8 +60,8 @@
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. --> In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries> <queries>
<intent> <intent>
<action android:name="android.intent.action.PROCESS_TEXT"/> <action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain"/> <data android:mimeType="text/plain" />
</intent> </intent>
</queries> </queries>
</manifest> </manifest>

@ -1,14 +1,19 @@
package com.example.hmg_qline.hmg_qline package com.example.hmg_qline.hmg_qline
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context; import android.content.Context
import android.content.Intent; import android.content.Intent
import android.util.Log
class BootReceiver : BroadcastReceiver() { class BootBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { 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) 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) context.startActivity(i)
} }
} }

@ -1,5 +1,19 @@
package com.example.hmg_qline.hmg_qline package com.example.hmg_qline.hmg_qline
import android.os.Build
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity 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
// }
}
}

Binary file not shown.

@ -25,7 +25,8 @@ class MyApp extends StatelessWidget {
builder: (context, constraints) { builder: (context, constraints) {
return OrientationBuilder(builder: (context, orientation) { return OrientationBuilder(builder: (context, orientation) {
SizeConfig().init(constraints, orientation); SizeConfig().init(constraints, orientation);
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
return MultiProvider( return MultiProvider(
providers: [ providers: [
ChangeNotifierProvider<ScreenConfigViewModel>(create: (context) => getIt.get<ScreenConfigViewModel>()), ChangeNotifierProvider<ScreenConfigViewModel>(create: (context) => getIt.get<ScreenConfigViewModel>()),

@ -44,7 +44,7 @@ class GlobalConfigurationsModel {
dynamic editedOn; dynamic editedOn;
bool isToneReq = false; bool isToneReq = false;
bool isVoiceReq = false; bool isVoiceReq = false;
int orientationType = 1; ScreenOrientationEnum orientationTypeEnum = ScreenOrientationEnum.portraitUp;
bool? isTurnOn; bool? isTurnOn;
int? waitingAreaType; int? waitingAreaType;
int? gender; int? gender;
@ -99,7 +99,7 @@ class GlobalConfigurationsModel {
this.editedOn, this.editedOn,
this.isToneReq = false, this.isToneReq = false,
this.isVoiceReq = false, this.isVoiceReq = false,
this.orientationType = 1, this.orientationTypeEnum = ScreenOrientationEnum.portraitUp,
this.isTurnOn, this.isTurnOn,
this.waitingAreaType, this.waitingAreaType,
this.gender, this.gender,
@ -157,7 +157,7 @@ class GlobalConfigurationsModel {
isVoiceReq = json['isVoiceReq'] ?? false; isVoiceReq = json['isVoiceReq'] ?? false;
// isToneReq = true; // isToneReq = true;
// isVoiceReq = true; // isVoiceReq = true;
orientationType = json['orientationType'] ?? 1; orientationTypeEnum = ((json['orientationType'] ?? 1) as int).toScreenOrientationEnum();
isTurnOn = json['isTurnOn']; isTurnOn = json['isTurnOn'];
waitingAreaType = json['waitingAreaType']; waitingAreaType = json['waitingAreaType'];
gender = json['gender']; gender = json['gender'];

@ -34,6 +34,8 @@ class TicketData {
String? patientEmail; String? patientEmail;
int? preferredLang; int? preferredLang;
LanguageEnum voiceLanguageEnum = LanguageEnum.english; LanguageEnum voiceLanguageEnum = LanguageEnum.english;
String ticketNoText = "Ticket Number";
String postVoiceText = "Please Visit Counter";
int? patientGender; int? patientGender;
String? roomNo; String? roomNo;
bool? isActive; bool? isActive;
@ -55,6 +57,9 @@ class TicketData {
this.mobileNo, this.mobileNo,
this.patientEmail, this.patientEmail,
this.preferredLang, this.preferredLang,
this.voiceLanguageEnum = LanguageEnum.english,
this.ticketNoText = "Ticket Number",
this.postVoiceText = "Please Visit Counter",
this.patientGender, this.patientGender,
this.roomNo, this.roomNo,
this.isActive, this.isActive,
@ -77,7 +82,9 @@ class TicketData {
mobileNo = json['mobileNo']; mobileNo = json['mobileNo'];
patientEmail = json['patientEmail']; patientEmail = json['patientEmail'];
preferredLang = (json['preferredLang'] != null && json['preferredLang'].trim() != "") ? int.parse(json['preferredLang']) : 1; 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; patientGender = json['patientGender'] ?? 1;
roomNo = json['roomNo'].toString(); roomNo = json['roomNo'].toString();
isActive = json['isActive']; isActive = json['isActive'];

@ -13,6 +13,8 @@ abstract class TextToSpeechService {
required GlobalConfigurationsModel globalConfigurationsModel, required GlobalConfigurationsModel globalConfigurationsModel,
}); });
Future<void> speechTextTest(String test);
void listenToTextToSpeechEvents({required Function() onVoiceCompleted}); void listenToTextToSpeechEvents({required Function() onVoiceCompleted});
} }
@ -25,6 +27,14 @@ class TextToSpeechServiceImp implements TextToSpeechService {
double pitch = 0.6; double pitch = 0.6;
double rate = 0.2; double rate = 0.2;
@override
Future<void> speechTextTest(String test) async {
await textToSpeechInstance.setLanguage(LanguageEnum.english.enumToString());
textToSpeechInstance.setSpeechRate(0.37);
textToSpeechInstance.setPitch(0.8);
await textToSpeechInstance.speak(test);
}
@override @override
Future<void> speechText({ Future<void> speechText({
required TicketDetailsModel ticket, required TicketDetailsModel ticket,
@ -33,7 +43,7 @@ class TextToSpeechServiceImp implements TextToSpeechService {
const ttsGoogleEngine = 'com.google.android.tts'; const ttsGoogleEngine = 'com.google.android.tts';
// const ttsFlyTecEngine = 'com.iflytek.speechcloud'; // const ttsFlyTecEngine = 'com.iflytek.speechcloud';
LanguageEnum langEnum = globalConfigurationsModel.voiceLanguageEnum; LanguageEnum langEnum = ticket.ticketModel!.voiceLanguageEnum;
List engines = await textToSpeechInstance.getEngines; List engines = await textToSpeechInstance.getEngines;
if (engines.contains(ttsGoogleEngine)) { if (engines.contains(ttsGoogleEngine)) {
await textToSpeechInstance.setEngine(ttsGoogleEngine); await textToSpeechInstance.setEngine(ttsGoogleEngine);
@ -51,9 +61,9 @@ class TextToSpeechServiceImp implements TextToSpeechService {
textToSpeechInstance.setPitch(0.85); textToSpeechInstance.setPitch(0.85);
} }
// String postVoice = globalConfigurationsModel.postVoiceText; // 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 preVoice = '';
String roomNo = ''; String roomNo = '';
if (ticket.ticketModel!.roomNo != null && ticket.ticketModel!.roomNo!.isNotEmpty) { if (ticket.ticketModel!.roomNo != null && ticket.ticketModel!.roomNo!.isNotEmpty) {
@ -97,9 +107,9 @@ class TextToSpeechServiceImp implements TextToSpeechService {
textToSpeechInstance.setLanguage(LanguageEnum.english.enumToString()); textToSpeechInstance.setLanguage(LanguageEnum.english.enumToString());
await textToSpeechInstance.speak(" $patientAlpha .. $patientNumeric .. "); await textToSpeechInstance.speak(" $patientAlpha .. $patientNumeric .. ");
await textToSpeechInstance.setLanguage(langEnum.enumToString()); await textToSpeechInstance.setLanguage(langEnum.enumToString());
await textToSpeechInstance.speak(" $postVoice "); await textToSpeechInstance.speak(" $postVoice $roomNo");
} else { } else {
await textToSpeechInstance.speak("$preVoice $patientAlpha .. .. $patientNumeric .. .. $postVoice"); await textToSpeechInstance.speak("$preVoice $patientAlpha .. .. $patientNumeric .. .. $postVoice $roomNo");
} }
} }

@ -142,6 +142,11 @@ class QueuingViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> testSpeech() async {
audioService.playTone(path: AppAssets.callTone);
textToSpeechService.speechTextTest("Hello Qamar?");
}
Future<void> voiceCallTicket({required TicketData? ticketData}) async { Future<void> voiceCallTicket({required TicketData? ticketData}) async {
if (ticketData == null) return; if (ticketData == null) return;
GlobalConfigurationsModel globalConfigurationsModel = getIt.get<ScreenConfigViewModel>().globalConfigurationsModel; GlobalConfigurationsModel globalConfigurationsModel = getIt.get<ScreenConfigViewModel>().globalConfigurationsModel;

@ -27,7 +27,6 @@ class ScreenConfigViewModel extends ChangeNotifier {
}); });
Future<void> initializeScreenConfigVM() async { Future<void> initializeScreenConfigVM() async {
await getCurrentScreenIP();
await getGlobalConfigurationsByIP(); await getGlobalConfigurationsByIP();
await getInfoWidgetsDetailsFromServer(); await getInfoWidgetsDetailsFromServer();
await getLastTimeUpdatedFromCache(); await getLastTimeUpdatedFromCache();
@ -35,6 +34,17 @@ class ScreenConfigViewModel extends ChangeNotifier {
getTheWidgetsConfigurationsEveryMidnight(); getTheWidgetsConfigurationsEveryMidnight();
} }
Future<void> waitForIPAndInitializeConfigVM() async {
while (currentScreenIP == "") {
await getCurrentScreenIP();
if (currentScreenIP != "") {
initializeScreenConfigVM();
} else {
await Future.delayed(const Duration(seconds: 2));
}
}
}
bool isInternetConnected = true; bool isInternetConnected = true;
updateIsInternetConnected(bool value) { updateIsInternetConnected(bool value) {
@ -56,10 +66,8 @@ class ScreenConfigViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
ScreenOrientationEnum currentScreenRotation = ScreenOrientationEnum.portraitUp;
updateCurrentScreenRotation(ScreenOrientationEnum value) { updateCurrentScreenRotation(ScreenOrientationEnum value) {
currentScreenRotation = value; globalConfigurationsModel.orientationTypeEnum = value;
notifyListeners(); notifyListeners();
} }
@ -82,6 +90,7 @@ class ScreenConfigViewModel extends ChangeNotifier {
currentScreenIP = AppConstants.testIP; currentScreenIP = AppConstants.testIP;
} else { } else {
currentScreenIP = await connectivityService.getCurrentScreenIP(); currentScreenIP = await connectivityService.getCurrentScreenIP();
log("currentScreenIP: $currentScreenIP");
} }
} }
@ -269,8 +278,7 @@ class ScreenConfigViewModel extends ChangeNotifier {
} }
} }
Future<void> createAutoTickets() async { Future<void> createAutoTickets({required int numOfTicketsToCreate}) async {
int numOfTicketsToCreate = 20;
int startTicket = 123456920; int startTicket = 123456920;
for (int i = 0; i < numOfTicketsToCreate; i++) { for (int i = 0; i < numOfTicketsToCreate; i++) {
@ -281,5 +289,7 @@ class ScreenConfigViewModel extends ChangeNotifier {
return; return;
} }
} }
log("last ticket is: $startTicket ");
} }
} }

@ -79,7 +79,7 @@ class AppFooter extends StatelessWidget {
const SizedBox(width: 10), const SizedBox(width: 10),
InkWell( InkWell(
onTap: () { onTap: () {
// context.read<ScreenConfigViewModel>().createAutoTickets(); // context.read<ScreenConfigViewModel>().createAutoTickets(numOfTicketsToCreate: 20);
}, },
child: Image.asset( child: Image.asset(
AppAssets.cloudLogo, AppAssets.cloudLogo,

@ -64,7 +64,7 @@ class AppHeader extends StatelessWidget implements PreferredSizeWidget {
children: [ children: [
Container( Container(
alignment: Alignment.center, alignment: Alignment.center,
height: SizeConfig.getHeightMultiplier() * 0.8, height: SizeConfig.getHeightMultiplier() * 0.65,
padding: const EdgeInsets.only(left: 20, right: 20), padding: const EdgeInsets.only(left: 20, right: 20),
decoration: BoxDecoration(color: AppColors.redColor), decoration: BoxDecoration(color: AppColors.redColor),
child: Directionality( child: Directionality(

@ -22,7 +22,7 @@ class MainQueueScreen extends StatelessWidget {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
return Container( 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() * 2
: SizeConfig.getHeightMultiplier() * 0.9, : SizeConfig.getHeightMultiplier() * 0.9,
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
@ -66,7 +66,7 @@ class MainQueueScreen extends StatelessWidget {
} }
return SizedBox( return SizedBox(
child: Container( 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() * 2
: SizeConfig.getHeightMultiplier() * 0.9, : SizeConfig.getHeightMultiplier() * 0.9,
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
@ -147,7 +147,7 @@ class MainQueueScreen extends StatelessWidget {
widget = PriorityTicketsSidelist( widget = PriorityTicketsSidelist(
tickets: queuingViewModel.currentTickets, tickets: queuingViewModel.currentTickets,
globalConfigurationsModel: screenConfigViewModel.globalConfigurationsModel, globalConfigurationsModel: screenConfigViewModel.globalConfigurationsModel,
screenOrientationEnum: screenConfigViewModel.currentScreenRotation, screenOrientationEnum: screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum,
); );
} else { } else {
widget = PriorityTickets( widget = PriorityTickets(
@ -165,13 +165,13 @@ class MainQueueScreen extends StatelessWidget {
int flex = 1; int flex = 1;
if (screenConfigVM.currentScreenTypeEnum == ScreenTypeEnum.roomLevelScreen) { 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; flex = 2;
} else { } else {
flex = 3; flex = 3;
} }
} else { } else {
if (screenConfigVM.currentScreenRotation == ScreenOrientationEnum.portraitUp || screenConfigVM.currentScreenRotation == ScreenOrientationEnum.portraitDown) { if (screenConfigVM.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitUp || screenConfigVM.globalConfigurationsModel.orientationTypeEnum == ScreenOrientationEnum.portraitDown) {
flex = 2; flex = 2;
} else { } else {
flex = 1; flex = 1;
@ -216,7 +216,7 @@ class MainQueueScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector<ScreenConfigViewModel, ScreenOrientationEnum>( return Selector<ScreenConfigViewModel, ScreenOrientationEnum>(
selector: (context, screenConfigViewModel) => screenConfigViewModel.currentScreenRotation, selector: (context, screenConfigViewModel) => screenConfigViewModel.globalConfigurationsModel.orientationTypeEnum,
builder: (BuildContext context, ScreenOrientationEnum screenOrientationEnum, Widget? child) { builder: (BuildContext context, ScreenOrientationEnum screenOrientationEnum, Widget? child) {
//TODO: For Testing Only //TODO: For Testing Only
// context.read<QueuingViewModel>().voiceCallTicket(ticketData: context.read<QueuingViewModel>().currentTickets.first.ticketModel); // context.read<QueuingViewModel>().voiceCallTicket(ticketData: context.read<QueuingViewModel>().currentTickets.first.ticketModel);

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_qline/config/routes.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/utilities/extensions.dart';
import 'package:hmg_qline/view_models/queuing_view_model.dart'; import 'package:hmg_qline/view_models/queuing_view_model.dart';
import 'package:hmg_qline/view_models/screen_config_view_model.dart'; import 'package:hmg_qline/view_models/screen_config_view_model.dart';
@ -12,7 +11,7 @@ class SplashScreen extends StatelessWidget {
Future<void> _loadData(BuildContext context) async { Future<void> _loadData(BuildContext context) async {
final screenConfigViewModel = context.read<ScreenConfigViewModel>(); final screenConfigViewModel = context.read<ScreenConfigViewModel>();
final queuingViewModel = context.read<QueuingViewModel>(); final queuingViewModel = context.read<QueuingViewModel>();
await screenConfigViewModel.initializeScreenConfigVM(); await screenConfigViewModel.waitForIPAndInitializeConfigVM();
await queuingViewModel.initializeQueueingVM(); await queuingViewModel.initializeQueueingVM();
} }

Loading…
Cancel
Save