Ver código fonte

Merge pull request #1205 from deltachat/voice_message_length

show audio file duration in audio message bubbles
bjoern 4 anos atrás
pai
commit
9866272642

+ 4 - 0
DcCore/DcCore/DC/Wrapper.swift

@@ -968,6 +968,10 @@ public class DcMsg {
     public var messageWidth: CGFloat {
         return CGFloat(dc_msg_get_width(messagePointer))
     }
+    
+    public var duration: Int {
+        return Int(dc_msg_get_duration(messagePointer))
+    }
 
     public func setLateFilingMediaSize(width: CGFloat, height: CGFloat, duration: Int) {
         dc_msg_latefiling_mediasize(messagePointer, Int32(width), Int32(height), Int32(duration))

+ 35 - 0
deltachat-ios/Chat/AudioController.swift

@@ -85,6 +85,41 @@ open class AudioController: NSObject, AVAudioPlayerDelegate, AudioMessageCellDel
             cell.audioPlayerView.setDuration(duration: player.currentTime)
         }
     }
+    
+    public func getAudioDuration(messageId: Int, successHandler: @escaping (Int, Double) -> Void) {
+        let message = DcMsg(id: messageId)
+        if playingMessage?.id == messageId {
+            // irgnore messages that are currently playing or recently paused
+            return
+        }
+        
+        DispatchQueue.global(qos: .userInitiated).async {
+            let duration = message.duration
+            if duration > 0 {
+                DispatchQueue.main.async {
+                    successHandler(messageId, Double(duration) / 1000)
+                }
+            } else if let fileURL = message.fileURL {
+                let audioAsset = AVURLAsset.init(url: fileURL, options: nil)
+                audioAsset.loadValuesAsynchronously(forKeys: ["duration"]) {
+                    var error: NSError?
+                    let status = audioAsset.statusOfValue(forKey: "duration", error: &error)
+                    switch status {
+                    case .loaded:
+                        let duration = audioAsset.duration
+                        let durationInSeconds = CMTimeGetSeconds(duration)
+                        message.setLateFilingMediaSize(width: 0, height: 0, duration: Int(1000 * durationInSeconds))
+                        DispatchQueue.main.async {
+                            successHandler(messageId, Double(durationInSeconds))
+                        }
+                    case .failed:
+                        logger.warning("loading audio message \(messageId) failed: \(String(describing: error?.localizedDescription))")
+                    default: break
+                    }
+                }
+            }
+        }
+    }
 
     public func playButtonTapped(cell: AudioMessageCell, messageId: Int) {
             let message = DcMsg(id: messageId)

+ 10 - 1
deltachat-ios/Chat/Views/Cells/AudioMessageCell.swift

@@ -5,6 +5,8 @@ import DcCore
 // do not confuse with BaseMessageCellDelegate that is for sending events to ChatViewControllerNew.
 public protocol AudioMessageCellDelegate: AnyObject {
     func playButtonTapped(cell: AudioMessageCell, messageId: Int)
+    func getAudioDuration(messageId: Int, successHandler: @escaping (Int, Double) -> Void)
+
 }
 
 public class AudioMessageCell: BaseMessageCell {
@@ -38,7 +40,6 @@ public class AudioMessageCell: BaseMessageCell {
     }
 
     override func update(msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool) {
-        //audioPlayerView.reset()
         messageId = msg.id
         if let text = msg.text {
             mainContentView.spacing = text.isEmpty ? 0 : 8
@@ -51,6 +52,14 @@ public class AudioMessageCell: BaseMessageCell {
         } else {
             accessibilityLabel = String.localized("audio")
         }
+        
+        delegate?.getAudioDuration(messageId: messageId, successHandler: { [weak self] (messageId, duration) -> Void in
+            if let self = self,
+               messageId == self.messageId {
+                self.audioPlayerView.setDuration(duration: duration)
+            }
+        })
+        
 
         super.update(msg: msg, messageStyle: messageStyle, showAvatar: showAvatar, showName: showName)
     }