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 f584b7140..fdd9b4923 100644
--- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java
+++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java
@@ -1843,6 +1843,14 @@ public class CallActivity extends CallBaseActivity {
for (String sessionId : newSessions) {
Log.d(TAG, " newSession joined: " + sessionId);
getOrCreatePeerConnectionWrapperForSessionIdAndType(sessionId, VIDEO_STREAM_TYPE_VIDEO, false);
+
+ runOnUiThread(() -> {
+ setupVideoStreamForLayout(
+ null,
+ sessionId,
+ false,
+ VIDEO_STREAM_TYPE_VIDEO);
+ });
}
if (newSessions.size() > 0 && !currentCallStatus.equals(CallStatus.IN_CONVERSATION)) {
@@ -2019,6 +2027,17 @@ public class CallActivity extends CallBaseActivity {
updateSelfVideoViewPosition();
}
+ private void updateSelfVideoViewConnected(boolean connected) {
+ // FIXME In voice only calls there is no video view, so the progress bar would appear floating in the middle of
+ // nowhere. However, a way to signal that the local participant is not connected to the HPB is still need in
+ // that case.
+ if (!connected && !isVoiceOnlyCall) {
+ binding.selfVideoViewProgressBar.setVisibility(View.VISIBLE);
+ } else {
+ binding.selfVideoViewProgressBar.setVisibility(View.GONE);
+ }
+ }
+
private void updateSelfVideoViewPosition() {
Log.d(TAG, "updateSelfVideoViewPosition");
if (!isInPipMode) {
@@ -2061,6 +2080,22 @@ public class CallActivity extends CallBaseActivity {
String sessionId = peerConnectionEvent.getSessionId();
if (peerConnectionEvent.getPeerConnectionEventType() ==
+ PeerConnectionEvent.PeerConnectionEventType.PEER_CONNECTED) {
+ if (webSocketClient != null && webSocketClient.getSessionId() == sessionId) {
+ updateSelfVideoViewConnected(true);
+ } else if (participantDisplayItems.get(sessionId) != null) {
+ participantDisplayItems.get(sessionId).setConnected(true);
+ participantsAdapter.notifyDataSetChanged();
+ }
+ } else if (peerConnectionEvent.getPeerConnectionEventType() ==
+ PeerConnectionEvent.PeerConnectionEventType.PEER_DISCONNECTED) {
+ if (webSocketClient != null && webSocketClient.getSessionId() == sessionId) {
+ updateSelfVideoViewConnected(false);
+ } else if (participantDisplayItems.get(sessionId) != null) {
+ participantDisplayItems.get(sessionId).setConnected(false);
+ participantsAdapter.notifyDataSetChanged();
+ }
+ } else if (peerConnectionEvent.getPeerConnectionEventType() ==
PeerConnectionEvent.PeerConnectionEventType.PEER_CLOSED) {
endPeerConnection(sessionId, VIDEO_STREAM_TYPE_SCREEN.equals(peerConnectionEvent.getVideoStreamType()));
} else if (peerConnectionEvent.getPeerConnectionEventType() ==
@@ -2081,23 +2116,20 @@ public class CallActivity extends CallBaseActivity {
PeerConnectionEvent.PeerConnectionEventType.NICK_CHANGE) {
if (participantDisplayItems.get(sessionId) != null) {
participantDisplayItems.get(sessionId).setNick(peerConnectionEvent.getNick());
+ participantsAdapter.notifyDataSetChanged();
}
- participantsAdapter.notifyDataSetChanged();
-
} else if (peerConnectionEvent.getPeerConnectionEventType() ==
PeerConnectionEvent.PeerConnectionEventType.VIDEO_CHANGE && !isVoiceOnlyCall) {
if (participantDisplayItems.get(sessionId) != null) {
participantDisplayItems.get(sessionId).setStreamEnabled(peerConnectionEvent.getChangeValue());
+ participantsAdapter.notifyDataSetChanged();
}
- participantsAdapter.notifyDataSetChanged();
-
} else if (peerConnectionEvent.getPeerConnectionEventType() ==
PeerConnectionEvent.PeerConnectionEventType.AUDIO_CHANGE) {
if (participantDisplayItems.get(sessionId) != null) {
participantDisplayItems.get(sessionId).setAudioEnabled(peerConnectionEvent.getChangeValue());
+ participantsAdapter.notifyDataSetChanged();
}
- participantsAdapter.notifyDataSetChanged();
-
} else if (peerConnectionEvent.getPeerConnectionEventType() ==
PeerConnectionEvent.PeerConnectionEventType.PUBLISHER_FAILED) {
currentCallStatus = CallStatus.PUBLISHER_FAILED;
@@ -2253,12 +2285,20 @@ public class CallActivity extends CallBaseActivity {
String session,
boolean videoStreamEnabled,
String videoStreamType) {
+ PeerConnectionWrapper peerConnectionWrapper = getPeerConnectionWrapperForSessionIdAndType(session,
+ videoStreamType);
+
+ boolean connected = false;
+ if (peerConnectionWrapper != null) {
+ PeerConnection.IceConnectionState iceConnectionState = peerConnectionWrapper.getPeerConnection().iceConnectionState();
+ connected = iceConnectionState == PeerConnection.IceConnectionState.CONNECTED ||
+ iceConnectionState == PeerConnection.IceConnectionState.COMPLETED;
+ }
+
String nick;
if (hasExternalSignalingServer) {
nick = webSocketClient.getDisplayNameForSession(session);
} else {
- PeerConnectionWrapper peerConnectionWrapper = getPeerConnectionWrapperForSessionIdAndType(session,
- videoStreamType);
nick = peerConnectionWrapper != null ? peerConnectionWrapper.getNick() : "";
}
@@ -2282,6 +2322,7 @@ public class CallActivity extends CallBaseActivity {
ParticipantDisplayItem participantDisplayItem = new ParticipantDisplayItem(userId,
session,
+ connected,
nick,
urlForAvatar,
mediaStream,
diff --git a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java
index aefb742d8..adc75a338 100644
--- a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java
+++ b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java
@@ -6,6 +6,7 @@ import org.webrtc.MediaStream;
public class ParticipantDisplayItem {
private String userId;
private String session;
+ private boolean connected;
private String nick;
private String urlForAvatar;
private MediaStream mediaStream;
@@ -14,9 +15,10 @@ public class ParticipantDisplayItem {
private EglBase rootEglBase;
private boolean isAudioEnabled;
- public ParticipantDisplayItem(String userId, String session, String nick, String urlForAvatar, MediaStream mediaStream, String streamType, boolean streamEnabled, EglBase rootEglBase) {
+ public ParticipantDisplayItem(String userId, String session, boolean connected, String nick, String urlForAvatar, MediaStream mediaStream, String streamType, boolean streamEnabled, EglBase rootEglBase) {
this.userId = userId;
this.session = session;
+ this.connected = connected;
this.nick = nick;
this.urlForAvatar = urlForAvatar;
this.mediaStream = mediaStream;
@@ -41,6 +43,14 @@ public class ParticipantDisplayItem {
this.session = session;
}
+ public boolean isConnected() {
+ return connected;
+ }
+
+ public void setConnected(boolean connected) {
+ this.connected = connected;
+ }
+
public String getNick() {
return nick;
}
diff --git a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java
index 20b708ff1..bd09717d6 100644
--- a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java
+++ b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java
@@ -8,6 +8,7 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -96,6 +97,13 @@ public class ParticipantsAdapter extends BaseAdapter {
surfaceViewRenderer = convertView.findViewById(R.id.surface_view);
}
+ ProgressBar progressBar = convertView.findViewById(R.id.participant_progress_bar);
+ if (!participantDisplayItem.isConnected()) {
+ progressBar.setVisibility(View.VISIBLE);
+ } else {
+ progressBar.setVisibility(View.GONE);
+ }
+
ViewGroup.LayoutParams layoutParams = convertView.getLayoutParams();
layoutParams.height = scaleGridViewItemHeight();
convertView.setLayoutParams(layoutParams);
diff --git a/app/src/main/java/com/nextcloud/talk/events/PeerConnectionEvent.java b/app/src/main/java/com/nextcloud/talk/events/PeerConnectionEvent.java
index 4e48929f7..c6722732e 100644
--- a/app/src/main/java/com/nextcloud/talk/events/PeerConnectionEvent.java
+++ b/app/src/main/java/com/nextcloud/talk/events/PeerConnectionEvent.java
@@ -120,6 +120,6 @@ public class PeerConnectionEvent {
}
public enum PeerConnectionEventType {
- PEER_CONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE, PUBLISHER_FAILED
+ PEER_CONNECTED, PEER_DISCONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE, PUBLISHER_FAILED
}
}
diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java b/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java
index 07a8f4df2..64e7c0ddf 100644
--- a/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java
+++ b/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java
@@ -344,6 +344,8 @@ public class PeerConnectionWrapper {
Log.d("iceConnectionChangeTo: ", iceConnectionState.name() + " over " + peerConnection.hashCode() + " " + sessionId);
if (iceConnectionState.equals(PeerConnection.IceConnectionState.CONNECTED)) {
+ EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.PEER_CONNECTED,
+ sessionId, null, null, null));
if (!isMCUPublisher) {
EventBus.getDefault().post(new MediaStreamEvent(remoteStream, sessionId, videoStreamType));
@@ -352,11 +354,20 @@ public class PeerConnectionWrapper {
if (hasInitiated) {
sendInitialMediaStatus();
}
-
+ } else if (iceConnectionState.equals(PeerConnection.IceConnectionState.COMPLETED)) {
+ EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.PEER_CONNECTED,
+ sessionId, null, null, null));
} else if (iceConnectionState.equals(PeerConnection.IceConnectionState.CLOSED)) {
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.PEER_CLOSED, sessionId, null, null, videoStreamType));
+ } else if (iceConnectionState.equals(PeerConnection.IceConnectionState.DISCONNECTED) ||
+ iceConnectionState.equals(PeerConnection.IceConnectionState.NEW) ||
+ iceConnectionState.equals(PeerConnection.IceConnectionState.CHECKING)) {
+ EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.PEER_DISCONNECTED,
+ sessionId, null, null, null));
} else if (iceConnectionState.equals(PeerConnection.IceConnectionState.FAILED)) {
+ EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.PEER_DISCONNECTED,
+ sessionId, null, null, null));
if (isMCUPublisher) {
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.PUBLISHER_FAILED, sessionId, null, null, null));
}
diff --git a/app/src/main/res/layout/call_activity.xml b/app/src/main/res/layout/call_activity.xml
index 2b43482a3..e7dc38665 100644
--- a/app/src/main/res/layout/call_activity.xml
+++ b/app/src/main/res/layout/call_activity.xml
@@ -77,6 +77,14 @@
android:layout_marginBottom="20dp"
app:placeholderImage="@drawable/ic_switch_video_white_24px"
app:roundAsCircle="true" />
+
+
+
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index ec96955c0..444cd0df9 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -67,6 +67,8 @@
80dp
180dp
110dp
+ 48dp
+ 48dp
0dp
52dp