From 19d4d4aebb59dd19ccc6e8e9fa1cc0c499e8314a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 17 Mar 2021 20:22:18 +0400 Subject: [PATCH] Voice chats: support reversed ordering --- .../Sources/PresentationGroupCall.swift | 61 ++++++------ .../Sources/VoiceChatController.swift | 2 + .../TelegramCore/Sources/GroupCalls.swift | 92 +++++++++++++------ submodules/TgVoipWebrtc/tgcalls | 2 +- 4 files changed, 96 insertions(+), 61 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index a9d102bab9..7408ac93ba 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -77,7 +77,8 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { clientParams: nil, streamDcId: nil, title: call.title, - recordingStartTimestamp: nil + recordingStartTimestamp: nil, + sortAscending: true ), topParticipants: [], participantCount: 0, @@ -85,7 +86,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { groupCall: nil ))) - self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", ssrcs: [], limit: 100) + self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: nil) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) @@ -119,7 +120,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { } return GroupCallPanelData( peerId: peerId, - info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: state.title, recordingStartTimestamp: nil), + info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: state.title, recordingStartTimestamp: nil, sortAscending: state.sortAscending), topParticipants: topParticipants, participantCount: state.totalCount, activeSpeakers: activeSpeakers, @@ -900,7 +901,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { volume: nil, about: about )) - participants.sort() + participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: state.sortAscending) }) } } @@ -958,31 +959,28 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { 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: strongSelf.temporaryRaiseHandRating, - hasRaiseHand: strongSelf.temporaryHasRaiseHand, - activityTimestamp: strongSelf.temporaryActivityTimestamp, - activityRank: strongSelf.temporaryActivityRank, - muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), - volume: nil, - about: about - )) - participants.sort() + 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: strongSelf.temporaryRaiseHandRating, + hasRaiseHand: strongSelf.temporaryHasRaiseHand, + activityTimestamp: strongSelf.temporaryActivityTimestamp, + activityRank: strongSelf.temporaryActivityRank, + muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), + volume: nil, + about: about + )) } for participant in participants { @@ -1471,7 +1469,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { volume: nil, about: about )) - participants.sort() + participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: state.sortAscending) }) } } @@ -1588,7 +1586,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { clientParams: nil, streamDcId: nil, title: state.title, - recordingStartTimestamp: state.recordingStartTimestamp + recordingStartTimestamp: state.recordingStartTimestamp, + sortAscending: state.sortAscending )))) strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( @@ -1671,7 +1670,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.isRequestingMissingSsrcs = true let requestedSsrcs = self.missingSsrcs - self.missingSsrcsDisposable.set((getGroupCallParticipants(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, offset: "", ssrcs: Array(requestedSsrcs), limit: 100) + self.missingSsrcsDisposable.set((getGroupCallParticipants(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, offset: "", ssrcs: Array(requestedSsrcs), limit: 100, sortAscending: callInfo.sortAscending) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index c5a6569624..9019a62c05 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -3188,6 +3188,8 @@ public final class VoiceChatController: ViewController { if allEqual { disableAnimation = true } + } else if abs(previousEntries.count - entries.count) > 2 { + disableAnimation = true } let presentationData = self.presentationData.withUpdated(theme: self.darkTheme) diff --git a/submodules/TelegramCore/Sources/GroupCalls.swift b/submodules/TelegramCore/Sources/GroupCalls.swift index 2e12c0d761..a7c812308c 100644 --- a/submodules/TelegramCore/Sources/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/GroupCalls.swift @@ -12,6 +12,7 @@ public struct GroupCallInfo: Equatable { public var streamDcId: Int32? public var title: String? public var recordingStartTimestamp: Int32? + public var sortAscending: Bool public init( id: Int64, @@ -20,7 +21,8 @@ public struct GroupCallInfo: Equatable { clientParams: String?, streamDcId: Int32?, title: String?, - recordingStartTimestamp: Int32? + recordingStartTimestamp: Int32?, + sortAscending: Bool ) { self.id = id self.accessHash = accessHash @@ -29,6 +31,7 @@ public struct GroupCallInfo: Equatable { self.streamDcId = streamDcId self.title = title self.recordingStartTimestamp = recordingStartTimestamp + self.sortAscending = sortAscending } } @@ -40,7 +43,7 @@ public struct GroupCallSummary: Equatable { extension GroupCallInfo { init?(_ call: Api.GroupCall) { switch call { - case let .groupCall(_, id, accessHash, participantCount, params, title, streamDcId, recordStartDate, _): + case let .groupCall(flags, id, accessHash, participantCount, params, title, streamDcId, recordStartDate, _): var clientParams: String? if let params = params { switch params { @@ -55,7 +58,8 @@ extension GroupCallInfo { clientParams: clientParams, streamDcId: streamDcId, title: title, - recordingStartTimestamp: recordStartDate + recordingStartTimestamp: recordStartDate, + sortAscending: (flags & (1 << 6)) != 0 ) case .groupCallDiscarded: return nil @@ -227,12 +231,31 @@ public enum GetGroupCallParticipantsError { case generic } -public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32) -> Signal { - return account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), ids: [], sources: ssrcs.map { Int32(bitPattern: $0) }, offset: offset, limit: limit)) - |> mapError { _ -> GetGroupCallParticipantsError in - return .generic +public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal { + let sortAscendingValue: Signal + if let sortAscending = sortAscending { + sortAscendingValue = .single(sortAscending) + } else { + sortAscendingValue = getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash) + |> mapError { _ -> GetGroupCallParticipantsError in + return .generic + } + |> mapToSignal { result -> Signal in + guard let result = result else { + return .fail(.generic) + } + return .single(result.info.sortAscending) + } } - |> mapToSignal { result -> Signal in + + return combineLatest( + account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), ids: [], sources: ssrcs.map { Int32(bitPattern: $0) }, offset: offset, limit: limit)) + |> mapError { _ -> GetGroupCallParticipantsError in + return .generic + }, + sortAscendingValue + ) + |> mapToSignal { result, sortAscendingValue -> Signal in return account.postbox.transaction { transaction -> GroupCallParticipantsContext.State in var parsedParticipants: [GroupCallParticipantsContext.Participant] = [] let totalCount: Int @@ -320,8 +343,8 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash } } } - - parsedParticipants.sort() + + parsedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: sortAscendingValue) }) return GroupCallParticipantsContext.State( participants: parsedParticipants, @@ -329,6 +352,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash adminIds: Set(), isCreator: false, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), + sortAscending: sortAscendingValue, recordingStartTimestamp: nil, title: nil, totalCount: totalCount, @@ -388,7 +412,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal return .generic } - let getParticipantsRequest = getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100) + let getParticipantsRequest = getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: true) |> mapError { _ -> JoinGroupCallError in return .generic } @@ -451,6 +475,8 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal guard let parsedCall = maybeParsedCall else { return .fail(.generic) } + + state.sortAscending = parsedCall.sortAscending let apiUsers: [Api.User] = [] @@ -548,7 +574,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal } } - state.participants.sort() + state.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: state.sortAscending) }) updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in return updated @@ -670,7 +696,7 @@ private func binaryInsertionIndex(_ inputArr: [GroupCallParticipantsContext.Part } public final class GroupCallParticipantsContext { - public struct Participant: Equatable, Comparable { + public struct Participant: Equatable { public struct MuteState: Equatable { public var canUnmute: Bool public var mutedByYou: Bool @@ -761,7 +787,7 @@ public final class GroupCallParticipantsContext { return true } - public static func <(lhs: Participant, rhs: Participant) -> Bool { + public static func compare(lhs: Participant, rhs: Participant, sortAscending: Bool) -> Bool { if let lhsActivityRank = lhs.activityRank, let rhsActivityRank = rhs.activityRank { if lhsActivityRank != rhsActivityRank { return lhsActivityRank < rhsActivityRank @@ -793,7 +819,11 @@ public final class GroupCallParticipantsContext { } if lhs.joinTimestamp != rhs.joinTimestamp { - return lhs.joinTimestamp > rhs.joinTimestamp + if sortAscending { + return lhs.joinTimestamp < rhs.joinTimestamp + } else { + return lhs.joinTimestamp > rhs.joinTimestamp + } } return lhs.peer.id < rhs.peer.id @@ -811,6 +841,7 @@ public final class GroupCallParticipantsContext { public var adminIds: Set public var isCreator: Bool public var defaultParticipantsAreMuted: DefaultParticipantsAreMuted + public var sortAscending: Bool public var recordingStartTimestamp: Int32? public var title: String? public var totalCount: Int @@ -831,7 +862,7 @@ public final class GroupCallParticipantsContext { } } - self.participants.sort() + self.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: self.sortAscending) }) } } @@ -974,7 +1005,7 @@ public final class GroupCallParticipantsContext { } } if sortAgain { - publicState.participants.sort() + publicState.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: publicState.sortAscending) }) } return publicState } @@ -1089,7 +1120,7 @@ public final class GroupCallParticipantsContext { } if updated { - updatedParticipants.sort() + updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) }) strongSelf.stateValue = InternalState( state: State( @@ -1098,6 +1129,7 @@ public final class GroupCallParticipantsContext { adminIds: strongSelf.stateValue.state.adminIds, isCreator: strongSelf.stateValue.state.isCreator, defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted, + sortAscending: strongSelf.stateValue.state.sortAscending, recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp, title: strongSelf.stateValue.state.title, totalCount: strongSelf.stateValue.state.totalCount, @@ -1134,7 +1166,7 @@ public final class GroupCallParticipantsContext { } } if updated { - strongSelf.stateValue.state.participants.sort() + strongSelf.stateValue.state.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) }) } }, queue: .mainQueue()) self.activityRankResetTimer?.start() @@ -1220,7 +1252,7 @@ public final class GroupCallParticipantsContext { } if updated { - updatedParticipants.sort() + updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) }) strongSelf.stateValue = InternalState( state: State( @@ -1229,6 +1261,7 @@ public final class GroupCallParticipantsContext { adminIds: strongSelf.stateValue.state.adminIds, isCreator: strongSelf.stateValue.state.isCreator, defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted, + sortAscending: strongSelf.stateValue.state.sortAscending, recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp, title: strongSelf.stateValue.state.title, totalCount: strongSelf.stateValue.state.totalCount, @@ -1274,7 +1307,7 @@ public final class GroupCallParticipantsContext { let ssrcs = self.missingSsrcs - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: Array(ssrcs), limit: 100) + self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: Array(ssrcs), limit: 100, sortAscending: true) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -1285,7 +1318,7 @@ public final class GroupCallParticipantsContext { var updatedState = strongSelf.stateValue.state - updatedState.participants = mergeAndSortParticipants(current: updatedState.participants, with: state.participants) + updatedState.participants = mergeAndSortParticipants(current: updatedState.participants, with: state.participants, sortAscending: updatedState.sortAscending) updatedState.totalCount = max(updatedState.totalCount, state.totalCount) updatedState.version = max(updatedState.version, updatedState.version) @@ -1438,7 +1471,7 @@ public final class GroupCallParticipantsContext { let recordingStartTimestamp = strongSelf.stateValue.state.recordingStartTimestamp let title = strongSelf.stateValue.state.title - updatedParticipants.sort() + updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) }) strongSelf.stateValue = InternalState( state: State( @@ -1447,6 +1480,7 @@ public final class GroupCallParticipantsContext { adminIds: adminIds, isCreator: isCreator, defaultParticipantsAreMuted: defaultParticipantsAreMuted, + sortAscending: strongSelf.stateValue.state.sortAscending, recordingStartTimestamp: recordingStartTimestamp, title: title, totalCount: updatedTotalCount, @@ -1469,7 +1503,7 @@ public final class GroupCallParticipantsContext { self.updateQueue.removeAll() - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: [], limit: 100) + self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: self.stateValue.state.sortAscending) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -1639,7 +1673,7 @@ public final class GroupCallParticipantsContext { } self.isLoadingMore = true - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, ssrcs: [], limit: 100) + self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, ssrcs: [], limit: 100, sortAscending: self.stateValue.state.sortAscending) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -1648,7 +1682,7 @@ public final class GroupCallParticipantsContext { var updatedState = strongSelf.stateValue.state - updatedState.participants = mergeAndSortParticipants(current: updatedState.participants, with: state.participants) + updatedState.participants = mergeAndSortParticipants(current: updatedState.participants, with: state.participants, sortAscending: updatedState.sortAscending) updatedState.nextParticipantsFetchOffset = state.nextParticipantsFetchOffset updatedState.totalCount = max(updatedState.totalCount, state.totalCount) @@ -1999,7 +2033,7 @@ public func updatedCurrentPeerGroupCall(account: Account, peerId: PeerId) -> Sig } } -private func mergeAndSortParticipants(current currentParticipants: [GroupCallParticipantsContext.Participant], with updatedParticipants: [GroupCallParticipantsContext.Participant]) -> [GroupCallParticipantsContext.Participant] { +private func mergeAndSortParticipants(current currentParticipants: [GroupCallParticipantsContext.Participant], with updatedParticipants: [GroupCallParticipantsContext.Participant], sortAscending: Bool) -> [GroupCallParticipantsContext.Participant] { var mergedParticipants = currentParticipants var existingParticipantIndices: [PeerId: Int] = [:] @@ -2013,8 +2047,8 @@ private func mergeAndSortParticipants(current currentParticipants: [GroupCallPar mergedParticipants.append(participant) } } - - mergedParticipants.sort() + + mergedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: sortAscending) }) return mergedParticipants } diff --git a/submodules/TgVoipWebrtc/tgcalls b/submodules/TgVoipWebrtc/tgcalls index ea8dbb49de..c0a62629f9 160000 --- a/submodules/TgVoipWebrtc/tgcalls +++ b/submodules/TgVoipWebrtc/tgcalls @@ -1 +1 @@ -Subproject commit ea8dbb49dea53d6778ba3ffbd556a10d164cef69 +Subproject commit c0a62629f968091c21fcdb3d5519f1e77d593079