Skip to content

Commit 362696c

Browse files
author
Florian Renaud
committed
VoiceBroadcast - Show error dialog if user is not able to record a voice broadcast
1 parent 838e11c commit 362696c

File tree

6 files changed

+79
-7
lines changed

6 files changed

+79
-7
lines changed

library/ui-strings/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3085,6 +3085,10 @@
30853085
<string name="a11y_play_voice_broadcast">Play or resume voice broadcast</string>
30863086
<string name="a11y_pause_voice_broadcast">Pause voice broadcast</string>
30873087
<string name="a11y_voice_broadcast_buffering">Buffering</string>
3088+
<string name="error_voice_broadcast_unauthorized_title">Can’t start a new voice broadcast</string>
3089+
<string name="error_voice_broadcast_permission_denied_message">You don’t have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.</string>
3090+
<string name="error_voice_broadcast_blocked_by_someone_else_message">Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.</string>
3091+
<string name="error_voice_broadcast_already_in_progress_message">You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.</string>
30883092

30893093
<string name="upgrade_room_for_restricted">Anyone in %s will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime.</string>
30903094
<string name="upgrade_room_for_restricted_no_param">Anyone in a parent space will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime.</string>

vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import im.vector.app.R
2121
import im.vector.app.core.resources.StringProvider
2222
import im.vector.app.features.call.dialpad.DialPadLookup
2323
import im.vector.app.features.voice.VoiceFailure
24+
import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure
25+
import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure.RecordingError
2426
import org.matrix.android.sdk.api.failure.Failure
2527
import org.matrix.android.sdk.api.failure.MatrixError
2628
import org.matrix.android.sdk.api.failure.MatrixIdFailure
@@ -135,6 +137,7 @@ class DefaultErrorFormatter @Inject constructor(
135137
is MatrixIdFailure.InvalidMatrixId ->
136138
stringProvider.getString(R.string.login_signin_matrix_id_error_invalid_matrix_id)
137139
is VoiceFailure -> voiceMessageError(throwable)
140+
is VoiceBroadcastFailure -> voiceBroadcastMessageError(throwable)
138141
is ActivityNotFoundException ->
139142
stringProvider.getString(R.string.error_no_external_application_found)
140143
else -> throwable.localizedMessage
@@ -149,6 +152,14 @@ class DefaultErrorFormatter @Inject constructor(
149152
}
150153
}
151154

155+
private fun voiceBroadcastMessageError(throwable: VoiceBroadcastFailure): String {
156+
return when (throwable) {
157+
RecordingError.BlockedBySomeoneElse -> stringProvider.getString(R.string.error_voice_broadcast_blocked_by_someone_else_message)
158+
RecordingError.NoPermission -> stringProvider.getString(R.string.error_voice_broadcast_permission_denied_message)
159+
RecordingError.UserAlreadyBroadcasting -> stringProvider.getString(R.string.error_voice_broadcast_already_in_progress_message)
160+
}
161+
}
162+
152163
private fun limitExceededError(error: MatrixError): String {
153164
val delay = error.retryAfterMillis
154165

vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import android.widget.FrameLayout
3333
import android.widget.ImageView
3434
import android.widget.TextView
3535
import androidx.activity.addCallback
36+
import androidx.annotation.StringRes
3637
import androidx.appcompat.view.menu.MenuBuilder
3738
import androidx.constraintlayout.widget.ConstraintSet
3839
import androidx.core.content.ContextCompat
@@ -1320,8 +1321,12 @@ class TimelineFragment :
13201321
}
13211322

13221323
private fun displayRoomDetailActionFailure(result: RoomDetailViewEvents.ActionFailure) {
1324+
@StringRes val titleResId = when(result.action) {
1325+
RoomDetailAction.VoiceBroadcastAction.Recording.Start -> R.string.error_voice_broadcast_unauthorized_title
1326+
else -> R.string.dialog_title_error
1327+
}
13231328
MaterialAlertDialogBuilder(requireActivity())
1324-
.setTitle(R.string.dialog_title_error)
1329+
.setTitle(titleResId)
13251330
.setMessage(errorFormatter.toHumanReadable(result.throwable))
13261331
.setPositiveButton(R.string.ok, null)
13271332
.show()

vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,12 @@ class TimelineViewModel @AssistedInject constructor(
604604
if (room == null) return
605605
viewModelScope.launch {
606606
when (action) {
607-
RoomDetailAction.VoiceBroadcastAction.Recording.Start -> voiceBroadcastHelper.startVoiceBroadcast(room.roomId)
607+
RoomDetailAction.VoiceBroadcastAction.Recording.Start -> {
608+
voiceBroadcastHelper.startVoiceBroadcast(room.roomId).fold(
609+
{ _viewEvents.post(RoomDetailViewEvents.ActionSuccess(action)) },
610+
{ _viewEvents.post(RoomDetailViewEvents.ActionFailure(action, it)) },
611+
)
612+
}
608613
RoomDetailAction.VoiceBroadcastAction.Recording.Pause -> voiceBroadcastHelper.pauseVoiceBroadcast(room.roomId)
609614
RoomDetailAction.VoiceBroadcastAction.Recording.Resume -> voiceBroadcastHelper.resumeVoiceBroadcast(room.roomId)
610615
RoomDetailAction.VoiceBroadcastAction.Recording.Stop -> voiceBroadcastHelper.stopVoiceBroadcast(room.roomId)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2022 New Vector Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package im.vector.app.features.voicebroadcast
18+
19+
sealed class VoiceBroadcastFailure : Throwable() {
20+
sealed class RecordingError : VoiceBroadcastFailure() {
21+
object NoPermission : RecordingError()
22+
object BlockedBySomeoneElse : RecordingError()
23+
object UserAlreadyBroadcasting : RecordingError()
24+
}
25+
}

vector/src/main/java/im/vector/app/features/voicebroadcast/recording/usecase/StartVoiceBroadcastUseCase.kt

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,22 @@ import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
2424
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
2525
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastChunk
2626
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
27+
import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure
2728
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder
2829
import im.vector.app.features.voicebroadcast.usecase.GetOngoingVoiceBroadcastsUseCase
2930
import im.vector.lib.multipicker.utils.toMultiPickerAudioType
31+
import org.matrix.android.sdk.api.query.QueryStringValue
3032
import org.matrix.android.sdk.api.session.Session
33+
import org.matrix.android.sdk.api.session.events.model.EventType
3134
import org.matrix.android.sdk.api.session.events.model.RelationType
3235
import org.matrix.android.sdk.api.session.events.model.toContent
36+
import org.matrix.android.sdk.api.session.events.model.toModel
3337
import org.matrix.android.sdk.api.session.getRoom
3438
import org.matrix.android.sdk.api.session.room.Room
39+
import org.matrix.android.sdk.api.session.room.getStateEvent
40+
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
3541
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
42+
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
3643
import timber.log.Timber
3744
import java.io.File
3845
import javax.inject.Inject
@@ -50,12 +57,27 @@ class StartVoiceBroadcastUseCase @Inject constructor(
5057

5158
Timber.d("## StartVoiceBroadcastUseCase: Start voice broadcast requested")
5259

53-
val onGoingVoiceBroadcastEvents = getOngoingVoiceBroadcastsUseCase.execute(roomId)
60+
val powerLevelsHelper = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
61+
?.content
62+
?.toModel<PowerLevelsContent>()
63+
?.let { PowerLevelsHelper(it) }
5464

55-
if (onGoingVoiceBroadcastEvents.isEmpty()) {
56-
startVoiceBroadcast(room)
57-
} else {
58-
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: currentVoiceBroadcastEvents=$onGoingVoiceBroadcastEvents")
65+
when {
66+
powerLevelsHelper?.isUserAllowedToSend(session.myUserId, true, VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO) != true -> {
67+
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: no permission")
68+
throw VoiceBroadcastFailure.RecordingError.NoPermission
69+
}
70+
voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Recording || voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Paused -> {
71+
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: another voice broadcast")
72+
throw VoiceBroadcastFailure.RecordingError.UserAlreadyBroadcasting
73+
}
74+
getOngoingVoiceBroadcastsUseCase.execute(roomId).isNotEmpty() -> {
75+
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: user already broadcasting")
76+
throw VoiceBroadcastFailure.RecordingError.BlockedBySomeoneElse
77+
}
78+
else -> {
79+
startVoiceBroadcast(room)
80+
}
5981
}
6082
}
6183

0 commit comments

Comments
 (0)