Voice chat fixes

This commit is contained in:
Ali 2021-01-28 23:03:39 +05:00
parent 5f19374c9d
commit fab42fd01d
4 changed files with 173 additions and 20 deletions

View File

@ -302,6 +302,8 @@ public protocol PresentationGroupCall: class {
func invitePeer(_ peerId: PeerId) -> Bool
func removedPeer(_ peerId: PeerId)
var invitedPeers: Signal<[PeerId], NoError> { get }
func loadMoreMembers(token: String)
}
public protocol PresentationCallManager: class {

View File

@ -57,7 +57,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
groupCall: nil
)))
self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", limit: 100)
self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", peerIds: [], limit: 100)
|> map(Optional.init)
|> `catch` { _ -> Signal<GroupCallParticipantsContext.State?, NoError> in
return .single(nil)
@ -1476,4 +1476,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
public func updateDefaultParticipantsAreMuted(isMuted: Bool) {
self.participantsContext?.updateDefaultParticipantsAreMuted(isMuted: isMuted)
}
public func loadMoreMembers(token: String) {
self.participantsContext?.loadMore(token: token)
}
}

View File

@ -375,14 +375,14 @@ public final class VoiceChatController: ViewController {
}
}
private func preparedTransition(from fromEntries: [ListEntry], to toEntries: [ListEntry], isLoading: Bool, isEmpty: Bool, crossFade: Bool, context: AccountContext, presentationData: PresentationData, interaction: Interaction) -> ListTransition {
private func preparedTransition(from fromEntries: [ListEntry], to toEntries: [ListEntry], isLoading: Bool, isEmpty: Bool, crossFade: Bool, animated: Bool, context: AccountContext, presentationData: PresentationData, interaction: Interaction) -> ListTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, interaction: interaction), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, interaction: interaction), directionHint: nil) }
return ListTransition(deletions: deletions, insertions: insertions, updates: updates, isLoading: isLoading, isEmpty: isEmpty, crossFade: crossFade, count: toEntries.count, animated: true)
return ListTransition(deletions: deletions, insertions: insertions, updates: updates, isLoading: isLoading, isEmpty: isEmpty, crossFade: crossFade, count: toEntries.count, animated: animated)
}
private weak var controller: VoiceChatController?
@ -424,7 +424,7 @@ public final class VoiceChatController: ViewController {
private var currentTitle: String = ""
private var currentSubtitle: String = ""
private var currentCallMembers: [GroupCallParticipantsContext.Participant]?
private var currentCallMembers: ([GroupCallParticipantsContext.Participant], String?)?
private var currentInvitedPeers: [Peer]?
private var currentSpeakingPeers: Set<PeerId>?
private var currentContentOffset: CGFloat?
@ -445,6 +445,8 @@ public final class VoiceChatController: ViewController {
private var callState: PresentationGroupCallState?
private var currentLoadToken: String?
private var effectiveMuteState: GroupCallParticipantsContext.Participant.MuteState? {
if self.pushingToTalk {
return nil
@ -577,7 +579,7 @@ public final class VoiceChatController: ViewController {
}
var filters: [ChannelMembersSearchFilter] = []
if let currentCallMembers = strongSelf.currentCallMembers {
if let (currentCallMembers, _) = strongSelf.currentCallMembers {
filters.append(.disable(Array(currentCallMembers.map { $0.peer.id })))
}
if let groupPeer = groupPeer as? TelegramChannel {
@ -1030,7 +1032,7 @@ public final class VoiceChatController: ViewController {
}
}
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: callMembers?.participants ?? [], invitedPeers: invitedPeers, speakingPeers: callMembers?.speakingParticipants ?? [])
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: (callMembers?.participants ?? [], callMembers?.loadMoreToken), invitedPeers: invitedPeers, speakingPeers: callMembers?.speakingParticipants ?? [])
let subtitle = strongSelf.presentationData.strings.VoiceChat_Panel_Members(Int32(max(1, callMembers?.totalCount ?? 0)))
strongSelf.currentSubtitle = subtitle
@ -1059,7 +1061,7 @@ public final class VoiceChatController: ViewController {
}
if !strongSelf.didSetDataReady {
strongSelf.accountPeer = accountPeer
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: strongSelf.currentCallMembers ?? [], invitedPeers: strongSelf.currentInvitedPeers ?? [], speakingPeers: strongSelf.currentSpeakingPeers ?? Set())
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: strongSelf.currentCallMembers ?? ([], nil), invitedPeers: strongSelf.currentInvitedPeers ?? [], speakingPeers: strongSelf.currentSpeakingPeers ?? Set())
strongSelf.didSetDataReady = true
strongSelf.controller?.dataReady.set(true)
@ -1223,6 +1225,18 @@ public final class VoiceChatController: ViewController {
}
}
self.listNode.visibleBottomContentOffsetChanged = { [weak self] offset in
guard let strongSelf = self else {
return
}
if case let .known(value) = offset, value < 100.0 {
if let loadMoreToken = strongSelf.currentCallMembers?.1 {
strongSelf.currentLoadToken = loadMoreToken
strongSelf.call.loadMoreMembers(token: loadMoreToken)
}
}
}
self.memberEventsDisposable.set((self.call.memberEvents
|> deliverOnMainQueue).start(next: { [weak self] event in
guard let strongSelf = self else {
@ -1336,7 +1350,7 @@ public final class VoiceChatController: ViewController {
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
}
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? [], invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? ([], nil), invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
}
@objc private func actionButtonPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer) {
@ -1381,7 +1395,7 @@ public final class VoiceChatController: ViewController {
if let (layout, navigationHeight) = self.validLayout {
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
}
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? [], invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? ([], nil), invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
default:
break
}
@ -2030,7 +2044,12 @@ public final class VoiceChatController: ViewController {
}
}
private func updateMembers(muteState: GroupCallParticipantsContext.Participant.MuteState?, callMembers: [GroupCallParticipantsContext.Participant], invitedPeers: [Peer], speakingPeers: Set<PeerId>) {
private func updateMembers(muteState: GroupCallParticipantsContext.Participant.MuteState?, callMembers: ([GroupCallParticipantsContext.Participant], String?), invitedPeers: [Peer], speakingPeers: Set<PeerId>) {
var disableAnimation = false
if self.currentCallMembers?.1 != callMembers.1 {
disableAnimation = true
}
self.currentCallMembers = callMembers
self.currentSpeakingPeers = speakingPeers
self.currentInvitedPeers = invitedPeers
@ -2044,7 +2063,7 @@ public final class VoiceChatController: ViewController {
entries.append(.invite(self.presentationData.theme, self.presentationData.strings, self.presentationData.strings.VoiceChat_InviteMember))
for member in callMembers {
for member in callMembers.0 {
if processedPeerIds.contains(member.peer.id) {
continue
}
@ -2109,7 +2128,7 @@ public final class VoiceChatController: ViewController {
self.currentEntries = entries
let presentationData = self.presentationData.withUpdated(theme: self.darkTheme)
let transition = preparedTransition(from: previousEntries, to: entries, isLoading: false, isEmpty: false, crossFade: false, context: self.context, presentationData: presentationData, interaction: self.itemInteraction!)
let transition = preparedTransition(from: previousEntries, to: entries, isLoading: false, isEmpty: false, crossFade: false, animated: !disableAnimation, context: self.context, presentationData: presentationData, interaction: self.itemInteraction!)
self.enqueueTransition(transition)
}

View File

@ -187,8 +187,8 @@ public enum GetGroupCallParticipantsError {
case generic
}
public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, limit: Int32) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> {
return account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), ids: [], sources: [], offset: offset, limit: limit))
public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, peerIds: [PeerId], limit: Int32) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> {
return account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), ids: peerIds.map { $0.id }, sources: [], offset: offset, limit: limit))
|> mapError { _ -> GetGroupCallParticipantsError in
return .generic
}
@ -368,7 +368,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, callId: Int64, acces
|> mapError { _ -> JoinGroupCallError in
return .generic
},
getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", limit: 100)
getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", peerIds: [], limit: 100)
|> mapError { _ -> JoinGroupCallError in
return .generic
},
@ -718,7 +718,7 @@ public final class GroupCallParticipantsContext {
private let id: Int64
private let accessHash: Int64
private var hasReceivedSpeackingParticipantsReport: Bool = false
private var hasReceivedSpeakingParticipantsReport: Bool = false
private var stateValue: InternalState {
didSet {
@ -770,6 +770,10 @@ public final class GroupCallParticipantsContext {
private let updatesDisposable = MetaDisposable()
private var activitiesDisposable: Disposable?
private var isLoadingMore: Bool = false
private var shouldResetStateFromServer: Bool = false
private var missingPeerIds = Set<PeerId>()
private let updateDefaultMuteDisposable = MetaDisposable()
public init(account: Account, peerId: PeerId, id: Int64, accessHash: Int64, state: State) {
@ -802,11 +806,14 @@ public final class GroupCallParticipantsContext {
return
}
strongSelf.activeSpeakersValue = Set(activities.map { item -> PeerId in
let peerIds = Set(activities.map { item -> PeerId in
item.0
})
strongSelf.activeSpeakersValue = peerIds
if !strongSelf.hasReceivedSpeackingParticipantsReport {
strongSelf.ensureHaveParticipants(peerIds: peerIds)
if !strongSelf.hasReceivedSpeakingParticipantsReport {
var updatedParticipants = strongSelf.stateValue.state.participants
var indexMap: [PeerId: Int] = [:]
for i in 0 ..< updatedParticipants.count {
@ -885,7 +892,7 @@ public final class GroupCallParticipantsContext {
public func reportSpeakingParticipants(ids: [PeerId]) {
if !ids.isEmpty {
self.hasReceivedSpeackingParticipantsReport = true
self.hasReceivedSpeakingParticipantsReport = true
}
let strongSelf = self
@ -942,6 +949,75 @@ public final class GroupCallParticipantsContext {
}
}
private func ensureHaveParticipants(peerIds: Set<PeerId>) {
var missingPeerIds = Set<PeerId>()
var existingParticipantIds = Set<PeerId>()
for participant in self.stateValue.state.participants {
existingParticipantIds.insert(participant.peer.id)
}
for peerId in peerIds {
if !existingParticipantIds.contains(peerId) {
missingPeerIds.insert(peerId)
}
}
if !missingPeerIds.isEmpty {
self.missingPeerIds.formUnion(missingPeerIds)
self.loadMissingPeers()
}
}
private func loadMissingPeers() {
if self.missingPeerIds.isEmpty {
return
}
if self.isLoadingMore {
return
}
self.isLoadingMore = true
let peerIds = self.missingPeerIds
self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", peerIds: Array(peerIds), limit: 100)
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
strongSelf.isLoadingMore = false
strongSelf.missingPeerIds.subtract(peerIds)
var updatedState = strongSelf.stateValue.state
var existingParticipantIds = Set<PeerId>()
for participant in updatedState.participants {
existingParticipantIds.insert(participant.peer.id)
}
for participant in state.participants {
if existingParticipantIds.contains(participant.peer.id) {
continue
}
existingParticipantIds.insert(participant.peer.id)
updatedState.participants.append(participant)
}
updatedState.participants.sort()
updatedState.totalCount = max(updatedState.totalCount, state.totalCount)
updatedState.version = max(updatedState.version, updatedState.version)
strongSelf.stateValue.state = updatedState
if strongSelf.shouldResetStateFromServer {
strongSelf.resetStateFromServer()
} else {
strongSelf.loadMissingPeers()
}
}))
}
private func beginProcessingUpdatesIfNeeded() {
if self.isProcessingUpdate {
return
@ -1080,13 +1156,22 @@ public final class GroupCallParticipantsContext {
}
private func resetStateFromServer() {
if self.isLoadingMore {
self.shouldResetStateFromServer = true
return
}
self.isLoadingMore = true
self.updateQueue.removeAll()
self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", limit: 100)
self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", peerIds: [], limit: 100)
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
strongSelf.isLoadingMore = false
strongSelf.shouldResetStateFromServer = false
strongSelf.stateValue.state = state
strongSelf.endedProcessingUpdate()
}))
@ -1189,6 +1274,49 @@ public final class GroupCallParticipantsContext {
strongSelf.account.stateManager.addUpdates(updates)
}))
}
public func loadMore(token: String) {
if token != self.stateValue.state.nextParticipantsFetchOffset {
Logger.shared.log("GroupCallParticipantsContext", "loadMore called with an invalid token \(token) (the valid one is \(String(describing: self.stateValue.state.nextParticipantsFetchOffset)))")
return
}
if self.isLoadingMore {
return
}
self.isLoadingMore = true
self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, peerIds: [], limit: 100)
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
strongSelf.isLoadingMore = false
var updatedState = strongSelf.stateValue.state
var existingParticipantIds = Set<PeerId>()
for participant in updatedState.participants {
existingParticipantIds.insert(participant.peer.id)
}
for participant in state.participants {
if existingParticipantIds.contains(participant.peer.id) {
continue
}
existingParticipantIds.insert(participant.peer.id)
updatedState.participants.append(participant)
}
updatedState.nextParticipantsFetchOffset = state.nextParticipantsFetchOffset
updatedState.totalCount = max(updatedState.totalCount, state.totalCount)
updatedState.version = max(updatedState.version, updatedState.version)
strongSelf.stateValue.state = updatedState
if strongSelf.shouldResetStateFromServer {
strongSelf.resetStateFromServer()
}
}))
}
}
extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {