From 6502926dfe40c746380699f74ab68e9b15485f56 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Fri, 10 Apr 2020 21:49:05 +0300 Subject: [PATCH 01/21] -initial BVideo Conference supppot --- app/build.gradle | 5 +- .../data/auth/AppSignatureHelper.java | 4 +- .../{calls => conference}/ActiveCallBase.java | 10 +- .../conference/ConferenceVideoModule.java | 64 ++ .../data/sdk/ConferenceSDKPresenter.java | 2 +- .../data/sdk/calls/ActiveConferenceCall.java | 63 +- .../data/sdk/calls/ConferenceCallData.java | 148 +++++ .../data/sdk/calls/ConferenceListItem.java | 13 +- .../data/sdk/calls/ConferenceSDKListener.java | 2 +- .../data/sdk/calls/ConferenceSDKModule.java | 156 +++-- .../mvp/presenters/BasePresenter.java | 2 +- .../mvp/presenters/CallActivityPresenter.java | 36 +- .../presenters/CallTapToSpeakPresenter.java | 2 +- .../presenters/ConferenceCallPresenter.java | 67 ++- .../presenters/ConferenceVideoPresenter.java | 197 ++++++ .../mvp/view/CallActivityView.java | 8 + .../mvp/view/CallTapToSpeakView.java | 2 +- .../communicator/mvp/view/CallView.java | 2 +- .../mvp/view/ConferenceVideoView.java | 35 ++ .../ui/activities/MainActivity.java | 6 +- .../ui/activities/calls/CallActivity.java | 159 +++-- .../ActiveCallPagerAdapter.java | 141 ++++- .../ConferenceParticipantsAdapter.java | 4 +- .../conference/ConferenceVideoAdapter.java | 64 ++ .../{ => conference}/ConferenceContactVh.java | 2 +- .../conference/ConferenceVideoItemVh.java | 169 ++++++ .../communicator/ui/base/BaseAdapter.java | 8 + .../mobile/communicator/ui/base/BaseVH.java | 1 + .../conference/CallTapToSpeakFragment.java | 2 +- .../conference/ConferenceCallFragment.java | 75 ++- .../conference/ConferenceVideoFragment.java | 563 ++++++++++++++++++ .../conference/ScreenShareFragment.kt | 14 +- .../ui/views/CirclePageIndicator.java | 4 + .../views/CirclePagerIndicatorDecoration.java | 118 ++++ app/src/main/res/layout/activity_rv_call.xml | 14 + .../layout/fragment_conference_video_call.xml | 13 + .../main/res/layout/li_conference_video.xml | 94 +++ app/src/main/res/values/dimen.xml | 5 + 38 files changed, 2022 insertions(+), 252 deletions(-) rename app/src/main/java/com/nynja/mobile/communicator/data/{calls => conference}/ActiveCallBase.java (81%) create mode 100644 app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java create mode 100644 app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java create mode 100644 app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java create mode 100644 app/src/main/java/com/nynja/mobile/communicator/mvp/view/ConferenceVideoView.java rename app/src/main/java/com/nynja/mobile/communicator/ui/adapters/{ => conference}/ActiveCallPagerAdapter.java (60%) rename app/src/main/java/com/nynja/mobile/communicator/ui/adapters/{ => conference}/ConferenceParticipantsAdapter.java (94%) create mode 100644 app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java rename app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/{ => conference}/ConferenceContactVh.java (98%) create mode 100644 app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java create mode 100644 app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java create mode 100644 app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java create mode 100644 app/src/main/res/layout/activity_rv_call.xml create mode 100644 app/src/main/res/layout/fragment_conference_video_call.xml create mode 100644 app/src/main/res/layout/li_conference_video.xml diff --git a/app/build.gradle b/app/build.gradle index f5c3052a9c..5c0c5d2627 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -617,6 +617,7 @@ dependencies { //RecyclerView header implementation 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar' + implementation 'com.android.support:recyclerview-v7:23.28.0.0' //navigation implementation 'ru.terrakok.cicerone:cicerone:3.0.0' @@ -661,8 +662,8 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" // Conference, Calls mobile SDK - implementation 'com.nynja.sdk:NynjaSdk:1.20.3@aar' - //implementation(name: 'NynjaSdk-1.20.2', ext: 'aar') + //implementation 'com.nynja.sdk:NynjaSdk:1.20.3@aar' + implementation(name: 'NynjaSdk-1.20.4', ext: 'aar') //ExoPlayer implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6' diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/auth/AppSignatureHelper.java b/app/src/main/java/com/nynja/mobile/communicator/data/auth/AppSignatureHelper.java index ee914486f0..412c56cc4d 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/auth/AppSignatureHelper.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/auth/AppSignatureHelper.java @@ -66,10 +66,10 @@ public class AppSignatureHelper extends ContextWrapper { String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP); base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR); - Timber.v("sms_sample_test pkg: %s -- hash: %s", packageName, base64Hash); + Timber.v("Nynja pkg: %s -- hash: %s", packageName, base64Hash); return base64Hash; } catch (NoSuchAlgorithmException e) { - Timber.v("sms_sample_test hash:NoSuchAlgorithm"); + Timber.v("Nynja hash:NoSuchAlgorithm"); } return null; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/calls/ActiveCallBase.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ActiveCallBase.java similarity index 81% rename from app/src/main/java/com/nynja/mobile/communicator/data/calls/ActiveCallBase.java rename to app/src/main/java/com/nynja/mobile/communicator/data/conference/ActiveCallBase.java index ed56871a44..fce484df70 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/calls/ActiveCallBase.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ActiveCallBase.java @@ -1,4 +1,4 @@ -package com.nynja.mobile.communicator.data.calls; +package com.nynja.mobile.communicator.data.conference; import com.nynja.mobile.communicator.utils.StringUtils; @@ -27,15 +27,12 @@ public abstract class ActiveCallBase { public boolean isSpeakerOn; public AudioRouteType mAudioRouteType; public boolean isCallInProgress; - public boolean isOwnStreamActive; public boolean isRinging; public boolean isSwitchToAudio; public boolean isVideoEnabled; public boolean isVideoFullScreen; public boolean isScreenShareEnabled; public long mCallStartTime; // in miliseconds - public boolean hasRemoteVideoTrack; - public boolean hasRemoteScreenShareTrack; public boolean mIsAdHock; public ActiveCallBase(String endPointId, CallType callType, boolean videoEnabled, boolean outgoingCall) { @@ -43,10 +40,8 @@ public abstract class ActiveCallBase { mCallType = callType; mEndPointId = (endPointId == null) ? "" : endPointId; mCallStartTime = -1; - isVideoEnabled = (callType == CallType.P2PCall); + isVideoEnabled = true;//(callType == CallType.P2PCall); isVideoFullScreen = false; - hasRemoteVideoTrack = false; - isOwnStreamActive = videoEnabled; isOutgoingCall = outgoingCall; isMuted = false; isSpeakerOn = false; @@ -54,7 +49,6 @@ public abstract class ActiveCallBase { isRinging = false; isCallInProgress = false; isSwitchToAudio = false; - hasRemoteScreenShareTrack = false; isScreenShareEnabled = true; mIsAdHock = (isOutgoingCall && (callType == CallType.ConferenceCall) && diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java new file mode 100644 index 0000000000..c76b139604 --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -0,0 +1,64 @@ +package com.nynja.mobile.communicator.data.conference; + +import com.nynja.mobile.communicator.NynjaApp; +import com.nynja.mobile.communicator.data.DataManager; +import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; + +import org.webrtc.SurfaceViewRenderer; + +public class ConferenceVideoModule { + + private static ConferenceVideoModule mInstance = null; + + private DataManager mDataManager; + // Call worker object + private ActiveConferenceCall mCurrentActiveCall; + + + private ConferenceVideoModule() { + init(); + } + + public static ConferenceVideoModule getInstance() { + if (mInstance == null) { + mInstance = new ConferenceVideoModule(); + } + return mInstance; + } + + private void init() { + // ToDo:... + mCurrentActiveCall = null; + mDataManager = NynjaApp.getComponent().dataManager(); + } + + public void reset() { + // ToDo:... + mCurrentActiveCall = null; + } + + public void setCurrentActiveCall(ActiveConferenceCall currentActiveCall) { + if (mCurrentActiveCall != currentActiveCall) { + mCurrentActiveCall = currentActiveCall; + } + } + + public void setVideoRendererForTrack(SurfaceViewRenderer videoFeed, String trackId, boolean isLocal) { + if (mCurrentActiveCall != null) { + if (isLocal) { + mCurrentActiveCall.mConference.setLocalVideoRenderer(videoFeed); + } else { + mCurrentActiveCall.mConference.setRemoteVideoRenderer(videoFeed, trackId); + } + } + } + + public String getTrackIdByParticipantId(String participantId) { + String trackId = ""; + if (mCurrentActiveCall != null) { + trackId = mCurrentActiveCall.mData.getTrackIdForParticipant(participantId); + } + return trackId; + } + +} diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java index 0ad28d0afd..b0c8c38c6f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java @@ -1,6 +1,6 @@ package com.nynja.mobile.communicator.data.sdk; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceSDKListener; import com.nynja.mobile.communicator.data.sdk.calls.RejoinConferenceCallData; diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java index 7908377f41..4b0d379b94 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java @@ -1,16 +1,14 @@ package com.nynja.mobile.communicator.data.sdk.calls; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; import com.nynja.mobile.communicator.utils.Consts; import com.nynja.mobile.communicator.utils.StringUtils; import com.nynja.sdk.NYNCall; import com.nynja.sdk.NYNCallParticipant; -import com.nynja.sdk.NYNCallParticipantArray; import com.nynja.sdk.NYNCallRoomType; import java.util.ArrayList; -import java.util.HashMap; /** * Created by Ergyun Syuleyman on 4/19/18. @@ -20,39 +18,29 @@ public class ActiveConferenceCall extends ActiveCallBase { private ArrayList mMembers; public NYNCall mConference; - public NYNCallParticipantArray mParticipantArray; public String mMyDisplayName; - public String mMyPhoneId; public boolean mIsSpeakerForceStopped; public boolean mPartial; - public int mParticipantsCountLimit; public boolean mInitialStartCapturer; - public String mRemoteSSTrackId; - public String mRemoteVideoTrackId; public boolean mWaiting; public boolean mAutoCreateAndStart; - public HashMap mActiveTracks; + public ConferenceCallData mData; - public static final int CONFERENCE_PARTICIPANTS_COUNT_LIMIT = 1000; public static final int ANDROID_10_PUSH_CALL_NTFN_ID = 1234567890; public ActiveConferenceCall(NYNCall conference, String endPointId, CallType callType, boolean isVideoEnabled, boolean outgoingCall) { super(endPointId, callType, isVideoEnabled, outgoingCall); + mData = new ConferenceCallData((callType == CallType.P2PCall), isVideoEnabled); mConference = conference; mMembers = new ArrayList(); mMyDisplayName = ""; - mMyPhoneId = ""; mIsSpeakerForceStopped = false; mPartial = false; - mParticipantsCountLimit = CONFERENCE_PARTICIPANTS_COUNT_LIMIT; // default limit - if cannot get from sdk mInitialStartCapturer = isVideoEnabled; - mRemoteSSTrackId = ""; - mRemoteVideoTrackId = ""; mWaiting = false; mAutoCreateAndStart = false; - mActiveTracks = new HashMap<>(); } public void setMembers(ArrayList members) { @@ -99,7 +87,7 @@ public class ActiveConferenceCall extends ActiveCallBase { public boolean isCameraRunning() { return (mConference != null - && isOwnStreamActive + && mData.isOwnStreamActive && isCallInProgress() && mConference.isCameraRunning()); } @@ -123,10 +111,10 @@ public class ActiveConferenceCall extends ActiveCallBase { public boolean isParticipateInConference(String memberId) { if (memberId == null) return false; - if (mParticipantArray == null) return false; + if (mData.mParticipantArray == null) return false; - for (int index = 0; index < mParticipantArray.size(); index++) { - NYNCallParticipant participant = mParticipantArray.get(index); + for (int index = 0; index < mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = mData.mParticipantArray.get(index); if (participant.getMemberId().contentEquals(memberId)) { return true; } @@ -141,7 +129,8 @@ public class ActiveConferenceCall extends ActiveCallBase { } public boolean isConference() { - return (mConference != null && mConference.isConference()); + return (mConference != null && + (mConference.isConference() || mCallType == CallType.ConferenceCall)); } public String getConferenceRoomId() { @@ -157,24 +146,7 @@ public class ActiveConferenceCall extends ActiveCallBase { return null; } - public String getConferenceModeratorName() { - if (mParticipantArray != null) { - for (int index = 0; index < mParticipantArray.size(); index++) { - NYNCallParticipant participant = mParticipantArray.get(index); - if (participant.isOwner()) { - return participant.getName(); - } - } - } - return ""; - - } - public String getConferenceSSOwner() { - String participanId = ""; - if (mActiveTracks.containsKey(mRemoteSSTrackId)) { - participanId = mActiveTracks.get(mRemoteSSTrackId); - } boolean isP2P = (mConference != null && !mConference.isConference()); if (isP2P) { if (mConference.isOutgoing()) { @@ -183,17 +155,8 @@ public class ActiveConferenceCall extends ActiveCallBase { return mConference.caller(); } } else { - if (mParticipantArray != null ) { - for (int index = 0; index < mParticipantArray.size(); index++) { - NYNCallParticipant participant = mParticipantArray.get(index); - if (participanId.contentEquals(participant.getParticipantId())) { - return participant.getName(); - } - } - } + return mData.getConferenceSSOwner(); } - - return getConferenceModeratorName(); } @@ -221,9 +184,9 @@ public class ActiveConferenceCall extends ActiveCallBase { ", isSpeakerOn=" + isSpeakerOn + ", mAudioRouteType=" + mAudioRouteType.toString() + ", mConference=" + mConference + - ", isOwnStreamActive=" + isOwnStreamActive + - ", hasRemoteVideoTrack=" + hasRemoteVideoTrack + - ", hasRemoteScreenShareTrack=" + hasRemoteScreenShareTrack + + ", isOwnStreamActive=" + mData.isOwnStreamActive + + ", hasRemoteVideoTrack=" + mData.hasRemoteVideoTrack + + ", hasRemoteScreenShareTrack=" + mData.hasRemoteScreenShareTrack + ", isVideoEnabled=" + isVideoEnabled + ", isCallInProgress=" + isCallInProgress + ", isRinging=" + isRinging + diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java new file mode 100644 index 0000000000..8f40428288 --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java @@ -0,0 +1,148 @@ +package com.nynja.mobile.communicator.data.sdk.calls; + +import com.nynja.mobile.communicator.utils.StringUtils; +import com.nynja.sdk.NYNCallParticipant; +import com.nynja.sdk.NYNCallParticipantArray; + +import java.util.HashMap; + +/** + * Created by Ergyun Syuleyman on 04/03/2020. + */ + +public class ConferenceCallData { + + public static final int CONFERENCE_PARTICIPANTS_COUNT_LIMIT = 1000; + + public NYNCallParticipantArray mParticipantArray; + public int mParticipantsCountLimit; + public String mRemoteSSTrackId; + public String mRemoteVideoTrackId; + public HashMap mActiveTracks; + public HashMap mActiveParticipanTracks; + public HashMap mActiveParticipanSSTracks; + public boolean hasRemoteVideoTrack; + public boolean hasRemoteScreenShareTrack; + public boolean mIsConference; + public boolean isOwnStreamActive; + + public ConferenceCallData() { + init(); + mIsConference = false; + } + + public ConferenceCallData(boolean isConference, boolean videoEnabled) { + init(); + mIsConference = isConference; + isOwnStreamActive = videoEnabled; + } + + private void init() { + mParticipantsCountLimit = CONFERENCE_PARTICIPANTS_COUNT_LIMIT; // default limit - if cannot get from sdk + mRemoteSSTrackId = ""; + mRemoteVideoTrackId = ""; + mActiveTracks = new HashMap<>(); + mActiveParticipanTracks = new HashMap<>(); + mActiveParticipanSSTracks = new HashMap<>(); + hasRemoteVideoTrack = false; + hasRemoteScreenShareTrack = false; + } + + public void onRemoteVideoAdded(String trackId, String participantId) { + hasRemoteVideoTrack = true; + mActiveTracks.put(trackId, participantId); + mActiveParticipanTracks.put(participantId, trackId); + mRemoteVideoTrackId = trackId; + } + + public void onRemoteVideoRemoved(String trackId, String participantId) { + mActiveTracks.remove(trackId); + mActiveParticipanTracks.remove(participantId); + hasRemoteVideoTrack = !isRemoteVideoTracksEmpty(); + mRemoteVideoTrackId = ""; + } + + public void onRemoteSSAdded(String trackId, String participantId) { + hasRemoteScreenShareTrack = true; + mActiveTracks.put(trackId, participantId); + mActiveParticipanSSTracks.put(participantId, trackId); + mRemoteSSTrackId = trackId; + } + + public void onRemoteSSRemoved(String trackId, String participantId) { + hasRemoteScreenShareTrack = false; + mActiveTracks.remove(trackId); + mActiveParticipanSSTracks.remove(participantId); + mRemoteSSTrackId = ""; + } + + public String getParticipantIdForTrack(String trackId) { + if (StringUtils.isEmpty(trackId)) return ""; + if (mActiveTracks.containsKey(trackId)) { + return mActiveTracks.get(trackId); + } + + return ""; + } + + public String getTrackIdForParticipant(String participantId) { + return getTrackIdForParticipant(participantId, true); + } + + public String getScreenTrackIdForParticipant(String participantId) { + return getTrackIdForParticipant(participantId, false); + } + + protected String getTrackIdForParticipant(String participantId, boolean isVideo) { + if (StringUtils.isEmpty(participantId)) return ""; + if (isVideo) { + if (mActiveParticipanTracks.containsKey(participantId)) { + return mActiveParticipanTracks.get(participantId); + } + } else { + if (mActiveParticipanSSTracks.containsKey(participantId)) { + return mActiveParticipanSSTracks.get(participantId); + } + } + + return ""; + } + + public String getConferenceSSOwner() { + if (mParticipantArray != null ) { + String participanId = getParticipantIdForTrack(mRemoteSSTrackId); + if (StringUtils.isEmpty(participanId)) return ""; + for (int index = 0; index < mParticipantArray.size(); index++) { + NYNCallParticipant participant = mParticipantArray.get(index); + if (participanId.contentEquals(participant.getParticipantId())) { + return participant.getName(); + } + } + } + + return getConferenceModeratorName(); + } + + public String getConferenceModeratorName() { + if (mParticipantArray != null) { + for (int index = 0; index < mParticipantArray.size(); index++) { + NYNCallParticipant participant = mParticipantArray.get(index); + if (participant.isOwner()) { + return participant.getName(); + } + } + } + + return ""; + } + + public boolean isRemoteVideoTracksEmpty() { + return !(mActiveParticipanTracks.size() > 0 && + mActiveTracks.size() > 0); + } + + public boolean hasRemoteVideoTrack() { + return (hasRemoteVideoTrack && + !isRemoteVideoTracksEmpty()); + } +} diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java index 980d2a4e94..3abe899349 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java @@ -75,7 +75,9 @@ public class ConferenceListItem { this.isScreenPaused = false; } - protected ConferenceListItem(ConferenceItemType type, NYNCallParticipant participant, boolean isFriend) { + protected ConferenceListItem(ConferenceItemType type, NYNCallParticipant participant, + boolean isFriend, + boolean isOwnStreamActive) { this.type = type; this.phoneId = participant.getAddress(); this.memberId = participant.getMemberId(); @@ -87,7 +89,7 @@ public class ConferenceListItem { this.isMuted = participant.isMuted(); this.isFriend = isFriend; this.memberActions = new ArrayList<>(); - this.hasVideo = participant.hasVideo(); + this.hasVideo = (participant.hasVideo() || (isMe && isOwnStreamActive)); this.hasScreen = participant.hasScreen(); this.isVideoPaused = participant.isVideoPaused(); this.isScreenPaused = participant.isScreenPaused(); @@ -246,10 +248,11 @@ public class ConferenceListItem { return item; } - public static ConferenceListItem fromSdkParticipant(NYNCallParticipant participant, boolean isFriend) { + public static ConferenceListItem fromSdkParticipant(NYNCallParticipant participant, + boolean isFriend, + boolean isOwnStreamActive) { ConferenceListItem item = new ConferenceListItem( - ConferenceItemType.Participant, - participant, isFriend); + ConferenceItemType.Participant, participant, isFriend, isOwnStreamActive); return item; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java index 2bcf3622ee..01de83d3bb 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java @@ -1,6 +1,6 @@ package com.nynja.mobile.communicator.data.sdk.calls; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.sdk.NYNCall; import com.nynja.sdk.NYNCallHistoryCode; diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index d7ae416bb5..86c004c53a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -1,7 +1,6 @@ package com.nynja.mobile.communicator.data.sdk.calls; import android.Manifest; -import android.app.Notification; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; @@ -26,9 +25,9 @@ import com.nynja.mobile.communicator.NynjaApp; import com.nynja.mobile.communicator.R; import com.nynja.mobile.communicator.data.ProfileSyncManager; import com.nynja.mobile.communicator.data.audio.NynjaSoundManager; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.db.DbHelper; -import com.nynja.mobile.communicator.data.db.PreferenceHelper; import com.nynja.mobile.communicator.data.models.SettingNotifications; import com.nynja.mobile.communicator.data.models.StateDevice; import com.nynja.mobile.communicator.data.models.mqtt.Conference; @@ -37,7 +36,6 @@ import com.nynja.mobile.communicator.data.models.nynjamodels.MemberModel; import com.nynja.mobile.communicator.data.sdk.BaseSDKModule; import com.nynja.mobile.communicator.ui.activities.MainActivity; import com.nynja.mobile.communicator.utils.Consts; -import com.nynja.mobile.communicator.utils.DialogFactory; import com.nynja.mobile.communicator.utils.MobileSDKConstants; import com.nynja.mobile.communicator.utils.NotificationHelper; import com.nynja.mobile.communicator.utils.StringUtils; @@ -657,6 +655,7 @@ public class ConferenceSDKModule extends BaseSDKModule { //addCallHistoryListener(); //////////////////////////////////////////////////////////////////////////////////////////////////////// mConferenceAudioManager = AppRTCAudioManager.create(getContext()); + //ConferenceVideoModule.getInstance(); try { mCallsLooper = Looper.myLooper(); @@ -755,7 +754,7 @@ public class ConferenceSDKModule extends BaseSDKModule { && StringUtils.isNotEmpty(chatRoomId)) { mActiveConference.mEndPointId = chatRoomId; } - if (mHandler != null) mHandler.post( () -> { + runOnUIThread( () -> { onConferenceParticipantsUpdated(callId); }); } @@ -802,12 +801,7 @@ public class ConferenceSDKModule extends BaseSDKModule { Timber.d("onRemoteVideoTrackAdded(): callId=" + call.callId() + "; trackId=" + trackId + "; participantId=" + participantId + "; isConference=" + (isConference ? "true" : "false")); - if (isConference) { - mActiveConference.hasRemoteVideoTrack = true; - onRemoteScreenShareAdded(call.callId(), trackId, participantId); - } else { - onRemoteVideoAdded(call.callId(), trackId, participantId, isConference); - } + onRemoteVideoAdded(call.callId(), trackId, participantId, isConference); } } @@ -818,12 +812,7 @@ public class ConferenceSDKModule extends BaseSDKModule { Timber.d("onRemoteVideoTrackRemoved(): callId=" + call.callId() + "; trackId=" + trackId + "; participantId=" + participantId + "; isConference=" + (isConference ? "true" : "false")); - if (isConference) { - onRemoteScreenShareRemoved(call.callId(), trackId, participantId); - mActiveConference.hasRemoteVideoTrack = false; - } else { - onRemoteVideoRemoved(call.callId(), trackId, participantId, isConference); - } + onRemoteVideoRemoved(call.callId(), trackId, participantId, isConference); } } @@ -900,7 +889,7 @@ public class ConferenceSDKModule extends BaseSDKModule { NYNCall conference = mCallManager.getCallById(conferenceId); if (conference != null) { mConferenceDetails.mActiveConference.mConference = conference; - mConferenceDetails.mActiveConference.mParticipantsCountLimit = conference.getParticipantsCountLimit(); + mConferenceDetails.mActiveConference.mData.mParticipantsCountLimit = conference.getParticipantsCountLimit(); onGetConferenceRoomLimitsFinished(null, mConferenceDetails.mActiveConference.mEndPointId, conference.getParticipantsCountLimit()); addConferenceCallListener(mConferenceDetails.mActiveConference.mConference); @@ -1027,7 +1016,7 @@ public class ConferenceSDKModule extends BaseSDKModule { mActiveConference.mConference = mCallManager.getCallById(mConferenceDetails.mCallId); if (mActiveConference.mConference != null) { // todo: for limits use the new logic - local hashMap - mActiveConference.mParticipantsCountLimit = mActiveConference.mConference.getParticipantsCountLimit(); + mActiveConference.mData.mParticipantsCountLimit = mActiveConference.mConference.getParticipantsCountLimit(); addConferenceCallListener(mActiveConference.mConference); onCallReady(conferenceId, mActiveConference.isVideoEnabled, true); } @@ -1072,11 +1061,11 @@ public class ConferenceSDKModule extends BaseSDKModule { if (!hasCreatedActiveCall()) return; Timber.d("Request conference member with \'ConferenceId\'=\'" + conferenceId + "\' " + (result ? "succeed" : "failed!!!")); - mActiveConference.mParticipantArray = mActiveConference.mConference.getParticipants(); + mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); // update chatRoomId - if (mActiveConference.mParticipantArray != null && - mActiveConference.mParticipantArray.size() > 0 && + if (mActiveConference.mData.mParticipantArray != null && + mActiveConference.mData.mParticipantArray.size() > 0 && StringUtils.isEmpty(mActiveConference.mEndPointId)) { mActiveConference.mEndPointId = mActiveConference.mConference.getChatRoomId(); } @@ -1563,7 +1552,7 @@ public class ConferenceSDKModule extends BaseSDKModule { initConferenceCall(false); new Handler(Looper.getMainLooper()).postDelayed(() -> { mActiveConference.isCallInProgress = true; - mActiveConference.mParticipantArray = mActiveConference.mConference.getParticipants(); + mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); startConferenceActivityImpl(NynjaNavigator.MAIN_NEW_CALL, true); }, Consts.DELAY_100); } @@ -1597,61 +1586,96 @@ public class ConferenceSDKModule extends BaseSDKModule { private void onRemoteScreenShareAdded(String callId, String trackId, String participantId) { if (!hasCreatedActiveCall()) return; - mActiveConference.mActiveTracks.put(trackId, participantId); + mActiveConference.mData.onRemoteSSAdded(trackId, participantId); if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { - mActiveConference.mRemoteSSTrackId = trackId; - mActiveConference.hasRemoteScreenShareTrack = true; for (ConferenceSDKListener conferenceListener : mConferenceSDKListener) { conferenceListener.onRemoteScreenShareTrackAdded(mActiveConference, trackId); } } +// mActiveConference.mData.mActiveTracks.put(trackId, participantId); +// if (mActiveConference.mConference == null) return; +// if (mActiveConference.mConference.callId().contentEquals(callId)) { +// mActiveConference.mData.mRemoteSSTrackId = trackId; +// mActiveConference.mData.hasRemoteScreenShareTrack = true; +// for (ConferenceSDKListener conferenceListener : mConferenceSDKListener) { +// conferenceListener.onRemoteScreenShareTrackAdded(mActiveConference, trackId); +// } +// } } private void onRemoteScreenShareRemoved(String callId, String trackId, String participantId) { if (!hasCreatedActiveCall()) return; - mActiveConference.mActiveTracks.remove(trackId); + mActiveConference.mData.onRemoteSSRemoved(trackId, participantId); if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { - mActiveConference.hasRemoteScreenShareTrack = false; for (ConferenceSDKListener conferenceListener : mConferenceSDKListener) { conferenceListener.onRemoteScreenShareTrackRemoved(mActiveConference, trackId); } - mActiveConference.mRemoteSSTrackId = ""; } +// mActiveConference.mData.mActiveTracks.remove(trackId); +// if (mActiveConference.mConference == null) return; +// if (mActiveConference.mConference.callId().contentEquals(callId)) { +// mActiveConference.mData.hasRemoteScreenShareTrack = false; +// for (ConferenceSDKListener conferenceListener : mConferenceSDKListener) { +// conferenceListener.onRemoteScreenShareTrackRemoved(mActiveConference, trackId); +// } +// mActiveConference.mData.mRemoteSSTrackId = ""; +// } } private void onRemoteVideoAdded(String callId, String trackId, String participantId, boolean isConference) { if (!hasCreatedActiveCall()) return; - mActiveConference.mActiveTracks.put(trackId, participantId); + mActiveConference.mData.onRemoteVideoAdded(trackId, participantId); if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { - mActiveConference.mRemoteVideoTrackId = trackId; - mActiveConference.hasRemoteVideoTrack = true; for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { conferenceSDKListener.onRemoteVideoTrackAdded(mActiveConference, trackId); } } +// if (isConference) { +// mActiveConference.mData.hasRemoteVideoTrack = true; +// onRemoteScreenShareAdded(callId, trackId, participantId); +// } else { +// mActiveConference.mData.mActiveTracks.put(trackId, participantId); +// if (mActiveConference.mConference == null) return; +// if (mActiveConference.mConference.callId().contentEquals(callId)) { +// mActiveConference.mData.mRemoteVideoTrackId = trackId; +// mActiveConference.mData.hasRemoteVideoTrack = true; +// } +// } } private void onRemoteVideoRemoved(String callId, String trackId, String participantId, boolean isConference) { if (!hasCreatedActiveCall()) return; - mActiveConference.mActiveTracks.remove(trackId); + mActiveConference.mData.onRemoteVideoRemoved(trackId, participantId); if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { - mActiveConference.hasRemoteVideoTrack = false; for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { conferenceSDKListener.onRemoteVideoTrackRemoved(mActiveConference, trackId); } - mActiveConference.mRemoteVideoTrackId = ""; } +// if (isConference) { +// onRemoteScreenShareRemoved(callId, trackId, participantId); +// mActiveConference.mData.hasRemoteVideoTrack = false; +// } else { +// mActiveConference.mData.mActiveTracks.remove(trackId); +// if (mActiveConference.mConference == null) return; +// if (mActiveConference.mConference.callId().contentEquals(callId)) { +// mActiveConference.mData.hasRemoteVideoTrack = false; +// for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { +// conferenceSDKListener.onRemoteVideoTrackRemoved(mActiveConference, trackId); +// } +// mActiveConference.mData.mRemoteVideoTrackId = ""; +// } +// } } private void onLocalVideoStarted(String callId) { if (!hasCreatedActiveCall()) return; if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { - mActiveConference.isOwnStreamActive = true; + mActiveConference.mData.isOwnStreamActive = true; for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { conferenceSDKListener.onLocalVideoCapturerStarted(mActiveConference); } @@ -1662,7 +1686,12 @@ public class ConferenceSDKModule extends BaseSDKModule { if (!hasCreatedActiveCall()) return; if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { - mActiveConference.isOwnStreamActive = false; + mActiveConference.mData.isOwnStreamActive = false; + if (mActiveConference.isConference()) { + new Handler(Looper.getMainLooper()).post(() -> { + mActiveConference.mConference.setLocalVideoRenderer(null); + }); + } for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { conferenceSDKListener.onLocalVideoCapturerStopped(mActiveConference); } @@ -2078,13 +2107,10 @@ public class ConferenceSDKModule extends BaseSDKModule { mConferenceDetails = new ConferenceDetails(getDeviceId()); mActiveConference = createActiveConference(null, contact.phoneId, true, isVideoEnabled, ActiveCallBase.CallType.P2PCall); - mActiveConference.isOwnStreamActive = isVideoEnabled; + mActiveConference.mData.isOwnStreamActive = isVideoEnabled; mActiveConference.addMember(contact); setConferenceCallName(mActiveConference, contact.getFullName()); AppsTrackerUtils.getCleverTapInstance().trackEvent(getContext(), AppsTrackerConsts.ATEventMakeP2PCall); - if (StringUtils.isNotEmpty(phoneId)) { - mActiveConference.mMyPhoneId = phoneId; - } startConferenceActivityImpl(NynjaNavigator.ACTIVE_CALL); } } @@ -2558,10 +2584,10 @@ public class ConferenceSDKModule extends BaseSDKModule { private void updateConferenceNameIfNeeds() { if (mConferenceDetails != null && mConferenceDetails.mMembersCounter < 0) { if (mActiveConference == null) return; - if (mActiveConference.mParticipantArray == null) return; - if (mActiveConference.mParticipantArray.size() > 0 && TEMP_ALLOW_UPDATE_CONF_CALLS_NAME) { + if (mActiveConference.mData.mParticipantArray == null) return; + if (mActiveConference.mData.mParticipantArray.size() > 0 && TEMP_ALLOW_UPDATE_CONF_CALLS_NAME) { tryUpdateConferenceCallName(mActiveConference, - generateGroupConferenceName(mActiveConference.mParticipantArray.size() - 1)); + generateGroupConferenceName(mActiveConference.mData.mParticipantArray.size() - 1)); } } @@ -2584,7 +2610,7 @@ public class ConferenceSDKModule extends BaseSDKModule { } if (mActiveConference.mConference != null) { // todo: for limits use the new logic - local hashMap - mActiveConference.mParticipantsCountLimit = mActiveConference.mConference.getParticipantsCountLimit(); + mActiveConference.mData.mParticipantsCountLimit = mActiveConference.mConference.getParticipantsCountLimit(); addConferenceCallListener(mActiveConference.mConference); } } @@ -2809,7 +2835,7 @@ public class ConferenceSDKModule extends BaseSDKModule { mConferenceDetails = new ConferenceDetails(getDeviceId(), iConference.callId()); mActiveConference = createActiveConference(iConference); if (!hasCreatedActiveCall()) return false; - mActiveConference.isOwnStreamActive = false; + mActiveConference.mData.isOwnStreamActive = false; initConferenceCall(startActivity); if (startActivity) { if (Consts.SHOW_INCOMING_CALLS_AS_POPUP_NOTIFICATIONS) { @@ -2883,8 +2909,8 @@ public class ConferenceSDKModule extends BaseSDKModule { if (mConferenceDetails.mCallId != null && mConferenceDetails.mCallId.contentEquals(conferenceId)) { // @TODO: request update server side conference name ..... - for (int index = 0; index < mActiveConference.mParticipantArray.size(); index++) { - NYNCallParticipant participant = mActiveConference.mParticipantArray.get(index); + for (int index = 0; index < mActiveConference.mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = mActiveConference.mData.mParticipantArray.get(index); if (!participant.getMemberId().contentEquals(memberId)) { continue; } @@ -2894,10 +2920,10 @@ public class ConferenceSDKModule extends BaseSDKModule { break; } } - if (mActiveConference.mParticipantArray.size() > 1 && TEMP_ALLOW_UPDATE_CONF_CALLS_NAME) { - mActiveConference.mParticipantArray.remove(index); + if (mActiveConference.mData.mParticipantArray.size() > 1 && TEMP_ALLOW_UPDATE_CONF_CALLS_NAME) { + mActiveConference.mData.mParticipantArray.remove(index); tryUpdateConferenceCallName(mActiveConference, - generateGroupConferenceName(mActiveConference.mParticipantArray.size() - 1));// exclude me + generateGroupConferenceName(mActiveConference.mData.mParticipantArray.size() - 1));// exclude me } break; } @@ -3015,7 +3041,7 @@ public class ConferenceSDKModule extends BaseSDKModule { return; } if (!mActiveConference.isOutgoingCall) { - mActiveConference.isVideoEnabled = videoEnabled; + //mActiveConference.isVideoEnabled = videoEnabled; } mActiveConference.isCallInProgress = true; mActiveConference.isRinging = false; @@ -3154,6 +3180,11 @@ public class ConferenceSDKModule extends BaseSDKModule { if (!activeConferenceCall.mConference.isCameraRunning()) return; activeConferenceCall.mConference.stopCamera(); + if (mActiveConference.isConference()) { + new Handler(Looper.getMainLooper()).post(() -> { + mActiveConference.mConference.setLocalVideoRenderer(null); + }); + } } public boolean hasRemoteScreenShare() { @@ -3161,7 +3192,7 @@ public class ConferenceSDKModule extends BaseSDKModule { if (mActiveConference.mConference == null) return false; return (mActiveConference.mConference.hasRemoteScreenShare() - || !mActiveConference.mActiveTracks.isEmpty()); + || !mActiveConference.mData.mActiveTracks.isEmpty()); } public boolean isScreenSharing() { @@ -3263,13 +3294,13 @@ public class ConferenceSDKModule extends BaseSDKModule { } public int getActiveConferenceParticipantsLimit() { - if (!hasCreatedActiveCall()) return ActiveConferenceCall.CONFERENCE_PARTICIPANTS_COUNT_LIMIT; + if (!hasCreatedActiveCall()) return ConferenceCallData.CONFERENCE_PARTICIPANTS_COUNT_LIMIT; if (mActiveConference.mConference != null && mActiveConference.mCallType == ActiveCallBase.CallType.P2PCall && mConferenceDetails != null && mConferenceDetails.mActiveConference != null) { - return mConferenceDetails.mActiveConference.mParticipantsCountLimit; + return mConferenceDetails.mActiveConference.mData.mParticipantsCountLimit; } - return mActiveConference.mParticipantsCountLimit; + return mActiveConference.mData.mParticipantsCountLimit; } private void playConnecting() { @@ -3393,7 +3424,7 @@ public class ConferenceSDKModule extends BaseSDKModule { replaceCallEx(subject, deleteGroupIfNoMessages, deleteAfterCall, isVideoConference, mActiveConference.mConference.callId(), - contacts); + contacts, mActiveConference.mData.isOwnStreamActive); } else { createAndStartConferenceEx(subject, chatRoomId, deleteGroupIfNoMessages, deleteAfterCall, isVideoConference, contacts); @@ -3428,7 +3459,7 @@ public class ConferenceSDKModule extends BaseSDKModule { if (limits >= 0) return limits; // set the default value - limits = ActiveConferenceCall.CONFERENCE_PARTICIPANTS_COUNT_LIMIT; + limits = ConferenceCallData.CONFERENCE_PARTICIPANTS_COUNT_LIMIT; mConferenceRoomLimits.put(defRoomId, limits); return limits; @@ -3479,7 +3510,8 @@ public class ConferenceSDKModule extends BaseSDKModule { boolean deleteAfterCall, boolean isVideoConference, String replaceRef, - ArrayList contacts) { + ArrayList contacts, + boolean isVideo) { if (StringUtils.isEmpty(replaceRef)) return; if (!(hasCreatedActiveCall() && isP2P())) return; @@ -3492,7 +3524,8 @@ public class ConferenceSDKModule extends BaseSDKModule { subject, !deleteGroupIfNoMessages, deleteAfterCall ? DELETE_CONFERENCE_CALL_AFTER_END : DELETE_CONFERENCE_CALL_AFTER_1_DAY, - members ); + members, + isVideoConference || isVideo); AppsTrackerUtils.getCleverTapInstance().trackEvent(getContext(), AppsTrackerConsts.ATEventMakeGroupCall); }); } @@ -3517,7 +3550,8 @@ public class ConferenceSDKModule extends BaseSDKModule { !deleteGroupIfNoMessages, deleteAfterCall ? DELETE_CONFERENCE_CALL_AFTER_END : DELETE_CONFERENCE_CALL_AFTER_1_DAY, "", - members ); + members, + isVideoConference); AppsTrackerUtils.getCleverTapInstance().trackEvent(getContext(), AppsTrackerConsts.ATEventMakeGroupCall); }); diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BasePresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BasePresenter.java index b7a5129ff4..fd01699566 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BasePresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BasePresenter.java @@ -9,7 +9,7 @@ import com.nynja.mobile.communicator.data.DataManager; import com.nynja.mobile.communicator.data.FragmentTransferObject; import com.nynja.mobile.communicator.data.GooglePlacesService; import com.nynja.mobile.communicator.data.NynjaKeyboardManager; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.models.events.ServerData; import com.nynja.mobile.communicator.data.models.events.ServerMessage; import com.nynja.mobile.communicator.data.models.events.local.AccountAuthFailedEvent; diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java index 6ed9d0569a..5f18704316 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java @@ -1,14 +1,12 @@ package com.nynja.mobile.communicator.mvp.presenters; import com.arellomobile.mvp.InjectViewState; -import com.nynja.mobile.communicator.NynjaApp; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.models.events.local.Event; import com.nynja.mobile.communicator.data.models.events.local.SimpleEvent; import com.nynja.mobile.communicator.data.sdk.ConferenceSDKPresenter; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.mvp.view.CallActivityView; -import com.nynja.mobile.communicator.utils.navigation.navigators.NynjaNavigator; /** * Created by Ergyun Syuleyman on 7/19/19. @@ -36,6 +34,37 @@ public class CallActivityPresenter extends ConferenceSDKPresenter } public void switchCamera() { + if (getAttachedViews().size() == 0) return; ActiveConferenceCall activeConferenceCall = mDataManager.getConferenceSDK(). getActiveConference(); if (activeConferenceCall != null && activeConferenceCall.mConference != null) { @@ -91,6 +92,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void showProfile(ConferenceListItem item) { + if (getAttachedViews().size() == 0) return; getViewState().closenConference(); if (!item.isMe) { ContactModel contact = mDataManager.getContactByChatId(item.phoneId); @@ -184,6 +186,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void goToHome() { + if (getAttachedViews().size() == 0) return; getViewState().closenConference(); openHome(); } @@ -191,6 +194,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter public void openChatWithParticipant(String participantPhoneId) { ContactModel contactByChatId = mDataManager.getContactByChatId(participantPhoneId); if (contactByChatId != null) { + if (getAttachedViews().size() == 0) return; getViewState().closenConference(); RoomModel room = new RoomModel(contactByChatId); FragmentTransferObject fto = new FragmentTransferObject(room, null); @@ -199,6 +203,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void navigateToChatRoom(RoomModel room) { + if (getAttachedViews().size() == 0) return; if (mDataManager.isMainActivityIsActive()) { getViewState().closenConference(); FragmentTransferObject fto = null; @@ -213,6 +218,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void loadUser(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; ContactModel user = mDataManager.getContactByChatId(activeConferenceCall.mEndPointId); getViewState().setUser(user); if (user == null) { @@ -225,6 +231,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void onLeaveCall() { + if (getAttachedViews().size() == 0) return; if (isConferenceActive()) { if (isP2PCall()) { getViewState().showLeaveCallConfirmation(); @@ -244,6 +251,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter @Override public void timeAway(boolean videoEnabled, String time) { + if (getAttachedViews().size() == 0) return; getViewState().conferenceTimeUpdated(videoEnabled, time); } @@ -254,17 +262,19 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter @Override public void conferenceEnded() { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; getViewState().onConferenceEnded(); } @Override public void onConferenceRinging() { + if (getAttachedViews().size() == 0) return; getViewState().onConferenceRinging(); } @Override public void onConferenceConnected(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; if (!activeConferenceCall.mConference.isConference()) { String personId = activeConferenceCall.isOutgoingCall ? activeConferenceCall.mEndPointId : activeConferenceCall.mConference.caller(); @@ -276,32 +286,34 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter @Override public void onConferenceFailed(String reason) { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; getViewState().onConferenceFailed(reason); } @Override public void onConferenceJoinFailed(String reason) { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; getViewState().onConferenceJoinFailed(reason); } @Override public void onCallFailed(String reason) { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; getViewState().onCallFailed(reason); } @Override public void onConferenceStateChanged(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; getViewState().onConferenceStateChanged(activeConferenceCall); } protected ConferenceListItem conferenceParticipant(NYNCallParticipant participant, - boolean isModerator) { + boolean isModerator, + boolean isOwnStreamActive) { ContactModel user = mDataManager.getContactsByPhoneId(participant.getAddress()); - ConferenceListItem conferenceListItem = ConferenceListItem.fromSdkParticipant(participant, (user != null)); + ConferenceListItem conferenceListItem = ConferenceListItem.fromSdkParticipant(participant, (user != null), isOwnStreamActive); if (user != null) { conferenceListItem.avatar = user.avatar; } @@ -312,12 +324,13 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter @Override public void onConferenceMembersUpdate(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; if (activeConferenceCall == null) return; ArrayList members = new ArrayList<>(); - if (activeConferenceCall.mParticipantArray != null) { - for (int index = 0; index < activeConferenceCall.mParticipantArray.size(); index++) { - NYNCallParticipant participant = activeConferenceCall.mParticipantArray.get(index); - members.add(conferenceParticipant(participant, participant.isOwner())); + if (activeConferenceCall.mData.mParticipantArray != null) { + for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); + members.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); } } else { for (int index = 0; index < activeConferenceCall.getMembers().size(); index++) { @@ -334,66 +347,79 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter @Override public void onCreateVideoCallReady(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; getViewState().onCreateVideoCallReady(activeConferenceCall); } @Override public void onScreenShareState(boolean active) { + if (getAttachedViews().size() == 0) return; getViewState().onScreenShareStateChanged(active && isScreenSharing()); } @Override public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { + if (getAttachedViews().size() == 0) return; + if (activeConferenceCall == null) return; + if (activeConferenceCall.isConference()) return; getViewState().onRemoteVideoTrackAdded(activeConferenceCall, trackId); } @Override public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) { + if (getAttachedViews().size() == 0) return; + if (activeConferenceCall == null) return; + if (activeConferenceCall.isConference()) return; getViewState().onRemoteVideoTrackRemoved(activeConferenceCall, trackId); } @Override public void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; getViewState().onLocalVideoCapturerStarted(activeConferenceCall); } @Override public void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; getViewState().onLocalVideoCapturerStopped(activeConferenceCall); } @Override public void onMicrophoneStateChanged(boolean isMuted) { + if (getAttachedViews().size() == 0) return; getViewState().onMicrophoneStateChanged(isMuted); } @Override public void onSpeakerStateChanged(boolean isSpeakerOn) { + if (getAttachedViews().size() == 0) return; getViewState().onSpeakerStateChanged(isSpeakerOn); } @Override public void onAudioRouteChange(ActiveCallBase.AudioRouteType audioRouteType) { + if (getAttachedViews().size() == 0) return; getViewState().onAudioRouteChange(audioRouteType); } @Override public void tryCallCameraStateChange(boolean pause) { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; getViewState().tryCallCameraStateChange(pause); } @Override public void onActiveSpeakersUpdate(String activeSpeakers) { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; getViewState().onActiveSpeakersUpdate(activeSpeakers); } @Override public void onMuteStateChangedByHost(boolean isMuted) { - if (getViewState() == null) return; + if (getAttachedViews().size() == 0) return; int stringResId = isMuted ? R.string.call_mute_by_host : R.string.call_unmute_by_host; getViewState().showInfoBanner(stringResId); getViewState().updateMicrophonState(isMuted); @@ -412,6 +438,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void onClickScreenShare(boolean isShareOn) { + if (getAttachedViews().size() == 0) return; ActiveConferenceCall call = mDataManager.getConferenceSDK().getActiveConference(); if (call != null && !call.isModerator() && !mDataManager.getConferenceSDK().isP2P()) { if (!isScreenSharing() && hasRemoteScreenShare()) { @@ -439,10 +466,10 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter @Nullable private ArrayList getConferenceParticipants() { if (mDataManager.getConferenceSDK(). - getActiveConference().mParticipantArray != null) { + getActiveConference().mData.mParticipantArray != null) { ArrayList currentContacts = new ArrayList<>(); long count = mDataManager.getConferenceSDK(). - getActiveConference().mParticipantArray.size(); + getActiveConference().mData.mParticipantArray.size(); String roomId = mDataManager.getConferenceSDK().getConferenceRoomId(); RoomModel room = mDataManager.getRoomById(roomId); List membersList = new ArrayList<>(); @@ -452,7 +479,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter for (int index = 0; index < count; index++) { NYNCallParticipant participant = mDataManager.getConferenceSDK(). - getActiveConference().mParticipantArray.get(index); + getActiveConference().mData.mParticipantArray.get(index); if (!participant.isMe()) { String memberAddress = participant.getAddress(); if (memberAddress == null) continue; @@ -515,7 +542,9 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } if (type != null) { - getViewState().closenConference(); + if (getAttachedViews().size() > 0) { + getViewState().closenConference(); + } FragmentTransferObject fto = new FragmentTransferObject(currentContacts, room, type); mRouter.backOrNavigateTo(HomeNavigator.CHOOSE_USER, fto); } @@ -562,6 +591,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void showInviteDialog() { + if (getAttachedViews().size() == 0) return; if (mDataManager.getConferenceSDK().isConferenceModerator()) { int addParticipantStringResId = isCallCreatedFromHome() ? R.string.contacts_contacts : R.string.group_participants; getViewState().showInviteOptionsModerator(addParticipantStringResId); @@ -575,6 +605,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } public void copyLinkToClipboard() { + if (getAttachedViews().size() == 0) return; getViewState().showCopyLinkMessage(); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java new file mode 100644 index 0000000000..e52fdbcbe5 --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -0,0 +1,197 @@ +package com.nynja.mobile.communicator.mvp.presenters; + +import com.arellomobile.mvp.InjectViewState; +import com.nynja.mobile.communicator.data.FragmentTransferObject; +import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; +import com.nynja.mobile.communicator.data.models.nynjamodels.RoomModel; +import com.nynja.mobile.communicator.data.sdk.ConferenceSDKPresenter; +import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceSDKListener; +import com.nynja.mobile.communicator.mvp.view.ConferenceVideoView; +import com.nynja.sdk.NYNCallParticipant; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + +@InjectViewState +public class ConferenceVideoPresenter extends ConferenceSDKPresenter + implements ConferenceSDKListener { + private String mParticipantPhoneId; + + @Override + protected void onFirstViewAttach() { + super.onFirstViewAttach(); + ActiveConferenceCall activeConferenceCall = mDataManager.getConferenceSDK(). + getActiveConference(); + if (activeConferenceCall != null) { + getViewState().initConferenceStates(activeConferenceCall); + if (activeConferenceCall.isRinging) onConferenceRinging(); + } + } + + public void removeFromCall(ConferenceListItem item) { + if (item != null) { + mDataManager.getConferenceSDK().removeParticipant(item.memberId, item.participantId); + } + } + + public void muteParticipant(ConferenceListItem item) { + if (!item.isMe) { + mDataManager.getConferenceSDK().muteParticipant(item.participantId); + } else { + mDataManager.getConferenceSDK().mute(); + } + } + + public void unMuteParticipant(String participantId) { + mDataManager.getConferenceSDK().unMuteParticipant(participantId); + } + + public void stopParticipantSS(ConferenceListItem item) { + if (!item.isMe) { + mDataManager.getConferenceSDK().stopParticipantSS(item.participantId); + } else { + mDataManager.getConferenceSDK().stopScreenCapture(); + } + } + + public void stopParticipantVideo(ConferenceListItem item) { + if (!item.isMe) { + mDataManager.getConferenceSDK().stopParticipantVideo(item.participantId); + } else { + mDataManager.getConferenceSDK().stopCameraCapture(); + } + } + + public void mute() { + mDataManager.getConferenceSDK().mute(); + } + + public void endCall() { + mDataManager.getConferenceSDK().endCall(); + } + + public boolean isConferenceModerator() { + return mDataManager.getConferenceSDK().isConferenceModerator(); + } + + public void openChatWithParticipant(String participantPhoneId) { + ContactModel contactByChatId = mDataManager.getContactByChatId(participantPhoneId); + if (contactByChatId != null) { + if (getAttachedViews().size() == 0) return; + getViewState().closenConference(); + RoomModel room = new RoomModel(contactByChatId); + FragmentTransferObject fto = new FragmentTransferObject(room, null); + navigateToChat(fto, FragmentTransferObject.Type.P2pList); + } + } + + public void loadConferenceParticipants(ActiveConferenceCall activeConferenceCall) { + onConferenceMembersUpdate(activeConferenceCall); + } + + protected ConferenceListItem conferenceParticipant(NYNCallParticipant participant, + boolean isModerator, + boolean isOwnStreamActive) { + ContactModel user = mDataManager.getContactsByPhoneId(participant.getAddress()); + ConferenceListItem conferenceListItem = ConferenceListItem.fromSdkParticipant(participant, (user != null), isOwnStreamActive); + if (user != null) { + conferenceListItem.avatar = user.avatar; + } + if (isModerator) conferenceListItem.type = ConferenceListItem.ConferenceItemType.Moderator; + + return conferenceListItem; + } + + @Override + public void onConferenceMembersUpdate(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; + if (activeConferenceCall == null) return; + ArrayList members = new ArrayList<>(); + if (activeConferenceCall.mData.mParticipantArray != null) { + for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); + if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { + members.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); + } + } + } + getViewState().onConferenceMembersUpdate(members); + } + + @Override + public void onScreenShareState(boolean active) { + if (getAttachedViews().size() == 0) return; + getViewState().onScreenShareStateChanged(active && isScreenSharing()); + } + + @Override + public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, + String trackId) { + if (getAttachedViews().size() == 0) return; + getViewState().onRemoteVideoTrackAdded(activeConferenceCall, trackId); + } + + @Override + public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, + String trackId) { + getViewState().onRemoteVideoTrackRemoved(activeConferenceCall, trackId); + } + + @Override + public void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; + getViewState().onLocalVideoCapturerStarted(activeConferenceCall); + } + + @Override + public void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) { + if (getAttachedViews().size() == 0) return; + getViewState().onLocalVideoCapturerStopped(activeConferenceCall); + } + + @Override + public void onMicrophoneStateChanged(boolean isMuted) { + if (getAttachedViews().size() == 0) return; + getViewState().onMicrophoneStateChanged(isMuted); + } + + @Override + public void onSpeakerStateChanged(boolean isSpeakerOn) { + if (getAttachedViews().size() == 0) return; + getViewState().onSpeakerStateChanged(isSpeakerOn); + } + + @Override + public void onActiveSpeakersUpdate(String activeSpeakers) { + if (getAttachedViews().size() == 0) return; + getViewState().onActiveSpeakersUpdate(activeSpeakers); + } + + @Override + public void onMuteStateChangedByHost(boolean isMuted) { + if (getAttachedViews().size() == 0) return; + getViewState().updateMicrophonState(isMuted); + } + + + public void callBackPerson(ConferenceListItem item) { + mDataManager.getConferenceSDK().callBackMember(item.memberId, item.phoneId, item.name); + } + + public void pauseCallVideoCapturer() { + mDataManager.getConferenceSDK().setCallCameraPauseState(true); + } + + public void resumeCallVideoCapturer() { + mDataManager.getConferenceSDK().setCallCameraPauseState(false); + } + + + private boolean isContactInFriendList(@NotNull String phoneId) { + return (mDataManager.getContactsByPhoneId(phoneId) != null); + } +} + diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallActivityView.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallActivityView.java index 4769faf639..2ffd3c3131 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallActivityView.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallActivityView.java @@ -18,6 +18,14 @@ public interface CallActivityView extends ErrorMvpView { void onRemoteScreenShareTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) ; + void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId); + + void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId); + + void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall); + + void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall); + void showPurchaseDialog(boolean isModerator, final String message); void closeActivity(); diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallTapToSpeakView.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallTapToSpeakView.java index 8d39df5902..2f87ef0293 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallTapToSpeakView.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallTapToSpeakView.java @@ -1,6 +1,6 @@ package com.nynja.mobile.communicator.mvp.view; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; /** * Created by Ergyun Syuleyman on 9/14/18. diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java index d891294e74..a87a147dbc 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java @@ -2,7 +2,7 @@ package com.nynja.mobile.communicator.mvp.view; import android.support.annotation.StringRes; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/ConferenceVideoView.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/ConferenceVideoView.java new file mode 100644 index 0000000000..f055d72750 --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/ConferenceVideoView.java @@ -0,0 +1,35 @@ +package com.nynja.mobile.communicator.mvp.view; + +import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; + +import java.util.ArrayList; + +public interface ConferenceVideoView extends ErrorMvpView { + + void initConferenceStates(ActiveConferenceCall activeConferenceCall); + + void onConferenceMembersUpdate(ArrayList members); + + void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) ; + + void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) ; + + void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) ; + + void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) ; + + void onScreenShareStateChanged(boolean isSharing); + + void onMicrophoneStateChanged(boolean isMuted); + + void onSpeakerStateChanged(boolean isSpeakerOn); + + void onActiveSpeakersUpdate(String activeSpeakers); + + void updateMicrophonState(boolean isMuted); + + void closenConference(); + +} + diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java index 1735f7def1..0badef1469 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java @@ -615,17 +615,17 @@ public class MainActivity extends BaseActivity implements MainActivityView, chatAudioLayout.setVisibility(View.VISIBLE); mPresenter.requestUser(); //TODO: video feeds support in next features - //if (!activeConferenceCall.isOwnStreamActive || !activeConferenceCall.hasRemoteVideoTrack) { + //if (!activeConferenceCall.mData.isOwnStreamActive || !activeConferenceCall.hasRemoteVideoTrack) { // video.setVisibility(View.GONE); // chatAudioLayout.setVisibility(View.VISIBLE); // mPresenter.requestUser(); // if (activeConferenceCall.mConference != null) - // activeConferenceCall.mConference.setRemoteVideoRenderer(video); + // activeConferenceCall.mConference.setVideoRendererForTrack(video); //} else { // video.setVisibility(View.VISIBLE); // chatAudioLayout.setVisibility(View.GONE); // if (activeConferenceCall.mConference != null) { - // activeConferenceCall.mConference.setRemoteVideoRenderer(null); + // activeConferenceCall.mConference.setVideoRendererForTrack(null); // } //} } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java index 4346ba422c..f904202ade 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java @@ -5,26 +5,22 @@ import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; -import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.media.projection.MediaProjectionManager; -import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.provider.Settings; import android.support.v4.view.ViewPager; -import android.widget.LinearLayout; import com.arellomobile.mvp.presenter.InjectPresenter; import com.nynja.mobile.communicator.R; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.mvp.presenters.CallActivityPresenter; import com.nynja.mobile.communicator.mvp.view.CallActivityView; -import com.nynja.mobile.communicator.ui.adapters.ActiveCallPagerAdapter; +import com.nynja.mobile.communicator.ui.adapters.conference.ActiveCallPagerAdapter; import com.nynja.mobile.communicator.ui.base.BaseActivity; import com.nynja.mobile.communicator.ui.views.CirclePageIndicator; import com.nynja.mobile.communicator.ui.views.CustomViewPager; @@ -35,6 +31,7 @@ import org.webrtc.ContextUtils; import org.webrtc.VideoSourceUtility; import butterknife.BindView; +import kotlin.jvm.Synchronized; import ru.terrakok.cicerone.Navigator; import timber.log.Timber; @@ -42,10 +39,11 @@ public class CallActivity extends BaseActivity implements CallActivityView { private static final int CAPTURE_PERMISSION_REQUEST_CODE = 1; - public boolean isScreenShareActive; @BindView(R.id.active_call_viewpager) CustomViewPager mViewPager; @BindView(R.id.active_call_indicator) CirclePageIndicator mIndicator; +// @BindView(R.id.active_call_rv) RecyclerView mRecyclerView; + @InjectPresenter CallActivityPresenter mPresenter; public interface BluetoothConnectivityListener { @@ -76,6 +74,12 @@ public class CallActivity extends BaseActivity implements CallActivityView { mPresenter.bluetoothConnected(); } + initUI(); + + registerBluetoothReceiver(); + } + + private void initUI() { mPagerAdapter = new ActiveCallPagerAdapter(this); mViewPager.setAdapter(mPagerAdapter); addPageViewListener(); @@ -83,7 +87,27 @@ public class CallActivity extends BaseActivity implements CallActivityView { mIndicator.setSaveEnabled(false); mIndicator.setViewPager(mViewPager, ActiveCallPagerAdapter.CallPages.CallPageActiveCallFragment.ordinal()); mIndicator.notifyDataSetChanged(); - registerBluetoothReceiver(); + } + + private void initUIRv() { +// final DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); +// itemAnimator.setSupportsChangeAnimations(false); +// mRecyclerView.setItemAnimator(itemAnimator); +// mRecyclerView.setNestedScrollingEnabled(false); +// mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4)); +// mRecyclerView.setHasFixedSize(true); +// //mRecyclerView.setAdapter(ActiveCallAdapter); +// mRecyclerView.addItemDecoration(new CirclePagerIndicatorDecoration(R.dimen.rv_indicator_radius, +// R.dimen.rv_indicator_padding, +// R.dimen.rv_indicator_height, +// R.color.wheel_unselected_corner_bg, +// R.color.colorAccent)); +// new PagerSnapHelper().attachToRecyclerView(mRecyclerView); + } + + public boolean isScreenShareActive() { + if (mPagerAdapter != null) return mPagerAdapter.isScreenShareActive; + return false; } @Override @@ -93,39 +117,41 @@ public class CallActivity extends BaseActivity implements CallActivityView { mPagerAdapter.onConfigurationChanged(newConfig, mViewPager.getCurrentItem()); } - protected void addPageViewListener() { - if (mViewPager == null) return; - mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - Timber.d("CallActivity::onPageScrolled(): position=%d, positionOffset=%f, " + - "positionOffsetPixels=%d", position, positionOffset, positionOffsetPixels); - } + protected ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + Timber.d("CallActivity::onPageScrolled(): position=%d, positionOffset=%f, " + + "positionOffsetPixels=%d", position, positionOffset, positionOffsetPixels); + } - @Override - public void onPageSelected(int position) { - Timber.d("CallActivity::onPageSelected(): page=%d", position); + @Override + public void onPageSelected(int position) { + Timber.d("CallActivity::onPageSelected(): page=%d", position); // if (position == ActiveCallPagerAdapter.CallPages.CallPageActiveCallFragment.ordinal()) { // mIndicator.setVisibility(View.GONE); // } else { // mIndicator.setVisibility(View.VISIBLE); // } - synchronized (mPagerAdapter) { - mPagerAdapter.setFragmentActiveByPosition(position); - } + synchronized (mPagerAdapter) { + mPagerAdapter.setFragmentActiveByPosition(position); } + } - @Override - public void onPageScrollStateChanged(int state) { - Timber.d("CallActivity::onPageScrollStateChanged(): state=%d", state); + @Override + public void onPageScrollStateChanged(int state) { + Timber.d("CallActivity::onPageScrollStateChanged(): state=%d", state); - } - }); + } + }; + + protected void addPageViewListener() { + if (mViewPager == null) return; + mViewPager.addOnPageChangeListener(mOnPageChangeListener); } - public void showShareScreen(boolean show) { - isScreenShareActive = show; + protected void showShareScreen(boolean show) { synchronized (mPagerAdapter) { + mViewPager.removeOnPageChangeListener(mOnPageChangeListener); mViewPager.setAdapter(null); if (show) { mPagerAdapter.showShareScreen(); @@ -133,6 +159,7 @@ public class CallActivity extends BaseActivity implements CallActivityView { mPagerAdapter.hideShareScreen(); } + mViewPager.addOnPageChangeListener(mOnPageChangeListener); mViewPager.setAdapter(mPagerAdapter); } // addPageViewListener(); @@ -210,7 +237,7 @@ public class CallActivity extends BaseActivity implements CallActivityView { @Override public void initConferenceStates(ActiveConferenceCall activeConferenceCall) { - if (activeConferenceCall != null && activeConferenceCall.hasRemoteScreenShareTrack) { + if (activeConferenceCall != null && activeConferenceCall.mData.hasRemoteScreenShareTrack) { showShareScreen(true); } } @@ -302,24 +329,88 @@ public class CallActivity extends BaseActivity implements CallActivityView { @Override public void onRemoteScreenShareTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { - final boolean hasRemoteScreenShareTrack = (activeConferenceCall != null && activeConferenceCall.hasRemoteScreenShareTrack); - runOnUiThread(() -> { + final boolean hasRemoteScreenShareTrack = (activeConferenceCall != null && activeConferenceCall.mData.hasRemoteScreenShareTrack); + mHandler.postDelayed(() -> { if (hasRemoteScreenShareTrack) { showShareScreen(true); } - }); + }, Consts.DELAY_100); } @Override public void onRemoteScreenShareTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) { - runOnUiThread(() -> { + mHandler.postDelayed(() -> { showShareScreen(false); - }); + }, Consts.DELAY_100); + } + + @Override + public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { + mHandler.postDelayed(() -> { + tryUpdateConferenceVideoScreen(activeConferenceCall, true); + }, Consts.DELAY_100); } + @Override + public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) { + mHandler.postDelayed(() -> { + tryUpdateConferenceVideoScreen(activeConferenceCall, false); + }, Consts.DELAY_100); + } + + @Override + public void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) { + mHandler.postDelayed(() -> { + tryUpdateConferenceVideoScreen(activeConferenceCall, true); + }, Consts.DELAY_100); + } + + @Override + public void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) { + mHandler.postDelayed(() -> { + tryUpdateConferenceVideoScreen(activeConferenceCall, false); + }, Consts.DELAY_200); + } @Override public Navigator getActivityNavigator() { return null; } + @Synchronized + private void tryUpdateConferenceVideoScreen(ActiveConferenceCall activeConferenceCall, boolean show) { + if (activeConferenceCall == null) { + return; + } + if (!activeConferenceCall.isConference()) { + return; + } + if (show && mPagerAdapter.isConferenceVideoActive) return; + + boolean updated = false; + int currentItem = mIndicator.getCurrentItem(); + ActiveCallPagerAdapter.CallPages page = mPagerAdapter.getPageByPosition(currentItem); + synchronized (mPagerAdapter) { + if (show && (activeConferenceCall.mData.hasRemoteVideoTrack() || activeConferenceCall.mData.isOwnStreamActive)) { + mViewPager.removeOnPageChangeListener(mOnPageChangeListener); + mViewPager.setAdapter(null); + mPagerAdapter.showConferenceVideoScreen(); + mViewPager.addOnPageChangeListener(mOnPageChangeListener); + mViewPager.setAdapter(mPagerAdapter); + updated = true; + } else if (!activeConferenceCall.mData.hasRemoteVideoTrack() && !activeConferenceCall.mData.isOwnStreamActive){ + mViewPager.removeOnPageChangeListener(mOnPageChangeListener); + mViewPager.setAdapter(null); + mPagerAdapter.hideConferenceVideoScreen(); + mViewPager.addOnPageChangeListener(mOnPageChangeListener); + mViewPager.setAdapter(mPagerAdapter); + updated = true; + } + } + // set to position 1 + if (updated) { + mIndicator.setViewPager(mViewPager, mPagerAdapter.getFragmentPositionByType(page)); + mIndicator.notifyDataSetChanged(); + } + } + } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ActiveCallPagerAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java similarity index 60% rename from app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ActiveCallPagerAdapter.java rename to app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java index 7a4a38e168..0d9e7fa7c3 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ActiveCallPagerAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java @@ -1,4 +1,4 @@ -package com.nynja.mobile.communicator.ui.adapters; +package com.nynja.mobile.communicator.ui.adapters.conference; import android.content.res.Configuration; import android.support.annotation.NonNull; @@ -9,6 +9,7 @@ import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; import com.nynja.mobile.communicator.ui.base.BaseFragment; import com.nynja.mobile.communicator.ui.fragments.conference.CallTapToSpeakFragment; import com.nynja.mobile.communicator.ui.fragments.conference.ConferenceCallFragment; +import com.nynja.mobile.communicator.ui.fragments.conference.ConferenceVideoFragment; import com.nynja.mobile.communicator.ui.fragments.conference.ScreenShareFragment; import java.util.ArrayList; @@ -16,6 +17,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +import kotlin.jvm.Synchronized; import timber.log.Timber; /** @@ -25,9 +27,24 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { private HashMap mAdapterPages = new HashMap<>(); private List callPages = new ArrayList<>(); + public boolean isScreenShareActive = false; + public boolean isConferenceVideoActive = false; private CallActivity callActivity; + public enum CallPages { + CallPageTapToSpeak, + ShareScreenFragment, + ConferenceVideoFragment, + CallPageActiveCallFragment + } + + public ActiveCallPagerAdapter(CallActivity callActivity) { + super(callActivity); + this.callActivity = callActivity; + hideShareScreen(); + } + public void reset() { for (CallPages callPage : CallPages.values()) { final String itemId = makeFragmentId(getItemId(callPage.ordinal())); @@ -41,36 +58,86 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { callPages.clear(); } - public void hideShareScreen() { - final String itemId = makeFragmentId(getItemId(CallPages.ShareScreenFragment.ordinal())); + @Synchronized + private void preparePages() { +// callPages.clear(); +// for (CallPages callPage : CallPages.values()) { +// if (callPage == CallPages.ShareScreenFragment && !isScreenShareActive) { +// final String itemId = makeFragmentId(getItemId(callPage.ordinal())); +// BaseFragment fragment = mAdapterPages.get(itemId); +// if (fragment != null) { +// destroyView(fragment); +// } +// mAdapterPages.remove(itemId); +// continue; +// } +// if (callPage == CallPages.ConferenceVideoFragment && !isConferenceVideoActive) { +// final String itemId = makeFragmentId(getItemId(callPage.ordinal())); +// BaseFragment fragment = mAdapterPages.get(itemId); +// if (fragment != null) { +// destroyView(fragment); +// } +// mAdapterPages.remove(itemId); +// continue; +// } +// +// callPages.add(callPage); +// } + + for (CallPages callPage : callPages) { + if (callPage == CallPages.ShareScreenFragment && !isScreenShareActive) { + final String itemId = makeFragmentId(getItemId(callPage.ordinal())); + BaseFragment fragment = mAdapterPages.get(itemId); + if (fragment != null) { + destroyView(fragment); + } + mAdapterPages.remove(itemId); + } + if (callPage == CallPages.ConferenceVideoFragment && !isConferenceVideoActive) { + final String itemId = makeFragmentId(getItemId(callPage.ordinal())); + BaseFragment fragment = mAdapterPages.get(itemId); + if (fragment != null) { + destroyView(fragment); + } + mAdapterPages.remove(itemId); + } + } callPages.clear(); for (CallPages callPage : CallPages.values()) { - if (callPage == CallPages.ShareScreenFragment) { + if (callPage == CallPages.ShareScreenFragment && !isScreenShareActive) { + continue; + } + if (callPage == CallPages.ConferenceVideoFragment && !isConferenceVideoActive) { continue; } callPages.add(callPage); } - mAdapterPages.remove(itemId); + + } + + public void hideShareScreen() { + isScreenShareActive = false; + preparePages(); notifyDataSetChanged(); } public void showShareScreen() { - callPages.clear(); - callPages.addAll(Arrays.asList(CallPages.values())); + isScreenShareActive = true; + preparePages(); notifyDataSetChanged(); } - public enum CallPages { - CallPageTapToSpeak, - ShareScreenFragment, - CallPageActiveCallFragment + public void hideConferenceVideoScreen() { + isConferenceVideoActive = false; + preparePages(); + notifyDataSetChanged(); } - public ActiveCallPagerAdapter(CallActivity callActivity) { - super(callActivity); - this.callActivity = callActivity; - hideShareScreen(); + public void showConferenceVideoScreen() { + isConferenceVideoActive = true; + preparePages(); + notifyDataSetChanged(); } public BaseFragment getItem(int position) { @@ -99,6 +166,12 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { ((ScreenShareFragment) fragment).setCallActivity(callActivity); ((ScreenShareFragment)fragment).setIsActive(false); } + } else if (callPages.get(position) == CallPages.ConferenceVideoFragment) { + fragment = new ConferenceVideoFragment(); + if (callActivity != null) { + ((ConferenceVideoFragment) fragment).setCallActivity(callActivity); + ((ConferenceVideoFragment)fragment).setIsActive(false); + } } // if (position == CallPages.CallPageTapToSpeak.ordinal()) { @@ -171,12 +244,21 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { } else if (position == CallPages.ShareScreenFragment.ordinal() && fragment instanceof ScreenShareFragment) { ((ScreenShareFragment)fragment).setActiveState(active); + } else if (position == CallPages.ConferenceVideoFragment.ordinal() + && fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment)fragment).setActiveState(active); } else if (position == CallPages.CallPageActiveCallFragment.ordinal() && fragment instanceof ConferenceCallFragment) { ((ConferenceCallFragment)fragment).setActiveState(active); } else if (position == CallPages.ShareScreenFragment.ordinal() && fragment instanceof ConferenceCallFragment) { ((ConferenceCallFragment)fragment).setActiveState(active); + } else if (position == CallPages.ConferenceVideoFragment.ordinal() + && fragment instanceof ConferenceCallFragment) { + ((ConferenceCallFragment)fragment).setActiveState(active); + } else if (position == CallPages.ShareScreenFragment.ordinal() + && fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment)fragment).setActiveState(active); } } @@ -186,6 +268,26 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { } } + public int getFragmentPositionByType(CallPages page) { + int index = 0; + for (CallPages p : callPages) { + if (p == page) { + return index; + } + ++index; + } + return page.ordinal(); + } + + + public CallPages getPageByPosition( int position) { + CallPages page = CallPages.CallPageActiveCallFragment; + if (position < callPages.size()) { + page = callPages.get(position); + } + return page; + } + public void onConfigurationChanged(Configuration newConfig, int position) { BaseFragment fragment = getItemByPosition(position); if (fragment == null) return; @@ -193,10 +295,17 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { && fragment instanceof CallTapToSpeakFragment) || (position == CallPages.ShareScreenFragment.ordinal() && fragment instanceof ScreenShareFragment) + || (position == CallPages.ConferenceVideoFragment.ordinal() + && fragment instanceof ConferenceVideoFragment) || (position == CallPages.CallPageActiveCallFragment.ordinal() && fragment instanceof ConferenceCallFragment) || (position == CallPages.ShareScreenFragment.ordinal() - && fragment instanceof ConferenceCallFragment)) { + && fragment instanceof ConferenceCallFragment) + || (position == CallPages.ConferenceVideoFragment.ordinal() + && fragment instanceof ConferenceCallFragment) + || (position == CallPages.ShareScreenFragment.ordinal() + && fragment instanceof ConferenceVideoFragment) + ) { fragment.onConfigurationChanged(newConfig); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ConferenceParticipantsAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceParticipantsAdapter.java similarity index 94% rename from app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ConferenceParticipantsAdapter.java rename to app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceParticipantsAdapter.java index 3f978282a5..f1e40fff28 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ConferenceParticipantsAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceParticipantsAdapter.java @@ -1,4 +1,4 @@ -package com.nynja.mobile.communicator.ui.adapters; +package com.nynja.mobile.communicator.ui.adapters.conference; import android.content.Context; import android.support.annotation.NonNull; @@ -10,7 +10,7 @@ import android.widget.ArrayAdapter; import com.nynja.mobile.communicator.R; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; -import com.nynja.mobile.communicator.ui.adapters.viewholders.ConferenceContactVh; +import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceContactVh; import java.util.ArrayList; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java new file mode 100644 index 0000000000..9d5378332b --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -0,0 +1,64 @@ +package com.nynja.mobile.communicator.ui.adapters.conference; + +import android.support.annotation.NonNull; +import android.view.ViewGroup; + +import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; +import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; +import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceVideoItemVh; +import com.nynja.mobile.communicator.ui.base.BaseAdapter; +import com.nynja.mobile.communicator.ui.base.BaseVH; + +import java.util.List; + +public class ConferenceVideoAdapter> extends BaseAdapter { + private OnConferenceItemClickListener mOnConferenceItemClickListener; + private boolean mIsModerator = false; + + public ConferenceVideoAdapter(List list, + OnConferenceItemClickListener onConferenceItemClickListener) { + super(list); + this.mOnConferenceItemClickListener = onConferenceItemClickListener; + } + + public void setOnItemClickListener(OnConferenceItemClickListener onConferenceItemClickListener) { + this.mOnConferenceItemClickListener = onConferenceItemClickListener; + } + + public void setIsModerator(boolean isModerator) { + this.mIsModerator = isModerator; + } + + public boolean isModerator() { + return this.mIsModerator; + } + + public void releaseVideoCallRrenderers() { + clear(); + } + + @NonNull + @Override + public T onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + ConferenceVideoItemVh viewHolder = new ConferenceVideoItemVh(viewGroup, mIsModerator); + viewHolder.setOnItemClickListener(mOnConferenceItemClickListener); + return (T) viewHolder; + } + + @Override public void onViewAttachedToWindow(@NonNull T holder) { + ((ConferenceVideoItemVh)holder).initVideoCallRenderer(); + ConferenceVideoModule.getInstance().setVideoRendererForTrack(((ConferenceVideoItemVh)holder).getVideoFeed(), + ConferenceVideoModule.getInstance().getTrackIdByParticipantId(((ConferenceVideoItemVh)holder).getItem().participantId), + ((ConferenceVideoItemVh)holder).getItem().isMe); + } + + @Override public void onViewDetachedFromWindow(@NonNull T holder) { + ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, + ConferenceVideoModule.getInstance().getTrackIdByParticipantId(((ConferenceVideoItemVh)holder).getItem().participantId), + ((ConferenceVideoItemVh)holder).getItem().isMe); + ((ConferenceVideoItemVh)holder).releaseVideoCallRrenderers(); + } + +} + diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/ConferenceContactVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceContactVh.java similarity index 98% rename from app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/ConferenceContactVh.java rename to app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceContactVh.java index 7ea4d9ee01..e97f58d1db 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/ConferenceContactVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceContactVh.java @@ -1,4 +1,4 @@ -package com.nynja.mobile.communicator.ui.adapters.viewholders; +package com.nynja.mobile.communicator.ui.adapters.viewholders.conference; import android.content.Context; import android.view.LayoutInflater; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java new file mode 100644 index 0000000000..d9b2d2648c --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -0,0 +1,169 @@ +package com.nynja.mobile.communicator.ui.adapters.viewholders.conference; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.nynja.mobile.communicator.R; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; +import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; +import com.nynja.mobile.communicator.ui.base.BaseVH; +import com.nynja.mobile.communicator.ui.views.CheckableImageView; + +import org.webrtc.RendererCommon; +import org.webrtc.SurfaceViewRenderer; + +import butterknife.BindView; +import kotlin.jvm.Synchronized; +import timber.log.Timber; + +import static org.webrtc.ContextUtils.createRootEglBase; + +public class ConferenceVideoItemVh extends BaseVH { + + @BindView(R.id.conf_video_muted) ImageView mMutedIndicator; + @BindView(R.id.conf_video_name) TextView mName; + @BindView(R.id.conf_video_ss) CheckableImageView mSS; + @BindView(R.id.conf_video_active) CheckableImageView mActiveVideo; + @BindView(R.id.conf_video_feed) SurfaceViewRenderer mVideoFeed; + + + protected ConferenceListItem mItem; + private OnConferenceItemClickListener mListener; + private boolean mIsModerator; + private boolean mIsRenderersInitialized = false; + + public ConferenceVideoItemVh(ViewGroup parent, boolean isModerator) { + super(parent, R.layout.li_conference_video); + mIsModerator = isModerator; + } + + public void setOnItemClickListener(OnConferenceItemClickListener onConferenceItemClickListener) { + this.mListener = onConferenceItemClickListener; + } + + public SurfaceViewRenderer getVideoFeed() { + return mVideoFeed; + } + + public ConferenceListItem getItem() { + return mItem; + } + + @Override public void setData(ConferenceListItem item) { + this.mItem = item; + mSS.setAutoToggle(false); + mActiveVideo.setAutoToggle(false); + if (item.type == ConferenceListItem.ConferenceItemType.Plus) { +// mPhoto.setImageResource(R.drawable.v_add_member_voice_call); + } else { + // item.type == ConferenceListItem.ConferenceItemType.Participant + if (item.memberId == null || item.memberId.isEmpty()) { +// mPhoto.setImageResource(R.drawable.participant_placeholder_grey); + } else { + // in Conference + setupInConference(item); + } + } + mName.setText(item.name); + itemView.setOnClickListener(null); + itemView.setOnLongClickListener(null); + if (mListener != null) { + item.initActions(mIsModerator); + itemView.setOnClickListener(v -> mListener.onItemClick(item, -1)); + itemView.setOnLongClickListener(v -> mListener.onItemLongClick(item, -1)); + } + } + + @Synchronized + public void initVideoCallRenderer() { + if (mIsRenderersInitialized) return; + try { + mVideoFeed.init(createRootEglBase().getEglBaseContext(), null); + mVideoFeed.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); + mVideoFeed.setEnableHardwareScaler(true); + mIsRenderersInitialized = true; + } catch (Exception ex) { + Timber.e(ex); + } + } + + @Synchronized + public void releaseVideoCallRrenderers() { + if (!mIsRenderersInitialized) return; + if (mVideoFeed != null) { + mVideoFeed.release(); + } + mIsRenderersInitialized = false; + } + + + private void setupInConference(ConferenceListItem item) { + initVideoCallRenderer(); + if (item.participantId == null || !item.isActive) { + // in Conference - but not joined yet + mMutedIndicator.setVisibility(View.GONE); +// mPhoto.setImageResource(R.drawable.participant_placeholder_grey); + } else { + // already joined in Conference + drawIsMutedIfNeeded(item); + drawIsScfreenSharingIfNeeded(item); + drawIsActiveVideoIfNeeded(item); + drawIsFeedVideoIfNeeded(item.hasVideo); + } + } + + private void drawIsMutedIfNeeded(ConferenceListItem item) { + if(item.isMuted) { + mMutedIndicator.setVisibility(View.VISIBLE); + } else { + mMutedIndicator.setVisibility(View.GONE); +// ImageUtils.loadAvatarImage(item.avatar, mPhoto); + } + } + + private void drawIsActiveVideoIfNeeded(ConferenceListItem item) { + if(item.hasVideo) { + mActiveVideo.setChecked(true); + mActiveVideo.setVisibility(View.VISIBLE); + } else { + mActiveVideo.setVisibility(View.GONE); + } + } + + private void drawIsScfreenSharingIfNeeded(ConferenceListItem item) { + if(item.hasScreen) { + mSS.setChecked(true); + mSS.setVisibility(View.VISIBLE); + } else { + mSS.setVisibility(View.GONE); + } + } + + private void drawIsFeedVideoIfNeeded(boolean visible) { + if (visible) { + mVideoFeed.setVisibility(View.VISIBLE); + } else { + mVideoFeed.setVisibility(View.GONE); + } + refreshFeedVideo(); + } + + private void refreshFeedVideo() { + if (mVideoFeed != null) { + mVideoFeed.invalidate(); + mVideoFeed.refreshDrawableState(); + } + } + + public void showHideItemView(boolean show) { + if (show) { + itemView.setVisibility(View.VISIBLE); + } else { + itemView.setVisibility(View.GONE); + } + + } + +} diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java index 79e9e1fb86..89da948d1e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java @@ -4,6 +4,8 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; +import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceVideoItemVh; + import java.util.ArrayList; import java.util.List; @@ -162,4 +164,10 @@ public abstract class BaseAdapter> extends RecyclerVie } } } + + @Override public void onViewAttachedToWindow(@NonNull Vh holder) { + } + + @Override public void onViewDetachedFromWindow(@NonNull Vh holder) { + } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java index 24db500d3b..e356e2efe5 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java @@ -2,6 +2,7 @@ package com.nynja.mobile.communicator.ui.base; import android.content.Context; import android.support.annotation.LayoutRes; +import android.support.v4.view.ViewCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java index 9b81c77fa3..49cfa60f9d 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java @@ -20,7 +20,7 @@ import android.widget.Toast; import com.arellomobile.mvp.presenter.InjectPresenter; import com.nynja.mobile.communicator.R; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.mvp.presenters.CallTapToSpeakPresenter; import com.nynja.mobile.communicator.mvp.view.CallTapToSpeakView; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java index ee681fb52d..c2bc814d5c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java @@ -34,7 +34,7 @@ import android.widget.Toast; import com.arellomobile.mvp.presenter.InjectPresenter; import com.nynja.mobile.communicator.BuildConfig; import com.nynja.mobile.communicator.R; -import com.nynja.mobile.communicator.data.calls.ActiveCallBase; +import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; import com.nynja.mobile.communicator.data.models.nynjamodels.RoomModel; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; @@ -43,8 +43,8 @@ import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; import com.nynja.mobile.communicator.mvp.presenters.ConferenceCallPresenter; import com.nynja.mobile.communicator.mvp.view.CallView; import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; -import com.nynja.mobile.communicator.ui.adapters.ActiveCallPagerAdapter; -import com.nynja.mobile.communicator.ui.adapters.ConferenceParticipantsAdapter; +import com.nynja.mobile.communicator.ui.adapters.conference.ActiveCallPagerAdapter; +import com.nynja.mobile.communicator.ui.adapters.conference.ConferenceParticipantsAdapter; import com.nynja.mobile.communicator.ui.base.BaseFragment; import com.nynja.mobile.communicator.ui.views.CheckableImageView; import com.nynja.mobile.communicator.utils.ActionSheetDialog; @@ -53,7 +53,6 @@ import com.nynja.mobile.communicator.utils.DialogFactory; import com.nynja.mobile.communicator.utils.ImageUtils; import com.nynja.mobile.communicator.utils.PermissionHelper; import com.nynja.mobile.communicator.utils.StringUtils; -import com.nynja.mobile.communicator.utils.Utils; import org.webrtc.ContextUtils; import org.webrtc.EglBase; @@ -231,12 +230,12 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, @Override public void onResume() { super.onResume(); -// setRemoteVideoRenderer(mConferencePresenter.getActiveConference()); +// setVideoRendererForTrack(mConferencePresenter.getActiveConference()); // setLocalVideoRenderer(mConferencePresenter.getActiveConference()); // mConferencePresenter.resumeCallVideoCapturer(); isActive = true; if (callActivity != null) { - openShareScreenButton.setVisibility(callActivity.isScreenShareActive ? View.VISIBLE : View.GONE); + openShareScreenButton.setVisibility(callActivity.isScreenShareActive() ? View.VISIBLE : View.GONE); } if (mConferencePresenter.getActiveConference() != null) { @@ -265,7 +264,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, // @Override // public void onStart() { // super.onStart(); -// setRemoteVideoRenderer(mConferencePresenter.getActiveConference(), ""); +// setVideoRendererForTrack(mConferencePresenter.getActiveConference(), ""); // setLocalVideoRenderer(mConferencePresenter.getActiveConference()); // mConferencePresenter.resumeCallVideoCapturer(); // isActive = true; @@ -541,7 +540,9 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, mConfParticipantsAdapter.setIsModerator(activeConferenceCall.isModerator()); if (activeConferenceCall.isWaiting()) { waitingConference(activeConferenceCall); - } else if (activeConferenceCall.isVideoEnabled || activeConferenceCall.isOwnStreamActive) { + } else if ((activeConferenceCall.isVideoEnabled + || activeConferenceCall.mData.isOwnStreamActive) + && !activeConferenceCall.isConference()){ videoConference(activeConferenceCall); //if (!activeConferenceCall.isSpeakerOn) } else { @@ -639,7 +640,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, audioIncomeLayout.setVisibility(visible); name.setVisibility(visible); callActivity.getPageIndicator().setVisibility(visible); - if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) { + if (activeConferenceCall.isConference()) { activeUserPhotoLayout.setVisibility(View.GONE); conferenceParticipantsLayout.setVisibility(visible); } else { @@ -652,7 +653,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, protected void updateRendererUI(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall != null && activeConferenceCall.mConference != null) { - if (activeConferenceCall.hasRemoteVideoTrack + if (activeConferenceCall.mData.hasRemoteVideoTrack // && activeConferenceCall.mConference.hasRemoteVideo() && isActive) { videoRemote.setVisibility(View.VISIBLE); @@ -699,7 +700,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, conferenceParticipantsLayout.setVisibility(View.GONE); activeUserNameSection.setVisibility(visible); callActivity.getPageIndicator().setVisibility(visible); - if (activeConferenceCall != null && activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) { + if (activeConferenceCall != null && activeConferenceCall.isConference()) { // TODO: for later Conference calls video support. } else { mConferencePresenter.loadUser(activeConferenceCall); @@ -741,7 +742,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, } } - if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) { + if (activeConferenceCall.isConference()) { mConferencePresenter.loadConferenceParticipants(activeConferenceCall); addCallerLayout.setEnabled(activeConferenceCall.isModerator()); } else { @@ -757,7 +758,8 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, if (callActivity != null && !activeConferenceCall.isCallInProgress()) { callActivity.getViewPager().setPagingEnabled(false); } - mHandler.post(() -> initialConferenceStates(activeConferenceCall)); + //mHandler.post(() -> initialConferenceStates(activeConferenceCall)); + initialConferenceStates(activeConferenceCall); //////////////////////////////////////////////////////////////////////////////////////////// // TEST TEST TEST if (BuildConfig.DEBUG) { @@ -891,7 +893,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, if (active) { updateMicrophonState(activeConferenceCall.isMuted); if (activeConferenceCall.isVideoEnabled) { - if (activeConferenceCall.isOwnStreamActive) { + if (activeConferenceCall.mData.isOwnStreamActive) { setLocalVideoRenderer(mConferencePresenter.getActiveConference()); mConferencePresenter.resumeCallVideoCapturer(); } @@ -902,8 +904,8 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, muteMicHint.setVisibility(View.GONE); mHandler.removeCallbacks(mShowMuteMicHintExpired); if (activeConferenceCall.isVideoEnabled) { - if (activeConferenceCall.isOwnStreamActive) { - mConferencePresenter.pauseCallVideoCapturer(); + if (activeConferenceCall.mData.isOwnStreamActive) { + //mConferencePresenter.pauseCallVideoCapturer(); removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); } removeRemoteVideoRenderer(mConferencePresenter.getActiveConference()); @@ -1128,7 +1130,8 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, private void requestPermissionIfNeeds(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; - boolean enableVideo = (activeConferenceCall.isOwnStreamActive && activeConferenceCall.mInitialStartCapturer); + boolean enableVideo = (activeConferenceCall.mData.isOwnStreamActive + && activeConferenceCall.mInitialStartCapturer); ArrayList permissions = getPermissionsForCall(enableVideo); String[] perms = new String[0]; @@ -1204,7 +1207,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, private void updateAddContact(ActiveConferenceCall activeConferenceCall) { if (shouldCallActionsActive(activeConferenceCall)) { - if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) { + if (activeConferenceCall.isConference()) { addCallerLayout.setEnabled(activeConferenceCall.isModerator()); addContact.setEnabled(activeConferenceCall.isModerator()); } else { @@ -1249,7 +1252,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, private void initVideoCallRrenderers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; - if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) return; + if (activeConferenceCall.isConference()) return; if (!activeConferenceCall.isVideoEnabled) return; try { videoLocal.init(createRootEglBase().getEglBaseContext(), null); @@ -1278,34 +1281,37 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, private void setRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall) { if (!mIsRenderersInitialized) return; if (activeConferenceCall == null) return; - //if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) return; + if (activeConferenceCall.isConference()) return; if (activeConferenceCall.mConference == null) return; + if (activeConferenceCall.mConference.isConference()) return; if (!activeConferenceCall.isVideoEnabled) return; - if (activeConferenceCall.hasRemoteVideoTrack) { - activeConferenceCall.mConference.setRemoteVideoRenderer(videoRemote, activeConferenceCall.mRemoteVideoTrackId); + if (activeConferenceCall.mData.hasRemoteVideoTrack) { + activeConferenceCall.mConference.setRemoteVideoRenderer(videoRemote, activeConferenceCall.mData.mRemoteVideoTrackId); } } private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall, String trackId) { if (activeConferenceCall == null) return; - //if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) return; + if (activeConferenceCall.isConference()) return; if (activeConferenceCall.mConference == null) return; + if (activeConferenceCall.mConference.isConference()) return; if (!activeConferenceCall.mConference.isRunning()) return; if (!activeConferenceCall.isVideoEnabled) return; - if (!activeConferenceCall.hasRemoteVideoTrack && StringUtils.isNotEmpty(trackId)) { + if (!activeConferenceCall.mData.hasRemoteVideoTrack && StringUtils.isNotEmpty(trackId)) { activeConferenceCall.mConference.setRemoteVideoRenderer(null, trackId); } } private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; - removeRemoteVideoRenderer(activeConferenceCall, activeConferenceCall.mRemoteVideoTrackId); + if (activeConferenceCall.isConference()) return; + removeRemoteVideoRenderer(activeConferenceCall, activeConferenceCall.mData.mRemoteVideoTrackId); } private void setLocalVideoRenderer(ActiveConferenceCall activeConferenceCall) { if (!mIsRenderersInitialized) return; if (activeConferenceCall == null) return; - //if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) return; + if (activeConferenceCall.isConference()) return; if (activeConferenceCall.mConference == null) return; if (!activeConferenceCall.isVideoEnabled) return; @@ -1314,7 +1320,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, private void removeLocalVideoRenderer(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; - //if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) return; + if (activeConferenceCall.isConference()) return; if (activeConferenceCall.mConference == null) return; if (!activeConferenceCall.mConference.isRunning()) return; if (!activeConferenceCall.isVideoEnabled) return; @@ -1377,8 +1383,10 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, } private void startConferenceCall() { - mConferencePresenter.startConference(); - status.setText(R.string.call_connecting); + if (getActivity() != null) { + mConferencePresenter.startConference(); + status.setText(R.string.call_connecting); + } } private void updateContactInfo() { @@ -1391,8 +1399,9 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, private void setConferenceState(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall.isWaiting()) { waitingConference(activeConferenceCall); - } else if (activeConferenceCall.isSwitchToAudio || - !activeConferenceCall.isVideoEnabled) { + } else if (activeConferenceCall.isSwitchToAudio + || !activeConferenceCall.isVideoEnabled + || activeConferenceCall.isConference()) { audioConference(activeConferenceCall); } else { videoConference(activeConferenceCall); @@ -1424,7 +1433,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, @Override public void updateMicrophonState(boolean isMuted) { if (audioMute != null && isActive) { - audioMute.post(() -> audioMute.setChecked(isMuted)); + audioMute.setChecked(isMuted); } } @@ -1552,7 +1561,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, public void showFirstStopScreenSharingWarning(ActiveConferenceCall call){ if (call == null) return; String message = getString(R.string.call_ask_to_stop_ss_first, call.getConferenceSSOwner()); - if (call.isConference() && call.hasRemoteVideoTrack) { + if (call.isConference() && call.mData.hasRemoteVideoTrack) { message = getString(R.string.call_ask_to_stop_camera_first, call.getConferenceSSOwner()); } final String msg = message; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java new file mode 100644 index 0000000000..2598b35b66 --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -0,0 +1,563 @@ +package com.nynja.mobile.communicator.ui.fragments.conference; + +import android.Manifest; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.PagerSnapHelper; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.arellomobile.mvp.presenter.InjectPresenter; +import com.nynja.mobile.communicator.R; +import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; +import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; +import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; +import com.nynja.mobile.communicator.mvp.presenters.ConferenceVideoPresenter; +import com.nynja.mobile.communicator.mvp.view.ConferenceVideoView; +import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; +import com.nynja.mobile.communicator.ui.adapters.conference.ConferenceVideoAdapter; +import com.nynja.mobile.communicator.ui.base.BaseFragment; +import com.nynja.mobile.communicator.utils.ActionSheetDialog; +import com.nynja.mobile.communicator.utils.DialogFactory; +import com.nynja.mobile.communicator.utils.PermissionHelper; +import com.nynja.mobile.communicator.utils.StringUtils; + +import org.webrtc.ContextUtils; +import org.webrtc.EglBase; + +import java.util.ArrayList; +import java.util.Arrays; + +import butterknife.BindView; +import timber.log.Timber; + +public class ConferenceVideoFragment extends BaseFragment implements ConferenceVideoView, + OnConferenceItemClickListener { + + private static final int FRONT_CAMERA = 1; + + // conference controls + @BindView(R.id.f_call_rv) RecyclerView mRecyclerView; + + @InjectPresenter + ConferenceVideoPresenter mConferencePresenter; + + private ConferenceVideoAdapter mConfParticipantsAdapter; + private boolean isActive; + private CallActivity callActivity; + private Handler mHandler; + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mHandler = new Handler(); + createRootEglBase(); + ActiveConferenceCall activeConferenceCall = mConferencePresenter.getActiveConference(); + ConferenceVideoModule.getInstance().setCurrentActiveCall(activeConferenceCall); + mConfParticipantsAdapter = new ConferenceVideoAdapter(new ArrayList<>(), this); + initUIRv(); + } + + @Override + public void onDestroyView() { + mConfParticipantsAdapter.releaseVideoCallRrenderers(); + ConferenceVideoModule.getInstance().setCurrentActiveCall(null); + super.onDestroyView(); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_conference_video_call, container, false); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + + @Override + public void onResume() { + super.onResume(); + isActive = true; + } + + @Override + public void onPause() { + mConferencePresenter.pauseCallVideoCapturer(); + removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); + removeRemoteVideoRenderer(mConferencePresenter.getActiveConference()); + isActive = false; + super.onPause(); + } + + @Override + public void onItemClick(ConferenceListItem item, int position) { + Timber.d("On clicked position: %d contact: %s", position, item); + if (item == null) return; + // '+' item + if (item.type == ConferenceListItem.ConferenceItemType.Plus) { + } else { + } + } + + @Override + public boolean onItemLongClick(ConferenceListItem item, int position) { + Timber.d("On long clicked position: %d contact: %s", position, item); + if (item == null) return false; + // '+' item + if (item.type == ConferenceListItem.ConferenceItemType.Plus) { + return false; + } + + if (item.memberActions.size() == 0) return false; + + return true; + } + + private void initUIRv() { +// final DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); +// itemAnimator.setSupportsChangeAnimations(false); +// mRecyclerView.setItemAnimator(itemAnimator); + mRecyclerView.setNestedScrollingEnabled(false); +// mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); + GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),2, LinearLayoutManager.HORIZONTAL, false); +// gridLayoutManager.setItemPrefetchEnabled(true); + mRecyclerView.setLayoutManager(gridLayoutManager); + mRecyclerView.setHasFixedSize(true); + mRecyclerView.setAdapter(mConfParticipantsAdapter); +// mRecyclerView.addItemDecoration(new CirclePagerIndicatorDecoration(R.dimen.rv_indicator_radius, +// R.dimen.rv_indicator_padding, +// R.dimen.rv_indicator_height, +// R.color.wheel_unselected_corner_bg, +// R.color.colorAccent)); +// new PagerSnapHelper().attachToRecyclerView(mRecyclerView); + } + + protected void updateRendererUI(ActiveConferenceCall activeConferenceCall) { + if (mConfParticipantsAdapter != null) { + mConfParticipantsAdapter.notifyDataSetChanged(); + } + } + + protected void videoConference(ActiveConferenceCall activeConferenceCall) { + if (getActivity() == null || !isAdded()) return; + updateRendererUI(activeConferenceCall); + int visible = isActive ? View.VISIBLE : View.GONE; + callActivity.getPageIndicator().setVisibility(visible); + if (activeConferenceCall != null && activeConferenceCall.isConference()) { + // TODO: for later Conference calls video support. + } + } + + protected void initialConferenceStates(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall.isOutgoingCall) { + requestPermissionIfNeeds(activeConferenceCall); + } + setRemoteVideoRenderer(activeConferenceCall); + if (isActive) { + mConferencePresenter.resumeCallVideoCapturer(); + } + } + + @Override + public void initConferenceStates(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall.isConference()) { + mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + } + + // on first cretate time it is Active. + isActive = true; + initConference(activeConferenceCall); + mConfParticipantsAdapter.setIsModerator(activeConferenceCall.isModerator()); + if (callActivity != null && !activeConferenceCall.isCallInProgress()) { + callActivity.getViewPager().setPagingEnabled(false); + } + mHandler.post(() -> initialConferenceStates(activeConferenceCall)); + } + + @Override + public void onConferenceMembersUpdate(ArrayList members) { + if (getActivity() == null || !isAdded()) return; + getActivity().runOnUiThread(() -> loadConferenceMembers(members)); + } + + @Override + public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { + if (getActivity() == null || !isAdded()) return; + getActivity().runOnUiThread(() -> { + setRemoteVideoRenderer(activeConferenceCall); + setConferenceState(activeConferenceCall); + }); + } + + @Override + public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) { + if (getActivity() == null || !isAdded()) return; + getActivity().runOnUiThread(() -> { + removeRemoteVideoRenderer(activeConferenceCall, trackId); + setConferenceState(activeConferenceCall); + }); + } + + @Override + public void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) { + if (getActivity() == null || !isAdded()) return; + mHandler.post(() -> { + setLocalVideoRenderer(activeConferenceCall); + setConferenceState(activeConferenceCall); + }); + } + + @Override + public void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) { + if (getActivity() == null || !isAdded()) return; + mHandler.post(() -> { + removeLocalVideoRenderer(activeConferenceCall); + setConferenceState(activeConferenceCall); + }); + } + + @Override + public void onScreenShareStateChanged(boolean isSharing) { + if (getActivity() == null || !isAdded()) return; + mHandler.post(() -> mConfParticipantsAdapter.notifyDataSetChanged()); + } + + @Override + public void onMicrophoneStateChanged(boolean isMuted) { + if (getActivity() == null || !isAdded()) return; + getActivity().runOnUiThread(() -> updateMicrophonState(isMuted)); + } + + @Override + public void onSpeakerStateChanged(boolean isSpeakerOn) { + if (getActivity() == null || !isAdded()) return; +// getActivity().runOnUiThread(() -> updateSpeakerState(isSpeakerOn)); + } + + @Override + public void onActiveSpeakersUpdate(String activeSpeakers) { + if (getActivity() == null || !isAdded()) return; + getActivity().runOnUiThread(() -> { + if (getActivity() == null || !isAdded() || !isActive) return; + if (StringUtils.isEmpty(activeSpeakers)) { +// activeSpeakerLayout.setVisibility(View.GONE); + } else { +// activeSpeakersText.setText(activeSpeakers); +// activeSpeakerLayout.setVisibility(View.VISIBLE); + } + + }); + } + + @Override + public void showInternetError() { + if (isAdded()) { + Toast.makeText(getActivity(), R.string.error_no_internet_connection, Toast.LENGTH_SHORT).show(); + } + } + + public boolean onBackPressed() { + return false; + } + + public void setCallActivity(CallActivity activity) { + callActivity = activity; + } + + public void setIsActive(boolean isActive) { + //this.isActive = isActive; + } + + public void setActiveState(boolean active) { + ActiveConferenceCall activeConferenceCall = mConferencePresenter.getActiveConference(); + isActive = active; + if (activeConferenceCall == null) return; + if (active) { + updateMicrophonState(activeConferenceCall.isMuted); + if (activeConferenceCall.isVideoEnabled) { + if (activeConferenceCall.mData.isOwnStreamActive) { + setLocalVideoRenderer(mConferencePresenter.getActiveConference()); + mConferencePresenter.resumeCallVideoCapturer(); + } + setRemoteVideoRenderer(mConferencePresenter.getActiveConference()); + setConferenceState(activeConferenceCall); + } + } else { + if (activeConferenceCall.isVideoEnabled) { + if (activeConferenceCall.mData.isOwnStreamActive) { + mConferencePresenter.pauseCallVideoCapturer(); + removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); + } + removeRemoteVideoRenderer(mConferencePresenter.getActiveConference()); + setConferenceState(activeConferenceCall); + } + } + } + + // Helpers + private void onClickMyIconItem(ConferenceListItem participant, Integer postion) { + if (postion >= participant.memberActions.size() || postion < 0) return; + switch (participant.memberActions.get(postion)) { +// case R.string.call_my_profile: +// mConferencePresenter.showProfile(participant); +// break; +// case R.string.call_leave_call): +// leaveCall(); +// break; + + default: + break; + } + } + + private void onClickOthersFriendIconItem(ConferenceListItem participant, Integer postion) { + if (postion >= participant.memberActions.size() || postion < 0) return; + switch (participant.memberActions.get(postion)) { + case R.string.call_view_profile: + //mConferencePresenter.showProfile(participant); + break; + case R.string.send_a_message: + mConferencePresenter.openChatWithParticipant(participant.phoneId); + break; + + case R.string.call_remove_from_call: + showRemoveParticipantConfirmation(participant); + break; + + case R.string.call_back: + mConferencePresenter.callBackPerson(participant); + break; + + case R.string.call_unmute: + unMuteParticipant(participant); + break; + case R.string.call_mute: + muteParticipant(participant); + break; + + case R.string.call_item_menu_stop_ss: + stopParticipantSS(participant); + break; + + case R.string.call_item_menu_stop_video: + stopParticipantVideo(participant); + break; + + default: + break; + } + } + + private void onClickOthersIconItem(ConferenceListItem participant, Integer postion) { + if (postion >= participant.memberActions.size() || postion < 0) return; + switch (participant.memberActions.get(postion)) { + case R.string.call_view_profile: + //mConferencePresenter.showProfile(participant); + break; + + case R.string.call_remove_from_call: + showRemoveParticipantConfirmation(participant); + break; + + case R.string.call_unmute: + unMuteParticipant(participant); + break; + case R.string.call_mute: + muteParticipant(participant); + break; + case R.string.call_item_menu_stop_ss: + stopParticipantSS(participant); + break; + case R.string.call_item_menu_stop_video: + stopParticipantVideo(participant); + break; + + default: + break; + } + } + + private void showRemoveParticipantConfirmation(ConferenceListItem participant) { + DialogFactory.createYesNoDialog(getActivity(), R.string.call_remove_participant_confirm, + (dialog, which) -> mConferencePresenter.removeFromCall(participant), + (dialog, which) -> dialog.dismiss()).show(); + } + + private void muteParticipant(ConferenceListItem item) { + mConferencePresenter.muteParticipant(item); + } + + private void unMuteParticipant(ConferenceListItem item) { + mConferencePresenter.unMuteParticipant(item.participantId); + } + + private void stopParticipantSS(ConferenceListItem item) { + mConferencePresenter.stopParticipantSS(item); + } + + private void stopParticipantVideo(ConferenceListItem item) { + mConferencePresenter.stopParticipantVideo(item); + } + + + private void showActionSheetDialog(ActionSheetDialog.MenuItemClickListener listener, String... items) { + ActionSheetDialog actionSheet = new ActionSheetDialog(getActivity()); + actionSheet.setCancelButtonTitle(getString(R.string.cancel)); + actionSheet.addItems(items); + actionSheet.setItemClickListener(listener); + actionSheet.setCancelableOnTouchMenuOutside(true); + actionSheet.showMenu(); + } + + private EglBase createRootEglBase() { + return ContextUtils.createRootEglBase(); + } + + private void requestPermissionIfNeeds(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall == null) return; + boolean enableVideo = (activeConferenceCall.mData.isOwnStreamActive + && activeConferenceCall.mInitialStartCapturer); + ArrayList permissions = getPermissionsForCall(enableVideo); + + String[] perms = new String[0]; + addDisposable(mRxPermissions.requestEachCombined(permissions.toArray(perms)) + .subscribe(permission -> { + + if (permission.granted) { + Timber.d("All (READ_PHONE_STATE, RECORD_AUDIO, CAMERA) permission(s) requests finished"); + } else if (!permission.shouldShowRequestPermissionRationale) { + ArrayList notGranted = getNotGrantedCallingPermissions(enableVideo); + if (notGranted.size() > 0) { + PermissionHelper.getInstance().showPermissionDialog(getContext(), + mConferencePresenter.getPermissionDialogListener(), + notGranted.toArray(perms)); + } + } + }, Timber::e, () -> Timber.d("Complete"))); + } + + private ArrayList getPermissionsForCall(boolean enabledVideo) { + ArrayList permissions; + if (enabledVideo) { + permissions = new ArrayList<>(Arrays.asList(Manifest.permission.READ_PHONE_STATE, + Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA)); + } else { + permissions = new ArrayList<>(Arrays.asList(Manifest.permission.READ_PHONE_STATE, + Manifest.permission.RECORD_AUDIO)); + } + + return permissions; + } + + private ArrayList getNotGrantedCallingPermissions(boolean enabledVideo) { + ArrayList permissions = getPermissionsForCall(enabledVideo); + ArrayList notGranted = new ArrayList<>(); + + for (String item : permissions) { + if (!mRxPermissions.isGranted(item)) { + notGranted.add(item); + } + } + + return notGranted; + } + + private boolean isCallActive(ActiveConferenceCall activeConferenceCall) { + return (activeConferenceCall != null + && activeConferenceCall.isCallInProgress() + && !activeConferenceCall.isRinging); + } + + private boolean shouldCallActionsActive(ActiveConferenceCall activeConferenceCall) { + return (activeConferenceCall != null + && isCallActive(activeConferenceCall) + && !activeConferenceCall.isWaiting()); + } + + + private void loadConferenceMembers(ArrayList members) { + mConfParticipantsAdapter.clear(); + mConfParticipantsAdapter.setItems(members); + } + + private void setRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall == null) return; + if (!activeConferenceCall.isConference()) return; + if (activeConferenceCall.mConference == null) return; + if (!activeConferenceCall.mConference.isConference()) return; + if (!activeConferenceCall.isVideoEnabled) return; + + mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + } + + private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall, String trackId) { + if (activeConferenceCall == null) return; + if (activeConferenceCall.mConference == null) return; + if (!activeConferenceCall.mConference.isConference()) return; + if (!activeConferenceCall.mConference.isRunning()) return; + if (!activeConferenceCall.isVideoEnabled) return; + + mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + } + + private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall == null) return; + mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + } + + private void setLocalVideoRenderer(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall == null) return; + if (activeConferenceCall.mConference == null) return; + if (!activeConferenceCall.isVideoEnabled) return; + + mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + } + + private void removeLocalVideoRenderer(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall == null) return; + if (activeConferenceCall.mConference == null) return; + if (!activeConferenceCall.mConference.isRunning()) return; + if (!activeConferenceCall.isVideoEnabled) return; + + mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + } + + private void setConferenceState(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall.isConference()) { + videoConference(activeConferenceCall); + } + } + + private void initConference(ActiveConferenceCall activeConferenceCall) { + setConferenceState(activeConferenceCall); + } + + @Override + public void updateMicrophonState(boolean isMuted) { + } + + @Override + public void closenConference() { + if (getActivity() == null) return; + getActivity().finish(); + } + + private void updateConferenceState(ActiveConferenceCall activeConferenceCall) { + initConference(activeConferenceCall); + } + + +} diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt index 92f0d45b9f..0165e4583d 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt @@ -68,7 +68,7 @@ class ScreenShareFragment : BaseFragment(), ScreenShareView { mScreenShareRemote?.layoutParams = layoutParams mZoomableFrameLayout.reset() mFrameLayout?.addView(mContainer) - remoteScreenShareState(mPresenter.activeConference.hasRemoteScreenShareTrack) + remoteScreenShareState(mPresenter.activeConference.mData.hasRemoteScreenShareTrack) } override fun onConfigurationChanged(newConfig: Configuration) { @@ -87,7 +87,7 @@ class ScreenShareFragment : BaseFragment(), ScreenShareView { } override fun initConferenceStates(activeConferenceCall: ActiveConferenceCall) { - if (activeConferenceCall.hasRemoteScreenShareTrack) { + if (activeConferenceCall.mData.hasRemoteScreenShareTrack) { setRemoteScreenShareRenderer(activeConferenceCall) } else { removeRemoteScreenShareRenderer(activeConferenceCall) @@ -121,7 +121,7 @@ class ScreenShareFragment : BaseFragment(), ScreenShareView { } private fun removeRemoteScreenShareRenderer(activeConferenceCall: ActiveConferenceCall?) { - removeRemoteScreenShareRenderer(activeConferenceCall, activeConferenceCall?.mRemoteSSTrackId) + removeRemoteScreenShareRenderer(activeConferenceCall, activeConferenceCall?.mData?.mRemoteSSTrackId) } private fun remoteScreenShareState(visible: Boolean) { @@ -148,10 +148,10 @@ class ScreenShareFragment : BaseFragment(), ScreenShareView { if (activeConferenceCall == null) return //if (activeConferenceCall.mCallType == ActiveCallBase.CallType.ConferenceCall) return if (activeConferenceCall.mConference == null) return - if (!activeConferenceCall.hasRemoteScreenShareTrack) return + if (!activeConferenceCall.mData.hasRemoteScreenShareTrack) return - if (StringUtils.isNotEmpty(activeConferenceCall.mRemoteSSTrackId)) { - setRemoteScreenShareRenderer(activeConferenceCall, activeConferenceCall.mRemoteSSTrackId) + if (StringUtils.isNotEmpty(activeConferenceCall.mData.mRemoteSSTrackId)) { + setRemoteScreenShareRenderer(activeConferenceCall, activeConferenceCall.mData.mRemoteSSTrackId) } remoteScreenShareState(activeConferenceCall, true) @@ -176,7 +176,7 @@ class ScreenShareFragment : BaseFragment(), ScreenShareView { mScreenShareRemote?.setEnableHardwareScaler(true) mScreenShareRemote?.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT, RendererCommon.ScalingType.SCALE_ASPECT_FIT) // duplicates to Presenter::attachView(view: ScreenShareView?) -> setRemoteScreenShareRenderer()... - //if (activeConferenceCall.hasRemoteScreenShareTrack) { + //if (activeConferenceCall.mData.hasRemoteScreenShareTrack) { // setRemoteScreenShareRenderer(activeConferenceCall) //} diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePageIndicator.java b/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePageIndicator.java index 1de72cc6a3..e3e48346fe 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePageIndicator.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePageIndicator.java @@ -374,6 +374,10 @@ public class CirclePageIndicator extends View implements ViewPager.OnPageChangeL invalidate(); } + public int getCurrentItem() { + return mCurrentPage; + } + public void notifyDataSetChanged() { invalidate(); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java b/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java new file mode 100644 index 0000000000..898677c168 --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java @@ -0,0 +1,118 @@ +package com.nynja.mobile.communicator.ui.views; + +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.annotation.ColorInt; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import org.jetbrains.annotations.NotNull; + +/** + * Created by Ergyun Syuleyman on 04/07/20. + */ +public class CirclePagerIndicatorDecoration extends RecyclerView.ItemDecoration { + + private final int indicatorHeight; + private final int indicatorItemPadding; + private final int radius; + + private final Paint inactivePaint = new Paint(); + private final Paint activePaint = new Paint(); + + public CirclePagerIndicatorDecoration(int radius, int padding, int indicatorHeight, + int colorInactive, int colorActive) { + float strokeWidth = Resources.getSystem().getDisplayMetrics().density * 2; + this.radius = radius; + inactivePaint.setStrokeCap(Paint.Cap.ROUND); + inactivePaint.setStrokeWidth(strokeWidth); + inactivePaint.setStyle(Paint.Style.STROKE); + inactivePaint.setAntiAlias(true); + inactivePaint.setColor(colorInactive); + + activePaint.setStrokeCap(Paint.Cap.ROUND); + activePaint.setStrokeWidth(strokeWidth); + activePaint.setStyle(Paint.Style.FILL); + activePaint.setAntiAlias(true); + activePaint.setColor(colorActive); + + this.indicatorItemPadding = padding; + this.indicatorHeight = indicatorHeight; + } + + @Override + public void onDrawOver(@NotNull Canvas c, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) { + super.onDrawOver(c, parent, state); + + final RecyclerView.Adapter adapter = parent.getAdapter(); + + if (adapter == null) { + return; + } + + int itemCount = adapter.getItemCount(); + + // center horizontally, calculate width and subtract half from center + float totalLength = this.radius * 2 * itemCount; + float paddingBetweenItems = Math.max(0, itemCount - 1) * indicatorItemPadding; + float indicatorTotalWidth = totalLength + paddingBetweenItems; + float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2f; + + // center vertically in the allotted space + float indicatorPosY = parent.getHeight() - indicatorHeight / 2f; + + drawInactiveDots(c, indicatorStartX, indicatorPosY, itemCount); + + final int activePosition; + + if (parent.getLayoutManager() instanceof GridLayoutManager) { + activePosition = ((GridLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); + } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { + activePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); + } else { + // not supported layout manager + return; + } + + if (activePosition == RecyclerView.NO_POSITION) { + return; + } + + // find offset of active page if the user is scrolling + final View activeChild = parent.getLayoutManager().findViewByPosition(activePosition); + if (activeChild == null) { + return; + } + + drawActiveDot(c, indicatorStartX, indicatorPosY, activePosition); + } + + private void drawInactiveDots(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) { + // width of item indicator including padding + final float itemWidth = this.radius * 2 + indicatorItemPadding; + + float start = indicatorStartX + radius; + for (int i = 0; i < itemCount; i++) { + c.drawCircle(start, indicatorPosY, radius, inactivePaint); + start += itemWidth; + } + } + + private void drawActiveDot(Canvas c, float indicatorStartX, float indicatorPosY, + int highlightPosition) { + // width of item indicator including padding + final float itemWidth = this.radius * 2 + indicatorItemPadding; + float highlightStart = indicatorStartX + radius + itemWidth * highlightPosition; + c.drawCircle(highlightStart, indicatorPosY, radius, activePaint); + } + + @Override + public void getItemOffsets(@NotNull Rect outRect, @NotNull View view, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + outRect.bottom = indicatorHeight; + } +} diff --git a/app/src/main/res/layout/activity_rv_call.xml b/app/src/main/res/layout/activity_rv_call.xml new file mode 100644 index 0000000000..26a98b0d3c --- /dev/null +++ b/app/src/main/res/layout/activity_rv_call.xml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/app/src/main/res/layout/fragment_conference_video_call.xml b/app/src/main/res/layout/fragment_conference_video_call.xml new file mode 100644 index 0000000000..260e83a942 --- /dev/null +++ b/app/src/main/res/layout/fragment_conference_video_call.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/app/src/main/res/layout/li_conference_video.xml b/app/src/main/res/layout/li_conference_video.xml new file mode 100644 index 0000000000..fbd9446dab --- /dev/null +++ b/app/src/main/res/layout/li_conference_video.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index ec7e8a434e..28d7133a14 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -260,4 +260,9 @@ 30dp + + 12dp + 5dp + 8dp + -- GitLab From f68ae0200c6b472d7df47a9be0607abc7dda6656 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Fri, 24 Apr 2020 03:06:58 +0300 Subject: [PATCH 02/21] minor stability fixes for conference video calls --- app/build.gradle | 2 +- .../data/sdk/calls/ConferenceListItem.java | 7 + .../mvp/presenters/ChatPresenter.java | 7 +- .../presenters/ConferenceVideoPresenter.java | 31 ++-- .../mvp/presenters/MainActivityPresenter.kt | 10 +- .../ui/activities/calls/CallActivity.java | 6 +- .../ui/adapters/ChatLanguageAdapter.kt | 2 +- .../adapters/ChooseUserVerticalAdapter.java | 2 +- .../ui/adapters/ContactsAdapter.java | 2 +- .../ui/adapters/CountryPickerAdapter.java | 2 +- .../ui/adapters/InviteFriendsAdapter.java | 2 +- .../ui/adapters/NynjaContactsAdapter.java | 2 +- .../ui/adapters/ShareContactsAdapter.java | 2 +- .../ui/adapters/TimeZoneAdapter.java | 2 +- .../conference/ActiveCallPagerAdapter.java | 59 +++--- .../conference/ConferenceVideoAdapter.java | 22 ++- .../conference/ConferenceVideoItemVh.java | 89 ++++++--- .../communicator/ui/base/BaseAdapter.java | 8 +- .../mobile/communicator/ui/base/BaseVH.java | 11 +- .../ui/fragments/chats/ChatFragment.java | 2 +- .../conference/CallTapToSpeakFragment.java | 4 +- .../conference/ConferenceCallFragment.java | 7 + .../conference/ConferenceVideoFragment.java | 174 ++++++++---------- .../communicator/ui/wheel/entity/Factory.java | 14 +- .../main/res/layout/li_conference_video.xml | 20 +- 25 files changed, 265 insertions(+), 224 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 333dc8960f..892b836862 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -678,7 +678,7 @@ dependencies { // Conference, Calls mobile SDK //implementation 'com.nynja.sdk:NynjaSdk:1.20.6@aar' - implementation(name: 'NynjaSdk-1.20.5', ext: 'aar') + implementation(name: 'NynjaSdk-1.20.7', ext: 'aar') //ExoPlayer implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6' diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java index 3abe899349..671c2e41a3 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java @@ -39,6 +39,7 @@ public class ConferenceListItem { public boolean hasScreen; public boolean isVideoPaused; public boolean isScreenPaused; + public int isTrackActive; protected ConferenceListItem() { phoneId = ""; @@ -53,6 +54,7 @@ public class ConferenceListItem { hasScreen = false; isVideoPaused = false; isScreenPaused = false; + isTrackActive = 0; } protected ConferenceListItem(ConferenceItemType type, String phoneId, String memberId, @@ -73,6 +75,7 @@ public class ConferenceListItem { this.hasScreen = false; this.isVideoPaused = false; this.isScreenPaused = false; + isTrackActive = 0; } protected ConferenceListItem(ConferenceItemType type, NYNCallParticipant participant, @@ -93,6 +96,7 @@ public class ConferenceListItem { this.hasScreen = participant.hasScreen(); this.isVideoPaused = participant.isVideoPaused(); this.isScreenPaused = participant.isScreenPaused(); + this.isTrackActive = 0; } public void update(ConferenceListItem participant) { @@ -105,6 +109,9 @@ public class ConferenceListItem { this.hasScreen = participant.hasScreen; this.isVideoPaused = participant.isVideoPaused; this.isScreenPaused = participant.isScreenPaused; + this.isTrackActive = 0; + this.isMe = participant.isMe; + this.isMuted = participant.isMuted; } private void setActions(ArrayList itemActions) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java index 2a0f5df0f8..992f0a9c1e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java @@ -126,6 +126,7 @@ import timber.log.Timber; import static com.nynja.mobile.communicator.data.FragmentTransferObject.Type.OpenAudioConferenceCreate; import static com.nynja.mobile.communicator.data.FragmentTransferObject.Type.OpenChooseUsersAdminAddUsersEditMode; +import static com.nynja.mobile.communicator.data.FragmentTransferObject.Type.OpenVideoConferenceCreate; import static com.nynja.mobile.communicator.data.models.events.local.Event.Type; import static com.nynja.mobile.communicator.mvp.presenters.ChatLanguagePresenter.LANGUAGE_LIST_REQUEST_CODE; import static com.nynja.mobile.communicator.utils.Consts.LIMIT_MESSAGE_TO_CHAT; @@ -2287,9 +2288,9 @@ public class ChatPresenter extends BaseChatPresenter { return; } if (mRoom.isGroupOrCalllChat()) { - getViewState().showAlertNotSupportedFeature(); -// FragmentTransferObject fto = new FragmentTransferObject(null, mRoom, OpenVideoConferenceCreate); -// mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto); + //getViewState().showAlertNotSupportedFeature(); + FragmentTransferObject fto = new FragmentTransferObject(null, mRoom, OpenVideoConferenceCreate); + mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto); } else { mDataManager.startCall(new ContactModel(mRoom.getOnlyMembers().get(0)), true); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java index e52fdbcbe5..58769f6d0e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -11,14 +11,11 @@ import com.nynja.mobile.communicator.data.sdk.calls.ConferenceSDKListener; import com.nynja.mobile.communicator.mvp.view.ConferenceVideoView; import com.nynja.sdk.NYNCallParticipant; -import org.jetbrains.annotations.NotNull; - import java.util.ArrayList; @InjectViewState public class ConferenceVideoPresenter extends ConferenceSDKPresenter implements ConferenceSDKListener { - private String mParticipantPhoneId; @Override protected void onFirstViewAttach() { @@ -27,7 +24,6 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter members = new ArrayList<>(); - if (activeConferenceCall.mData.mParticipantArray != null) { - for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { - NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); - if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { - members.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); - } - } - } + ArrayList members = getConferenceVideoMembers(activeConferenceCall); getViewState().onConferenceMembersUpdate(members); } @@ -189,9 +176,19 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { + ArrayList members = new ArrayList<>(); + if (activeConferenceCall == null) return members; + if (activeConferenceCall.mData.mParticipantArray != null) { + for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); + if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { + members.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); + } + } + } + return members; } + } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt index e36d21205d..3ba4b264bc 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt @@ -366,11 +366,11 @@ class MainActivityPresenter : ConferenceSDKPresenter() { } HomeActions.VideoCallAction -> { - viewState.showAlertNotSupportedFeature() -// val fto = FragmentTransferObject(null, -// FragmentTransferObject.Type.OpenGroupVideoConferenceCreate, -// null) -// mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto) +// viewState.showAlertNotSupportedFeature() + val fto = FragmentTransferObject(null, + FragmentTransferObject.Type.OpenGroupVideoConferenceCreate, + null) + mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto) viewState.closeWheel() } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java index f904202ade..00c1bad834 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java @@ -237,8 +237,10 @@ public class CallActivity extends BaseActivity implements CallActivityView { @Override public void initConferenceStates(ActiveConferenceCall activeConferenceCall) { - if (activeConferenceCall != null && activeConferenceCall.mData.hasRemoteScreenShareTrack) { - showShareScreen(true); + if (activeConferenceCall == null) return; + if (mPagerAdapter != null) { + mPagerAdapter.initFlags(activeConferenceCall.mData.hasRemoteScreenShareTrack, + (activeConferenceCall.mData.hasRemoteVideoTrack() || activeConferenceCall.mData.isOwnStreamActive)); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChatLanguageAdapter.kt b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChatLanguageAdapter.kt index fa8edda924..7425f187a6 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChatLanguageAdapter.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChatLanguageAdapter.kt @@ -38,7 +38,7 @@ class ChatLanguageAdapter(list: List, val onItemClickListener: On } override fun onBindHeaderViewHolder(holder: CountryPickerLetterViewHolder, position: Int) { - holder.bind(getCellChar(position).toString()) + holder.bind(getCellChar(position).toString(), position) } private fun getCellChar(position: Int): Char { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChooseUserVerticalAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChooseUserVerticalAdapter.java index 1fdc9cc31d..1a7a4f64ed 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChooseUserVerticalAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ChooseUserVerticalAdapter.java @@ -71,7 +71,7 @@ public class ChooseUserVerticalAdapter extends BaseSelectableModelAdapter contacts) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ContactsAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ContactsAdapter.java index 355bf7891b..1620eccd6e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ContactsAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/ContactsAdapter.java @@ -46,7 +46,7 @@ public class ContactsAdapter extends BaseAdapter implem } @Override public void onBindHeaderViewHolder(ContactHeaderVh holder, int position) { - holder.bind(String.valueOf(getCellChar(position))); + holder.bind(String.valueOf(getCellChar(position)), position); } private char getCellChar(int position) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/CountryPickerAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/CountryPickerAdapter.java index 147cd34646..660b7389c4 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/CountryPickerAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/CountryPickerAdapter.java @@ -50,7 +50,7 @@ public class CountryPickerAdapter extends BaseAdapter> exten return (T) viewHolder; } + @Override + public int getItemViewType(int position) { + return super.getItemViewType(position); + } + @Override public void onViewAttachedToWindow(@NonNull T holder) { - ((ConferenceVideoItemVh)holder).initVideoCallRenderer(); - ConferenceVideoModule.getInstance().setVideoRendererForTrack(((ConferenceVideoItemVh)holder).getVideoFeed(), - ConferenceVideoModule.getInstance().getTrackIdByParticipantId(((ConferenceVideoItemVh)holder).getItem().participantId), - ((ConferenceVideoItemVh)holder).getItem().isMe); + super.onViewAttachedToWindow(holder); + ((ConferenceVideoItemVh) holder).onViewAttachedToWindow(); } @Override public void onViewDetachedFromWindow(@NonNull T holder) { - ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, - ConferenceVideoModule.getInstance().getTrackIdByParticipantId(((ConferenceVideoItemVh)holder).getItem().participantId), - ((ConferenceVideoItemVh)holder).getItem().isMe); - ((ConferenceVideoItemVh)holder).releaseVideoCallRrenderers(); + super.onViewDetachedFromWindow(holder); + ((ConferenceVideoItemVh) holder).onViewDetachedFromWindow(); } + @Override + public void onViewRecycled(@NonNull T holder) { + super.onViewRecycled(holder); + ((ConferenceVideoItemVh)holder).onViewRecycled(); + } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index d9b2d2648c..e07a8a7344 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -1,15 +1,18 @@ package com.nynja.mobile.communicator.ui.adapters.viewholders.conference; +import android.support.annotation.NonNull; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.nynja.mobile.communicator.R; +import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; import com.nynja.mobile.communicator.ui.base.BaseVH; import com.nynja.mobile.communicator.ui.views.CheckableImageView; +import com.nynja.mobile.communicator.utils.StringUtils; import org.webrtc.RendererCommon; import org.webrtc.SurfaceViewRenderer; @@ -55,6 +58,15 @@ public class ConferenceVideoItemVh extends BaseVH { this.mItem = item; mSS.setAutoToggle(false); mActiveVideo.setAutoToggle(false); + mName.setText(item.name); + itemView.setOnClickListener(null); + itemView.setOnLongClickListener(null); + if (mListener != null) { + item.initActions(mIsModerator); + itemView.setOnClickListener(v -> mListener.onItemClick(item, mPosition)); + itemView.setOnLongClickListener(v -> mListener.onItemLongClick(item, mPosition)); + } + itemView.setTag(this); if (item.type == ConferenceListItem.ConferenceItemType.Plus) { // mPhoto.setImageResource(R.drawable.v_add_member_voice_call); } else { @@ -64,41 +76,46 @@ public class ConferenceVideoItemVh extends BaseVH { } else { // in Conference setupInConference(item); + onViewAttachedToWindow(); } } - mName.setText(item.name); - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - if (mListener != null) { - item.initActions(mIsModerator); - itemView.setOnClickListener(v -> mListener.onItemClick(item, -1)); - itemView.setOnLongClickListener(v -> mListener.onItemLongClick(item, -1)); - } } - @Synchronized - public void initVideoCallRenderer() { - if (mIsRenderersInitialized) return; - try { - mVideoFeed.init(createRootEglBase().getEglBaseContext(), null); - mVideoFeed.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); - mVideoFeed.setEnableHardwareScaler(true); - mIsRenderersInitialized = true; - } catch (Exception ex) { - Timber.e(ex); + public void onViewAttachedToWindow() { + if (mItem == null) return; + initVideoCallRenderer(); + if (mItem.isTrackActive == 1) return; + String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); + if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { + mItem.isTrackActive = 1; + ConferenceVideoModule.getInstance().setVideoRendererForTrack(mVideoFeed, trackId, mItem.isMe); } } - @Synchronized - public void releaseVideoCallRrenderers() { - if (!mIsRenderersInitialized) return; - if (mVideoFeed != null) { - mVideoFeed.release(); + public void onViewDetachedFromWindow() { + if (mItem == null) return; + if (mItem.isTrackActive == 0) return; + String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); + if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { + ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, mItem.isMe); + mItem.isTrackActive = 0; } - mIsRenderersInitialized = false; } + public void onViewRecycled() { + onViewDetachedFromWindow(); + releaseVideoCallRrenderers(); + } + + @Override + public void onUnbind() { + super.onUnbind(); + onViewRecycled(); + } + + ///////////////////////////////////////////////////////////////////////////////////// + // Internal Helpers private void setupInConference(ConferenceListItem item) { initVideoCallRenderer(); if (item.participantId == null || !item.isActive) { @@ -157,7 +174,7 @@ public class ConferenceVideoItemVh extends BaseVH { } } - public void showHideItemView(boolean show) { + private void showHideItemView(boolean show) { if (show) { itemView.setVisibility(View.VISIBLE); } else { @@ -166,4 +183,26 @@ public class ConferenceVideoItemVh extends BaseVH { } + @Synchronized + private void initVideoCallRenderer() { + if (mIsRenderersInitialized) return; + try { + mVideoFeed.init(createRootEglBase().getEglBaseContext(), null); + mVideoFeed.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); + mVideoFeed.setEnableHardwareScaler(true); + mIsRenderersInitialized = true; + } catch (Exception ex) { + Timber.e(ex); + } + } + + @Synchronized + private void releaseVideoCallRrenderers() { + if (!mIsRenderersInitialized) return; + if (mVideoFeed != null) { + mVideoFeed.release(); + } + mIsRenderersInitialized = false; + } + } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java index 89da948d1e..fe33b3d069 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java @@ -35,7 +35,7 @@ public abstract class BaseAdapter> extends RecyclerVie } @Override public void onBindViewHolder(Vh holder, int position) { - holder.bind(getItem(position)); + holder.bind(getItem(position), position); } @Override public int getItemCount() { @@ -164,10 +164,4 @@ public abstract class BaseAdapter> extends RecyclerVie } } } - - @Override public void onViewAttachedToWindow(@NonNull Vh holder) { - } - - @Override public void onViewDetachedFromWindow(@NonNull Vh holder) { - } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java index e356e2efe5..9ff3b5270f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java @@ -26,6 +26,7 @@ public abstract class BaseVH extends RecyclerView.ViewHolder { private Context mContext; private Unbinder mUnbinder; + protected int mPosition = -1; public BaseVH(ViewGroup parent, @LayoutRes int layoutId) { this(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false)); @@ -37,8 +38,12 @@ public abstract class BaseVH extends RecyclerView.ViewHolder { mUnbinder = ButterKnife.bind(this, itemView); } - public void bind(I item) { - if (mUnbinder != null) mUnbinder.unbind(); + public void bind(I item, int position) { + if (mUnbinder != null) { + onUnbind(); + mUnbinder.unbind(); + } + mPosition = position; mUnbinder = ButterKnife.bind(this, itemView); setData(item); } @@ -49,5 +54,7 @@ public abstract class BaseVH extends RecyclerView.ViewHolder { public abstract void setData(I item); + public void onUnbind() {} + public void onClick() {} } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/chats/ChatFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/chats/ChatFragment.java index eb2e0d6b9c..d502309d40 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/chats/ChatFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/chats/ChatFragment.java @@ -413,7 +413,7 @@ public class ChatFragment extends BaseChatFragment implements ChatMvpView, mPresenter.startAudioCall(); updateHeaderActionButtons(); }); - if (!mRoom.isGroupChat() && !mRoom.isChannel()) { + if (!mRoom.isChannel()) { mNynjaHeaderView.showVideoCallButton(); mNynjaHeaderView.subscribeToVideoButtonEvent(v -> { mPresenter.startVideoCall(); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java index 49cfa60f9d..d69f39b90e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/CallTapToSpeakFragment.java @@ -393,10 +393,10 @@ public class CallTapToSpeakFragment extends BaseFragment if (isBluetoothHeadsetConnected()) { onAudioRouteChange(audioRouteType); } else { - speaker.post(() -> { + if (speaker != null) { speaker.setImageResource(R.drawable.speaker_selector); speaker.setChecked(isSpeakerOn); - }); + }; } speaker.setAutoToggle(!isBluetoothHeadsetConnected()); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java index c2bc814d5c..1eae95af24 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java @@ -745,6 +745,13 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, if (activeConferenceCall.isConference()) { mConferencePresenter.loadConferenceParticipants(activeConferenceCall); addCallerLayout.setEnabled(activeConferenceCall.isModerator()); + if (activeConferenceCall.mInitialStartCapturer && + activeConferenceCall.mData.isOwnStreamActive) { + mHandler.postDelayed(() ->{ + activeConferenceCall.mConference.startCamera(); + }, Consts.DELAY_200); + activeConferenceCall.mInitialStartCapturer = false; + } } else { mConferencePresenter.loadUser(activeConferenceCall); // TODO: update state after P2P upgrade to Group call support implemented !!!! diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 2598b35b66..c8cfb37896 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -1,15 +1,15 @@ package com.nynja.mobile.communicator.ui.fragments.conference; -import android.Manifest; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.LinearSnapHelper; import android.support.v7.widget.PagerSnapHelper; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SnapHelper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -25,17 +25,16 @@ import com.nynja.mobile.communicator.mvp.presenters.ConferenceVideoPresenter; import com.nynja.mobile.communicator.mvp.view.ConferenceVideoView; import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; import com.nynja.mobile.communicator.ui.adapters.conference.ConferenceVideoAdapter; +import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceVideoItemVh; import com.nynja.mobile.communicator.ui.base.BaseFragment; import com.nynja.mobile.communicator.utils.ActionSheetDialog; import com.nynja.mobile.communicator.utils.DialogFactory; -import com.nynja.mobile.communicator.utils.PermissionHelper; import com.nynja.mobile.communicator.utils.StringUtils; import org.webrtc.ContextUtils; import org.webrtc.EglBase; import java.util.ArrayList; -import java.util.Arrays; import butterknife.BindView; import timber.log.Timber; @@ -69,8 +68,10 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV @Override public void onDestroyView() { + mRecyclerView.clearOnChildAttachStateChangeListeners(); + mRecyclerView.clearOnScrollListeners(); mConfParticipantsAdapter.releaseVideoCallRrenderers(); - ConferenceVideoModule.getInstance().setCurrentActiveCall(null); + mConfParticipantsAdapter = null; super.onDestroyView(); } @@ -83,6 +84,8 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV @Override public void onDestroy() { super.onDestroy(); + ConferenceVideoModule.getInstance().setCurrentActiveCall(null); + ContextUtils.releaseRootEglBase(); } @@ -96,7 +99,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV public void onPause() { mConferencePresenter.pauseCallVideoCapturer(); removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); - removeRemoteVideoRenderer(mConferencePresenter.getActiveConference()); + removeRemoteVideoRenderers(mConferencePresenter.getActiveConference()); isActive = false; super.onPause(); } @@ -130,9 +133,27 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV // itemAnimator.setSupportsChangeAnimations(false); // mRecyclerView.setItemAnimator(itemAnimator); mRecyclerView.setNestedScrollingEnabled(false); -// mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); - GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),2, LinearLayoutManager.HORIZONTAL, false); -// gridLayoutManager.setItemPrefetchEnabled(true); + GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),2); + gridLayoutManager.setSpanCount(2); + gridLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + gridLayoutManager.setReverseLayout(false); +// gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { +// @Override +// public int getSpanSize(int position) { +// // 5 is the sum of items in one repeated section +// switch (position % 4) { +// case 0: +// case 2: +// return 2; +// // next 3 items span 2 columns each +// case 1: +// case 3: +// return 1; +// } +// throw new IllegalStateException("internal error"); +// } +// }); + gridLayoutManager.setItemPrefetchEnabled(true); mRecyclerView.setLayoutManager(gridLayoutManager); mRecyclerView.setHasFixedSize(true); mRecyclerView.setAdapter(mConfParticipantsAdapter); @@ -142,6 +163,36 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV // R.color.wheel_unselected_corner_bg, // R.color.colorAccent)); // new PagerSnapHelper().attachToRecyclerView(mRecyclerView); + SnapHelper snapHelper = new LinearSnapHelper(); + snapHelper.attachToRecyclerView(mRecyclerView); + + mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() { + @Override + public void onChildViewAttachedToWindow(View view) { + ConferenceVideoItemVh holder = (ConferenceVideoItemVh)getChildViewHolderInternal(view); + if (holder != null) { + //holder.onViewAttachedToWindow(); + } + } + + @Override + public void onChildViewDetachedFromWindow(View view) { + ConferenceVideoItemVh holder = (ConferenceVideoItemVh)getChildViewHolderInternal(view); + if (holder != null) { + //holder.onViewDetachedFromWindow(); + } + } + }); + mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + } + }); + } + + private RecyclerView.ViewHolder getChildViewHolderInternal(View child) { + return child == null ? null : (RecyclerView.ViewHolder)(child.getTag()); } protected void updateRendererUI(ActiveConferenceCall activeConferenceCall) { @@ -153,17 +204,9 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV protected void videoConference(ActiveConferenceCall activeConferenceCall) { if (getActivity() == null || !isAdded()) return; updateRendererUI(activeConferenceCall); - int visible = isActive ? View.VISIBLE : View.GONE; - callActivity.getPageIndicator().setVisibility(visible); - if (activeConferenceCall != null && activeConferenceCall.isConference()) { - // TODO: for later Conference calls video support. - } } protected void initialConferenceStates(ActiveConferenceCall activeConferenceCall) { - if (activeConferenceCall.isOutgoingCall) { - requestPermissionIfNeeds(activeConferenceCall); - } setRemoteVideoRenderer(activeConferenceCall); if (isActive) { mConferencePresenter.resumeCallVideoCapturer(); @@ -176,13 +219,10 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV mConferencePresenter.loadConferenceParticipants(activeConferenceCall); } - // on first cretate time it is Active. + // on first create time it is Active. isActive = true; - initConference(activeConferenceCall); mConfParticipantsAdapter.setIsModerator(activeConferenceCall.isModerator()); - if (callActivity != null && !activeConferenceCall.isCallInProgress()) { - callActivity.getViewPager().setPagingEnabled(false); - } + setConferenceState(activeConferenceCall); mHandler.post(() -> initialConferenceStates(activeConferenceCall)); } @@ -300,7 +340,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV mConferencePresenter.pauseCallVideoCapturer(); removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); } - removeRemoteVideoRenderer(mConferencePresenter.getActiveConference()); + removeRemoteVideoRenderers(mConferencePresenter.getActiveConference()); setConferenceState(activeConferenceCall); } } @@ -425,71 +465,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV return ContextUtils.createRootEglBase(); } - private void requestPermissionIfNeeds(ActiveConferenceCall activeConferenceCall) { - if (activeConferenceCall == null) return; - boolean enableVideo = (activeConferenceCall.mData.isOwnStreamActive - && activeConferenceCall.mInitialStartCapturer); - ArrayList permissions = getPermissionsForCall(enableVideo); - - String[] perms = new String[0]; - addDisposable(mRxPermissions.requestEachCombined(permissions.toArray(perms)) - .subscribe(permission -> { - - if (permission.granted) { - Timber.d("All (READ_PHONE_STATE, RECORD_AUDIO, CAMERA) permission(s) requests finished"); - } else if (!permission.shouldShowRequestPermissionRationale) { - ArrayList notGranted = getNotGrantedCallingPermissions(enableVideo); - if (notGranted.size() > 0) { - PermissionHelper.getInstance().showPermissionDialog(getContext(), - mConferencePresenter.getPermissionDialogListener(), - notGranted.toArray(perms)); - } - } - }, Timber::e, () -> Timber.d("Complete"))); - } - - private ArrayList getPermissionsForCall(boolean enabledVideo) { - ArrayList permissions; - if (enabledVideo) { - permissions = new ArrayList<>(Arrays.asList(Manifest.permission.READ_PHONE_STATE, - Manifest.permission.RECORD_AUDIO, - Manifest.permission.CAMERA)); - } else { - permissions = new ArrayList<>(Arrays.asList(Manifest.permission.READ_PHONE_STATE, - Manifest.permission.RECORD_AUDIO)); - } - - return permissions; - } - - private ArrayList getNotGrantedCallingPermissions(boolean enabledVideo) { - ArrayList permissions = getPermissionsForCall(enabledVideo); - ArrayList notGranted = new ArrayList<>(); - - for (String item : permissions) { - if (!mRxPermissions.isGranted(item)) { - notGranted.add(item); - } - } - - return notGranted; - } - - private boolean isCallActive(ActiveConferenceCall activeConferenceCall) { - return (activeConferenceCall != null - && activeConferenceCall.isCallInProgress() - && !activeConferenceCall.isRinging); - } - - private boolean shouldCallActionsActive(ActiveConferenceCall activeConferenceCall) { - return (activeConferenceCall != null - && isCallActive(activeConferenceCall) - && !activeConferenceCall.isWaiting()); - } - - private void loadConferenceMembers(ArrayList members) { - mConfParticipantsAdapter.clear(); mConfParticipantsAdapter.setItems(members); } @@ -510,12 +486,22 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (!activeConferenceCall.mConference.isRunning()) return; if (!activeConferenceCall.isVideoEnabled) return; - mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + if (StringUtils.isNotEmpty(trackId)) { + ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, false); + } + + mConfParticipantsAdapter.notifyDataSetChanged(); } - private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall) { + private void removeRemoteVideoRenderers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; - mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + ArrayList members = mConferencePresenter.getConferenceVideoMembers(activeConferenceCall); + for (ConferenceListItem item : members) { + String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(item.participantId); + if (StringUtils.isNotEmpty(trackId) || item.isMe) { + ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, item.isMe); + } + } } private void setLocalVideoRenderer(ActiveConferenceCall activeConferenceCall) { @@ -541,10 +527,6 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } } - private void initConference(ActiveConferenceCall activeConferenceCall) { - setConferenceState(activeConferenceCall); - } - @Override public void updateMicrophonState(boolean isMuted) { } @@ -555,9 +537,5 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV getActivity().finish(); } - private void updateConferenceState(ActiveConferenceCall activeConferenceCall) { - initConference(activeConferenceCall); - } - } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/wheel/entity/Factory.java b/app/src/main/java/com/nynja/mobile/communicator/ui/wheel/entity/Factory.java index 6d865403a9..047e26a48a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/wheel/entity/Factory.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/wheel/entity/Factory.java @@ -541,13 +541,13 @@ public class Factory { .enableBgColor(isSubItems ? R.color.wheel_unselected_corner_bg : R.color.intercom_full_transparent_full_black) .build()); - // add(SimpleWheelItem.newBuilder() - // .wheelAction(HomeActions.VideoCallAction) - // .text(R.string.video_call) - // .icons(R.drawable.ic_new_video_call_vector, 0) - // .enableBgColor(isSubItems ? R.color.wheel_unselected_corner_bg : R.color.intercom_full_transparent_full_black) - // .build()); - // + add(SimpleWheelItem.newBuilder() + .wheelAction(HomeActions.VideoCallAction) + .text(R.string.video_call) + .icons(R.drawable.ic_new_video_call_vector, 0) + .enableBgColor(isSubItems ? R.color.wheel_unselected_corner_bg : R.color.intercom_full_transparent_full_black) + .build()); + add(SimpleWheelItem.newBuilder() .wheelAction(HomeActions.CallHistory) diff --git a/app/src/main/res/layout/li_conference_video.xml b/app/src/main/res/layout/li_conference_video.xml index fbd9446dab..9b7652d616 100644 --- a/app/src/main/res/layout/li_conference_video.xml +++ b/app/src/main/res/layout/li_conference_video.xml @@ -1,13 +1,12 @@ - + android:gravity="center"> Date: Fri, 24 Apr 2020 03:29:50 +0300 Subject: [PATCH 03/21] -local video feed m irrored in conference video call --- .../adapters/viewholders/conference/ConferenceVideoItemVh.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index e07a8a7344..6b921b3355 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -190,6 +190,9 @@ public class ConferenceVideoItemVh extends BaseVH { mVideoFeed.init(createRootEglBase().getEglBaseContext(), null); mVideoFeed.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); mVideoFeed.setEnableHardwareScaler(true); + if (mItem != null && mItem.isMe) { + mVideoFeed.setMirror(true); + } mIsRenderersInitialized = true; } catch (Exception ex) { Timber.e(ex); -- GitLab From 20dd723ac327f61b45a7f99c426f3bbdfdee20fd Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Fri, 24 Apr 2020 14:39:02 +0300 Subject: [PATCH 04/21] -changed call views order -fixed some memory leaks and craches --- .../data/sdk/calls/ConferenceSDKModule.java | 16 +++-- .../ui/activities/calls/CallActivity.java | 10 ++- .../conference/ActiveCallPagerAdapter.java | 69 +++++++------------ .../conference/ConferenceCallFragment.java | 8 ++- .../conference/ScreenShareFragment.kt | 6 ++ 5 files changed, 53 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index 89583ed5b7..ea97ab595f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -374,8 +374,10 @@ public class ConferenceSDKModule extends BaseSDKModule { stopCallAllActiions(); clearConference(); if (fireEvent) { - for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { - conferenceSDKListener.conferenceEnded(); + synchronized (mConferenceSDKListener) { + for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { + conferenceSDKListener.conferenceEnded(); + } } } if (delayed) { @@ -393,8 +395,10 @@ public class ConferenceSDKModule extends BaseSDKModule { mConferenceDetails = null; isSpeakerPhoneForced = false; if (fireEvent) { - for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { - conferenceSDKListener.conferenceEnded(); + synchronized (mConferenceSDKListener) { + for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { + conferenceSDKListener.conferenceEnded(); + } } } if (delayed) { @@ -3214,7 +3218,9 @@ public class ConferenceSDKModule extends BaseSDKModule { activeConferenceCall.mConference.stopCamera(); if (mActiveConference.isConference()) { new Handler(Looper.getMainLooper()).post(() -> { - mActiveConference.mConference.setLocalVideoRenderer(null); + if (mActiveConference != null && mActiveConference.mConference != null) { + mActiveConference.mConference.setLocalVideoRenderer(null); + } }); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java index 00c1bad834..b52eaee87a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java @@ -150,6 +150,8 @@ public class CallActivity extends BaseActivity implements CallActivityView { } protected void showShareScreen(boolean show) { + int currentItem = mIndicator.getCurrentItem(); + ActiveCallPagerAdapter.CallPages page = mPagerAdapter.getPageByPosition(currentItem); synchronized (mPagerAdapter) { mViewPager.removeOnPageChangeListener(mOnPageChangeListener); mViewPager.setAdapter(null); @@ -164,7 +166,7 @@ public class CallActivity extends BaseActivity implements CallActivityView { } // addPageViewListener(); // set to position 1 - mIndicator.setViewPager(mViewPager, ActiveCallPagerAdapter.CallPages.ShareScreenFragment.ordinal()); + mIndicator.setViewPager(mViewPager, mPagerAdapter.getFragmentPositionByType(page)); mIndicator.notifyDataSetChanged(); } @@ -176,9 +178,11 @@ public class CallActivity extends BaseActivity implements CallActivityView { @Override protected void onDestroy() { unregisterReceiver(mBluetoothReceiver); - releaseWakeLockActivity(); - mViewPager.removeAllViews(); mPagerAdapter.reset(); + mViewPager.removeAllViews(); + ContextUtils.releaseRootEglBase(); + ContextUtils.releaseSSEglBase(); + releaseWakeLockActivity(); super.onDestroy(); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java index 57633a53c7..e44338e767 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java @@ -35,9 +35,10 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { public enum CallPages { CallPageTapToSpeak, ShareScreenFragment, - ConferenceVideoFragment, - CallPageActiveCallFragment - } + CallPageActiveCallFragment, + ConferenceVideoFragment + + } public ActiveCallPagerAdapter(CallActivity callActivity) { super(callActivity); @@ -68,29 +69,6 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { @Synchronized private void preparePages() { -// callPages.clear(); -// for (CallPages callPage : CallPages.values()) { -// if (callPage == CallPages.ShareScreenFragment && !isScreenShareActive) { -// final String itemId = makeFragmentId(getItemId(callPage.ordinal())); -// BaseFragment fragment = mAdapterPages.get(itemId); -// if (fragment != null) { -// destroyView(fragment); -// } -// mAdapterPages.remove(itemId); -// continue; -// } -// if (callPage == CallPages.ConferenceVideoFragment && !isConferenceVideoActive) { -// final String itemId = makeFragmentId(getItemId(callPage.ordinal())); -// BaseFragment fragment = mAdapterPages.get(itemId); -// if (fragment != null) { -// destroyView(fragment); -// } -// mAdapterPages.remove(itemId); -// continue; -// } -// -// callPages.add(callPage); -// } for (CallPages callPage : callPages) { if (callPage == CallPages.ShareScreenFragment && !isScreenShareActive) { @@ -101,14 +79,14 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { } mAdapterPages.remove(itemId); } - if (callPage == CallPages.ConferenceVideoFragment && !isConferenceVideoActive) { - final String itemId = makeFragmentId(getItemId(callPage.ordinal())); - BaseFragment fragment = mAdapterPages.get(itemId); - if (fragment != null) { - destroyView(fragment); - } - mAdapterPages.remove(itemId); - } +// if (callPage == CallPages.ConferenceVideoFragment && !isConferenceVideoActive) { +// final String itemId = makeFragmentId(getItemId(callPage.ordinal())); +// BaseFragment fragment = mAdapterPages.get(itemId); +// if (fragment != null) { +// destroyView(fragment); +// } +// mAdapterPages.remove(itemId); +// } } callPages.clear(); for (CallPages callPage : CallPages.values()) { @@ -249,20 +227,21 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { } else if (position == CallPages.ShareScreenFragment.ordinal()) { if (fragment instanceof ScreenShareFragment) { ((ScreenShareFragment)fragment).setActiveState(active); - } else if (fragment instanceof ConferenceVideoFragment) { - ((ConferenceVideoFragment)fragment).setActiveState(active); } else if (fragment instanceof ConferenceCallFragment) { ((ConferenceCallFragment) fragment).setActiveState(active); + } else if (fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment)fragment).setActiveState(active); + } + } else if (position == CallPages.CallPageActiveCallFragment.ordinal()) { + if (fragment instanceof ConferenceCallFragment) { + ((ConferenceCallFragment)fragment).setActiveState(active); + } else if (fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment) fragment).setActiveState(active); } } else if (position == CallPages.ConferenceVideoFragment.ordinal()) { if (fragment instanceof ConferenceVideoFragment) { ((ConferenceVideoFragment)fragment).setActiveState(active); - } else if (fragment instanceof ConferenceCallFragment) { - ((ConferenceCallFragment) fragment).setActiveState(active); } - } else if (position == CallPages.CallPageActiveCallFragment.ordinal() - && fragment instanceof ConferenceCallFragment) { - ((ConferenceCallFragment)fragment).setActiveState(active); } } @@ -304,12 +283,12 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { && fragment instanceof ConferenceVideoFragment) || (position == CallPages.ShareScreenFragment.ordinal() && fragment instanceof ConferenceCallFragment) - || (position == CallPages.ConferenceVideoFragment.ordinal() - && fragment instanceof ConferenceVideoFragment) - || (position == CallPages.ConferenceVideoFragment.ordinal() - && fragment instanceof ConferenceCallFragment) || (position == CallPages.CallPageActiveCallFragment.ordinal() && fragment instanceof ConferenceCallFragment) + || (position == CallPages.CallPageActiveCallFragment.ordinal() + && fragment instanceof ConferenceVideoFragment) + || (position == CallPages.ConferenceVideoFragment.ordinal() + && fragment instanceof ConferenceVideoFragment) ) { fragment.onConfigurationChanged(newConfig); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java index 8881db73c5..39229dcddb 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java @@ -306,6 +306,8 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, mConferencePresenter.getPermissionDialogListener(), Manifest.permission.CAMERA); } }, Timber::e); + } else { + videoOnOf.setChecked(mConferencePresenter.isCameraRunning()); } } else if (videoOnOf.isChecked() && mConferencePresenter.isCameraRunning()) { mConferencePresenter.stopCameraCapture(); @@ -568,7 +570,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, @Override public void onConferenceEnded() { if (getActivity() == null || !isAdded()) return; - getActivity().runOnUiThread(() -> getActivity().finish()); + //getActivity().runOnUiThread(() -> getActivity().finish()); } @Override @@ -639,7 +641,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, activeUserNameSection.setVisibility(visible); audioIncomeLayout.setVisibility(visible); name.setVisibility(visible); - callActivity.getPageIndicator().setVisibility(visible); + //callActivity.getPageIndicator().setVisibility(visible); if (activeConferenceCall.isConference()) { activeUserPhotoLayout.setVisibility(View.GONE); conferenceParticipantsLayout.setVisibility(visible); @@ -699,7 +701,7 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, name.setVisibility(visible); conferenceParticipantsLayout.setVisibility(View.GONE); activeUserNameSection.setVisibility(visible); - callActivity.getPageIndicator().setVisibility(visible); + //callActivity.getPageIndicator().setVisibility(visible); if (activeConferenceCall != null && activeConferenceCall.isConference()) { // TODO: for later Conference calls video support. } else { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt index 0165e4583d..8abd3f1779 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ScreenShareFragment.kt @@ -71,6 +71,12 @@ class ScreenShareFragment : BaseFragment(), ScreenShareView { remoteScreenShareState(mPresenter.activeConference.mData.hasRemoteScreenShareTrack) } + override fun onDestroyView() { + removeRemoteScreenShareRenderer(mPresenter.getActiveConference()) + mScreenShareRemote?.release() + super.onDestroyView() + } + override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) onOrientationChanged(newConfig.orientation) -- GitLab From 341797d4dd8326bd64c8adb22c29f4c073d309f0 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Fri, 24 Apr 2020 22:57:04 +0300 Subject: [PATCH 05/21] -added divider between conference call video feeds --- .../conference/ConferenceVideoFragment.java | 59 +++++++++---------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index c8cfb37896..23ce2eab47 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -4,6 +4,8 @@ import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearSnapHelper; @@ -129,8 +131,6 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } private void initUIRv() { -// final DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); -// itemAnimator.setSupportsChangeAnimations(false); // mRecyclerView.setItemAnimator(itemAnimator); mRecyclerView.setNestedScrollingEnabled(false); GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),2); @@ -157,38 +157,33 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV mRecyclerView.setLayoutManager(gridLayoutManager); mRecyclerView.setHasFixedSize(true); mRecyclerView.setAdapter(mConfParticipantsAdapter); -// mRecyclerView.addItemDecoration(new CirclePagerIndicatorDecoration(R.dimen.rv_indicator_radius, -// R.dimen.rv_indicator_padding, -// R.dimen.rv_indicator_height, -// R.color.wheel_unselected_corner_bg, -// R.color.colorAccent)); -// new PagerSnapHelper().attachToRecyclerView(mRecyclerView); SnapHelper snapHelper = new LinearSnapHelper(); snapHelper.attachToRecyclerView(mRecyclerView); - - mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() { - @Override - public void onChildViewAttachedToWindow(View view) { - ConferenceVideoItemVh holder = (ConferenceVideoItemVh)getChildViewHolderInternal(view); - if (holder != null) { - //holder.onViewAttachedToWindow(); - } - } - - @Override - public void onChildViewDetachedFromWindow(View view) { - ConferenceVideoItemVh holder = (ConferenceVideoItemVh)getChildViewHolderInternal(view); - if (holder != null) { - //holder.onViewDetachedFromWindow(); - } - } - }); - mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - } - }); + mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL)); + mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); +// mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() { +// @Override +// public void onChildViewAttachedToWindow(View view) { +// ConferenceVideoItemVh holder = (ConferenceVideoItemVh)getChildViewHolderInternal(view); +// if (holder != null) { +// //holder.onViewAttachedToWindow(); +// } +// } +// +// @Override +// public void onChildViewDetachedFromWindow(View view) { +// ConferenceVideoItemVh holder = (ConferenceVideoItemVh)getChildViewHolderInternal(view); +// if (holder != null) { +// //holder.onViewDetachedFromWindow(); +// } +// } +// }); +// mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { +// @Override +// public void onScrolled(RecyclerView recyclerView, int dx, int dy) { +// super.onScrolled(recyclerView, dx, dy); +// } +// }); } private RecyclerView.ViewHolder getChildViewHolderInternal(View child) { -- GitLab From 512dc0eb8250c3eae773f0a8037835f2cbfc698d Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Mon, 27 Apr 2020 12:35:52 +0300 Subject: [PATCH 06/21] -fixed memory leaks on end conference video call -auto ordering resixing video feeds on add/remove --- .../conference/ConferenceVideoModule.java | 96 +++++++++++++ .../data/sdk/calls/ConferenceListItem.java | 31 ++++- .../presenters/ConferenceVideoPresenter.java | 26 +--- .../conference/ConferenceVideoAdapter.java | 53 +++++++ .../conference/ConferenceVideoItemVh.java | 30 ++-- .../conference/ConferenceVideoFragment.java | 29 ++-- .../res/drawable/video_feed_square_stroke.xml | 9 ++ .../main/res/layout/li_conference_video.xml | 130 ++++++++++-------- 8 files changed, 287 insertions(+), 117 deletions(-) create mode 100644 app/src/main/res/drawable/video_feed_square_stroke.xml diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index c76b139604..f9c39214bb 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -2,10 +2,15 @@ package com.nynja.mobile.communicator.data.conference; import com.nynja.mobile.communicator.NynjaApp; import com.nynja.mobile.communicator.data.DataManager; +import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; +import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; +import com.nynja.sdk.NYNCallParticipant; import org.webrtc.SurfaceViewRenderer; +import java.util.ArrayList; + public class ConferenceVideoModule { private static ConferenceVideoModule mInstance = null; @@ -14,6 +19,9 @@ public class ConferenceVideoModule { // Call worker object private ActiveConferenceCall mCurrentActiveCall; + public int mActiveVideoParticipantsCount = 0; + public ArrayList mActiveVideoParticipants= new ArrayList<>(); + private ConferenceVideoModule() { init(); @@ -30,6 +38,7 @@ public class ConferenceVideoModule { // ToDo:... mCurrentActiveCall = null; mDataManager = NynjaApp.getComponent().dataManager(); + mActiveVideoParticipantsCount = 0; } public void reset() { @@ -61,4 +70,91 @@ public class ConferenceVideoModule { return trackId; } + public ArrayList getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { + if (activeConferenceCall == null) return new ArrayList<>(); + mActiveVideoParticipants.clear(); + if (activeConferenceCall.mData.mParticipantArray != null) { + for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); + if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { + mActiveVideoParticipants.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); + } + } + } + mActiveVideoParticipantsCount = mActiveVideoParticipants.size(); + return mActiveVideoParticipants; + } + + public float getSpanSize(int position) { +// if (mActiveVideoParticipantsCount <= 4) return 1; +// switch (position % 4) { +// case 0: +// case 1: +// { +// return 1; +// } +// } +// if (position < mActiveVideoParticipants.size()) { +// if (mActiveVideoParticipants.get(position).isVideoFullScreen) +// return 1; +// } +// return 2; + return ((int)(position/4)) +1; + } + + public float getWidthDiv(int position) { + if (mActiveVideoParticipantsCount <= 2) return 1f; + switch (position % 4) { + case 0: + { + if (position == mActiveVideoParticipantsCount -1) return 1f; + if (position == mActiveVideoParticipantsCount -2) return 1f; + return 2f; + } + case 1: + { + if (position == mActiveVideoParticipantsCount -1) return 1f; + if (position == mActiveVideoParticipantsCount -2) return 2f; + return 2f; + } + case 2: + { + return 2f; + } + // next 3 items span 2 columns each + case 3: + { + return 2f; + } + } + + return 1f; + } + + public float getHeightDiv(int position) { + if (mActiveVideoParticipantsCount <= 1) return 1f; + switch (position % 4) { + case 0: + { + if (position == mActiveVideoParticipantsCount -1) return 1f; + return 2f; + } + } + + return 2f; + } + + protected ConferenceListItem conferenceParticipant(NYNCallParticipant participant, + boolean isModerator, + boolean isOwnStreamActive) { + ContactModel user = mDataManager.getContactsByPhoneId(participant.getAddress()); + ConferenceListItem conferenceListItem = ConferenceListItem.fromSdkParticipant(participant, (user != null), isOwnStreamActive); + if (user != null) { + conferenceListItem.avatar = user.avatar; + } + if (isModerator) conferenceListItem.type = ConferenceListItem.ConferenceItemType.Moderator; + + return conferenceListItem; + } + } diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java index 671c2e41a3..d6d7d0cf02 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java @@ -1,9 +1,8 @@ package com.nynja.mobile.communicator.data.sdk.calls; -import android.content.Context; - import com.nynja.mobile.communicator.R; import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; +import com.nynja.mobile.communicator.utils.StringUtils; import com.nynja.sdk.NYNCallParticipant; import java.util.ArrayList; @@ -14,7 +13,7 @@ import io.reactivex.annotations.NonNull; * Created by Ergyun Syuleyman on 5/27/18. */ -public class ConferenceListItem { +public class ConferenceListItem extends Object { // Conference items in Grid view type public enum ConferenceItemType { Plus, @@ -40,6 +39,7 @@ public class ConferenceListItem { public boolean isVideoPaused; public boolean isScreenPaused; public int isTrackActive; + public boolean isVideoFullScreen; protected ConferenceListItem() { phoneId = ""; @@ -55,6 +55,7 @@ public class ConferenceListItem { isVideoPaused = false; isScreenPaused = false; isTrackActive = 0; + isVideoFullScreen = false; } protected ConferenceListItem(ConferenceItemType type, String phoneId, String memberId, @@ -75,7 +76,8 @@ public class ConferenceListItem { this.hasScreen = false; this.isVideoPaused = false; this.isScreenPaused = false; - isTrackActive = 0; + this.isTrackActive = 0; + this.isVideoFullScreen = false; } protected ConferenceListItem(ConferenceItemType type, NYNCallParticipant participant, @@ -97,6 +99,26 @@ public class ConferenceListItem { this.isVideoPaused = participant.isVideoPaused(); this.isScreenPaused = participant.isScreenPaused(); this.isTrackActive = 0; + this.isVideoFullScreen = false; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConferenceListItem item = (ConferenceListItem) o; + return (StringUtils.isEqual(phoneId, item.phoneId) + && StringUtils.isEqual(memberId, item.memberId) + && StringUtils.isEqual(participantId, item.participantId)); + } + + + @Override + public int hashCode() { + int result = phoneId != null ? phoneId.hashCode() : 0; + result = 31 * result + (memberId != null ? memberId.hashCode() : 0); + result = 31 * result + (participantId != null ? participantId.hashCode() : 0); + return result; } public void update(ConferenceListItem participant) { @@ -112,6 +134,7 @@ public class ConferenceListItem { this.isTrackActive = 0; this.isMe = participant.isMe; this.isMuted = participant.isMuted; + this.isVideoFullScreen = false; } private void setActions(ArrayList itemActions) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java index 58769f6d0e..b1b183137e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -2,6 +2,7 @@ package com.nynja.mobile.communicator.mvp.presenters; import com.arellomobile.mvp.InjectViewState; import com.nynja.mobile.communicator.data.FragmentTransferObject; +import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; import com.nynja.mobile.communicator.data.models.nynjamodels.RoomModel; import com.nynja.mobile.communicator.data.sdk.ConferenceSDKPresenter; @@ -88,19 +89,6 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { - ArrayList members = new ArrayList<>(); - if (activeConferenceCall == null) return members; - if (activeConferenceCall.mData.mParticipantArray != null) { - for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { - NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); - if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { - members.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); - } - } - } - return members; + return ConferenceVideoModule.getInstance().getConferenceVideoMembers(activeConferenceCall); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index 91bebebbe3..2189637ddb 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -1,25 +1,38 @@ package com.nynja.mobile.communicator.ui.adapters.conference; +import android.content.Context; import android.support.annotation.NonNull; +import android.util.DisplayMetrics; +import android.view.Display; import android.view.ViewGroup; +import android.view.WindowManager; import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; +import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceVideoItemVh; import com.nynja.mobile.communicator.ui.base.BaseAdapter; import com.nynja.mobile.communicator.ui.base.BaseVH; +import java.util.HashSet; import java.util.List; public class ConferenceVideoAdapter> extends BaseAdapter { + + private static int STATIC_BOTTOM_HEIGHT_OFFSET = 60; private OnConferenceItemClickListener mOnConferenceItemClickListener; private boolean mIsModerator = false; + private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); + private int mScreenWidth = 0; + private int mScreenHeight = 0; + HashSet mHoldersSet; public ConferenceVideoAdapter(List list, OnConferenceItemClickListener onConferenceItemClickListener) { super(list); this.mOnConferenceItemClickListener = onConferenceItemClickListener; + mHoldersSet = new HashSet<>(); } public void setOnItemClickListener(OnConferenceItemClickListener onConferenceItemClickListener) { @@ -35,6 +48,12 @@ public class ConferenceVideoAdapter> exten } public void releaseVideoCallRrenderers() { + for (ConferenceVideoItemVh vh : mHoldersSet) { + vh.onViewRecycled(); + vh.releaseVideoCallRrenderers(); + } + mHoldersSet.clear(); + clear(); } @@ -43,9 +62,43 @@ public class ConferenceVideoAdapter> exten public T onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { ConferenceVideoItemVh viewHolder = new ConferenceVideoItemVh(viewGroup, mIsModerator); viewHolder.setOnItemClickListener(mOnConferenceItemClickListener); + if (viewGroup.getContext() instanceof CallActivity) { + WindowManager wm = (WindowManager) viewHolder.itemView.getContext().getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + display.getMetrics(mDisplayMetrics); + mScreenWidth = mDisplayMetrics.widthPixels; + mScreenHeight = mDisplayMetrics.heightPixels; + } + mHoldersSet.add(viewHolder); return (T) viewHolder; } + @Override + public void onBindViewHolder(T holder, int position) { + super.onBindViewHolder(holder, position); + if (mScreenWidth > 0) { + int itemPadding = 0; + float divH = ConferenceVideoModule.getInstance().getWidthDiv(position); + float divV = ConferenceVideoModule.getInstance().getHeightDiv(position); + //////////////////////////////////////////////////// + //if (position == 2) ((ConferenceVideoItemVh) holder).getItem().isVideoFullScreen = true; + //if (((ConferenceVideoItemVh) holder).getItem().isVideoFullScreen) { + // divH = 1f; divV = 1f; + //} + //////////////////////////////////////////////////// + int itemWidth = (int) ((mScreenWidth - itemPadding) / divH); + int itemHeight = (int) ((mScreenHeight - itemPadding) / divV); + ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); + if (divV == 2f) { + layoutParams.height = itemHeight - STATIC_BOTTOM_HEIGHT_OFFSET; + } else { + layoutParams.height = itemHeight; + } + layoutParams.width = itemWidth; + holder.itemView.setLayoutParams(layoutParams); + } + } + @Override public int getItemViewType(int position) { return super.getItemViewType(position); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 6b921b3355..2cc5fe7206 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -1,8 +1,10 @@ package com.nynja.mobile.communicator.ui.adapters.viewholders.conference; +import android.graphics.Color; import android.support.annotation.NonNull; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -30,7 +32,7 @@ public class ConferenceVideoItemVh extends BaseVH { @BindView(R.id.conf_video_ss) CheckableImageView mSS; @BindView(R.id.conf_video_active) CheckableImageView mActiveVideo; @BindView(R.id.conf_video_feed) SurfaceViewRenderer mVideoFeed; - + @BindView(R.id.conf_video_holder_layout) FrameLayout mFeedFrameLayout; protected ConferenceListItem mItem; private OnConferenceItemClickListener mListener; @@ -104,7 +106,7 @@ public class ConferenceVideoItemVh extends BaseVH { public void onViewRecycled() { onViewDetachedFromWindow(); - releaseVideoCallRrenderers(); + //releaseVideoCallRrenderers(); } @Override @@ -114,6 +116,16 @@ public class ConferenceVideoItemVh extends BaseVH { onViewRecycled(); } + + @Synchronized + public void releaseVideoCallRrenderers() { + if (!mIsRenderersInitialized) return; + if (mVideoFeed != null) { + mVideoFeed.release(); + } + mIsRenderersInitialized = false; + } + ///////////////////////////////////////////////////////////////////////////////////// // Internal Helpers private void setupInConference(ConferenceListItem item) { @@ -128,6 +140,11 @@ public class ConferenceVideoItemVh extends BaseVH { drawIsScfreenSharingIfNeeded(item); drawIsActiveVideoIfNeeded(item); drawIsFeedVideoIfNeeded(item.hasVideo); + if (mItem != null && mItem.isMe) { + mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke); + } else { + mFeedFrameLayout.setBackgroundColor(Color.TRANSPARENT); + } } } @@ -199,13 +216,4 @@ public class ConferenceVideoItemVh extends BaseVH { } } - @Synchronized - private void releaseVideoCallRrenderers() { - if (!mIsRenderersInitialized) return; - if (mVideoFeed != null) { - mVideoFeed.release(); - } - mIsRenderersInitialized = false; - } - } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 23ce2eab47..0126f9e719 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -56,6 +56,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV private boolean isActive; private CallActivity callActivity; private Handler mHandler; + GridLayoutManager mGridLayoutManager; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { @@ -131,30 +132,20 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } private void initUIRv() { -// mRecyclerView.setItemAnimator(itemAnimator); mRecyclerView.setNestedScrollingEnabled(false); - GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),2); - gridLayoutManager.setSpanCount(2); - gridLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); - gridLayoutManager.setReverseLayout(false); -// gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + mGridLayoutManager = new GridLayoutManager(getActivity(), 2, + LinearLayoutManager.HORIZONTAL, false); +// mGridLayoutManager.setSpanCount(2); +// mGridLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); +// mGridLayoutManager.setReverseLayout(false); +// mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { // @Override // public int getSpanSize(int position) { -// // 5 is the sum of items in one repeated section -// switch (position % 4) { -// case 0: -// case 2: -// return 2; -// // next 3 items span 2 columns each -// case 1: -// case 3: -// return 1; -// } -// throw new IllegalStateException("internal error"); +// return (int)ConferenceVideoModule.getInstance().getSpanSize(position); // } // }); - gridLayoutManager.setItemPrefetchEnabled(true); - mRecyclerView.setLayoutManager(gridLayoutManager); + mGridLayoutManager.setItemPrefetchEnabled(true); + mRecyclerView.setLayoutManager(mGridLayoutManager); mRecyclerView.setHasFixedSize(true); mRecyclerView.setAdapter(mConfParticipantsAdapter); SnapHelper snapHelper = new LinearSnapHelper(); diff --git a/app/src/main/res/drawable/video_feed_square_stroke.xml b/app/src/main/res/drawable/video_feed_square_stroke.xml new file mode 100644 index 0000000000..ec8f78faa7 --- /dev/null +++ b/app/src/main/res/drawable/video_feed_square_stroke.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/li_conference_video.xml b/app/src/main/res/layout/li_conference_video.xml index 9b7652d616..44b2d8f4bb 100644 --- a/app/src/main/res/layout/li_conference_video.xml +++ b/app/src/main/res/layout/li_conference_video.xml @@ -6,78 +6,90 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" - android:gravity="center"> + android:padding="@dimen/padding_small"> - + android:gravity="center" + android:layout_gravity="center"> - + android:layout_height="wrap_content" + android:layout_gravity="center" + android:padding="2dp" + android:layout_marginStart="@dimen/margin_small" + android:layout_marginTop="@dimen/margin_small" + android:layout_marginEnd="@dimen/margin_small" + android:layout_marginBottom="@dimen/margin_small"> + + + + - + - + - + - + - + - + Date: Mon, 27 Apr 2020 18:05:33 +0300 Subject: [PATCH 07/21] -changes related to control conference video feed using the core option --- .../conference/ConferenceVideoModule.java | 41 +++++++++++---- .../data/sdk/calls/ActiveConferenceCall.java | 7 +++ .../data/sdk/calls/ConferenceListItem.java | 1 + .../data/sdk/calls/ConferenceSDKModule.java | 20 +++++--- .../presenters/ConferenceVideoPresenter.java | 17 +++++++ .../conference/ConferenceVideoItemVh.java | 51 +++++++++++++------ .../conference/ConferenceVideoFragment.java | 33 +++++++++--- 7 files changed, 131 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index f9c39214bb..c04375018f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -5,11 +5,14 @@ import com.nynja.mobile.communicator.data.DataManager; import com.nynja.mobile.communicator.data.models.nynjamodels.ContactModel; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; +import com.nynja.mobile.communicator.utils.StringUtils; import com.nynja.sdk.NYNCallParticipant; import org.webrtc.SurfaceViewRenderer; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; public class ConferenceVideoModule { @@ -20,7 +23,7 @@ public class ConferenceVideoModule { private ActiveConferenceCall mCurrentActiveCall; public int mActiveVideoParticipantsCount = 0; - public ArrayList mActiveVideoParticipants= new ArrayList<>(); + public HashMap mActiveVideoParticipantsMap= new HashMap<>(); private ConferenceVideoModule() { @@ -53,7 +56,7 @@ public class ConferenceVideoModule { } public void setVideoRendererForTrack(SurfaceViewRenderer videoFeed, String trackId, boolean isLocal) { - if (mCurrentActiveCall != null) { + if (mCurrentActiveCall != null && mCurrentActiveCall.mConference != null) { if (isLocal) { mCurrentActiveCall.mConference.setLocalVideoRenderer(videoFeed); } else { @@ -62,6 +65,12 @@ public class ConferenceVideoModule { } } + public void enableVideoForTrack(String participantId, boolean enable) { + if (mCurrentActiveCall != null && mCurrentActiveCall.mConference != null) { + mCurrentActiveCall.mConference.enableVideoForTrack(participantId, enable); + } + } + public String getTrackIdByParticipantId(String participantId) { String trackId = ""; if (mCurrentActiveCall != null) { @@ -72,17 +81,29 @@ public class ConferenceVideoModule { public ArrayList getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return new ArrayList<>(); - mActiveVideoParticipants.clear(); - if (activeConferenceCall.mData.mParticipantArray != null) { - for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { - NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); - if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { - mActiveVideoParticipants.add(conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive)); + Set participatIds = mActiveVideoParticipantsMap.keySet(); + mActiveVideoParticipantsMap.clear(); + synchronized (activeConferenceCall.mData.mParticipantArray) { + if (activeConferenceCall.mData.mParticipantArray != null) { + for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { + NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); + if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { + ConferenceListItem item = conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive); + mActiveVideoParticipantsMap.put(item.participantId, item); + } } } } - mActiveVideoParticipantsCount = mActiveVideoParticipants.size(); - return mActiveVideoParticipants; + + for (String participantId : participatIds) { + if (!mActiveVideoParticipantsMap.containsKey(participantId)) { + String trackId = getTrackIdByParticipantId(participantId); + setVideoRendererForTrack(null, trackId, StringUtils.isEmpty(trackId)); + } + } + + mActiveVideoParticipantsCount = mActiveVideoParticipantsMap.size(); + return new ArrayList<>(mActiveVideoParticipantsMap.values()); } public float getSpanSize(int position) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java index 314e202519..d613e9b7b8 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ActiveConferenceCall.java @@ -43,6 +43,13 @@ public class ActiveConferenceCall extends ActiveCallBase { mAutoCreateAndStart = false; } + void setInternalCall(NYNCall conference) { + mConference = conference; + if (conference != null) { + mData.mParticipantArray = conference.getParticipants(); + } + } + public void setMembers(ArrayList members) { this.mMembers = members; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java index d6d7d0cf02..4f3b6c0dcf 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java @@ -133,6 +133,7 @@ public class ConferenceListItem extends Object { this.isScreenPaused = participant.isScreenPaused; this.isTrackActive = 0; this.isMe = participant.isMe; + this.isFriend = participant.isFriend; this.isMuted = participant.isMuted; this.isVideoFullScreen = false; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index ea97ab595f..e53193b483 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -892,7 +892,7 @@ public class ConferenceSDKModule extends BaseSDKModule { mConferenceDetails.mCallId = conferenceId; NYNCall conference = mCallManager.getCallById(conferenceId); if (conference != null) { - mConferenceDetails.mActiveConference.mConference = conference; + mConferenceDetails.mActiveConference.setInternalCall(conference); mConferenceDetails.mActiveConference.mData.mParticipantsCountLimit = conference.getParticipantsCountLimit(); onGetConferenceRoomLimitsFinished(null, mConferenceDetails.mActiveConference.mEndPointId, conference.getParticipantsCountLimit()); @@ -1017,7 +1017,7 @@ public class ConferenceSDKModule extends BaseSDKModule { conferenceId != null && conferenceId.contentEquals(mConferenceDetails.mCallId) && mActiveConference.isWaiting()) { - mActiveConference.mConference = mCallManager.getCallById(mConferenceDetails.mCallId); + mActiveConference.setInternalCall(mCallManager.getCallById(mConferenceDetails.mCallId)); if (mActiveConference.mConference != null) { // todo: for limits use the new logic - local hashMap mActiveConference.mData.mParticipantsCountLimit = mActiveConference.mConference.getParticipantsCountLimit(); @@ -1065,7 +1065,9 @@ public class ConferenceSDKModule extends BaseSDKModule { if (!hasCreatedActiveCall()) return; Timber.d("Request conference member with \'ConferenceId\'=\'" + conferenceId + "\' " + (result ? "succeed" : "failed!!!")); - mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); + synchronized (mActiveConference.mData.mParticipantArray) { + mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); + } // update chatRoomId if (mActiveConference.mData.mParticipantArray != null && @@ -1422,7 +1424,7 @@ public class ConferenceSDKModule extends BaseSDKModule { @Override public void createCallFinished(String requestId, String callId, boolean success) { if (!hasCreatedActiveCall()) return; - mActiveConference.mConference = mCallManager.getCallById(callId); + mActiveConference.setInternalCall(mCallManager.getCallById(callId)); Timber.d("Request create call with \'CallId\'=\'" + callId + "\' " + (success ? "succeed" : "failed!!!")); if (mActiveConference.isOutgoingCall) { @@ -1561,7 +1563,9 @@ public class ConferenceSDKModule extends BaseSDKModule { initConferenceCall(false); new Handler(Looper.getMainLooper()).postDelayed(() -> { mActiveConference.isCallInProgress = true; - mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); + synchronized (mActiveConference.mData.mParticipantArray) { + mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); + } startConferenceActivityImpl(NynjaNavigator.MAIN_NEW_CALL, true); }, Consts.DELAY_100); } @@ -2615,7 +2619,7 @@ public class ConferenceSDKModule extends BaseSDKModule { if (mActiveConference.mConference != null) { mActiveConference.mConference.setListener(null); } - mActiveConference.mConference = mCallManager.getCallById(mConferenceDetails.mCallId); + mActiveConference.setInternalCall(mCallManager.getCallById(mConferenceDetails.mCallId)); } if (mActiveConference.mConference != null) { // todo: for limits use the new logic - local hashMap @@ -2955,7 +2959,9 @@ public class ConferenceSDKModule extends BaseSDKModule { } } if (mActiveConference.mData.mParticipantArray.size() > 1 && TEMP_ALLOW_UPDATE_CONF_CALLS_NAME) { - mActiveConference.mData.mParticipantArray.remove(index); + synchronized (mActiveConference.mData.mParticipantArray) { + mActiveConference.mData.mParticipantArray.remove(index); + } tryUpdateConferenceCallName(mActiveConference, generateGroupConferenceName(mActiveConference.mData.mParticipantArray.size() - 1));// exclude me } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java index b1b183137e..84efff1b88 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -10,6 +10,7 @@ import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceSDKListener; import com.nynja.mobile.communicator.mvp.view.ConferenceVideoView; +import com.nynja.mobile.communicator.utils.navigation.navigators.HomeNavigator; import com.nynja.sdk.NYNCallParticipant; import java.util.ArrayList; @@ -74,6 +75,22 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter { } public void onViewAttachedToWindow() { - if (mItem == null) return; initVideoCallRenderer(); - if (mItem.isTrackActive == 1) return; - String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); - if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { - mItem.isTrackActive = 1; - ConferenceVideoModule.getInstance().setVideoRendererForTrack(mVideoFeed, trackId, mItem.isMe); - } + setVideoRendererForTrack(); + enableVideoForTrack(true); } public void onViewDetachedFromWindow() { - if (mItem == null) return; - if (mItem.isTrackActive == 0) return; - String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); - if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { - ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, mItem.isMe); - mItem.isTrackActive = 0; - } + enableVideoForTrack(false); } public void onViewRecycled() { onViewDetachedFromWindow(); - //releaseVideoCallRrenderers(); } @Override public void onUnbind() { super.onUnbind(); - onViewRecycled(); +// onViewRecycled(); } @Synchronized public void releaseVideoCallRrenderers() { + removeVideoRendererForTrack(); if (!mIsRenderersInitialized) return; if (mVideoFeed != null) { mVideoFeed.release(); @@ -216,4 +205,34 @@ public class ConferenceVideoItemVh extends BaseVH { } } + @Synchronized + private void setVideoRendererForTrack() { + if (mItem == null) return; + if (mItem.isTrackActive == 1) return; + String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); + if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { + mItem.isTrackActive = 1; + ConferenceVideoModule.getInstance().setVideoRendererForTrack(mVideoFeed, trackId, mItem.isMe); + } + } + + @Synchronized + private void removeVideoRendererForTrack() { + if (mItem == null) return; + if (mItem.isTrackActive == 0) return; + String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); + if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { + ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, mItem.isMe); + mItem.isTrackActive = 0; + } + } + + @Synchronized + private void enableVideoForTrack(boolean enable) { + if (mItem == null) return; + if (StringUtils.isNotEmpty(mItem.participantId)) { + mItem.isTrackActive = 1; + ConferenceVideoModule.getInstance().enableVideoForTrack(mItem.participantId, enable); + } + } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 0126f9e719..7d7d25aef1 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -57,6 +57,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV private CallActivity callActivity; private Handler mHandler; GridLayoutManager mGridLayoutManager; + private ArrayList mMembersList = new ArrayList<>(); @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { @@ -65,7 +66,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV createRootEglBase(); ActiveConferenceCall activeConferenceCall = mConferencePresenter.getActiveConference(); ConferenceVideoModule.getInstance().setCurrentActiveCall(activeConferenceCall); - mConfParticipantsAdapter = new ConferenceVideoAdapter(new ArrayList<>(), this); + mConfParticipantsAdapter = new ConferenceVideoAdapter(mMembersList, this); initUIRv(); } @@ -112,9 +113,6 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV Timber.d("On clicked position: %d contact: %s", position, item); if (item == null) return; // '+' item - if (item.type == ConferenceListItem.ConferenceItemType.Plus) { - } else { - } } @Override @@ -128,6 +126,29 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (item.memberActions.size() == 0) return false; + + ActionSheetDialog actionSheet = new ActionSheetDialog(getActivity()); + actionSheet.isKeyPrevPressed = true; + actionSheet.setCancelButtonTitle(getString(R.string.cancel)); + ArrayList itemsArray = new ArrayList<>(); + for(int resId : item.memberActions) { + itemsArray.add(getString(resId)); + } + actionSheet.addItems(itemsArray.toArray(new String[itemsArray.size()])); + actionSheet.setItemClickListener( + itemPosition -> { + if (item.isMe) { + onClickMyIconItem(item, itemPosition); + } else { + if (item.isFriend) { + onClickOthersFriendIconItem(item, itemPosition); + } else { + onClickOthersIconItem(item, itemPosition); + } + } + }); + actionSheet.setCancelableOnTouchMenuOutside(true); +// actionSheet.showMenu(); return true; } @@ -352,7 +373,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (postion >= participant.memberActions.size() || postion < 0) return; switch (participant.memberActions.get(postion)) { case R.string.call_view_profile: - //mConferencePresenter.showProfile(participant); + mConferencePresenter.showProfile(participant); break; case R.string.send_a_message: mConferencePresenter.openChatWithParticipant(participant.phoneId); @@ -390,7 +411,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (postion >= participant.memberActions.size() || postion < 0) return; switch (participant.memberActions.get(postion)) { case R.string.call_view_profile: - //mConferencePresenter.showProfile(participant); + mConferencePresenter.showProfile(participant); break; case R.string.call_remove_from_call: -- GitLab From fb629cabc31d29cec21b98b72029988e77407ec9 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Mon, 27 Apr 2020 21:57:04 +0300 Subject: [PATCH 08/21] -added SS and Camera start fsailing handler --- .../data/sdk/ConferenceSDKPresenter.java | 2 ++ .../data/sdk/calls/ConferenceSDKListener.java | 2 ++ .../data/sdk/calls/ConferenceSDKModule.java | 34 +++++++++++++++++-- .../presenters/ConferenceCallPresenter.java | 5 +++ .../communicator/mvp/view/CallView.java | 2 ++ .../conference/ConferenceCallFragment.java | 18 ++++++++++ app/src/main/res/values-en/strings.xml | 6 ++++ app/src/main/res/values-es/strings.xml | 6 ++++ app/src/main/res/values-ko/strings.xml | 7 ++++ app/src/main/res/values-zh-rCN/strings.xml | 6 ++++ app/src/main/res/values-zh/strings.xml | 6 ++++ app/src/main/res/values/strings.xml | 5 +++ 12 files changed, 97 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java index c927f05b89..4f8e3242fe 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java @@ -53,6 +53,8 @@ public abstract class ConferenceSDKPresenter extends Bas @Override public void onScreenShareState(boolean active) {} + @Override public void onStartCapturerFailed(int msgResId, boolean isCamera) {} + @Override public void onRemoteScreenShareTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) {} @Override public void onRemoteScreenShareTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) {} diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java index 7071dbafb3..def48a97ca 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java @@ -38,6 +38,8 @@ public interface ConferenceSDKListener { void onScreenShareState(boolean active); + void onStartCapturerFailed(int msgResId, boolean isCamera); + void onRemoteScreenShareTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) ; void onRemoteScreenShareTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) ; diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index e53193b483..edd53689d1 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -865,10 +865,10 @@ public class ConferenceSDKModule extends BaseSDKModule { } @Override - public void startScreenShareFailed(NYNCall call) { + public void startScreenShareFailed(NYNCall call, int code) { if (call != null) { Timber.d("startScreenShareFailed(): callId=" + call.callId()); - onOwnScreenShareStopped(call); + onStartCapturerFailed(call, code, false); } } @@ -879,6 +879,14 @@ public class ConferenceSDKModule extends BaseSDKModule { onOwnScreenShareStopped(call); } } + + @Override + public void startCameraFailed(NYNCall call, int code) { + if (call != null) { + Timber.d("startCameraFailed(): callId=" + call.callId()); + onStartCapturerFailed(call, code, true); + } + } }; } @@ -1745,6 +1753,28 @@ public class ConferenceSDKModule extends BaseSDKModule { } } + private void onStartCapturerFailed(NYNCall call, int code, boolean isCamera) { + if (call != null && + hasCreatedActiveCall() && mActiveConference.mConference != null + && mActiveConference.mConference.callId().contentEquals(call.callId())) { + for (ConferenceSDKListener conferenceListener : mConferenceSDKListener) { + if (code == -47) { + if (isCamera) { + conferenceListener.onStartCapturerFailed(R.string.call_start_camera_failed_busy, isCamera); + } else { + conferenceListener.onStartCapturerFailed(R.string.call_start_ss_failed_busy, isCamera); + } + } else { + if (isCamera) { + conferenceListener.onStartCapturerFailed(R.string.call_start_camera_failed_invalid_state, isCamera); + } else { + conferenceListener.onStartCapturerFailed(R.string.call_start_ss_failed_invalid_state, isCamera); + } + } + } + } + } + private void onChangeCallState(NYNCall call, NYNCallState newState) { for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { conferenceSDKListener.onConferenceStateChanged(mActiveConference); diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java index d9a067fe16..9565cb8cfe 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java @@ -357,6 +357,11 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter getViewState().onScreenShareStateChanged(active && isScreenSharing()); } + @Override public void onStartCapturerFailed(int msgResId, boolean isCamera) { + if (getAttachedViews().size() == 0) return; + getViewState().onStartCapturerFailed(msgResId, isCamera); + } + @Override public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java index a87a147dbc..d718d095ff 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/CallView.java @@ -42,6 +42,8 @@ public interface CallView extends ErrorMvpView { void onCreateVideoCallReady(ActiveConferenceCall activeConferenceCall); + void onStartCapturerFailed(int msgResId, boolean isCamera); + void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) ; void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) ; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java index 39229dcddb..a298c7e639 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java @@ -7,6 +7,7 @@ import android.bluetooth.BluetoothDevice; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; @@ -794,6 +795,23 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, } + @Override public void onStartCapturerFailed(int msgResId, final boolean isCamera) { + getActivity().runOnUiThread(() -> DialogFactory.showAlert(getActivity(), + getString(msgResId), + getString(R.string.call_conference_alert_title), + new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + if (isCamera) { + videoOnOf.setChecked(mConferencePresenter.isCameraRunning()); + } else { + setScreenShareOn(false); + } + } + })); + + } + @Override public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { if (getActivity() == null || !isAdded()) return; diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 4d37bdf51d..7285083368 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1324,4 +1324,10 @@ Phone number: +%1$s Please select at least one message. + + Please stop your screen share first + Cannot start camera because it has been already started by another participant + Please stop your camera first + Cannot start screen share because it has been already started by another participant + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 22bd5fd832..a84ca16736 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + Please stop your screen share first + Cannot start camera because it has been already started by another participant + Please stop your camera first + Cannot start screen share because it has been already started by another participant + diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 1f467439e7..b6773a7a6c 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1323,4 +1323,11 @@ Uploading View + + + Please stop your screen share first + Cannot start camera because it has been already started by another participant + Please stop your camera first + Cannot start screen share because it has been already started by another participant + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9e0603dfe0..7e93e58e74 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + Please stop your screen share first + Cannot start camera because it has been already started by another participant + Please stop your camera first + Cannot start screen share because it has been already started by another participant + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 9e0603dfe0..7e93e58e74 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + Please stop your screen share first + Cannot start camera because it has been already started by another participant + Please stop your camera first + Cannot start screen share because it has been already started by another participant + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db722a5096..0239dc8f4c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1325,5 +1325,10 @@ Stop sharing Stop video + + Please stop your screen share first + Cannot start camera because it has been already started by another participant + Please stop your camera first + Cannot start screen share because it has been already started by another participant -- GitLab From 17fb0e3e3144bf026b54fde1b92843a0fb5a30a8 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Tue, 28 Apr 2020 12:22:50 +0300 Subject: [PATCH 09/21] -NY-10075: [AN]: Change "Terms of Use" link in registration page to https://nynja.work/terms-of-use --- app/src/Superapp/res/values-en/strings.xml | 8 ++++---- app/src/Superapp/res/values-es/strings.xml | 8 ++++---- app/src/Superapp/res/values-ko/strings.xml | 8 ++++---- app/src/Superapp/res/values-zh-rCN/strings.xml | 8 ++++---- app/src/Superapp/res/values-zh/strings.xml | 8 ++++---- app/src/Superapp/res/values/strings.xml | 8 ++++---- app/src/main/res/values-en/strings.xml | 8 ++++---- app/src/main/res/values-es/strings.xml | 8 ++++---- app/src/main/res/values-ko/strings.xml | 8 ++++---- app/src/main/res/values-zh-rCN/strings.xml | 8 ++++---- app/src/main/res/values-zh/strings.xml | 8 ++++---- app/src/main/res/values/strings.xml | 8 ++++---- app/src/prod/res/values-en/strings.xml | 8 ++++---- app/src/prod/res/values-es/strings.xml | 8 ++++---- app/src/prod/res/values-ko/strings.xml | 8 ++++---- app/src/prod/res/values-zh-rCN/strings.xml | 8 ++++---- app/src/prod/res/values-zh/strings.xml | 8 ++++---- app/src/prod/res/values/strings.xml | 8 ++++---- 18 files changed, 72 insertions(+), 72 deletions(-) diff --git a/app/src/Superapp/res/values-en/strings.xml b/app/src/Superapp/res/values-en/strings.xml index 4fa5447bdc..3a7a46f88c 100644 --- a/app/src/Superapp/res/values-en/strings.xml +++ b/app/src/Superapp/res/values-en/strings.xml @@ -5,9 +5,9 @@ Introducing an amazing new platform called NYNJA! It is a productivity and communications aggregator platform. Download it here: https://www.nynja.io/mobile and add me as a contact with my NYNJA user ID: %1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + hhttps://nynja.work/terms-of-use diff --git a/app/src/Superapp/res/values-es/strings.xml b/app/src/Superapp/res/values-es/strings.xml index 78812d62f3..3cb971897d 100644 --- a/app/src/Superapp/res/values-es/strings.xml +++ b/app/src/Superapp/res/values-es/strings.xml @@ -5,9 +5,9 @@ ¡Presentamos una nueva y sorprendente plataforma llamada NYNJA! Es una plataforma agregadora de comunicaciones y productividad. Descárgala aquí: https://www.nynja.io/mobile y agrégame como contacto con mi ID de usuario NYNJA: %1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/Superapp/res/values-ko/strings.xml b/app/src/Superapp/res/values-ko/strings.xml index e7d0c196c2..7d4eb06e46 100644 --- a/app/src/Superapp/res/values-ko/strings.xml +++ b/app/src/Superapp/res/values-ko/strings.xml @@ -5,9 +5,9 @@ 새로운 플랫폼 NYNJA를 소개합니다! 다양한 커뮤니케이션 웹사이트 플랫폼입니다. https://www.nynja.io/mobile 여기에서 다운로드 후, NYNJA 사용자 ID: %1$s 연락처로 저를 추가하세요 - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/Superapp/res/values-zh-rCN/strings.xml b/app/src/Superapp/res/values-zh-rCN/strings.xml index e11af51323..66e01815f8 100644 --- a/app/src/Superapp/res/values-zh-rCN/strings.xml +++ b/app/src/Superapp/res/values-zh-rCN/strings.xml @@ -5,9 +5,9 @@ 介绍一款名叫NYNJA的超棒的全新平台!这是一个集工作效率和沟通通信于一体的平台。在这里下载它:https://www.nynja.io/mobile并添加我为联系人,我的NYNJA用户名:%1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/Superapp/res/values-zh/strings.xml b/app/src/Superapp/res/values-zh/strings.xml index e11af51323..66e01815f8 100644 --- a/app/src/Superapp/res/values-zh/strings.xml +++ b/app/src/Superapp/res/values-zh/strings.xml @@ -5,9 +5,9 @@ 介绍一款名叫NYNJA的超棒的全新平台!这是一个集工作效率和沟通通信于一体的平台。在这里下载它:https://www.nynja.io/mobile并添加我为联系人,我的NYNJA用户名:%1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/Superapp/res/values/strings.xml b/app/src/Superapp/res/values/strings.xml index 4fa5447bdc..fd4bc8680e 100644 --- a/app/src/Superapp/res/values/strings.xml +++ b/app/src/Superapp/res/values/strings.xml @@ -5,9 +5,9 @@ Introducing an amazing new platform called NYNJA! It is a productivity and communications aggregator platform. Download it here: https://www.nynja.io/mobile and add me as a contact with my NYNJA user ID: %1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 4d37bdf51d..da0ec2b57a 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -848,10 +848,10 @@ Get Help Unblock No Data - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use Terminate this session? Please check Internet connection and try again. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 22bd5fd832..bcac887ffe 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -843,10 +843,10 @@ Obtener ayuda Desbloquear No hay datos - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use ¿FInalizar esta sesión? Comprueba la conexión a Internet e inténtalo de nuevo. diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 1f467439e7..7626e83c24 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -843,10 +843,10 @@ 도움말 보기 차단 해제 데이터 없음 - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use 이 세션을 끝내시겠습니까? 인터넷 연결 상태를 확인 후 다시 시도하세요. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9e0603dfe0..bb8308369e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -843,10 +843,10 @@ 获得帮助 移出黑名单 无数据 - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use 中止本会话? 请检查网络连接并重试。 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 9e0603dfe0..bb8308369e 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -843,10 +843,10 @@ 获得帮助 移出黑名单 无数据 - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use 中止本会话? 请检查网络连接并重试。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db722a5096..246fb8297e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -855,10 +855,10 @@ Get Help Unblock No Data - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use Terminate this session? Please check Internet connection and try again. diff --git a/app/src/prod/res/values-en/strings.xml b/app/src/prod/res/values-en/strings.xml index 4fa5447bdc..fd4bc8680e 100644 --- a/app/src/prod/res/values-en/strings.xml +++ b/app/src/prod/res/values-en/strings.xml @@ -5,9 +5,9 @@ Introducing an amazing new platform called NYNJA! It is a productivity and communications aggregator platform. Download it here: https://www.nynja.io/mobile and add me as a contact with my NYNJA user ID: %1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/prod/res/values-es/strings.xml b/app/src/prod/res/values-es/strings.xml index 78812d62f3..254f235df0 100644 --- a/app/src/prod/res/values-es/strings.xml +++ b/app/src/prod/res/values-es/strings.xml @@ -5,9 +5,9 @@ ¡Presentamos una nueva y sorprendente plataforma llamada NYNJA! Es una plataforma agregadora de comunicaciones y productividad. Descárgala aquí: https://www.nynja.io/mobile y agrégame como contacto con mi ID de usuario NYNJA: %1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.works/terms-of-use diff --git a/app/src/prod/res/values-ko/strings.xml b/app/src/prod/res/values-ko/strings.xml index e7d0c196c2..7d4eb06e46 100644 --- a/app/src/prod/res/values-ko/strings.xml +++ b/app/src/prod/res/values-ko/strings.xml @@ -5,9 +5,9 @@ 새로운 플랫폼 NYNJA를 소개합니다! 다양한 커뮤니케이션 웹사이트 플랫폼입니다. https://www.nynja.io/mobile 여기에서 다운로드 후, NYNJA 사용자 ID: %1$s 연락처로 저를 추가하세요 - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/prod/res/values-zh-rCN/strings.xml b/app/src/prod/res/values-zh-rCN/strings.xml index e11af51323..66e01815f8 100644 --- a/app/src/prod/res/values-zh-rCN/strings.xml +++ b/app/src/prod/res/values-zh-rCN/strings.xml @@ -5,9 +5,9 @@ 介绍一款名叫NYNJA的超棒的全新平台!这是一个集工作效率和沟通通信于一体的平台。在这里下载它:https://www.nynja.io/mobile并添加我为联系人,我的NYNJA用户名:%1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/prod/res/values-zh/strings.xml b/app/src/prod/res/values-zh/strings.xml index e11af51323..66e01815f8 100644 --- a/app/src/prod/res/values-zh/strings.xml +++ b/app/src/prod/res/values-zh/strings.xml @@ -5,9 +5,9 @@ 介绍一款名叫NYNJA的超棒的全新平台!这是一个集工作效率和沟通通信于一体的平台。在这里下载它:https://www.nynja.io/mobile并添加我为联系人,我的NYNJA用户名:%1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use diff --git a/app/src/prod/res/values/strings.xml b/app/src/prod/res/values/strings.xml index 4fa5447bdc..fd4bc8680e 100644 --- a/app/src/prod/res/values/strings.xml +++ b/app/src/prod/res/values/strings.xml @@ -5,9 +5,9 @@ Introducing an amazing new platform called NYNJA! It is a productivity and communications aggregator platform. Download it here: https://www.nynja.io/mobile and add me as a contact with my NYNJA user ID: %1$s - https://www.nynja.io/nynja-faq - https://www.nynja.io/how-to-videos - https://www.nynja.io/privacy-policy - https://www.nynja.io/terms-of-use + https://nynja.work/nynja-faq + https://nynja.work/how-to-videos + https://nynja.work/privacy-policy + https://nynja.work/terms-of-use -- GitLab From f3776cd3ba0511438b6b7a361b215be02e239b7c Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Tue, 28 Apr 2020 12:32:23 +0300 Subject: [PATCH 10/21] fixed some mistakes in the urls --- app/src/Superapp/res/values-en/strings.xml | 2 +- app/src/prod/res/values-es/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/Superapp/res/values-en/strings.xml b/app/src/Superapp/res/values-en/strings.xml index 3a7a46f88c..fd4bc8680e 100644 --- a/app/src/Superapp/res/values-en/strings.xml +++ b/app/src/Superapp/res/values-en/strings.xml @@ -8,6 +8,6 @@ https://nynja.work/nynja-faq https://nynja.work/how-to-videos https://nynja.work/privacy-policy - hhttps://nynja.work/terms-of-use + https://nynja.work/terms-of-use diff --git a/app/src/prod/res/values-es/strings.xml b/app/src/prod/res/values-es/strings.xml index 254f235df0..3cb971897d 100644 --- a/app/src/prod/res/values-es/strings.xml +++ b/app/src/prod/res/values-es/strings.xml @@ -8,6 +8,6 @@ https://nynja.work/nynja-faq https://nynja.work/how-to-videos https://nynja.work/privacy-policy - https://nynja.works/terms-of-use + https://nynja.work/terms-of-use -- GitLab From 1a0d92600a60a48b5b437574a3ea62b0a710c6b2 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Tue, 28 Apr 2020 16:11:59 +0300 Subject: [PATCH 11/21] NY-10034: [AN]: Add one more screen before login screen --- .../ui/fragments/signin/LoginFragment.java | 64 +++- .../main/res/layout/fragment_input_phone.xml | 298 ++++++++---------- .../main/res/layout/login_buttons_layout.xml | 122 +++++++ .../main/res/layout/login_choice_layout.xml | 121 +++++++ 4 files changed, 424 insertions(+), 181 deletions(-) create mode 100644 app/src/main/res/layout/login_buttons_layout.xml create mode 100644 app/src/main/res/layout/login_choice_layout.xml diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/LoginFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/LoginFragment.java index e177ed9487..1e424f5001 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/LoginFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/LoginFragment.java @@ -29,6 +29,7 @@ import android.view.WindowManager; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -88,12 +89,15 @@ public class LoginFragment extends BaseFragment implements LoginView, OnPhoneEdi @BindView(R.id.f_iphone_root) ConstraintLayout mCoordinatorLayout; @BindView(R.id.phone_ll) LinearLayout mPhoneLayout; @BindView(R.id.email_ll) LinearLayout mEmailLayout; - @BindView(R.id.login_change_type_iv) ImageView mChangeTypeIv; - @BindView(R.id.login_change_type_tv) TextView mChangeTypeTv; @BindView(R.id.email_et) EditText mEmailEt; @BindView(R.id.email_til) TextInputLayout mEmailTil; @BindView(R.id.f_iphone_btn_next) AppCompatButton mNextBtn; + @BindView(R.id.login_choice_auth_layout) ConstraintLayout mAuthStep1Layout; + @BindView(R.id.login_auth_step_layout) ConstraintLayout mAuthStep2Layout; + @BindView(R.id.login_by_email) RelativeLayout mLoginByEmailButton; + @BindView(R.id.login_by_phone) RelativeLayout mLoginByPhoneButton; + @InjectPresenter LoginPresenter mPresenter; private Handler mHandler; private boolean isUpdateVersionVisible; @@ -140,7 +144,7 @@ public class LoginFragment extends BaseFragment implements LoginView, OnPhoneEdi phoneEdt.setTextObservers(); setTextWatchers(); //initSpannableTerms(); - requestHint(); + //requestHint(); } private void setTextWatchers() { @@ -241,29 +245,63 @@ public class LoginFragment extends BaseFragment implements LoginView, OnPhoneEdi mPresenter.showCountryPickerFragment(); } - @OnClick(R.id.login_change_type_btn) void onClickChangeLoginType() { - if (mEmailLayout.getVisibility() == View.VISIBLE) { - showPhoneLogin(); - } else { + @OnClick(R.id.login_choice_by_email) void onClickLoginChoiceEmail() { + if (mAuthStep1Layout.getVisibility() == View.VISIBLE) { + onClickLoginChoiceByEmail(); + } + } + + @OnClick(R.id.login_choice_by_phone) void onClickLoginChoicePhone() { + if (mAuthStep1Layout.getVisibility() == View.VISIBLE) { + onClickLoginChoiceByPhone(); + } + } + + @OnClick(R.id.login_by_email) void onClickLoginEmail() { + if (mEmailLayout.getVisibility() != View.VISIBLE) { showEmailLogin(); } } + @OnClick(R.id.login_by_phone) void onClickLoginPhone() { + if (mPhoneLayout.getVisibility() != View.VISIBLE) { + showPhoneLogin(); + } + } + private void showPhoneLogin() { mEmailLayout.setVisibility(View.INVISIBLE); mPhoneLayout.setVisibility(View.VISIBLE); - mChangeTypeIv.setImageResource(R.drawable.icons_general_ic_email); - mChangeTypeTv.setText(R.string.signin_email); + mLoginByPhoneButton.setVisibility(View.GONE); + mLoginByEmailButton.setVisibility(View.VISIBLE); mNextBtn.setEnabled(validatePhone()); mPresenter.requestPhoneHint(); } + private void onClickLoginChoiceByEmail() { + if (mAuthStep1Layout.getVisibility() == View.VISIBLE) { + showEmailLogin(); + mAuthStep1Layout.setVisibility(View.INVISIBLE); + mAuthStep2Layout.setVisibility(View.VISIBLE); + requestHint(); + } + } + + private void onClickLoginChoiceByPhone() { + if (mAuthStep1Layout.getVisibility() == View.VISIBLE) { + showPhoneLogin(); + mAuthStep1Layout.setVisibility(View.INVISIBLE); + mAuthStep2Layout.setVisibility(View.VISIBLE); + requestHint(); + } + } + private void showEmailLogin() { mPhoneLayout.setVisibility(View.INVISIBLE); mEmailLayout.setVisibility(View.VISIBLE); - mChangeTypeIv.setImageResource(R.drawable.icons_general_ic_phone); - mChangeTypeTv.setText(R.string.signin_phone); + mLoginByEmailButton.setVisibility(View.GONE); + mLoginByPhoneButton.setVisibility(View.VISIBLE); if (mEmailEt.getText().toString().isEmpty()) { mEmailTil.setError(null); mNextBtn.setEnabled(false); @@ -273,11 +311,11 @@ public class LoginFragment extends BaseFragment implements LoginView, OnPhoneEdi mPresenter.requestEmailHint(); } - @OnClick(R.id.login_fb_btn) void onClickLoginFB() { + @OnClick({R.id.login_fb_btn, R.id.login_choice_fb_btn}) void onClickLoginFB() { mPresenter.loginBySocial(new FBSocialLoginImpl()); } - @OnClick(R.id.login_google_btn) void onClickLoginGoogle() { + @OnClick({R.id.login_google_btn, R.id.login_choice_google_btn}) void onClickLoginGoogle() { mPresenter.loginBySocial(new GoogleLoginImpl()); } diff --git a/app/src/main/res/layout/fragment_input_phone.xml b/app/src/main/res/layout/fragment_input_phone.xml index 11e1d60ee9..1bb2aa7f1b 100644 --- a/app/src/main/res/layout/fragment_input_phone.xml +++ b/app/src/main/res/layout/fragment_input_phone.xml @@ -37,211 +37,173 @@ app:layout_constraintTop_toBottomOf="@id/top_welcome_label_tv" app:srcCompat="@drawable/logo"/> - + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/f_iphone_img_logo" + tools:layout_editor_absoluteX="16dp"> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent"> - - - - - + android:layout_height="wrap_content" /> + + - - - + - + android:animateLayoutChanges="true" + app:layout_constraintTop_toTopOf="parent"> - - - + + - - + tools:text="Ukraine" /> - - - - + + + - - + - + - - - + - + + + + + + + + - + - + android:enabled="false" + android:text="@string/next" + app:layout_constraintTop_toBottomOf="@id/auth_layout" /> - - - - - - - - + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/margin_large" + android:animateLayoutChanges="true" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="parent"> - + android:layout_gravity="center_horizontal" + android:text="@string/signin.or" + android:textColor="@color/hint.grey" /> - - - - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/login_buttons_layout.xml b/app/src/main/res/layout/login_buttons_layout.xml new file mode 100644 index 0000000000..05d7f115ec --- /dev/null +++ b/app/src/main/res/layout/login_buttons_layout.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/login_choice_layout.xml b/app/src/main/res/layout/login_choice_layout.xml new file mode 100644 index 0000000000..534d7c072b --- /dev/null +++ b/app/src/main/res/layout/login_choice_layout.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- GitLab From ef7c42765a8003ae4dedb61c22aa80d06d1cf9b7 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Tue, 28 Apr 2020 22:09:54 +0300 Subject: [PATCH 12/21] NY-9820: New account creation confirmation message --- .../data/data_impl/SocialLoginDetailsImpl.kt | 7 ++ .../data_interfaces/ISocialLoginDetails.kt | 3 +- .../mvp/presenters/BaseLoginPresenter.java | 4 + .../mvp/presenters/InfoPresenter.kt | 4 + .../mvp/presenters/LoginPresenter.java | 6 +- .../ui/fragments/signin/InfoFragment.java | 47 +++++++++-- .../communicator/utils/DialogFactory.java | 79 ++++++++++++++++++- app/src/main/res/values-en/strings.xml | 6 ++ app/src/main/res/values-es/strings.xml | 6 ++ app/src/main/res/values-ko/strings.xml | 6 ++ app/src/main/res/values-zh-rCN/strings.xml | 6 ++ app/src/main/res/values-zh/strings.xml | 6 ++ app/src/main/res/values/strings.xml | 6 +- 13 files changed, 170 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_impl/SocialLoginDetailsImpl.kt b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_impl/SocialLoginDetailsImpl.kt index e203b51184..4b035926a2 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_impl/SocialLoginDetailsImpl.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_impl/SocialLoginDetailsImpl.kt @@ -15,17 +15,22 @@ class SocialLoginDetailsImpl() : ISocialLoginDetails { override var avatar: String? = null override var firstName: String? = null override var lastName: String? = null + override var isPending: Boolean = true + override var isSocial: Boolean = false constructor(parcel: Parcel) : this() { avatar = parcel.readString() firstName = parcel.readString() lastName = parcel.readString() + isPending = (parcel.readInt() > 0) + isSocial = (parcel.readInt() > 0) } constructor(data: NYNSocialLoginDetails?) : this() { avatar = data?.pictureUrl firstName = data?.firstName lastName = data?.lastName + isSocial = true } constructor(data: IAccount?) : this() { @@ -48,6 +53,8 @@ class SocialLoginDetailsImpl() : ISocialLoginDetails { parcel.writeString(avatar) parcel.writeString(firstName) parcel.writeString(lastName) + parcel.writeInt(if (isPending) 1 else 0) + parcel.writeInt(if (isSocial) 1 else 0) } override fun describeContents(): Int { diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_interfaces/ISocialLoginDetails.kt b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_interfaces/ISocialLoginDetails.kt index 07eabbea41..f149f4248a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_interfaces/ISocialLoginDetails.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/data/data_interfaces/ISocialLoginDetails.kt @@ -10,5 +10,6 @@ interface ISocialLoginDetails :Parcelable{ var firstName: String? var lastName: String? var avatar: String? - + var isPending: Boolean + var isSocial: Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BaseLoginPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BaseLoginPresenter.java index 6606a4d820..5e88205d4a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BaseLoginPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/BaseLoginPresenter.java @@ -1,6 +1,7 @@ package com.nynja.mobile.communicator.mvp.presenters; import com.nynja.mobile.communicator.data.sdk.data.data_impl.AccountImpl; +import com.nynja.mobile.communicator.data.sdk.data.data_impl.SocialLoginDetailsImpl; import com.nynja.mobile.communicator.data.sdk.data.data_interfaces.ISocialLoginDetails; import com.nynja.mobile.communicator.mvp.view.ErrorMvpView; import com.nynja.mobile.communicator.utils.StringUtils; @@ -23,6 +24,9 @@ public class BaseLoginPresenter extends BaseErrorPresent mDataManager.getAuthCodeReceiverClient().stop(); if (pending) { mDataProvider.saveAccount(account); + if (socialLoginDetails == null) { + socialLoginDetails = new SocialLoginDetailsImpl(account); + } mRouter.backToAndNavigate(new Screen(SignInNavigator.SIGN_IN), new Screen[]{ new Screen(SignInNavigator.INFO, socialLoginDetails)}); } else { diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/InfoPresenter.kt b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/InfoPresenter.kt index b8464bd529..832d5025b7 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/InfoPresenter.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/InfoPresenter.kt @@ -56,6 +56,10 @@ class InfoPresenter : BaseLoginPresenter() { mRouter.newRootScreen(NynjaNavigator.MAIN) } + fun backToLogin() { + mRouter.exit(); + } + private var userAvatar: String? = null private val mResultListener = ResultListener { resultData -> diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/LoginPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/LoginPresenter.java index 4e494a069e..50c80fff47 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/LoginPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/LoginPresenter.java @@ -171,13 +171,13 @@ public class LoginPresenter extends BaseLoginPresenter implements Soc if (mDataManager.invalidProtocol) getViewState().showErrorUpdateVersionDialog(); mDataManager.getAccountSDK().attachLoginCallback(this); - mDataManager.getAccountSDK().attachCodeCallback(this); +// mDataManager.getAccountSDK().attachCodeCallback(this); } @Override public void detachView(LoginView view) { // mDataManager.getAccountSDK().detachLoginCallback(this); -// mDataManager.getAccountSDK().detachCodeCallback(this); + mDataManager.getAccountSDK().detachCodeCallback(this); mDataManager.getAccountSDK().detachManageProfileCallback(mAccountListener); super.detachView(view); } @@ -192,7 +192,7 @@ public class LoginPresenter extends BaseLoginPresenter implements Soc public void attachView(LoginView view) { super.attachView(view); // mDataManager.getAccountSDK().attachLoginCallback(this); -// mDataManager.getAccountSDK().attachCodeCallback(this); + mDataManager.getAccountSDK().attachCodeCallback(this); mDataManager.getAccountSDK().attachManageProfileCallback(mAccountListener); //addDisposable(mDataManager.subscribeToProfile() // .filter(profile -> profile.getRoster() != null) diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/InfoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/InfoFragment.java index ee91283fd6..5e2db5dfa2 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/InfoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/signin/InfoFragment.java @@ -2,9 +2,13 @@ package com.nynja.mobile.communicator.ui.fragments.signin; import android.Manifest; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.ArrayRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.TextInputLayout; +import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -36,6 +40,10 @@ import com.nynja.mobile.communicator.utils.SpannableUtils; import com.nynja.mobile.communicator.utils.StringUtils; import com.nynja.mobile.communicator.utils.Utils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import butterknife.BindView; import butterknife.OnCheckedChanged; import butterknife.OnClick; @@ -85,8 +93,9 @@ public class InfoFragment extends BaseFragment implements InfoView, OnBackPresse initSpannableTerms(); if (getArguments() != null) { - if (getArguments().getParcelable(KEY_SOCIAL_DATA) != null) { - ISocialLoginDetails socialLoginDetails = getArguments().getParcelable(KEY_SOCIAL_DATA); + ISocialLoginDetails socialLoginDetails = getArguments().getParcelable(KEY_SOCIAL_DATA); + boolean isSocial = (socialLoginDetails != null && socialLoginDetails.isSocial()); + if (isSocial) { if (StringUtils.isNotEmpty(socialLoginDetails.getFirstName())) { mFirstNameEt.setText(socialLoginDetails.getFirstName()); } @@ -97,8 +106,12 @@ public class InfoFragment extends BaseFragment implements InfoView, OnBackPresse mPresenter.presetAvatar(socialLoginDetails.getAvatar()); } } + boolean isPending = (socialLoginDetails != null && socialLoginDetails.isPending()); + if (isPending) { + generateContextDialog(); + } - boolean hide = (getArguments().containsKey(KEY_SOCIAL_DATA) || !mPresenter.isLoggedIn()); + boolean hide = (isSocial || !mPresenter.isLoggedIn()); mAvatarIv.setVisibility(hide ? View.GONE : View.VISIBLE); mPresenter.setSignedInUserFlag(!hide); } @@ -138,6 +151,30 @@ public class InfoFragment extends BaseFragment implements InfoView, OnBackPresse } + private void generateContextDialog() { + new Handler(Looper.getMainLooper()).post(() ->{ + String title = getString(R.string.new_account_alert_message_body) ; + DialogFactory.showModalPurchaseStoreItem(getActivity(), getString(R.string.new_account_alert_title), + title, + getString(R.string.new_account_alert_action_create_new), getString(R.string.call_no_dont_ask_me_again), + (dialogInterface, i) -> { + // positive - continue pending account creation + onResumed(); + }, + (dialogInterface, i) -> { + //negative - go back to login with different accouint + mPresenter.backToLogin(); + }); + }); + } + + private void onResumed() { + if (getActivity() instanceof BaseActivity) { + ((BaseActivity) getActivity()).setOnBackPressedListener(this); + Utils.showKeyboard(getActivity(), mUserNameEt); + } + } + private void validateUserData(InfoPresenter.UserData userData) { mPresenter.validateData(userData, mTermsOfUse.isChecked()); } @@ -339,10 +376,6 @@ public class InfoFragment extends BaseFragment implements InfoView, OnBackPresse @Override public void onResume() { super.onResume(); - if (getActivity() instanceof BaseActivity) { - ((BaseActivity) getActivity()).setOnBackPressedListener(this); - Utils.showKeyboard(getActivity(), mUserNameEt); - } } @Override public void onPause() { diff --git a/app/src/main/java/com/nynja/mobile/communicator/utils/DialogFactory.java b/app/src/main/java/com/nynja/mobile/communicator/utils/DialogFactory.java index 16df41edf1..ea23d5bb11 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/utils/DialogFactory.java +++ b/app/src/main/java/com/nynja/mobile/communicator/utils/DialogFactory.java @@ -234,7 +234,7 @@ public class DialogFactory { return dialogBuilder.create(); } - public static AlertDialog createContextPopupDialog(Activity activity, int title, + public static AlertDialog createContextPopupDialog(Activity activity, @ArrayRes List itemsRes, DialogInterface.OnClickListener onClickListener) { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity, @@ -245,9 +245,6 @@ public class DialogFactory { } dialogBuilder.setAdapter(arrayAdapter, onClickListener); AlertDialog dialog = dialogBuilder.create(); - if (title > 0) { - dialog.setTitle(title); - } ListView listView = dialog.getListView(); listView.setDivider(new ColorDrawable(ContextCompat.getColor(activity, R.color.lite_grey))); listView.setDividerHeight(1); @@ -256,6 +253,50 @@ public class DialogFactory { return dialog; } + public static AlertDialog createContextPopupDialog(Activity activity, int title, + @ArrayRes List itemsRes, + DialogInterface.OnClickListener onClickListener) { + AlertDialog dialog = createContextPopupDialog(activity, itemsRes, onClickListener); + if (title > 0) { + dialog.setTitle(title); + } + return dialog; + } + + public static AlertDialog createContextPopupDialog(Activity activity, String title, + @ArrayRes List itemsRes, + DialogInterface.OnClickListener onClickListener) { + AlertDialog dialog = createContextPopupDialog(activity, itemsRes, onClickListener); + if (StringUtils.isNotEmpty(title)) { + dialog.setTitle(title); + } + return dialog; + } + + public static AlertDialog createContextPopupDialog(Activity activity, + int title, + int message, + @ArrayRes List itemsRes, + DialogInterface.OnClickListener onClickListener) { + AlertDialog dialog = createContextPopupDialog(activity, title, itemsRes, onClickListener); + if (message > 0) { + dialog.setMessage(activity.getString(message)); + } + return dialog; + } + + public static AlertDialog createContextPopupDialog(Activity activity, + int title, + String message, + @ArrayRes List itemsRes, + DialogInterface.OnClickListener onClickListener) { + AlertDialog dialog = createContextPopupDialog(activity, title, itemsRes, onClickListener); + if (StringUtils.isNotEmpty(message)) { + dialog.setMessage(message); + } + return dialog; + } + public static AlertDialog createDialogWithCustomView(final Activity activity, String message, View customView, DialogInterface.OnClickListener yesClickListener, @@ -514,4 +555,34 @@ public class DialogFactory { return dialog; } + + public static Dialog showModalPurchaseStoreItem(Context context, + String title, + String msg, + @Nullable String positiveButtonText, + @Nullable String negativeButtonText, + @Nullable DialogInterface.OnClickListener positiveListener, + @Nullable DialogInterface.OnClickListener negativeListener) { + if (context == null) return null; + AlertDialog.Builder builder = new AlertDialog.Builder(context, + R.style.Nynja_PopupMenu_AlertDialog + /*R.style.Nynja_Dialog*/ + ); + builder.setIcon(android.R.drawable.ic_dialog_info); + builder.setTitle(title); + builder.setMessage(msg); + builder.setPositiveButton(positiveButtonText, positiveListener); + builder.setNegativeButton(negativeButtonText, negativeListener); + builder.setCancelable(false); + Dialog dialog = builder.create(); + dialog.show(); + + TextView tv = dialog.findViewById(android.R.id.message); + if (tv != null) tv.setGravity(Gravity.CENTER); + + changeMessageTextSize(dialog); + + return dialog; + } + } \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 4d37bdf51d..9382af3534 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1324,4 +1324,10 @@ Phone number: +%1$s Please select at least one message. + + "Create New NYNJA Account!" + Click \"Create New NYNJA Account\" below to confirm. If you already have a NYNJA account, click \"Use Another Account\" + Create New NYNJA Account + Use Another Account + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 22bd5fd832..e30e89ab3f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + "Create New NYNJA Account!" + Click \"Create New NYNJA Account\" below to confirm. If you already have a NYNJA account, click \"Use Another Account\" + Create New NYNJA Account + Use Another Account + diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 1f467439e7..7618258bc0 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + "Create New NYNJA Account!" + Click \"Create New NYNJA Account\" below to confirm. If you already have a NYNJA account, click \"Use Another Account\" + Create New NYNJA Account + Use Another Account + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9e0603dfe0..6b1396940b 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + "Create New NYNJA Account!" + Click \"Create New NYNJA Account\" below to confirm. If you already have a NYNJA account, click \"Use Another Account\" + Create New NYNJA Account + Use Another Account + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 9e0603dfe0..6b1396940b 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1323,4 +1323,10 @@ Uploading View + + "Create New NYNJA Account!" + Click \"Create New NYNJA Account\" below to confirm. If you already have a NYNJA account, click \"Use Another Account\" + Create New NYNJA Account + Use Another Account + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db722a5096..f4ce29dee2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1325,5 +1325,9 @@ Stop sharing Stop video - + + "Create New NYNJA Account!" + Click \"Create New NYNJA Account\" below to confirm. If you already have a NYNJA account, click \"Use Another Account\" + Create New NYNJA Account + Use Another Account -- GitLab From 9d8be29a2f043cec0f0af682a9ff1b18d979691f Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Wed, 29 Apr 2020 11:32:37 +0300 Subject: [PATCH 13/21] -fixed video feeds flickering -fixed buffer plane copy crash from core --- .../conference/ConferenceVideoAdapter.java | 9 ++++++ .../conference/ConferenceVideoItemVh.java | 28 ++++++++++++------- .../mobile/communicator/ui/base/BaseVH.java | 13 ++++----- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index 2189637ddb..186842570b 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -33,12 +33,21 @@ public class ConferenceVideoAdapter> exten super(list); this.mOnConferenceItemClickListener = onConferenceItemClickListener; mHoldersSet = new HashSet<>(); + setHasStableIds(true); } public void setOnItemClickListener(OnConferenceItemClickListener onConferenceItemClickListener) { this.mOnConferenceItemClickListener = onConferenceItemClickListener; } + @Override + public long getItemId(int position) { + if (position < getItemCount()) { + return getItem(position).memberId.hashCode(); + } + return -1L; + } + public void setIsModerator(boolean isModerator) { this.mIsModerator = isModerator; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 94118680a6..4bc577f1bd 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -20,6 +20,7 @@ import org.webrtc.RendererCommon; import org.webrtc.SurfaceViewRenderer; import butterknife.BindView; +import butterknife.ButterKnife; import kotlin.jvm.Synchronized; import timber.log.Timber; @@ -48,6 +49,21 @@ public class ConferenceVideoItemVh extends BaseVH { this.mListener = onConferenceItemClickListener; } + + @Override public void bind() { + //mUnbinder = ButterKnife.bind(this, itemView); + } + + @Override public void bind(ConferenceListItem item, int position) { + mPosition = position; + if (mUnbinder != null) { + //mUnbinder.unbind(); + } else { + mUnbinder = ButterKnife.bind(this, itemView); + } + setData(item); + } + public SurfaceViewRenderer getVideoFeed() { return mVideoFeed; } @@ -94,17 +110,9 @@ public class ConferenceVideoItemVh extends BaseVH { } public void onViewRecycled() { - onViewDetachedFromWindow(); - } - - @Override - public void onUnbind() { - super.onUnbind(); - -// onViewRecycled(); + enableVideoForTrack(false); } - @Synchronized public void releaseVideoCallRrenderers() { removeVideoRendererForTrack(); @@ -230,8 +238,8 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void enableVideoForTrack(boolean enable) { if (mItem == null) return; + if (mItem.isTrackActive == 0) return; if (StringUtils.isNotEmpty(mItem.participantId)) { - mItem.isTrackActive = 1; ConferenceVideoModule.getInstance().enableVideoForTrack(mItem.participantId, enable); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java index 9ff3b5270f..1023fe205e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseVH.java @@ -25,7 +25,7 @@ import butterknife.Unbinder; public abstract class BaseVH extends RecyclerView.ViewHolder { private Context mContext; - private Unbinder mUnbinder; + protected Unbinder mUnbinder; protected int mPosition = -1; public BaseVH(ViewGroup parent, @LayoutRes int layoutId) { @@ -35,15 +35,16 @@ public abstract class BaseVH extends RecyclerView.ViewHolder { public BaseVH(View itemView) { super(itemView); mContext = itemView.getContext(); + bind(); + } + + public void bind() { mUnbinder = ButterKnife.bind(this, itemView); } public void bind(I item, int position) { - if (mUnbinder != null) { - onUnbind(); - mUnbinder.unbind(); - } mPosition = position; + if (mUnbinder != null) mUnbinder.unbind(); mUnbinder = ButterKnife.bind(this, itemView); setData(item); } @@ -54,7 +55,5 @@ public abstract class BaseVH extends RecyclerView.ViewHolder { public abstract void setData(I item); - public void onUnbind() {} - public void onClick() {} } -- GitLab From 3a4e7a5401937546596a366522e65e02a72e4767 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Wed, 29 Apr 2020 16:40:35 +0300 Subject: [PATCH 14/21] -conferemnce participants muted icon changed; -going to video participants view on start the camera --- .../data/sdk/calls/ConferenceListItem.java | 5 + .../ui/activities/calls/CallActivity.java | 32 ++++-- .../conference/ConferenceVideoAdapter.java | 7 +- .../conference/ConferenceVideoItemVh.java | 5 +- .../conference/ConferenceCallFragment.java | 3 +- .../main/res/drawable/ic_mute_mic_icon.xml | 15 +++ .../res/layout/li_conference_participant.xml | 4 +- .../main/res/layout/li_conference_video.xml | 103 +++++++++--------- 8 files changed, 106 insertions(+), 68 deletions(-) create mode 100644 app/src/main/res/drawable/ic_mute_mic_icon.xml diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java index 4f3b6c0dcf..e44ee8610c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java @@ -40,6 +40,7 @@ public class ConferenceListItem extends Object { public boolean isScreenPaused; public int isTrackActive; public boolean isVideoFullScreen; + public boolean isSpeaking; protected ConferenceListItem() { phoneId = ""; @@ -56,6 +57,7 @@ public class ConferenceListItem extends Object { isScreenPaused = false; isTrackActive = 0; isVideoFullScreen = false; + isSpeaking = false; } protected ConferenceListItem(ConferenceItemType type, String phoneId, String memberId, @@ -78,6 +80,7 @@ public class ConferenceListItem extends Object { this.isScreenPaused = false; this.isTrackActive = 0; this.isVideoFullScreen = false; + this.isSpeaking = false; } protected ConferenceListItem(ConferenceItemType type, NYNCallParticipant participant, @@ -98,6 +101,7 @@ public class ConferenceListItem extends Object { this.hasScreen = participant.hasScreen(); this.isVideoPaused = participant.isVideoPaused(); this.isScreenPaused = participant.isScreenPaused(); + this.isSpeaking = participant.isSpeaking(); this.isTrackActive = 0; this.isVideoFullScreen = false; } @@ -135,6 +139,7 @@ public class ConferenceListItem extends Object { this.isMe = participant.isMe; this.isFriend = participant.isFriend; this.isMuted = participant.isMuted; + this.isSpeaking = participant.isSpeaking; this.isVideoFullScreen = false; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java index b52eaee87a..ae1a3a3df5 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java @@ -212,6 +212,10 @@ public class CallActivity extends BaseActivity implements CallActivityView { return mIndicator; } + public void goToPage(ActiveCallPagerAdapter.CallPages page) { + mIndicator.setCurrentItem(mPagerAdapter.getFragmentPositionByType(page)); + } + @TargetApi(21) private void prepareScreenCapture() { MediaProjectionManager mediaProjectionManager = @@ -353,28 +357,28 @@ public class CallActivity extends BaseActivity implements CallActivityView { @Override public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) { mHandler.postDelayed(() -> { - tryUpdateConferenceVideoScreen(activeConferenceCall, true); + tryUpdateConferenceVideoScreen(activeConferenceCall, true, false); }, Consts.DELAY_100); } @Override public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) { mHandler.postDelayed(() -> { - tryUpdateConferenceVideoScreen(activeConferenceCall, false); + tryUpdateConferenceVideoScreen(activeConferenceCall, false, false); }, Consts.DELAY_100); } @Override public void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) { mHandler.postDelayed(() -> { - tryUpdateConferenceVideoScreen(activeConferenceCall, true); + tryUpdateConferenceVideoScreen(activeConferenceCall, true, true); }, Consts.DELAY_100); } @Override public void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) { mHandler.postDelayed(() -> { - tryUpdateConferenceVideoScreen(activeConferenceCall, false); + tryUpdateConferenceVideoScreen(activeConferenceCall, false, true); }, Consts.DELAY_200); } @@ -383,18 +387,24 @@ public class CallActivity extends BaseActivity implements CallActivityView { } @Synchronized - private void tryUpdateConferenceVideoScreen(ActiveConferenceCall activeConferenceCall, boolean show) { + private void tryUpdateConferenceVideoScreen(ActiveConferenceCall activeConferenceCall, + boolean show, boolean isMyVideo) { if (activeConferenceCall == null) { return; } if (!activeConferenceCall.isConference()) { return; } - if (show && mPagerAdapter.isConferenceVideoActive) return; - - boolean updated = false; int currentItem = mIndicator.getCurrentItem(); ActiveCallPagerAdapter.CallPages page = mPagerAdapter.getPageByPosition(currentItem); + if (show && mPagerAdapter.isConferenceVideoActive) { + if (show && isMyVideo && page != ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment) { + goToPage(ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment); + } + return; + } + + boolean updated = false; synchronized (mPagerAdapter) { if (show && (activeConferenceCall.mData.hasRemoteVideoTrack() || activeConferenceCall.mData.isOwnStreamActive)) { mViewPager.removeOnPageChangeListener(mOnPageChangeListener); @@ -414,8 +424,12 @@ public class CallActivity extends BaseActivity implements CallActivityView { } // set to position 1 if (updated) { + + if (show && isMyVideo) { + page = ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment; + } mIndicator.setViewPager(mViewPager, mPagerAdapter.getFragmentPositionByType(page)); - mIndicator.notifyDataSetChanged(); + //mIndicator.notifyDataSetChanged(); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index 186842570b..e8fce8020c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -43,7 +43,7 @@ public class ConferenceVideoAdapter> exten @Override public long getItemId(int position) { if (position < getItemCount()) { - return getItem(position).memberId.hashCode(); + return getItem(position).hashCode(); } return -1L; } @@ -86,7 +86,6 @@ public class ConferenceVideoAdapter> exten public void onBindViewHolder(T holder, int position) { super.onBindViewHolder(holder, position); if (mScreenWidth > 0) { - int itemPadding = 0; float divH = ConferenceVideoModule.getInstance().getWidthDiv(position); float divV = ConferenceVideoModule.getInstance().getHeightDiv(position); //////////////////////////////////////////////////// @@ -95,8 +94,8 @@ public class ConferenceVideoAdapter> exten // divH = 1f; divV = 1f; //} //////////////////////////////////////////////////// - int itemWidth = (int) ((mScreenWidth - itemPadding) / divH); - int itemHeight = (int) ((mScreenHeight - itemPadding) / divV); + int itemWidth = (int) (mScreenWidth / divH); + int itemHeight = (int) (mScreenHeight / divV); ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); if (divV == 2f) { layoutParams.height = itemHeight - STATIC_BOTTOM_HEIGHT_OFFSET; diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 4bc577f1bd..14adbb1138 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -6,6 +6,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.nynja.mobile.communicator.R; @@ -135,9 +136,9 @@ public class ConferenceVideoItemVh extends BaseVH { // already joined in Conference drawIsMutedIfNeeded(item); drawIsScfreenSharingIfNeeded(item); - drawIsActiveVideoIfNeeded(item); +// drawIsActiveVideoIfNeeded(item); drawIsFeedVideoIfNeeded(item.hasVideo); - if (mItem != null && mItem.isMe) { + if (mItem != null && mItem.isSpeaking) { mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke); } else { mFeedFrameLayout.setBackgroundColor(Color.TRANSPARENT); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java index a298c7e639..a9968258c4 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java @@ -274,7 +274,8 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, @OnClick(R.id.open_share_screen) void openShareScreen() { if (callActivity != null) { - callActivity.getPageIndicator().setCurrentItem(ActiveCallPagerAdapter.CallPages.ShareScreenFragment.ordinal()); + callActivity.goToPage(ActiveCallPagerAdapter.CallPages.ShareScreenFragment); +// callActivity.getPageIndicator().setCurrentItem(ActiveCallPagerAdapter.CallPages.ShareScreenFragment.ordinal()); } } diff --git a/app/src/main/res/drawable/ic_mute_mic_icon.xml b/app/src/main/res/drawable/ic_mute_mic_icon.xml new file mode 100644 index 0000000000..ee444f25f1 --- /dev/null +++ b/app/src/main/res/drawable/ic_mute_mic_icon.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/li_conference_participant.xml b/app/src/main/res/layout/li_conference_participant.xml index b01f8f61d5..4977502ffe 100644 --- a/app/src/main/res/layout/li_conference_participant.xml +++ b/app/src/main/res/layout/li_conference_participant.xml @@ -33,9 +33,7 @@ android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:srcCompat="@drawable/v_ic_mute_member" /> + app:srcCompat="@drawable/ic_mute_mic_icon" /> + @@ -42,63 +43,67 @@ app:layout_constraintTop_toTopOf="parent" tool:visibility="visible" /> - - - - - - - + android:orientation="horizontal"> + + + + + + + + + + + \ No newline at end of file -- GitLab From 44806a9d907694c6a28691a9c17207c811214ba8 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Thu, 30 Apr 2020 03:08:19 +0300 Subject: [PATCH 15/21] -fixed some resource leaking -ordering and full item showing with single feed in the screen -try to scroll to own feed item in the feeds view --- .../conference/ConferenceVideoModule.java | 48 +++++++++++-------- .../ui/activities/calls/CallActivity.java | 12 +++-- .../conference/ActiveCallPagerAdapter.java | 12 +++++ .../conference/ConferenceVideoAdapter.java | 29 ++++++++--- .../conference/ConferenceVideoItemVh.java | 7 ++- .../conference/ConferenceVideoFragment.java | 21 +++++++- 6 files changed, 96 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index c04375018f..b0e4b05705 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -14,9 +14,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Set; +import kotlin.jvm.Synchronized; + public class ConferenceVideoModule { private static ConferenceVideoModule mInstance = null; + public static final int MAX_VIDEO_FEEDS_COLUIMN_SIZE = 2; + public static final int MAX_VIDEO_FEEDS_COUNT_PER_PAGE = 4; private DataManager mDataManager; // Call worker object @@ -46,6 +50,7 @@ public class ConferenceVideoModule { public void reset() { // ToDo:... + mActiveVideoParticipantsMap.clear(); mCurrentActiveCall = null; } @@ -79,6 +84,7 @@ public class ConferenceVideoModule { return trackId; } + @Synchronized public ArrayList getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return new ArrayList<>(); Set participatIds = mActiveVideoParticipantsMap.keySet(); @@ -97,6 +103,7 @@ public class ConferenceVideoModule { for (String participantId : participatIds) { if (!mActiveVideoParticipantsMap.containsKey(participantId)) { + enableVideoForTrack(participantId, false); String trackId = getTrackIdByParticipantId(participantId); setVideoRendererForTrack(null, trackId, StringUtils.isEmpty(trackId)); } @@ -108,7 +115,7 @@ public class ConferenceVideoModule { public float getSpanSize(int position) { // if (mActiveVideoParticipantsCount <= 4) return 1; -// switch (position % 4) { +// switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { // case 0: // case 1: // { @@ -120,49 +127,50 @@ public class ConferenceVideoModule { // return 1; // } // return 2; - return ((int)(position/4)) +1; + if (getWidthDiv(position) == 1 && getHeightDiv(position) == 1) return 1; + return 2; } - public float getWidthDiv(int position) { - if (mActiveVideoParticipantsCount <= 2) return 1f; - switch (position % 4) { + public int getWidthDiv(int position) { + if (mActiveVideoParticipantsCount <= 2) return 1; + switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { case 0: { - if (position == mActiveVideoParticipantsCount -1) return 1f; - if (position == mActiveVideoParticipantsCount -2) return 1f; - return 2f; + if (position == mActiveVideoParticipantsCount -1) return 1; + if (position == mActiveVideoParticipantsCount -2) return 1; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } case 1: { - if (position == mActiveVideoParticipantsCount -1) return 1f; - if (position == mActiveVideoParticipantsCount -2) return 2f; - return 2f; + if (position == mActiveVideoParticipantsCount -1) return 1; + if (position == mActiveVideoParticipantsCount -2) return 2; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } case 2: { - return 2f; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } // next 3 items span 2 columns each case 3: { - return 2f; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } } - return 1f; + return 1; } - public float getHeightDiv(int position) { - if (mActiveVideoParticipantsCount <= 1) return 1f; - switch (position % 4) { + public int getHeightDiv(int position) { + if (mActiveVideoParticipantsCount <= 1) return 1; + switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { case 0: { - if (position == mActiveVideoParticipantsCount -1) return 1f; - return 2f; + if (position == mActiveVideoParticipantsCount -1) return 1; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } } - return 2f; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } protected ConferenceListItem conferenceParticipant(NYNCallParticipant participant, diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java index ae1a3a3df5..d1b02a96e2 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java @@ -397,8 +397,10 @@ public class CallActivity extends BaseActivity implements CallActivityView { } int currentItem = mIndicator.getCurrentItem(); ActiveCallPagerAdapter.CallPages page = mPagerAdapter.getPageByPosition(currentItem); + boolean goToMyFeed = (show && isMyVideo && page != ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment); if (show && mPagerAdapter.isConferenceVideoActive) { - if (show && isMyVideo && page != ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment) { + if (goToMyFeed) { + mPagerAdapter.tryToGoTooMyVideoFeed(); goToPage(ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment); } return; @@ -425,11 +427,15 @@ public class CallActivity extends BaseActivity implements CallActivityView { // set to position 1 if (updated) { - if (show && isMyVideo) { + if (goToMyFeed) { page = ActiveCallPagerAdapter.CallPages.ConferenceVideoFragment; } mIndicator.setViewPager(mViewPager, mPagerAdapter.getFragmentPositionByType(page)); - //mIndicator.notifyDataSetChanged(); + mIndicator.notifyDataSetChanged(); + + mHandler.postDelayed(() -> { + mPagerAdapter.tryToGoTooMyVideoFeed(); + }, Consts.DELAY_200); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java index e44338e767..803e6a4f02 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java @@ -293,4 +293,16 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { fragment.onConfigurationChanged(newConfig); } } + + public void tryToGoTooMyVideoFeed() { + for (CallPages callPage : callPages) { + if (callPage == CallPages.ConferenceVideoFragment) { + final String itemId = makeFragmentId(getItemId(callPage.ordinal())); + BaseFragment fragment = mAdapterPages.get(itemId); + if (fragment != null && fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment)fragment).tryToGoTooMyVideoFeed();; + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index e8fce8020c..8adb1695d0 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -1,12 +1,15 @@ package com.nynja.mobile.communicator.ui.adapters.conference; import android.content.Context; +import android.graphics.Insets; import android.support.annotation.NonNull; import android.util.DisplayMetrics; +import android.util.Size; import android.view.Display; import android.view.ViewGroup; import android.view.WindowManager; +import com.nynja.mobile.communicator.NynjaApp; import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; @@ -18,9 +21,10 @@ import com.nynja.mobile.communicator.ui.base.BaseVH; import java.util.HashSet; import java.util.List; +import static com.nynja.mobile.communicator.data.conference.ConferenceVideoModule.MAX_VIDEO_FEEDS_COLUIMN_SIZE; + public class ConferenceVideoAdapter> extends BaseAdapter { - private static int STATIC_BOTTOM_HEIGHT_OFFSET = 60; private OnConferenceItemClickListener mOnConferenceItemClickListener; private boolean mIsModerator = false; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @@ -66,17 +70,26 @@ public class ConferenceVideoAdapter> exten clear(); } + public int getoMyVideoFeedPostion() { + int pos = 0; + for (ConferenceListItem item : getItems()) { + if (item.isMe) return pos; + ++pos; + } + return -1; + } + @NonNull @Override public T onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { ConferenceVideoItemVh viewHolder = new ConferenceVideoItemVh(viewGroup, mIsModerator); viewHolder.setOnItemClickListener(mOnConferenceItemClickListener); if (viewGroup.getContext() instanceof CallActivity) { - WindowManager wm = (WindowManager) viewHolder.itemView.getContext().getSystemService(Context.WINDOW_SERVICE); + WindowManager wm = (WindowManager) NynjaApp.getComponent().context().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); display.getMetrics(mDisplayMetrics); mScreenWidth = mDisplayMetrics.widthPixels; - mScreenHeight = mDisplayMetrics.heightPixels; + mScreenHeight = (int) (mDisplayMetrics.heightPixels - mDisplayMetrics.densityDpi/mDisplayMetrics.density); } mHoldersSet.add(viewHolder); return (T) viewHolder; @@ -97,12 +110,16 @@ public class ConferenceVideoAdapter> exten int itemWidth = (int) (mScreenWidth / divH); int itemHeight = (int) (mScreenHeight / divV); ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); - if (divV == 2f) { - layoutParams.height = itemHeight - STATIC_BOTTOM_HEIGHT_OFFSET; + if (divV == MAX_VIDEO_FEEDS_COLUIMN_SIZE) { + layoutParams.height = -1; } else { layoutParams.height = itemHeight; } - layoutParams.width = itemWidth; + if (divH == MAX_VIDEO_FEEDS_COLUIMN_SIZE) { + layoutParams.width = itemWidth; + } else { + layoutParams.width = -1; + } holder.itemView.setLayoutParams(layoutParams); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 14adbb1138..2032a823de 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -6,7 +6,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import com.nynja.mobile.communicator.R; @@ -108,6 +107,7 @@ public class ConferenceVideoItemVh extends BaseVH { public void onViewDetachedFromWindow() { enableVideoForTrack(false); + removeVideoRendererForTrack(); } public void onViewRecycled() { @@ -216,6 +216,7 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void setVideoRendererForTrack() { + if (!mIsRenderersInitialized) return; if (mItem == null) return; if (mItem.isTrackActive == 1) return; String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); @@ -227,6 +228,7 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void removeVideoRendererForTrack() { + if (!mIsRenderersInitialized) return; if (mItem == null) return; if (mItem.isTrackActive == 0) return; String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); @@ -238,10 +240,11 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void enableVideoForTrack(boolean enable) { + if (!mIsRenderersInitialized) return; if (mItem == null) return; - if (mItem.isTrackActive == 0) return; if (StringUtils.isNotEmpty(mItem.participantId)) { ConferenceVideoModule.getInstance().enableVideoForTrack(mItem.participantId, enable); + refreshFeedVideo(); } } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 7d7d25aef1..1c4c1015ae 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -58,6 +58,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV private Handler mHandler; GridLayoutManager mGridLayoutManager; private ArrayList mMembersList = new ArrayList<>(); + private boolean mTryToGoTooMyVideoFeed = false; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { @@ -74,8 +75,8 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV public void onDestroyView() { mRecyclerView.clearOnChildAttachStateChangeListeners(); mRecyclerView.clearOnScrollListeners(); + mRecyclerView.setAdapter(null); mConfParticipantsAdapter.releaseVideoCallRrenderers(); - mConfParticipantsAdapter = null; super.onDestroyView(); } @@ -87,9 +88,9 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV @Override public void onDestroy() { + mConfParticipantsAdapter = null; super.onDestroy(); ConferenceVideoModule.getInstance().setCurrentActiveCall(null); - ContextUtils.releaseRootEglBase(); } @@ -97,6 +98,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV public void onResume() { super.onResume(); isActive = true; + scrollToMyFeedPosition(); } @Override @@ -327,6 +329,21 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV //this.isActive = isActive; } + public void tryToGoTooMyVideoFeed() { + mTryToGoTooMyVideoFeed = false; + if (isActive) { + scrollToMyFeedPosition(); + } + } + + private void scrollToMyFeedPosition() { + if (mTryToGoTooMyVideoFeed) { + mTryToGoTooMyVideoFeed = false; + int myPos = mConfParticipantsAdapter.getoMyVideoFeedPostion(); + if (myPos >= 0) mRecyclerView.scrollToPosition(myPos); + } + } + public void setActiveState(boolean active) { ActiveConferenceCall activeConferenceCall = mConferencePresenter.getActiveConference(); isActive = active; -- GitLab From 9f20b8302e50521202bc65a13b1a353ff85c95cd Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Thu, 30 Apr 2020 14:42:41 +0300 Subject: [PATCH 16/21] -added green rectangle for feead active speakers in the video feeds screen -marked my own feed in red rectangle --- .../data/conference/ConferenceVideoModule.java | 14 ++++++++++++++ .../data/sdk/ConferenceSDKPresenter.java | 4 +++- .../data/sdk/calls/ConferenceSDKListener.java | 4 +++- .../data/sdk/calls/ConferenceSDKModule.java | 4 +++- .../mvp/presenters/ConferenceCallPresenter.java | 2 +- .../mvp/presenters/ConferenceVideoPresenter.java | 12 ++++++++++-- .../communicator/mvp/view/ConferenceVideoView.java | 2 +- .../conference/ConferenceVideoItemVh.java | 13 ++++++++++--- .../conference/ConferenceVideoFragment.java | 10 ++-------- ...roke.xml => video_feed_square_stroke_green.xml} | 0 .../res/drawable/video_feed_square_stroke_red.xml | 9 +++++++++ 11 files changed, 56 insertions(+), 18 deletions(-) rename app/src/main/res/drawable/{video_feed_square_stroke.xml => video_feed_square_stroke_green.xml} (100%) create mode 100644 app/src/main/res/drawable/video_feed_square_stroke_red.xml diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index b0e4b05705..363253e815 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -113,6 +113,20 @@ public class ConferenceVideoModule { return new ArrayList<>(mActiveVideoParticipantsMap.values()); } + @Synchronized + public ArrayList getUpdatedActiveSpeakersParticipants(ArrayList participantIds) { + ArrayList items = new ArrayList<>(mActiveVideoParticipantsMap.values()); + for (ConferenceListItem item : items) { + item.isSpeaking = false; + for (String participandId : participantIds) { + if (participandId.contentEquals(item.participantId)) { + item.isSpeaking = true; + } + } + } + return items; + } + public float getSpanSize(int position) { // if (mActiveVideoParticipantsCount <= 4) return 1; // switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java index 4f8e3242fe..9c1ae7305c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java @@ -9,6 +9,8 @@ import com.nynja.mobile.communicator.mvp.view.ErrorMvpView; import com.nynja.sdk.NYNCall; import com.nynja.sdk.NYNCallHistoryCode; +import java.util.ArrayList; + /** * Created by Ergyun Syuleyman on 4/25/18. */ @@ -75,7 +77,7 @@ public abstract class ConferenceSDKPresenter extends Bas @Override public void tryCallCameraStateChange(boolean pause) {} - @Override public void onActiveSpeakersUpdate(String activeSpeakers) {} + @Override public void onActiveSpeakersUpdate(String activeSpeakers, ArrayList participantIds) {} @Override public void onMuteStateChangedByHost(boolean isMuted) {} diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java index def48a97ca..4710d6de07 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java @@ -4,6 +4,8 @@ import com.nynja.mobile.communicator.data.conference.ActiveCallBase; import com.nynja.sdk.NYNCall; import com.nynja.sdk.NYNCallHistoryCode; +import java.util.ArrayList; + /** * Created by Ergyun Syuleyman on 4/19/18. */ @@ -60,7 +62,7 @@ public interface ConferenceSDKListener { void tryCallCameraStateChange(boolean pause); - void onActiveSpeakersUpdate(String activeSpeakers); + void onActiveSpeakersUpdate(String activeSpeakers, ArrayList participantIds); void onMuteStateChangedByHost(boolean isMuted); diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index edd53689d1..00d3d130cf 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -1134,6 +1134,7 @@ public class ConferenceSDKModule extends BaseSDKModule { if (call == null) return; if (!mActiveConference.mConference.callId().contentEquals(call.callId())) return; String activeSpeakers = ""; + ArrayList participantIds = new ArrayList<>(); NYNCallParticipantArray participantArray = call.getParticipants(); for (int index = 0; index < participantArray.size(); index++) { NYNCallParticipant participant = participantArray.get(index); @@ -1144,9 +1145,10 @@ public class ConferenceSDKModule extends BaseSDKModule { } if (!activeSpeakers.isEmpty()) activeSpeakers += ", "; activeSpeakers += participant.getName(); + participantIds.add(participant.getParticipantId()); } for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) - conferenceSDKListener.onActiveSpeakersUpdate(activeSpeakers); + conferenceSDKListener.onActiveSpeakersUpdate(activeSpeakers, participantIds); } private synchronized void onMuteStateChangedByHost(NYNCall call, boolean isMuted) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java index 9565cb8cfe..f4bb992891 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceCallPresenter.java @@ -417,7 +417,7 @@ public class ConferenceCallPresenter extends ConferenceSDKPresenter } @Override - public void onActiveSpeakersUpdate(String activeSpeakers) { + public void onActiveSpeakersUpdate(String activeSpeakers, ArrayList participantIds) { if (getAttachedViews().size() == 0) return; getViewState().onActiveSpeakersUpdate(activeSpeakers); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java index 84efff1b88..8fe3b40d89 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -106,6 +106,13 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter participantIds) { + if (getAttachedViews().size() == 0) return; + ArrayList members = ConferenceVideoModule + .getInstance().getUpdatedActiveSpeakersParticipants(participantIds); + getViewState().onConferenceMembersUpdate(members); + } + @Override public void onConferenceMembersUpdate(ActiveConferenceCall activeConferenceCall) { if (getAttachedViews().size() == 0) return; @@ -157,9 +164,9 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter participantIds) { if (getAttachedViews().size() == 0) return; - getViewState().onActiveSpeakersUpdate(activeSpeakers); + getViewState().onActiveSpeakersUpdate(activeSpeakers, participantIds); } @Override @@ -185,5 +192,6 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter participantIds); void updateMicrophonState(boolean isMuted); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 2032a823de..39cb8c437a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -1,11 +1,11 @@ package com.nynja.mobile.communicator.ui.adapters.viewholders.conference; import android.graphics.Color; -import android.support.annotation.NonNull; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import com.nynja.mobile.communicator.R; @@ -34,6 +34,7 @@ public class ConferenceVideoItemVh extends BaseVH { @BindView(R.id.conf_video_active) CheckableImageView mActiveVideo; @BindView(R.id.conf_video_feed) SurfaceViewRenderer mVideoFeed; @BindView(R.id.conf_video_holder_layout) FrameLayout mFeedFrameLayout; + //@BindView(R.id.conf_participant_item) RelativeLayout mFeedFrameLayout; protected ConferenceListItem mItem; private OnConferenceItemClickListener mListener; @@ -138,8 +139,14 @@ public class ConferenceVideoItemVh extends BaseVH { drawIsScfreenSharingIfNeeded(item); // drawIsActiveVideoIfNeeded(item); drawIsFeedVideoIfNeeded(item.hasVideo); - if (mItem != null && mItem.isSpeaking) { - mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke); + if (mItem != null) { + if (mItem != null && mItem.isMe) { + mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke_red); + } else if (mItem != null && mItem.isSpeaking) { + mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke_green); + } else { + mFeedFrameLayout.setBackgroundColor(Color.TRANSPARENT); + } } else { mFeedFrameLayout.setBackgroundColor(Color.TRANSPARENT); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 1c4c1015ae..69f6dd867d 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -296,17 +296,11 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } @Override - public void onActiveSpeakersUpdate(String activeSpeakers) { + public void onActiveSpeakersUpdate(String activeSpeakers, ArrayList participantIds) { if (getActivity() == null || !isAdded()) return; getActivity().runOnUiThread(() -> { if (getActivity() == null || !isAdded() || !isActive) return; - if (StringUtils.isEmpty(activeSpeakers)) { -// activeSpeakerLayout.setVisibility(View.GONE); - } else { -// activeSpeakersText.setText(activeSpeakers); -// activeSpeakerLayout.setVisibility(View.VISIBLE); - } - + mConferencePresenter.updateActiveSpeakersState(participantIds); }); } diff --git a/app/src/main/res/drawable/video_feed_square_stroke.xml b/app/src/main/res/drawable/video_feed_square_stroke_green.xml similarity index 100% rename from app/src/main/res/drawable/video_feed_square_stroke.xml rename to app/src/main/res/drawable/video_feed_square_stroke_green.xml diff --git a/app/src/main/res/drawable/video_feed_square_stroke_red.xml b/app/src/main/res/drawable/video_feed_square_stroke_red.xml new file mode 100644 index 0000000000..04f48350ef --- /dev/null +++ b/app/src/main/res/drawable/video_feed_square_stroke_red.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file -- GitLab From a905683bc836039014a96c150be321ed4ec252ed Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Thu, 30 Apr 2020 17:11:52 +0300 Subject: [PATCH 17/21] -NY-10108: [AN]: Put button for switching between front/back camera in local feed on top left corner --- .../OnConferenceVideoFeedClickListener.java | 9 +++++++++ .../mvp/presenters/ConferenceVideoPresenter.java | 9 +++++++++ .../adapters/conference/ConferenceVideoAdapter.java | 13 +++++++------ .../conference/ConferenceVideoItemVh.java | 13 ++++++++++--- .../conference/ConferenceVideoFragment.java | 10 +++++++--- app/src/main/res/layout/li_conference_video.xml | 12 +++++++++++- 6 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/nynja/mobile/communicator/interfaces/OnConferenceVideoFeedClickListener.java diff --git a/app/src/main/java/com/nynja/mobile/communicator/interfaces/OnConferenceVideoFeedClickListener.java b/app/src/main/java/com/nynja/mobile/communicator/interfaces/OnConferenceVideoFeedClickListener.java new file mode 100644 index 0000000000..a707d0639e --- /dev/null +++ b/app/src/main/java/com/nynja/mobile/communicator/interfaces/OnConferenceVideoFeedClickListener.java @@ -0,0 +1,9 @@ +package com.nynja.mobile.communicator.interfaces; + +/** + * Created by Ergyun Syuleyman on 4/25/18. + */ + +public interface OnConferenceVideoFeedClickListener extends OnConferenceItemClickListener { + void onSwitchCameraClick(T item); +} diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java index 8fe3b40d89..93ff6234b0 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -193,5 +193,14 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter> extends BaseAdapter { - private OnConferenceItemClickListener mOnConferenceItemClickListener; + private OnConferenceVideoFeedClickListener mOnConferenceVideoFeedClickListener; private boolean mIsModerator = false; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); private int mScreenWidth = 0; @@ -33,15 +34,15 @@ public class ConferenceVideoAdapter> exten HashSet mHoldersSet; public ConferenceVideoAdapter(List list, - OnConferenceItemClickListener onConferenceItemClickListener) { + OnConferenceVideoFeedClickListener onConferenceItemClickListener) { super(list); - this.mOnConferenceItemClickListener = onConferenceItemClickListener; + this.mOnConferenceVideoFeedClickListener = onConferenceItemClickListener; mHoldersSet = new HashSet<>(); setHasStableIds(true); } - public void setOnItemClickListener(OnConferenceItemClickListener onConferenceItemClickListener) { - this.mOnConferenceItemClickListener = onConferenceItemClickListener; + public void setOnItemClickListener(OnConferenceVideoFeedClickListener onConferenceItemClickListener) { + this.mOnConferenceVideoFeedClickListener = onConferenceItemClickListener; } @Override @@ -83,7 +84,7 @@ public class ConferenceVideoAdapter> exten @Override public T onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { ConferenceVideoItemVh viewHolder = new ConferenceVideoItemVh(viewGroup, mIsModerator); - viewHolder.setOnItemClickListener(mOnConferenceItemClickListener); + viewHolder.setOnClickListener(mOnConferenceVideoFeedClickListener); if (viewGroup.getContext() instanceof CallActivity) { WindowManager wm = (WindowManager) NynjaApp.getComponent().context().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 39cb8c437a..2238094c0a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -12,6 +12,7 @@ import com.nynja.mobile.communicator.R; import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; +import com.nynja.mobile.communicator.interfaces.OnConferenceVideoFeedClickListener; import com.nynja.mobile.communicator.ui.base.BaseVH; import com.nynja.mobile.communicator.ui.views.CheckableImageView; import com.nynja.mobile.communicator.utils.StringUtils; @@ -35,9 +36,10 @@ public class ConferenceVideoItemVh extends BaseVH { @BindView(R.id.conf_video_feed) SurfaceViewRenderer mVideoFeed; @BindView(R.id.conf_video_holder_layout) FrameLayout mFeedFrameLayout; //@BindView(R.id.conf_participant_item) RelativeLayout mFeedFrameLayout; + @BindView(R.id.video_active_switch_camera) ImageView mSwithCamera; protected ConferenceListItem mItem; - private OnConferenceItemClickListener mListener; + private OnConferenceVideoFeedClickListener mListener; private boolean mIsModerator; private boolean mIsRenderersInitialized = false; @@ -46,8 +48,8 @@ public class ConferenceVideoItemVh extends BaseVH { mIsModerator = isModerator; } - public void setOnItemClickListener(OnConferenceItemClickListener onConferenceItemClickListener) { - this.mListener = onConferenceItemClickListener; + public void setOnClickListener(OnConferenceVideoFeedClickListener listener) { + this.mListener = listener; } @@ -142,6 +144,11 @@ public class ConferenceVideoItemVh extends BaseVH { if (mItem != null) { if (mItem != null && mItem.isMe) { mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke_red); + mSwithCamera.setOnClickListener(null); + if (mListener != null) { + mSwithCamera.setOnClickListener(v -> mListener.onSwitchCameraClick(item)); + mSwithCamera.setVisibility(View.VISIBLE); + } } else if (mItem != null && mItem.isSpeaking) { mFeedFrameLayout.setBackgroundResource(R.drawable.video_feed_square_stroke_green); } else { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 69f6dd867d..235bdb555f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -23,6 +23,7 @@ import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ActiveConferenceCall; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; +import com.nynja.mobile.communicator.interfaces.OnConferenceVideoFeedClickListener; import com.nynja.mobile.communicator.mvp.presenters.ConferenceVideoPresenter; import com.nynja.mobile.communicator.mvp.view.ConferenceVideoView; import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; @@ -42,7 +43,7 @@ import butterknife.BindView; import timber.log.Timber; public class ConferenceVideoFragment extends BaseFragment implements ConferenceVideoView, - OnConferenceItemClickListener { + OnConferenceVideoFeedClickListener { private static final int FRONT_CAMERA = 1; @@ -104,12 +105,15 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV @Override public void onPause() { mConferencePresenter.pauseCallVideoCapturer(); - removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); - removeRemoteVideoRenderers(mConferencePresenter.getActiveConference()); isActive = false; super.onPause(); } + @Override + public void onSwitchCameraClick(ConferenceListItem item) { + mConferencePresenter.switchCamera(); + } + @Override public void onItemClick(ConferenceListItem item, int position) { Timber.d("On clicked position: %d contact: %s", position, item); diff --git a/app/src/main/res/layout/li_conference_video.xml b/app/src/main/res/layout/li_conference_video.xml index 98d04fcc2f..dfc71020c7 100644 --- a/app/src/main/res/layout/li_conference_video.xml +++ b/app/src/main/res/layout/li_conference_video.xml @@ -43,7 +43,17 @@ app:layout_constraintTop_toTopOf="parent" tool:visibility="visible" /> - + + + -- GitLab From 8219feb927e35e3945e05bb24d455378253273d1 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Thu, 30 Apr 2020 18:18:04 +0300 Subject: [PATCH 18/21] -fixed pause camera on switch between conference participants and video feeds screen --- .../communicator/ui/activities/calls/CallActivity.java | 8 +++++++- .../ui/adapters/conference/ActiveCallPagerAdapter.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java index d1b02a96e2..f8f34f2abd 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/calls/CallActivity.java @@ -54,6 +54,7 @@ public class CallActivity extends BaseActivity implements CallActivityView { private ActiveCallPagerAdapter mPagerAdapter; + private int mSelectedPage = -1; public static Intent getLaunchIntent(Context context) { Intent intent = new Intent(context, CallActivity.class); @@ -133,7 +134,12 @@ public class CallActivity extends BaseActivity implements CallActivityView { // mIndicator.setVisibility(View.VISIBLE); // } synchronized (mPagerAdapter) { - mPagerAdapter.setFragmentActiveByPosition(position); +// mPagerAdapter.setFragmentActiveByPosition(position); + if (mSelectedPage >= 0) { + mPagerAdapter.setFragmentActiveByPosition(mSelectedPage, false); + } + mPagerAdapter.setFragmentActiveByPosition(position, true); + mSelectedPage = position; } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java index 803e6a4f02..2570c49232 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java @@ -218,7 +218,7 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { return mAdapterPages.get(itemId); } - protected void setFragmentActiveByPosition(int position, boolean active) { + public void setFragmentActiveByPosition(int position, boolean active) { BaseFragment fragment = getItemByPosition(position); if (fragment == null) return; if (position == CallPages.CallPageTapToSpeak.ordinal() -- GitLab From 2d5cd587352640b51957bbc0a47e1b36a12f80a4 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Thu, 30 Apr 2020 19:37:58 +0300 Subject: [PATCH 19/21] NY-10111: [AN]: Video Conferencing should be available only for Samsung app --- .../mvp/presenters/ChatPresenter.java | 10 ++-- .../mvp/presenters/MainActivityPresenter.kt | 6 ++- .../mvp/view/MainActivityView.java | 2 + .../ui/activities/MainActivity.java | 8 +++ .../conference/ConferenceCallFragment.java | 51 ++++++++++++------- .../mobile/communicator/utils/Consts.java | 8 ++- app/src/main/res/values-en/strings.xml | 2 + app/src/main/res/values-es/strings.xml | 2 + app/src/main/res/values-ko/strings.xml | 2 + app/src/main/res/values-zh-rCN/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 12 files changed, 74 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java index d39e742ba6..60b0ae62df 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ChatPresenter.java @@ -2293,9 +2293,13 @@ public class ChatPresenter extends BaseChatPresenter { return; } if (mRoom.isGroupOrCalllChat()) { - //getViewState().showAlertNotSupportedFeature(); - FragmentTransferObject fto = new FragmentTransferObject(null, mRoom, OpenVideoConferenceCreate); - mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto); + if (Consts.CLIENT_ALLOWED_VIDEO_CONFERENCE) { + navigateToStartGroupCall(true, mRoom); +// FragmentTransferObject fto = new FragmentTransferObject(null, mRoom, OpenVideoConferenceCreate); +// mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto); + } else { + getViewState().showMessage(R.string.call_start_video_conference_alert); + } } else { mDataManager.startCall(new ContactModel(mRoom.getOnlyMembers().get(0)), true); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt index 183895b6cd..923269e60c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/MainActivityPresenter.kt @@ -369,7 +369,11 @@ class MainActivityPresenter : ConferenceSDKPresenter() { // FragmentTransferObject.Type.OpenGroupVideoConferenceCreate, // null) // mRouter.navigateTo(HomeNavigator.CHOOSE_USER, fto) - tryStartCall(true, true, true, null) + if (Consts.CLIENT_ALLOWED_VIDEO_CONFERENCE) { + tryStartCall(true, true, true, null) + } else { + viewState.showAlertMessage(R.string.call_start_video_conference_alert) + } viewState.closeWheel() } diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/MainActivityView.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/MainActivityView.java index e2b7a3e309..4ecb0e41d9 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/view/MainActivityView.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/view/MainActivityView.java @@ -74,4 +74,6 @@ public interface MainActivityView extends JoinGroupView { void showPurchaseDialog(boolean isModerator, final String message); void tryStartCall(boolean createNew, boolean isGroup, boolean isVideo, Parcelable prevModel); + + void showAlertMessage(int res); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java index 2680912d89..cc4a659d41 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/activities/MainActivity.java @@ -668,6 +668,14 @@ public class MainActivity extends BaseActivity implements MainActivityView, onCallPermission(false, isVideo, createNew, isGroup, prevModel); } + @Override + public void showAlertMessage(int res) { + DialogFactory.showAlertDialog(this, + getString(res), + getString(R.string.signin_text_ok), + (dialog, which) -> dialog.dismiss()); + } + @Override public void openActiveConference() { mPresenter.navigateToActiveCall(); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java index a9968258c4..7122cc65bf 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceCallFragment.java @@ -295,27 +295,17 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, @OnClick(R.id.voice_call_active_video_layout) //turn_video_on_off) void turnVideoOnOff() { - if (!videoOnOf.isEnabled()) return; - if (!videoOnOf.isChecked()) { - if (!mConferencePresenter.isCameraRunning()) { - mRxPermissions.requestEachCombined(Manifest.permission.CAMERA) - .subscribe(permission -> { - if (permission.granted) { - videoOnOf.setChecked(true); - mConferencePresenter.startCameraCapture(); - } else if (!permission.shouldShowRequestPermissionRationale) { - PermissionHelper.getInstance().showPermissionDialog(getActivity(), - mConferencePresenter.getPermissionDialogListener(), Manifest.permission.CAMERA); - } - }, Timber::e); + if (mConferencePresenter.getActiveConference().isConference()) { + if (Consts.CLIENT_ALLOWED_VIDEO_CONFERENCE) { + onClickCameraButton(); } else { - videoOnOf.setChecked(mConferencePresenter.isCameraRunning()); + DialogFactory.showAlertDialog(getContext(), + getString(R.string.call_start_video_conference_alert), + getString(R.string.signin_text_ok), + (dialog, which) -> dialog.dismiss()); } - } else if (videoOnOf.isChecked() && mConferencePresenter.isCameraRunning()) { - mConferencePresenter.stopCameraCapture(); - videoOnOf.setChecked(false); } else { - videoOnOf.setChecked(mConferencePresenter.isCameraRunning()); + onClickCameraButton(); } } @@ -370,6 +360,31 @@ public class ConferenceCallFragment extends BaseFragment implements CallView, } } + private void onClickCameraButton() { + if (!videoOnOf.isEnabled()) return; + if (!videoOnOf.isChecked()) { + if (!mConferencePresenter.isCameraRunning()) { + mRxPermissions.requestEachCombined(Manifest.permission.CAMERA) + .subscribe(permission -> { + if (permission.granted) { + videoOnOf.setChecked(true); + mConferencePresenter.startCameraCapture(); + } else if (!permission.shouldShowRequestPermissionRationale) { + PermissionHelper.getInstance().showPermissionDialog(getActivity(), + mConferencePresenter.getPermissionDialogListener(), Manifest.permission.CAMERA); + } + }, Timber::e); + } else { + videoOnOf.setChecked(mConferencePresenter.isCameraRunning()); + } + } else if (videoOnOf.isChecked() && mConferencePresenter.isCameraRunning()) { + mConferencePresenter.stopCameraCapture(); + videoOnOf.setChecked(false); + } else { + videoOnOf.setChecked(mConferencePresenter.isCameraRunning()); + } + } + private void showAudioRoutActionSheet() { if (getContext() != null) { String bluetoothDeviceName = getString(R.string.bluetooth); diff --git a/app/src/main/java/com/nynja/mobile/communicator/utils/Consts.java b/app/src/main/java/com/nynja/mobile/communicator/utils/Consts.java index 3a4cf23d08..8dc5ca8301 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/utils/Consts.java +++ b/app/src/main/java/com/nynja/mobile/communicator/utils/Consts.java @@ -116,13 +116,19 @@ public interface Consts { // Incoming call showing as a popup Notification boolean SHOW_INCOMING_CALLS_AS_POPUP_NOTIFICATIONS = false; - // Samsung IAP + // Samsung + // IAP boolean CLIENT_SIDE_MODERATOR_END_CONFERENCE = true;//BuildConfig.FLAVOR.toLowerCase().contentEquals("samsung"); boolean ENABLE_SAMSUNG_IAP_TEST_MODE = false; long SHOW_TRIAL_PEROIOD_MSG_AT_START = 30; // in seconds long SHOW_TRIAL_PEROIOD_VALUE_5 = 5; // in minutes long SHOW_TRIAL_PEROIOD_VALUE_10 = 10; // in minutes int SHOW_TRIAL_PEROIOD_END_TIME = 40; // in minutes + // Video conference + //boolean CLIENT_ALLOWED_VIDEO_CONFERENCE = (BuildConfig.FLAVOR.toLowerCase().contentEquals("samsung") + // || BuildConfig.FLAVOR.toLowerCase().contentEquals("samsungdev") + // || BuildConfig.FLAVOR.toLowerCase().contentEquals("samsungpreprod")); + boolean CLIENT_ALLOWED_VIDEO_CONFERENCE = (BuildConfig.APPLICATION_ID.toLowerCase().contentEquals("com.nynja.mobile.communicator.superapp")); // Default Max length restriction of group chat (room) name - on creation int MAX_GROUP_NAME_SIZE_RESTRICTION = 32; diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 7285083368..e0f25562be 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1330,4 +1330,6 @@ Please stop your camera first Cannot start screen share because it has been already started by another participant + Start camera is not available for groups + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index a84ca16736..c4dfff8784 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1329,4 +1329,6 @@ Please stop your camera first Cannot start screen share because it has been already started by another participant + Start camera is not available for groups + diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index b6773a7a6c..12922e2833 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1330,4 +1330,6 @@ Please stop your camera first Cannot start screen share because it has been already started by another participant + Start camera is not available for groups + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 7e93e58e74..1f2cac1244 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1329,4 +1329,6 @@ Please stop your camera first Cannot start screen share because it has been already started by another participant + Start camera is not available for groups + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 7e93e58e74..1f2cac1244 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1329,4 +1329,6 @@ Please stop your camera first Cannot start screen share because it has been already started by another participant + Start camera is not available for groups + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0239dc8f4c..8f0450cc21 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1331,4 +1331,6 @@ Please stop your camera first Cannot start screen share because it has been already started by another participant + Start camera is not available for groups + -- GitLab From 84176f950853d8cbc8feef496ea172da439e6dc2 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Mon, 4 May 2020 12:05:31 +0300 Subject: [PATCH 20/21] -removed hardcoded values on calculate video feeds size; -fixed csse going to own feed on start cam=era --- .../conference/ConferenceVideoModule.java | 119 +++++++++++------- .../data/sdk/calls/ConferenceSDKModule.java | 6 +- .../conference/ActiveCallPagerAdapter.java | 26 +++- .../conference/ConferenceVideoAdapter.java | 20 +-- .../conference/ConferenceVideoItemVh.java | 4 +- .../conference/ConferenceVideoFragment.java | 11 +- 6 files changed, 117 insertions(+), 69 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index 363253e815..bf856e2b93 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -20,7 +20,8 @@ public class ConferenceVideoModule { private static ConferenceVideoModule mInstance = null; public static final int MAX_VIDEO_FEEDS_COLUIMN_SIZE = 2; - public static final int MAX_VIDEO_FEEDS_COUNT_PER_PAGE = 4; + public static final int MAX_VIDEO_FEEDS_ROW_SIZE = 2; + public static final int MAX_VIDEO_FEEDS_COUNT_PER_PAGE = MAX_VIDEO_FEEDS_COLUIMN_SIZE*MAX_VIDEO_FEEDS_ROW_SIZE; private DataManager mDataManager; // Call worker object @@ -108,9 +109,9 @@ public class ConferenceVideoModule { setVideoRendererForTrack(null, trackId, StringUtils.isEmpty(trackId)); } } - - mActiveVideoParticipantsCount = mActiveVideoParticipantsMap.size(); - return new ArrayList<>(mActiveVideoParticipantsMap.values()); + ArrayList items = new ArrayList<>(mActiveVideoParticipantsMap.values()); + mActiveVideoParticipantsCount = items.size(); + return items; } @Synchronized @@ -128,62 +129,90 @@ public class ConferenceVideoModule { } public float getSpanSize(int position) { -// if (mActiveVideoParticipantsCount <= 4) return 1; -// switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { -// case 0: -// case 1: -// { -// return 1; -// } -// } -// if (position < mActiveVideoParticipants.size()) { -// if (mActiveVideoParticipants.get(position).isVideoFullScreen) -// return 1; -// } -// return 2; if (getWidthDiv(position) == 1 && getHeightDiv(position) == 1) return 1; - return 2; + return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } - public int getWidthDiv(int position) { - if (mActiveVideoParticipantsCount <= 2) return 1; + public int getWidthDividerLength(int position) { + if (mActiveVideoParticipantsCount/MAX_VIDEO_FEEDS_COLUIMN_SIZE <= MAX_VIDEO_FEEDS_ROW_SIZE) { + return mActiveVideoParticipantsCount / MAX_VIDEO_FEEDS_COLUIMN_SIZE + 1; //MAX_VIDEO_FEEDS_ROW_SIZE + 1; + } + int lastPageBeginer = ((mActiveVideoParticipantsCount / MAX_VIDEO_FEEDS_COUNT_PER_PAGE) * MAX_VIDEO_FEEDS_COUNT_PER_PAGE); + if (mActiveVideoParticipantsCount == lastPageBeginer) { + lastPageBeginer = mActiveVideoParticipantsCount - MAX_VIDEO_FEEDS_COUNT_PER_PAGE; + } + + if (position < lastPageBeginer) { + return MAX_VIDEO_FEEDS_COUNT_PER_PAGE / MAX_VIDEO_FEEDS_COLUIMN_SIZE - 1; + } + + int row = (mActiveVideoParticipantsCount - lastPageBeginer)/MAX_VIDEO_FEEDS_COLUIMN_SIZE; + if (row <= MAX_VIDEO_FEEDS_ROW_SIZE) { + int rest = (mActiveVideoParticipantsCount - lastPageBeginer)%MAX_VIDEO_FEEDS_COLUIMN_SIZE; + if (rest == 0) { + if (row < MAX_VIDEO_FEEDS_ROW_SIZE) return row; + if (position/lastPageBeginer == 1) return row + 1; + return row - 1; + } + return row + 1; + } + + return row-1; + } + + private int widthDivider(int count) { + if (count <= MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { + if ((count % MAX_VIDEO_FEEDS_COLUIMN_SIZE) == 0) { + return count / MAX_VIDEO_FEEDS_COLUIMN_SIZE; + } + } + return count / MAX_VIDEO_FEEDS_COLUIMN_SIZE + 1; + } + + private int lastPageWidthDivider(int position) { switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { - case 0: - { - if (position == mActiveVideoParticipantsCount -1) return 1; - if (position == mActiveVideoParticipantsCount -2) return 1; - return MAX_VIDEO_FEEDS_COLUIMN_SIZE; + case 0: { + if (position == mActiveVideoParticipantsCount - 1) return 1; + if (position == mActiveVideoParticipantsCount - 2) return 1; + return MAX_VIDEO_FEEDS_ROW_SIZE; } - case 1: - { - if (position == mActiveVideoParticipantsCount -1) return 1; - if (position == mActiveVideoParticipantsCount -2) return 2; - return MAX_VIDEO_FEEDS_COLUIMN_SIZE; + case 1: { + if (position == mActiveVideoParticipantsCount - 1) return 1; + if (position == mActiveVideoParticipantsCount - 2) return MAX_VIDEO_FEEDS_ROW_SIZE; + return MAX_VIDEO_FEEDS_ROW_SIZE; } - case 2: - { - return MAX_VIDEO_FEEDS_COLUIMN_SIZE; + case 2: { + return MAX_VIDEO_FEEDS_ROW_SIZE; } // next 3 items span 2 columns each - case 3: - { - return MAX_VIDEO_FEEDS_COLUIMN_SIZE; + case 3: { + return MAX_VIDEO_FEEDS_ROW_SIZE; } } - return 1; + return MAX_VIDEO_FEEDS_ROW_SIZE; } - public int getHeightDiv(int position) { - if (mActiveVideoParticipantsCount <= 1) return 1; - switch (position % MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { - case 0: - { - if (position == mActiveVideoParticipantsCount -1) return 1; - return MAX_VIDEO_FEEDS_COLUIMN_SIZE; - } + private int lastPageWidthDivider2(int lastPageCount) { + if (lastPageCount < MAX_VIDEO_FEEDS_COLUIMN_SIZE) return 1; + return MAX_VIDEO_FEEDS_ROW_SIZE; + } + + public int getWidthDiv(int position) { + if (mActiveVideoParticipantsCount <= MAX_VIDEO_FEEDS_COLUIMN_SIZE) return 1; + if (mActiveVideoParticipantsCount <= MAX_VIDEO_FEEDS_COUNT_PER_PAGE) { + return widthDivider(mActiveVideoParticipantsCount); } + int lastPageBeginer = ((mActiveVideoParticipantsCount / MAX_VIDEO_FEEDS_COUNT_PER_PAGE) + * MAX_VIDEO_FEEDS_COUNT_PER_PAGE); + if (position < lastPageBeginer) { + return MAX_VIDEO_FEEDS_ROW_SIZE; + } + return lastPageWidthDivider2(mActiveVideoParticipantsCount - lastPageBeginer); + } + public int getHeightDiv(int position) { + if (mActiveVideoParticipantsCount < MAX_VIDEO_FEEDS_COLUIMN_SIZE) return 1; return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index 00d3d130cf..b00746dd83 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -1073,7 +1073,7 @@ public class ConferenceSDKModule extends BaseSDKModule { if (!hasCreatedActiveCall()) return; Timber.d("Request conference member with \'ConferenceId\'=\'" + conferenceId + "\' " + (result ? "succeed" : "failed!!!")); - synchronized (mActiveConference.mData.mParticipantArray) { + synchronized (mActiveConference.mData) { mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); } @@ -1573,7 +1573,7 @@ public class ConferenceSDKModule extends BaseSDKModule { initConferenceCall(false); new Handler(Looper.getMainLooper()).postDelayed(() -> { mActiveConference.isCallInProgress = true; - synchronized (mActiveConference.mData.mParticipantArray) { + synchronized (mActiveConference.mData) { mActiveConference.mData.mParticipantArray = mActiveConference.mConference.getParticipants(); } startConferenceActivityImpl(NynjaNavigator.MAIN_NEW_CALL, true); @@ -2991,7 +2991,7 @@ public class ConferenceSDKModule extends BaseSDKModule { } } if (mActiveConference.mData.mParticipantArray.size() > 1 && TEMP_ALLOW_UPDATE_CONF_CALLS_NAME) { - synchronized (mActiveConference.mData.mParticipantArray) { + synchronized (mActiveConference.mData) { mActiveConference.mData.mParticipantArray.remove(index); } tryUpdateConferenceCallName(mActiveConference, diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java index 2570c49232..4e40f108f1 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ActiveCallPagerAdapter.java @@ -236,7 +236,7 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { if (fragment instanceof ConferenceCallFragment) { ((ConferenceCallFragment)fragment).setActiveState(active); } else if (fragment instanceof ConferenceVideoFragment) { - ((ConferenceVideoFragment) fragment).setActiveState(active); + ((ConferenceVideoFragment)fragment).setActiveState(active); } } else if (position == CallPages.ConferenceVideoFragment.ordinal()) { if (fragment instanceof ConferenceVideoFragment) { @@ -295,12 +295,28 @@ public class ActiveCallPagerAdapter extends NynjaViewPagerAdapter { } public void tryToGoTooMyVideoFeed() { - for (CallPages callPage : callPages) { - if (callPage == CallPages.ConferenceVideoFragment) { - final String itemId = makeFragmentId(getItemId(callPage.ordinal())); + int position = 0; + for (; position < callPages.size(); position++ ) { + if (position == CallPages.ShareScreenFragment.ordinal()) { + final String itemId = makeFragmentId(getItemId(position)); + BaseFragment fragment = mAdapterPages.get(itemId); + if (fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment)fragment).tryToGoTooMyVideoFeed();; + return; + } + } else if (position == CallPages.CallPageActiveCallFragment.ordinal()) { + final String itemId = makeFragmentId(getItemId(position)); + BaseFragment fragment = mAdapterPages.get(itemId); + if (fragment instanceof ConferenceVideoFragment) { + ((ConferenceVideoFragment)fragment).tryToGoTooMyVideoFeed();; + return; + } + } else if (position == CallPages.ConferenceVideoFragment.ordinal()) { + final String itemId = makeFragmentId(getItemId(position)); BaseFragment fragment = mAdapterPages.get(itemId); - if (fragment != null && fragment instanceof ConferenceVideoFragment) { + if (fragment instanceof ConferenceVideoFragment) { ((ConferenceVideoFragment)fragment).tryToGoTooMyVideoFeed();; + return; } } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index 7cced0e276..0956d049d7 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -12,7 +12,6 @@ import android.view.WindowManager; import com.nynja.mobile.communicator.NynjaApp; import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; -import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; import com.nynja.mobile.communicator.interfaces.OnConferenceVideoFeedClickListener; import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceVideoItemVh; @@ -23,6 +22,7 @@ import java.util.HashSet; import java.util.List; import static com.nynja.mobile.communicator.data.conference.ConferenceVideoModule.MAX_VIDEO_FEEDS_COLUIMN_SIZE; +import static com.nynja.mobile.communicator.data.conference.ConferenceVideoModule.MAX_VIDEO_FEEDS_ROW_SIZE; public class ConferenceVideoAdapter> extends BaseAdapter { @@ -100,26 +100,26 @@ public class ConferenceVideoAdapter> exten public void onBindViewHolder(T holder, int position) { super.onBindViewHolder(holder, position); if (mScreenWidth > 0) { - float divH = ConferenceVideoModule.getInstance().getWidthDiv(position); - float divV = ConferenceVideoModule.getInstance().getHeightDiv(position); + float divWidth = ConferenceVideoModule.getInstance().getWidthDiv(position); + float divHeight = ConferenceVideoModule.getInstance().getHeightDiv(position); //////////////////////////////////////////////////// //if (position == 2) ((ConferenceVideoItemVh) holder).getItem().isVideoFullScreen = true; //if (((ConferenceVideoItemVh) holder).getItem().isVideoFullScreen) { // divH = 1f; divV = 1f; //} //////////////////////////////////////////////////// - int itemWidth = (int) (mScreenWidth / divH); - int itemHeight = (int) (mScreenHeight / divV); + int itemWidth = (int) (mScreenWidth / divWidth); + int itemHeight = (int) (mScreenHeight / divHeight); ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); - if (divV == MAX_VIDEO_FEEDS_COLUIMN_SIZE) { - layoutParams.height = -1; + if (divHeight == MAX_VIDEO_FEEDS_COLUIMN_SIZE) { + layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; } else { layoutParams.height = itemHeight; } - if (divH == MAX_VIDEO_FEEDS_COLUIMN_SIZE) { - layoutParams.width = itemWidth; + if (divWidth == 1) { + layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; } else { - layoutParams.width = -1; + layoutParams.width = itemWidth - ConferenceVideoModule.getInstance().getWidthDividerLength(position); } holder.itemView.setLayoutParams(layoutParams); } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 2238094c0a..8c4e016561 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -5,13 +5,11 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.TextView; import com.nynja.mobile.communicator.R; import com.nynja.mobile.communicator.data.conference.ConferenceVideoModule; import com.nynja.mobile.communicator.data.sdk.calls.ConferenceListItem; -import com.nynja.mobile.communicator.interfaces.OnConferenceItemClickListener; import com.nynja.mobile.communicator.interfaces.OnConferenceVideoFeedClickListener; import com.nynja.mobile.communicator.ui.base.BaseVH; import com.nynja.mobile.communicator.ui.views.CheckableImageView; @@ -110,7 +108,7 @@ public class ConferenceVideoItemVh extends BaseVH { public void onViewDetachedFromWindow() { enableVideoForTrack(false); - removeVideoRendererForTrack(); + //removeVideoRendererForTrack(); } public void onViewRecycled() { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 235bdb555f..eaad10fb5c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -42,6 +42,8 @@ import java.util.ArrayList; import butterknife.BindView; import timber.log.Timber; +import static com.nynja.mobile.communicator.data.conference.ConferenceVideoModule.MAX_VIDEO_FEEDS_COLUIMN_SIZE; + public class ConferenceVideoFragment extends BaseFragment implements ConferenceVideoView, OnConferenceVideoFeedClickListener { @@ -160,8 +162,10 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV private void initUIRv() { mRecyclerView.setNestedScrollingEnabled(false); - mGridLayoutManager = new GridLayoutManager(getActivity(), 2, - LinearLayoutManager.HORIZONTAL, false); + mGridLayoutManager = new GridLayoutManager(getActivity(), + MAX_VIDEO_FEEDS_COLUIMN_SIZE, + LinearLayoutManager.HORIZONTAL, + false); // mGridLayoutManager.setSpanCount(2); // mGridLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // mGridLayoutManager.setReverseLayout(false); @@ -328,7 +332,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } public void tryToGoTooMyVideoFeed() { - mTryToGoTooMyVideoFeed = false; + mTryToGoTooMyVideoFeed = true; if (isActive) { scrollToMyFeedPosition(); } @@ -356,6 +360,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV setRemoteVideoRenderer(mConferencePresenter.getActiveConference()); setConferenceState(activeConferenceCall); } + scrollToMyFeedPosition(); } else { if (activeConferenceCall.isVideoEnabled) { if (activeConferenceCall.mData.isOwnStreamActive) { -- GitLab From 2c24e151c806830073e6c0aa327dfa1eb2f922ab Mon Sep 17 00:00:00 2001 From: Angel Terziev Date: Mon, 4 May 2020 19:49:55 +0300 Subject: [PATCH 21/21] Linked with NynjaSDK 1.21 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7970867905..7439189f85 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -677,8 +677,8 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" // Conference, Calls mobile SDK - //implementation 'com.nynja.sdk:NynjaSdk:1.20.7@aar' - implementation(name: 'NynjaSdk-1.20.7', ext: 'aar') + implementation 'com.nynja.sdk:NynjaSdk:1.21@aar' + //implementation(name: 'NynjaSdk-1.21', ext: 'aar') //ExoPlayer implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6' -- GitLab