mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-20 03:59:35 +01:00
Handle more call recording states
more call recording states are: 3 = Starting video recording 4 = Starting audio recording 5 = Recording failed these actions were added: - Show grey recording icon to moderators if recording is starting - Show toast to moderators if recording failed - Add system message for recording failed Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
c1b79ac4dd
commit
499e022114
@ -445,30 +445,44 @@ public class CallActivity extends CallBaseActivity {
|
||||
|
||||
callRecordingViewModel.getViewState().observe(this, viewState -> {
|
||||
if (viewState instanceof CallRecordingViewModel.RecordingStartedState) {
|
||||
binding.callRecordingIndicator.setImageResource(R.drawable.record_stop);
|
||||
binding.callRecordingIndicator.setVisibility(View.VISIBLE);
|
||||
if (((CallRecordingViewModel.RecordingStartedState) viewState).getShowStartedInfo()) {
|
||||
VibrationUtils.INSTANCE.vibrateShort(context);
|
||||
Toast.makeText(context, context.getResources().getString(R.string.record_active_info), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (viewState instanceof CallRecordingViewModel.RecordingStartingState) {
|
||||
if (isAllowedToStartOrStopRecording()) {
|
||||
binding.callRecordingIndicator.setImageResource(R.drawable.record_starting);
|
||||
binding.callRecordingIndicator.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.callRecordingIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
} else if (viewState instanceof CallRecordingViewModel.RecordingConfirmStopState) {
|
||||
MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.record_stop_confirm_title)
|
||||
.setMessage(R.string.record_stop_confirm_message)
|
||||
.setPositiveButton(R.string.record_stop_description,
|
||||
(dialog, which) -> callRecordingViewModel.stopRecording())
|
||||
.setNegativeButton(R.string.nc_common_dismiss,
|
||||
(dialog, which) -> callRecordingViewModel.dismissStopRecording());
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, dialogBuilder);
|
||||
AlertDialog dialog = dialogBuilder.show();
|
||||
|
||||
viewThemeUtils.platform.colorTextButtons(
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
||||
);
|
||||
if (isAllowedToStartOrStopRecording()) {
|
||||
MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.record_stop_confirm_title)
|
||||
.setMessage(R.string.record_stop_confirm_message)
|
||||
.setPositiveButton(R.string.record_stop_description,
|
||||
(dialog, which) -> callRecordingViewModel.stopRecording())
|
||||
.setNegativeButton(R.string.nc_common_dismiss,
|
||||
(dialog, which) -> callRecordingViewModel.dismissStopRecording());
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, dialogBuilder);
|
||||
AlertDialog dialog = dialogBuilder.show();
|
||||
|
||||
viewThemeUtils.platform.colorTextButtons(
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
||||
);
|
||||
} else {
|
||||
Log.e(TAG, "Being in RecordingConfirmStopState as non moderator. This should not happen!");
|
||||
}
|
||||
} else if (viewState instanceof CallRecordingViewModel.RecordingErrorState) {
|
||||
Toast.makeText(context, context.getResources().getString(R.string.nc_common_error_sorry),
|
||||
Toast.LENGTH_LONG).show();
|
||||
if (isAllowedToStartOrStopRecording()) {
|
||||
Toast.makeText(context, context.getResources().getString(R.string.record_failed_info),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
binding.callRecordingIndicator.setVisibility(View.GONE);
|
||||
} else {
|
||||
binding.callRecordingIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
@ -603,7 +617,14 @@ public class CallActivity extends CallBaseActivity {
|
||||
|
||||
binding.callRecordingIndicator.setOnClickListener(l -> {
|
||||
if (isAllowedToStartOrStopRecording()) {
|
||||
callRecordingViewModel.clickRecordButton();
|
||||
if (callRecordingViewModel.getViewState().getValue() instanceof CallRecordingViewModel.RecordingStartingState) {
|
||||
if (moreCallActionsDialog == null) {
|
||||
moreCallActionsDialog = new MoreCallActionsDialog(this);
|
||||
}
|
||||
moreCallActionsDialog.show();
|
||||
} else {
|
||||
callRecordingViewModel.clickRecordButton();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(context, context.getResources().getString(R.string.record_active_info), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -530,6 +530,7 @@ data class ChatMessage(
|
||||
RECORDING_STOPPED,
|
||||
AUDIO_RECORDING_STARTED,
|
||||
AUDIO_RECORDING_STOPPED,
|
||||
RECORDING_FAILED,
|
||||
BREAKOUT_ROOMS_STARTED,
|
||||
BREAKOUT_ROOMS_STOPPED
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.REACTIO
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.REACTION_REVOKED
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.READ_ONLY
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.READ_ONLY_OFF
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.RECORDING_FAILED
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.RECORDING_STARTED
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.RECORDING_STOPPED
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.USER_ADDED
|
||||
@ -143,6 +144,7 @@ class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.Syst
|
||||
"recording_stopped" -> RECORDING_STOPPED
|
||||
"audio_recording_started" -> AUDIO_RECORDING_STARTED
|
||||
"audio_recording_stopped" -> AUDIO_RECORDING_STOPPED
|
||||
"recording_failed" -> RECORDING_FAILED
|
||||
"breakout_rooms_started" -> BREAKOUT_ROOMS_STARTED
|
||||
"breakout_rooms_stopped" -> BREAKOUT_ROOMS_STOPPED
|
||||
else -> DUMMY
|
||||
@ -206,6 +208,7 @@ class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.Syst
|
||||
RECORDING_STOPPED -> "recording_stopped"
|
||||
AUDIO_RECORDING_STARTED -> "audio_recording_started"
|
||||
AUDIO_RECORDING_STOPPED -> "audio_recording_stopped"
|
||||
RECORDING_FAILED -> "recording_failed"
|
||||
BREAKOUT_ROOMS_STARTED -> "breakout_rooms_started"
|
||||
BREAKOUT_ROOMS_STOPPED -> "breakout_rooms_stopped"
|
||||
else -> ""
|
||||
|
@ -94,6 +94,20 @@ class MoreCallActionsDialog(private val callActivity: CallActivity) : BottomShee
|
||||
private fun initObservers() {
|
||||
callActivity.callRecordingViewModel.viewState.observe(this) { state ->
|
||||
when (state) {
|
||||
is CallRecordingViewModel.RecordingStoppedState,
|
||||
is CallRecordingViewModel.RecordingErrorState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_start_description)
|
||||
binding.recordCallIcon.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.record_start)
|
||||
)
|
||||
dismiss()
|
||||
}
|
||||
is CallRecordingViewModel.RecordingStartingState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_starting)
|
||||
binding.recordCallIcon.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.record_stop)
|
||||
)
|
||||
}
|
||||
is CallRecordingViewModel.RecordingStartedState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_stop_description)
|
||||
binding.recordCallIcon.setImageDrawable(
|
||||
@ -101,18 +115,8 @@ class MoreCallActionsDialog(private val callActivity: CallActivity) : BottomShee
|
||||
)
|
||||
dismiss()
|
||||
}
|
||||
is CallRecordingViewModel.RecordingStoppedState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_start_description)
|
||||
binding.recordCallIcon.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.record_start)
|
||||
)
|
||||
dismiss()
|
||||
}
|
||||
is CallRecordingViewModel.RecordingStartLoadingState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_start_loading)
|
||||
}
|
||||
is CallRecordingViewModel.RecordingStopLoadingState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_stop_loading)
|
||||
is CallRecordingViewModel.RecordingStoppingState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_stopping)
|
||||
}
|
||||
is CallRecordingViewModel.RecordingConfirmStopState -> {
|
||||
binding.recordCallText.text = context.getText(R.string.record_stop_description)
|
||||
|
@ -42,11 +42,11 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
lateinit var roomToken: String
|
||||
|
||||
sealed interface ViewState
|
||||
open class RecordingStartedState(val showStartedInfo: Boolean) : ViewState
|
||||
open class RecordingStartedState(val hasVideo: Boolean, val showStartedInfo: Boolean) : ViewState
|
||||
|
||||
object RecordingStoppedState : ViewState
|
||||
object RecordingStartLoadingState : ViewState
|
||||
object RecordingStopLoadingState : ViewState
|
||||
open class RecordingStartingState(val hasVideo: Boolean) : ViewState
|
||||
object RecordingStoppingState : ViewState
|
||||
object RecordingConfirmStopState : ViewState
|
||||
object RecordingErrorState : ViewState
|
||||
|
||||
@ -69,6 +69,9 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
// just show it again.
|
||||
_viewState.value = RecordingConfirmStopState
|
||||
}
|
||||
is RecordingStartingState -> {
|
||||
stopRecording()
|
||||
}
|
||||
RecordingErrorState -> {
|
||||
stopRecording()
|
||||
}
|
||||
@ -77,7 +80,7 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
}
|
||||
|
||||
private fun startRecording() {
|
||||
_viewState.value = RecordingStartLoadingState
|
||||
_viewState.value = RecordingStartingState(true)
|
||||
repository.startRecording(roomToken)
|
||||
.subscribeOn(Schedulers.io())
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -85,7 +88,7 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
}
|
||||
|
||||
fun stopRecording() {
|
||||
_viewState.value = RecordingStopLoadingState
|
||||
_viewState.value = RecordingStoppingState
|
||||
repository.stopRecording(roomToken)
|
||||
.subscribeOn(Schedulers.io())
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -93,7 +96,7 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
}
|
||||
|
||||
fun dismissStopRecording() {
|
||||
_viewState.value = RecordingStartedState(false)
|
||||
_viewState.value = RecordingStartedState(true, false)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
@ -109,8 +112,11 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
fun setRecordingState(state: Int) {
|
||||
when (state) {
|
||||
RECORDING_STOPPED_CODE -> _viewState.value = RecordingStoppedState
|
||||
RECORDING_STARTED_VIDEO_CODE -> _viewState.value = RecordingStartedState(true)
|
||||
RECORDING_STARTED_AUDIO_CODE -> _viewState.value = RecordingStartedState(true)
|
||||
RECORDING_STARTED_VIDEO_CODE -> _viewState.value = RecordingStartedState(true, true)
|
||||
RECORDING_STARTED_AUDIO_CODE -> _viewState.value = RecordingStartedState(false, true)
|
||||
RECORDING_STARTING_VIDEO_CODE -> _viewState.value = RecordingStartingState(true)
|
||||
RECORDING_STARTING_AUDIO_CODE -> _viewState.value = RecordingStartingState(false)
|
||||
RECORDING_FAILED_CODE -> _viewState.value = RecordingErrorState
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@ -160,5 +166,8 @@ class CallRecordingViewModel @Inject constructor(private val repository: CallRec
|
||||
const val RECORDING_STOPPED_CODE = 0
|
||||
const val RECORDING_STARTED_VIDEO_CODE = 1
|
||||
const val RECORDING_STARTED_AUDIO_CODE = 2
|
||||
const val RECORDING_STARTING_VIDEO_CODE = 3
|
||||
const val RECORDING_STARTING_AUDIO_CODE = 4
|
||||
const val RECORDING_FAILED_CODE = 5
|
||||
}
|
||||
}
|
||||
|
9
app/src/main/res/drawable/record_starting.xml
Normal file
9
app/src/main/res/drawable/record_starting.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@color/grey_600"
|
||||
android:pathData="M12,2A10,10 0,0 0,2 12A10,10 0,0 0,12 22A10,10 0,0 0,22 12A10,10 0,0 0,12 2M9,9H15V15H9"/>
|
||||
</vector>
|
@ -582,12 +582,13 @@ How to translate with transifex:
|
||||
|
||||
<!-- Call recording -->
|
||||
<string name="record_start_description">Start recording</string>
|
||||
<string name="record_start_loading">Starting …</string>
|
||||
<string name="record_starting">Cancel recording start</string>
|
||||
<string name="record_stop_description">Stop recording</string>
|
||||
<string name="record_stop_loading">Stopping …</string>
|
||||
<string name="record_stopping">Stopping recording …</string>
|
||||
<string name="record_stop_confirm_title">Stop Call recording</string>
|
||||
<string name="record_stop_confirm_message">Do you really want to stop the recording?</string>
|
||||
<string name="record_active_info">The call is being recorded</string>
|
||||
<string name="record_failed_info">The recording failed. Please contact your administrator.</string>
|
||||
|
||||
<!-- Shared items -->
|
||||
<string name="shared_items_media">Media</string>
|
||||
|
@ -21,7 +21,7 @@ class CallRecordingViewModelTest : AbstractViewModelTest() {
|
||||
viewModel.setData("foo")
|
||||
viewModel.clickRecordButton()
|
||||
|
||||
Assert.equals(CallRecordingViewModel.RecordingStartLoadingState, viewModel.viewState.value)
|
||||
Assert.equals(CallRecordingViewModel.RecordingStartingState(true), viewModel.viewState.value)
|
||||
|
||||
// fake to execute setRecordingState which would be triggered by signaling message
|
||||
viewModel.setRecordingState(CallRecordingViewModel.RECORDING_STARTED_VIDEO_CODE)
|
||||
@ -78,7 +78,7 @@ class CallRecordingViewModelTest : AbstractViewModelTest() {
|
||||
viewModel.dismissStopRecording()
|
||||
|
||||
Assert.equals(
|
||||
CallRecordingViewModel.RecordingStartedState(false).javaClass,
|
||||
CallRecordingViewModel.RecordingStartedState(true, false).javaClass,
|
||||
viewModel.viewState.value?.javaClass
|
||||
)
|
||||
Assert.equals(
|
||||
|
Loading…
Reference in New Issue
Block a user