Can delete multiple messages on Edit mode

This commit is contained in:
Benoit Martins 2023-03-31 17:25:12 +02:00 committed by QuentinArguillere
parent 1fd242122f
commit c8e7e4591a
5 changed files with 131 additions and 60 deletions

View file

@ -24,8 +24,11 @@ class ChatConversationTableViewModel: ControlsViewModel {
var editModeOn = MutableLiveData<Bool>(false) var editModeOn = MutableLiveData<Bool>(false)
var messageSelected = MutableLiveData<Int>(0)
var messageListSelected = MutableLiveData<[Bool]>([]) var messageListSelected = MutableLiveData<[Bool]>([])
var messageListToDelete : [EventLog] = []
override init() { override init() {
super.init() super.init()
} }
@ -89,16 +92,34 @@ class ChatConversationTableViewModel: ControlsViewModel {
} }
func selectAllMessages(){ func selectAllMessages(){
for i in 0...messageListSelected.value!.count { for i in 0...messageListSelected.value!.count - 1 {
messageListSelected.value![i] = true messageListSelected.value![i] = true
messageSelected.value! += 1
} }
refreshIndexPath.value! += 1 refreshIndexPath.value! += 1
} }
func unSelectAllMessages(){ func unSelectAllMessages(){
for i in 0...messageListSelected.value!.count { for i in 0...messageListSelected.value!.count - 1 {
messageListSelected.value![i] = false messageListSelected.value![i] = false
} }
messageSelected.value! = 0
refreshIndexPath.value! += 1
}
func deleteMessagesSelected(){
for i in 0...(messageListSelected.value!.count - 1) {
if messageListSelected.value![i] == true {
let messageEvent = getMessage(index: i)
//if messageEvent
messageListToDelete.append((messageEvent)!)
}
}
messageListToDelete.forEach { chatMessage in
chatMessage.deleteFromDatabase()
}
messageSelected.value! = 0
refreshIndexPath.value! += 1 refreshIndexPath.value! += 1
} }
} }

View file

@ -138,43 +138,52 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour
} }
func scrollToBottomWithRelaod(){ func scrollToBottomWithRelaod(){
let isDisplayingBottomOfTable = collectionView.contentOffset.y <= 20 if (ChatConversationTableViewModel.sharedModel.getNBMessages() > 1){
collectionView.reloadData() let isDisplayingBottomOfTable = collectionView.contentOffset.y <= 20
if isDisplayingBottomOfTable { collectionView.reloadData()
self.collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .top, animated: false) if isDisplayingBottomOfTable {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { self.collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .top, animated: false)
self.scrollToBottomNewMessage() DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
} self.scrollToBottomNewMessage()
}else{ }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { }else{
self.scrollToBottom() DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
} self.scrollToBottom()
} }
if ChatConversationTableViewModel.sharedModel.editModeOn.value! { }
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.insert(false, at: 0) if ChatConversationTableViewModel.sharedModel.editModeOn.value! {
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.insert(false, at: 0)
}
}else{
collectionView.reloadData()
} }
} }
func refreshData(){ func refreshData(){
let indexBottom = collectionView.indexPathsForVisibleItems.sorted().first?.row if (ChatConversationTableViewModel.sharedModel.getNBMessages() > 1){
let isDisplayingBottomOfTable = collectionView.contentOffset.y <= 20 let indexBottom = collectionView.indexPathsForVisibleItems.sorted().first?.row
let sizeCell = (self.collectionView.cellForItem(at: IndexPath(row: indexBottom!, section: 0))?.frame.size.height) let isDisplayingBottomOfTable = collectionView.contentOffset.y <= 20
collectionView.reloadData() let sizeCell = (self.collectionView.cellForItem(at: IndexPath(row: indexBottom!, section: 0))?.frame.size.height)
collectionView.reloadData()
if isDisplayingBottomOfTable { if isDisplayingBottomOfTable {
self.collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .top, animated: false) self.collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .top, animated: false)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.scrollToBottomNewMessage() self.scrollToBottomNewMessage()
}
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: self.collectionView.contentOffset.y + sizeCell! + 2.0)
}
scrollBadge!.isHidden = false
scrollBadge!.text = "\(ChatConversationViewModel.sharedModel.chatRoom?.unreadMessagesCount ?? 0)"
} }
} else { if ChatConversationTableViewModel.sharedModel.editModeOn.value! {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { ChatConversationTableViewModel.sharedModel.messageListSelected.value!.insert(false, at: 0)
self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: self.collectionView.contentOffset.y + sizeCell! + 2.0)
} }
scrollBadge!.isHidden = false }else{
scrollBadge!.text = "\(ChatConversationViewModel.sharedModel.chatRoom?.unreadMessagesCount ?? 0)" collectionView.reloadData()
}
if ChatConversationTableViewModel.sharedModel.editModeOn.value! {
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.insert(false, at: 0)
} }
} }
@ -225,6 +234,9 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour
cell.imageViewBubble.onClick { cell.imageViewBubble.onClick {
self.onImageClick(chatMessage: event.chatMessage!, index: indexPath.row) self.onImageClick(chatMessage: event.chatMessage!, index: indexPath.row)
} }
cell.imageVideoViewBubble.onClick {
self.onImageClick(chatMessage: event.chatMessage!, index: indexPath.row)
}
} }
} }
@ -432,6 +444,7 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour
if ChatConversationTableViewModel.sharedModel.editModeOn.value! { if ChatConversationTableViewModel.sharedModel.editModeOn.value! {
let indexDeletedMessage = ChatConversationTableViewModel.sharedModel.getIndexMessage(message: message) let indexDeletedMessage = ChatConversationTableViewModel.sharedModel.getIndexMessage(message: message)
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.remove(at: indexDeletedMessage) ChatConversationTableViewModel.sharedModel.messageListSelected.value!.remove(at: indexDeletedMessage)
ChatConversationTableViewModel.sharedModel.messageSelected.value! -= 1
} }
message.chatRoom?.deleteMessage(message: message) message.chatRoom?.deleteMessage(message: message)
collectionView.reloadData() collectionView.reloadData()
@ -468,7 +481,7 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour
if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue) { if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue) {
print("Messsage not delivered") print("Messsage not delivered")
} else { } else {
if (VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) || ConfigManager.instance().lpConfigBoolForKey(key: "use_in_app_file_viewer_for_non_encrypted_files", section: "app")){ if ((VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) || ConfigManager.instance().lpConfigBoolForKey(key: "use_in_app_file_viewer_for_non_encrypted_files", section: "app")) && chatMessage.contents.first?.type == "image"){
let view: ImageView = VIEW(ImageView.compositeViewDescription()) let view: ImageView = VIEW(ImageView.compositeViewDescription())
let image = UIImage(contentsOfFile: chatMessage.contents.first!.filePath) let image = UIImage(contentsOfFile: chatMessage.contents.first!.filePath)
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription()) PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
@ -495,7 +508,7 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour
if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue) { if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue) {
print("Messsage not delivered") print("Messsage not delivered")
} else { } else {
if (VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) || ConfigManager.instance().lpConfigBoolForKey(key: "use_in_app_file_viewer_for_non_encrypted_files", section: "app")){ if ((VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) || ConfigManager.instance().lpConfigBoolForKey(key: "use_in_app_file_viewer_for_non_encrypted_files", section: "app")) && chatMessage!.contents[index].type == "image"){
let view: ImageView = VIEW(ImageView.compositeViewDescription()) let view: ImageView = VIEW(ImageView.compositeViewDescription())
let image = UIImage(contentsOfFile: chatMessage!.contents[index].filePath) let image = UIImage(contentsOfFile: chatMessage!.contents[index].filePath)
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription()) PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())

View file

@ -206,6 +206,18 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll
self.messageView.messageText.text = ChatConversationViewModel.sharedModel.shareFileMessage self.messageView.messageText.text = ChatConversationViewModel.sharedModel.shareFileMessage
self.confirmShare(ChatConversationViewModel.sharedModel.nsDataRead(), url: url, fileName: nil) self.confirmShare(ChatConversationViewModel.sharedModel.nsDataRead(), url: url, fileName: nil)
} }
ChatConversationTableViewModel.sharedModel.messageSelected.observe { result in
if ChatConversationTableViewModel.sharedModel.messageSelected.value! > 0 {
self.action1SelectAllButton.isHidden = true
self.action1DeselectAllButton.isHidden = false
self.action2Delete.isEnabled = true
}else{
self.action1SelectAllButton.isHidden = false
self.action1DeselectAllButton.isHidden = true
self.action2Delete.isEnabled = false
}
}
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@ -617,9 +629,9 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll
override func selectDeselectAll(){ override func selectDeselectAll(){
super.selectDeselectAll() super.selectDeselectAll()
if(action1SelectAllButton.isHidden){ if(action1SelectAllButton.isHidden){
//tableController.onSelectionToggle(action1SelectAllButton) ChatConversationTableViewModel.sharedModel.selectAllMessages()
}else{ }else{
//tableController.onSelectionToggle(action1SelectAllButton) ChatConversationTableViewModel.sharedModel.unSelectAllMessages()
} }
} }
@ -635,11 +647,11 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll
cancelMessage: nil, cancelMessage: nil,
confirmMessage: nil, confirmMessage: nil,
onCancelClick: { [self] in onCancelClick: { [self] in
onEditionChangeClick()}, //onEditionChangeClick()
},
onConfirmationClick: { onConfirmationClick: {
//self.tableController.removeSelection(nil) ChatConversationTableViewModel.sharedModel.deleteMessagesSelected()
self.editModeOff() self.editModeOff()
//self.tableController.loadData()
} }
) )
} }
@ -816,6 +828,7 @@ class ChatConversationViewSwift: BackActionsNavigationView, PHPickerViewControll
ChatMessage.getSwiftObject(cObject: message!).contents.forEach({ content in ChatMessage.getSwiftObject(cObject: message!).contents.forEach({ content in
if(content.isFile){ if(content.isFile){
let indexPath = IndexPath(row: ChatConversationViewModel.sharedModel.replyCollectionView.count, section: 0) let indexPath = IndexPath(row: ChatConversationViewModel.sharedModel.replyCollectionView.count, section: 0)
ChatConversationViewModel.sharedModel.replyURLCollection.append(URL(string: content.filePath.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)!) ChatConversationViewModel.sharedModel.replyURLCollection.append(URL(string: content.filePath.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)!)
ChatConversationViewModel.sharedModel.replyCollectionView.append(ChatConversationViewModel.sharedModel.getImageFrom(content.getCobject, filePath: content.filePath, forReplyBubble: true)!) ChatConversationViewModel.sharedModel.replyCollectionView.append(ChatConversationViewModel.sharedModel.getImageFrom(content.getCobject, filePath: content.filePath, forReplyBubble: true)!)
collectionViewReply.insertItems(at: [indexPath]) collectionViewReply.insertItems(at: [indexPath])

View file

@ -8,7 +8,6 @@
import UIKit import UIKit
import Foundation import Foundation
import linphonesw import linphonesw
import SDWebImage
class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate { class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
static let reuseId = "MultilineMessageCellReuseId" static let reuseId = "MultilineMessageCellReuseId"
@ -925,10 +924,22 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
contentView.onClick { contentView.onClick {
self.deleteItemCheckBox.isSelected = !self.deleteItemCheckBox.isSelected self.deleteItemCheckBox.isSelected = !self.deleteItemCheckBox.isSelected
ChatConversationTableViewModel.sharedModel.messageListSelected.value![self.selfIndexMessage] = self.deleteItemCheckBox.isSelected ChatConversationTableViewModel.sharedModel.messageListSelected.value![self.selfIndexMessage] = self.deleteItemCheckBox.isSelected
if ChatConversationTableViewModel.sharedModel.messageListSelected.value![self.selfIndexMessage] == true {
ChatConversationTableViewModel.sharedModel.messageSelected.value! += 1
}else{
ChatConversationTableViewModel.sharedModel.messageSelected.value! -= 1
}
} }
deleteItemCheckBox.onClick { deleteItemCheckBox.onClick {
self.deleteItemCheckBox.isSelected = !self.deleteItemCheckBox.isSelected self.deleteItemCheckBox.isSelected = !self.deleteItemCheckBox.isSelected
ChatConversationTableViewModel.sharedModel.messageListSelected.value![self.selfIndexMessage] = self.deleteItemCheckBox.isSelected ChatConversationTableViewModel.sharedModel.messageListSelected.value![self.selfIndexMessage] = self.deleteItemCheckBox.isSelected
if ChatConversationTableViewModel.sharedModel.messageListSelected.value![self.selfIndexMessage] == true {
ChatConversationTableViewModel.sharedModel.messageSelected.value! += 1
}else{
ChatConversationTableViewModel.sharedModel.messageSelected.value! -= 1
}
} }
}else{ }else{
deleteItemCheckBox.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true deleteItemCheckBox.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
@ -1078,7 +1089,7 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
let imageCell = replyCollectionView[indexPath.row] let imageCell = replyCollectionView[indexPath.row]
var myImageView = UIImageView() var myImageView = UIImageView()
if(replyURLCollection[indexPath.row].type == FileType.file_picture_default.rawValue || replyURLCollection[indexPath.row].type == FileType.file_video_default.rawValue){ if(replyURLCollection[indexPath.row].type == "image" || replyURLCollection[indexPath.row].type == "video"){
myImageView = UIImageView(image: imageCell) myImageView = UIImageView(image: imageCell)
}else{ }else{
let fileNameText = replyURLCollection[indexPath.row].name let fileNameText = replyURLCollection[indexPath.row].name
@ -1089,7 +1100,7 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
myImageView.size(w: (viewCell.frame.width), h: (viewCell.frame.height)).done() myImageView.size(w: (viewCell.frame.width), h: (viewCell.frame.height)).done()
viewCell.addSubview(myImageView) viewCell.addSubview(myImageView)
if(replyURLCollection[indexPath.row].type == FileType.file_video_default.rawValue){ if(replyURLCollection[indexPath.row].type == "video"){
var imagePlay = UIImage() var imagePlay = UIImage()
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
imagePlay = (UIImage(named: "vr_play")!.withTintColor(.white)) imagePlay = (UIImage(named: "vr_play")!.withTintColor(.white))
@ -1137,11 +1148,25 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
let myImageView = UIImageView() let myImageView = UIImageView()
if(self.chatMessage?.contents[indexPath.row].type == FileType.file_picture_default.rawValue || self.chatMessage?.contents[indexPath.row].type == FileType.file_video_default.rawValue){ if(self.chatMessage?.contents[indexPath.row].type == "image" || self.chatMessage?.contents[indexPath.row].type == "video"){
if #available(iOS 15.0, *) {
myImageView.image = UIImage(named: "file_picture_default")
let imageAsync: UIImage = getImageFrom(self.chatMessage?.contents[indexPath.row], forReplyBubble: false)!
imageAsync.prepareForDisplay(completionHandler: { imageAsyncResult in
DispatchQueue.main.async {
myImageView.image = imageAsyncResult
}
})
} else {
DispatchQueue.global().async { [weak self] in
if let image = self!.getImageFrom(self!.chatMessage?.contents[indexPath.row], forReplyBubble: false) {
DispatchQueue.main.async {
myImageView.image = image
}
}
}
}
myImageView.sd_setImage(with: URL(string: (self.chatMessage?.contents[indexPath.row].filePath)!), placeholderImage: UIImage(named: "file_picture_default"), completed: {(_ image: UIImage?, _ error: Error?, _ cacheType: SDImageCacheType, _ imageURL: URL?) -> Void in
myImageView.image = self.getImageFrom(self.chatMessage?.contents[indexPath.row], forReplyBubble: false)!
})
}else{ }else{
myImageView.image = self.getImageFrom(self.chatMessage?.contents[indexPath.row], forReplyBubble: false)! myImageView.image = self.getImageFrom(self.chatMessage?.contents[indexPath.row], forReplyBubble: false)!
} }
@ -1149,18 +1174,6 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
myImageView.size(w: (viewCell.frame.width), h: (viewCell.frame.height)).done() myImageView.size(w: (viewCell.frame.width), h: (viewCell.frame.height)).done()
viewCell.addSubview(myImageView) viewCell.addSubview(myImageView)
if(self.chatMessage?.contents[indexPath.row].type == FileType.file_video_default.rawValue){
var imagePlay = UIImage()
if #available(iOS 13.0, *) {
imagePlay = (UIImage(named: "vr_play")!.withTintColor(.white))
} else {
imagePlay = UIImage(named: "vr_play")!
}
let myImagePlayView = UIImageView(image: imagePlay)
viewCell.addSubview(myImagePlayView)
myImagePlayView.size(w: viewCell.frame.width/4, h: viewCell.frame.height/4).done()
myImagePlayView.alignHorizontalCenterWith(viewCell).alignVerticalCenterWith(viewCell).done()
}
myImageView.contentMode = .scaleAspectFill myImageView.contentMode = .scaleAspectFill
myImageView.clipsToBounds = true myImageView.clipsToBounds = true
@ -1170,6 +1183,19 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
uploadView.content = chatMessage?.contents[indexPath.row] uploadView.content = chatMessage?.contents[indexPath.row]
uploadView.size(w: 138, h: 138).done() uploadView.size(w: 138, h: 138).done()
if(self.chatMessage?.contents[indexPath.row].type == "video"){
var imagePlay = UIImage()
if #available(iOS 13.0, *) {
imagePlay = (UIImage(named: "vr_play")!.withTintColor(.white))
} else {
imagePlay = UIImage(named: "vr_play")!
}
let myImagePlayView = UIImageView(image: imagePlay)
viewCell.addSubview(myImagePlayView)
myImagePlayView.size(w: viewCell.frame.width/4, h: viewCell.frame.height/4).done()
myImagePlayView.alignHorizontalCenterWith(viewCell).alignVerticalCenterWith(viewCell).done()
}
viewCell.onClick { viewCell.onClick {
ChatConversationTableViewModel.sharedModel.onGridClick(indexMessage: self.selfIndexMessage, index: indexPath.row) ChatConversationTableViewModel.sharedModel.onGridClick(indexMessage: self.selfIndexMessage, index: indexPath.row)
} }
@ -1332,7 +1358,6 @@ class MultilineMessageCell: UICollectionViewCell, UICollectionViewDataSource, UI
DispatchQueue.main.async(execute: { [self] in DispatchQueue.main.async(execute: { [self] in
if (offset == total) { if (offset == total) {
downloadContentCollection[indexTransferProgress] = nil downloadContentCollection[indexTransferProgress] = nil
//chatMessage?.contents[indexTransferProgress] = content
imagesGridCollectionView[indexTransferProgress] = getImageFrom(content, forReplyBubble: false)! imagesGridCollectionView[indexTransferProgress] = getImageFrom(content, forReplyBubble: false)!

View file

@ -33,7 +33,6 @@ target 'linphone' do
pod 'SnapKit', '~> 5.6.0' pod 'SnapKit', '~> 5.6.0'
pod 'DropDown' pod 'DropDown'
pod 'IQKeyboardManager' pod 'IQKeyboardManager'
pod 'SDWebImage'
all_pods all_pods
end end