// ignore_for_file: use_build_context_synchronously
import ' dart:developer ' ;
import ' package:flutter/cupertino.dart ' ;
import ' package:mc_common_app/classes/app_state.dart ' ;
import ' package:mc_common_app/classes/consts.dart ' ;
import ' package:mc_common_app/extensions/string_extensions.dart ' ;
import ' package:mc_common_app/generated/locale_keys.g.dart ' ;
import ' package:mc_common_app/main.dart ' ;
import ' package:mc_common_app/models/chat_models/chat_message_model.dart ' ;
import ' package:mc_common_app/models/general_models/generic_resp_model.dart ' ;
import ' package:mc_common_app/models/requests_models/provider_offers_model.dart ' ;
import ' package:mc_common_app/repositories/chat_repo.dart ' ;
import ' package:mc_common_app/repositories/request_repo.dart ' ;
import ' package:mc_common_app/utils/enums.dart ' ;
import ' package:mc_common_app/utils/utils.dart ' ;
import ' package:mc_common_app/view_models/requests_view_model.dart ' ;
import ' package:provider/provider.dart ' ;
import ' package:signalr_core/signalr_core.dart ' ;
import ' package:easy_localization/easy_localization.dart ' ;
class ChatVM extends ChangeNotifier {
final ChatRepo chatRepo ;
final RequestRepo requestRepo ;
ChatVM ( { required this . chatRepo , required this . requestRepo } ) ;
HubConnection ? hubConnection ;
String chatMessageText = " " ;
updateChatMessageText ( String value ) {
chatMessageText = value ;
}
clearChatMessageText ( ) {
chatMessageText = " " ;
notifyListeners ( ) ;
}
int latestOfferId = 0 ;
updateLatestOfferId ( var value ) {
latestOfferId = value ;
notifyListeners ( ) ;
}
List < OfferRequestCommentModel > offerRejectModelList = [
OfferRequestCommentModel (
index: 0 ,
isSelected: false ,
title: LocaleKeys . changedMind . tr ( ) ,
) ,
OfferRequestCommentModel (
index: 1 ,
isSelected: false ,
title: LocaleKeys . veryHighPrice . tr ( ) ,
) ,
OfferRequestCommentModel (
index: 2 ,
isSelected: false ,
title: LocaleKeys . alreadySold . tr ( ) ,
) ,
OfferRequestCommentModel (
index: 3 ,
isSelected: true ,
title: LocaleKeys . otherVar . tr ( ) ,
) ,
] ;
void updateSelectionInOfferRejectModelList ( int index ) {
for ( var value in offerRejectModelList ) {
value . isSelected = false ;
}
offerRejectModelList [ index ] . isSelected = true ;
notifyListeners ( ) ;
}
String rejectOfferDescription = " " ;
String rejectOfferDescriptionError = " " ;
void updateRejectOfferDescription ( String value ) {
rejectOfferDescription = value ;
if ( value . isNotEmpty ) {
rejectOfferDescriptionError = " " ;
}
}
//REJECTING OFFER
bool isRejectOfferButtonValidated ( ) {
bool isValidated = true ;
if ( rejectOfferDescription . isEmpty ) {
rejectOfferDescriptionError = GlobalConsts . descriptionError ;
isValidated = false ;
} else {
rejectOfferDescriptionError = " " ;
}
notifyListeners ( ) ;
return isValidated ;
}
Future < void > onNewMessageReceived (
{ required List < ChatMessageModel > messages ,
required BuildContext context ,
bool isMyOwnOffer = false } ) async {
// log("message I received in onNewMessageReceived ${messages.first.toString()}");
if ( AppState ( ) . currentAppType = = AppType . customer ) {
for ( var msg in messages ) {
int providerIndex = serviceProviderOffersList . indexWhere (
( element ) = > element . providerUserId = = msg . senderUserID ) ;
if ( providerIndex ! = - 1 ) {
serviceProviderOffersList [ providerIndex ] . chatMessages ! . add ( msg ) ;
}
}
} else {
for ( var msg in messages ) {
// Where we need to call this function for saving a message in chat we will use receiverUserID and in those cases where received ID is null , it means it is a signal R call
int providerIndex = - 1 ;
if ( isMyOwnOffer ) {
providerIndex =
context . read < RequestsVM > ( ) . myFilteredRequests . indexWhere (
( element ) = > element . customerUserID = = msg . receiverUserID ,
) ;
} else {
providerIndex =
context . read < RequestsVM > ( ) . myFilteredRequests . indexWhere (
( element ) = > element . customerUserID = = msg . senderUserID ,
) ;
}
// log("here is it: $providerIndex");
// log("here is it: ${msg.senderUserID}");
// log("here is it: ${context.read<RequestsVM>().myFilteredRequests.first.customerUserID.toString()}");
if ( providerIndex ! = - 1 ) {
context
. read < RequestsVM > ( )
. addChatMessagesInRequestsModel ( msg: msg , index: providerIndex ) ;
}
}
}
notifyListeners ( ) ;
}
Future < void > buildHubConnection ( BuildContext context ) async {
if ( hubConnection = = null | |
hubConnection ! . state ! = HubConnectionState . connected ) {
try {
hubConnection = await chatRepo . getHubConnection ( ) ;
await hubConnection ! . start ( ) ;
hubConnection ! . on ( " ReceiveMessageRequestOffer " ,
( List < Object ? > ? arguments ) {
if ( arguments = = null | | arguments . isEmpty ) return ;
List < ChatMessageModel > chat = [ ] ;
for ( var message in arguments ) {
final chatMessage =
ChatMessageModel . fromJson ( message as Map < String , dynamic > ) ;
chat . add ( chatMessage ) ;
}
onNewMessageReceived ( messages: chat , context: context ) ;
logger . i ( " I received ping : ${ arguments . toString ( ) } " ) ;
} ) ;
} catch ( e ) {
logger . i ( " Error: ${ e . toString ( ) } " ) ;
}
notifyListeners ( ) ;
}
}
Future < bool > onSendMessageForRequestOffer ( {
required String receiverId ,
required ChatMessageTypeEnum chatMessageType ,
required String message ,
required int requestId ,
required String offerPrice ,
required BuildContext context ,
} ) async {
if ( hubConnection = = null | |
hubConnection ! . state ! = HubConnectionState . connected ) {
await buildHubConnection ( context ) ;
}
if ( hubConnection ! . state = = HubConnectionState . connected ) {
final providerId = AppState ( ) . getUser . data ! . userInfo ! . providerId ;
hubConnection ! . invoke (
" SendMessageRequestOffer " ,
args: < Object > [
< String , dynamic > {
" ReceiverUserID " : receiverId ,
" MessageType " : chatMessageType . getIdFromChatMessageTypeEnum ( ) ,
" ChatText " : message ,
" RequestID " : requestId ,
" ReqOfferID " : 0 ,
" ReqOffer " : < String , dynamic > {
" RequestID " : requestId ,
" Price " : double . parse ( offerPrice ) ,
" ServiceProviderID " : providerId ,
" OfferStatus " : RequestOfferStatusEnum . offer
. getIdFromRequestOfferStatusEnum ( ) ,
" Comment " : message ,
} ,
}
] ,
) . catchError ( ( e ) {
logger . i ( " error in invoking SendMessageRequestOffer: ${ e . toString ( ) } " ) ;
Utils . showToast ( e . toString ( ) ) ;
return false ;
} ) ;
}
return true ;
}
Future < bool > onTextMessageSend ( {
required String receiverId ,
required ChatMessageTypeEnum chatMessageType ,
required String message ,
required int requestId ,
required String offerPrice ,
required BuildContext context ,
} ) async {
if ( message . isEmpty ) return false ;
if ( hubConnection = = null | |
hubConnection ! . state ! = HubConnectionState . connected ) {
await buildHubConnection ( context ) ;
}
if ( hubConnection ! . state = = HubConnectionState . connected ) {
final userId = AppState ( ) . getUser . data ! . userInfo ! . userId . toString ( ) ;
final name = AppState ( ) . getUser . data ! . userInfo ! . firstName . toString ( ) ;
log ( " I have saved this: $ {(<String, dynamic>{
" ReceiverUserID " : receiverId ,
" SenderUserID " : userId ,
" MessageType " : chatMessageType . getIdFromChatMessageTypeEnum ( ) ,
" ChatText " : message ,
" RequestID " : requestId ,
" ReqOfferID " : latestOfferId ,
} ) . toString ( ) } " );
hubConnection ! . invoke (
" SendMessageRequestOffer " ,
args: < Object > [
< String , dynamic > {
" ReceiverUserID " : receiverId ,
" SenderUserID " : userId ,
" MessageType " : chatMessageType . getIdFromChatMessageTypeEnum ( ) ,
" ChatText " : message ,
" RequestID " : requestId ,
" ReqOfferID " : latestOfferId ,
}
] ,
) . catchError ( ( e ) {
logger . i ( " error in invoking SendMessageRequestOffer: ${ e . toString ( ) } " ) ;
Utils . showToast ( e . toString ( ) ) ;
return false ;
} ) ;
ChatMessageModel chatMessageModel = ChatMessageModel (
messageType: chatMessageType . getIdFromChatMessageTypeEnum ( ) ,
chatText: message ,
isMyMessage: true ,
requestID: requestId ,
senderName: name ,
senderUserID: userId ,
chatMessageTypeEnum: ChatMessageTypeEnum . freeText ,
receiverUserID: receiverId ,
) ;
if ( AppState ( ) . currentAppType = = AppType . customer ) {
int providerIndex = serviceProviderOffersList
. indexWhere ( ( element ) = > element . providerUserId = = receiverId ) ;
if ( providerIndex ! = - 1 ) {
serviceProviderOffersList [ providerIndex ]
. chatMessages !
. add ( chatMessageModel ) ;
}
} else {
int providerIndex = context
. read < RequestsVM > ( )
. myFilteredRequests
. indexWhere ( ( element ) = > element . customerUserID = = receiverId ) ;
if ( providerIndex ! = - 1 ) {
context . read < RequestsVM > ( ) . addChatMessagesInRequestsModel (
msg: chatMessageModel , index: providerIndex ) ;
}
}
return true ;
}
return false ;
}
List < ServiceProvidersOffers > serviceProviderOffersList = [ ] ;
Future < void > getOffersFromProvidersByRequest (
{ required int requestId , required BuildContext context } ) async {
try {
Utils . showLoading ( context ) ;
ProviderOffersModel providerOffersModel = await requestRepo
. getOffersFromProvidersByRequest ( requestId: requestId ) ;
Utils . hideLoading ( context ) ;
serviceProviderOffersList . clear ( ) ;
serviceProviderOffersList = providerOffersModel . serviceProviders ? ? [ ] ;
notifyListeners ( ) ;
} catch ( e ) {
logger . i ( e . toString ( ) ) ;
Utils . showToast ( e . toString ( ) ) ;
Utils . hideLoading ( context ) ;
}
}
Future < void > getUsersChatMessagesForCustomer ( {
required BuildContext context ,
required int providerId ,
required int requestOfferId ,
required int requestId ,
required int providerOfferIndex ,
} ) async {
try {
int customerId = AppState ( ) . getUser . data ! . userInfo ! . customerId ! ;
Utils . showLoading ( context ) ;
List < ChatMessageModel > chatMessages = await chatRepo . getUsersChatMessages (
providerId: providerId ,
customerId: customerId ,
requestOfferId: requestOfferId ,
requestId: requestId ) ;
serviceProviderOffersList [ providerOfferIndex ] . chatMessages = chatMessages ;
if ( serviceProviderOffersList [ providerOfferIndex ] . chatMessages ! = null ) {
for ( var message
in serviceProviderOffersList [ providerOfferIndex ] . chatMessages ! ) {
if ( message . chatMessageTypeEnum = = ChatMessageTypeEnum . offer ) {
updateLatestOfferId ( message . reqOfferID ? ? 0 ) ;
log ( " latestOfferId: $ latestOfferId " ) ;
}
}
}
Utils . hideLoading ( context ) ;
notifyListeners ( ) ;
} catch ( e ) {
logger . i ( e . toString ( ) ) ;
Utils . showToast ( e . toString ( ) ) ;
Utils . hideLoading ( context ) ;
}
}
Future < void > getUsersChatMessagesForProvider ( {
required BuildContext context ,
required int customerId ,
required int requestOfferId ,
required int requestId ,
required int customerRequestIndex ,
} ) async {
try {
int providerId = AppState ( ) . getUser . data ! . userInfo ! . providerId ! ;
Utils . showLoading ( context ) ;
List < ChatMessageModel > chatMessages = await chatRepo . getUsersChatMessages (
providerId: providerId ,
customerId: customerId ,
requestOfferId: requestOfferId ,
requestId: requestId ) ;
context . read < RequestsVM > ( ) . overwriteChatMessagesInRequestsModel (
messages: chatMessages , index: customerRequestIndex ) ;
Utils . hideLoading ( context ) ;
} catch ( e ) {
logger . i ( e . toString ( ) ) ;
Utils . showToast ( e . toString ( ) ) ;
Utils . hideLoading ( context ) ;
}
}
Future < int > onActionOfferTapped (
{ required BuildContext context ,
required RequestOfferStatusEnum requestOfferStatusEnum ,
required int reqOfferId } ) async {
try {
Utils . showLoading ( context ) ;
GenericRespModel genericRespModel =
await requestRepo . updateOfferRequestStatus (
requestOfferStatusEnum: requestOfferStatusEnum ,
requestOfferId: reqOfferId ) ;
Utils . hideLoading ( context ) ;
return genericRespModel . messageStatus = = 1 ? reqOfferId : - 1 ;
} catch ( e ) {
logger . i ( e . toString ( ) ) ;
Utils . showToast ( e . toString ( ) ) ;
Utils . hideLoading ( context ) ;
return - 1 ;
}
}
}