diff --git a/android/app/build.gradle b/android/app/build.gradle index 8a164e5..1d1f0af 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,7 +44,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.queuing_system" - minSdkVersion flutter.minSdkVersion + minSdkVersion localProperties.getProperty('flutter.minSdkVersion').toInteger() targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 455e8d2..9b4b6a4 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,10 @@ + + + + + - + diff --git a/android/build.gradle b/android/build.gradle index 24047dc..9e8dea7 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.6.0' repositories { google() mavenCentral() diff --git a/assets/images/wait.svg b/assets/images/wait.svg new file mode 100644 index 0000000..854fb2b --- /dev/null +++ b/assets/images/wait.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/assets/voice_ar/0.mp3 b/assets/voice_ar/0.mp3 new file mode 100644 index 0000000..2c1cf4f Binary files /dev/null and b/assets/voice_ar/0.mp3 differ diff --git a/assets/voice_ar/1.mp3 b/assets/voice_ar/1.mp3 new file mode 100644 index 0000000..b05d617 Binary files /dev/null and b/assets/voice_ar/1.mp3 differ diff --git a/assets/voice_ar/2.mp3 b/assets/voice_ar/2.mp3 new file mode 100644 index 0000000..5bfe89e Binary files /dev/null and b/assets/voice_ar/2.mp3 differ diff --git a/assets/voice_ar/3.mp3 b/assets/voice_ar/3.mp3 new file mode 100644 index 0000000..68c1af5 Binary files /dev/null and b/assets/voice_ar/3.mp3 differ diff --git a/assets/voice_ar/4.mp3 b/assets/voice_ar/4.mp3 new file mode 100644 index 0000000..3a3e2ec Binary files /dev/null and b/assets/voice_ar/4.mp3 differ diff --git a/assets/voice_ar/5.mp3 b/assets/voice_ar/5.mp3 new file mode 100644 index 0000000..e2e0fee Binary files /dev/null and b/assets/voice_ar/5.mp3 differ diff --git a/assets/voice_ar/6.mp3 b/assets/voice_ar/6.mp3 new file mode 100644 index 0000000..6e5646d Binary files /dev/null and b/assets/voice_ar/6.mp3 differ diff --git a/assets/voice_ar/7.mp3 b/assets/voice_ar/7.mp3 new file mode 100644 index 0000000..ba90910 Binary files /dev/null and b/assets/voice_ar/7.mp3 differ diff --git a/assets/voice_ar/8.mp3 b/assets/voice_ar/8.mp3 new file mode 100644 index 0000000..5b2e025 Binary files /dev/null and b/assets/voice_ar/8.mp3 differ diff --git a/assets/voice_ar/9.mp3 b/assets/voice_ar/9.mp3 new file mode 100644 index 0000000..4112f24 Binary files /dev/null and b/assets/voice_ar/9.mp3 differ diff --git a/assets/voice_ar/ticket_number.mp3 b/assets/voice_ar/ticket_number.mp3 new file mode 100644 index 0000000..3a1ce47 Binary files /dev/null and b/assets/voice_ar/ticket_number.mp3 differ diff --git a/assets/voice_ar/visit_doctor.mp3 b/assets/voice_ar/visit_doctor.mp3 new file mode 100644 index 0000000..6bf38d9 Binary files /dev/null and b/assets/voice_ar/visit_doctor.mp3 differ diff --git a/assets/voice_ar/visit_nurse.mp3 b/assets/voice_ar/visit_nurse.mp3 new file mode 100644 index 0000000..cfa32e5 Binary files /dev/null and b/assets/voice_ar/visit_nurse.mp3 differ diff --git a/assets/voice_en/0.mp3 b/assets/voice_en/0.mp3 new file mode 100644 index 0000000..5603d80 Binary files /dev/null and b/assets/voice_en/0.mp3 differ diff --git a/assets/voice_en/1.mp3 b/assets/voice_en/1.mp3 new file mode 100644 index 0000000..f5cced9 Binary files /dev/null and b/assets/voice_en/1.mp3 differ diff --git a/assets/voice_en/2.mp3 b/assets/voice_en/2.mp3 new file mode 100644 index 0000000..f0c6084 Binary files /dev/null and b/assets/voice_en/2.mp3 differ diff --git a/assets/voice_en/3.mp3 b/assets/voice_en/3.mp3 new file mode 100644 index 0000000..da489e8 Binary files /dev/null and b/assets/voice_en/3.mp3 differ diff --git a/assets/voice_en/4.mp3 b/assets/voice_en/4.mp3 new file mode 100644 index 0000000..f76338c Binary files /dev/null and b/assets/voice_en/4.mp3 differ diff --git a/assets/voice_en/5.mp3 b/assets/voice_en/5.mp3 new file mode 100644 index 0000000..0cbc7de Binary files /dev/null and b/assets/voice_en/5.mp3 differ diff --git a/assets/voice_en/6.mp3 b/assets/voice_en/6.mp3 new file mode 100644 index 0000000..779ed79 Binary files /dev/null and b/assets/voice_en/6.mp3 differ diff --git a/assets/voice_en/7.mp3 b/assets/voice_en/7.mp3 new file mode 100644 index 0000000..28f2ea7 Binary files /dev/null and b/assets/voice_en/7.mp3 differ diff --git a/assets/voice_en/8.mp3 b/assets/voice_en/8.mp3 new file mode 100644 index 0000000..b1947c2 Binary files /dev/null and b/assets/voice_en/8.mp3 differ diff --git a/assets/voice_en/9.mp3 b/assets/voice_en/9.mp3 new file mode 100644 index 0000000..4e5453c Binary files /dev/null and b/assets/voice_en/9.mp3 differ diff --git a/assets/voice_en/ticket_number.mp3 b/assets/voice_en/ticket_number.mp3 new file mode 100644 index 0000000..ca4b295 Binary files /dev/null and b/assets/voice_en/ticket_number.mp3 differ diff --git a/assets/voice_en/visit_doctor.mp3 b/assets/voice_en/visit_doctor.mp3 new file mode 100644 index 0000000..fa3f018 Binary files /dev/null and b/assets/voice_en/visit_doctor.mp3 differ diff --git a/assets/voice_en/visit_nurse.mp3 b/assets/voice_en/visit_nurse.mp3 new file mode 100644 index 0000000..f60684d Binary files /dev/null and b/assets/voice_en/visit_nurse.mp3 differ diff --git a/lib/core/api.dart b/lib/core/api.dart new file mode 100644 index 0000000..01bb09c --- /dev/null +++ b/lib/core/api.dart @@ -0,0 +1,47 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:queuing_system/core/base/base_app_client.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; + +const _getCallRequestInfoByClinicInfo = "/GetCallRequestInfoByClinincInfo"; +const _call_UpdateNotIsQueueRecordByIDAsync = "/Call_UpdateNotIsQueueRecordByIDAsync"; + +class API{ + + static GetCallRequestInfoByClinincInfo(String deviceIp, {@required Function(List, List) onSuccess, @required Function(dynamic) onFailure}) async{ + final body = { "IPAdress" : deviceIp }; + BaseAppClient.post(_getCallRequestInfoByClinicInfo, body: body, onSuccess: (response, status){ + if(status == 200){ + final calledByNurse = (response["CalledByNurse"] as List).map((j) => Tickets.fromJson(j)).toList(); + final clinicCurrentPatient = (response["ClinicCurrentPatient"] as List).map((j) => Tickets.fromJson(j)).toList(); + onSuccess(calledByNurse, clinicCurrentPatient); + }else{ + onFailure(response); + } + }, onFailure: (error, status) => onFailure(error)); + } + + static Call_UpdateNotIsQueueRecordByIDAsync(String deviceIp, {@required List tickets, @required Function(List) onSuccess, @required Function(dynamic) onFailure}) async{ + if(tickets.isEmpty) { + return; + } + + List _ticketsUpdated = []; + + for (var ticket in tickets) { + final body = { "CallID" : ticket.callNo}; + await BaseAppClient.post(_call_UpdateNotIsQueueRecordByIDAsync, body: body, onSuccess: (response, status){ + if(status == 200){ + ticket.call_updated = true; + _ticketsUpdated.add(ticket); + } + }, onFailure: (error, status) => onFailure(error)); + } + + if(_ticketsUpdated.isNotEmpty) { + onSuccess(_ticketsUpdated); + }else{ + onFailure(false); + } + } +} diff --git a/lib/core/config/config.dart b/lib/core/config/config.dart index 7221b93..7f1dc2c 100644 --- a/lib/core/config/config.dart +++ b/lib/core/config/config.dart @@ -5,7 +5,8 @@ const ONLY_NUMBERS = "[0-9]"; const ONLY_LETTERS = "[a-zA-Z &'\"]"; const ONLY_DATE = "[0-9/]"; const BASE_URL_LIVE_CARE = 'https://livecare.hmg.com/'; -const BASE_URL = 'https://hmgwebservices.com/'; +const BASE_URL = 'http://10.200.204.11:2222/Services/Nurses.svc/REST'; +// const BASE_URL = 'https://hmgwebservices.com/'; /// Timer Info diff --git a/lib/core/response_model/patient_call.dart b/lib/core/response_model/patient_call.dart new file mode 100644 index 0000000..a7332f2 --- /dev/null +++ b/lib/core/response_model/patient_call.dart @@ -0,0 +1,75 @@ + +import 'dart:convert'; + +import 'package:queuing_system/utils/call_type.dart'; + +class Tickets { + Tickets({ + this.callNo, + this.roomNo, + this.callType, + this.createdON, + this.doctorName, + this.doctorNameN, + this.editedON, + this.mobileNo, + this.patientGender, + this.patientID, + this.queueNo,}); + + Tickets.fromJson(dynamic json) { + callNo = json['CallNo']; + roomNo = json['RoomNo']; + callType = json['CallType']; + createdON = json['CreatedON']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + editedON = json['EditedON']; + mobileNo = json['MobileNo']; + patientGender = json['PatientGender']; + patientID = json['PatientID']; + queueNo = json['QueueNo']; + } + + int callNo; + String roomNo; + int callType; + String createdON; + String doctorName; + String doctorNameN; + String editedON; + String mobileNo; + int patientGender; + int patientID; + String queueNo; + bool call_updated = false; + + Map toJson() { + final map = {}; + map['CallNo'] = callNo; + map['RoomNo'] = roomNo; + map['CallType'] = callType; + map['CreatedON'] = createdON; + map['DoctorName'] = doctorName; + map['DoctorNameN'] = doctorNameN; + map['EditedON'] = editedON; + map['MobileNo'] = mobileNo; + map['PatientGender'] = patientGender; + map['PatientID'] = patientID; + map['QueueNo'] = queueNo; + return map; + } + + @override + String toString() { + return (callNo).toString(); + } + + CallType getCallType(){ + if(callType == 0) return CallType.RECEPTION; + if(callType == 1) return CallType.NURSE; + if(callType == 2) return CallType.DOCTOR; + return CallType.NONE; + } + +} \ No newline at end of file diff --git a/lib/core/response_model/xyz.dart b/lib/core/response_model/xyz.dart new file mode 100644 index 0000000..11e0cb5 --- /dev/null +++ b/lib/core/response_model/xyz.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; +Xyz xyzFromJson(String str) => Xyz.fromJson(json.decode(str)); +String xyzToJson(Xyz data) => json.encode(data.toJson()); +class Xyz { + Xyz({ + this.callNo, + this.roomNo, + this.callType, + this.createdON, + this.doctorName, + this.doctorNameN, + this.editedON, + this.mobileNo, + this.patientGender, + this.patientID, + this.queueNo,}); + + Xyz.fromJson(dynamic json) { + callNo = json['CallNo']; + roomNo = json['RoomNo']; + callType = json['CallType']; + createdON = json['CreatedON']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + editedON = json['EditedON']; + mobileNo = json['MobileNo']; + patientGender = json['PatientGender']; + patientID = json['PatientID']; + queueNo = json['QueueNo']; + } + int callNo; + String roomNo; + int callType; + String createdON; + String doctorName; + String doctorNameN; + String editedON; + String mobileNo; + int patientGender; + int patientID; + String queueNo; + + Map toJson() { + final map = {}; + map['CallNo'] = callNo; + map['RoomNo'] = roomNo; + map['CallType'] = callType; + map['CreatedON'] = createdON; + map['DoctorName'] = doctorName; + map['DoctorNameN'] = doctorNameN; + map['EditedON'] = editedON; + map['MobileNo'] = mobileNo; + map['PatientGender'] = patientGender; + map['PatientID'] = patientID; + map['QueueNo'] = queueNo; + return map; + } + +} \ No newline at end of file diff --git a/lib/header/app_header.dart b/lib/header/app_header.dart index aadf25b..4cae3c2 100644 --- a/lib/header/app_header.dart +++ b/lib/header/app_header.dart @@ -12,14 +12,12 @@ class AppHeader extends StatelessWidget with PreferredSizeWidget { padding: const EdgeInsets.only( left: 0, right: 5, - bottom: 5, ), decoration: BoxDecoration( - color: AppGlobal.appRedColor - , - border: const Border(bottom: BorderSide(color: Color(0xFFEFEFEF)))), + color: AppGlobal.appRedColor, border: const Border(bottom: BorderSide(color: Color(0xFFEFEFEF)))), child: Container( - padding: const EdgeInsets.only(left: 30, right: 50, bottom: 0,), + height: 100, + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 0,), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/home/first_column.dart b/lib/home/first_column.dart index 23d24df..f99e8eb 100644 --- a/lib/home/first_column.dart +++ b/lib/home/first_column.dart @@ -13,7 +13,7 @@ class FirstColumn extends StatelessWidget { return Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - const QueItem(queNo: "OBG-T45", isFirstLine: true, isNurseVisit: true, haveListOfPatient: true,), + const TicketItem(queNo: "OBG-T45", isFirstLine: true, isNurseVisit: true, haveListOfPatient: true,), SizedBox( height: SizeConfig.getHeightMultiplier() * 5,), if(have3Patient ||have2Patient ) @@ -21,9 +21,9 @@ class FirstColumn extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ if(have2Patient || have3Patient) - const QueItem(queNo: "OBG-T45", isSecondLine: true, isNurseVisit: false, haveListOfPatient: true,), + const TicketItem(queNo: "OBG-T45", isSecondLine: true, isNurseVisit: false, haveListOfPatient: true,), if(have3Patient) - const QueItem(queNo: "OBG-T45", isSecondLine: true, isNurseVisit: true, haveListOfPatient: true,), + const TicketItem(queNo: "OBG-T45", isSecondLine: true, isNurseVisit: true, haveListOfPatient: true,), ], ), ], diff --git a/lib/home/home_screen.dart b/lib/home/home_screen.dart index 89a8bc1..ea3f400 100644 --- a/lib/home/home_screen.dart +++ b/lib/home/home_screen.dart @@ -1,181 +1,195 @@ import 'dart:async'; +import 'dart:io'; +import 'package:connectivity/connectivity.dart'; import 'package:flutter/material.dart'; +import 'package:queuing_system/core/api.dart'; import 'package:queuing_system/core/base/app_scaffold_widget.dart'; +import 'package:queuing_system/core/base/base_app_client.dart'; import 'package:queuing_system/core/config/config.dart'; import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; import 'package:queuing_system/header/app_header.dart'; +import 'package:queuing_system/home/home_screen_components.dart'; import 'package:queuing_system/home/que_item_list.dart'; +import 'package:queuing_system/utils/call_by_voice.dart'; +import 'package:queuing_system/utils/call_type.dart'; import 'package:queuing_system/utils/signalR_utils.dart'; import 'package:queuing_system/utils/utils.dart'; import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; +import 'package:signalr_core/signalr_core.dart'; +import 'package:text_to_speech/text_to_speech.dart'; import 'first_column.dart'; + +var DEVICE_IP = "10.20.20.19"; // Testing IP +// var DEVICE_IP = "10.70.249.21"; // (Make sure by Haroon before use it) Production IP + class MyHomePage extends StatefulWidget { String title = "MyHomePage"; - bool have0Patient = true; - bool have1Patient = false; - bool have2Patient = false; - bool have3Patient = false; - bool haveListOfPatient = false; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { - Timer _timer; - int remainingTime = 30; + SignalRHelper signalRHelper = SignalRHelper(); + + final _tts = TextToSpeech(); + + List waitings = []; + List currents = []; @override void dispose() { - _timer.cancel(); super.dispose(); } - startTimer() { - Timer.periodic(const Duration(seconds: 1), (timer) { - if (remainingTime == 0) { - setState(() { - remainingTime = 30; - }); - } else { - setState(() { - remainingTime--; - if (remainingTime > 25) { - - /// for 0 patinet - widget.have0Patient = true; - widget.have1Patient = false; - widget.have2Patient = false; - widget.have3Patient = false; - widget.haveListOfPatient = false; - } else if (remainingTime > 20) { - /// for 1 patinet - - widget.have0Patient = false; - widget.have1Patient = true; - widget.have2Patient = false; - widget.have3Patient = false; - widget.haveListOfPatient = false; - } else if (remainingTime > 15) { - - /// for 2 patinet - - widget.have0Patient = false; - widget.have1Patient = false; - widget.have2Patient = true; - widget.have3Patient = false; - widget.haveListOfPatient = false; - } else if (remainingTime > 10) { - /// for 3 only patinet - widget.have0Patient = false; - widget.have1Patient = false; - widget.have2Patient = false; - widget.have3Patient = true; - widget.haveListOfPatient = false; - } else { - /// for 3+ only patinet - - widget.have0Patient = false; - widget.have1Patient = false; - widget.have2Patient = false; - widget.have3Patient = true; - widget.haveListOfPatient = true; - } - }); - } - }); - } @override void initState() { - startTimer(); - SignalRHelper signalRHelper = new SignalRHelper(); - if (!signalRHelper.getConnectionState()) signalRHelper.startSignalRConnection(); + listenNetworkConnectivity(); + + if (!signalRHelper.getConnectionState()) { + signalRHelper.startSignalRConnection( + DEVICE_IP, + onUpdateAvailable: onUpdateAvailable, + onConnect: onConnect, + onConnecting: onConnecting, + onDisconnect: onDisconnect + ); + } + + _tts.setLanguage("en"); + _tts.setRate(0.7); + + // _tts.getVoiceByLang('en').then((value){ + // + // }) + _tts.getVoice().then((value){ + _tts.setVoice(value[2]); + }); + super.initState(); } @override Widget build(BuildContext context) { - return AppScaffold( appBar: AppHeader(), - body: Column( - children: [ - SizedBox( - height: SizeConfig.getHeightMultiplier() * - (widget.haveListOfPatient - ? 2 - : widget.have1Patient || widget.have0Patient - ? 20 - : 10)), - widget.have0Patient - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Center( - child: AppText("Awaiting Patients Arrival", - fontFamily: 'Poppins-SemiBold.ttf', - letterSpacing: -1.56, - fontSize: SizeConfig.getWidthMultiplier() * 9), - ), - ], - ) - : widget.haveListOfPatient - ? Row( - children: [ - FirstColumn( - have3Patient: widget.have3Patient, - have2Patient: widget.have2Patient, - ), - const SizedBox( - width: 40, - ), - if (widget.haveListOfPatient) - Container( - width: 10, - height: SizeConfig.getHeightMultiplier() * 40, - color: AppGlobal.appLightGreyColor, - ), - if (widget.haveListOfPatient) - const SizedBox( - width: 40, - ), - if (widget.haveListOfPatient) const QueItemList() - ], - ) - : FirstColumn( - have3Patient: widget.have3Patient, - have2Patient: widget.have2Patient, - ), - ], - ), - bottomSheet: Container( - color: Colors.transparent, + body: content(), + bottomNavigationBar: Container( + color: Colors.grey.withOpacity(0.1), height: Utils.getHeight(), width: double.infinity, child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Padding( - padding: const EdgeInsets.only(top: 30, left: 30), - child: AppText( - "Powered By", - letterSpacing: -1.56, - fontSize: SizeConfig.getWidthMultiplier() * 2.6, - fontFamily: 'Poppins-Medium.ttf', - ), + const SizedBox(width: 20), + AppText( + "Powered By", + fontSize: SizeConfig.getWidthMultiplier() * 2.6, + fontFamily: 'Poppins-Medium.ttf', ), - Padding( - padding: const EdgeInsets.only(top: 40, left: 18), - child: Image.asset( - "assets/images/cloud_logo.png", - height: SizeConfig.getHeightMultiplier() * 6, - ), + const SizedBox(width: 20), + Image.asset( + "assets/images/cloud_logo.png", + height: SizeConfig.getHeightMultiplier() * 4, ), + const SizedBox(width: 20), ], ), - ), // This trailing comma makes auto-formatting nicer for build methods. + ), ); } + + Widget content(){ + // waitings = waitings.sublist(0,3); + voiceCall(); + + if(waitings.isEmpty) { + // No Patient in Queue + return noPatientInQueue(); + + }else if(waitings.length > 4){ + // Return Content With Side List + return priorityTicketsWithSideList(waitings); + + }else{ + // Return Content In Center Aligned + return priorityTickets(waitings); + + } + } + + + CallByVoice voiceCaller; + voiceCall() async{ + if(waitings.isNotEmpty && voiceCaller == null){ + final postVoice = waitings.first.getCallType().audio('en'); + voiceCaller = CallByVoice(waitings.first.callNo.toString(), preVoice: 'ticket_number.mp3', postVoice: postVoice, lang: 'en'); + await voiceCaller.start(); + voiceCaller = null; + } + } + + onUpdateAvailable(data) async{ + API.GetCallRequestInfoByClinincInfo( + DEVICE_IP, + onSuccess: (waitingCalls, currentInClinic){ + + setState(() { + waitings = waitingCalls; + currents = currentInClinic; + }); + + print("\n\n"); + print("--------------------"); + print("Current: $currentInClinic"); + print("Waiting: $waitingCalls"); + print("--------------------"); + print("\n\n"); + + updateTickets(); + + }, onFailure: (error){ + + }); + } + + + updateTickets(){ + List _ticketsToUpdate = waitings.where((t) => t.call_updated == false); + API.Call_UpdateNotIsQueueRecordByIDAsync(DEVICE_IP, tickets: _ticketsToUpdate, onSuccess: (tickets_updated){ + print("[${tickets_updated.length}] Tickets Updated: $tickets_updated"); + }, onFailure: (e){ + + }); + } + + + onConnect(){ + print("SignalR: onConnect"); + } + + onDisconnect(exception){ + print("SignalR: onDisconnect"); + } + + onConnecting(){ + print("SignalR: onConnecting"); + } + + listenNetworkConnectivity() async{ + Connectivity().onConnectivityChanged.listen((event) { + switch (event) { + case ConnectivityResult.wifi: + signalRHelper.connection.start(); + break; + case ConnectivityResult.none: + signalRHelper.closeConnection(context); + break; + } + }); + } } diff --git a/lib/home/home_screen_bkp.dart b/lib/home/home_screen_bkp.dart new file mode 100644 index 0000000..34b0dc2 --- /dev/null +++ b/lib/home/home_screen_bkp.dart @@ -0,0 +1,205 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:queuing_system/core/api.dart'; +import 'package:queuing_system/core/base/app_scaffold_widget.dart'; +import 'package:queuing_system/core/base/base_app_client.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/header/app_header.dart'; +import 'package:queuing_system/home/que_item_list.dart'; +import 'package:queuing_system/utils/signalR_utils.dart'; +import 'package:queuing_system/utils/utils.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; +import 'first_column.dart'; + + +var DEVICE_IP = "10.70.249.21"; + +class MyHomePage extends StatefulWidget { + String title = "MyHomePage"; + bool have0Patient = true; + bool have1Patient = false; + bool have2Patient = false; + bool have3Patient = false; + bool haveListOfPatient = false; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + Timer _timer; + int remainingTime = 30; + + @override + void dispose() { + _timer.cancel(); + super.dispose(); + } + + startTimer() { + Timer.periodic(const Duration(seconds: 1), (timer) { + if (remainingTime == 0) { + setState(() { + remainingTime = 30; + }); + } else { + setState(() { + remainingTime--; + if (remainingTime > 25) { + + /// for 0 patinet + widget.have0Patient = true; + widget.have1Patient = false; + widget.have2Patient = false; + widget.have3Patient = false; + widget.haveListOfPatient = false; + } else if (remainingTime > 20) { + /// for 1 patinet + + widget.have0Patient = false; + widget.have1Patient = true; + widget.have2Patient = false; + widget.have3Patient = false; + widget.haveListOfPatient = false; + } else if (remainingTime > 15) { + + /// for 2 patinet + + widget.have0Patient = false; + widget.have1Patient = false; + widget.have2Patient = true; + widget.have3Patient = false; + widget.haveListOfPatient = false; + } else if (remainingTime > 10) { + /// for 3 only patinet + widget.have0Patient = false; + widget.have1Patient = false; + widget.have2Patient = false; + widget.have3Patient = true; + widget.haveListOfPatient = false; + } else { + /// for 3+ only patinet + + widget.have0Patient = false; + widget.have1Patient = false; + widget.have2Patient = false; + widget.have3Patient = true; + widget.haveListOfPatient = true; + } + }); + } + }); + } + + @override + void initState() { + startTimer(); + // Get Ticket Info + // http://10.200.204.11:2222/Services/Nurses.svc/REST/GetCallRequestInfoByClinincInfo + + SignalRHelper signalRHelper = SignalRHelper(); + if (!signalRHelper.getConnectionState()) { + signalRHelper.startSignalRConnection(DEVICE_IP, onUpdateAvailable: onUpdateAvailable); + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + + + return AppScaffold( + appBar: AppHeader(), + body: Column( + children: [ + SizedBox( + height: SizeConfig.getHeightMultiplier() * + (widget.haveListOfPatient + ? 2 + : widget.have1Patient || widget.have0Patient + ? 20 + : 10)), + widget.have0Patient + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: AppText("Awaiting Patients Arrival", + fontFamily: 'Poppins-SemiBold.ttf', + fontSize: SizeConfig.getWidthMultiplier() * 9), + ), + ], + ) + : widget.haveListOfPatient + ? Row( + children: [ + FirstColumn( + have3Patient: widget.have3Patient, + have2Patient: widget.have2Patient, + ), + const SizedBox( + width: 40, + ), + if (widget.haveListOfPatient) + Container( + width: 10, + height: SizeConfig.getHeightMultiplier() * 40, + color: AppGlobal.appLightGreyColor, + ), + if (widget.haveListOfPatient) + const SizedBox( + width: 40, + ), + if (widget.haveListOfPatient) const QueItemList() + ], + ) + : FirstColumn( + have3Patient: widget.have3Patient, + have2Patient: widget.have2Patient, + ), + ], + ), + bottomSheet: Container( + color: Colors.transparent, + height: Utils.getHeight(), + width: double.infinity, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(top: 30, left: 30), + child: AppText( + "Powered By", + fontSize: SizeConfig.getWidthMultiplier() * 2.6, + fontFamily: 'Poppins-Medium.ttf', + ), + ), + Padding( + padding: const EdgeInsets.only(top: 40, left: 18), + child: Image.asset( + "assets/images/cloud_logo.png", + height: SizeConfig.getHeightMultiplier() * 6, + ), + ), + ], + ), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } + + + onUpdateAvailable(data) async{ + API.GetCallRequestInfoByClinincInfo( + DEVICE_IP, + onSuccess: (waitingCalls, currentInClinic){ + print("\n\n"); + print("--------------------"); + print("Current: $currentInClinic"); + print("Waiting: $waitingCalls"); + print("--------------------"); + print("\n\n"); + }, onFailure: (error){ + + }); + } +} diff --git a/lib/home/home_screen_components.dart b/lib/home/home_screen_components.dart new file mode 100644 index 0000000..01a118c --- /dev/null +++ b/lib/home/home_screen_components.dart @@ -0,0 +1,93 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; +import 'package:queuing_system/home/priority_calls.dart'; +import 'package:queuing_system/utils/call_type.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +Widget noPatientInQueue(){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: AppText("Awaiting Patients Arrival", + fontFamily: 'Poppins-SemiBold.ttf', + fontSize: SizeConfig.getWidthMultiplier() * 9), + ), + ], + ); +} + +Widget priorityTickets(List tickets){ + return PriorityTickets(tickets); +} + + + +Widget priorityTicketsWithSideList(List tickets){ + final priorityTickets = tickets.sublist(0,3); + final otherTickets = tickets.sublist(3,tickets.length); + return Row( + children: [ + Expanded( + flex: 3, + child: PriorityTickets(priorityTickets) + ), + Container(color: Colors.grey.withOpacity(0.1), width: 10, margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 50)), + Expanded( + flex: 2, + child: ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), + itemCount: otherTickets.length, + itemBuilder: (ctx,idx){ + + final itm = otherTickets[idx]; + final isDoctor = itm.callType == 1; + + final icon = "assets/images/${isDoctor ? 'doctoricon' : 'nurseicon'}.svg"; + final title = "Please Visit ${isDoctor ? 'Doctor' : 'Nurse'}"; + final color = isDoctor ? AppGlobal.appRedColor : AppGlobal.appGreenColor; + + return ListTile( + contentPadding: const EdgeInsets.all(8), + title: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 140, + child: AppText( + itm.callNo.toString(), + letterSpacing: -2.32, + fontWeight: FontWeight.bold, + fontSize: SizeConfig.getWidthMultiplier() * 5, + textAlign: TextAlign.end, + ), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + itm.getCallType().icon(SizeConfig.getHeightMultiplier()*2.5), + const SizedBox(width: 10), + AppText( + itm.getCallType().message('en'), + color: itm.getCallType().color(), + letterSpacing: -1.5, + fontSize: SizeConfig.getWidthMultiplier() * 3.3, + fontWeight: FontWeight.w600, + fontHeight: 0.5, + ), + ], + ) + ], + ), + ); + }, + ), + ) + ], + ); +} \ No newline at end of file diff --git a/lib/home/priority_calls.dart b/lib/home/priority_calls.dart new file mode 100644 index 0000000..18b8695 --- /dev/null +++ b/lib/home/priority_calls.dart @@ -0,0 +1,101 @@ +import 'package:blinking_text/blinking_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; +import 'package:queuing_system/home/que_item/que_item.dart'; +import 'package:queuing_system/utils/call_type.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +class PriorityTickets extends StatelessWidget { + List tickets; + + PriorityTickets(this.tickets, {Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + final firstTicket = tickets[0]; + final otherTickets = tickets.sublist(1,tickets.length); + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + + vTicketItem(ticketNo: "${firstTicket.callNo ?? ''}", callType: firstTicket.getCallType(), scale: 1.2, blink: true), + + const SizedBox(height: 100), + + if(tickets.length > 1) + ...[ + SizedBox(height: SizeConfig.getHeightMultiplier()*1.5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: otherTickets.map((ticket) => vTicketItem(ticketNo: "${ticket.callNo ?? ''}", callType: ticket.getCallType(), scale: 0.8)).toList(), + ) + ] + ], + ); + } +} + +class vTicketItem extends StatelessWidget{ + final String ticketNo; + final CallType callType; + final bool blink; + final double scale; + vTicketItem({@required this.ticketNo, @required this.callType, this.scale, this.blink = false}); + + @override + Widget build(BuildContext context) { + + return Transform.scale( + scale: scale, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + BlinkText( + ticketNo, + style: TextStyle( + fontSize: SizeConfig.getWidthMultiplier() * 16, + letterSpacing: -9.32, + height: 0.5, + fontWeight: FontWeight.bold + ), + beginColor: Colors.black, + endColor: blink ? Colors.black.withOpacity(0.1) : Colors.black, + // endColor: blink ? AppGlobal.appRedColor : Colors.black, + times: 0, + duration: const Duration(seconds: 1) + ), + // AppText( + // ticketNo, + // letterSpacing: -9.32, + // fontSize: SizeConfig.getWidthMultiplier() * 16, + // fontWeight: FontWeight.bold, + // fontHeight: 0.7, + // ), + + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + callType.icon(SizeConfig.getHeightMultiplier()*2.5), + const SizedBox(width: 10), + AppText( + callType.message('en'), + color: callType.color(), + letterSpacing: -1.5, + fontSize: SizeConfig.getWidthMultiplier() * 3.3, + fontWeight: FontWeight.w600, + fontHeight: 0.5, + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/home/que_item/que_item.dart b/lib/home/que_item/que_item.dart index 39ad8c4..68c0454 100644 --- a/lib/home/que_item/que_item.dart +++ b/lib/home/que_item/que_item.dart @@ -5,8 +5,8 @@ import 'package:queuing_system/core/config/size_config.dart'; import 'package:queuing_system/home/que_item/que_item_widget.dart'; import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; -class QueItem extends StatelessWidget { - const QueItem({ +class TicketItem extends StatelessWidget { + const TicketItem({ Key key, this.isFirstLine = false, this.isSecondLine = false, diff --git a/lib/home/que_item_list.dart b/lib/home/que_item_list.dart index e4e1461..5b8d098 100644 --- a/lib/home/que_item_list.dart +++ b/lib/home/que_item_list.dart @@ -12,14 +12,14 @@ class QueItemList extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: SizeConfig.getHeightMultiplier() *2.3,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), - const QueItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), ],), ); diff --git a/lib/main.dart b/lib/main.dart index f61e6b5..0d37e23 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; import 'core/base/project_view_model.dart'; import 'core/config/size_config.dart'; import 'home/home_screen.dart'; +// import 'home/home_screen_bkp.dart'; void main() { runApp(const MyApp()); diff --git a/lib/utils/call_by_voice.dart b/lib/utils/call_by_voice.dart new file mode 100644 index 0000000..044c1c7 --- /dev/null +++ b/lib/utils/call_by_voice.dart @@ -0,0 +1,48 @@ +import 'package:flutter/cupertino.dart'; +import 'package:just_audio/just_audio.dart'; +import 'package:queuing_system/utils/call_type.dart'; + +class CallByVoice{ + + final String lang; + final String preVoice; + final String ticketNo; + final String postVoice; + + CallByVoice(this.ticketNo, {this.lang = 'en', @required this.preVoice, @required this.postVoice}); + + final _player = AudioPlayer(); + start() async{ + + // Create Pre Voice Players + if(preVoice != null && preVoice.isNotEmpty) { + await _player.setAsset('assets/voice_$lang/$preVoice'); + await _player.play(); + } + + // Create Ticket Number Voice Players + final characters = ticketNo.characters.toList(); + for(int i = 0; i< characters.length; i++){ + final no = characters[i]; + if(no.isNotEmpty){ + await Future.delayed(const Duration(milliseconds: 200)); + + await _player.stop(); + await _player.setAsset('assets/voice_$lang/$no.mp3'); + await _player.play(); + } + } + + + // Create Post Voice Players + if(postVoice != null && postVoice.isNotEmpty) { + await Future.delayed(const Duration(milliseconds: 1000)); + + await _player.stop(); + await _player.setAsset('assets/voice_$lang/$postVoice'); + await _player.play(); + } + + _player.dispose(); + } +} \ No newline at end of file diff --git a/lib/utils/call_type.dart b/lib/utils/call_type.dart new file mode 100644 index 0000000..b3cfb99 --- /dev/null +++ b/lib/utils/call_type.dart @@ -0,0 +1,60 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:queuing_system/core/config/config.dart'; + +enum CallType{ + RECEPTION, + NURSE, + DOCTOR, + NONE, +} + +extension xCallType on CallType{ + + Color color(){ + if(this == CallType.RECEPTION) { + return AppGlobal.appRedColor; + }else if(this == CallType.NURSE) { + return AppGlobal.appGreenColor; + }else if(this == CallType.DOCTOR) { + return AppGlobal.appRedColor ; + }else{ + return Colors.black54; + } + } + + SvgPicture icon(double height,){ + if(this == CallType.RECEPTION) { + return SvgPicture.asset("assets/images/doctoricon.svg", height: height, color: color()); + }else if(this == CallType.NURSE) { + return SvgPicture.asset("assets/images/nurseicon.svg", height: height, color: color()); + }else if(this == CallType.DOCTOR) { + return SvgPicture.asset("assets/images/doctoricon.svg", height: height, color: color()); + } + return SvgPicture.asset("assets/images/wait.svg", height: height, color: color());; + } + + String message(String lang){ + if(this == CallType.RECEPTION) { + return "Please visit reception"; + }else if(this == CallType.NURSE) { + return "Please visit nurse"; + }else if(this == CallType.DOCTOR) { + return "Please visit doctor"; + } + return "Please wait . . ."; + } + + String audio(String lang){ + if(this == CallType.RECEPTION) { + return "visit_doctor.mp3"; + }else if(this == CallType.NURSE) { + return "visit_nurse.mp3"; + }else if(this == CallType.DOCTOR) { + return "visit_doctor.mp3"; + } + return ""; + } +} \ No newline at end of file diff --git a/lib/utils/signalR_utils.dart b/lib/utils/signalR_utils.dart index 395e438..eb7ebcc 100644 --- a/lib/utils/signalR_utils.dart +++ b/lib/utils/signalR_utils.dart @@ -4,43 +4,54 @@ import 'package:flutter/material.dart'; import 'package:http/io_client.dart'; import 'package:signalr_core/signalr_core.dart'; -class SignalRHelper{ +/* +https://vcallapi.hmg.com/patientcalling.html?IPAddress=10.10.14.20&Clinic=4&Project=15 + +--------------------------------------- + IP, Clinic, Project Mapping to SignalR +--------------------------------------- +(SignalR: 10.10.14.11) <<<< [IP=10.10.14.20 | Clinic=4 | Project=15] +(SignalR: 10.70.249.21) <<<< [IP=10.10.14.20 | Clinic=3 | Project=16] +--------------------------------------- +*/ - String hubBaseURL ="https://vcallapi.hmg.com/patientcalling.html?IPAddress=10.10.14.11&Clinic=4&Project=15"; +class SignalRHelper{ + String hubBaseURL = "https://vcallapi.hmg.com/PatientCallingHub"; + // String hubBaseURL = "https://vcallapi.hmg.com/PatientCallingHub?IPAddress=10.10.14.20"; // "https://VCallApi.hmg.com/WebRTCHub?source=mobile&username=2001273"; String msg ="Awaiting Patients Arrival"; HubConnection connection; - startSignalRConnection() async { + + startSignalRConnection(String deviceIp, {@required Function(dynamic) onUpdateAvailable, @required VoidCallback onConnect, @required Function(dynamic) onDisconnect, @required VoidCallback onConnecting}) async { + + // Hardcoded IP For Testing + deviceIp = "10.10.14.11"; + + final url = hubBaseURL+"?IPAddress=$deviceIp"; connection = HubConnectionBuilder() .withUrl( - hubBaseURL, + url, HttpConnectionOptions( client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true), transport: HttpTransportType.webSockets, logging: (level, message) => { print(message) - }, )) .build(); - await connection.start(); + connection.onclose(onDisconnect); + connection.onreconnecting((exception) => onConnecting()); + connection.onreconnected((connectionId) => onConnect()); - connection.on('ReceiveMessage', (message) { - handleIncomingMessage(message); + connection.on('addChatMessage', (message) { + onUpdateAvailable(message); }); - - connection.start(); - + await connection.start(); } - - void handleIncomingMessage(List message) { - print(message.toString()); - } - void sendMessage(List args) async { await connection.invoke('SendMessage', args: args); //['Bob', 'Says hi!'] } @@ -52,11 +63,18 @@ class SignalRHelper{ } - closeConnection(BuildContext context) async { - if(connection.state == HubConnectionState.connected) + if(connection.state == HubConnectionState.connected || connection.state == HubConnectionState.connecting) { await connection.stop(); } } + + startConnection(BuildContext context) async { + if(connection.state == HubConnectionState.connected || connection.state == HubConnectionState.connecting) + { + connection.off('addChatMessage'); + await connection.start(); + } + } } \ No newline at end of file diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index d119548..cc01d0f 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -178,6 +178,6 @@ class Utils { } static getHeight() { - return SizeConfig.getHeightMultiplier()*9; + return SizeConfig.getHeightMultiplier()*7; } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 9994324..1d5268d 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,16 @@ import FlutterMacOS import Foundation +import audio_session import connectivity_macos +import just_audio +import path_provider_macos +import text_to_speech_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + TextToSpeechMacOsPlugin.register(with: registry.registrar(forPlugin: "TextToSpeechMacOsPlugin")) } diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 6ade3d5..6b9af40 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 6AAE3FFB3F8FFB988FA76AB9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11DB0DA04C904ACC8281A43B /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 11DB0DA04C904ACC8281A43B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* queuing_system.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "queuing_system.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* queuing_system.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = queuing_system.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,8 +68,11 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 48B59F1CA514D4FE4E3BDC17 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + B1FB68A5A367B781DB228777 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + B5F3688D63D2A57A68A0C215 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,12 +80,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6AAE3FFB3F8FFB988FA76AB9 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 03070B72BAE9950C266BFD12 /* Pods */ = { + isa = PBXGroup; + children = ( + 48B59F1CA514D4FE4E3BDC17 /* Pods-Runner.debug.xcconfig */, + B1FB68A5A367B781DB228777 /* Pods-Runner.release.xcconfig */, + B5F3688D63D2A57A68A0C215 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -99,6 +116,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 03070B72BAE9950C266BFD12 /* Pods */, ); sourceTree = ""; }; @@ -148,6 +166,7 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 11DB0DA04C904ACC8281A43B /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + AD55B7E3AC663188F5990F5E /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + E17CB185511E52C6C3C36151 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -270,6 +291,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + AD55B7E3AC663188F5990F5E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E17CB185511E52C6C3C36151 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/pubspec.yaml b/pubspec.yaml index 446205c..287b451 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,10 @@ dependencies: flutter_gifimage: ^1.0.1 flutter_svg: ^1.0.3 http: ^0.13.0 + blinking_text: ^1.0.2 + + text_to_speech: ^0.2.3 + just_audio: ^0.9.29 #signalr core signalr_core: ^1.1.1 @@ -71,6 +75,8 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - assets/images/ + - assets/voice_en/ + - assets/voice_ar/ fonts: