partial development in add audio message support

This commit is contained in:
Iosif Moldovan
2018-10-03 12:19:33 +03:00
parent 46d9f1c4d9
commit 515b98ce45
25 changed files with 643 additions and 21 deletions
@@ -25,6 +25,7 @@ SOFTWARE.
import UIKit
import MessageKit
import MessageInputBar
import AVFoundation
/// A base class for the example controllers
class ChatViewController: MessagesViewController, MessagesDataSource {
@@ -32,7 +33,11 @@ class ChatViewController: MessagesViewController, MessagesDataSource {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
var audioPlayer: AVAudioPlayer?
var audioTimer: Timer?
var messageList: [MockMessage] = []
let refreshControl = UIRefreshControl()
@@ -64,6 +69,7 @@ class ChatViewController: MessagesViewController, MessagesDataSource {
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
MockSocket.shared.disconnect()
self.stopCurrentAudioPlayer()
}
func loadFirstMessages() {
@@ -204,6 +210,63 @@ extension ChatViewController: MessageCellDelegate {
func didTapMessageBottomLabel(in cell: MessageCollectionViewCell) {
print("Bottom label tapped")
}
func didTapPlayButton(in cell: AudioMessageCell) {
print("Did tap on play button")
// guard let indexPath = messagesCollectionView.indexPath(for: cell),
// let message = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else {
// return
// }
// switch message.kind {
// case .audio(let item):
// self.stopPreviousAudioIfNeeded(item)
// if cell.isPlaying() == true {
// audioPlayer?.pause()
// self.audioTimer?.invalidate()
// cell.pasue()
// } else {
// if audioPlayer == nil {
// audioPlayer = try? AVAudioPlayer.init(contentsOf: item.url)
// audioPlayer?.delegate = self
// }
// cell.play()
// audioPlayer?.play()
// // start timer to update audio pregress
// self.audioTimer?.invalidate()
// self.audioTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ChatViewController.didFireAudioTimer(_:)), userInfo: cell, repeats: true)
// }
// default: break
// }
}
// MARK: - Audio Helpers
@objc internal func didFireAudioTimer(_ timer: Timer) {
guard let audioCell = timer.userInfo as? AudioMessageCell else {
return
}
let totalDuration = self.audioPlayer?.duration ?? 0.0
let currentTime = self.audioPlayer?.currentTime ?? 0.0
let percent = (totalDuration != 0) ? (Float(currentTime/totalDuration)) : 0.0
audioCell.updateProgress(percent: percent, duration: currentTime)
}
private func stopPreviousAudioIfNeeded(_ currentAudioItem: AudioItem) {
// stop a previous audio if current received item url is diffrent than audio player url
guard let playingAudioURL = self.audioPlayer?.url else {
return // there is no audio player playing at this moment
}
if playingAudioURL.absoluteString != currentAudioItem.url.absoluteString {
self.stopCurrentAudioPlayer()
}
}
fileprivate func stopCurrentAudioPlayer() {
guard let player = audioPlayer else {
return // there is no audio player to stop
}
player.stop() // by calling stop will not audioPlayerDidFinishPlaying(player:flag:) delegate method - it should be called manualy
self.audioPlayerDidFinishPlaying(player, successfully: true)
}
}
@@ -255,3 +318,40 @@ extension ChatViewController: MessageInputBarDelegate {
}
}
// MARK: - AVAudioPlayerDelegate
extension ChatViewController: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
guard let playingURL = player.url, let currentPlayingMessage = self.getMessageWithAudioURL(playingURL) else {
return
}
// update cell that is current playing
if let sectionIndex = messageList.index(where: { $0.messageId == currentPlayingMessage.messageId }) {
let indexPath = IndexPath.init(row: 0, section: sectionIndex)
if let audioCell = messagesCollectionView.cellForItem(at: indexPath) as? AudioMessageCell {
audioCell.stop(with: currentPlayingMessage.kind)
}
}
self.audioTimer?.invalidate()
self.audioTimer = nil
audioPlayer = nil
}
private func getMessageWithAudioURL(_ url: URL) -> MockMessage? {
let message = messageList.filter { (message) -> Bool in
switch message.kind {
case .audio(let audioItem):
if audioItem.url.absoluteString == url.absoluteString {
return true
}
default: break
}
return false
}.first
return message
}
}