From 0e44390a0f2fbbc174e29e36aed6fb859a3be86e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 12 Mar 2021 17:25:25 +0400 Subject: [PATCH] Avoid empty participant list in voice chats --- .../Sources/PresentationGroupCall.swift | 252 +++++++++++------- 1 file changed, 158 insertions(+), 94 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index e2d921fa52..d0f9461669 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -742,9 +742,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { if let initialCall = initialCall, let temporaryParticipantsContext = (self.accountContext.cachedGroupCallContexts as? AccountGroupCallContextCacheImpl)?.impl.syncWith({ impl in impl.get(account: accountContext.account, peerId: peerId, call: CachedChannelData.ActiveCall(id: initialCall.id, accessHash: initialCall.accessHash, title: initialCall.title)) }) { - if let participantsContext = temporaryParticipantsContext.context.participantsContext, let immediateState = participantsContext.immediateState { - self.switchToTemporaryParticipantsContext(sourceContext: participantsContext, initialState: immediateState, oldMyPeerId: self.joinAsPeerId) - } + self.switchToTemporaryParticipantsContext(sourceContext: temporaryParticipantsContext.context.participantsContext, oldMyPeerId: self.joinAsPeerId) + } else { + self.switchToTemporaryParticipantsContext(sourceContext: nil, oldMyPeerId: self.joinAsPeerId) } self.removedChannelMembersDisposable = (accountContext.peerChannelMemberCategoriesContextsManager.removedChannelMembers @@ -817,7 +817,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.removedChannelMembersDisposable?.dispose() } - private func switchToTemporaryParticipantsContext(sourceContext: GroupCallParticipantsContext, initialState: GroupCallParticipantsContext.State, oldMyPeerId: PeerId) { + private func switchToTemporaryParticipantsContext(sourceContext: GroupCallParticipantsContext?, oldMyPeerId: PeerId) { let myPeerId = self.joinAsPeerId let myPeer = self.accountContext.account.postbox.transaction { transaction -> (Peer, CachedPeerData?)? in if let peer = transaction.getPeer(myPeerId) { @@ -826,102 +826,166 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { return nil } } - let temporaryParticipantsContext = GroupCallParticipantsContext(account: self.account, peerId: self.peerId, myPeerId: myPeerId, id: sourceContext.id, accessHash: sourceContext.accessHash, state: initialState) - self.temporaryParticipantsContext = temporaryParticipantsContext - self.participantsContextStateDisposable.set((combineLatest(queue: .mainQueue(), - myPeer, - temporaryParticipantsContext.state, - temporaryParticipantsContext.activeSpeakers - ) - |> take(1)).start(next: { [weak self] myPeerAndCachedData, state, activeSpeakers in - guard let strongSelf = self else { - return - } - - var topParticipants: [GroupCallParticipantsContext.Participant] = [] - - var members = PresentationGroupCallMembers( - participants: [], - speakingParticipants: [], - totalCount: 0, - loadMoreToken: nil + if let sourceContext = sourceContext, let initialState = sourceContext.immediateState { + let temporaryParticipantsContext = GroupCallParticipantsContext(account: self.account, peerId: self.peerId, myPeerId: myPeerId, id: sourceContext.id, accessHash: sourceContext.accessHash, state: initialState) + self.temporaryParticipantsContext = temporaryParticipantsContext + self.participantsContextStateDisposable.set((combineLatest(queue: .mainQueue(), + myPeer, + temporaryParticipantsContext.state, + temporaryParticipantsContext.activeSpeakers ) - - var updatedInvitedPeers = strongSelf.invitedPeersValue - var didUpdateInvitedPeers = false - - var participants = state.participants - - if oldMyPeerId != myPeerId { - for i in 0 ..< participants.count { - if participants[i].peer.id == oldMyPeerId { - participants.remove(at: i) - break + |> take(1)).start(next: { [weak self] myPeerAndCachedData, state, activeSpeakers in + guard let strongSelf = self else { + return + } + + var topParticipants: [GroupCallParticipantsContext.Participant] = [] + + var members = PresentationGroupCallMembers( + participants: [], + speakingParticipants: [], + totalCount: 0, + loadMoreToken: nil + ) + + var updatedInvitedPeers = strongSelf.invitedPeersValue + var didUpdateInvitedPeers = false + + var participants = state.participants + + if oldMyPeerId != myPeerId { + for i in 0 ..< participants.count { + if participants[i].peer.id == oldMyPeerId { + participants.remove(at: i) + break + } } } - } - - if !participants.contains(where: { $0.peer.id == myPeerId }) { - if let (myPeer, cachedData) = myPeerAndCachedData { - let about: String? - if let cachedData = cachedData as? CachedUserData { - about = cachedData.about - } else if let cachedData = cachedData as? CachedUserData { - about = cachedData.about - } else { - about = nil + + if !participants.contains(where: { $0.peer.id == myPeerId }) { + if let (myPeer, cachedData) = myPeerAndCachedData { + let about: String? + if let cachedData = cachedData as? CachedUserData { + about = cachedData.about + } else if let cachedData = cachedData as? CachedUserData { + about = cachedData.about + } else { + about = nil + } + participants.append(GroupCallParticipantsContext.Participant( + peer: myPeer, + ssrc: nil, + jsonParams: nil, + joinTimestamp: strongSelf.temporaryJoinTimestamp, + raiseHandRating: nil, + hasRaiseHand: false, + activityTimestamp: strongSelf.temporaryActivityTimestamp, + activityRank: strongSelf.temporaryActivityRank, + muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), + volume: nil, + about: about + )) + participants.sort() } - participants.append(GroupCallParticipantsContext.Participant( - peer: myPeer, - ssrc: nil, - jsonParams: nil, - joinTimestamp: strongSelf.temporaryJoinTimestamp, - raiseHandRating: nil, - hasRaiseHand: false, - activityTimestamp: strongSelf.temporaryActivityTimestamp, - activityRank: strongSelf.temporaryActivityRank, - muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), - volume: nil, - about: about - )) - participants.sort() } - } - - for participant in participants { - members.participants.append(participant) - - if topParticipants.count < 3 { - topParticipants.append(participant) + + for participant in participants { + members.participants.append(participant) + + if topParticipants.count < 3 { + topParticipants.append(participant) + } + + if let index = updatedInvitedPeers.firstIndex(of: participant.peer.id) { + updatedInvitedPeers.remove(at: index) + didUpdateInvitedPeers = true + } } - - if let index = updatedInvitedPeers.firstIndex(of: participant.peer.id) { - updatedInvitedPeers.remove(at: index) - didUpdateInvitedPeers = true + + members.totalCount = state.totalCount + members.loadMoreToken = state.nextParticipantsFetchOffset + + strongSelf.membersValue = members + + var stateValue = strongSelf.stateValue + stateValue.myPeerId = strongSelf.joinAsPeerId + stateValue.adminIds = state.adminIds + + strongSelf.stateValue = stateValue + + strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( + participantCount: state.totalCount, + topParticipants: topParticipants, + activeSpeakers: activeSpeakers + ))) + + if didUpdateInvitedPeers { + strongSelf.invitedPeersValue = updatedInvitedPeers } - } - - members.totalCount = state.totalCount - members.loadMoreToken = state.nextParticipantsFetchOffset - - strongSelf.membersValue = members - - var stateValue = strongSelf.stateValue - stateValue.myPeerId = strongSelf.joinAsPeerId - stateValue.adminIds = state.adminIds - - strongSelf.stateValue = stateValue - - strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( - participantCount: state.totalCount, - topParticipants: topParticipants, - activeSpeakers: activeSpeakers - ))) - - if didUpdateInvitedPeers { - strongSelf.invitedPeersValue = updatedInvitedPeers - } - })) + })) + } else { + self.temporaryParticipantsContext = nil + self.participantsContextStateDisposable.set((myPeer + |> deliverOnMainQueue + |> take(1)).start(next: { [weak self] myPeerAndCachedData in + guard let strongSelf = self else { + return + } + + var topParticipants: [GroupCallParticipantsContext.Participant] = [] + + var members = PresentationGroupCallMembers( + participants: [], + speakingParticipants: [], + totalCount: 0, + loadMoreToken: nil + ) + + var participants: [GroupCallParticipantsContext.Participant] = [] + + if !participants.contains(where: { $0.peer.id == myPeerId }) { + if let (myPeer, cachedData) = myPeerAndCachedData { + let about: String? + if let cachedData = cachedData as? CachedUserData { + about = cachedData.about + } else if let cachedData = cachedData as? CachedUserData { + about = cachedData.about + } else { + about = nil + } + participants.append(GroupCallParticipantsContext.Participant( + peer: myPeer, + ssrc: nil, + jsonParams: nil, + joinTimestamp: strongSelf.temporaryJoinTimestamp, + raiseHandRating: nil, + hasRaiseHand: false, + activityTimestamp: strongSelf.temporaryActivityTimestamp, + activityRank: strongSelf.temporaryActivityRank, + muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), + volume: nil, + about: about + )) + participants.sort() + } + } + + for participant in participants { + members.participants.append(participant) + + if topParticipants.count < 3 { + topParticipants.append(participant) + } + } + + strongSelf.membersValue = members + + var stateValue = strongSelf.stateValue + stateValue.myPeerId = strongSelf.joinAsPeerId + + strongSelf.stateValue = stateValue + })) + } } private func updateSessionState(internalState: InternalState, audioSessionControl: ManagedAudioSessionControl?) { @@ -1671,7 +1735,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { strongSelf.temporaryActivityRank = participant.activityRank } } - strongSelf.switchToTemporaryParticipantsContext(sourceContext: participantsContext, initialState: immediateState, oldMyPeerId: previousPeerId) + strongSelf.switchToTemporaryParticipantsContext(sourceContext: participantsContext, oldMyPeerId: previousPeerId) } else { strongSelf.stateValue.myPeerId = peerId }