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 abff92925..1fd0d2c99 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -740,6 +740,10 @@ public class CallActivity extends CallBaseActivity { } }); + if (participantsAdapter != null) { + participantsAdapter.destroy(); + } + participantsAdapter = new ParticipantsAdapter( this, participantDisplayItems, @@ -1853,17 +1857,11 @@ public class CallActivity extends CallBaseActivity { String userId = userIdsBySessionId.get(sessionId); if (userId != null) { runOnUiThread(() -> { - boolean notifyDataSetChanged = false; if (participantDisplayItems.get(sessionId + "-video") != null) { participantDisplayItems.get(sessionId + "-video").setUserId(userId); - notifyDataSetChanged = true; } if (participantDisplayItems.get(sessionId + "-screen") != null) { participantDisplayItems.get(sessionId + "-screen").setUserId(userId); - notifyDataSetChanged = true; - } - if (notifyDataSetChanged) { - participantsAdapter.notifyDataSetChanged(); } }); } @@ -2527,17 +2525,11 @@ public class CallActivity extends CallBaseActivity { private void onOfferOrAnswer(String nick) { this.nick = nick; - boolean notifyDataSetChanged = false; if (participantDisplayItems.get(sessionId + "-video") != null) { participantDisplayItems.get(sessionId + "-video").setNick(nick); - notifyDataSetChanged = true; } if (participantDisplayItems.get(sessionId + "-screen") != null) { participantDisplayItems.get(sessionId + "-screen").setNick(nick); - notifyDataSetChanged = true; - } - if (notifyDataSetChanged) { - participantsAdapter.notifyDataSetChanged(); } } @@ -2582,7 +2574,6 @@ public class CallActivity extends CallBaseActivity { runOnUiThread(() -> { if (participantDisplayItems.get(participantDisplayItemId) != null) { participantDisplayItems.get(participantDisplayItemId).setAudioEnabled(true); - participantsAdapter.notifyDataSetChanged(); } }); } @@ -2592,7 +2583,6 @@ public class CallActivity extends CallBaseActivity { runOnUiThread(() -> { if (participantDisplayItems.get(participantDisplayItemId) != null) { participantDisplayItems.get(participantDisplayItemId).setAudioEnabled(false); - participantsAdapter.notifyDataSetChanged(); } }); } @@ -2602,7 +2592,6 @@ public class CallActivity extends CallBaseActivity { runOnUiThread(() -> { if (participantDisplayItems.get(participantDisplayItemId) != null) { participantDisplayItems.get(participantDisplayItemId).setStreamEnabled(true); - participantsAdapter.notifyDataSetChanged(); } }); } @@ -2612,7 +2601,6 @@ public class CallActivity extends CallBaseActivity { runOnUiThread(() -> { if (participantDisplayItems.get(participantDisplayItemId) != null) { participantDisplayItems.get(participantDisplayItemId).setStreamEnabled(false); - participantsAdapter.notifyDataSetChanged(); } }); } @@ -2622,7 +2610,6 @@ public class CallActivity extends CallBaseActivity { runOnUiThread(() -> { if (participantDisplayItems.get(participantDisplayItemId) != null) { participantDisplayItems.get(participantDisplayItemId).setNick(nick); - participantsAdapter.notifyDataSetChanged(); } }); } @@ -2664,7 +2651,6 @@ public class CallActivity extends CallBaseActivity { ParticipantDisplayItem participantDisplayItem = participantDisplayItems.get(participantDisplayItemId); participantDisplayItem.setMediaStream(mediaStream); participantDisplayItem.setStreamEnabled(hasAtLeastOneVideoStream); - participantsAdapter.notifyDataSetChanged(); }); } @@ -2675,7 +2661,6 @@ public class CallActivity extends CallBaseActivity { updateSelfVideoViewIceConnectionState(iceConnectionState); } else if (participantDisplayItems.get(participantDisplayItemId) != null) { participantDisplayItems.get(participantDisplayItemId).setIceConnectionState(iceConnectionState); - participantsAdapter.notifyDataSetChanged(); } if (iceConnectionState == PeerConnection.IceConnectionState.CLOSED) { 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 1ababf417..746f21710 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java @@ -9,6 +9,13 @@ import org.webrtc.MediaStream; import org.webrtc.PeerConnection; public class ParticipantDisplayItem { + + public interface Observer { + void onChange(); + } + + private final ParticipantDisplayItemNotifier participantDisplayItemNotifier = new ParticipantDisplayItemNotifier(); + private final String baseUrl; private final String defaultGuestNick; private final EglBase rootEglBase; @@ -43,6 +50,8 @@ public class ParticipantDisplayItem { this.userId = userId; this.updateUrlForAvatar(); + + participantDisplayItemNotifier.notifyChange(); } public boolean isConnected() { @@ -52,6 +61,8 @@ public class ParticipantDisplayItem { public void setIceConnectionState(PeerConnection.IceConnectionState iceConnectionState) { this.iceConnectionState = iceConnectionState; + + participantDisplayItemNotifier.notifyChange(); } public String getNick() { @@ -66,6 +77,8 @@ public class ParticipantDisplayItem { this.nick = nick; this.updateUrlForAvatar(); + + participantDisplayItemNotifier.notifyChange(); } public String getUrlForAvatar() { @@ -86,6 +99,8 @@ public class ParticipantDisplayItem { public void setMediaStream(MediaStream mediaStream) { this.mediaStream = mediaStream; + + participantDisplayItemNotifier.notifyChange(); } public boolean isStreamEnabled() { @@ -94,6 +109,8 @@ public class ParticipantDisplayItem { public void setStreamEnabled(boolean streamEnabled) { this.streamEnabled = streamEnabled; + + participantDisplayItemNotifier.notifyChange(); } public EglBase getRootEglBase() { @@ -106,6 +123,16 @@ public class ParticipantDisplayItem { public void setAudioEnabled(boolean audioEnabled) { isAudioEnabled = audioEnabled; + + participantDisplayItemNotifier.notifyChange(); + } + + public void addObserver(Observer observer) { + participantDisplayItemNotifier.addObserver(observer); + } + + public void removeObserver(Observer observer) { + participantDisplayItemNotifier.removeObserver(observer); } @Override diff --git a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItemNotifier.java b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItemNotifier.java new file mode 100644 index 000000000..239b9f85b --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItemNotifier.java @@ -0,0 +1,55 @@ +/* + * Nextcloud Talk application + * + * @author Daniel Calviño Sánchez + * Copyright (C) 2022 Daniel Calviño Sánchez + * + * 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 . + */ +package com.nextcloud.talk.adapters; + +import com.nextcloud.talk.signaling.SignalingMessageReceiver; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * Helper class to register and notify ParticipantDisplayItem.Observers. + * + * This class is only meant for internal use by ParticipantDisplayItem; observers must register themselves against a + * ParticipantDisplayItem rather than against a ParticipantDisplayItemNotifier. + */ +class ParticipantDisplayItemNotifier { + + private final Set participantDisplayItemObservers = new LinkedHashSet<>(); + + public synchronized void addObserver(ParticipantDisplayItem.Observer observer) { + if (observer == null) { + throw new IllegalArgumentException("ParticipantDisplayItem.Observer can not be null"); + } + + participantDisplayItemObservers.add(observer); + } + + public synchronized void removeObserver(ParticipantDisplayItem.Observer observer) { + participantDisplayItemObservers.remove(observer); + } + + public synchronized void notifyChange() { + for (ParticipantDisplayItem.Observer observer : new ArrayList<>(participantDisplayItemObservers)) { + observer.onChange(); + } + } +} 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 b8b5cc60b..85e24d50d 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/ParticipantsAdapter.java @@ -29,6 +29,8 @@ public class ParticipantsAdapter extends BaseAdapter { private static final String TAG = "ParticipantsAdapter"; + private final ParticipantDisplayItem.Observer participantDisplayItemObserver = this::notifyDataSetChanged; + private final Context mContext; private final ArrayList participantDisplayItems; private final RelativeLayout gridViewWrapper; @@ -50,8 +52,17 @@ public class ParticipantsAdapter extends BaseAdapter { this.participantDisplayItems = new ArrayList<>(); this.participantDisplayItems.addAll(participantDisplayItems.values()); + + for (ParticipantDisplayItem participantDisplayItem : this.participantDisplayItems) { + participantDisplayItem.addObserver(participantDisplayItemObserver); + } } + public void destroy() { + for (ParticipantDisplayItem participantDisplayItem : participantDisplayItems) { + participantDisplayItem.removeObserver(participantDisplayItemObserver); + } + } @Override public int getCount() {