diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index abd5a7c8c..2791e23f4 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -2805,6 +2805,10 @@ public class CallActivity extends CallBaseActivity { } } + @Override + public void onReaction(String reaction) { + } + @Override public void onUnshareScreen() { endPeerConnection(sessionId, "screen"); diff --git a/app/src/main/java/com/nextcloud/talk/call/CallParticipant.java b/app/src/main/java/com/nextcloud/talk/call/CallParticipant.java index d3e202a0c..e0f4df295 100644 --- a/app/src/main/java/com/nextcloud/talk/call/CallParticipant.java +++ b/app/src/main/java/com/nextcloud/talk/call/CallParticipant.java @@ -40,6 +40,10 @@ public class CallParticipant { callParticipantModel.setRaisedHand(state, timestamp); } + @Override + public void onReaction(String reaction) { + } + @Override public void onUnshareScreen() { } diff --git a/app/src/main/java/com/nextcloud/talk/models/json/signaling/NCMessagePayload.kt b/app/src/main/java/com/nextcloud/talk/models/json/signaling/NCMessagePayload.kt index ce078f11e..1f478b9fc 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/signaling/NCMessagePayload.kt +++ b/app/src/main/java/com/nextcloud/talk/models/json/signaling/NCMessagePayload.kt @@ -42,8 +42,10 @@ data class NCMessagePayload( @JsonField(name = ["state"]) var state: Boolean? = null, @JsonField(name = ["timestamp"]) - var timestamp: Long? = null + var timestamp: Long? = null, + @JsonField(name = ["reaction"]) + var reaction: String? = null ) : Parcelable { // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' - constructor() : this(null, null, null, null, null, null, null) + constructor() : this(null, null, null, null, null, null, null, null) } diff --git a/app/src/main/java/com/nextcloud/talk/signaling/CallParticipantMessageNotifier.java b/app/src/main/java/com/nextcloud/talk/signaling/CallParticipantMessageNotifier.java index f1cf54e9b..07679304b 100644 --- a/app/src/main/java/com/nextcloud/talk/signaling/CallParticipantMessageNotifier.java +++ b/app/src/main/java/com/nextcloud/talk/signaling/CallParticipantMessageNotifier.java @@ -93,6 +93,12 @@ class CallParticipantMessageNotifier { } } + public void notifyReaction(String sessionId, String reaction) { + for (SignalingMessageReceiver.CallParticipantMessageListener listener : getListenersFor(sessionId)) { + listener.onReaction(reaction); + } + } + public synchronized void notifyUnshareScreen(String sessionId) { for (SignalingMessageReceiver.CallParticipantMessageListener listener : getListenersFor(sessionId)) { listener.onUnshareScreen(); diff --git a/app/src/main/java/com/nextcloud/talk/signaling/SignalingMessageReceiver.java b/app/src/main/java/com/nextcloud/talk/signaling/SignalingMessageReceiver.java index ad18751a8..8853af425 100644 --- a/app/src/main/java/com/nextcloud/talk/signaling/SignalingMessageReceiver.java +++ b/app/src/main/java/com/nextcloud/talk/signaling/SignalingMessageReceiver.java @@ -149,6 +149,7 @@ public abstract class SignalingMessageReceiver { */ public interface CallParticipantMessageListener { void onRaiseHand(boolean state, long timestamp); + void onReaction(String reaction); void onUnshareScreen(); } @@ -562,6 +563,57 @@ public abstract class SignalingMessageReceiver { return; } + if ("reaction".equals(type)) { + // Message schema (external signaling server): + // { + // "type": "message", + // "message": { + // "sender": { + // ... + // }, + // "data": { + // "to": #STRING#, + // "roomType": "video", + // "type": "reaction", + // "payload": { + // "reaction": #STRING#, + // }, + // "from": #STRING#, + // }, + // }, + // } + // + // Message schema (internal signaling server): + // { + // "type": "message", + // "data": { + // "to": #STRING#, + // "roomType": "video", + // "type": "reaction", + // "payload": { + // "reaction": #STRING#, + // }, + // "from": #STRING#, + // }, + // } + + NCMessagePayload payload = signalingMessage.getPayload(); + if (payload == null) { + // Broken message, this should not happen. + return; + } + + String reaction = payload.getReaction(); + if (reaction == null) { + // Broken message, this should not happen. + return; + } + + callParticipantMessageNotifier.notifyReaction(sessionId, reaction); + + return; + } + // "unshareScreen" messages are directly sent to the screen peer connection when the internal signaling // server is used, and to the room when the external signaling server is used. However, the (relevant) data // of the received message ("from" and "type") is the same in both cases. diff --git a/app/src/test/java/com/nextcloud/talk/signaling/SignalingMessageReceiverCallParticipantTest.java b/app/src/test/java/com/nextcloud/talk/signaling/SignalingMessageReceiverCallParticipantTest.java index 96d90b23d..525e26d69 100644 --- a/app/src/test/java/com/nextcloud/talk/signaling/SignalingMessageReceiverCallParticipantTest.java +++ b/app/src/test/java/com/nextcloud/talk/signaling/SignalingMessageReceiverCallParticipantTest.java @@ -84,6 +84,26 @@ public class SignalingMessageReceiverCallParticipantTest { verify(mockedCallParticipantMessageListener, only()).onRaiseHand(true, 4815162342L); } + @Test + public void testCallParticipantMessageReaction() { + SignalingMessageReceiver.CallParticipantMessageListener mockedCallParticipantMessageListener = + mock(SignalingMessageReceiver.CallParticipantMessageListener.class); + + signalingMessageReceiver.addListener(mockedCallParticipantMessageListener, "theSessionId"); + + NCSignalingMessage signalingMessage = new NCSignalingMessage(); + signalingMessage.setFrom("theSessionId"); + signalingMessage.setType("reaction"); + signalingMessage.setRoomType("theRoomType"); + NCMessagePayload messagePayload = new NCMessagePayload(); + messagePayload.setType("reaction"); + messagePayload.setReaction("theReaction"); + signalingMessage.setPayload(messagePayload); + signalingMessageReceiver.processSignalingMessage(signalingMessage); + + verify(mockedCallParticipantMessageListener, only()).onReaction("theReaction"); + } + @Test public void testCallParticipantMessageUnshareScreen() { SignalingMessageReceiver.CallParticipantMessageListener mockedCallParticipantMessageListener =