import 'dart:async'; import 'dart:developer'; import 'dart:io'; import 'package:connectivity/connectivity.dart'; import 'package:flutter/cupertino.dart'; import 'package:just_audio/just_audio.dart'; import 'package:queuing_system/core/api.dart'; import 'package:queuing_system/core/response_models/call_config.dart'; import 'package:queuing_system/core/response_models/patient_call.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'; class AppProvider extends ChangeNotifier { AppProvider() { startSignalHubConnection(); listenNetworkConnectivity(); } SignalRHelper signalRHelper = SignalRHelper(); final AudioPlayer audioPlayer = AudioPlayer(); CallConfig patientCallConfigurations = CallConfig(); List patientTickets = []; List isQueuePatients = []; String currentDeviceIp = ""; bool isCallingInProgress = false; bool isInternetConnectionAvailable = true; updateInternetConnection(bool value) { isInternetConnectionAvailable = value; notifyListeners(); } Future getCurrentIP() async { final ips = await NetworkInterface.list(type: InternetAddressType.IPv4); for (var interface in ips) { if (interface.name == "eth0") { for (var address in interface.addresses) { currentDeviceIp = address.address; notifyListeners(); } } if (interface.name == "wlan0") { for (var address in interface.addresses) { currentDeviceIp = address.address; notifyListeners(); } } } } Future startSignalHubConnection() async { if (!signalRHelper.getConnectionState()) { signalRHelper.startSignalRConnection(currentDeviceIp, onUpdateAvailable: onPingReceived, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect); } } Future callPatientsAPI() async { patientTickets.clear(); API.getCallRequestInfoByClinicInfo(currentDeviceIp, onSuccess: (waitingCalls, isQueuePatientsCalls, callConfigs) { patientCallConfigurations = callConfigs; if (waitingCalls.length > patientCallConfigurations.screenMaxDisplayPatients) { patientTickets = waitingCalls.sublist(0, patientCallConfigurations.screenMaxDisplayPatients); } else { patientTickets = waitingCalls; } isQueuePatients = isQueuePatientsCalls; notifyListeners(); }, onFailure: (error) { log("Api call failed with this error: ${error.toString()}"); }); } onPingReceived(data) async { if (patientTickets.isNotEmpty) { if ((patientTickets.first.isToneReq && isCallingInProgress) || (patientTickets.first.isVoiceReq && voiceCaller != null)) { Timer(Duration(seconds: patientCallConfigurations.concurrentCallDelaySec), () async { await callPatientsAPI(); }); } else { await callPatientsAPI(); } } else { await callPatientsAPI(); } } String getCallTypeText(Tickets ticket, CallConfig callConfig) { final callType = ticket.getCallType(); switch (callType) { case CallType.vitalSign: return callConfig.vitalSignText; case CallType.doctor: return callConfig.doctorText; case CallType.procedure: return callConfig.procedureText; case CallType.vaccination: return callConfig.vaccinationText; case CallType.nebulization: return callConfig.nebulizationText; default: return callConfig.vitalSignText; } } CallByVoice? voiceCaller; callPatientTicket(AudioPlayer audioPlayer) async { isCallingInProgress = true; if (patientTickets.isNotEmpty) { if (patientTickets.first.isToneReq && !patientTickets.first.isQueue) { audioPlayer.setAsset("assets/tones/call_tone.mp3"); await audioPlayer.play(); await Future.delayed(const Duration(seconds: 2)); isCallingInProgress = false; } if (patientTickets.first.isVoiceReq && voiceCaller == null && !patientTickets.first.isQueue) { final postVoice = getCallTypeText(patientTickets.first, patientCallConfigurations); voiceCaller = CallByVoice(preVoice: "Ticket Number", ticketNo: patientTickets.first.queueNo.trim().toString(), postVoice: postVoice, lang: 'en'); await voiceCaller!.startCalling(patientTickets.first.queueNo.trim().toString() != patientTickets.first.callNoStr.trim().toString()); voiceCaller = null; isCallingInProgress = false; } } if (isQueuePatients.isNotEmpty) { await Future.delayed(Duration(seconds: isQueuePatients.first.concurrentCallDelaySec)).whenComplete(() async { if (isQueuePatients.isNotEmpty) { isQueuePatients.removeAt(0); } if (patientTickets.isNotEmpty) { // Tickets ticket = patientTickets.elementAt(0); // patientTickets.removeAt(0); // patientTickets.add(ticket); } if (isQueuePatients.isNotEmpty) { // setState(() {}); } }); } else { // if (isQueuePatients.isEmpty && callFlag == 1) { // callFlag == 0; // await Future.delayed(const Duration(seconds: 3)); // patientTickets.clear(); // API.getCallRequestInfoByClinicInfo(DEVICE_IP, onSuccess: (waitingCalls, isQueuePatientsCalls) { // setState(() { // patientTickets = waitingCalls; // isQueuePatients = isQueuePatientsCalls; // // currents = currentInClinic; // }); // // log("--------------------"); // log("waiting: $patientTickets"); // log("isQueuePatients: $isQueuePatients"); // log("--------------------"); // // updateTickets(); // }, onFailure: (error) {}); // } } } Future listenAudioPlayerEvents() async { audioPlayer.playerStateStream.listen((playerState) { if (playerState.processingState == ProcessingState.completed) { isCallingInProgress = false; } }); } updatePatientTickets() { if (patientTickets.isNotEmpty) { List _ticketsToUpdate = patientTickets.where((t) => t.callUpdated == false).toList(); API.callUpdateNotIsQueueRecordByIDAsync(currentDeviceIp, ticket: _ticketsToUpdate.first, onSuccess: (ticketsUpdated) { log("[${ticketsUpdated.length}] Tickets Updated: $ticketsUpdated"); }, onFailure: (e) { log(" Tickets Update Failed with : ${e.toString()}"); }); } } updatePatientTicketByIndex(int index) { if (patientTickets.isNotEmpty) { API.callUpdateNotIsQueueRecordByIDAsync(currentDeviceIp, ticket: patientTickets.elementAt(index), onSuccess: (ticketsUpdated) { log("[${patientTickets.elementAt(index).callNoStr}] Ticket Updated: $ticketsUpdated"); }, onFailure: (e) { log(" Tickets Update ${patientTickets.elementAt(index).callNoStr} Failed with Error : ${e.toString()}"); }); } } onConnect() { log("SignalR: onConnect"); } onDisconnect(exception) { log("SignalR: onDisconnect"); signalRHelper.startSignalRConnection(currentDeviceIp, onUpdateAvailable: onPingReceived, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect); } onConnecting() { log("SignalR: onConnecting"); } listenNetworkConnectivity() async { Connectivity().onConnectivityChanged.listen((event) async { switch (event) { case ConnectivityResult.wifi: updateInternetConnection(true); await getCurrentIP(); if (signalRHelper.connection == null || signalRHelper.connection!.state != ConnectionState.active) { signalRHelper.connection!.start(); } break; case ConnectivityResult.none: updateInternetConnection(false); signalRHelper.closeConnection(); break; case ConnectivityResult.mobile: break; } }); } }