|
|
|
@ -110,7 +110,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
disableChatForThisUser = false;
|
|
|
|
disableChatForThisUser = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isUserOnline = false;
|
|
|
|
isUserOnline = false;
|
|
|
|
if (Platform.isIOS) {
|
|
|
|
if (Platform.isIOS) {
|
|
|
|
AppState().setisUserOnline = false;
|
|
|
|
AppState().setisUserOnline = false;
|
|
|
|
@ -163,14 +162,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
chatHubConnection.on("OnUserTypingAsync", onUserTyping);
|
|
|
|
chatHubConnection.on("OnUserTypingAsync", onUserTyping);
|
|
|
|
chatHubConnection.on("OnUserCountAsync", userCountAsync);
|
|
|
|
chatHubConnection.on("OnUserCountAsync", userCountAsync);
|
|
|
|
// chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
|
|
|
|
// chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
|
|
|
|
chatHubConnection.on(
|
|
|
|
chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
|
|
|
|
"OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
|
|
|
|
chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
|
|
|
|
chatHubConnection.on(
|
|
|
|
chatHubConnection.on("OnGetGroupUserStatusAsync", getGroupUserStatus);
|
|
|
|
"OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
|
|
|
|
chatHubConnection.on("OnAddGroupChatHistoryAsync", groupChatHistoryAsync);
|
|
|
|
chatHubConnection.on(
|
|
|
|
|
|
|
|
"OnGetGroupUserStatusAsync", getGroupUserStatus);
|
|
|
|
|
|
|
|
chatHubConnection.on(
|
|
|
|
|
|
|
|
"OnAddGroupChatHistoryAsync", groupChatHistoryAsync);
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// {"type":1,"target":"","arguments":[[{"id":217869,"userName":"Sultan.Khan","email":"Sultan.Khan@cloudsolutions.com.sa","phone":null,"title":"Sultan.Khan","userStatus":1,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":false,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null},{"id":15153,"userName":"Tamer.Fanasheh","email":"Tamer.F@cloudsolutions.com.sa","phone":null,"title":"Tamer Fanasheh","userStatus":2,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":true,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null}]]}
|
|
|
|
// {"type":1,"target":"","arguments":[[{"id":217869,"userName":"Sultan.Khan","email":"Sultan.Khan@cloudsolutions.com.sa","phone":null,"title":"Sultan.Khan","userStatus":1,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":false,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null},{"id":15153,"userName":"Tamer.Fanasheh","email":"Tamer.F@cloudsolutions.com.sa","phone":null,"title":"Tamer Fanasheh","userStatus":2,"image":null,"unreadMessageCount":0,"userAction":3,"isPin":false,"isFav":false,"isAdmin":true,"rKey":null,"totalCount":0,"isHuaweiDevice":false,"deviceToken":null}]]}
|
|
|
|
|
|
|
|
|
|
|
|
@ -182,7 +177,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
Future<void> getUserRecentChats() async {
|
|
|
|
Future<void> getUserRecentChats() async {
|
|
|
|
ChatUserModel recentChat = await ChatApiClient().getRecentChats();
|
|
|
|
ChatUserModel recentChat = await ChatApiClient().getRecentChats();
|
|
|
|
ChatUserModel favUList = await ChatApiClient().getFavUsers();
|
|
|
|
ChatUserModel favUList = await ChatApiClient().getFavUsers();
|
|
|
|
userGroups = await ChatApiClient().getGroupsByUserId();
|
|
|
|
userGroups = await ChatApiClient().getGroupsByUserId();
|
|
|
|
if (favUList.response != null && recentChat.response != null) {
|
|
|
|
if (favUList.response != null && recentChat.response != null) {
|
|
|
|
favUsersList = favUList.response!;
|
|
|
|
favUsersList = favUList.response!;
|
|
|
|
favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
|
|
|
|
favUsersList.sort((ChatUser a, ChatUser b) => a.userName!.toLowerCase().compareTo(b.userName!.toLowerCase()));
|
|
|
|
@ -324,12 +319,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
notifyListeners();
|
|
|
|
notifyListeners();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void getGroupUserStatus(List<Object?>? args){
|
|
|
|
void getGroupUserStatus(List<Object?>? args) {
|
|
|
|
//note: need to implement this function when group user status
|
|
|
|
//note: need to implement this function when group user status
|
|
|
|
|
|
|
|
|
|
|
|
print(args);
|
|
|
|
print(args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void groupChatHistoryAsync(List<Object?>? args){
|
|
|
|
|
|
|
|
|
|
|
|
void groupChatHistoryAsync(List<Object?>? args) {
|
|
|
|
//need to imlement this event when any group details updated.
|
|
|
|
//need to imlement this event when any group details updated.
|
|
|
|
print(args);
|
|
|
|
print(args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -430,21 +426,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
data.first.currentUserName = temp.first.targetUserName;
|
|
|
|
data.first.currentUserName = temp.first.targetUserName;
|
|
|
|
data.first.currentUserEmail = temp.first.targetUserEmail;
|
|
|
|
data.first.currentUserEmail = temp.first.targetUserEmail;
|
|
|
|
if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) {
|
|
|
|
if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) {
|
|
|
|
data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg",fileSource: 1);
|
|
|
|
data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (data.first.userChatReplyResponse != null) {
|
|
|
|
if (data.first.userChatReplyResponse != null) {
|
|
|
|
if (data.first.fileTypeResponse != null) {
|
|
|
|
if (data.first.fileTypeResponse != null) {
|
|
|
|
if (data.first.userChatReplyResponse!.fileTypeId == 12 ||
|
|
|
|
if (data.first.userChatReplyResponse!.fileTypeId == 12 || data.first.userChatReplyResponse!.fileTypeId == 4 || data.first.userChatReplyResponse!.fileTypeId == 3) {
|
|
|
|
data.first.userChatReplyResponse!.fileTypeId == 4 ||
|
|
|
|
|
|
|
|
data.first.userChatReplyResponse!.fileTypeId == 3) {
|
|
|
|
|
|
|
|
data.first.userChatReplyResponse!.image = await ChatApiClient()
|
|
|
|
data.first.userChatReplyResponse!.image = await ChatApiClient()
|
|
|
|
.downloadURL(
|
|
|
|
.downloadURL(fileName: data.first.userChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 1);
|
|
|
|
fileName: data.first.userChatReplyResponse!.contant!,
|
|
|
|
|
|
|
|
fileTypeDescription:
|
|
|
|
|
|
|
|
data.first.fileTypeResponse!.fileTypeDescription ??
|
|
|
|
|
|
|
|
"image/jpg",
|
|
|
|
|
|
|
|
fileSource:1
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
data.first.userChatReplyResponse!.isImageLoaded = true;
|
|
|
|
data.first.userChatReplyResponse!.isImageLoaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -516,30 +504,14 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
// data.first.currentUserId = temp.first.currentUserId;
|
|
|
|
// data.first.currentUserId = temp.first.currentUserId;
|
|
|
|
// data.first.currentUserName = temp.first.currentUserName;
|
|
|
|
// data.first.currentUserName = temp.first.currentUserName;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (data.first.fileTypeId == 12 || data.first.fileTypeId == 4 || data.first.fileTypeId == 3) {
|
|
|
|
if (data.first.fileTypeId == 12 ||
|
|
|
|
data.first.image = await ChatApiClient().downloadURL(fileName: data.first.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 2);
|
|
|
|
data.first.fileTypeId == 4 ||
|
|
|
|
|
|
|
|
data.first.fileTypeId == 3) {
|
|
|
|
|
|
|
|
data.first.image = await ChatApiClient().downloadURL(
|
|
|
|
|
|
|
|
fileName: data.first.contant!,
|
|
|
|
|
|
|
|
fileTypeDescription:
|
|
|
|
|
|
|
|
data.first.fileTypeResponse!.fileTypeDescription ??
|
|
|
|
|
|
|
|
"image/jpg",
|
|
|
|
|
|
|
|
fileSource:2
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (data.first.groupChatReplyResponse != null) {
|
|
|
|
if (data.first.groupChatReplyResponse != null) {
|
|
|
|
if (data.first.fileTypeResponse != null) {
|
|
|
|
if (data.first.fileTypeResponse != null) {
|
|
|
|
if (data.first.groupChatReplyResponse!.fileTypeId == 12 ||
|
|
|
|
if (data.first.groupChatReplyResponse!.fileTypeId == 12 || data.first.groupChatReplyResponse!.fileTypeId == 4 || data.first.groupChatReplyResponse!.fileTypeId == 3) {
|
|
|
|
data.first.groupChatReplyResponse!.fileTypeId == 4 ||
|
|
|
|
|
|
|
|
data.first.groupChatReplyResponse!.fileTypeId == 3) {
|
|
|
|
|
|
|
|
data.first.groupChatReplyResponse!.image = await ChatApiClient()
|
|
|
|
data.first.groupChatReplyResponse!.image = await ChatApiClient()
|
|
|
|
.downloadURL(
|
|
|
|
.downloadURL(fileName: data.first.groupChatReplyResponse!.contant!, fileTypeDescription: data.first.fileTypeResponse!.fileTypeDescription ?? "image/jpg", fileSource: 2);
|
|
|
|
fileName: data.first.groupChatReplyResponse!.contant!,
|
|
|
|
|
|
|
|
fileTypeDescription:
|
|
|
|
|
|
|
|
data.first.fileTypeResponse!.fileTypeDescription ??
|
|
|
|
|
|
|
|
"image/jpg",
|
|
|
|
|
|
|
|
fileSource:2);
|
|
|
|
|
|
|
|
data.first.groupChatReplyResponse!.isImageLoaded = true;
|
|
|
|
data.first.groupChatReplyResponse!.isImageLoaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -932,8 +904,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) {
|
|
|
|
else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) {
|
|
|
|
logger.d("// Normal Image Message");
|
|
|
|
logger.d("// Normal Image Message");
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, '2');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), selectedFile,'2');
|
|
|
|
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendGroupChatToServer(
|
|
|
|
sendGroupChatToServer(
|
|
|
|
@ -953,8 +924,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
} else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) {
|
|
|
|
} else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) {
|
|
|
|
logger.d("// Image as Reply Msg");
|
|
|
|
logger.d("// Image as Reply Msg");
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, '2');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), selectedFile,'2');
|
|
|
|
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendGroupChatToServer(
|
|
|
|
sendGroupChatToServer(
|
|
|
|
@ -990,9 +960,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
isPlaying = false;
|
|
|
|
isPlaying = false;
|
|
|
|
isRecoding = false;
|
|
|
|
isRecoding = false;
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, '2');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), voiceFile,'2');
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendGroupChatToServer(
|
|
|
|
sendGroupChatToServer(
|
|
|
|
chatEventId: 2,
|
|
|
|
chatEventId: 2,
|
|
|
|
@ -1027,9 +996,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
isRecoding = false;
|
|
|
|
isRecoding = false;
|
|
|
|
|
|
|
|
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, '2');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), voiceFile,'2');
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendGroupChatToServer(
|
|
|
|
sendGroupChatToServer(
|
|
|
|
chatEventId: 2,
|
|
|
|
chatEventId: 2,
|
|
|
|
@ -1130,8 +1098,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) {
|
|
|
|
else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && !isReplyMsg) {
|
|
|
|
logger.d("// Normal Image Message");
|
|
|
|
logger.d("// Normal Image Message");
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, '1');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), selectedFile,'1');
|
|
|
|
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendChatToServer(
|
|
|
|
sendChatToServer(
|
|
|
|
@ -1150,8 +1117,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
} else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) {
|
|
|
|
} else if (!isTextMsg && isAttachmentMsg && !isVoiceMsg && isReplyMsg) {
|
|
|
|
logger.d("// Image as Reply Msg");
|
|
|
|
logger.d("// Image as Reply Msg");
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), selectedFile, '1');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), selectedFile,'1');
|
|
|
|
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
String? ext = getFileExtension(selectedFile.path);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendChatToServer(
|
|
|
|
sendChatToServer(
|
|
|
|
@ -1186,8 +1152,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
isPlaying = false;
|
|
|
|
isPlaying = false;
|
|
|
|
isRecoding = false;
|
|
|
|
isRecoding = false;
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, '1');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), voiceFile, '1');
|
|
|
|
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendChatToServer(
|
|
|
|
sendChatToServer(
|
|
|
|
@ -1221,8 +1186,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
isRecoding = false;
|
|
|
|
isRecoding = false;
|
|
|
|
|
|
|
|
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
dynamic value = await uploadAttachments(
|
|
|
|
dynamic value = await uploadAttachments(AppState().chatDetails!.response!.id.toString(), voiceFile, '1');
|
|
|
|
AppState().chatDetails!.response!.id.toString(), voiceFile, '1');
|
|
|
|
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
String? ext = getFileExtension(voiceFile.path);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
sendChatToServer(
|
|
|
|
sendChatToServer(
|
|
|
|
@ -1618,23 +1582,10 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future<void> getChatMedia(BuildContext context,
|
|
|
|
Future<void> getChatMedia(BuildContext context, {required String fileName, required String fileTypeName, required int fileTypeID, required int fileSource}) async {
|
|
|
|
{required String fileName,
|
|
|
|
|
|
|
|
required String fileTypeName,
|
|
|
|
|
|
|
|
required int fileTypeID,
|
|
|
|
|
|
|
|
required int fileSource}) async {
|
|
|
|
|
|
|
|
Utils.showLoading(context);
|
|
|
|
Utils.showLoading(context);
|
|
|
|
if (fileTypeID == 1 ||
|
|
|
|
if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 || fileTypeID == 2 || fileTypeID == 16) {
|
|
|
|
fileTypeID == 5 ||
|
|
|
|
Uint8List encodedString = await ChatApiClient().downloadURL(fileName: fileName, fileTypeDescription: getFileTypeDescription(fileTypeName), fileSource: fileSource);
|
|
|
|
fileTypeID == 7 ||
|
|
|
|
|
|
|
|
fileTypeID == 6 ||
|
|
|
|
|
|
|
|
fileTypeID == 8 ||
|
|
|
|
|
|
|
|
fileTypeID == 2 || fileTypeID ==16) {
|
|
|
|
|
|
|
|
Uint8List encodedString = await ChatApiClient().downloadURL(
|
|
|
|
|
|
|
|
fileName: fileName,
|
|
|
|
|
|
|
|
fileTypeDescription: getFileTypeDescription(fileTypeName),
|
|
|
|
|
|
|
|
fileSource: fileSource
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
String path = await downChatMedia(encodedString, fileTypeName ?? "");
|
|
|
|
String path = await downChatMedia(encodedString, fileTypeName ?? "");
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
|