allow playback of audio messages from the message detail view
* allow playback of audio messages from the message detail view * Update UI when an audio message pauses because another one started playing * pr feedback
This commit is contained in:
parent
17c3dba264
commit
2d149b8525
@ -114,7 +114,17 @@ public class CVAudioPlayer: NSObject {
|
||||
audioPlayback.setPlaybackRate(1)
|
||||
}
|
||||
audioPlayback.delegate = self
|
||||
|
||||
let oldAudioPlayback = self.audioPlayback
|
||||
self.audioPlayback = audioPlayback
|
||||
|
||||
// Let the existing player know its state has changed.
|
||||
if let oldId = oldAudioPlayback?.attachmentId {
|
||||
for listener in listeners.elements {
|
||||
listener.audioPlayerStateDidChange(attachmentId: oldId)
|
||||
}
|
||||
}
|
||||
|
||||
return audioPlayback
|
||||
}
|
||||
|
||||
|
||||
@ -246,6 +246,8 @@ class MessageDetailViewController: OWSTableViewController2 {
|
||||
let cellContainer = UIView()
|
||||
cellContainer.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
|
||||
|
||||
cellContainer.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapCell)))
|
||||
|
||||
cellContainer.addSubview(cellView)
|
||||
cellView.autoPinHeightToSuperviewMargins()
|
||||
|
||||
@ -324,6 +326,16 @@ class MessageDetailViewController: OWSTableViewController2 {
|
||||
return section
|
||||
}
|
||||
|
||||
@objc private func didTapCell(_ sender: UITapGestureRecognizer) {
|
||||
// For now, only allow tapping on audio cells. The full gamut of cell types
|
||||
// might result in unexpected behaviors if made tappable from the detail view.
|
||||
guard renderItem?.componentState.audioAttachment != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
_ = cellView.handleTap(sender: sender, componentDelegate: self)
|
||||
}
|
||||
|
||||
private func buildSenderSection() -> OWSTableSection {
|
||||
guard let incomingMessage = message as? TSIncomingMessage else {
|
||||
owsFailDebug("Unexpected message type")
|
||||
@ -764,23 +776,35 @@ extension MessageDetailViewController: DatabaseChangeDelegate {
|
||||
refreshContentForDatabaseUpdate()
|
||||
}
|
||||
|
||||
private func refreshContentForDatabaseUpdate() {
|
||||
guard databaseUpdateTimer == nil else { return }
|
||||
/// ForceImmediately should only be used based on user input, since it ignores any debouncing
|
||||
/// and makes an update happen right away (killing any scheduled/debounced updates)
|
||||
private func refreshContentForDatabaseUpdate(forceImmediately: Bool = false) {
|
||||
// Updating this view is slightly expensive and there will be tons of relevant
|
||||
// database updates when sending to a large group. Update latency isn't that
|
||||
// imporant, so we de-bounce to never update this view more than once every N seconds.
|
||||
self.databaseUpdateTimer = Timer.scheduledTimer(
|
||||
withTimeInterval: 2.0,
|
||||
repeats: false
|
||||
) { [weak self] _ in
|
||||
|
||||
let updateBlock = { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
assert(self.databaseUpdateTimer != nil)
|
||||
self.databaseUpdateTimer?.invalidate()
|
||||
self.databaseUpdateTimer = nil
|
||||
self.refreshContent()
|
||||
}
|
||||
if forceImmediately {
|
||||
updateBlock()
|
||||
return
|
||||
}
|
||||
|
||||
guard databaseUpdateTimer == nil else { return }
|
||||
|
||||
self.databaseUpdateTimer = Timer.scheduledTimer(
|
||||
withTimeInterval: 2.0,
|
||||
repeats: false
|
||||
) { _ in
|
||||
assert(self.databaseUpdateTimer != nil)
|
||||
updateBlock()
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshContent() {
|
||||
@ -886,7 +910,7 @@ extension MessageDetailViewController: CVComponentDelegate {
|
||||
}
|
||||
|
||||
func cvc_enqueueReloadWithoutCaches() {
|
||||
self.refreshContentForDatabaseUpdate()
|
||||
self.refreshContentForDatabaseUpdate(forceImmediately: true)
|
||||
}
|
||||
|
||||
// MARK: - Body Text Items
|
||||
|
||||
Loading…
Reference in New Issue
Block a user