You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			693 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			693 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Dart
		
	
import 'dart:async';
 | 
						|
import 'dart:convert';
 | 
						|
import 'dart:io';
 | 
						|
 | 
						|
import 'package:easy_localization/easy_localization.dart';
 | 
						|
import 'package:flutter/cupertino.dart';
 | 
						|
import 'package:flutter/foundation.dart';
 | 
						|
import 'package:http/http.dart';
 | 
						|
import 'package:logger/logger.dart' as L;
 | 
						|
import 'package:logging/logging.dart';
 | 
						|
import 'package:mohem_flutter_app/api/api_client.dart';
 | 
						|
import 'package:mohem_flutter_app/app_state/app_state.dart';
 | 
						|
import 'package:mohem_flutter_app/classes/consts.dart';
 | 
						|
import 'package:mohem_flutter_app/classes/utils.dart';
 | 
						|
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
 | 
						|
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
 | 
						|
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as login;
 | 
						|
import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav;
 | 
						|
import 'package:mohem_flutter_app/widgets/image_picker.dart';
 | 
						|
import 'package:signalr_netcore/signalr_client.dart';
 | 
						|
import 'package:uuid/uuid.dart';
 | 
						|
 | 
						|
class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
 | 
						|
  ScrollController scrollController = ScrollController();
 | 
						|
  TextEditingController message = TextEditingController();
 | 
						|
  TextEditingController search = TextEditingController();
 | 
						|
  List<SingleUserChatModel> userChatHistory = [];
 | 
						|
  List<ChatUser>? pChatHistory, searchedChats;
 | 
						|
  late HubConnection hubConnection;
 | 
						|
  L.Logger logger = L.Logger();
 | 
						|
  bool hubConInitialized = false;
 | 
						|
 | 
						|
  bool isLoading = true;
 | 
						|
  bool isChatScreenActive = false;
 | 
						|
  late File selectedFile;
 | 
						|
  bool isFileSelected = false;
 | 
						|
  String sFileType = "";
 | 
						|
  bool isMsgReply = false;
 | 
						|
  List<SingleUserChatModel> repliedMsg = [];
 | 
						|
  List<ChatUser> favUsersList = [];
 | 
						|
  int paginationVal = 0;
 | 
						|
 | 
						|
  //Scroll
 | 
						|
  bool _firstAutoscrollExecuted = false;
 | 
						|
  bool _shouldAutoscroll = false;
 | 
						|
 | 
						|
  Future<void> getUserAutoLoginToken() async {
 | 
						|
    Response response = await ApiClient().postJsonForResponse(
 | 
						|
      "${ApiConsts.chatServerBaseApiUrl}user/externaluserlogin",
 | 
						|
      {
 | 
						|
        "employeeNumber": int.parse(
 | 
						|
          AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
 | 
						|
        ),
 | 
						|
        "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG"
 | 
						|
      },
 | 
						|
    );
 | 
						|
    login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(
 | 
						|
      response.body,
 | 
						|
    );
 | 
						|
 | 
						|
    if (userLoginResponse.response != null) {
 | 
						|
      hubConInitialized = true;
 | 
						|
      AppState().setchatUserDetails = userLoginResponse;
 | 
						|
      await buildHubConnection();
 | 
						|
    } else {
 | 
						|
      Utils.showToast(userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<List<ChatUser>?> getChatMemberFromSearch(String sName, int cUserId) async {
 | 
						|
    Response response = await ApiClient().getJsonForResponse(
 | 
						|
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId",
 | 
						|
      token: AppState().chatDetails!.response!.token,
 | 
						|
    );
 | 
						|
    return searchUserJsonModel(response.body);
 | 
						|
  }
 | 
						|
 | 
						|
  List<ChatUser> searchUserJsonModel(String str) => List<ChatUser>.from(json.decode(str).map((x) => ChatUser.fromJson(x)));
 | 
						|
 | 
						|
  void getUserRecentChats() async {
 | 
						|
    Response response = await ApiClient().getJsonForResponse(
 | 
						|
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}",
 | 
						|
      token: AppState().chatDetails!.response!.token,
 | 
						|
    );
 | 
						|
    ChatUserModel recentChat = userToList(response.body);
 | 
						|
 | 
						|
    Response favRes = await ApiClient().getJsonForResponse(
 | 
						|
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatFavoriteUsers}${AppState().chatDetails!.response!.id}",
 | 
						|
      token: AppState().chatDetails!.response!.token,
 | 
						|
    );
 | 
						|
    ChatUserModel favUList = userToList(favRes.body);
 | 
						|
    if (favUList.response != null) {
 | 
						|
      favUsersList = favUList.response!;
 | 
						|
      favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
 | 
						|
      for (dynamic user in recentChat.response!) {
 | 
						|
        for (dynamic favUser in favUList.response!) {
 | 
						|
          if (user.id == favUser.id) {
 | 
						|
            user.isFav = favUser.isFav;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    pChatHistory = recentChat.response == null ? [] : recentChat.response;
 | 
						|
    if (pChatHistory != null) pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
 | 
						|
 | 
						|
    searchedChats = pChatHistory;
 | 
						|
    isLoading = false;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future GetUserChatHistoryNotDeliveredAsync(int userId) async {
 | 
						|
    await hubConnection.invoke("GetUserChatHistoryNotDeliveredAsync", args: [userId]);
 | 
						|
    return "";
 | 
						|
  }
 | 
						|
 | 
						|
  void getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false}) async {
 | 
						|
    isLoading = true;
 | 
						|
    if (isNewChat) userChatHistory = [];
 | 
						|
    if (!loadMore) paginationVal = 0;
 | 
						|
    isChatScreenActive = true;
 | 
						|
    Response response = await ApiClient().getJsonForResponse(
 | 
						|
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$paginationVal",
 | 
						|
      token: AppState().chatDetails!.response!.token,
 | 
						|
    );
 | 
						|
    if (response.statusCode == 204) {
 | 
						|
      if (isNewChat) {
 | 
						|
        userChatHistory = [];
 | 
						|
      } else if (loadMore) {
 | 
						|
        // userChatHistory = [];
 | 
						|
        Utils.showToast("No More Data To Load");
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      if (loadMore) {
 | 
						|
        List<SingleUserChatModel> temp = getSingleUserChatModel(response.body).reversed.toList();
 | 
						|
        userChatHistory.addAll(temp);
 | 
						|
      } else {
 | 
						|
        userChatHistory = getSingleUserChatModel(response.body).reversed.toList();
 | 
						|
      }
 | 
						|
    }
 | 
						|
    isLoading = false;
 | 
						|
    await GetUserChatHistoryNotDeliveredAsync(senderUID);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void updateUserChatHistoryStatusAsync(List data) {
 | 
						|
    hubConnection.invoke("UpdateUserChatHistoryStatusAsync", args: [data]);
 | 
						|
  }
 | 
						|
 | 
						|
  List<SingleUserChatModel> getSingleUserChatModel(String str) => List<SingleUserChatModel>.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x)));
 | 
						|
 | 
						|
  ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str));
 | 
						|
 | 
						|
  Future<dynamic> uploadAttachments(String userId, File file) async {
 | 
						|
    dynamic result;
 | 
						|
    dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatMediaImageUploadUrl}'));
 | 
						|
    request.fields.addAll({'userId': userId, 'fileSource': '1'});
 | 
						|
    request.files.add(await MultipartFile.fromPath('files', file.path));
 | 
						|
    request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
 | 
						|
    try {
 | 
						|
      StreamedResponse response = await request.send();
 | 
						|
      if (response.statusCode == 200) {
 | 
						|
        result = jsonDecode(await response.stream.bytesToString());
 | 
						|
      } else {
 | 
						|
        result = [];
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      if (kDebugMode) {
 | 
						|
        print(e);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ;
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> buildHubConnection() async {
 | 
						|
    HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
 | 
						|
    hubConnection = HubConnectionBuilder()
 | 
						|
        .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
 | 
						|
        .withAutomaticReconnect(
 | 
						|
          retryDelays: <int>[2000, 5000, 10000, 20000],
 | 
						|
        )
 | 
						|
        .configureLogging(
 | 
						|
          Logger("Loggin"),
 | 
						|
        )
 | 
						|
        .build();
 | 
						|
    hubConnection.onclose(
 | 
						|
      ({Exception? error}) {},
 | 
						|
    );
 | 
						|
    hubConnection.onreconnecting(
 | 
						|
      ({Exception? error}) {},
 | 
						|
    );
 | 
						|
    hubConnection.onreconnected(
 | 
						|
      ({String? connectionId}) {},
 | 
						|
    );
 | 
						|
    if (hubConnection.state != HubConnectionState.Connected) {
 | 
						|
      await hubConnection.start();
 | 
						|
      hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
 | 
						|
      hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);
 | 
						|
      //   hubConnection.on("OnSeenChatUserAsync", onChatSeen);
 | 
						|
 | 
						|
      //hubConnection.on("OnUserTypingAsync", onUserTyping);
 | 
						|
      hubConnection.on("OnUserCountAsync", userCountAsync);
 | 
						|
      hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
 | 
						|
      hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
 | 
						|
      hubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void updateUserChatStatus(List<Object?>? args) {
 | 
						|
    dynamic items = args!.toList();
 | 
						|
    for (dynamic cItem in items[0]) {
 | 
						|
      for (SingleUserChatModel chat in userChatHistory) {
 | 
						|
        if (chat.userChatHistoryId.toString() == cItem["userChatHistoryId"].toString()) {
 | 
						|
          chat.isSeen = cItem["isSeen"];
 | 
						|
          chat.isDelivered = cItem["isDelivered"];
 | 
						|
          notifyListeners();
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void onChatSeen(List<Object?>? args) {
 | 
						|
    dynamic items = args!.toList();
 | 
						|
    logger.d("---------------------------------Chat Seen  -------------------------------------");
 | 
						|
    logger.d(items);
 | 
						|
    // for (var user in searchedChats!) {
 | 
						|
    //   if (user.id == items.first["id"]) {
 | 
						|
    //     user.userStatus = items.first["userStatus"];
 | 
						|
    //   }
 | 
						|
    // }
 | 
						|
    // notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void userCountAsync(List<Object?>? args) {
 | 
						|
    dynamic items = args!.toList();
 | 
						|
    // logger.d(items);
 | 
						|
    //logger.d("---------------------------------User Count Async -------------------------------------");
 | 
						|
    //logger.d(items);
 | 
						|
    // for (var user in searchedChats!) {
 | 
						|
    //   if (user.id == items.first["id"]) {
 | 
						|
    //     user.userStatus = items.first["userStatus"];
 | 
						|
    //   }
 | 
						|
    // }
 | 
						|
    // notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void updateChatHistoryWindow(List<Object?>? args) {
 | 
						|
    dynamic items = args!.toList();
 | 
						|
    print("---------------------------------Update Chat History Windows  Async -------------------------------------");
 | 
						|
    logger.d(items);
 | 
						|
    // for (var user in searchedChats!) {
 | 
						|
    //   if (user.id == items.first["id"]) {
 | 
						|
    //     user.userStatus = items.first["userStatus"];
 | 
						|
    //   }
 | 
						|
    // }
 | 
						|
    // notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void chatNotDelivered(List<Object?>? args) {
 | 
						|
    dynamic items = args!.toList();
 | 
						|
    for (dynamic item in items[0]) {
 | 
						|
      dynamic data = [
 | 
						|
        {
 | 
						|
          "userChatHistoryId": item["userChatHistoryId"],
 | 
						|
          "TargetUserId": item["targetUserId"],
 | 
						|
          "isDelivered": true,
 | 
						|
          "isSeen": true,
 | 
						|
        }
 | 
						|
      ];
 | 
						|
      updateUserChatHistoryStatusAsync(data);
 | 
						|
    }
 | 
						|
    logger.d(items);
 | 
						|
    // for (var user in searchedChats!) {
 | 
						|
    //   if (user.id == items.first["id"]) {
 | 
						|
    //     user.userStatus = items.first["userStatus"];
 | 
						|
    //   }
 | 
						|
    // }
 | 
						|
    // notifyListeners();2
 | 
						|
  }
 | 
						|
 | 
						|
  void changeStatus(List<Object?>? args) {
 | 
						|
    if (kDebugMode) {
 | 
						|
      // print("================= Status Online // Offline  ====================");
 | 
						|
    }
 | 
						|
    dynamic items = args!.toList();
 | 
						|
    // logger.d(items);
 | 
						|
    for (ChatUser user in searchedChats!) {
 | 
						|
      if (user.id == items.first["id"]) {
 | 
						|
        user.userStatus = items.first["userStatus"];
 | 
						|
      }
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void filter(String value) async {
 | 
						|
    List<ChatUser>? tmp = [];
 | 
						|
    if (value.isEmpty || value == "") {
 | 
						|
      tmp = pChatHistory;
 | 
						|
    } else {
 | 
						|
      for (ChatUser element in pChatHistory!) {
 | 
						|
        if (element.userName!.toLowerCase().contains(value.toLowerCase())) {
 | 
						|
          tmp.add(element);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    searchedChats = tmp;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onMsgReceived(List<Object?>? parameters) async {
 | 
						|
    List<SingleUserChatModel> data = [];
 | 
						|
    List<SingleUserChatModel> temp = [];
 | 
						|
    for (dynamic msg in parameters!) {
 | 
						|
      data = getSingleUserChatModel(jsonEncode(msg));
 | 
						|
      temp = getSingleUserChatModel(jsonEncode(msg));
 | 
						|
      data.first.targetUserId = temp.first.currentUserId;
 | 
						|
      data.first.targetUserName = temp.first.currentUserName;
 | 
						|
      data.first.currentUserId = temp.first.targetUserId;
 | 
						|
      data.first.currentUserName = temp.first.targetUserName;
 | 
						|
    }
 | 
						|
    userChatHistory.insert(0, data.first);
 | 
						|
    // searchedChats!.forEach((element) {
 | 
						|
    //   if (element.id == data.first.currentUserId) {
 | 
						|
    //     var val = element.unreadMessageCount == null ? 0 : element.unreadMessageCount;
 | 
						|
    //     element.unreadMessageCount = val! + 1;
 | 
						|
    //   }
 | 
						|
    // });
 | 
						|
 | 
						|
    var list = [
 | 
						|
      {
 | 
						|
        "userChatHistoryId": data.first.userChatHistoryId,
 | 
						|
        "TargetUserId": data.first.targetUserId,
 | 
						|
        "isDelivered": true,
 | 
						|
        "isSeen": isChatScreenActive ? true : false,
 | 
						|
      }
 | 
						|
    ];
 | 
						|
    updateUserChatHistoryStatusAsync(list);
 | 
						|
 | 
						|
    notifyListeners();
 | 
						|
    //  if (isChatScreenActive) scrollToBottom();
 | 
						|
  }
 | 
						|
 | 
						|
  void onUserTyping(List<Object?>? parameters) {
 | 
						|
    //  print("==================== Typing Active ==================");
 | 
						|
    //   logger.d(parameters);
 | 
						|
    for (ChatUser user in searchedChats!) {
 | 
						|
      if (user.id == parameters![1] && parameters[0] == true) {
 | 
						|
        user.isTyping = parameters[0] as bool?;
 | 
						|
        Future.delayed(
 | 
						|
          const Duration(seconds: 2),
 | 
						|
          () {
 | 
						|
            user.isTyping = false;
 | 
						|
            notifyListeners();
 | 
						|
          },
 | 
						|
        );
 | 
						|
      }
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  int getFileType(String value) {
 | 
						|
    switch (value) {
 | 
						|
      case ".pdf":
 | 
						|
        return 1;
 | 
						|
      case ".png":
 | 
						|
        return 3;
 | 
						|
      case ".txt":
 | 
						|
        return 5;
 | 
						|
      case ".jpg":
 | 
						|
        return 12;
 | 
						|
      case ".jpeg":
 | 
						|
        return 4;
 | 
						|
      case ".xls":
 | 
						|
        return 7;
 | 
						|
      case ".xlsx":
 | 
						|
        return 7;
 | 
						|
      case ".doc":
 | 
						|
        return 6;
 | 
						|
      case ".docx":
 | 
						|
        return 6;
 | 
						|
      case ".ppt":
 | 
						|
        return 8;
 | 
						|
      case ".pptx":
 | 
						|
        return 8;
 | 
						|
      case ".zip":
 | 
						|
        return 2;
 | 
						|
      case ".rar":
 | 
						|
        return 2;
 | 
						|
      default:
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  String getFileTypeDescription(String value) {
 | 
						|
    switch (value) {
 | 
						|
      case ".pdf":
 | 
						|
        return "application/pdf";
 | 
						|
      case ".png":
 | 
						|
        return "image/png";
 | 
						|
      case ".txt":
 | 
						|
        return "text/plain";
 | 
						|
      case ".jpg":
 | 
						|
        return "image/jpg";
 | 
						|
      case ".jpeg":
 | 
						|
        return "image/jpeg";
 | 
						|
      case ".ppt":
 | 
						|
        return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
 | 
						|
      case ".pptx":
 | 
						|
        return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
 | 
						|
      case ".doc":
 | 
						|
        return "application/vnd.openxmlformats-officedocument.wordprocessingm";
 | 
						|
      case ".docx":
 | 
						|
        return "application/vnd.openxmlformats-officedocument.wordprocessingm";
 | 
						|
      case ".xls":
 | 
						|
        return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
 | 
						|
      case ".xlsx":
 | 
						|
        return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
 | 
						|
      case ".zip":
 | 
						|
        return "application/octet-stream";
 | 
						|
      case ".rar":
 | 
						|
        return "application/octet-stream";
 | 
						|
      default:
 | 
						|
        return "";
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> sendChatToServer(
 | 
						|
      {required int chatEventId, required fileTypeId, required int targetUserId, required String targetUserName, required chatReplyId, required bool isAttachment, required bool isReply}) async {
 | 
						|
    Uuid uuid = const Uuid();
 | 
						|
    var msg = message.text;
 | 
						|
    SingleUserChatModel data = SingleUserChatModel(
 | 
						|
      chatEventId: chatEventId,
 | 
						|
      chatSource: 1,
 | 
						|
      contant: msg,
 | 
						|
      contantNo: uuid.v4(),
 | 
						|
      conversationId: uuid.v4(),
 | 
						|
      createdDate: DateTime.now(),
 | 
						|
      currentUserId: AppState().chatDetails!.response!.id,
 | 
						|
      currentUserName: AppState().chatDetails!.response!.userName,
 | 
						|
      targetUserId: targetUserId,
 | 
						|
      targetUserName: targetUserName,
 | 
						|
      isReplied: false,
 | 
						|
      fileTypeId: fileTypeId,
 | 
						|
      userChatReplyResponse: isReply ? UserChatReplyResponse.fromJson(repliedMsg.first.toJson()) : null,
 | 
						|
      fileTypeResponse: isAttachment
 | 
						|
          ? FileTypeResponse(
 | 
						|
              fileTypeId: fileTypeId,
 | 
						|
              fileTypeName: getFileType(getFileExtension(selectedFile.path).toString()),
 | 
						|
              fileKind: getFileExtension(selectedFile.path),
 | 
						|
              fileName: selectedFile.path.split("/").last,
 | 
						|
              fileTypeDescription: getFileTypeDescription(getFileExtension(selectedFile.path).toString()),
 | 
						|
            )
 | 
						|
          : null,
 | 
						|
    );
 | 
						|
    userChatHistory.insert(0, data);
 | 
						|
    isFileSelected = false;
 | 
						|
    isMsgReply = false;
 | 
						|
    sFileType = "";
 | 
						|
    message.clear();
 | 
						|
    notifyListeners();
 | 
						|
 | 
						|
    String chatData =
 | 
						|
        '{"contant":"$msg","contantNo":"${uuid.v4()}","chatEventId":$chatEventId,"fileTypeId": $fileTypeId,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"chatReplyId":$chatReplyId,"conversationId":"${uuid.v4()}"}';
 | 
						|
    await hubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
 | 
						|
  }
 | 
						|
 | 
						|
  void sendChatMessage(int targetUserId, String targetUserName, BuildContext context) async {
 | 
						|
    dynamic contain = searchedChats!.where((ChatUser element) => element.id == targetUserId);
 | 
						|
    if (contain.isEmpty) {
 | 
						|
      searchedChats!.add(
 | 
						|
        ChatUser(
 | 
						|
          id: targetUserId,
 | 
						|
          userName: targetUserName,
 | 
						|
        ),
 | 
						|
      );
 | 
						|
      notifyListeners();
 | 
						|
    }
 | 
						|
    if (!isFileSelected && !isMsgReply) {
 | 
						|
      logger.d("Normal Text Message");
 | 
						|
      if (message.text == null || message.text.isEmpty) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      sendChatToServer(chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: false, chatReplyId: null, isReply: false);
 | 
						|
    }
 | 
						|
    if (isFileSelected && !isMsgReply) {
 | 
						|
      Utils.showLoading(context);
 | 
						|
      logger.d("Normal Attachment Message");
 | 
						|
      dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
 | 
						|
      String? ext = getFileExtension(selectedFile.path);
 | 
						|
      Utils.hideLoading(context);
 | 
						|
      sendChatToServer(chatEventId: 2, fileTypeId: getFileType(ext.toString()), targetUserId: targetUserId, targetUserName: targetUserName, isAttachment: true, chatReplyId: null, isReply: false);
 | 
						|
    }
 | 
						|
    if (!isFileSelected && isMsgReply) {
 | 
						|
      logger.d("Normal Text Message With Reply");
 | 
						|
      if (message.text == null || message.text.isEmpty) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      sendChatToServer(
 | 
						|
          chatEventId: 1, fileTypeId: null, targetUserId: targetUserId, targetUserName: targetUserName, chatReplyId: repliedMsg.first.userChatHistoryId, isAttachment: false, isReply: true);
 | 
						|
    }
 | 
						|
    if (isFileSelected && isMsgReply) {
 | 
						|
      logger.d("Attachment Message With Reply");
 | 
						|
      Utils.showLoading(context);
 | 
						|
      dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
 | 
						|
      String? ext = getFileExtension(selectedFile.path);
 | 
						|
      Utils.hideLoading(context);
 | 
						|
      sendChatToServer(
 | 
						|
        chatEventId: 2,
 | 
						|
        fileTypeId: getFileType(ext.toString()),
 | 
						|
        targetUserId: targetUserId,
 | 
						|
        targetUserName: targetUserName,
 | 
						|
        isAttachment: true,
 | 
						|
        chatReplyId: repliedMsg.first.userChatHistoryId,
 | 
						|
        isReply: true,
 | 
						|
      );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void selectImageToUpload(BuildContext context) {
 | 
						|
    ImageOptions.showImageOptionsNew(context, true, (String image, File file) async {
 | 
						|
      if (checkFileSize(file.path)) {
 | 
						|
        selectedFile = file;
 | 
						|
        isFileSelected = true;
 | 
						|
        sFileType = getFileExtension(file.path)!;
 | 
						|
        message.text = file.path.split("/").last;
 | 
						|
        Navigator.of(context).pop();
 | 
						|
      } else {
 | 
						|
        Utils.showToast("Max 1 mb size is allowed to upload");
 | 
						|
      }
 | 
						|
      notifyListeners();
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  void removeAttachment() {
 | 
						|
    isFileSelected = false;
 | 
						|
    sFileType = "";
 | 
						|
    message.text = '';
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  String? getFileExtension(String fileName) {
 | 
						|
    try {
 | 
						|
      return "." + fileName.split('.').last;
 | 
						|
    } catch (e) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  bool checkFileSize(String path) {
 | 
						|
    int fileSizeLimit = 1024;
 | 
						|
    File f = File(path);
 | 
						|
    double fileSizeInKB = f.lengthSync() / 1024;
 | 
						|
    double fileSizeInMB = fileSizeInKB / 1024;
 | 
						|
    if (fileSizeInKB > fileSizeLimit) {
 | 
						|
      return false;
 | 
						|
    } else {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  String getType(String type) {
 | 
						|
    switch (type) {
 | 
						|
      case ".pdf":
 | 
						|
        return "assets/images/pdf.svg";
 | 
						|
      case ".png":
 | 
						|
        return "assets/images/png.svg";
 | 
						|
      case ".txt":
 | 
						|
        return "assets/icons/chat/txt.svg";
 | 
						|
      case ".jpg":
 | 
						|
        return "assets/images/jpg.svg";
 | 
						|
      case ".jpeg":
 | 
						|
        return "assets/images/jpg.svg";
 | 
						|
      case ".xls":
 | 
						|
        return "assets/icons/chat/xls.svg";
 | 
						|
      case ".xlsx":
 | 
						|
        return "assets/icons/chat/xls.svg";
 | 
						|
      case ".doc":
 | 
						|
        return "assets/icons/chat/doc.svg";
 | 
						|
      case ".docx":
 | 
						|
        return "assets/icons/chat/doc.svg";
 | 
						|
      case ".ppt":
 | 
						|
        return "assets/icons/chat/ppt.svg";
 | 
						|
      case ".pptx":
 | 
						|
        return "assets/icons/chat/ppt.svg";
 | 
						|
      case ".zip":
 | 
						|
        return "assets/icons/chat/zip.svg";
 | 
						|
      case ".rar":
 | 
						|
        return "assets/icons/chat/zip.svg";
 | 
						|
      default:
 | 
						|
        return "assets/images/thumb.svg";
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void chatReply(SingleUserChatModel data) {
 | 
						|
    repliedMsg = [];
 | 
						|
    data.isReplied = true;
 | 
						|
    isMsgReply = true;
 | 
						|
    repliedMsg.add(data);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void closeMe() {
 | 
						|
    repliedMsg = [];
 | 
						|
    isMsgReply = false;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  String dateFormte(DateTime data) {
 | 
						|
    DateFormat f = DateFormat('hh:mm a dd MMM yyyy');
 | 
						|
    f.format(data);
 | 
						|
    return f.format(data);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> favoriteUser({required int userID, required int targetUserID}) async {
 | 
						|
    Response response =
 | 
						|
        await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
 | 
						|
    fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
 | 
						|
    if (favoriteChatUser.response != null) {
 | 
						|
      for (ChatUser user in searchedChats!) {
 | 
						|
        if (user.id == favoriteChatUser.response!.targetUserId!) {
 | 
						|
          user.isFav = favoriteChatUser.response!.isFav;
 | 
						|
          favUsersList.add(user);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> unFavoriteUser({required int userID, required int targetUserID}) async {
 | 
						|
    Response response = await ApiClient()
 | 
						|
        .postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}FavUser/deleteFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
 | 
						|
    fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
 | 
						|
    if (favoriteChatUser.response != null) {
 | 
						|
      for (var user in searchedChats!) {
 | 
						|
        if (user.id == favoriteChatUser.response!.targetUserId!) {
 | 
						|
          user.isFav = favoriteChatUser.response!.isFav;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      favUsersList.removeWhere((ChatUser element) => element.id == targetUserID);
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void clearSelections() {
 | 
						|
    searchedChats = pChatHistory;
 | 
						|
    search.clear();
 | 
						|
    isChatScreenActive = false;
 | 
						|
    paginationVal = 0;
 | 
						|
    message.text = '';
 | 
						|
    isFileSelected = false;
 | 
						|
    repliedMsg = [];
 | 
						|
    sFileType = "";
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void clearAll() {
 | 
						|
    searchedChats = pChatHistory;
 | 
						|
    search.clear();
 | 
						|
    isChatScreenActive = false;
 | 
						|
    paginationVal = 0;
 | 
						|
    message.text = '';
 | 
						|
    isFileSelected = false;
 | 
						|
    repliedMsg = [];
 | 
						|
    sFileType = "";
 | 
						|
  }
 | 
						|
 | 
						|
  void scrollListener() {
 | 
						|
    _firstAutoscrollExecuted = true;
 | 
						|
    if (scrollController.hasClients && scrollController.position.pixels == scrollController.position.maxScrollExtent) {
 | 
						|
      _shouldAutoscroll = true;
 | 
						|
    } else {
 | 
						|
      _shouldAutoscroll = false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void scrollToBottom() {
 | 
						|
    scrollController.animateTo(
 | 
						|
      scrollController.position.maxScrollExtent + 100,
 | 
						|
      duration: const Duration(milliseconds: 500),
 | 
						|
      curve: Curves.easeIn,
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  void msgScroll() {
 | 
						|
    scrollController.animateTo(
 | 
						|
      scrollController.position.minScrollExtent - 100,
 | 
						|
      duration: const Duration(milliseconds: 500),
 | 
						|
      curve: Curves.easeIn,
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |