|
|
@@ -97,6 +97,122 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
print("Failed to identify message when audio cell receive tap gesture")
|
|
|
return
|
|
|
}
|
|
|
+ didTapMessage(in: cell, message: messageViewModel.message)
|
|
|
+ }
|
|
|
+
|
|
|
+ func didLongTapMessage(in cell: MessageCollectionViewCell) {
|
|
|
+ if viewModel.chatInputState == .multiSelected {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ showMenu(cell: cell as! HXMessageContentCell)
|
|
|
+ }
|
|
|
+
|
|
|
+ public func didTapCellTopLabel(in cell: MessageCollectionViewCell) {
|
|
|
+ self.view.endEditing(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ public func didTapBackground(in cell: MessageCollectionViewCell) {
|
|
|
+ self.view.endEditing(true)
|
|
|
+
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
|
|
|
+ else {
|
|
|
+ print("Failed to identify didTapBackground message when cell receive tap gesture")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if messageViewModel.isMultiSelected {
|
|
|
+ viewModel.update(message: messageViewModel.message, selected: !messageViewModel.isSelected)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapCellBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Bottom cell label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapMessageTopLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Top message label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapMessageBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Bottom label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ func didStartAudio(in _: HXAudioMessageContentCell) {
|
|
|
+ print("Did start playing audio sound")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didPauseAudio(in _: HXAudioMessageContentCell) {
|
|
|
+ print("Did pause audio sound")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didStopAudio(in _: HXAudioMessageContentCell) {
|
|
|
+ print("Did stop audio sound")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapAccessoryView(in _: MessageCollectionViewCell) {
|
|
|
+ print("Accessory view tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectPhoneNumber(_ phoneNumber: String) {
|
|
|
+ printLog("")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapResend(in cell: MessageCollectionViewCell) {
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if viewModel.chatInputState == .multiSelected {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let message = messageViewModel.message
|
|
|
+ let infos = MessageAttachmentProvider.fileUploadInfos(of: message.kind)
|
|
|
+ viewModel.resendMessage(message, infos: infos)
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapCloseMessageTimeView(in cell: MessageCollectionViewCell) {
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if viewModel.chatInputState == .multiSelected {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ viewModel.cleanShowMessageTime(messageId: messageViewModel.message.messageId)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 点击了引用消息
|
|
|
+ func didTapQuoteMessageView(in cell: MessageCollectionViewCell) {
|
|
|
+ self.view.endEditing(true)
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ guard let replyMessage = messageViewModel.replyMessage else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ didTapMessage(in: nil, message: replyMessage)
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapReadReceipt(in cell: MessageCollectionViewCell) {
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
if viewModel.chatInputState == .multiSelected {
|
|
|
return
|
|
|
@@ -104,20 +220,67 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
|
|
|
let message = messageViewModel.message
|
|
|
|
|
|
+ let targetId: Int?
|
|
|
+ switch message.conversationType {
|
|
|
+ case .single:
|
|
|
+ targetId = message.userId
|
|
|
+ case .system:
|
|
|
+ return
|
|
|
+ case .group:
|
|
|
+ targetId = message.groupId
|
|
|
+ case .microServer:
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ guard let targetId = targetId else { return }
|
|
|
+ self.navigator.show(segue: .readReceipt(messageUid: message.id, targetId: targetId, convType: message.conversationType), sender: self)
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapRewriteText(in cell: MessageCollectionViewCell) {
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView),
|
|
|
+ case .text(let textElem) = messageViewModel.message.messageKind else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ guard viewModel.chatInputState == .normal else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if viewModel.chatInputState == .multiSelected {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ messageInputBar.appendTextView(textElem.text)
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// MARK: - tap message
|
|
|
+extension ChatViewController {
|
|
|
+
|
|
|
+ private func didTapMessage(in cell: MessageCollectionViewCell?, message: Message) {
|
|
|
+ if viewModel.chatInputState == .multiSelected {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
switch message.kind {
|
|
|
- case .text:
|
|
|
+ case .text(let textElem):
|
|
|
+ let controller = TextPreviewViewController(navigator: self.navigator, text: textElem.text)
|
|
|
+ self.present(controller, animated: false)
|
|
|
break
|
|
|
case .image:
|
|
|
- break
|
|
|
+ didTapImage(in: cell, message: message)
|
|
|
case .video:
|
|
|
- break
|
|
|
+ didTapImage(in: cell, message: message)
|
|
|
case .location(let locationItem):
|
|
|
self.navigator.show(segue: .locationPreview(location: locationItem), sender: self)
|
|
|
case .emoticon(let emoticonItem):
|
|
|
let item = EmoticonItem(id: emoticonItem.itemId, emoticonId: emoticonItem.id, name: emoticonItem.name, type: emoticonItem.type)
|
|
|
self.navigator.show(segue: .emoticonPreview(emoticonItem: item), sender: self)
|
|
|
case .audio:
|
|
|
- didTapPlayAudio(in: cell as! HXAudioMessageContentCell)
|
|
|
+ didTapPlayAudio(in: cell as? HXAudioMessageContentCell, message: message)
|
|
|
case .contact(let contactItem):
|
|
|
switch contactItem.type {
|
|
|
case .contact:
|
|
|
@@ -159,30 +322,13 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- func didLongTapMessage(in cell: MessageCollectionViewCell) {
|
|
|
- if viewModel.chatInputState == .multiSelected {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- showMenu(cell: cell as! HXMessageContentCell)
|
|
|
- }
|
|
|
-
|
|
|
- func didTapImage(in cell: MessageCollectionViewCell) {
|
|
|
+ private func didTapImage(in cell: MessageCollectionViewCell?, message: Message) {
|
|
|
print("Image tapped")
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
|
|
|
- else {
|
|
|
- print("Failed to identify message when audio cell receive tap gesture")
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
+
|
|
|
if viewModel.chatInputState == .multiSelected {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- let message = messageViewModel.message
|
|
|
-
|
|
|
if case .image(_) = message.kind {
|
|
|
|
|
|
viewModel.getHistoryImageMessageList { [weak self] messages in
|
|
|
@@ -280,8 +426,28 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
}
|
|
|
|
|
|
// 更丝滑的Zoom动画
|
|
|
- lantern.transitionAnimator = LanternSmoothZoomAnimator(transitionViewAndFrame: { (index, destinationView) -> LanternSmoothZoomAnimator.TransitionViewAndFrame? in
|
|
|
- guard let imageView = (cell as? HXVideoMessageContentCell)?.imageView else {
|
|
|
+ lantern.transitionAnimator = LanternSmoothZoomAnimator(transitionViewAndFrame: { [weak self] (index, destinationView) -> LanternSmoothZoomAnimator.TransitionViewAndFrame? in
|
|
|
+ guard let self = self else { return nil }
|
|
|
+
|
|
|
+ let fromCell: HXVideoMessageContentCell?
|
|
|
+ if let cell = cell as? HXVideoMessageContentCell {
|
|
|
+ fromCell = cell
|
|
|
+ } else {
|
|
|
+ guard let index = viewModel.messages.firstIndex(where: { $0.message.id == message.id }),
|
|
|
+ let cell = messagesCollectionView.visibleCells.first(where: { cell in
|
|
|
+ guard let cell = (cell as? HXVideoMessageContentCell) else { return false }
|
|
|
+ guard let indexPath = self.messagesCollectionView.indexPath(for: cell) else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return indexPath.row == index
|
|
|
+ })
|
|
|
+ else {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ fromCell = cell as? HXVideoMessageContentCell
|
|
|
+ }
|
|
|
+
|
|
|
+ guard let imageView = fromCell?.imageView else {
|
|
|
return nil
|
|
|
}
|
|
|
let image = imageView.image
|
|
|
@@ -300,39 +466,7 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
fatalError("Configuring LocationMessageCell with wrong")
|
|
|
}
|
|
|
|
|
|
- public func didTapCellTopLabel(in cell: MessageCollectionViewCell) {
|
|
|
- self.view.endEditing(true)
|
|
|
- }
|
|
|
-
|
|
|
- public func didTapBackground(in cell: MessageCollectionViewCell) {
|
|
|
- self.view.endEditing(true)
|
|
|
-
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
|
|
|
- else {
|
|
|
- print("Failed to identify didTapBackground message when cell receive tap gesture")
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if messageViewModel.isMultiSelected {
|
|
|
- viewModel.update(message: messageViewModel.message, selected: !messageViewModel.isSelected)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func didTapCellBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Bottom cell label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapMessageTopLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Top message label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapMessageBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Bottom label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapPlayAudio(in cell: HXAudioMessageContentCell) {
|
|
|
+ private func didTapPlayAudio(in cell: HXAudioMessageContentCell?, message: Message) {
|
|
|
if viewModel.chatInputState == .multiSelected {
|
|
|
return
|
|
|
}
|
|
|
@@ -342,12 +476,30 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
|
|
|
- else {
|
|
|
- print("Failed to identify message when audio cell receive tap gesture")
|
|
|
- return
|
|
|
+ let messageViewModel: MessageViewModel
|
|
|
+ let playCell: HXAudioMessageContentCell?
|
|
|
+
|
|
|
+ if let cell = cell,
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let viewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) {
|
|
|
+ playCell = cell
|
|
|
+ messageViewModel = viewModel
|
|
|
+ } else {
|
|
|
+ if let index = viewModel.messages.firstIndex(where: { $0.message.id == message.id }) {
|
|
|
+ /// 数据中找到这个 message 了(来自引用)
|
|
|
+ let cell = messagesCollectionView.visibleCells.first(where: { cell in
|
|
|
+ guard let cell = (cell as? HXAudioMessageContentCell) else { return false }
|
|
|
+ guard let indexPath = self.messagesCollectionView.indexPath(for: cell) else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return indexPath.row == index
|
|
|
+ })
|
|
|
+ playCell = cell as? HXAudioMessageContentCell
|
|
|
+ messageViewModel = viewModel.messages[index]
|
|
|
+ } else {
|
|
|
+ playCell = nil
|
|
|
+ messageViewModel = MessageViewModel(message: message)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
let message = messageViewModel.message
|
|
|
@@ -357,10 +509,10 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
}
|
|
|
|
|
|
viewModel.audioMessagePlayed(messageViewModel: messageViewModel)
|
|
|
- cell.unReadIcon.isHidden = true
|
|
|
+ playCell?.unReadIcon.isHidden = true
|
|
|
|
|
|
guard let localPath = audioItem.localPath, FileManager.default.fileExists(atPath: localPath) else {
|
|
|
- cell.activityIndicatorView.startAnimating()
|
|
|
+ playCell?.activityIndicatorView.startAnimating()
|
|
|
|
|
|
let fileKey = audioItem.file
|
|
|
guard fileKey.isNotEmpty else {
|
|
|
@@ -381,12 +533,12 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
let info = MessageDownloadInfo(bucket: "\(bucket)", fileKey: fileKey, fileName: fileKey, fileType: .audio)
|
|
|
manager.prepareDownloadTask(messageId: messageId, info: info) { [weak self] result in
|
|
|
DispatchQueue.main.async {
|
|
|
- cell.activityIndicatorView.stopAnimating()
|
|
|
+ playCell?.activityIndicatorView.stopAnimating()
|
|
|
|
|
|
guard let self = self else { return }
|
|
|
switch result {
|
|
|
case .success:
|
|
|
- self.playSound(messageViewModel: messageViewModel, cell: cell)
|
|
|
+ self.playSound(messageViewModel: messageViewModel, cell: playCell)
|
|
|
case .failed:
|
|
|
break
|
|
|
case.cancel:
|
|
|
@@ -398,112 +550,10 @@ extension ChatViewController: MessageCellDelegate {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- self.playSound(messageViewModel: messageViewModel, cell: cell)
|
|
|
+ self.playSound(messageViewModel: messageViewModel, cell: playCell)
|
|
|
}
|
|
|
|
|
|
- func didStartAudio(in _: HXAudioMessageContentCell) {
|
|
|
- print("Did start playing audio sound")
|
|
|
- }
|
|
|
-
|
|
|
- func didPauseAudio(in _: HXAudioMessageContentCell) {
|
|
|
- print("Did pause audio sound")
|
|
|
- }
|
|
|
-
|
|
|
- func didStopAudio(in _: HXAudioMessageContentCell) {
|
|
|
- print("Did stop audio sound")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapAccessoryView(in _: MessageCollectionViewCell) {
|
|
|
- print("Accessory view tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectPhoneNumber(_ phoneNumber: String) {
|
|
|
- printLog("")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapResend(in cell: MessageCollectionViewCell) {
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if viewModel.chatInputState == .multiSelected {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let message = messageViewModel.message
|
|
|
- let infos = MessageAttachmentProvider.fileUploadInfos(of: message.kind)
|
|
|
- viewModel.resendMessage(message, infos: infos)
|
|
|
- }
|
|
|
-
|
|
|
- func didTapCloseMessageTimeView(in cell: MessageCollectionViewCell) {
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if viewModel.chatInputState == .multiSelected {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- viewModel.cleanShowMessageTime(messageId: messageViewModel.message.messageId)
|
|
|
- }
|
|
|
-
|
|
|
- func didTapReadReceipt(in cell: MessageCollectionViewCell) {
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if viewModel.chatInputState == .multiSelected {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let message = messageViewModel.message
|
|
|
-
|
|
|
- let targetId: Int?
|
|
|
- switch message.conversationType {
|
|
|
- case .single:
|
|
|
- targetId = message.userId
|
|
|
- case .system:
|
|
|
- return
|
|
|
- case .group:
|
|
|
- targetId = message.groupId
|
|
|
- case .microServer:
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- guard let targetId = targetId else { return }
|
|
|
- self.navigator.show(segue: .readReceipt(messageUid: message.id, targetId: targetId, convType: message.conversationType), sender: self)
|
|
|
- }
|
|
|
-
|
|
|
- func didTapRewriteText(in cell: MessageCollectionViewCell) {
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let messageViewModel = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView),
|
|
|
- case .text(let textElem) = messageViewModel.message.messageKind else {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- guard viewModel.chatInputState == .normal else {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if viewModel.chatInputState == .multiSelected {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- messageInputBar.appendTextView(textElem.text)
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension ChatViewController {
|
|
|
-
|
|
|
- private func playSound(messageViewModel: MessageViewModel, cell: HXAudioMessageContentCell) {
|
|
|
+ private func playSound(messageViewModel: MessageViewModel, cell: HXAudioMessageContentCell?) {
|
|
|
guard audioController.state != .stopped else {
|
|
|
// There is no audio sound playing - prepare to start playing for given audio message
|
|
|
audioController.playSound(for: messageViewModel, in: cell)
|