Przeglądaj źródła

Respect can publish audio & video permission

With this implementation the can publish audio & video permission are
set during the creation of the 'CallActivity'. This permissions are
fixed for the complete call. If the permissions are changed by a
moderator the call must be left and joined again.

Resolves: #1783

Signed-off-by: Tim Krüger <t@timkrueger.me>
Tim Krüger 2 lat temu
rodzic
commit
c554535bae

+ 74 - 32
app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

@@ -170,6 +170,8 @@ import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME;
 import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_PASSWORD;
 import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FROM_NOTIFICATION_START_CALL;
 import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MODIFIED_BASE_URL;
+import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO;
+import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO;
 import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_ID;
 import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN;
 import static com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY;
@@ -293,6 +295,9 @@ public class CallActivity extends CallBaseActivity {
             }
         });
 
+    private boolean canPublishAudioStream;
+    private boolean canPublishVideoStream;
+
     @SuppressLint("ClickableViewAccessibility")
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -314,6 +319,8 @@ public class CallActivity extends CallBaseActivity {
         conversationName = extras.getString(KEY_CONVERSATION_NAME, "");
         isVoiceOnlyCall = extras.getBoolean(KEY_CALL_VOICE_ONLY, false);
         isCallWithoutNotification = extras.getBoolean(KEY_CALL_WITHOUT_NOTIFICATION, false);
+        canPublishAudioStream = extras.getBoolean(KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO);
+        canPublishVideoStream = extras.getBoolean(KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO);
 
         if (extras.containsKey(KEY_FROM_NOTIFICATION_START_CALL)) {
             isIncomingCallFromNotification = extras.getBoolean(KEY_FROM_NOTIFICATION_START_CALL);
@@ -387,23 +394,41 @@ public class CallActivity extends CallBaseActivity {
             audioOutputDialog.show();
         });
 
-        binding.microphoneButton.setOnClickListener(l -> onMicrophoneClick());
-        binding.microphoneButton.setOnLongClickListener(l -> {
-            if (!microphoneOn) {
-                callControlHandler.removeCallbacksAndMessages(null);
-                callInfosHandler.removeCallbacksAndMessages(null);
-                cameraSwitchHandler.removeCallbacksAndMessages(null);
-                isPTTActive = true;
-                binding.callControls.setVisibility(View.VISIBLE);
-                if (!isVoiceOnlyCall) {
-                    binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
+        if (canPublishAudioStream) {
+            binding.microphoneButton.setOnClickListener(l -> onMicrophoneClick());
+            binding.microphoneButton.setOnLongClickListener(l -> {
+                if (!microphoneOn) {
+                    callControlHandler.removeCallbacksAndMessages(null);
+                    callInfosHandler.removeCallbacksAndMessages(null);
+                    cameraSwitchHandler.removeCallbacksAndMessages(null);
+                    isPTTActive = true;
+                    binding.callControls.setVisibility(View.VISIBLE);
+                    if (!isVoiceOnlyCall) {
+                        binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
+                    }
                 }
-            }
-            onMicrophoneClick();
-            return true;
-        });
+                onMicrophoneClick();
+                return true;
+            });
+        } else {
+            binding.microphoneButton.setOnClickListener(
+                l -> Toast.makeText(context,
+                                    R.string.nc_not_allowed_to_activate_audio,
+                                    Toast.LENGTH_SHORT
+                                   ).show()
+                                                       );
+        }
 
-        binding.cameraButton.setOnClickListener(l -> onCameraClick());
+        if (canPublishVideoStream) {
+            binding.cameraButton.setOnClickListener(l -> onCameraClick());
+        } else {
+            binding.cameraButton.setOnClickListener(
+                l -> Toast.makeText(context,
+                                    R.string.nc_not_allowed_to_activate_video,
+                                    Toast.LENGTH_SHORT
+                                   ).show()
+                                                   );
+        }
 
         binding.hangupButton.setOnClickListener(l -> {
             hangup(true);
@@ -558,7 +583,7 @@ public class CallActivity extends CallBaseActivity {
                         }
                     }
 
-                    checkPermissions();
+                    checkDevicePermissions();
                 }
 
                 @Override
@@ -705,7 +730,7 @@ public class CallActivity extends CallBaseActivity {
     }
 
 
-    private void checkPermissions() {
+    private void checkDevicePermissions() {
         if (isVoiceOnlyCall) {
             onMicrophoneClick();
         } else {
@@ -764,7 +789,7 @@ public class CallActivity extends CallBaseActivity {
                 binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
             }
 
-            if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
+            if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA) && canPublishVideoStream) {
                 if (!videoOn) {
                     onCameraClick();
                 }
@@ -775,7 +800,7 @@ public class CallActivity extends CallBaseActivity {
             }
         }
 
-        if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
+        if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE) && canPublishAudioStream) {
             if (!microphoneOn) {
                 onMicrophoneClick();
             }
@@ -888,6 +913,18 @@ public class CallActivity extends CallBaseActivity {
     }
 
     public void onMicrophoneClick() {
+
+        if (isVoiceOnlyCall && !isConnectionEstablished()) {
+            fetchSignalingSettings();
+        }
+
+        if (!canPublishAudioStream) {
+            microphoneOn = false;
+            binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
+            // In the case no audio stream will be published it's not needed to check microphone permissions
+            return;
+        }
+
         if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
 
             if (!appPreferences.getPushToTalkIntroShown()) {
@@ -936,11 +973,6 @@ public class CallActivity extends CallBaseActivity {
                 pulseAnimation.start();
                 toggleMedia(true, false);
             }
-
-            if (isVoiceOnlyCall && !isConnectionEstablished()) {
-                fetchSignalingSettings();
-            }
-
         } else if (EffortlessPermissions.somePermissionPermanentlyDenied(this, PERMISSIONS_MICROPHONE)) {
             // Microphone permission is permanently denied so we cannot request it normally.
 
@@ -957,6 +989,14 @@ public class CallActivity extends CallBaseActivity {
     }
 
     public void onCameraClick() {
+
+        if (!canPublishVideoStream) {
+            videoOn = false;
+            binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
+            binding.switchSelfVideoButton.setVisibility(View.GONE);
+            return;
+        }
+
         if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_CAMERA)) {
             videoOn = !videoOn;
 
@@ -1384,12 +1424,14 @@ public class CallActivity extends CallBaseActivity {
     }
 
     private void performCall() {
-        int inCallFlag;
-        if (isVoiceOnlyCall) {
-            inCallFlag = Participant.InCallFlags.IN_CALL + Participant.InCallFlags.WITH_AUDIO;
-        } else {
-            inCallFlag =
-                Participant.InCallFlags.IN_CALL + Participant.InCallFlags.WITH_AUDIO + Participant.InCallFlags.WITH_VIDEO;
+        int inCallFlag = Participant.InCallFlags.IN_CALL;
+
+        if (canPublishAudioStream) {
+            inCallFlag += Participant.InCallFlags.WITH_AUDIO;
+        }
+
+        if (!isVoiceOnlyCall && canPublishVideoStream) {
+            inCallFlag += Participant.InCallFlags.WITH_VIDEO;
         }
 
         int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
@@ -1495,7 +1537,7 @@ public class CallActivity extends CallBaseActivity {
 
     private void initiateCall() {
         if (!TextUtils.isEmpty(roomToken)) {
-            checkPermissions();
+            checkDevicePermissions();
         } else {
             handleFromNotification();
         }
@@ -2302,7 +2344,7 @@ public class CallActivity extends CallBaseActivity {
         if (peerConnectionWrapper != null) {
             PeerConnection.IceConnectionState iceConnectionState = peerConnectionWrapper.getPeerConnection().iceConnectionState();
             connected = iceConnectionState == PeerConnection.IceConnectionState.CONNECTED ||
-                        iceConnectionState == PeerConnection.IceConnectionState.COMPLETED;
+                iceConnectionState == PeerConnection.IceConnectionState.COMPLETED;
         }
 
         String nick;

+ 8 - 0
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -2747,6 +2747,14 @@ class ChatController(args: Bundle) :
             bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, roomPassword)
             bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, conversationUser?.baseUrl)
             bundle.putString(KEY_CONVERSATION_NAME, it.displayName)
+            bundle.putBoolean(
+                BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO,
+                participantPermissions.canPublishAudio()
+            )
+            bundle.putBoolean(
+                BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO,
+                participantPermissions.canPublishVideo()
+            )
 
             if (isVoiceOnlyCall) {
                 bundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true)

+ 18 - 2
app/src/main/java/com/nextcloud/talk/utils/ParticipantPermissions.kt

@@ -39,8 +39,8 @@ class ParticipantPermissions(
     private val canStartCall = (conversation.permissions and START_CALL) == START_CALL
     val canJoinCall = (conversation.permissions and JOIN_CALL) == JOIN_CALL
     private val canIgnoreLobby = (conversation.permissions and CAN_IGNORE_LOBBY) == CAN_IGNORE_LOBBY
-    val canPublishAudio = (conversation.permissions and PUBLISH_AUDIO) == PUBLISH_AUDIO
-    val canPublishVideo = (conversation.permissions and PUBLISH_VIDEO) == PUBLISH_VIDEO
+    private val canPublishAudio = (conversation.permissions and PUBLISH_AUDIO) == PUBLISH_AUDIO
+    private val canPublishVideo = (conversation.permissions and PUBLISH_VIDEO) == PUBLISH_VIDEO
     val canPublishScreen = (conversation.permissions and PUBLISH_SCREEN) == PUBLISH_SCREEN
     private val hasChatPermission = (conversation.permissions and CHAT) == CHAT
 
@@ -67,6 +67,22 @@ class ParticipantPermissions(
         }
     }
 
+    fun canPublishAudio(): Boolean {
+        return if (hasConversationPermissions()) {
+            canPublishAudio
+        } else {
+            true
+        }
+    }
+
+    fun canPublishVideo(): Boolean {
+        return if (hasConversationPermissions()) {
+            canPublishVideo
+        } else {
+            true
+        }
+    }
+
     fun hasChatPermission(): Boolean {
         if (CapabilitiesUtilNew.hasSpreedFeatureCapability(user, "chat-permission")) {
             return hasChatPermission

+ 2 - 0
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt

@@ -75,4 +75,6 @@ object BundleKeys {
     const val KEY_SYSTEM_NOTIFICATION_ID = "KEY_SYSTEM_NOTIFICATION_ID"
     const val KEY_MESSAGE_ID = "KEY_MESSAGE_ID"
     const val KEY_MIME_TYPE_FILTER = "KEY_MIME_TYPE_FILTER"
+    const val KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO = "KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO"
+    const val KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO = "KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO"
 }

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -602,4 +602,7 @@
     <string name="nc_expire_message_one_hour">1 hour</string>
     <string name="nc_expire_messages_explanation">Chat messages can be expired after a certain time. Note: Files shared in chat will not be deleted for the owner, but will no longer be shared in the conversation.</string>
 
+    <string name="nc_not_allowed_to_activate_audio">You\'re not allowed to activate audio!</string>
+    <string name="nc_not_allowed_to_activate_video">You\'re not allowed to activate video!</string>
+
 </resources>

+ 3 - 3
app/src/test/java/com/nextcloud/talk/utils/ParticipantPermissionsTest.kt

@@ -50,8 +50,8 @@ class ParticipantPermissionsTest : TestCase() {
 
         assertFalse(attendeePermissions.isCustom)
         assertFalse(attendeePermissions.canStartCall())
-        assertFalse(attendeePermissions.canIgnoreLobby)
-        assertFalse(attendeePermissions.canPublishAudio)
-        assertFalse(attendeePermissions.canPublishVideo)
+        assertFalse(attendeePermissions.canIgnoreLobby())
+        assertTrue(attendeePermissions.canPublishAudio())
+        assertTrue(attendeePermissions.canPublishVideo())
     }
 }