@ -1,8 +1,10 @@
import ' dart:developer ' ;
import ' dart:async ' ;
import ' package:flutter/foundation.dart ' ;
import ' package:flutter/material.dart ' ;
import ' package:hmg_qline/config/dependency_injection.dart ' ;
import ' package:hmg_qline/constants/app_constants.dart ' ;
import ' package:hmg_qline/main.dart ' ;
import ' package:hmg_qline/models/generic_response_model.dart ' ;
import ' package:hmg_qline/models/global_config_model.dart ' ;
import ' package:hmg_qline/models/kiosk_language_config_model.dart ' ;
@ -12,33 +14,53 @@ import 'package:hmg_qline/models/prayers_widget_model.dart';
import ' package:hmg_qline/models/rss_feed_model.dart ' ;
import ' package:hmg_qline/models/weathers_widget_model.dart ' ;
import ' package:hmg_qline/repositories/screen_details_repo.dart ' ;
import ' package:hmg_qline/repositories/signalR_repo.dart ' ;
import ' package:hmg_qline/services/cache_service.dart ' ;
import ' package:hmg_qline/services/connectivity_service.dart ' ;
import ' package:hmg_qline/services/logger_service.dart ' ;
import ' package:hmg_qline/utilities/enums.dart ' ;
import ' package:hmg_qline/utilities/extensions.dart ' ;
import ' package:hmg_qline/utilities/native_method_handler.dart ' ;
import ' package:hmg_qline/view_models/queuing_view_model.dart ' ;
import ' package:hmg_qline/views/view_helpers/info_components.dart ' ;
import ' package:qr_code_scanner_plus/qr_code_scanner_plus.dart ' ;
/ / import ' package:timezone/browser.dart ' as tz ;
class ScreenConfigViewModel extends ChangeNotifier {
final ScreenDetailsRepo screenDetailsRepo ;
final CacheService cacheService ;
final ConnectivityService connectivityService ;
final LoggerService loggerService ;
final NativeMethodChannelService nativeMethodChannelService ;
ScreenConfigViewModel ( {
required this . screenDetailsRepo ,
required this . cacheService ,
required this . connectivityService ,
required this . loggerService ,
required this . nativeMethodChannelService ,
} ) ;
Future < void > initializeScreenConfigVM ( ) async {
await getGlobalConfigurationsByIP ( ) ;
await getInfoWidgetsDetailsFromServer ( ) ;
await getLastTimeUpdatedFromCache ( ) ;
await getLastTimeLogsClearedFromCache ( ) ;
listenNetworkConnectivity ( ) ;
getTheWidgetsConfigurationsEveryMidnight ( ) ;
}
Future < void > onAppResumed ( ) async {
loggerService . logToFile ( message: " [didChangeAppLifecycleState] : [onAppResumed] " , source : " onAppResumed -> screen_config_view_model.dart " , type: LogTypeEnum . data ) ;
}
Future < void > onAppPaused ( ) async {
loggerService . logToFile ( message: " [didChangeAppLifecycleState] : [onAppPaused] " , source : " onAppPaused -> screen_config_view_model.dart " , type: LogTypeEnum . data ) ;
/ / nativeMethodChannelService . reopenApp ( ) ;
nativeMethodChannelService . restartApp ( ) ;
/ / runApp ( const MyApp ( ) ) ;
}
Future < void > waitForIPAndInitializeConfigVM ( ) async {
while ( currentScreenIP = = " " ) {
await getCurrentScreenIP ( ) ;
@ -100,22 +122,27 @@ class ScreenConfigViewModel extends ChangeNotifier {
}
void listenNetworkConnectivity ( ) {
return connectivityService . subscribeToConnectivityChange ( onInternetDisConnected: ( ) {
updateIsInternetConnected ( false ) ;
updateIsHubConnected ( false ) ;
} , onInternetConnected: ( ) {
updateIsInternetConnected ( true ) ;
QueuingViewModel queuingViewModel = getIt . get < QueuingViewModel > ( ) ;
queuingViewModel . startHubConnection ( ) ;
} ) ;
return connectivityService . subscribeToConnectivityChange (
onInternetDisConnected: ( ) {
updateIsInternetConnected ( false ) ;
updateIsHubConnected ( false ) ;
} ,
onInternetConnected: ( ) {
updateIsInternetConnected ( true ) ;
QueuingViewModel queuingViewModel = getIt . get < QueuingViewModel > ( ) ;
queuingViewModel . startHubConnection ( ) ;
} ,
) ;
}
GlobalConfigurationsModel globalConfigurationsModel = GlobalConfigurationsModel ( ) ;
Future < void > getGlobalConfigurationsByIP ( ) async {
GlobalConfigurationsModel ? response = await screenDetailsRepo . getGlobalScreenConfigurations ( ipAddress: currentScreenIP ) ;
if ( response = = null ) {
log ( " response; $ response " ) ;
loggerService . logError ( " response was: $ response " ) ;
updateViewState ( ViewState . error ) ;
return ;
}
updateGlobalConfigurationsModel ( value: response ) ;
@ -127,6 +154,7 @@ class ScreenConfigViewModel extends ChangeNotifier {
void updateGlobalConfigurationsModel ( { required var value , bool needNotify = false , bool shouldUpdateNextPrayer = false } ) {
globalConfigurationsModel = value ;
if ( needNotify ) {
notifyListeners ( ) ;
}
@ -188,7 +216,7 @@ class ScreenConfigViewModel extends ChangeNotifier {
Future < void > getWeatherDetailsFromServer ( ) async {
int testCityKey = 297030 ;
WeathersWidgetModel ? response = await screenDetailsRepo . getWeatherDetailsByCity (
cityId: ( globalConfigurationsModel . cityKey = = 0 ? testCityKey : globalConfigurationsModel . cityKey ) . toString ( ) ,
cityId: ( ( globalConfigurationsModel . cityKey = = null | | globalConfigurationsModel . cityKey = = 0 ) ? testCityKey : globalConfigurationsModel . cityKey ) . toString ( ) ,
) ;
if ( response = = null ) {
@ -202,12 +230,20 @@ class ScreenConfigViewModel extends ChangeNotifier {
void getNextPrayerToShow ( ) async {
final current = DateTime . now ( ) ;
log ( " Checking Namaz time Locally at ${ current . toString ( ) } and ${ current . timeZoneName } " ) ;
log ( " Checking Namaz time Locally at $ current and ${ current . timeZoneName } " ) ;
/ / log ( " Data Before Check : ${ prayersWidgetModel . fajr } " ) ;
/ / log ( " Data Before Check : ${ globalConfigurationsModel . isPrayerTimeReq } " ) ;
if ( globalConfigurationsModel . isPrayerTimeReq & & prayersWidgetModel . fajr = = null ) {
await getPrayerDetailsFromServer ( ) ;
}
/ / log ( " prayersWidgetModel.dhuhr: ${ prayersWidgetModel . dhuhr ! } " ) ;
/ / log ( " dhuhr: ${ prayersWidgetModel . dhuhr ! . toDateTimeFromInt ( ) } " ) ;
/ / log ( " current: ${ DateFormat ( ' yyyy-MM-dd hh:mm a ' ) . format ( DateTime . now ( ) . toLocal ( ) ) } " ) ;
/ / log ( " current: ${ DateTime . now ( ) . timeZoneName } " ) ;
if ( prayersWidgetModel . fajr ! = null & & prayersWidgetModel . fajr ! . toDateTimeFromInt ( ) . isAfter ( current ) ) {
final namazTime = prayersWidgetModel . fajr ! . toFormattedDateTimeFromInt ( ) ;
nextPrayerToShowWithTime = " ${ globalConfigurationsModel . fajarText } at $ namazTime " ;
@ -238,54 +274,69 @@ class ScreenConfigViewModel extends ChangeNotifier {
notifyListeners ( ) ;
return ;
}
final namazTime = prayersWidgetModel . fajr ! . toFormattedDateTimeFromInt ( ) ;
nextPrayerToShowWithTime = " ${ globalConfigurationsModel . fajarText } at $ namazTime " ;
notifyListeners ( ) ;
return ;
}
int counter = 0 ;
DateTime lastChecked = DateTime . now ( ) ;
Timer ? _midnightTimer ;
Future < void > getTheWidgetsConfigurationsEveryMidnight ( ) async {
/ / Cancel any existing timer to avoid multiple timers running
_midnightTimer ? . cancel ( ) ;
if ( ! ( globalConfigurationsModel . isWeatherReq ) & & ! ( globalConfigurationsModel . isPrayerTimeReq ) & & ! ( globalConfigurationsModel . isRssFeedReq ) ) {
return ;
}
DateTime current = DateTime . now ( ) ;
Stream timer = Stream . periodic ( const Duration ( minutes: 1 ) , ( i ) {
current = current . add ( const Duration ( minutes: 1 ) ) ;
return current ;
} ) ;
timer . listen ( ( data ) async {
DateTime dateTime = DateTime . parse ( data . toString ( ) ) ;
/ / Only start timer if not already running
if ( _midnightTimer ! = null ) {
return ;
}
_midnightTimer = Timer . periodic ( const Duration ( minutes: 1 ) , ( timer ) async {
counter + + ;
DateTime now = DateTime . now ( ) ;
log ( " counterValue: $ counter " ) ;
if ( counter = = 60 & & globalConfigurationsModel . isRssFeedReq ) {
/ / Every hour , update RSS feed if required
if ( counter % 60 = = 0 & & globalConfigurationsModel . isRssFeedReq ) {
await getRssFeedDetailsFromServer ( ) ;
}
if ( globalConfigurationsModel . isWeatherReq ) {
if ( dateTime . day > currentLastTimeUpdated . day ) {
await getWeatherDetailsFromServer ( ) ;
}
}
if ( globalConfigurationsModel . isPrayerTimeReq ) {
if ( dateTime . day > currentLastTimeUpdated . day ) {
await getPrayerDetailsFromServer ( ) ;
}
}
if ( globalConfigurationsModel . isRssFeedReq ) {
if ( dateTime . day > currentLastTimeUpdated . day ) {
await getRssFeedDetailsFromServer ( ) ;
log ( " lastChecked: [ ${ lastChecked . day } ] " ) ;
log ( " now: [ ${ now . day } ] " ) ;
/ / At midnight , update weather and prayer details if required
if ( now . day ! = lastChecked . day ) {
if ( now . difference ( now . copyWith ( hour: 0 , minute: 0 , second: 0 , millisecond: 0 , microsecond: 0 ) ) . inMinutes > = 5 ) {
if ( globalConfigurationsModel . isWeatherReq ) {
await getWeatherDetailsFromServer ( ) ;
}
if ( globalConfigurationsModel . isPrayerTimeReq ) {
await getPrayerDetailsFromServer ( ) ;
}
lastChecked = now ;
}
}
getNextPrayerToShow ( ) ;
syncHubConnectionState ( ) ;
} ) ;
}
@ override
void dispose ( ) {
_midnightTimer ? . cancel ( ) ;
patientIdController . dispose ( ) ;
super . dispose ( ) ;
}
DateTime currentLastTimeUpdated = DateTime . now ( ) ;
Future < void > getLastTimeUpdatedFromCache ( ) async {
@ -295,6 +346,15 @@ class ScreenConfigViewModel extends ChangeNotifier {
}
}
DateTime ? lastTimeLogsCleared = DateTime . now ( ) ;
Future < void > getLastTimeLogsClearedFromCache ( ) async {
lastTimeLogsCleared = await cacheService . getLastTimeLogsCleared ( ) ;
if ( lastTimeLogsCleared = = null ) {
await cacheService . setLastTimeLogsCleared ( lastTimeCleared: DateTime . now ( ) . millisecondsSinceEpoch ) . whenComplete ( ( ) = > lastTimeLogsCleared = DateTime . now ( ) ) ;
}
}
/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * KIOSK FUNCTIONS * * * * * * * * * * * * * * * * * * * * * * * * *
KioskScreenStateEnums kioskScreenStateEnum = KioskScreenStateEnums . languageState ;
@ -364,28 +424,42 @@ class ScreenConfigViewModel extends ChangeNotifier {
patientId: patientId ,
) ;
if ( response = = null | | response . messageStatus ! = 1 ) {
logger . e ( " response null from createTicketFromKiosk " ) ;
logger Service. logError ( " response null from createTicketFromKiosk " ) ;
return null ;
}
return response . data ;
} catch ( e ) {
InfoComponents . showToast ( e . toString ( ) ) ;
logger . i ( e . toString ( ) ) ;
logger Service. logError ( e . toString ( ) ) ;
return null ;
}
}
Future < void > acknowledgeTicket ( { required String ticketQueueID } ) async {
Future < void > acknowledgeTicket ( { required int ticketQueueID } ) async {
GenericRespModel ? response = await screenDetailsRepo . acknowledgeTicket (
ipAddress: currentScreenIP ,
ticketQueueID: ticketQueueID ,
qTypeEnum: globalConfigurationsModel . qTypeEnum ,
) ;
if ( response = = null | | response . messageStatus ! = 1 ) {
logger . e ( " response null from acknowledgeTicket " ) ;
logger Service. logError ( " response null from acknowledgeTicket " ) ;
return ;
} else {
logger . i ( " response from acknowledgeTicket ${ response . data } " ) ;
loggerService . logInfo ( " response from acknowledgeTicket ${ response . data } " ) ;
}
}
Future < void > acknowledgeTicketForAppointmentOnly ( { required int ticketQueueID , required String ipAddress , required CallTypeEnum callTypeEnum } ) async {
GenericRespModel ? response = await screenDetailsRepo . acknowledgeTicketForAppointment (
ticketId: ticketQueueID ,
ipAddress: ipAddress ,
callTypeEnum: callTypeEnum ,
) ;
if ( response = = null | | response . messageStatus ! = 1 ) {
loggerService . logError ( " response null from acknowledgeTicketForAppointmentOnly " ) ;
return ;
} else {
loggerService . logInfo ( " response from acknowledgeTicketForAppointmentOnly ${ response . data } " ) ;
}
}
@ -393,12 +467,6 @@ class ScreenConfigViewModel extends ChangeNotifier {
final TextEditingController patientIdController = TextEditingController ( ) ;
@ override
void dispose ( ) {
patientIdController . dispose ( ) ;
super . dispose ( ) ;
}
Future < void > onPatientIdSubmitted ( String text ) async {
int ? patientId = int . tryParse ( text ) ;
if ( patientId ! = null & & patientId > 0 ) {
@ -427,7 +495,7 @@ class ScreenConfigViewModel extends ChangeNotifier {
qrViewController = controller ;
controller . scannedDataStream . listen ( ( scanData ) async {
logger . i ( " Found: ${ scanData . code } and isGeneratingTicket: $ isGeneratingTicket " ) ;
logger Service. logInfo ( " Found: ${ scanData . code } and isGeneratingTicket: $ isGeneratingTicket " ) ;
if ( isGeneratingTicket ) return ;
await validateAndGenerateTicketFromQR ( data: scanData , onFailure: onFailure , onSuccess: onSuccess ) ;
} ) ;
@ -466,4 +534,20 @@ class ScreenConfigViewModel extends ChangeNotifier {
await qrViewController ! . flipCamera ( ) ;
}
}
void syncHubConnectionState ( ) async {
QueuingViewModel queuingViewModel = getIt . get < QueuingViewModel > ( ) ;
bool newState = ( queuingViewModel . signalrRepo as SignalrRepoImp ) . isConnected ;
if ( isHubConnected ! = newState ) {
updateIsHubConnected ( newState ) ;
}
if ( ! isHubConnected ) {
log ( " Hub is Not Connected!, I will try to reconnect now. " ) ;
QueuingViewModel queuingViewModel = getIt . get < QueuingViewModel > ( ) ;
bool ? status = await queuingViewModel . startHubConnection ( ) ;
/ / syncHubConnectionState will update isHubConnected
} else {
log ( " Hub is Connected! " ) ;
}
}
}