mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
de73c57d9d
@ -51,7 +51,6 @@ BAZEL_OPTIONS=(\
|
||||
--spawn_strategy=standalone \
|
||||
--strategy=SwiftCompile=standalone \
|
||||
--features=swift.enable_batch_mode \
|
||||
--apple_generate_dsym \
|
||||
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
|
||||
)
|
||||
|
||||
|
@ -202,6 +202,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
private var audioLevelsDisposable = MetaDisposable()
|
||||
|
||||
private let speakingParticipantsContext = SpeakingParticipantsContext()
|
||||
private var speakingParticipantsReportTimestamp: [PeerId: Double] = [:]
|
||||
public var speakingAudioLevels: Signal<[(PeerId, Float)], NoError> {
|
||||
return self.speakingParticipantsContext.getAudioLevels()
|
||||
}
|
||||
@ -396,7 +397,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
removedSsrc.append(participantUpdate.ssrc)
|
||||
|
||||
if participantUpdate.peerId == strongSelf.accountContext.account.peerId {
|
||||
strongSelf._canBeRemoved.set(.single(true))
|
||||
if case let .estabilished(_, _, ssrc, _) = strongSelf.internalState, ssrc == participantUpdate.ssrc {
|
||||
strongSelf._canBeRemoved.set(.single(true))
|
||||
}
|
||||
}
|
||||
} else if participantUpdate.peerId == strongSelf.accountContext.account.peerId {
|
||||
if case let .estabilished(_, _, ssrc, _) = strongSelf.internalState, ssrc != participantUpdate.ssrc {
|
||||
@ -616,8 +619,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
self.participantsContext = participantsContext
|
||||
self.participantsContextStateDisposable.set(combineLatest(queue: .mainQueue(),
|
||||
participantsContext.state,
|
||||
participantsContext.numberOfActiveSpeakers,
|
||||
self.speakingParticipantsContext.get()
|
||||
participantsContext.numberOfActiveSpeakers |> deliverOnMainQueue,
|
||||
self.speakingParticipantsContext.get() |> deliverOnMainQueue
|
||||
).start(next: { [weak self] state, numberOfActiveSpeakers, speakingParticipants in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -625,6 +628,27 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
var topParticipants: [GroupCallParticipantsContext.Participant] = []
|
||||
|
||||
var reportSpeakingParticipants: [PeerId] = []
|
||||
let timestamp = CACurrentMediaTime()
|
||||
for peerId in speakingParticipants {
|
||||
let shouldReport: Bool
|
||||
if let previousTimestamp = strongSelf.speakingParticipantsReportTimestamp[peerId] {
|
||||
shouldReport = previousTimestamp + 1.0 < timestamp
|
||||
} else {
|
||||
shouldReport = true
|
||||
}
|
||||
if shouldReport {
|
||||
strongSelf.speakingParticipantsReportTimestamp[peerId] = timestamp
|
||||
reportSpeakingParticipants.append(peerId)
|
||||
}
|
||||
}
|
||||
|
||||
if !reportSpeakingParticipants.isEmpty {
|
||||
Queue.mainQueue().justDispatch {
|
||||
self?.participantsContext?.reportSpeakingParticipants(ids: reportSpeakingParticipants)
|
||||
}
|
||||
}
|
||||
|
||||
var members = PresentationGroupCallMembers(
|
||||
participants: [],
|
||||
speakingParticipants: speakingParticipants,
|
||||
|
@ -314,11 +314,11 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
let revealOptions: [VoiceChatParticipantItem.RevealOption] = []
|
||||
|
||||
return VoiceChatParticipantItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, presence: peerEntry.presence, text: text, icon: icon, enabled: true, getAudioLevel: { return interaction.getAudioLevel(peer.id) }, revealOptions: revealOptions, revealed: peerEntry.revealed, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
return VoiceChatParticipantItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, presence: peerEntry.presence, text: text, icon: icon, enabled: true, selectable: peer.id != context.account.peerId, getAudioLevel: { return interaction.getAudioLevel(peer.id) }, revealOptions: revealOptions, revealed: peerEntry.revealed, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
interaction.setPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, action: {
|
||||
interaction.openPeer(peer.id)
|
||||
}, contextAction: { node, gesture in
|
||||
}, contextAction: peer.id == context.account.peerId ? nil : { node, gesture in
|
||||
interaction.peerContextAction(peerEntry, node, gesture)
|
||||
})
|
||||
}
|
||||
@ -443,7 +443,8 @@ public final class VoiceChatController: ViewController {
|
||||
updateIsMuted: { [weak self] peerId, isMuted in
|
||||
self?.call.updateMuteState(peerId: peerId, isMuted: isMuted)
|
||||
}, openPeer: { [weak self] peerId in
|
||||
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
||||
if let strongSelf = self, let navigationController = strongSelf.controller?.parentNavigationController {
|
||||
strongSelf.controller?.dismiss()
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), keepStack: .always, purposefulAction: {}, peekData: nil))
|
||||
}
|
||||
}, openInvite: {
|
||||
@ -1190,17 +1191,19 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
private func updateMembers(muteState: GroupCallParticipantsContext.Participant.MuteState?, groupMembers: [RenderedChannelParticipant], callMembers: [GroupCallParticipantsContext.Participant], speakingPeers: Set<PeerId>) {
|
||||
var callMembers = callMembers
|
||||
callMembers.sort()
|
||||
var sortedCallMembers = callMembers
|
||||
sortedCallMembers.sort()
|
||||
|
||||
for i in 0 ..< callMembers.count {
|
||||
if callMembers[i].peer.id == self.context.account.peerId {
|
||||
let member = callMembers[i]
|
||||
callMembers.remove(at: i)
|
||||
callMembers.insert(member, at: 0)
|
||||
/*for i in 0 ..< sortedCallMembers.count {
|
||||
if sortedCallMembers[i].peer.id == self.context.account.peerId {
|
||||
let member = sortedCallMembers[i]
|
||||
sortedCallMembers.remove(at: i)
|
||||
sortedCallMembers.insert(member, at: 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//assert(sortedCallMembers == callMembers)
|
||||
|
||||
self.currentGroupMembers = groupMembers
|
||||
self.currentCallMembers = callMembers
|
||||
@ -1214,7 +1217,7 @@ public final class VoiceChatController: ViewController {
|
||||
var processedPeerIds = Set<PeerId>()
|
||||
|
||||
entries.append(.invite(self.presentationData.theme, self.presentationData.strings, "Invite Member"))
|
||||
|
||||
|
||||
for member in callMembers {
|
||||
if processedPeerIds.contains(member.peer.id) {
|
||||
continue
|
||||
@ -1300,6 +1303,7 @@ public final class VoiceChatController: ViewController {
|
||||
private let sharedContext: SharedAccountContext
|
||||
public let call: PresentationGroupCall
|
||||
private let presentationData: PresentationData
|
||||
public var parentNavigationController: NavigationController?
|
||||
|
||||
fileprivate let contentsReady = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
fileprivate let dataReady = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
|
@ -65,6 +65,7 @@ public final class VoiceChatParticipantItem: ListViewItem {
|
||||
let text: ParticipantText
|
||||
let icon: Icon
|
||||
let enabled: Bool
|
||||
public let selectable: Bool
|
||||
let getAudioLevel: (() -> Signal<Float, NoError>)?
|
||||
let revealOptions: [RevealOption]
|
||||
let revealed: Bool?
|
||||
@ -72,7 +73,7 @@ public final class VoiceChatParticipantItem: ListViewItem {
|
||||
let action: (() -> Void)?
|
||||
let contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
|
||||
|
||||
public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, context: AccountContext, peer: Peer, presence: PeerPresence?, text: ParticipantText, icon: Icon, enabled: Bool, getAudioLevel: (() -> Signal<Float, NoError>)?, revealOptions: [RevealOption], revealed: Bool?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil) {
|
||||
public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, context: AccountContext, peer: Peer, presence: PeerPresence?, text: ParticipantText, icon: Icon, enabled: Bool, selectable: Bool, getAudioLevel: (() -> Signal<Float, NoError>)?, revealOptions: [RevealOption], revealed: Bool?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
@ -82,6 +83,7 @@ public final class VoiceChatParticipantItem: ListViewItem {
|
||||
self.text = text
|
||||
self.icon = icon
|
||||
self.enabled = enabled
|
||||
self.selectable = selectable
|
||||
self.getAudioLevel = getAudioLevel
|
||||
self.revealOptions = revealOptions
|
||||
self.revealed = revealed
|
||||
@ -89,9 +91,7 @@ public final class VoiceChatParticipantItem: ListViewItem {
|
||||
self.action = action
|
||||
self.contextAction = contextAction
|
||||
}
|
||||
|
||||
public var selectable: Bool = true
|
||||
|
||||
|
||||
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||
async {
|
||||
let node = VoiceChatParticipantItemNode()
|
||||
|
@ -232,7 +232,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
peer: peer,
|
||||
ssrc: ssrc,
|
||||
joinTimestamp: date,
|
||||
activityTimestamp: activeDate,
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
muteState: muteState
|
||||
))
|
||||
}
|
||||
@ -494,7 +494,7 @@ public final class GroupCallParticipantsContext {
|
||||
public var peer: Peer
|
||||
public var ssrc: UInt32
|
||||
public var joinTimestamp: Int32
|
||||
public var activityTimestamp: Int32?
|
||||
public var activityTimestamp: Double?
|
||||
public var muteState: MuteState?
|
||||
|
||||
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
|
||||
@ -587,7 +587,7 @@ public final class GroupCallParticipantsContext {
|
||||
public var peerId: PeerId
|
||||
public var ssrc: UInt32
|
||||
public var joinTimestamp: Int32
|
||||
public var activityTimestamp: Int32?
|
||||
public var activityTimestamp: Double?
|
||||
public var muteState: Participant.MuteState?
|
||||
public var isRemoved: Bool
|
||||
}
|
||||
@ -606,9 +606,13 @@ public final class GroupCallParticipantsContext {
|
||||
private let id: Int64
|
||||
private let accessHash: Int64
|
||||
|
||||
private var hasReceivedSpeackingParticipantsReport: Bool = false
|
||||
|
||||
private var stateValue: InternalState {
|
||||
didSet {
|
||||
self.statePromise.set(self.stateValue)
|
||||
if self.stateValue != oldValue {
|
||||
self.statePromise.set(self.stateValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
private let statePromise: ValuePromise<InternalState>
|
||||
@ -682,52 +686,56 @@ public final class GroupCallParticipantsContext {
|
||||
|
||||
strongSelf.numberOfActiveSpeakersValue = activities.count
|
||||
|
||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||
var indexMap: [PeerId: Int] = [:]
|
||||
for i in 0 ..< updatedParticipants.count {
|
||||
indexMap[updatedParticipants[i].peer.id] = i
|
||||
}
|
||||
var updated = false
|
||||
|
||||
for (activityPeerId, activity) in activities {
|
||||
if case let .speakingInGroupCall(timestamp) = activity {
|
||||
if let index = indexMap[activityPeerId] {
|
||||
if let activityTimestamp = updatedParticipants[index].activityTimestamp {
|
||||
if activityTimestamp < timestamp {
|
||||
if !strongSelf.hasReceivedSpeackingParticipantsReport {
|
||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||
var indexMap: [PeerId: Int] = [:]
|
||||
for i in 0 ..< updatedParticipants.count {
|
||||
indexMap[updatedParticipants[i].peer.id] = i
|
||||
}
|
||||
var updated = false
|
||||
|
||||
for (activityPeerId, activity) in activities {
|
||||
if case let .speakingInGroupCall(intTimestamp) = activity {
|
||||
let timestamp = Double(intTimestamp)
|
||||
|
||||
if let index = indexMap[activityPeerId] {
|
||||
if let activityTimestamp = updatedParticipants[index].activityTimestamp {
|
||||
if activityTimestamp < timestamp {
|
||||
updatedParticipants[index].activityTimestamp = timestamp
|
||||
updated = true
|
||||
}
|
||||
} else {
|
||||
updatedParticipants[index].activityTimestamp = timestamp
|
||||
updated = true
|
||||
}
|
||||
} else {
|
||||
updatedParticipants[index].activityTimestamp = timestamp
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if updated {
|
||||
updatedParticipants.sort()
|
||||
for i in 0 ..< updatedParticipants.count {
|
||||
if updatedParticipants[i].peer.id == strongSelf.account.peerId {
|
||||
let member = updatedParticipants[i]
|
||||
updatedParticipants.remove(at: i)
|
||||
updatedParticipants.insert(member, at: 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.stateValue = InternalState(
|
||||
state: State(
|
||||
participants: updatedParticipants,
|
||||
nextParticipantsFetchOffset: strongSelf.stateValue.state.nextParticipantsFetchOffset,
|
||||
adminIds: strongSelf.stateValue.state.adminIds,
|
||||
isCreator: strongSelf.stateValue.state.isCreator,
|
||||
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
|
||||
totalCount: strongSelf.stateValue.state.totalCount,
|
||||
version: strongSelf.stateValue.state.version
|
||||
),
|
||||
overlayState: strongSelf.stateValue.overlayState
|
||||
)
|
||||
if updated {
|
||||
updatedParticipants.sort()
|
||||
for i in 0 ..< updatedParticipants.count {
|
||||
if updatedParticipants[i].peer.id == strongSelf.account.peerId {
|
||||
let member = updatedParticipants[i]
|
||||
updatedParticipants.remove(at: i)
|
||||
updatedParticipants.insert(member, at: 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.stateValue = InternalState(
|
||||
state: State(
|
||||
participants: updatedParticipants,
|
||||
nextParticipantsFetchOffset: strongSelf.stateValue.state.nextParticipantsFetchOffset,
|
||||
adminIds: strongSelf.stateValue.state.adminIds,
|
||||
isCreator: strongSelf.stateValue.state.isCreator,
|
||||
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
|
||||
totalCount: strongSelf.stateValue.state.totalCount,
|
||||
version: strongSelf.stateValue.state.version
|
||||
),
|
||||
overlayState: strongSelf.stateValue.overlayState
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -755,6 +763,65 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public func reportSpeakingParticipants(ids: [PeerId]) {
|
||||
if !ids.isEmpty {
|
||||
self.hasReceivedSpeackingParticipantsReport = true
|
||||
}
|
||||
|
||||
let strongSelf = self
|
||||
|
||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||
var indexMap: [PeerId: Int] = [:]
|
||||
for i in 0 ..< updatedParticipants.count {
|
||||
indexMap[updatedParticipants[i].peer.id] = i
|
||||
}
|
||||
var updated = false
|
||||
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
|
||||
for activityPeerId in ids {
|
||||
if let index = indexMap[activityPeerId] {
|
||||
var updateTimestamp = false
|
||||
if let activityTimestamp = updatedParticipants[index].activityTimestamp {
|
||||
if activityTimestamp < timestamp {
|
||||
updateTimestamp = true
|
||||
}
|
||||
} else {
|
||||
updateTimestamp = true
|
||||
}
|
||||
if updateTimestamp {
|
||||
updatedParticipants[index].activityTimestamp = timestamp
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if updated {
|
||||
updatedParticipants.sort()
|
||||
for i in 0 ..< updatedParticipants.count {
|
||||
if updatedParticipants[i].peer.id == strongSelf.account.peerId {
|
||||
let member = updatedParticipants[i]
|
||||
updatedParticipants.remove(at: i)
|
||||
updatedParticipants.insert(member, at: 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.stateValue = InternalState(
|
||||
state: State(
|
||||
participants: updatedParticipants,
|
||||
nextParticipantsFetchOffset: strongSelf.stateValue.state.nextParticipantsFetchOffset,
|
||||
adminIds: strongSelf.stateValue.state.adminIds,
|
||||
isCreator: strongSelf.stateValue.state.isCreator,
|
||||
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
|
||||
totalCount: strongSelf.stateValue.state.totalCount,
|
||||
version: strongSelf.stateValue.state.version
|
||||
),
|
||||
overlayState: strongSelf.stateValue.overlayState
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func beginProcessingUpdatesIfNeeded() {
|
||||
if self.isProcessingUpdate {
|
||||
return
|
||||
@ -824,7 +891,7 @@ public final class GroupCallParticipantsContext {
|
||||
assertionFailure()
|
||||
continue
|
||||
}
|
||||
var previousActivityTimestamp: Int32?
|
||||
var previousActivityTimestamp: Double?
|
||||
if let index = updatedParticipants.firstIndex(where: { $0.peer.id == participantUpdate.peerId }) {
|
||||
previousActivityTimestamp = updatedParticipants[index].activityTimestamp
|
||||
updatedParticipants.remove(at: index)
|
||||
@ -832,7 +899,7 @@ public final class GroupCallParticipantsContext {
|
||||
updatedTotalCount += 1
|
||||
}
|
||||
|
||||
var activityTimestamp: Int32?
|
||||
var activityTimestamp: Double?
|
||||
if let previousActivityTimestamp = previousActivityTimestamp, let updatedActivityTimestamp = participantUpdate.activityTimestamp {
|
||||
activityTimestamp = max(updatedActivityTimestamp, previousActivityTimestamp)
|
||||
} else {
|
||||
@ -1014,7 +1081,7 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
|
||||
peerId: peerId,
|
||||
ssrc: ssrc,
|
||||
joinTimestamp: date,
|
||||
activityTimestamp: activeDate,
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
muteState: muteState,
|
||||
isRemoved: isRemoved
|
||||
))
|
||||
|
@ -640,6 +640,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
if let call = call {
|
||||
mainWindow.hostView.containerView.endEditing(true)
|
||||
let groupCallController = VoiceChatController(sharedContext: strongSelf, accountContext: call.accountContext, call: call)
|
||||
groupCallController.parentNavigationController = mainWindow.viewController as? NavigationController
|
||||
strongSelf.groupCallController = groupCallController
|
||||
strongSelf.mainWindow?.present(groupCallController, on: .calls)
|
||||
strongSelf.hasOngoingCall.set(true)
|
||||
|
Loading…
x
Reference in New Issue
Block a user