merged element-ios 1.10.5 into 4409_basis_update_1_10_5

This commit is contained in:
Arnfried Griesert
2023-03-16 12:19:26 +01:00
168 changed files with 2451 additions and 850 deletions
@@ -53,7 +53,7 @@ class VoiceMessageAudioPlayer: NSObject {
return false
}
return (audioPlayer.rate > 0)
return audioPlayer.currentItem != nil && (audioPlayer.rate > 0)
}
var duration: TimeInterval {
@@ -118,6 +118,13 @@ class VoiceMessageAudioPlayer: NSObject {
}
}
func reloadContentIfNeeded() {
if let url, let audioPlayer, audioPlayer.currentItem == nil {
self.url = nil
loadContentFromURL(url)
}
}
func removeAllPlayerItems() {
audioPlayer?.removeAllItems()
}
@@ -130,6 +137,8 @@ class VoiceMessageAudioPlayer: NSObject {
func play() {
isStopped = false
reloadContentIfNeeded()
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
try AVAudioSession.sharedInstance().setActive(true)
@@ -73,15 +73,18 @@ class VoiceMessageAudioRecorder: NSObject, AVAudioRecorderDelegate {
}
}
func stopRecording() {
func stopRecording(releaseAudioSession: Bool = true) {
audioRecorder?.stop()
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch {
delegateContainer.notifyDelegatesWithBlock { delegate in
(delegate as? VoiceMessageAudioRecorderDelegate)?.audioRecorder(self, didFailWithError: VoiceMessageAudioRecorderError.genericError) }
if releaseAudioSession {
MXLog.debug("[VoiceMessageAudioRecorder] stopRecording() - releasing audio session")
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch {
delegateContainer.notifyDelegatesWithBlock { delegate in
(delegate as? VoiceMessageAudioRecorderDelegate)?.audioRecorder(self, didFailWithError: VoiceMessageAudioRecorderError.genericError) }
}
}
}
func peakPowerForChannelNumber(_ channelNumber: Int) -> Float {
@@ -187,7 +187,10 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate,
audioPlayer?.stop()
audioRecorder?.stopRecording()
sendRecordingAtURL(temporaryFileURL)
// As we only use a single temporary file, we have to rename it, otherwise it will be deleted once the file is sent and if another recording has been started meanwhile, it will fail.
if let finalFileURL = finalizeRecordingAtURL(temporaryFileURL) {
sendRecordingAtURL(finalFileURL)
}
isInLockedMode = false
updateUI()
@@ -196,15 +199,25 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate,
// MARK: - AudioRecorderDelegate
func audioRecorderDidStartRecording(_ audioRecorder: VoiceMessageAudioRecorder) {
guard self.audioRecorder === audioRecorder else {
return
}
notifiedRemainingTime = false
updateUI()
}
func audioRecorderDidFinishRecording(_ audioRecorder: VoiceMessageAudioRecorder) {
guard self.audioRecorder === audioRecorder else {
return
}
updateUI()
}
func audioRecorder(_ audioRecorder: VoiceMessageAudioRecorder, didFailWithError: Error) {
guard self.audioRecorder === audioRecorder else {
MXLog.error("[VoiceMessageController] audioRecorder failed but it's not the current one.")
return
}
isInLockedMode = false
updateUI()
@@ -214,20 +227,34 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate,
// MARK: - VoiceMessageAudioPlayerDelegate
func audioPlayerDidStartPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
guard self.audioPlayer === audioPlayer else {
return
}
updateUI()
}
func audioPlayerDidPausePlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
guard self.audioPlayer === audioPlayer else {
return
}
updateUI()
}
func audioPlayerDidStopPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
guard self.audioPlayer === audioPlayer else {
return
}
updateUI()
}
func audioPlayerDidFinishPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
guard self.audioPlayer === audioPlayer else {
return
}
audioPlayer.seekToTime(0.0) { [weak self] _ in
self?.updateUI()
// Reload its content if necessary, otherwise the seek won't work
self?.audioPlayer?.reloadContentIfNeeded()
}
}
@@ -260,8 +287,8 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate,
audioRecorder?.stopRecording()
guard isInLockedMode else {
if recordDuration ?? 0 >= Constants.minimumRecordingDuration {
sendRecordingAtURL(temporaryFileURL)
if recordDuration ?? 0 >= Constants.minimumRecordingDuration, let finalRecordingURL = finalizeRecordingAtURL(temporaryFileURL) {
sendRecordingAtURL(finalRecordingURL)
} else {
cancelRecording()
}
@@ -277,7 +304,13 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate,
isInLockedMode = false
audioPlayer?.stop()
audioRecorder?.stopRecording()
// Check if we are recording before stopping the recording, because it will try to pause the audio session and it can be problematic if another player or recorder is running
if let audioRecorder, audioRecorder.isRecording {
audioRecorder.stopRecording()
}
// Also, we can release it now, which will prevent the service provider from trying to manage an old audio recorder.
audioRecorder = nil
deleteRecordingAtURL(temporaryFileURL)
@@ -371,6 +404,23 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate,
}
}
private func finalizeRecordingAtURL(_ url: URL?) -> URL? {
guard let url = url, FileManager.default.fileExists(atPath: url.path) else {
return nil
}
// We rename the file to something unique, so that we can start a new recording without having to wait for this record to be sent.
let newPath = url.deletingPathExtension().path + "-\(UUID().uuidString)"
let destinationUrl = URL(fileURLWithPath: newPath).appendingPathExtension(url.pathExtension)
do {
try FileManager.default.moveItem(at: url, to: destinationUrl)
} catch {
MXLog.error("[VoiceMessageController] finalizeRecordingAtURL:", context: error)
return nil
}
return destinationUrl
}
private func deleteRecordingAtURL(_ url: URL?) {
// Fix: use url.path instead of url.absoluteString when using FileManager otherwise the url seems to be percent encoded and the file is not found.
guard let url = url, FileManager.default.fileExists(atPath: url.path) else {
@@ -48,7 +48,7 @@ import MediaPlayer
didSet {
// set avatar placeholder for now
roomAvatar = AvatarGenerator.generateAvatar(forMatrixItem: currentRoomSummary?.roomId,
withDisplayName: currentRoomSummary?.displayname,
withDisplayName: currentRoomSummary?.displayName,
size: Constants.roomAvatarImageSize.width,
andFontSize: Constants.roomAvatarFontSize)
@@ -191,7 +191,9 @@ import MediaPlayer
continue
}
audioRecorder.stopRecording()
// We should release the audio session only if we want to pause all services
let shouldReleaseAudioSession = (service == nil)
audioRecorder.stopRecording(releaseAudioSession: shouldReleaseAudioSession)
}
guard let audioPlayersEnumerator = audioPlayers.objectEnumerator() else {
@@ -149,6 +149,8 @@ class VoiceMessagePlaybackController: VoiceMessageAudioPlayerDelegate, VoiceMess
audioPlayer.seekToTime(0.0) { [weak self] _ in
guard let self = self else { return }
self.state = .stopped
// Reload its content if necessary, otherwise the seek won't work
self.audioPlayer?.reloadContentIfNeeded()
}
}