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.
590 lines
21 KiB
Dart
590 lines
21 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();
|
|
List<SingleUserChatModel> userChatHistory = [];
|
|
List<ChatUser>? pChatHistory, searchedChats;
|
|
late HubConnection hubConnection;
|
|
L.Logger logger = L.Logger();
|
|
|
|
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 {
|
|
String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString();
|
|
Response response =
|
|
await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}user/desktopuserlogin", {"userName": userName, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "loginType": 2});
|
|
login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(response.body);
|
|
AppState().setchatUserDetails = userLoginResponse;
|
|
await buildHubConnection();
|
|
}
|
|
|
|
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;
|
|
pChatHistory!.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
|
|
searchedChats = pChatHistory;
|
|
isLoading = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
void getSingleUserChatHistory({required String senderUID, required int receiverUID, required bool loadMore}) async {
|
|
isLoading = true;
|
|
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 (!loadMore) userChatHistory = [];
|
|
Utils.showToast("No More Data To Load");
|
|
} else {
|
|
if (loadMore) {
|
|
List<SingleUserChatModel> temp = getSingleUserChatModel(response.body);
|
|
userChatHistory.insertAll(0, temp);
|
|
} else {
|
|
userChatHistory = getSingleUserChatModel(response.body);
|
|
}
|
|
}
|
|
isLoading = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
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) {}
|
|
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: [2000, 5000, 10000, 20000])
|
|
.configureLogging(
|
|
Logger("Logs Enabled"),
|
|
)
|
|
.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("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 userCountAsync(List<Object?>? args) {
|
|
dynamic items = args!.toList();
|
|
//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();
|
|
if (kDebugMode) {
|
|
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();
|
|
if (kDebugMode) {
|
|
print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------");
|
|
}
|
|
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.add(data.first);
|
|
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();
|
|
SingleUserChatModel data = SingleUserChatModel(
|
|
chatEventId: chatEventId,
|
|
chatSource: 1,
|
|
contant: message.text,
|
|
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,
|
|
);
|
|
String chatData =
|
|
'{"contant":"${message.text}","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)]);
|
|
userChatHistory.add(data);
|
|
isFileSelected = false;
|
|
isMsgReply = false;
|
|
sFileType = "";
|
|
message.clear();
|
|
scrollToBottom();
|
|
notifyListeners();
|
|
}
|
|
|
|
void sendChatMessage(int targetUserId, String targetUserName) 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) {
|
|
logger.d("Normal Attachment Message");
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
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");
|
|
logger.d(repliedMsg.first.userChatHistoryId);
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile);
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
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() {
|
|
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,
|
|
);
|
|
}
|
|
}
|