Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VoiceBroadcast: Manage app crash cases when recording #7188

Merged
merged 14 commits into from
Dec 23, 2022
46 changes: 46 additions & 0 deletions Riot/Categories/MXRoomState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import MatrixSDK

extension MXRoomState {
func cancelCurrentVoiceBroadcastRecordingIfNeeded(for room: MXRoom, session: MXSession) {
// Detection of a potential unfinished VoiceBroadcast
// Check whether a VoiceBroadcast is in progress on the current session for this room whereas no VoiceBroadcast Service is available.
guard let event = self.stateEvents(with: .custom(VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType))?.last,
event.stateKey == session.myUserId,
let eventDeviceId = event.content[VoiceBroadcastSettings.voiceBroadcastContentKeyDeviceId] as? String,
session.myDeviceId == eventDeviceId,
let voiceBroadcastInfo = VoiceBroadcastInfo(fromJSON: event.content),
let state = VoiceBroadcastInfoState(rawValue: voiceBroadcastInfo.state),
state != .stopped,
session.voiceBroadcastService == nil else {
return
giomfo marked this conversation as resolved.
Show resolved Hide resolved
}

session.getOrCreateVoiceBroadcastService(for: room) { service in
guard let vbService = service else {
return
}

vbService.stopVoiceBroadcast(lastChunkSequence: 0,
voiceBroadcastId: event.eventId) { response in
MXLog.debug("[MXRoomState] cancelCurrentVoiceBroadcastRecordingIfNeeded stopVoiceBroadcast with response : \(response)")
session.tearDownVoiceBroadcastService()
}
}
}
}
6 changes: 6 additions & 0 deletions Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,12 @@ - (void)recentsListServiceDidChangeData:(id<RecentsListServiceProtocol>)service
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:(NSUInteger)sectionIndex];
[self.delegate dataSource:self didCellChange:indexPath];
}

if (section == RecentsListServiceSectionBreadcrumbs) {
[self.recentsListService cancelCurrentVoiceBroadcastRecordingIfNeededFor:self.recentsListService.breadcrumbsRoomListData];
} else if (section == RecentsListServiceSectionAllChats) {
[self.recentsListService cancelCurrentVoiceBroadcastRecordingIfNeededFor:self.recentsListService.allChatsRoomListData];
}
giomfo marked this conversation as resolved.
Show resolved Hide resolved
}

- (RecentsDataSourceSectionType)sectionTypeForServiceSection:(RecentsListServiceSection)serviceSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,23 @@ extension RecentsListService: MXRoomListDataFetcherDelegate {

}

// MARK: - VoiceBroadcast
extension RecentsListService {
@objc public func cancelCurrentVoiceBroadcastRecordingIfNeeded(for listData: MXRoomListData?) {
listData?.rooms.forEach({ roomSummary in
guard let roomSummary = roomSummary as? MXRoomSummary,
let room = roomSummary.room else {
return
}

room.state({ roomState in
guard let session = self.session else { return }
roomState?.cancelCurrentVoiceBroadcastRecordingIfNeeded(for: room, session: session)
})
})
}
}

// MARK: - FetcherTypes

private struct FetcherTypes: OptionSet {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,7 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
multicastDelegate.invoke({ $0.recentsListServiceDidChangeData?(self, totalCountsChanged: true) })
}

public func cancelCurrentVoiceBroadcastRecordingIfNeeded(for listData: MatrixSDK.MXRoomListData?) {
// nothing here
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,7 @@ public protocol RecentsListServiceProtocol {

/// Remove all delegates
func removeAllDelegates()

/// Cancel a VoiceBroadcast recording in case of application unexpected end before the end of the recording.
func cancelCurrentVoiceBroadcastRecordingIfNeeded(for listData: MXRoomListData?)
}
2 changes: 2 additions & 0 deletions Riot/Modules/Room/RoomViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,8 @@ - (void)displayRoom:(MXKRoomDataSource *)dataSource
[self setupUserSuggestionViewIfNeeded];

[self updateTopBanners];

[self cancelCurrentVoiceBroadcastRecordingIfNeeded];
}

- (void)onRoomDataSourceReady
Expand Down
9 changes: 9 additions & 0 deletions Riot/Modules/Room/RoomViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,12 @@ extension RoomViewController: ComposerLinkActionBridgePresenterDelegate {
composerLinkActionBridgePresenter = nil
}
}

// MARK: - VoiceBroadcast
extension RoomViewController {
@objc func cancelCurrentVoiceBroadcastRecordingIfNeeded() {
self.roomDataSource.room.state { roomState in
roomState?.cancelCurrentVoiceBroadcastRecordingIfNeeded(for: self.roomDataSource.room, session: self.mainSession)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,14 @@ public class VoiceBroadcastService: NSObject {
/// stop a voice broadcast info.
/// - Parameters:
/// - lastChunkSequence: The last sent chunk number.
/// - voiceBroadcastId: The VoiceBroadcast identifier to stop. Use it only to force stop a specific VoiceBroadcast.
/// - completion: A closure called when the operation completes. Provides the event id of the event generated on the home server on success.
func stopVoiceBroadcast(lastChunkSequence: Int, completion: @escaping (MXResponse<String?>) -> Void) {
func stopVoiceBroadcast(lastChunkSequence: Int,
voiceBroadcastId: String? = nil,
completion: @escaping (MXResponse<String?>) -> Void) {
if let voiceBroadcastId = voiceBroadcastId {
self.voiceBroadcastId = voiceBroadcastId
}
sendVoiceBroadcastInfo(lastChunkSequence: lastChunkSequence, state: VoiceBroadcastInfoState.stopped, completion: completion)
}

Expand Down Expand Up @@ -132,7 +138,7 @@ public class VoiceBroadcastService: NSObject {
case .resumed:
return [.paused, .stopped]
case .stopped:
return [.started]
return [.started, .stopped]
}
}

Expand Down
1 change: 1 addition & 0 deletions changelog.d/pr-7188.change
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Labs: VoiceBroadcast: Handle potential crash whereas a voice broadcast is in progress