diff --git a/Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/VoiceBroadcastAggregator.swift b/Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/VoiceBroadcastAggregator.swift index f85945dce..f9afbadc1 100644 --- a/Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/VoiceBroadcastAggregator.swift +++ b/Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/VoiceBroadcastAggregator.swift @@ -68,12 +68,7 @@ public class VoiceBroadcastAggregator { public var delegate: VoiceBroadcastAggregatorDelegate? deinit { - if let referenceEventsListener = referenceEventsListener { - room.removeListener(referenceEventsListener) - } - - NotificationCenter.default.removeObserver(self, name: NSNotification.Name.mxEventDidDecrypt, object: nil) - NotificationCenter.default.removeObserver(self, name: NSNotification.Name.mxRoomDidFlushData, object: nil) + self.stop() } public init(session: MXSession, room: MXRoom, voiceBroadcastStartEventId: String, voiceBroadcastState: VoiceBroadcastInfoState) throws { @@ -201,7 +196,9 @@ public class VoiceBroadcastAggregator { self.events.append(contentsOf: filteredChunk) let eventTypes = [VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType, kMXEventTypeStringRoomMessage] - self.referenceEventsListener = self.room.listen(toEventsOfTypes: eventTypes, onEvent: self.handleEvent) as Any + self.referenceEventsListener = self.room.listen(toEventsOfTypes: eventTypes, onEvent: { [weak self] event, direction, roomState in + self?.handleEvent(event: event, direction: direction, roomState: roomState) + }) as Any self.registerEventDidDecryptNotification() self.events.forEach { event in @@ -234,4 +231,13 @@ public class VoiceBroadcastAggregator { self.delegate?.voiceBroadcastAggregator(self, didFailWithError: error) } } + + func stop() { + if let referenceEventsListener = referenceEventsListener { + room.removeListener(referenceEventsListener) + } + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.mxEventDidDecrypt, object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.mxRoomDidFlushData, object: nil) + } } diff --git a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackCoordinator.swift b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackCoordinator.swift index 652d6f7b2..3f5e55c6e 100644 --- a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackCoordinator.swift @@ -56,6 +56,10 @@ final class VoiceBroadcastPlaybackCoordinator: Coordinator, Presentable { } + deinit { + viewModel.context.send(viewAction: .redact) + } + // MARK: - Public func start() { } diff --git a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackProvider.swift b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackProvider.swift index eaae1b11f..3f28ab081 100644 --- a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackProvider.swift +++ b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/Coordinator/VoiceBroadcastPlaybackProvider.swift @@ -29,7 +29,19 @@ import Foundation } } } - var coordinatorsForEventIdentifiers = [String: VoiceBroadcastPlaybackCoordinator]() + private var coordinatorsForEventIdentifiers = [String: VoiceBroadcastPlaybackCoordinator]() { + didSet { + if !self.coordinatorsForEventIdentifiers.isEmpty && self.redactionsListener == nil { + redactionsListener = session?.listenToEvents([MXEventType(identifier: kMXEventTypeStringRoomRedaction)], self.handleEvent) + } + + if self.coordinatorsForEventIdentifiers.isEmpty && self.redactionsListener != nil { + session?.removeListener(self.redactionsListener) + self.redactionsListener = nil + } + } + } + private var redactionsListener: Any? private override init() { } @@ -58,16 +70,24 @@ import Foundation return coordinator.toPresentable() } - - /// Retrieve the voiceBroadcast timeline coordinator for the given event or nil if it hasn't been created yet - func voiceBroadcastPlaybackCoordinatorForEventIdentifier(_ eventIdentifier: String) -> VoiceBroadcastPlaybackCoordinator? { - coordinatorsForEventIdentifiers[eventIdentifier] - } - + /// Pause current voice broadcast playback. @objc public func pausePlaying() { coordinatorsForEventIdentifiers.forEach { _, coordinator in coordinator.pausePlaying() } } + + private func handleEvent(event: MXEvent, direction: MXTimelineDirection, customObject: Any?) { + if direction == .backwards { + // ignore backwards events + return + } + + var coordinator = coordinatorsForEventIdentifiers.removeValue(forKey: event.redacts) + + coordinator?.toPresentable().dismiss(animated: false) { + coordinator = nil + } + } } diff --git a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/MatrixSDK/VoiceBroadcastPlaybackViewModel.swift b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/MatrixSDK/VoiceBroadcastPlaybackViewModel.swift index feeb1c183..1f5ac9872 100644 --- a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/MatrixSDK/VoiceBroadcastPlaybackViewModel.swift +++ b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/MatrixSDK/VoiceBroadcastPlaybackViewModel.swift @@ -102,10 +102,9 @@ class VoiceBroadcastPlaybackViewModel: VoiceBroadcastPlaybackViewModelType, Voic private func release() { MXLog.debug("[VoiceBroadcastPlaybackViewModel] release") - if let audioPlayer = audioPlayer { - audioPlayer.deregisterDelegate(self) - self.audioPlayer = nil - } + self.stop() + self.voiceBroadcastAggregator.delegate = nil + self.voiceBroadcastAggregator.stop() } // MARK: - Public @@ -116,6 +115,8 @@ class VoiceBroadcastPlaybackViewModel: VoiceBroadcastPlaybackViewModelType, Voic play() case .pause: pause() + case .redact: + release() case .sliderChange(let didChange): didSliderChanged(didChange) case .backward: @@ -468,7 +469,8 @@ extension VoiceBroadcastPlaybackViewModel: VoiceMessageAudioPlayerDelegate { MXLog.debug("[VoiceBroadcastPlaybackViewModel] audioPlayerDidStopPlaying") state.playbackState = .stopped state.playingState.isLive = false - release() + audioPlayer.deregisterDelegate(self) + self.audioPlayer = nil } func audioPlayer(_ audioPlayer: VoiceMessageAudioPlayer, didFailWithError error: Error) { diff --git a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackModels.swift b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackModels.swift index c2ca1ad5f..488b65c1d 100644 --- a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackModels.swift +++ b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackModels.swift @@ -23,6 +23,7 @@ enum VoiceBroadcastPlaybackViewAction { case sliderChange(didChange: Bool) case backward case forward + case redact } enum VoiceBroadcastPlaybackState { diff --git a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackScreenState.swift b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackScreenState.swift index 0172597b7..306a5be8c 100644 --- a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackScreenState.swift +++ b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackScreenState.swift @@ -18,7 +18,7 @@ import Foundation import SwiftUI typealias MockVoiceBroadcastPlaybackViewModelType = StateStoreViewModel -class MockVoiceBroadcastPlaybackViewModel: MockVoiceBroadcastPlaybackViewModelType, VoiceBroadcastPlaybackViewModelProtocol { +class MockVoiceBroadcastPlaybackViewModel: MockVoiceBroadcastPlaybackViewModelType, VoiceBroadcastPlaybackViewModelProtocol { } /// Using an enum for the screen allows you define the different state cases with diff --git a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackViewModelProtocol.swift index 1ad8d64c5..e89df8828 100644 --- a/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/VoiceBroadcastPlayback/VoiceBroadcastPlaybackViewModelProtocol.swift @@ -19,5 +19,5 @@ import Foundation typealias VoiceBroadcastPlaybackViewModelType = StateStoreViewModel protocol VoiceBroadcastPlaybackViewModelProtocol { - var context: VoiceBroadcastPlaybackViewModelType.Context { get } + var context: VoiceBroadcastPlaybackViewModelType.Context { get } }