mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-25 22:45:41 +03:00
Add recording consent feature
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
951f80315e
commit
bfbc352448
9 changed files with 305 additions and 11 deletions
|
@ -130,6 +130,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_ID
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_START_CALL_AFTER_ROOM_SWITCH
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_START_CALL_AFTER_ROOM_SWITCH
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SWITCH_TO_ROOM
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SWITCH_TO_ROOM
|
||||||
|
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
||||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.hasSpreedFeatureCapability
|
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.hasSpreedFeatureCapability
|
||||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.isCallRecordingAvailable
|
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.isCallRecordingAvailable
|
||||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||||
|
@ -376,6 +377,8 @@ class CallActivity : CallBaseActivity() {
|
||||||
AudioFormat.ENCODING_PCM_16BIT
|
AudioFormat.ENCODING_PCM_16BIT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private var recordingConsentGiven = false
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Log.d(TAG, "onCreate")
|
Log.d(TAG, "onCreate")
|
||||||
|
@ -496,11 +499,72 @@ class CallActivity : CallBaseActivity() {
|
||||||
callParticipants = HashMap()
|
callParticipants = HashMap()
|
||||||
participantDisplayItems = HashMap()
|
participantDisplayItems = HashMap()
|
||||||
initViews()
|
initViews()
|
||||||
if (!isConnectionEstablished) {
|
|
||||||
initiateCall()
|
|
||||||
}
|
|
||||||
updateSelfVideoViewPosition()
|
updateSelfVideoViewPosition()
|
||||||
reactionAnimator = ReactionAnimator(context, binding!!.reactionAnimationWrapper, viewThemeUtils)
|
reactionAnimator = ReactionAnimator(context, binding!!.reactionAnimationWrapper, viewThemeUtils)
|
||||||
|
|
||||||
|
checkRecordingConsentAndInitiateCall()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkRecordingConsentAndInitiateCall() {
|
||||||
|
fun askForRecordingConsent() {
|
||||||
|
val materialAlertDialogBuilder = MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle(R.string.recording_consent_title)
|
||||||
|
.setMessage(R.string.recording_consent_description)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(R.string.nc_yes) { _, _ ->
|
||||||
|
recordingConsentGiven = true
|
||||||
|
initiateCall()
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.nc_no) { _, _ ->
|
||||||
|
recordingConsentGiven = false
|
||||||
|
hangup(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, materialAlertDialogBuilder)
|
||||||
|
val dialog = materialAlertDialogBuilder.show()
|
||||||
|
viewThemeUtils.platform.colorTextButtons(
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (CapabilitiesUtilNew.getRecordingConsentType(conversationUser)) {
|
||||||
|
CapabilitiesUtilNew.RECORDING_CONSENT_NOT_REQUIRED -> initiateCall()
|
||||||
|
CapabilitiesUtilNew.RECORDING_CONSENT_REQUIRED -> askForRecordingConsent()
|
||||||
|
CapabilitiesUtilNew.RECORDING_CONSENT_DEPEND_ON_CONVERSATION -> {
|
||||||
|
val getRoomApiVersion = ApiUtils.getConversationApiVersion(
|
||||||
|
conversationUser,
|
||||||
|
intArrayOf(ApiUtils.APIv4, 1)
|
||||||
|
)
|
||||||
|
ncApi!!.getRoom(credentials, ApiUtils.getUrlForRoom(getRoomApiVersion, baseUrl, roomToken))
|
||||||
|
.retry(API_RETRIES)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : Observer<RoomOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(roomOverall: RoomOverall) {
|
||||||
|
val conversation = roomOverall.ocs!!.data
|
||||||
|
if (conversation?.recordingConsentRequired == 1) {
|
||||||
|
askForRecordingConsent()
|
||||||
|
} else {
|
||||||
|
initiateCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
Log.e(TAG, "Failed to get room", e)
|
||||||
|
Snackbar.make(binding!!.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -1660,7 +1724,8 @@ class CallActivity : CallBaseActivity() {
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken),
|
ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken),
|
||||||
inCallFlag,
|
inCallFlag,
|
||||||
isCallWithoutNotification
|
isCallWithoutNotification,
|
||||||
|
recordingConsentGiven
|
||||||
)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.retry(API_RETRIES)
|
.retry(API_RETRIES)
|
||||||
|
@ -1676,6 +1741,8 @@ class CallActivity : CallBaseActivity() {
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Log.e(TAG, "Failed to join call", e)
|
Log.e(TAG, "Failed to join call", e)
|
||||||
|
Snackbar.make(binding!!.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
||||||
|
hangup(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onComplete() {
|
override fun onComplete() {
|
||||||
|
@ -1804,6 +1871,10 @@ class CallActivity : CallBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initiateCall() {
|
private fun initiateCall() {
|
||||||
|
if (isConnectionEstablished) {
|
||||||
|
Log.d(TAG, "connection already established")
|
||||||
|
return
|
||||||
|
}
|
||||||
checkDevicePermissions()
|
checkDevicePermissions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,9 +245,11 @@ public interface NcApi {
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization, @Url String url,
|
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization,
|
||||||
|
@Url String url,
|
||||||
@Field("flags") Integer inCall,
|
@Field("flags") Integer inCall,
|
||||||
@Field("silent") Boolean callWithoutNotification);
|
@Field("silent") Boolean callWithoutNotification,
|
||||||
|
@Nullable @Field("recordingConsent") Boolean recordingConsent);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
||||||
|
@ -686,4 +688,10 @@ public interface NcApi {
|
||||||
Observable<ReminderOverall> setReminder(@Header("Authorization") String authorization,
|
Observable<ReminderOverall> setReminder(@Header("Authorization") String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@Field("timestamp") int timestamp);
|
@Field("timestamp") int timestamp);
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@PUT
|
||||||
|
Observable<GenericOverall> setRecordingConsent(@Header("Authorization") String authorization,
|
||||||
|
@Url String url,
|
||||||
|
@Field("recordingConsent") int recordingConsent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,7 +247,8 @@ class ConversationInfoActivity :
|
||||||
binding.notificationSettingsView.callNotificationsSwitch,
|
binding.notificationSettingsView.callNotificationsSwitch,
|
||||||
binding.notificationSettingsView.importantConversationSwitch,
|
binding.notificationSettingsView.importantConversationSwitch,
|
||||||
binding.guestAccessView.allowGuestsSwitch,
|
binding.guestAccessView.allowGuestsSwitch,
|
||||||
binding.guestAccessView.passwordProtectionSwitch
|
binding.guestAccessView.passwordProtectionSwitch,
|
||||||
|
binding.recordingConsentView.recordingConsentForConversationSwitch
|
||||||
).forEach(viewThemeUtils.talk::colorSwitch)
|
).forEach(viewThemeUtils.talk::colorSwitch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,6 +260,7 @@ class ConversationInfoActivity :
|
||||||
binding.webinarInfoView.webinarSettingsCategory,
|
binding.webinarInfoView.webinarSettingsCategory,
|
||||||
binding.guestAccessView.guestAccessSettingsCategory,
|
binding.guestAccessView.guestAccessSettingsCategory,
|
||||||
binding.sharedItemsTitle,
|
binding.sharedItemsTitle,
|
||||||
|
binding.recordingConsentView.recordingConsentSettingsCategory,
|
||||||
binding.conversationSettingsTitle,
|
binding.conversationSettingsTitle,
|
||||||
binding.participantsListCategory
|
binding.participantsListCategory
|
||||||
)
|
)
|
||||||
|
@ -707,6 +709,7 @@ class ConversationInfoActivity :
|
||||||
|
|
||||||
loadConversationAvatar()
|
loadConversationAvatar()
|
||||||
adjustNotificationLevelUI()
|
adjustNotificationLevelUI()
|
||||||
|
initRecordingConsentOption()
|
||||||
initExpiringMessageOption()
|
initExpiringMessageOption()
|
||||||
|
|
||||||
binding.let {
|
binding.let {
|
||||||
|
@ -738,6 +741,86 @@ class ConversationInfoActivity :
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initRecordingConsentOption() {
|
||||||
|
fun hide() {
|
||||||
|
binding.recordingConsentView.recordingConsentSettingsCategory.visibility = GONE
|
||||||
|
binding.recordingConsentView.recordingConsentForConversation.visibility = GONE
|
||||||
|
binding.recordingConsentView.recordingConsentAll.visibility = GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showAlwaysRequiredInfo() {
|
||||||
|
binding.recordingConsentView.recordingConsentForConversation.visibility = GONE
|
||||||
|
binding.recordingConsentView.recordingConsentAll.visibility = VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showSwitch() {
|
||||||
|
binding.recordingConsentView.recordingConsentForConversation.visibility = VISIBLE
|
||||||
|
binding.recordingConsentView.recordingConsentAll.visibility = GONE
|
||||||
|
|
||||||
|
if (conversation!!.hasCall) {
|
||||||
|
binding.recordingConsentView.recordingConsentForConversation.isEnabled = false
|
||||||
|
binding.recordingConsentView.recordingConsentForConversation.alpha = LOW_EMPHASIS_OPACITY
|
||||||
|
} else {
|
||||||
|
binding.recordingConsentView.recordingConsentForConversationSwitch.isChecked =
|
||||||
|
conversation!!.recordingConsentRequired == RECORDING_CONSENT_REQUIRED_FOR_CONVERSATION
|
||||||
|
|
||||||
|
binding.recordingConsentView.recordingConsentForConversation.setOnClickListener {
|
||||||
|
binding.recordingConsentView.recordingConsentForConversationSwitch.isChecked =
|
||||||
|
!binding.recordingConsentView.recordingConsentForConversationSwitch.isChecked
|
||||||
|
submitRecordingConsentChanges()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversation!!.isParticipantOwnerOrModerator &&
|
||||||
|
!ConversationUtils.isNoteToSelfConversation(ConversationModel.mapToConversationModel(conversation!!))
|
||||||
|
) {
|
||||||
|
when (CapabilitiesUtilNew.getRecordingConsentType(conversationUser)) {
|
||||||
|
CapabilitiesUtilNew.RECORDING_CONSENT_NOT_REQUIRED -> hide()
|
||||||
|
CapabilitiesUtilNew.RECORDING_CONSENT_REQUIRED -> showAlwaysRequiredInfo()
|
||||||
|
CapabilitiesUtilNew.RECORDING_CONSENT_DEPEND_ON_CONVERSATION -> showSwitch()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun submitRecordingConsentChanges() {
|
||||||
|
val state = if (binding.recordingConsentView.recordingConsentForConversationSwitch.isChecked) {
|
||||||
|
RECORDING_CONSENT_REQUIRED_FOR_CONVERSATION
|
||||||
|
} else {
|
||||||
|
RECORDING_CONSENT_NOT_REQUIRED_FOR_CONVERSATION
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
|
||||||
|
|
||||||
|
ncApi.setRecordingConsent(
|
||||||
|
ApiUtils.getCredentials(conversationUser.username, conversationUser.token),
|
||||||
|
ApiUtils.getUrlForRecordingConsent(apiVersion, conversationUser.baseUrl, conversation!!.token),
|
||||||
|
state
|
||||||
|
)
|
||||||
|
?.subscribeOn(Schedulers.io())
|
||||||
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
?.subscribe(object : Observer<GenericOverall> {
|
||||||
|
override fun onComplete() {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(t: GenericOverall) {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
||||||
|
Log.e(TAG, "Error when setting recording consent option for conversation", e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private fun initExpiringMessageOption() {
|
private fun initExpiringMessageOption() {
|
||||||
if (conversation!!.isParticipantOwnerOrModerator &&
|
if (conversation!!.isParticipantOwnerOrModerator &&
|
||||||
!ConversationUtils.isNoteToSelfConversation(ConversationModel.mapToConversationModel(conversation!!)) &&
|
!ConversationUtils.isNoteToSelfConversation(ConversationModel.mapToConversationModel(conversation!!)) &&
|
||||||
|
@ -1227,11 +1310,13 @@ class ConversationInfoActivity :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "ConversationInfo"
|
private val TAG = ConversationInfoActivity::class.java.simpleName
|
||||||
private const val NOTIFICATION_LEVEL_ALWAYS: Int = 1
|
private const val NOTIFICATION_LEVEL_ALWAYS: Int = 1
|
||||||
private const val NOTIFICATION_LEVEL_MENTION: Int = 2
|
private const val NOTIFICATION_LEVEL_MENTION: Int = 2
|
||||||
private const val NOTIFICATION_LEVEL_NEVER: Int = 3
|
private const val NOTIFICATION_LEVEL_NEVER: Int = 3
|
||||||
private const val LOW_EMPHASIS_OPACITY: Float = 0.38f
|
private const val LOW_EMPHASIS_OPACITY: Float = 0.38f
|
||||||
|
private const val RECORDING_CONSENT_NOT_REQUIRED_FOR_CONVERSATION: Int = 0
|
||||||
|
private const val RECORDING_CONSENT_REQUIRED_FOR_CONVERSATION: Int = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -157,7 +157,10 @@ data class Conversation(
|
||||||
var hasCustomAvatar: Boolean? = null,
|
var hasCustomAvatar: Boolean? = null,
|
||||||
|
|
||||||
@JsonField(name = ["callStartTime"])
|
@JsonField(name = ["callStartTime"])
|
||||||
var callStartTime: Long? = null
|
var callStartTime: Long? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["recordingConsent"])
|
||||||
|
var recordingConsentRequired: Int = 0
|
||||||
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
|
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
|
||||||
|
|
|
@ -536,4 +536,8 @@ public class ApiUtils {
|
||||||
String url = ApiUtils.getUrlForChatMessage(version, user.getBaseUrl(), roomToken, messageId);
|
String url = ApiUtils.getUrlForChatMessage(version, user.getBaseUrl(), roomToken, messageId);
|
||||||
return url + "/reminder";
|
return url + "/reminder";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getUrlForRecordingConsent(int version, String baseUrl, String token) {
|
||||||
|
return getUrlForRoom(version, baseUrl, token) + "/recording-consent";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,5 +250,29 @@ object CapabilitiesUtilNew {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getRecordingConsentType(user: User?): Int {
|
||||||
|
if (user?.capabilities != null) {
|
||||||
|
val capabilities = user.capabilities
|
||||||
|
if (
|
||||||
|
capabilities?.spreedCapability?.config?.containsKey("call") == true &&
|
||||||
|
capabilities.spreedCapability!!.config!!["call"] != null &&
|
||||||
|
capabilities.spreedCapability!!.config!!["call"]!!.containsKey("recording-consent")
|
||||||
|
) {
|
||||||
|
return when (
|
||||||
|
capabilities.spreedCapability!!.config!!["call"]!!["recording-consent"].toString()
|
||||||
|
.toInt()
|
||||||
|
) {
|
||||||
|
1 -> RECORDING_CONSENT_REQUIRED
|
||||||
|
2 -> RECORDING_CONSENT_DEPEND_ON_CONVERSATION
|
||||||
|
else -> RECORDING_CONSENT_NOT_REQUIRED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RECORDING_CONSENT_NOT_REQUIRED
|
||||||
|
}
|
||||||
|
|
||||||
const val DEFAULT_CHAT_SIZE = 1000
|
const val DEFAULT_CHAT_SIZE = 1000
|
||||||
|
const val RECORDING_CONSENT_NOT_REQUIRED = 0
|
||||||
|
const val RECORDING_CONSENT_REQUIRED = 1
|
||||||
|
const val RECORDING_CONSENT_DEPEND_ON_CONVERSATION = 2
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,6 +226,12 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/recording_consent_view"
|
||||||
|
layout="@layout/item_recording_consent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/standard_quarter_margin" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/conversation_settings"
|
android:id="@+id/conversation_settings"
|
||||||
|
@ -261,7 +267,6 @@
|
||||||
android:popupTheme="@style/ThemeOverlay.AppTheme.PopupMenu"
|
android:popupTheme="@style/ThemeOverlay.AppTheme.PopupMenu"
|
||||||
android:text="" />
|
android:text="" />
|
||||||
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
|
89
app/src/main/res/layout/item_recording_consent.xml
Normal file
89
app/src/main/res/layout/item_recording_consent.xml
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Nextcloud Talk application
|
||||||
|
~
|
||||||
|
~ @author Marcel Hibbe
|
||||||
|
~ Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/recording_consent_settings"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/recording_consent_settings_category"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/standard_margin"
|
||||||
|
android:layout_marginEnd="@dimen/standard_margin"
|
||||||
|
android:paddingTop="@dimen/standard_padding"
|
||||||
|
android:paddingBottom="@dimen/standard_half_padding"
|
||||||
|
android:text="@string/recording_settings_title"
|
||||||
|
android:textSize="@dimen/headline_text_size"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/recording_consent_for_conversation"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="@dimen/standard_margin"
|
||||||
|
android:paddingTop="@dimen/standard_margin"
|
||||||
|
android:paddingEnd="@dimen/standard_margin"
|
||||||
|
android:paddingBottom="@dimen/standard_half_margin">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/recording_consent_for_conversation_title"
|
||||||
|
android:textSize="@dimen/headline_text_size" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/recording_consent_for_conversation_description"
|
||||||
|
android:textSize="@dimen/supporting_text_text_size" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/recording_consent_for_conversation_switch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="@dimen/standard_margin"
|
||||||
|
android:clickable="false" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/recording_consent_all"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="@dimen/standard_margin"
|
||||||
|
android:paddingTop="@dimen/standard_margin"
|
||||||
|
android:paddingEnd="@dimen/standard_margin"
|
||||||
|
android:paddingBottom="@dimen/standard_half_margin"
|
||||||
|
android:text="@string/recording_consent_all" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -606,6 +606,12 @@ How to translate with transifex:
|
||||||
<string name="record_cancel_start">Cancel recording start</string>
|
<string name="record_cancel_start">Cancel recording start</string>
|
||||||
<string name="record_stopping">Stopping recording …</string>
|
<string name="record_stopping">Stopping recording …</string>
|
||||||
<string name="record_failed_info">The recording failed. Please contact your administrator.</string>
|
<string name="record_failed_info">The recording failed. Please contact your administrator.</string>
|
||||||
|
<string name="recording_consent_title">The call might be recorded.</string>
|
||||||
|
<string name="recording_consent_description">The recording might include your voice, video from camera, and screen share. Your consent is required before joining the call. Do you consent?</string>
|
||||||
|
<string name="recording_settings_title">Recording</string>
|
||||||
|
<string name="recording_consent_for_conversation_title">Recording consent</string>
|
||||||
|
<string name="recording_consent_for_conversation_description">Require recording consent before joining call in this conversation</string>
|
||||||
|
<string name="recording_consent_all">Recording consent is required for all calls</string>
|
||||||
|
|
||||||
<!-- Shared items -->
|
<!-- Shared items -->
|
||||||
<string name="nc_shared_items">Shared items</string>
|
<string name="nc_shared_items">Shared items</string>
|
||||||
|
@ -708,5 +714,4 @@ How to translate with transifex:
|
||||||
<string name="audio_call">Audio Call</string>
|
<string name="audio_call">Audio Call</string>
|
||||||
<string name="started_a_call">started a call</string>
|
<string name="started_a_call">started a call</string>
|
||||||
<string name="nc_settings_phone_book_integration_phone_number_dialog_429">Error 429 Too Many Requests</string>
|
<string name="nc_settings_phone_book_integration_phone_number_dialog_429">Error 429 Too Many Requests</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue