Voice chats: support reversed ordering

This commit is contained in:
Ali
2021-03-17 20:22:18 +04:00
parent c90e188caa
commit 19d4d4aebb
4 changed files with 96 additions and 61 deletions

View File

@@ -77,7 +77,8 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
clientParams: nil, clientParams: nil,
streamDcId: nil, streamDcId: nil,
title: call.title, title: call.title,
recordingStartTimestamp: nil recordingStartTimestamp: nil,
sortAscending: true
), ),
topParticipants: [], topParticipants: [],
participantCount: 0, participantCount: 0,
@@ -85,7 +86,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
groupCall: nil 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) |> map(Optional.init)
|> `catch` { _ -> Signal<GroupCallParticipantsContext.State?, NoError> in |> `catch` { _ -> Signal<GroupCallParticipantsContext.State?, NoError> in
return .single(nil) return .single(nil)
@@ -119,7 +120,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
} }
return GroupCallPanelData( return GroupCallPanelData(
peerId: peerId, 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, topParticipants: topParticipants,
participantCount: state.totalCount, participantCount: state.totalCount,
activeSpeakers: activeSpeakers, activeSpeakers: activeSpeakers,
@@ -900,7 +901,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
volume: nil, volume: nil,
about: about about: about
)) ))
participants.sort() participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: state.sortAscending) })
} }
} }
@@ -958,7 +959,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
var participants: [GroupCallParticipantsContext.Participant] = [] var participants: [GroupCallParticipantsContext.Participant] = []
if !participants.contains(where: { $0.peer.id == myPeerId }) {
if let (myPeer, cachedData) = myPeerAndCachedData { if let (myPeer, cachedData) = myPeerAndCachedData {
let about: String? let about: String?
if let cachedData = cachedData as? CachedUserData { if let cachedData = cachedData as? CachedUserData {
@@ -981,8 +981,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
volume: nil, volume: nil,
about: about about: about
)) ))
participants.sort()
}
} }
for participant in participants { for participant in participants {
@@ -1471,7 +1469,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
volume: nil, volume: nil,
about: about 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, clientParams: nil,
streamDcId: nil, streamDcId: nil,
title: state.title, title: state.title,
recordingStartTimestamp: state.recordingStartTimestamp recordingStartTimestamp: state.recordingStartTimestamp,
sortAscending: state.sortAscending
)))) ))))
strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState(
@@ -1671,7 +1670,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.isRequestingMissingSsrcs = true self.isRequestingMissingSsrcs = true
let requestedSsrcs = self.missingSsrcs 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 |> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else { guard let strongSelf = self else {
return return

View File

@@ -3188,6 +3188,8 @@ public final class VoiceChatController: ViewController {
if allEqual { if allEqual {
disableAnimation = true disableAnimation = true
} }
} else if abs(previousEntries.count - entries.count) > 2 {
disableAnimation = true
} }
let presentationData = self.presentationData.withUpdated(theme: self.darkTheme) let presentationData = self.presentationData.withUpdated(theme: self.darkTheme)

View File

@@ -12,6 +12,7 @@ public struct GroupCallInfo: Equatable {
public var streamDcId: Int32? public var streamDcId: Int32?
public var title: String? public var title: String?
public var recordingStartTimestamp: Int32? public var recordingStartTimestamp: Int32?
public var sortAscending: Bool
public init( public init(
id: Int64, id: Int64,
@@ -20,7 +21,8 @@ public struct GroupCallInfo: Equatable {
clientParams: String?, clientParams: String?,
streamDcId: Int32?, streamDcId: Int32?,
title: String?, title: String?,
recordingStartTimestamp: Int32? recordingStartTimestamp: Int32?,
sortAscending: Bool
) { ) {
self.id = id self.id = id
self.accessHash = accessHash self.accessHash = accessHash
@@ -29,6 +31,7 @@ public struct GroupCallInfo: Equatable {
self.streamDcId = streamDcId self.streamDcId = streamDcId
self.title = title self.title = title
self.recordingStartTimestamp = recordingStartTimestamp self.recordingStartTimestamp = recordingStartTimestamp
self.sortAscending = sortAscending
} }
} }
@@ -40,7 +43,7 @@ public struct GroupCallSummary: Equatable {
extension GroupCallInfo { extension GroupCallInfo {
init?(_ call: Api.GroupCall) { init?(_ call: Api.GroupCall) {
switch call { 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? var clientParams: String?
if let params = params { if let params = params {
switch params { switch params {
@@ -55,7 +58,8 @@ extension GroupCallInfo {
clientParams: clientParams, clientParams: clientParams,
streamDcId: streamDcId, streamDcId: streamDcId,
title: title, title: title,
recordingStartTimestamp: recordStartDate recordingStartTimestamp: recordStartDate,
sortAscending: (flags & (1 << 6)) != 0
) )
case .groupCallDiscarded: case .groupCallDiscarded:
return nil return nil
@@ -227,12 +231,31 @@ public enum GetGroupCallParticipantsError {
case generic case generic
} }
public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> { public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> {
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)) let sortAscendingValue: Signal<Bool, GetGroupCallParticipantsError>
if let sortAscending = sortAscending {
sortAscendingValue = .single(sortAscending)
} else {
sortAscendingValue = getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash)
|> mapError { _ -> GetGroupCallParticipantsError in |> mapError { _ -> GetGroupCallParticipantsError in
return .generic return .generic
} }
|> mapToSignal { result -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> in |> mapToSignal { result -> Signal<Bool, GetGroupCallParticipantsError> in
guard let result = result else {
return .fail(.generic)
}
return .single(result.info.sortAscending)
}
}
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<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> in
return account.postbox.transaction { transaction -> GroupCallParticipantsContext.State in return account.postbox.transaction { transaction -> GroupCallParticipantsContext.State in
var parsedParticipants: [GroupCallParticipantsContext.Participant] = [] var parsedParticipants: [GroupCallParticipantsContext.Participant] = []
let totalCount: Int let totalCount: Int
@@ -321,7 +344,7 @@ 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( return GroupCallParticipantsContext.State(
participants: parsedParticipants, participants: parsedParticipants,
@@ -329,6 +352,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
adminIds: Set(), adminIds: Set(),
isCreator: false, isCreator: false,
defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false),
sortAscending: sortAscendingValue,
recordingStartTimestamp: nil, recordingStartTimestamp: nil,
title: nil, title: nil,
totalCount: totalCount, totalCount: totalCount,
@@ -388,7 +412,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
return .generic 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 |> mapError { _ -> JoinGroupCallError in
return .generic return .generic
} }
@@ -452,6 +476,8 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
return .fail(.generic) return .fail(.generic)
} }
state.sortAscending = parsedCall.sortAscending
let apiUsers: [Api.User] = [] let apiUsers: [Api.User] = []
state.adminIds = Set(peerAdminIds) state.adminIds = Set(peerAdminIds)
@@ -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 updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated return updated
@@ -670,7 +696,7 @@ private func binaryInsertionIndex(_ inputArr: [GroupCallParticipantsContext.Part
} }
public final class GroupCallParticipantsContext { public final class GroupCallParticipantsContext {
public struct Participant: Equatable, Comparable { public struct Participant: Equatable {
public struct MuteState: Equatable { public struct MuteState: Equatable {
public var canUnmute: Bool public var canUnmute: Bool
public var mutedByYou: Bool public var mutedByYou: Bool
@@ -761,7 +787,7 @@ public final class GroupCallParticipantsContext {
return true 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 let lhsActivityRank = lhs.activityRank, let rhsActivityRank = rhs.activityRank {
if lhsActivityRank != rhsActivityRank { if lhsActivityRank != rhsActivityRank {
return lhsActivityRank < rhsActivityRank return lhsActivityRank < rhsActivityRank
@@ -793,8 +819,12 @@ public final class GroupCallParticipantsContext {
} }
if lhs.joinTimestamp != rhs.joinTimestamp { if lhs.joinTimestamp != rhs.joinTimestamp {
if sortAscending {
return lhs.joinTimestamp < rhs.joinTimestamp
} else {
return lhs.joinTimestamp > rhs.joinTimestamp return lhs.joinTimestamp > rhs.joinTimestamp
} }
}
return lhs.peer.id < rhs.peer.id return lhs.peer.id < rhs.peer.id
} }
@@ -811,6 +841,7 @@ public final class GroupCallParticipantsContext {
public var adminIds: Set<PeerId> public var adminIds: Set<PeerId>
public var isCreator: Bool public var isCreator: Bool
public var defaultParticipantsAreMuted: DefaultParticipantsAreMuted public var defaultParticipantsAreMuted: DefaultParticipantsAreMuted
public var sortAscending: Bool
public var recordingStartTimestamp: Int32? public var recordingStartTimestamp: Int32?
public var title: String? public var title: String?
public var totalCount: Int 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 { if sortAgain {
publicState.participants.sort() publicState.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: publicState.sortAscending) })
} }
return publicState return publicState
} }
@@ -1089,7 +1120,7 @@ public final class GroupCallParticipantsContext {
} }
if updated { if updated {
updatedParticipants.sort() updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) })
strongSelf.stateValue = InternalState( strongSelf.stateValue = InternalState(
state: State( state: State(
@@ -1098,6 +1129,7 @@ public final class GroupCallParticipantsContext {
adminIds: strongSelf.stateValue.state.adminIds, adminIds: strongSelf.stateValue.state.adminIds,
isCreator: strongSelf.stateValue.state.isCreator, isCreator: strongSelf.stateValue.state.isCreator,
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted, defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
sortAscending: strongSelf.stateValue.state.sortAscending,
recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp, recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp,
title: strongSelf.stateValue.state.title, title: strongSelf.stateValue.state.title,
totalCount: strongSelf.stateValue.state.totalCount, totalCount: strongSelf.stateValue.state.totalCount,
@@ -1134,7 +1166,7 @@ public final class GroupCallParticipantsContext {
} }
} }
if updated { 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()) }, queue: .mainQueue())
self.activityRankResetTimer?.start() self.activityRankResetTimer?.start()
@@ -1220,7 +1252,7 @@ public final class GroupCallParticipantsContext {
} }
if updated { if updated {
updatedParticipants.sort() updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) })
strongSelf.stateValue = InternalState( strongSelf.stateValue = InternalState(
state: State( state: State(
@@ -1229,6 +1261,7 @@ public final class GroupCallParticipantsContext {
adminIds: strongSelf.stateValue.state.adminIds, adminIds: strongSelf.stateValue.state.adminIds,
isCreator: strongSelf.stateValue.state.isCreator, isCreator: strongSelf.stateValue.state.isCreator,
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted, defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
sortAscending: strongSelf.stateValue.state.sortAscending,
recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp, recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp,
title: strongSelf.stateValue.state.title, title: strongSelf.stateValue.state.title,
totalCount: strongSelf.stateValue.state.totalCount, totalCount: strongSelf.stateValue.state.totalCount,
@@ -1274,7 +1307,7 @@ public final class GroupCallParticipantsContext {
let ssrcs = self.missingSsrcs 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 |> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@@ -1285,7 +1318,7 @@ public final class GroupCallParticipantsContext {
var updatedState = strongSelf.stateValue.state 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.totalCount = max(updatedState.totalCount, state.totalCount)
updatedState.version = max(updatedState.version, updatedState.version) updatedState.version = max(updatedState.version, updatedState.version)
@@ -1438,7 +1471,7 @@ public final class GroupCallParticipantsContext {
let recordingStartTimestamp = strongSelf.stateValue.state.recordingStartTimestamp let recordingStartTimestamp = strongSelf.stateValue.state.recordingStartTimestamp
let title = strongSelf.stateValue.state.title 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( strongSelf.stateValue = InternalState(
state: State( state: State(
@@ -1447,6 +1480,7 @@ public final class GroupCallParticipantsContext {
adminIds: adminIds, adminIds: adminIds,
isCreator: isCreator, isCreator: isCreator,
defaultParticipantsAreMuted: defaultParticipantsAreMuted, defaultParticipantsAreMuted: defaultParticipantsAreMuted,
sortAscending: strongSelf.stateValue.state.sortAscending,
recordingStartTimestamp: recordingStartTimestamp, recordingStartTimestamp: recordingStartTimestamp,
title: title, title: title,
totalCount: updatedTotalCount, totalCount: updatedTotalCount,
@@ -1469,7 +1503,7 @@ public final class GroupCallParticipantsContext {
self.updateQueue.removeAll() 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 |> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@@ -1639,7 +1673,7 @@ public final class GroupCallParticipantsContext {
} }
self.isLoadingMore = true 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 |> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@@ -1648,7 +1682,7 @@ public final class GroupCallParticipantsContext {
var updatedState = strongSelf.stateValue.state 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.nextParticipantsFetchOffset = state.nextParticipantsFetchOffset
updatedState.totalCount = max(updatedState.totalCount, state.totalCount) 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 mergedParticipants = currentParticipants
var existingParticipantIndices: [PeerId: Int] = [:] var existingParticipantIndices: [PeerId: Int] = [:]
@@ -2014,7 +2048,7 @@ private func mergeAndSortParticipants(current currentParticipants: [GroupCallPar
} }
} }
mergedParticipants.sort() mergedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: sortAscending) })
return mergedParticipants return mergedParticipants
} }