This commit is contained in:
Ali 2020-11-24 19:50:25 +04:00
parent b2f3ed1491
commit 2c7185763e
20 changed files with 620 additions and 286 deletions

View File

@ -4,6 +4,11 @@ build --action_env=ZERO_AR_DATE=1
build --strategy=Genrule=local
build --apple_platform_type=ios
build --cxxopt='-std=c++14'
build --per_file_copt="third-party/webrtc/.*\.m$","@-fno-stack-protector"
build --per_file_copt="third-party/webrtc/.*\.mm$","@-fno-stack-protector"
build --per_file_copt="third-party/webrtc/.*\.cpp$","@-std=c++14"
build --per_file_copt="third-party/webrtc/.*\.cc$","@-std=c++14"
build --per_file_copt="third-party/webrtc/.*\.mm$","@-std=c++14"
build --spawn_strategy=local
build --strategy=SwiftCompile=local
build --features=debug_prefix_map_pwd_is_dot

View File

@ -51,6 +51,7 @@ BAZEL_OPTIONS=(\
--spawn_strategy=standalone \
--strategy=SwiftCompile=standalone \
--features=swift.enable_batch_mode \
--apple_generate_dsym \
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
)

View File

@ -176,14 +176,14 @@ public struct PresentationGroupCallState: Equatable {
public struct PresentationGroupCallMemberState: Equatable {
public var ssrc: UInt32
public var isSpeaking: Bool
public var muteState: GroupCallParticipantsContext.Participant.MuteState?
public init(
ssrc: UInt32,
isSpeaking: Bool
muteState: GroupCallParticipantsContext.Participant.MuteState?
) {
self.ssrc = ssrc
self.isSpeaking = isSpeaking
self.muteState = muteState
}
}
@ -205,6 +205,7 @@ public protocol PresentationGroupCall: class {
func toggleIsMuted()
func setIsMuted(_ value: Bool)
func setCurrentAudioOutput(_ output: AudioSessionOutput)
func updateMuteState(peerId: PeerId, isMuted: Bool)
}
public protocol PresentationCallManager: class {

View File

@ -60,6 +60,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
text = strings.Activity_PlayingGame
case .typingText:
text = strings.DialogList_Typing
case .speakingInGroupCall:
text = ""
}
let string = NSAttributedString(string: text, font: textFont, textColor: color)
@ -74,6 +76,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
state = .uploading(string, lightColor)
case .playingGame:
state = .playingGame(string, lightColor)
case .speakingInGroupCall:
state = .typingText(string, lightColor)
}
} else {
let text: String
@ -96,6 +100,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
text = strings.DialogList_SinglePlayingGameSuffix(peerTitle).0
case .typingText:
text = strings.DialogList_SingleTypingSuffix(peerTitle).0
case .speakingInGroupCall:
text = ""
}
} else {
text = activities[0].0.compactDisplayTitle
@ -113,6 +119,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
state = .uploading(string, lightColor)
case .playingGame:
state = .playingGame(string, lightColor)
case .speakingInGroupCall:
state = .typingText(string, lightColor)
}
}
} else {

View File

@ -3,6 +3,9 @@ import UIKit
import AsyncDisplayKit
import SwiftSignalKit
public func qewfqewfq() {
}
private struct WindowLayout: Equatable {
let size: CGSize
let metrics: LayoutMetrics

View File

@ -6,8 +6,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[571523412] = { return $0.readDouble() }
dict[-1255641564] = { return parseString($0) }
dict[-1240849242] = { return Api.messages.StickerSet.parse_stickerSet($0) }
dict[1829443076] = { return Api.GroupCall.parse_groupCallPrivate($0) }
dict[2083222527] = { return Api.GroupCall.parse_groupCall($0) }
dict[-1331534976] = { return Api.GroupCall.parse_groupCallPrivate($0) }
dict[1435512961] = { return Api.GroupCall.parse_groupCall($0) }
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
@ -169,6 +169,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-580219064] = { return Api.SendMessageAction.parse_sendMessageGamePlayAction($0) }
dict[-1997373508] = { return Api.SendMessageAction.parse_sendMessageRecordRoundAction($0) }
dict[608050278] = { return Api.SendMessageAction.parse_sendMessageUploadRoundAction($0) }
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
dict[-1137792208] = { return Api.PrivacyKey.parse_privacyKeyStatusTimestamp($0) }
dict[1343122938] = { return Api.PrivacyKey.parse_privacyKeyChatInvite($0) }
dict[1030105979] = { return Api.PrivacyKey.parse_privacyKeyPhoneCall($0) }
@ -531,7 +532,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-2042159726] = { return Api.SecurePasswordKdfAlgo.parse_securePasswordKdfAlgoSHA512($0) }
dict[-1032140601] = { return Api.BotCommand.parse_botCommand($0) }
dict[1474462241] = { return Api.account.ContentSettings.parse_contentSettings($0) }
dict[1325740111] = { return Api.phone.GroupParticipants.parse_groupParticipants($0) }
dict[1021016465] = { return Api.phone.GroupParticipants.parse_groupParticipants($0) }
dict[-2066640507] = { return Api.messages.AffectedMessages.parse_affectedMessages($0) }
dict[-402498398] = { return Api.messages.SavedGifs.parse_savedGifsNotModified($0) }
dict[772213157] = { return Api.messages.SavedGifs.parse_savedGifs($0) }

View File

@ -1910,32 +1910,28 @@ public struct messages {
}
public extension Api {
public enum GroupCall: TypeConstructorDescription {
case groupCallPrivate(flags: Int32, id: Int64, accessHash: Int64, channelId: Int32?, participantsCount: Int32, adminId: Int32)
case groupCall(flags: Int32, id: Int64, accessHash: Int64, adminId: Int32, reflectorId: Int64, params: Api.DataJSON?, version: Int32)
case groupCallPrivate(id: Int64, accessHash: Int64, participantsCount: Int32)
case groupCall(flags: Int32, id: Int64, accessHash: Int64, participantsCount: Int32, params: Api.DataJSON?, version: Int32)
case groupCallDiscarded(id: Int64, accessHash: Int64, duration: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .groupCallPrivate(let flags, let id, let accessHash, let channelId, let participantsCount, let adminId):
case .groupCallPrivate(let id, let accessHash, let participantsCount):
if boxed {
buffer.appendInt32(1829443076)
buffer.appendInt32(-1331534976)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(channelId!, buffer: buffer, boxed: false)}
serializeInt32(participantsCount, buffer: buffer, boxed: false)
serializeInt32(adminId, buffer: buffer, boxed: false)
break
case .groupCall(let flags, let id, let accessHash, let adminId, let reflectorId, let params, let version):
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let version):
if boxed {
buffer.appendInt32(2083222527)
buffer.appendInt32(1435512961)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeInt32(adminId, buffer: buffer, boxed: false)
serializeInt64(reflectorId, buffer: buffer, boxed: false)
serializeInt32(participantsCount, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {params!.serialize(buffer, true)}
serializeInt32(version, buffer: buffer, boxed: false)
break
@ -1952,36 +1948,27 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .groupCallPrivate(let flags, let id, let accessHash, let channelId, let participantsCount, let adminId):
return ("groupCallPrivate", [("flags", flags), ("id", id), ("accessHash", accessHash), ("channelId", channelId), ("participantsCount", participantsCount), ("adminId", adminId)])
case .groupCall(let flags, let id, let accessHash, let adminId, let reflectorId, let params, let version):
return ("groupCall", [("flags", flags), ("id", id), ("accessHash", accessHash), ("adminId", adminId), ("reflectorId", reflectorId), ("params", params), ("version", version)])
case .groupCallPrivate(let id, let accessHash, let participantsCount):
return ("groupCallPrivate", [("id", id), ("accessHash", accessHash), ("participantsCount", participantsCount)])
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let version):
return ("groupCall", [("flags", flags), ("id", id), ("accessHash", accessHash), ("participantsCount", participantsCount), ("params", params), ("version", version)])
case .groupCallDiscarded(let id, let accessHash, let duration):
return ("groupCallDiscarded", [("id", id), ("accessHash", accessHash), ("duration", duration)])
}
}
public static func parse_groupCallPrivate(_ reader: BufferReader) -> GroupCall? {
var _1: Int32?
_1 = reader.readInt32()
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
var _5: Int32?
_5 = reader.readInt32()
var _6: Int32?
_6 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.GroupCall.groupCallPrivate(flags: _1!, id: _2!, accessHash: _3!, channelId: _4, participantsCount: _5!, adminId: _6!)
if _c1 && _c2 && _c3 {
return Api.GroupCall.groupCallPrivate(id: _1!, accessHash: _2!, participantsCount: _3!)
}
else {
return nil
@ -1996,23 +1983,20 @@ public extension Api {
_3 = reader.readInt64()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int64?
_5 = reader.readInt64()
var _6: Api.DataJSON?
var _5: Api.DataJSON?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.DataJSON
_5 = Api.parse(reader, signature: signature) as? Api.DataJSON
} }
var _7: Int32?
_7 = reader.readInt32()
var _6: Int32?
_6 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.GroupCall.groupCall(flags: _1!, id: _2!, accessHash: _3!, adminId: _4!, reflectorId: _5!, params: _6, version: _7!)
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.GroupCall.groupCall(flags: _1!, id: _2!, accessHash: _3!, participantsCount: _4!, params: _5, version: _6!)
}
else {
return nil
@ -5981,6 +5965,7 @@ public extension Api {
case sendMessageGamePlayAction
case sendMessageRecordRoundAction
case sendMessageUploadRoundAction(progress: Int32)
case speakingInGroupCallAction
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -6061,6 +6046,12 @@ public extension Api {
buffer.appendInt32(608050278)
}
serializeInt32(progress, buffer: buffer, boxed: false)
break
case .speakingInGroupCallAction:
if boxed {
buffer.appendInt32(-651419003)
}
break
}
}
@ -6093,6 +6084,8 @@ public extension Api {
return ("sendMessageRecordRoundAction", [])
case .sendMessageUploadRoundAction(let progress):
return ("sendMessageUploadRoundAction", [("progress", progress)])
case .speakingInGroupCallAction:
return ("speakingInGroupCallAction", [])
}
}
@ -6175,6 +6168,9 @@ public extension Api {
return nil
}
}
public static func parse_speakingInGroupCallAction(_ reader: BufferReader) -> SendMessageAction? {
return Api.SendMessageAction.speakingInGroupCallAction
}
}
public enum PrivacyKey: TypeConstructorDescription {

View File

@ -1715,13 +1715,13 @@ public struct phone {
}
public enum GroupParticipants: TypeConstructorDescription {
case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], users: [Api.User])
case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], users: [Api.User], version: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .groupParticipants(let count, let participants, let users):
case .groupParticipants(let count, let participants, let users, let version):
if boxed {
buffer.appendInt32(1325740111)
buffer.appendInt32(1021016465)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
@ -1734,14 +1734,15 @@ public struct phone {
for item in users {
item.serialize(buffer, true)
}
serializeInt32(version, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .groupParticipants(let count, let participants, let users):
return ("groupParticipants", [("count", count), ("participants", participants), ("users", users)])
case .groupParticipants(let count, let participants, let users, let version):
return ("groupParticipants", [("count", count), ("participants", participants), ("users", users), ("version", version)])
}
}
@ -1756,11 +1757,14 @@ public struct phone {
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.phone.GroupParticipants.groupParticipants(count: _1!, participants: _2!, users: _3!)
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.phone.GroupParticipants.groupParticipants(count: _1!, participants: _2!, users: _3!, version: _4!)
}
else {
return nil

View File

@ -27,7 +27,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private enum InternalState {
case requesting
case active(GroupCallInfo)
case estabilished(GroupCallInfo, String, UInt32, [UInt32], [UInt32: PeerId])
case estabilished(info: GroupCallInfo, clientParams: String, localSsrc: UInt32, initialState: GroupCallParticipantsContext.State)
var callInfo: GroupCallInfo? {
switch self {
@ -35,7 +35,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return nil
case let .active(info):
return info
case let .estabilished(info, _, _, _, _):
case let .estabilished(info, _, _, _):
return info
}
}
@ -81,6 +81,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
private var audioLevelsDisposable = MetaDisposable()
private var participantsContextStateDisposable = MetaDisposable()
private var participantsContext: GroupCallParticipantsContext?
private var audioSessionControl: ManagedAudioSessionControl?
private var audioSessionDisposable: Disposable?
private let audioSessionShouldBeActive = ValuePromise<Bool>(false, ignoreRepeated: true)
@ -231,26 +234,20 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
guard let strongSelf = self else {
return
}
if case let .estabilished(callInfo, _, _, _, _) = strongSelf.internalState {
var addedSsrc: [UInt32] = []
var removedSsrc: [UInt32] = []
for (callId, peerId, ssrc, isAdded) in updates {
if case let .estabilished(callInfo, _, _, _) = strongSelf.internalState {
/*var addedSsrc: [UInt32] = []
var removedSsrc: [UInt32] = []*/
for (callId, update) in updates {
if callId == callInfo.id {
let mappedSsrc = UInt32(bitPattern: ssrc)
if isAdded {
addedSsrc.append(mappedSsrc)
strongSelf.ssrcMapping[mappedSsrc] = peerId
} else {
removedSsrc.append(mappedSsrc)
}
strongSelf.participantsContext?.addUpdates(updates: [update])
}
}
if !addedSsrc.isEmpty {
/*if !addedSsrc.isEmpty {
strongSelf.callContext?.addSsrcs(ssrcs: addedSsrc)
}
if !removedSsrc.isEmpty {
strongSelf.callContext?.removeSsrcs(ssrcs: removedSsrc)
}
}*/
}
})
@ -270,6 +267,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.networkStateDisposable.dispose()
self.checkCallDisposable?.dispose()
self.audioLevelsDisposable.dispose()
self.participantsContextStateDisposable.dispose()
}
private func updateSessionState(internalState: InternalState, audioSessionControl: ManagedAudioSessionControl?) {
@ -319,7 +317,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return
}
if let clientParams = joinCallResult.callInfo.clientParams {
strongSelf.updateSessionState(internalState: .estabilished(joinCallResult.callInfo, clientParams, ssrc, joinCallResult.ssrcs, joinCallResult.ssrcMapping), audioSessionControl: strongSelf.audioSessionControl)
strongSelf.updateSessionState(internalState: .estabilished(info: joinCallResult.callInfo, clientParams: clientParams, localSsrc: ssrc, initialState: joinCallResult.state), audioSessionControl: strongSelf.audioSessionControl)
}
}))
}))
@ -361,23 +359,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
}))
self.memberStatesDisposable.set((callContext.memberStates
|> deliverOnMainQueue).start(next: { [weak self] memberStates in
guard let strongSelf = self else {
return
}
var result: [PeerId: PresentationGroupCallMemberState] = [:]
for (ssrc, _) in memberStates {
if let peerId = strongSelf.ssrcMapping[ssrc] {
result[peerId] = PresentationGroupCallMemberState(
ssrc: ssrc,
isSpeaking: false
)
}
}
strongSelf.membersValue = result
}))
self.audioLevelsDisposable.set((callContext.audioLevels
|> deliverOnMainQueue).start(next: { [weak self] levels in
guard let strongSelf = self else {
@ -400,9 +381,40 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
case .estabilished:
break
default:
if case let .estabilished(_, clientParams, _, ssrcs, ssrcMapping) = internalState {
self.ssrcMapping = ssrcMapping
if case let .estabilished(callInfo, clientParams, _, initialState) = internalState {
self.ssrcMapping.removeAll()
var ssrcs: [UInt32] = []
for participant in initialState.participants {
self.ssrcMapping[participant.ssrc] = participant.peer.id
ssrcs.append(participant.ssrc)
}
self.callContext?.setJoinResponse(payload: clientParams, ssrcs: ssrcs)
let participantsContext = GroupCallParticipantsContext(
account: self.accountContext.account,
id: callInfo.id,
accessHash: callInfo.accessHash,
state: initialState
)
self.participantsContext = participantsContext
self.participantsContextStateDisposable.set((participantsContext.state
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
var memberStates: [PeerId: PresentationGroupCallMemberState] = [:]
for participant in state.participants {
strongSelf.ssrcMapping[participant.ssrc] = participant.peer.id
memberStates[participant.peer.id] = PresentationGroupCallMemberState(
ssrc: participant.ssrc,
muteState: participant.muteState
)
}
strongSelf.membersValue = memberStates
}))
if let isCurrentlyConnecting = self.isCurrentlyConnecting, isCurrentlyConnecting {
self.startCheckingCallIfNeeded()
}
@ -414,7 +426,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
if self.checkCallDisposable != nil {
return
}
if case let .estabilished(callInfo, _, ssrc, _, _) = self.internalState {
if case let .estabilished(callInfo, _, ssrc, _) = self.internalState {
let checkSignal = checkGroupCall(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, ssrc: Int32(bitPattern: ssrc))
self.checkCallDisposable = ((
@ -448,7 +460,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
public func leave() -> Signal<Bool, NoError> {
if case let .estabilished(callInfo, _, _, _, _) = self.internalState {
if case let .estabilished(callInfo, _, _, _) = self.internalState {
self.leaveDisposable.set((leaveGroupCall(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash)
|> deliverOnMainQueue).start(completed: { [weak self] in
self?._canBeRemoved.set(.single(true))
@ -485,6 +497,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
}
public func updateMuteState(peerId: PeerId, isMuted: Bool) {
self.participantsContext?.updateMuteState(peerId: peerId, muteState: isMuted ? GroupCallParticipantsContext.Participant.MuteState(canUnmute: peerId == self.accountContext.account.peerId) : nil)
}
private func requestCall() {
self.callContext?.stop()
self.callContext = nil
@ -516,7 +532,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
}
let restartedCall = currentOrRequestedCall
/*let restartedCall = currentOrRequestedCall
|> mapToSignal { value -> Signal<GroupCallInfo, CallError> in
let stopped: Signal<GroupCallInfo, CallError> = stopGroupCall(account: account, callId: value.id, accessHash: value.accessHash)
|> mapError { _ -> CallError in
@ -527,7 +543,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return stopped
|> then(currentOrRequestedCall)
}
}*/
self.requestDisposable.set((currentOrRequestedCall
|> deliverOnMainQueue).start(next: { [weak self] value in

View File

@ -129,7 +129,12 @@ public final class VoiceChatController: ViewController {
private final class Interaction {
private var audioLevels: [PeerId: ValuePipe<Float>] = [:]
init() {
let updateIsMuted: (PeerId, Bool) -> Void
init(
updateIsMuted: @escaping (PeerId, Bool) -> Void
) {
self.updateIsMuted = updateIsMuted
}
func getAudioLevel(_ peerId: PeerId) -> Signal<Float, NoError>? {
@ -161,6 +166,7 @@ public final class VoiceChatController: ViewController {
var participant: RenderedChannelParticipant
var activityTimestamp: Int32
var state: State
var muteState: GroupCallParticipantsContext.Participant.MuteState?
var stableId: PeerId {
return self.participant.peer.id
@ -182,7 +188,13 @@ public final class VoiceChatController: ViewController {
text = .presence
case .listening:
//TODO:localize
text = .text("listening", .accent)
let muteString: String
if self.muteState != nil {
muteString = " [muted]"
} else {
muteString = ""
}
text = .text("listening\(muteString)", .accent)
case .speaking:
//TODO:localize
text = .text("speaking", .constructive)
@ -190,7 +202,16 @@ public final class VoiceChatController: ViewController {
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."), nameDisplayOrder: .firstLast, context: context, peer: peer, height: .peerList, presence: self.participant.presences[self.participant.peer.id], text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: ItemListPeerItemRevealOptions(options: [ItemListPeerItemRevealOption(type: .destructive, title: presentationData.strings.Common_Delete, action: {
//arguments.deleteIncludePeer(peer.peerId)
})]), switchValue: nil, enabled: true, selectable: false, sectionId: 0, action: nil, setPeerIdWithRevealedOptions: { lhs, rhs in
})]), switchValue: nil, enabled: true, selectable: true, sectionId: 0, action: {
switch self.state {
case .inactive:
break
default:
if self.participant.peer.id != context.account.peerId {
interaction.updateIsMuted(self.participant.peer.id, self.muteState != nil ? false : true)
}
}
}, setPeerIdWithRevealedOptions: { lhs, rhs in
//arguments.setItemIdWithRevealedOptions(lhs.flatMap { .peer($0) }, rhs.flatMap { .peer($0) })
}, removePeer: { id in
//arguments.deleteIncludePeer(id)
@ -277,7 +298,9 @@ public final class VoiceChatController: ViewController {
super.init()
self.itemInteraction = Interaction()
self.itemInteraction = Interaction(updateIsMuted: { [weak self] peerId, isMuted in
self?.call.updateMuteState(peerId: peerId, isMuted: isMuted)
})
self.backgroundColor = .black
@ -684,14 +707,16 @@ public final class VoiceChatController: ViewController {
for member in members {
let memberState: PeerEntry.State
var memberMuteState: GroupCallParticipantsContext.Participant.MuteState?
if member.peer.id == self.context.account.peerId {
if !isMuted {
memberState = .speaking
} else {
memberState = .listening
}
} else if let _ = memberStates[member.peer.id] {
} else if let state = memberStates[member.peer.id] {
memberState = .listening
memberMuteState = state.muteState
} else {
memberState = .inactive
}
@ -699,7 +724,8 @@ public final class VoiceChatController: ViewController {
entries.append(PeerEntry(
participant: member,
activityTimestamp: Int32.max - 1 - index,
state: memberState
state: memberState,
muteState: memberMuteState
))
index += 1
}

View File

@ -607,7 +607,7 @@ struct AccountReplayedFinalState {
let updatedWebpages: [MediaId: TelegramMediaWebpage]
let updatedCalls: [Api.PhoneCall]
let addedCallSignalingData: [(Int64, Data)]
let updatedGroupCallParticipants: [(Int64, PeerId, Int32, Bool)]
let updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.StateUpdate)]
let updatedPeersNearby: [PeerNearby]?
let isContactUpdates: [(PeerId, Bool)]
let delayNotificatonsUntil: Int32?
@ -623,7 +623,7 @@ struct AccountFinalStateEvents {
let updatedWebpages: [MediaId: TelegramMediaWebpage]
let updatedCalls: [Api.PhoneCall]
let addedCallSignalingData: [(Int64, Data)]
let updatedGroupCallParticipants: [(Int64, PeerId, Int32, Bool)]
let updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.StateUpdate)]
let updatedPeersNearby: [PeerNearby]?
let isContactUpdates: [(PeerId, Bool)]
let displayAlerts: [(text: String, isDropAuth: Bool)]
@ -639,7 +639,7 @@ struct AccountFinalStateEvents {
return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty
}
init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, PeerId, Int32, Bool)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]) {
init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.StateUpdate)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]) {
self.addedIncomingMessageIds = addedIncomingMessageIds
self.wasScheduledMessageIds = wasScheduledMessageIds
self.deletedMessageIds = deletedMessageIds

View File

@ -2201,7 +2201,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
var updatedCalls: [Api.PhoneCall] = []
var addedCallSignalingData: [(Int64, Data)] = []
var updatedGroupCallParticipants: [(Int64, PeerId, Int32, Bool)] = []
var updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.StateUpdate)] = []
var updatedPeersNearby: [PeerNearby]?
var isContactUpdates: [(PeerId, Bool)] = []
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
@ -2932,22 +2932,10 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
case let .AddCallSignalingData(callId, data):
addedCallSignalingData.append((callId, data))
case let .UpdateGroupCallParticipants(callId, _, participants, version):
for participant in participants {
var peerId: PeerId?
var ssrc: Int32?
var isAdded = true
switch participant {
case let .groupCallParticipant(flags, userId, date, source):
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
ssrc = source
if flags & (1 << 1) != 0 {
isAdded = false
}
}
if let peerId = peerId, let ssrc = ssrc {
updatedGroupCallParticipants.append((callId, peerId, ssrc, isAdded))
}
}
updatedGroupCallParticipants.append((
callId,
GroupCallParticipantsContext.StateUpdate(participants: participants, version: version)
))
case let .UpdateLangPack(langCode, difference):
if let difference = difference {
if langPackDifferences[langCode] == nil {

View File

@ -148,8 +148,8 @@ public final class AccountStateManager {
return self.threadReadStateUpdatesPipe.signal()
}
private let groupCallParticipantUpdatesPipe = ValuePipe<[(Int64, PeerId, Int32, Bool)]>()
public var groupCallParticipantUpdates: Signal<[(Int64, PeerId, Int32, Bool)], NoError> {
private let groupCallParticipantUpdatesPipe = ValuePipe<[(Int64, GroupCallParticipantsContext.StateUpdate)]>()
public var groupCallParticipantUpdates: Signal<[(Int64, GroupCallParticipantsContext.StateUpdate)], NoError> {
return self.groupCallParticipantUpdatesPipe.signal()
}

View File

@ -7,23 +7,19 @@ import SyncCore
public struct GroupCallInfo: Equatable {
public var id: Int64
public var accessHash: Int64
public var peerId: PeerId?
public var clientParams: String?
public var version: Int32?
}
private extension GroupCallInfo {
init?(_ call: Api.GroupCall) {
switch call {
case let .groupCallPrivate(_, id, accessHash, channelId, _, _):
case let .groupCallPrivate(id, accessHash, _):
self.init(
id: id,
accessHash: accessHash,
peerId: channelId.flatMap { PeerId(namespace: Namespaces.Peer.CloudChannel, id: $0) },
clientParams: nil,
version: nil
clientParams: nil
)
case let .groupCall(_, id, accessHash, _, _, params, version):
case let .groupCall(_, id, accessHash, _, params, _):
var clientParams: String?
if let params = params {
switch params {
@ -34,9 +30,7 @@ private extension GroupCallInfo {
self.init(
id: id,
accessHash: accessHash,
peerId: nil,
clientParams: clientParams,
version: version
clientParams: clientParams
)
case .groupCallDiscarded:
return nil
@ -84,7 +78,7 @@ public func getCurrentGroupCall(account: Account, peerId: PeerId) -> Signal<Grou
}
|> mapToSignal { result -> Signal<GroupCallInfo?, GetCurrentGroupCallError> in
switch result {
case let .groupCall(call, sources, participants, users):
case let .groupCall(call, _, _, _):
return account.postbox.transaction { transaction -> GroupCallInfo? in
return GroupCallInfo(call)
}
@ -137,41 +131,72 @@ public func createGroupCall(account: Account, peerId: PeerId) -> Signal<GroupCal
}
}
public struct GetGroupCallParticipantsResult {
public var ssrcMapping: [UInt32: PeerId]
}
public enum GetGroupCallParticipantsError {
case generic
}
public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, maxDate: Int32, limit: Int32) -> Signal<GetGroupCallParticipantsResult, GetGroupCallParticipantsError> {
public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, maxDate: Int32, limit: Int32) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> {
return account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), maxDate: maxDate, limit: limit))
|> mapError { _ -> GetGroupCallParticipantsError in
return .generic
}
|> map { result -> GetGroupCallParticipantsResult in
var ssrcMapping: [UInt32: PeerId] = [:]
switch result {
case let .groupParticipants(count, participants, users):
for participant in participants {
var peerId: PeerId?
var ssrc: UInt32?
switch participant {
case let .groupCallParticipant(flags, userId, date, source):
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
ssrc = UInt32(bitPattern: source)
|> mapToSignal { result -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> in
return account.postbox.transaction { transaction -> GroupCallParticipantsContext.State in
var parsedParticipants: [GroupCallParticipantsContext.Participant] = []
let totalCount: Int
let version: Int32
switch result {
case let .groupParticipants(count, participants, users, apiVersion):
totalCount = Int(count)
version = apiVersion
var peers: [Peer] = []
var peerPresences: [PeerId: PeerPresence] = [:]
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
if let presence = TelegramUserPresence(apiUser: user) {
peerPresences[telegramUser.id] = presence
}
}
if let peerId = peerId, let ssrc = ssrc {
ssrcMapping[ssrc] = peerId
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
loop: for participant in participants {
switch participant {
case let .groupCallParticipant(flags, userId, date, source):
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
let ssrc = UInt32(bitPattern: source)
guard let peer = transaction.getPeer(peerId) else {
continue loop
}
var muteState: GroupCallParticipantsContext.Participant.MuteState?
if (flags & (1 << 0)) != 0 {
let canUnmute = (flags & (1 << 2)) != 0
muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: canUnmute)
}
parsedParticipants.append(GroupCallParticipantsContext.Participant(
peer: peer,
ssrc: ssrc,
joinTimestamp: date,
muteState: muteState
))
}
}
}
return GroupCallParticipantsContext.State(
participants: parsedParticipants,
totalCount: totalCount,
version: version
)
}
return GetGroupCallParticipantsResult(
ssrcMapping: ssrcMapping
)
|> castError(GetGroupCallParticipantsError.self)
}
}
@ -181,8 +206,7 @@ public enum JoinGroupCallError {
public struct JoinGroupCallResult {
public var callInfo: GroupCallInfo
public var ssrcs: [UInt32]
public var ssrcMapping: [UInt32: PeerId]
public var state: GroupCallParticipantsContext.State
}
public func joinGroupCall(account: Account, callId: Int64, accessHash: Int64, joinPayload: String) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
@ -201,7 +225,7 @@ public func joinGroupCall(account: Account, callId: Int64, accessHash: Int64, jo
return .generic
}
)
|> mapToSignal { result, participantsResult -> Signal<JoinGroupCallResult, JoinGroupCallError> in
|> mapToSignal { result, state -> Signal<JoinGroupCallResult, JoinGroupCallError> in
account.stateManager.addUpdates(updates)
var maybeParsedCall: GroupCallInfo?
@ -220,28 +244,14 @@ public func joinGroupCall(account: Account, callId: Int64, accessHash: Int64, jo
}
switch result {
case let .groupCall(call, sources, participants, users):
case let .groupCall(call, sources, _, users):
guard let _ = GroupCallInfo(call) else {
return .fail(.generic)
}
var ssrcMapping: [UInt32: PeerId] = participantsResult.ssrcMapping
for participant in participants {
var peerId: PeerId?
var ssrc: UInt32?
switch participant {
case let .groupCallParticipant(flags, userId, date, source):
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
ssrc = UInt32(bitPattern: source)
}
if let peerId = peerId, let ssrc = ssrc {
ssrcMapping[ssrc] = peerId
}
}
return account.postbox.transaction { transaction -> JoinGroupCallResult in
return JoinGroupCallResult(
callInfo: parsedCall,
ssrcs: sources.map(UInt32.init(bitPattern:)),
ssrcMapping: ssrcMapping
state: state
)
}
|> castError(JoinGroupCallError.self)
@ -297,3 +307,368 @@ public func checkGroupCall(account: Account, callId: Int64, accessHash: Int64, s
}
}
}
private func binaryInsertionIndex(_ inputArr: [GroupCallParticipantsContext.Participant], searchItem: Int32) -> Int {
var lo = 0
var hi = inputArr.count - 1
while lo <= hi {
let mid = (lo + hi) / 2
if inputArr[mid].joinTimestamp < searchItem {
lo = mid + 1
} else if searchItem < inputArr[mid].joinTimestamp {
hi = mid - 1
} else {
return mid
}
}
return lo
}
public final class GroupCallParticipantsContext {
public struct Participant: Equatable {
public struct MuteState: Equatable {
public var canUnmute: Bool
public init(canUnmute: Bool) {
self.canUnmute = canUnmute
}
}
public var peer: Peer
public var ssrc: UInt32
public var joinTimestamp: Int32
public var muteState: MuteState?
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
if !lhs.peer.isEqual(rhs.peer) {
return false
}
if lhs.ssrc != rhs.ssrc {
return false
}
if lhs.joinTimestamp != rhs.joinTimestamp {
return false
}
if lhs.muteState != rhs.muteState {
return false
}
return true
}
}
public struct State: Equatable {
public var participants: [Participant]
public var totalCount: Int
public var version: Int32
}
private struct OverlayState: Equatable {
struct MuteStateChange: Equatable {
var state: Participant.MuteState?
var disposable: Disposable
static func ==(lhs: MuteStateChange, rhs: MuteStateChange) -> Bool {
if lhs.state != rhs.state {
return false
}
if lhs.disposable !== rhs.disposable {
return false
}
return true
}
}
var pendingMuteStateChanges: [PeerId: MuteStateChange] = [:]
var isEmpty: Bool {
if !self.pendingMuteStateChanges.isEmpty {
return false
}
return true
}
}
private struct InternalState: Equatable {
var state: State
var overlayState: OverlayState
}
public struct StateUpdate {
public struct ParticipantUpdate {
public var peerId: PeerId
public var ssrc: UInt32
public var joinTimestamp: Int32
public var muteState: Participant.MuteState?
public var isRemoved: Bool
}
public var participantUpdates: [ParticipantUpdate]
public var version: Int32
public var removePendingMuteStates: Set<PeerId>
}
private let account: Account
private let id: Int64
private let accessHash: Int64
private var stateValue: InternalState {
didSet {
self.statePromise.set(self.stateValue)
}
}
private let statePromise: ValuePromise<InternalState>
public var state: Signal<State, NoError> {
return self.statePromise.get()
|> map { state -> State in
if state.overlayState.isEmpty {
return state.state
}
var publicState = state.state
for i in 0 ..< publicState.participants.count {
if let pendingMuteState = state.overlayState.pendingMuteStateChanges[publicState.participants[i].peer.id] {
publicState.participants[i].muteState = pendingMuteState.state
}
}
return publicState
}
}
private var updateQueue: [StateUpdate] = []
private var isProcessingUpdate: Bool = false
private let disposable = MetaDisposable()
public init(account: Account, id: Int64, accessHash: Int64, state: State) {
self.account = account
self.id = id
self.accessHash = accessHash
self.stateValue = InternalState(state: state, overlayState: OverlayState())
self.statePromise = ValuePromise<InternalState>(self.stateValue)
}
deinit {
self.disposable.dispose()
}
public func addUpdates(updates: [StateUpdate]) {
self.updateQueue.append(contentsOf: updates)
self.beginProcessingUpdatesIfNeeded()
}
private func beginProcessingUpdatesIfNeeded() {
if self.isProcessingUpdate {
return
}
if self.updateQueue.isEmpty {
return
}
self.isProcessingUpdate = true
let update = self.updateQueue.removeFirst()
self.processUpdate(update: update)
}
private func endedProcessingUpdate() {
assert(self.isProcessingUpdate)
self.isProcessingUpdate = false
self.beginProcessingUpdatesIfNeeded()
}
private func processUpdate(update: StateUpdate) {
if update.version < self.stateValue.state.version {
for peerId in update.removePendingMuteStates {
self.stateValue.overlayState.pendingMuteStateChanges.removeValue(forKey: peerId)
}
self.endedProcessingUpdate()
return
}
if update.version > self.stateValue.state.version + 1 {
for peerId in update.removePendingMuteStates {
self.stateValue.overlayState.pendingMuteStateChanges.removeValue(forKey: peerId)
}
self.resetStateFromServer()
return
}
let _ = (self.account.postbox.transaction { transaction -> [PeerId: Peer] in
var peers: [PeerId: Peer] = [:]
for participantUpdate in update.participantUpdates {
if let peer = transaction.getPeer(participantUpdate.peerId) {
peers[peer.id] = peer
}
}
return peers
}
|> deliverOnMainQueue).start(next: { [weak self] peers in
guard let strongSelf = self else {
return
}
var updatedParticipants = Array(strongSelf.stateValue.state.participants.reversed())
var updatedTotalCount = strongSelf.stateValue.state.totalCount
for participantUpdate in update.participantUpdates {
if participantUpdate.isRemoved {
if let index = updatedParticipants.firstIndex(where: { $0.peer.id == participantUpdate.peerId }) {
updatedParticipants.remove(at: index)
updatedTotalCount -= 1
}
} else {
guard let peer = peers[participantUpdate.peerId] else {
assertionFailure()
continue
}
if let index = updatedParticipants.firstIndex(where: { $0.peer.id == participantUpdate.peerId }) {
updatedParticipants.remove(at: index)
} else {
updatedTotalCount += 1
}
let participant = Participant(
peer: peer,
ssrc: participantUpdate.ssrc,
joinTimestamp: participantUpdate.joinTimestamp,
muteState: participantUpdate.muteState
)
let index = binaryInsertionIndex(updatedParticipants, searchItem: participant.joinTimestamp)
updatedParticipants.insert(participant, at: index)
}
}
var updatedOverlayState = strongSelf.stateValue.overlayState
for peerId in update.removePendingMuteStates {
updatedOverlayState.pendingMuteStateChanges.removeValue(forKey: peerId)
}
strongSelf.stateValue = InternalState(
state: State(
participants: Array(updatedParticipants.reversed()),
totalCount: updatedTotalCount,
version: update.version
),
overlayState: updatedOverlayState
)
strongSelf.endedProcessingUpdate()
})
}
private func resetStateFromServer() {
self.updateQueue.removeAll()
self.disposable.set((
getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, maxDate: 0, limit: 100)
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self else {
return
}
strongSelf.stateValue.state = state
strongSelf.endedProcessingUpdate()
}))
}
public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?) {
if let current = self.stateValue.overlayState.pendingMuteStateChanges[peerId] {
if current.state == muteState {
return
}
current.disposable.dispose()
self.stateValue.overlayState.pendingMuteStateChanges.removeValue(forKey: peerId)
}
let disposable = MetaDisposable()
self.stateValue.overlayState.pendingMuteStateChanges[peerId] = OverlayState.MuteStateChange(
state: muteState,
disposable: disposable
)
let account = self.account
let id = self.id
let accessHash = self.accessHash
let signal: Signal<Api.Updates?, NoError> = self.account.postbox.transaction { transaction -> Api.InputUser? in
return transaction.getPeer(peerId).flatMap(apiInputUser)
}
|> mapToSignal { inputUser -> Signal<Api.Updates?, NoError> in
guard let inputUser = inputUser else {
return .single(nil)
}
var flags: Int32 = 0
if muteState != nil {
flags |= 1 << 0
}
return account.network.request(Api.functions.phone.editGroupCallMember(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), userId: inputUser))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)
}
}
disposable.set((signal
|> deliverOnMainQueue).start(next: { [weak self] updates in
guard let strongSelf = self else {
return
}
if let updates = updates {
var stateUpdates: [GroupCallParticipantsContext.StateUpdate] = []
loop: for update in updates.allUpdates {
switch update {
case let .updateGroupCallParticipants(call, participants, version):
switch call {
case let .inputGroupCall(updateCallId, _):
if updateCallId != id {
continue loop
}
}
stateUpdates.append(GroupCallParticipantsContext.StateUpdate(participants: participants, version: version, removePendingMuteStates: [peerId]))
default:
break
}
}
strongSelf.addUpdates(updates: stateUpdates)
strongSelf.account.stateManager.addUpdates(updates)
} else {
strongSelf.stateValue.overlayState.pendingMuteStateChanges.removeValue(forKey: peerId)
}
}))
}
}
extension GroupCallParticipantsContext.StateUpdate {
init(participants: [Api.GroupCallParticipant], version: Int32, removePendingMuteStates: Set<PeerId> = Set()) {
var participantUpdates: [GroupCallParticipantsContext.StateUpdate.ParticipantUpdate] = []
for participant in participants {
switch participant {
case let .groupCallParticipant(flags, userId, date, source):
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
let ssrc = UInt32(bitPattern: source)
var muteState: GroupCallParticipantsContext.Participant.MuteState?
if (flags & (1 << 0)) != 0 {
let canUnmute = (flags & (1 << 2)) != 0
muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: canUnmute)
}
let isRemoved = (flags & (1 << 1)) != 0
participantUpdates.append(GroupCallParticipantsContext.StateUpdate.ParticipantUpdate(
peerId: peerId,
ssrc: ssrc,
joinTimestamp: date,
muteState: muteState,
isRemoved: isRemoved
))
}
}
self.init(
participantUpdates: participantUpdates,
version: version,
removePendingMuteStates: removePendingMuteStates
)
}
}

View File

@ -115,6 +115,8 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa
return .sendMessageRecordRoundAction
case let .uploadingInstantVideo(progress):
return .sendMessageUploadRoundAction(progress: progress)
case .speakingInGroupCall:
return .speakingInGroupCallAction
}
} else {
return .sendMessageCancelAction

View File

@ -10,78 +10,28 @@ public enum PeerInputActivity: Comparable {
case playingGame
case recordingInstantVideo
case uploadingInstantVideo(progress: Int32)
public static func ==(lhs: PeerInputActivity, rhs: PeerInputActivity) -> Bool {
switch lhs {
case .typingText:
if case .typingText = rhs {
return true
} else {
return false
}
case let .uploadingFile(progress):
if case .uploadingFile(progress) = rhs {
return true
} else {
return false
}
case .recordingVoice:
if case .recordingVoice = rhs {
return true
} else {
return false
}
case .playingGame:
if case .playingGame = rhs {
return true
} else {
return false
}
case .uploadingPhoto(let progress):
if case .uploadingPhoto(progress) = rhs {
return true
} else {
return false
}
case .uploadingVideo(let progress):
if case .uploadingVideo(progress) = rhs {
return true
} else {
return false
}
case .recordingInstantVideo:
if case .recordingInstantVideo = rhs {
return true
} else {
return false
}
case .uploadingInstantVideo(let progress):
if case .uploadingInstantVideo(progress) = rhs {
return true
} else {
return false
}
}
}
case speakingInGroupCall
public var key: Int32 {
switch self {
case .typingText:
return 0
case .uploadingFile:
case .speakingInGroupCall:
return 1
case .recordingVoice:
case .uploadingFile:
return 2
case .uploadingPhoto:
case .recordingVoice:
return 3
case .uploadingVideo:
case .uploadingPhoto:
return 4
case .recordingInstantVideo:
case .uploadingVideo:
return 5
case .uploadingInstantVideo:
case .recordingInstantVideo:
return 6
case .playingGame:
case .uploadingInstantVideo:
return 7
case .playingGame:
return 8
}
}
@ -111,6 +61,8 @@ extension PeerInputActivity {
self = .recordingInstantVideo
case let .sendMessageUploadRoundAction(progress):
self = .uploadingInstantVideo(progress: progress)
case .speakingInGroupCallAction:
self = .speakingInGroupCall
}
}
}

View File

@ -318,6 +318,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
stringValue = strings.Activity_RecordingVideoMessage
case .uploadingInstantVideo:
stringValue = strings.Activity_UploadingVideoMessage
case .speakingInGroupCall:
stringValue = ""
}
} else {
for (peer, _) in inputActivities {
@ -345,6 +347,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
state = .uploading(string, color)
case .playingGame:
state = .playingGame(string, color)
case .speakingInGroupCall:
state = .typingText(string, color)
}
} else {
if let titleContent = self.titleContent {

@ -1 +1 @@
Subproject commit c0a1340e81d4c4ee27307164afc2f43b4183851a
Subproject commit b245c575f350e13186d34b9ae38f6af555c6fe14

View File

@ -625,6 +625,7 @@ webrtc_sources = [
"pc/data_channel.cc",
"pc/data_channel_controller.cc",
"pc/datagram_rtp_transport.cc",
"pc/dtls_srtp_transport.h",
"pc/dtls_srtp_transport.cc",
"pc/dtls_transport.cc",
"pc/dtmf_sender.cc",
@ -2091,58 +2092,11 @@ cc_library(
visibility = ["//visibility:public"],
)
objc_library(
name = "webrtc_objc_sdk",
enable_modules = True,
module_name = "webrtc_objc_sdk",
srcs = ["webrtc-ios/src/sdk/" + path for path in ios_objc_sources],
copts = [
"-Ithird-party/webrtc/webrtc-ios/src",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/abseil-cpp",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/usrsctp/usrsctplib",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/usrsctp/usrsctplib/usrsctplib",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/libsrtp/include",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/libsrtp/crypto/include",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/libyuv/include",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/libvpx/source/libvpx",
"-Ithird-party/webrtc/webrtc-ios/src/testing/gtest/include",
"-Ithird-party/webrtc/webrtc-ios/src/sdk/objc",
"-Ithird-party/webrtc/webrtc-ios/src/sdk/objc/base",
"-Ithird-party/webrtc/additional-files",
"-DWEBRTC_IOS",
"-DWEBRTC_MAC",
"-DWEBRTC_POSIX",
"-DRTC_ENABLE_VP9",
"-DBSD=1",
"-DUSE_KISS_FFT",
"-DHAVE_PTHREAD",
"-DWEBRTC_APM_DEBUG_DUMP=0",
"-DWEBRTC_USE_BUILTIN_ISAC_FLOAT",
"-DWEBRTC_OPUS_VARIABLE_COMPLEXITY=0",
"-DHAVE_NETINET_IN_H",
"-DWEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE",
"-DSCTP_SIMPLE_ALLOCATOR",
"-DSCTP_PROCESS_LEVEL_LOCKS",
"-D__Userspace__",
"-D__Userspace_os_Darwin",
"-DPACKAGE_VERSION='\"\"'",
] + arch_specific_cflags,
deps = [
"//third-party/boringssl:crypto",
"//third-party/boringssl:ssl",
"//submodules/Opus:opus",
":usrsctp",
":libsrtp",
":libevent",
],
visibility = ["//visibility:public"],
)
objc_library(
name = "webrtc_objcpp_sdk",
enable_modules = True,
module_name = "webrtc_objcpp_sdk",
srcs = ["webrtc-ios/src/sdk/" + path for path in ios_sources],
srcs = ["webrtc-ios/src/sdk/" + path for path in ios_sources + ios_objc_sources],
copts = [
"-Ithird-party/webrtc/webrtc-ios/src",
"-Ithird-party/webrtc/webrtc-ios/src/third_party/abseil-cpp",
@ -2173,7 +2127,6 @@ objc_library(
"-D__Userspace__",
"-D__Userspace_os_Darwin",
"-DPACKAGE_VERSION='\"\"'",
"-std=c++14",
] + arch_specific_cflags,
deps = [
"//third-party/boringssl:crypto",
@ -2225,7 +2178,6 @@ objc_library(
":libsrtp",
":libevent",
":libyuv",
":webrtc_objc_sdk",
":webrtc_objcpp_sdk",
"//third-party/libvpx:vpx",
],

@ -1 +1 @@
Subproject commit 782743c7931d09c1d2e4a0cf6cd349ee45452f1d
Subproject commit facc5cdcc8792fd1a83f39b14ce5d719c6f44625