Merge pull request #1769 from nextcloud/feature/1660/endMeetingForAll

Feature/1660/end meeting for all
This commit is contained in:
Marcel Hibbe 2022-01-12 13:57:58 +01:00 committed by GitHub
commit 77b6e2d6ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 83 additions and 80 deletions

View File

@ -1277,11 +1277,11 @@ public class CallActivity extends CallBaseActivity {
} }
private void performCall() { private void performCall() {
Integer inCallFlag; int inCallFlag;
if (isVoiceOnlyCall) { if (isVoiceOnlyCall) {
inCallFlag = (int) Participant.ParticipantFlags.IN_CALL_WITH_AUDIO.getValue(); inCallFlag = Participant.InCallFlags.IN_CALL + Participant.InCallFlags.WITH_AUDIO;
} else { } else {
inCallFlag = (int) Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue(); inCallFlag = Participant.InCallFlags.IN_CALL + Participant.InCallFlags.WITH_VIDEO;
} }
int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1}); int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
@ -1393,6 +1393,7 @@ public class CallActivity extends CallBaseActivity {
public void onMessageEvent(WebSocketCommunicationEvent webSocketCommunicationEvent) { public void onMessageEvent(WebSocketCommunicationEvent webSocketCommunicationEvent) {
switch (webSocketCommunicationEvent.getType()) { switch (webSocketCommunicationEvent.getType()) {
case "hello": case "hello":
Log.d(TAG, "onMessageEvent 'hello'");
if (!webSocketCommunicationEvent.getHashMap().containsKey("oldResumeId")) { if (!webSocketCommunicationEvent.getHashMap().containsKey("oldResumeId")) {
if (currentCallStatus.equals(CallStatus.RECONNECTING)) { if (currentCallStatus.equals(CallStatus.RECONNECTING)) {
hangup(false); hangup(false);
@ -1402,6 +1403,7 @@ public class CallActivity extends CallBaseActivity {
} }
break; break;
case "roomJoined": case "roomJoined":
Log.d(TAG, "onMessageEvent 'roomJoined'");
startSendingNick(); startSendingNick();
if (webSocketCommunicationEvent.getHashMap().get("roomToken").equals(roomToken)) { if (webSocketCommunicationEvent.getHashMap().get("roomToken").equals(roomToken)) {
@ -1409,6 +1411,7 @@ public class CallActivity extends CallBaseActivity {
} }
break; break;
case "participantsUpdate": case "participantsUpdate":
Log.d(TAG, "onMessageEvent 'participantsUpdate'");
if (webSocketCommunicationEvent.getHashMap().get("roomToken").equals(roomToken)) { if (webSocketCommunicationEvent.getHashMap().get("roomToken").equals(roomToken)) {
processUsersInRoom( processUsersInRoom(
(List<HashMap<String, Object>>) webSocketClient (List<HashMap<String, Object>>) webSocketClient
@ -1417,10 +1420,12 @@ public class CallActivity extends CallBaseActivity {
} }
break; break;
case "signalingMessage": case "signalingMessage":
Log.d(TAG, "onMessageEvent 'signalingMessage'");
processMessage((NCSignalingMessage) webSocketClient.getJobWithId( processMessage((NCSignalingMessage) webSocketClient.getJobWithId(
Integer.valueOf(webSocketCommunicationEvent.getHashMap().get("jobId")))); Integer.valueOf(webSocketCommunicationEvent.getHashMap().get("jobId"))));
break; break;
case "peerReadyForRequestingOffer": case "peerReadyForRequestingOffer":
Log.d(TAG, "onMessageEvent 'peerReadyForRequestingOffer'");
webSocketClient.requestOfferForSessionIdWithType( webSocketClient.requestOfferForSessionIdWithType(
webSocketCommunicationEvent.getHashMap().get("sessionId"), "video"); webSocketCommunicationEvent.getHashMap().get("sessionId"), "video");
break; break;
@ -1523,6 +1528,7 @@ public class CallActivity extends CallBaseActivity {
} }
private void hangup(boolean shutDownView) { private void hangup(boolean shutDownView) {
Log.d(TAG, "hangup! shutDownView=" + shutDownView);
stopCallingSound(); stopCallingSound();
dispose(null); dispose(null);
@ -1538,19 +1544,19 @@ public class CallActivity extends CallBaseActivity {
videoCapturer = null; videoCapturer = null;
} }
if (binding.selfVideoRenderer != null) {
binding.selfVideoRenderer.release(); binding.selfVideoRenderer.release();
}
if (audioSource != null) { if (audioSource != null) {
audioSource.dispose(); audioSource.dispose();
audioSource = null; audioSource = null;
} }
runOnUiThread(() -> {
if (audioManager != null) { if (audioManager != null) {
audioManager.stop(); audioManager.stop();
audioManager = null; audioManager = null;
} }
});
if (videoSource != null) { if (videoSource != null) {
videoSource = null; videoSource = null;
@ -1579,6 +1585,7 @@ public class CallActivity extends CallBaseActivity {
} }
private void hangupNetworkCalls(boolean shutDownView) { private void hangupNetworkCalls(boolean shutDownView) {
Log.d(TAG, "hangupNetworkCalls. shutDownView=" + shutDownView);
int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1}); int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken)) ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken))
@ -1618,33 +1625,39 @@ public class CallActivity extends CallBaseActivity {
} }
private void processUsersInRoom(List<HashMap<String, Object>> users) { private void processUsersInRoom(List<HashMap<String, Object>> users) {
Log.d(TAG, "processUsersInRoom");
List<String> newSessions = new ArrayList<>(); List<String> newSessions = new ArrayList<>();
Set<String> oldSessions = new HashSet<>(); Set<String> oldSessions = new HashSet<>();
hasMCU = hasExternalSignalingServer && webSocketClient != null && webSocketClient.hasMCU(); hasMCU = hasExternalSignalingServer && webSocketClient != null && webSocketClient.hasMCU();
Log.d(TAG, " hasMCU is " + hasMCU);
// The signaling session is the same as the Nextcloud session only when the MCU is not used. // The signaling session is the same as the Nextcloud session only when the MCU is not used.
String currentSessiondId = callSession; String currentSessionId = callSession;
if (hasMCU) { if (hasMCU) {
currentSessiondId = webSocketClient.getSessionId(); currentSessionId = webSocketClient.getSessionId();
} }
Log.d(TAG, " currentSessionId is " + currentSessionId);
for (HashMap<String, Object> participant : users) { for (HashMap<String, Object> participant : users) {
if (!participant.get("sessionId").equals(currentSessiondId)) { long inCallFlag = (long)participant.get("inCall");
Object inCallObject = participant.get("inCall"); if (!participant.get("sessionId").equals(currentSessionId)) {
boolean isNewSession; boolean isNewSession;
if (inCallObject instanceof Boolean) { Log.d(TAG, " inCallFlag of participant " + participant.get("sessionId").toString().substring(0,4) + " : " + inCallFlag);
isNewSession = (boolean) inCallObject; isNewSession = inCallFlag != 0;
} else {
isNewSession = ((long) inCallObject) != 0;
}
if (isNewSession) { if (isNewSession) {
newSessions.add(participant.get("sessionId").toString()); newSessions.add(participant.get("sessionId").toString());
} else { } else {
oldSessions.add(participant.get("sessionId").toString()); oldSessions.add(participant.get("sessionId").toString());
} }
} else {
Log.d(TAG, " inCallFlag of currentSessionId: " + inCallFlag);
if (inCallFlag == 0){
Log.d(TAG, "Most probably a moderator ended the call for all.");
hangup(true);
}
} }
} }
@ -1674,6 +1687,7 @@ public class CallActivity extends CallBaseActivity {
} }
for (String sessionId : newSessions) { for (String sessionId : newSessions) {
Log.d(TAG, " newSession joined: " + sessionId);
getPeerConnectionWrapperForSessionIdAndType(sessionId, "video", false); getPeerConnectionWrapperForSessionIdAndType(sessionId, "video", false);
} }
@ -1682,6 +1696,7 @@ public class CallActivity extends CallBaseActivity {
} }
for (String sessionId : oldSessions) { for (String sessionId : oldSessions) {
Log.d(TAG, " oldSession that will be removed is: " + sessionId);
endPeerConnection(sessionId, false); endPeerConnection(sessionId, false);
} }
} }
@ -1742,7 +1757,8 @@ public class CallActivity extends CallBaseActivity {
magicPeerConnectionWrapper = new MagicPeerConnectionWrapper(peerConnectionFactory, magicPeerConnectionWrapper = new MagicPeerConnectionWrapper(peerConnectionFactory,
iceServers, iceServers,
sdpConstraintsForMCU, sdpConstraintsForMCU,
sessionId, callSession, sessionId,
callSession,
localMediaStream, localMediaStream,
true, true,
true, true,

View File

@ -311,8 +311,7 @@ public class CallNotificationActivity extends CallBaseActivity {
} }
private boolean isInCallWithVideo(int callFlag) { private boolean isInCallWithVideo(int callFlag) {
return (Participant.ParticipantFlags.IN_CALL_WITH_VIDEO.getValue() == callFlag return (callFlag >= Participant.InCallFlags.IN_CALL + Participant.InCallFlags.WITH_VIDEO);
|| Participant.ParticipantFlags.IN_CALL_WITH_AUDIO_AND_VIDEO.getValue() == callFlag);
} }
private void setUpAfterConversationIsKnown() { private void setUpAfterConversationIsKnown() {

View File

@ -2298,12 +2298,16 @@ class ChatController(args: Bundle) :
} }
private fun startACall(isVoiceOnlyCall: Boolean) { private fun startACall(isVoiceOnlyCall: Boolean) {
if (currentConversation?.canStartCall == false && currentConversation?.hasCall == false) {
Toast.makeText(context, R.string.startCallForbidden, Toast.LENGTH_LONG).show()
} else {
ApplicationWideCurrentRoomHolder.getInstance().isDialing = true ApplicationWideCurrentRoomHolder.getInstance().isDialing = true
val callIntent = getIntentForCall(isVoiceOnlyCall) val callIntent = getIntentForCall(isVoiceOnlyCall)
if (callIntent != null) { if (callIntent != null) {
startActivity(callIntent) startActivity(callIntent)
} }
} }
}
private fun getIntentForCall(isVoiceOnlyCall: Boolean): Intent? { private fun getIntentForCall(isVoiceOnlyCall: Boolean): Intent? {
currentConversation?.let { currentConversation?.let {

View File

@ -621,6 +621,7 @@ public class ChatMessage implements MessageContentType, MessageContentType.Image
CALL_JOINED, CALL_JOINED,
CALL_LEFT, CALL_LEFT,
CALL_ENDED, CALL_ENDED,
CALL_ENDED_EVERYONE,
CALL_MISSED, CALL_MISSED,
CALL_TRIED, CALL_TRIED,
READ_ONLY_OFF, READ_ONLY_OFF,

View File

@ -92,8 +92,12 @@ public class Conversation {
public Long lobbyTimer; public Long lobbyTimer;
@JsonField(name = "lastReadMessage") @JsonField(name = "lastReadMessage")
public int lastReadMessage; public int lastReadMessage;
@JsonField(name = "hasCall")
public boolean hasCall;
@JsonField(name = "callFlag") @JsonField(name = "callFlag")
public int callFlag; public int callFlag;
@JsonField(name = "canStartCall")
public boolean canStartCall;
@JsonField(name = "canLeaveConversation") @JsonField(name = "canLeaveConversation")
public Boolean canLeaveConversation; public Boolean canLeaveConversation;
@ -259,10 +263,18 @@ public class Conversation {
return this.lastReadMessage; return this.lastReadMessage;
} }
public boolean getHasCall() {
return hasCall;
}
public int getCallFlag() { public int getCallFlag() {
return this.callFlag; return this.callFlag;
} }
public boolean getCanStartCall() {
return canStartCall;
}
public Boolean getUnreadMentionDirect() { public Boolean getUnreadMentionDirect() {
return unreadMentionDirect; return unreadMentionDirect;
} }
@ -370,10 +382,18 @@ public class Conversation {
this.lastReadMessage = lastReadMessage; this.lastReadMessage = lastReadMessage;
} }
public void setHasCall(boolean hasCall) {
this.hasCall = hasCall;
}
public void setCallFlag(int callFlag) { public void setCallFlag(int callFlag) {
this.callFlag = callFlag; this.callFlag = callFlag;
} }
public void setCanStartCall(boolean canStartCall) {
this.canStartCall = canStartCall;
}
public void setUnreadMentionDirect(Boolean unreadMentionDirect) { public void setUnreadMentionDirect(Boolean unreadMentionDirect) {
this.unreadMentionDirect = unreadMentionDirect; this.unreadMentionDirect = unreadMentionDirect;
} }
@ -411,9 +431,15 @@ public class Conversation {
if (lastReadMessage != that.lastReadMessage) { if (lastReadMessage != that.lastReadMessage) {
return false; return false;
} }
if (hasCall != that.hasCall) {
return false;
}
if (callFlag != that.callFlag) { if (callFlag != that.callFlag) {
return false; return false;
} }
if (canStartCall != that.canStartCall) {
return false;
}
if (!Objects.equals(roomId, that.roomId)) { if (!Objects.equals(roomId, that.roomId)) {
return false; return false;
} }
@ -508,7 +534,9 @@ public class Conversation {
result = 31 * result + (lobbyState != null ? lobbyState.hashCode() : 0); result = 31 * result + (lobbyState != null ? lobbyState.hashCode() : 0);
result = 31 * result + (lobbyTimer != null ? lobbyTimer.hashCode() : 0); result = 31 * result + (lobbyTimer != null ? lobbyTimer.hashCode() : 0);
result = 31 * result + lastReadMessage; result = 31 * result + lastReadMessage;
result = 31 * result + (hasCall ? 1 : 0);
result = 31 * result + callFlag; result = 31 * result + callFlag;
result = 31 * result + (canStartCall ? 1 : 0);
result = 31 * result + (canLeaveConversation != null ? canLeaveConversation.hashCode() : 0); result = 31 * result + (canLeaveConversation != null ? canLeaveConversation.hashCode() : 0);
result = 31 * result + (canDeleteConversation != null ? canDeleteConversation.hashCode() : 0); result = 31 * result + (canDeleteConversation != null ? canDeleteConversation.hashCode() : 0);
result = 31 * result + (notificationCalls != null ? notificationCalls.hashCode() : 0); result = 31 * result + (notificationCalls != null ? notificationCalls.hashCode() : 0);
@ -543,7 +571,9 @@ public class Conversation {
", lobbyState=" + lobbyState + ", lobbyState=" + lobbyState +
", lobbyTimer=" + lobbyTimer + ", lobbyTimer=" + lobbyTimer +
", lastReadMessage=" + lastReadMessage + ", lastReadMessage=" + lastReadMessage +
", hasCall=" + hasCall +
", callFlag=" + callFlag + ", callFlag=" + callFlag +
", canStartCall=" + canStartCall +
", canLeaveConversation=" + canLeaveConversation + ", canLeaveConversation=" + canLeaveConversation +
", canDeleteConversation=" + canDeleteConversation + ", canDeleteConversation=" + canDeleteConversation +
", notificationCalls=" + notificationCalls + ", notificationCalls=" + notificationCalls +

View File

@ -27,6 +27,7 @@ package com.nextcloud.talk.models.json.converters
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_ENDED import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_ENDED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_ENDED_EVERYONE
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_JOINED import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_JOINED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_LEFT import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_LEFT
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_MISSED import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_MISSED
@ -74,6 +75,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.USER_RE
* `call_joined` - {actor} joined the call * `call_joined` - {actor} joined the call
* `call_left` - {actor} left the call * `call_left` - {actor} left the call
* `call_ended` - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23) * `call_ended` - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23)
* `call_ended_everyone` - {user1} ended the call with {user2}, {user3}, {user4} and {user5} (Duration 30:23)
* `call_missed` - You missed a call from {user} * `call_missed` - You missed a call from {user}
* `call_tried` - You tried to call {user} * `call_tried` - You tried to call {user}
* `read_only_off` - {actor} unlocked the conversation * `read_only_off` - {actor} unlocked the conversation
@ -115,6 +117,7 @@ class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.Syst
"call_joined" -> return CALL_JOINED "call_joined" -> return CALL_JOINED
"call_left" -> return CALL_LEFT "call_left" -> return CALL_LEFT
"call_ended" -> return CALL_ENDED "call_ended" -> return CALL_ENDED
"call_ended_everyone" -> return CALL_ENDED_EVERYONE
"call_missed" -> return CALL_MISSED "call_missed" -> return CALL_MISSED
"call_tried" -> return CALL_TRIED "call_tried" -> return CALL_TRIED
"read_only_off" -> return READ_ONLY_OFF "read_only_off" -> return READ_ONLY_OFF
@ -163,6 +166,7 @@ class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.Syst
CALL_JOINED -> return "call_joined" CALL_JOINED -> return "call_joined"
CALL_LEFT -> return "call_left" CALL_LEFT -> return "call_left"
CALL_ENDED -> return "call_ended" CALL_ENDED -> return "call_ended"
CALL_ENDED_EVERYONE -> return "call_ended_everyone"
CALL_MISSED -> return "call_missed" CALL_MISSED -> return "call_missed"
CALL_TRIED -> return "call_tried" CALL_TRIED -> return "call_tried"
READ_ONLY_OFF -> return "read_only_off" READ_ONLY_OFF -> return "read_only_off"

View File

@ -82,23 +82,6 @@ public class Participant {
public boolean selected; public boolean selected;
public ParticipantFlags getParticipantFlags() {
ParticipantFlags participantFlags = ParticipantFlags.NOT_IN_CALL;
if (inCall != null) {
if (inCall instanceof Long) {
participantFlags = ParticipantFlags.fromValue((Long) inCall);
} else if (inCall instanceof Boolean) {
if ((boolean) inCall) {
participantFlags = ParticipantFlags.IN_CALL;
} else {
participantFlags = ParticipantFlags.NOT_IN_CALL;
}
}
}
return participantFlags;
}
public Long getAttendeeId() { public Long getAttendeeId() {
return attendeeId; return attendeeId;
} }
@ -346,40 +329,4 @@ public class Participant {
public static final int WITH_VIDEO = 4; public static final int WITH_VIDEO = 4;
public static final int WITH_PHONE = 8; public static final int WITH_PHONE = 8;
} }
@Deprecated
public enum ParticipantFlags {
NOT_IN_CALL(0),
IN_CALL(1),
IN_CALL_WITH_AUDIO(3),
IN_CALL_WITH_VIDEO(5),
IN_CALL_WITH_AUDIO_AND_VIDEO(7);
private long value;
ParticipantFlags(long value) {
this.value = value;
}
public static ParticipantFlags fromValue(long value) {
if (value == 0) {
return NOT_IN_CALL;
} else if (value == 1) {
return IN_CALL;
} else if (value == 3) {
return IN_CALL_WITH_AUDIO;
} else if (value == 5) {
return IN_CALL_WITH_VIDEO;
} else if (value == 7) {
return IN_CALL_WITH_AUDIO_AND_VIDEO;
} else {
return NOT_IN_CALL;
}
}
public long getValue() {
return value;
}
}
} }

View File

@ -23,6 +23,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/chat_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"

View File

@ -383,6 +383,7 @@
<string name="nc_reply_privately">Reply privately</string> <string name="nc_reply_privately">Reply privately</string>
<string name="nc_delete_message">Delete</string> <string name="nc_delete_message">Delete</string>
<string name="nc_delete_message_leaked_to_matterbridge">Message deleted successfully, but it might have been leaked to other services</string> <string name="nc_delete_message_leaked_to_matterbridge">Message deleted successfully, but it might have been leaked to other services</string>
<string name="startCallForbidden">You are not allowed to start a call</string>
<string name="share">Share</string> <string name="share">Share</string>
<string name="send_to">Send to</string> <string name="send_to">Send to</string>