mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'beta'
This commit is contained in:
commit
77bfc86c6f
@ -389,7 +389,10 @@ public extension GroupCallParticipantsContext.Participant {
|
|||||||
guard let videoDescription = self.videoDescription else {
|
guard let videoDescription = self.videoDescription else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return PresentationGroupCallRequestedVideo(audioSsrc: audioSsrc, peerId: self.peer.id.id._internalGetInt64Value(), endpointId: videoDescription.endpointId, ssrcGroups: videoDescription.ssrcGroups.map { group in
|
guard let peer = self.peer else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return PresentationGroupCallRequestedVideo(audioSsrc: audioSsrc, peerId: peer.id.id._internalGetInt64Value(), endpointId: videoDescription.endpointId, ssrcGroups: videoDescription.ssrcGroups.map { group in
|
||||||
PresentationGroupCallRequestedVideo.SsrcGroup(semantics: group.semantics, ssrcs: group.ssrcs)
|
PresentationGroupCallRequestedVideo.SsrcGroup(semantics: group.semantics, ssrcs: group.ssrcs)
|
||||||
}, minQuality: minQuality, maxQuality: maxQuality)
|
}, minQuality: minQuality, maxQuality: maxQuality)
|
||||||
}
|
}
|
||||||
@ -401,7 +404,10 @@ public extension GroupCallParticipantsContext.Participant {
|
|||||||
guard let presentationDescription = self.presentationDescription else {
|
guard let presentationDescription = self.presentationDescription else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return PresentationGroupCallRequestedVideo(audioSsrc: audioSsrc, peerId: self.peer.id.id._internalGetInt64Value(), endpointId: presentationDescription.endpointId, ssrcGroups: presentationDescription.ssrcGroups.map { group in
|
guard let peer = self.peer else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return PresentationGroupCallRequestedVideo(audioSsrc: audioSsrc, peerId: peer.id.id._internalGetInt64Value(), endpointId: presentationDescription.endpointId, ssrcGroups: presentationDescription.ssrcGroups.map { group in
|
||||||
PresentationGroupCallRequestedVideo.SsrcGroup(semantics: group.semantics, ssrcs: group.ssrcs)
|
PresentationGroupCallRequestedVideo.SsrcGroup(semantics: group.semantics, ssrcs: group.ssrcs)
|
||||||
}, minQuality: minQuality, maxQuality: maxQuality)
|
}, minQuality: minQuality, maxQuality: maxQuality)
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,8 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
|
|||||||
id: call.id,
|
id: call.id,
|
||||||
reference: .id(id: call.id, accessHash: call.accessHash),
|
reference: .id(id: call.id, accessHash: call.accessHash),
|
||||||
state: state,
|
state: state,
|
||||||
previousServiceState: nil
|
previousServiceState: nil,
|
||||||
|
e2eContext: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
self.participantsContext = context
|
self.participantsContext = context
|
||||||
|
@ -425,8 +425,8 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
|||||||
if let members = currentMembers {
|
if let members = currentMembers {
|
||||||
var speakingPeers: [Peer] = []
|
var speakingPeers: [Peer] = []
|
||||||
for member in members.participants {
|
for member in members.participants {
|
||||||
if members.speakingParticipants.contains(member.peer.id) {
|
if let memberPeer = member.peer, members.speakingParticipants.contains(memberPeer.id) {
|
||||||
speakingPeers.append(member.peer)
|
speakingPeers.append(memberPeer._asPeer())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
speakingPeer = speakingPeers.first
|
speakingPeer = speakingPeers.first
|
||||||
|
@ -395,7 +395,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
if data.info.isStream {
|
if data.info.isStream {
|
||||||
self.avatarsContent = self.avatarsContext.update(peers: [], animated: false)
|
self.avatarsContent = self.avatarsContext.update(peers: [], animated: false)
|
||||||
} else {
|
} else {
|
||||||
self.avatarsContent = self.avatarsContext.update(peers: data.topParticipants.map { EnginePeer($0.peer) }, animated: false)
|
self.avatarsContent = self.avatarsContext.update(peers: data.topParticipants.compactMap { $0.peer }, animated: false)
|
||||||
|
|
||||||
if let imageDisposable = self.imageDisposable {
|
if let imageDisposable = self.imageDisposable {
|
||||||
self.imageDisposable = nil
|
self.imageDisposable = nil
|
||||||
@ -430,7 +430,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
if let info = summaryState.info, info.isStream {
|
if let info = summaryState.info, info.isStream {
|
||||||
strongSelf.avatarsContent = strongSelf.avatarsContext.update(peers: [], animated: false)
|
strongSelf.avatarsContent = strongSelf.avatarsContext.update(peers: [], animated: false)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.avatarsContent = strongSelf.avatarsContext.update(peers: summaryState.topParticipants.map { EnginePeer($0.peer) }, animated: false)
|
strongSelf.avatarsContent = strongSelf.avatarsContext.update(peers: summaryState.topParticipants.compactMap { $0.peer }, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (size, leftInset, rightInset, isHidden) = strongSelf.validLayout {
|
if let (size, leftInset, rightInset, isHidden) = strongSelf.validLayout {
|
||||||
@ -513,7 +513,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
if data.info.isStream {
|
if data.info.isStream {
|
||||||
self.avatarsContent = self.avatarsContext.update(peers: [], animated: false)
|
self.avatarsContent = self.avatarsContext.update(peers: [], animated: false)
|
||||||
} else {
|
} else {
|
||||||
self.avatarsContent = self.avatarsContext.update(peers: data.topParticipants.map { EnginePeer($0.peer) }, animated: false)
|
self.avatarsContent = self.avatarsContext.update(peers: data.topParticipants.compactMap { $0.peer }, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAudioLevels = true
|
updateAudioLevels = true
|
||||||
|
@ -908,7 +908,7 @@ public final class PresentationCallImpl: PresentationCall {
|
|||||||
var found = false
|
var found = false
|
||||||
if let members {
|
if let members {
|
||||||
for participant in members.participants {
|
for participant in members.participants {
|
||||||
if participant.peer.id == waitForRemotePeerId {
|
if participant.id == .peer(waitForRemotePeerId) {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -921,7 +921,7 @@ public final class PresentationCallImpl: PresentationCall {
|
|||||||
if waitForLocalVideo {
|
if waitForLocalVideo {
|
||||||
if let members {
|
if let members {
|
||||||
for participant in members.participants {
|
for participant in members.participants {
|
||||||
if participant.peer.id == state.myPeerId {
|
if participant.id == .peer(state.myPeerId) {
|
||||||
if participant.videoDescription == nil {
|
if participant.videoDescription == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -932,7 +932,7 @@ public final class PresentationCallImpl: PresentationCall {
|
|||||||
if let waitForRemoteVideo {
|
if let waitForRemoteVideo {
|
||||||
if let members {
|
if let members {
|
||||||
for participant in members.participants {
|
for participant in members.participants {
|
||||||
if participant.peer.id == waitForRemoteVideo {
|
if participant.id == .peer(waitForRemoteVideo) {
|
||||||
if participant.videoDescription == nil {
|
if participant.videoDescription == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -332,8 +332,12 @@ private final class ConferenceCallE2EContextStateImpl: ConferenceCallE2EContextS
|
|||||||
return self.call.emojiState()
|
return self.call.emojiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getParticipants() -> [ConferenceCallE2EContext.BlockchainParticipant] {
|
||||||
|
return self.call.participants().map { ConferenceCallE2EContext.BlockchainParticipant(userId: $0.userId, internalId: $0.internalId) }
|
||||||
|
}
|
||||||
|
|
||||||
func getParticipantIds() -> [Int64] {
|
func getParticipantIds() -> [Int64] {
|
||||||
return self.call.participantIds().compactMap { $0.int64Value }
|
return self.call.participants().map { $0.userId }
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyBlock(block: Data) {
|
func applyBlock(block: Data) {
|
||||||
@ -1246,7 +1250,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let sourceContext = sourceContext, let initialState = sourceContext.immediateState {
|
if let sourceContext = sourceContext, let initialState = sourceContext.immediateState {
|
||||||
let temporaryParticipantsContext = self.accountContext.engine.calls.groupCall(peerId: self.peerId, myPeerId: myPeerId, id: sourceContext.id, reference: sourceContext.reference, state: initialState, previousServiceState: sourceContext.serviceState)
|
let temporaryParticipantsContext = self.accountContext.engine.calls.groupCall(peerId: self.peerId, myPeerId: myPeerId, id: sourceContext.id, reference: sourceContext.reference, state: initialState, previousServiceState: sourceContext.serviceState, e2eContext: self.e2eContext)
|
||||||
self.temporaryParticipantsContext = temporaryParticipantsContext
|
self.temporaryParticipantsContext = temporaryParticipantsContext
|
||||||
self.participantsContextStateDisposable.set((combineLatest(queue: .mainQueue(),
|
self.participantsContextStateDisposable.set((combineLatest(queue: .mainQueue(),
|
||||||
myPeerData,
|
myPeerData,
|
||||||
@ -1274,14 +1278,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
if oldMyPeerId != myPeerId {
|
if oldMyPeerId != myPeerId {
|
||||||
for i in 0 ..< participants.count {
|
for i in 0 ..< participants.count {
|
||||||
if participants[i].peer.id == oldMyPeerId {
|
if participants[i].id == .peer(oldMyPeerId) {
|
||||||
participants.remove(at: i)
|
participants.remove(at: i)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !participants.contains(where: { $0.peer.id == myPeerId }) {
|
if !participants.contains(where: { $0.id == .peer(myPeerId) }) {
|
||||||
if let (myPeer, aboutText) = myPeerData {
|
if let (myPeer, aboutText) = myPeerData {
|
||||||
let about: String?
|
let about: String?
|
||||||
if let aboutText = aboutText {
|
if let aboutText = aboutText {
|
||||||
@ -1290,7 +1294,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
about = " "
|
about = " "
|
||||||
}
|
}
|
||||||
participants.append(GroupCallParticipantsContext.Participant(
|
participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: myPeer._asPeer(),
|
id: .peer(myPeer.id),
|
||||||
|
peer: myPeer,
|
||||||
ssrc: nil,
|
ssrc: nil,
|
||||||
videoDescription: nil,
|
videoDescription: nil,
|
||||||
presentationDescription: nil,
|
presentationDescription: nil,
|
||||||
@ -1315,7 +1320,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
topParticipants.append(participant)
|
topParticipants.append(participant)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let index = updatedInvitedPeers.firstIndex(where: { $0.id == participant.peer.id }) {
|
if let index = updatedInvitedPeers.firstIndex(where: { participant.id == .peer($0.id) }) {
|
||||||
updatedInvitedPeers.remove(at: index)
|
updatedInvitedPeers.remove(at: index)
|
||||||
didUpdateInvitedPeers = true
|
didUpdateInvitedPeers = true
|
||||||
}
|
}
|
||||||
@ -1370,7 +1375,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
about = " "
|
about = " "
|
||||||
}
|
}
|
||||||
participants.append(GroupCallParticipantsContext.Participant(
|
participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: myPeer._asPeer(),
|
id: .peer(myPeer.id),
|
||||||
|
peer: myPeer,
|
||||||
ssrc: nil,
|
ssrc: nil,
|
||||||
videoDescription: nil,
|
videoDescription: nil,
|
||||||
presentationDescription: nil,
|
presentationDescription: nil,
|
||||||
@ -1495,7 +1501,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
isStream: callInfo.isStream,
|
isStream: callInfo.isStream,
|
||||||
version: 0
|
version: 0
|
||||||
),
|
),
|
||||||
previousServiceState: nil
|
previousServiceState: nil,
|
||||||
|
e2eContext: self.e2eContext
|
||||||
)
|
)
|
||||||
self.temporaryParticipantsContext = nil
|
self.temporaryParticipantsContext = nil
|
||||||
self.participantsContext = participantsContext
|
self.participantsContext = participantsContext
|
||||||
@ -1555,7 +1562,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
about = " "
|
about = " "
|
||||||
}
|
}
|
||||||
participants.append(GroupCallParticipantsContext.Participant(
|
participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: myPeer._asPeer(),
|
id: .peer(myPeer.id),
|
||||||
|
peer: myPeer,
|
||||||
ssrc: nil,
|
ssrc: nil,
|
||||||
videoDescription: nil,
|
videoDescription: nil,
|
||||||
presentationDescription: nil,
|
presentationDescription: nil,
|
||||||
@ -1967,11 +1975,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
self.ssrcMapping.removeAll()
|
self.ssrcMapping.removeAll()
|
||||||
for participant in joinCallResult.state.participants {
|
for participant in joinCallResult.state.participants {
|
||||||
if let ssrc = participant.ssrc {
|
if let ssrc = participant.ssrc, let participantPeer = participant.peer {
|
||||||
self.ssrcMapping[ssrc] = SsrcMapping(peerId: participant.peer.id, isPresentation: false)
|
self.ssrcMapping[ssrc] = SsrcMapping(peerId: participantPeer.id, isPresentation: false)
|
||||||
}
|
}
|
||||||
if let presentationSsrc = participant.presentationDescription?.audioSsrc {
|
if let presentationSsrc = participant.presentationDescription?.audioSsrc, let participantPeer = participant.peer {
|
||||||
self.ssrcMapping[presentationSsrc] = SsrcMapping(peerId: participant.peer.id, isPresentation: true)
|
self.ssrcMapping[presentationSsrc] = SsrcMapping(peerId: participantPeer.id, isPresentation: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2268,7 +2276,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
id: callInfo.id,
|
id: callInfo.id,
|
||||||
reference: reference,
|
reference: reference,
|
||||||
state: initialState,
|
state: initialState,
|
||||||
previousServiceState: serviceState
|
previousServiceState: serviceState,
|
||||||
|
e2eContext: self.e2eContext
|
||||||
)
|
)
|
||||||
self.temporaryParticipantsContext = nil
|
self.temporaryParticipantsContext = nil
|
||||||
self.participantsContext = participantsContext
|
self.participantsContext = participantsContext
|
||||||
@ -2367,14 +2376,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
if let (ignorePeerId, ignoreSsrc) = self.ignorePreviousJoinAsPeerId {
|
if let (ignorePeerId, ignoreSsrc) = self.ignorePreviousJoinAsPeerId {
|
||||||
for i in 0 ..< participants.count {
|
for i in 0 ..< participants.count {
|
||||||
if participants[i].peer.id == ignorePeerId && participants[i].ssrc == ignoreSsrc {
|
if participants[i].id == .peer(ignorePeerId) && participants[i].ssrc == ignoreSsrc {
|
||||||
participants.remove(at: i)
|
participants.remove(at: i)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !participants.contains(where: { $0.peer.id == myPeerId }) && !self.leaving {
|
if !participants.contains(where: { $0.id == .peer(myPeerId) }) && !self.leaving {
|
||||||
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 {
|
||||||
@ -2386,7 +2395,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
participants.append(GroupCallParticipantsContext.Participant(
|
participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: myPeer,
|
id: .peer(myPeer.id),
|
||||||
|
peer: EnginePeer(myPeer),
|
||||||
ssrc: nil,
|
ssrc: nil,
|
||||||
videoDescription: nil,
|
videoDescription: nil,
|
||||||
presentationDescription: nil,
|
presentationDescription: nil,
|
||||||
@ -2415,13 +2425,17 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let ssrc = participant.ssrc {
|
if let ssrc = participant.ssrc {
|
||||||
self.ssrcMapping[ssrc] = SsrcMapping(peerId: participant.peer.id, isPresentation: false)
|
if let participantPeer = participant.peer {
|
||||||
|
self.ssrcMapping[ssrc] = SsrcMapping(peerId: participantPeer.id, isPresentation: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let presentationSsrc = participant.presentationDescription?.audioSsrc {
|
if let presentationSsrc = participant.presentationDescription?.audioSsrc {
|
||||||
self.ssrcMapping[presentationSsrc] = SsrcMapping(peerId: participant.peer.id, isPresentation: true)
|
if let participantPeer = participant.peer {
|
||||||
|
self.ssrcMapping[presentationSsrc] = SsrcMapping(peerId: participantPeer.id, isPresentation: true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if participant.peer.id == self.joinAsPeerId {
|
if participant.id == .peer(self.joinAsPeerId) {
|
||||||
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 {
|
||||||
@ -2431,7 +2445,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
} else {
|
} else {
|
||||||
about = " "
|
about = " "
|
||||||
}
|
}
|
||||||
participant.peer = myPeer
|
participant.peer = EnginePeer(myPeer)
|
||||||
participant.about = about
|
participant.about = about
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2531,7 +2545,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let index = updatedInvitedPeers.firstIndex(where: { $0.id == participant.peer.id }) {
|
if let index = updatedInvitedPeers.firstIndex(where: { participant.id == .peer($0.id) }) {
|
||||||
updatedInvitedPeers.remove(at: index)
|
updatedInvitedPeers.remove(at: index)
|
||||||
didUpdateInvitedPeers = true
|
didUpdateInvitedPeers = true
|
||||||
}
|
}
|
||||||
@ -2646,21 +2660,24 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
if remainingSsrcs.contains(audioSsrc) {
|
if remainingSsrcs.contains(audioSsrc) {
|
||||||
remainingSsrcs.remove(audioSsrc)
|
remainingSsrcs.remove(audioSsrc)
|
||||||
|
|
||||||
|
if let participantPeer = participant.peer {
|
||||||
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
||||||
kind: .audio,
|
kind: .audio,
|
||||||
peerId: participant.peer.id.id._internalGetInt64Value(),
|
peerId: participantPeer.id.id._internalGetInt64Value(),
|
||||||
audioSsrc: audioSsrc,
|
audioSsrc: audioSsrc,
|
||||||
videoDescription: nil
|
videoDescription: nil
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let screencastSsrc = participant.presentationDescription?.audioSsrc {
|
if let screencastSsrc = participant.presentationDescription?.audioSsrc {
|
||||||
if remainingSsrcs.contains(screencastSsrc) {
|
if remainingSsrcs.contains(screencastSsrc) {
|
||||||
remainingSsrcs.remove(screencastSsrc)
|
remainingSsrcs.remove(screencastSsrc)
|
||||||
|
|
||||||
|
if let participantPeer = participant.peer {
|
||||||
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
||||||
kind: .audio,
|
kind: .audio,
|
||||||
peerId: participant.peer.id.id._internalGetInt64Value(),
|
peerId: participantPeer.id.id._internalGetInt64Value(),
|
||||||
audioSsrc: screencastSsrc,
|
audioSsrc: screencastSsrc,
|
||||||
videoDescription: nil
|
videoDescription: nil
|
||||||
))
|
))
|
||||||
@ -2668,6 +2685,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var remainingSsrcs = ssrcs
|
var remainingSsrcs = ssrcs
|
||||||
var result: [OngoingGroupCallContext.MediaChannelDescription] = []
|
var result: [OngoingGroupCallContext.MediaChannelDescription] = []
|
||||||
@ -2849,7 +2867,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
if let participantsContext = self.participantsContext, let immediateState = participantsContext.immediateState {
|
if let participantsContext = self.participantsContext, let immediateState = participantsContext.immediateState {
|
||||||
for participant in immediateState.participants {
|
for participant in immediateState.participants {
|
||||||
if participant.peer.id == previousPeerId {
|
if participant.id == .peer(previousPeerId) {
|
||||||
self.temporaryJoinTimestamp = participant.joinTimestamp
|
self.temporaryJoinTimestamp = participant.joinTimestamp
|
||||||
self.temporaryActivityTimestamp = participant.activityTimestamp
|
self.temporaryActivityTimestamp = participant.activityTimestamp
|
||||||
self.temporaryActivityRank = participant.activityRank
|
self.temporaryActivityRank = participant.activityRank
|
||||||
@ -3008,7 +3026,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for participant in membersValue.participants {
|
for participant in membersValue.participants {
|
||||||
if participant.peer.id == self.joinAsPeerId {
|
if participant.id == .peer(self.joinAsPeerId) {
|
||||||
if participant.hasRaiseHand {
|
if participant.hasRaiseHand {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -3024,7 +3042,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for participant in membersValue.participants {
|
for participant in membersValue.participants {
|
||||||
if participant.peer.id == self.joinAsPeerId {
|
if participant.id == .peer(self.joinAsPeerId) {
|
||||||
if !participant.hasRaiseHand {
|
if !participant.hasRaiseHand {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,9 @@ final class VideoChatParticipantThumbnailComponent: Component {
|
|||||||
gesture.cancel()
|
gesture.cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
component.contextAction?(EnginePeer(component.participant.peer), self.extractedContainerView, gesture)
|
if let participantPeer = component.participant.peer {
|
||||||
|
component.contextAction?(participantPeer, self.extractedContainerView, gesture)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,10 +215,10 @@ final class VideoChatParticipantThumbnailComponent: Component {
|
|||||||
let avatarFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - avatarSize.width) * 0.5), y: 7.0), size: avatarSize)
|
let avatarFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - avatarSize.width) * 0.5), y: 7.0), size: avatarSize)
|
||||||
transition.setFrame(view: avatarNode.view, frame: avatarFrame)
|
transition.setFrame(view: avatarNode.view, frame: avatarFrame)
|
||||||
avatarNode.updateSize(size: avatarSize)
|
avatarNode.updateSize(size: avatarSize)
|
||||||
if component.participant.peer.smallProfileImage != nil {
|
if component.participant.peer?.smallProfileImage != nil {
|
||||||
avatarNode.setPeerV2(context: component.call.accountContext, theme: component.theme, peer: EnginePeer(component.participant.peer), displayDimensions: avatarSize)
|
avatarNode.setPeerV2(context: component.call.accountContext, theme: component.theme, peer: component.participant.peer, displayDimensions: avatarSize)
|
||||||
} else {
|
} else {
|
||||||
avatarNode.setPeer(context: component.call.accountContext, theme: component.theme, peer: EnginePeer(component.participant.peer), displayDimensions: avatarSize)
|
avatarNode.setPeer(context: component.call.accountContext, theme: component.theme, peer: component.participant.peer, displayDimensions: avatarSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
let muteStatusSize = self.muteStatus.update(
|
let muteStatusSize = self.muteStatus.update(
|
||||||
@ -241,7 +243,7 @@ final class VideoChatParticipantThumbnailComponent: Component {
|
|||||||
let titleSize = self.title.update(
|
let titleSize = self.title.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: EnginePeer(component.participant.peer).compactDisplayTitle, font: Font.semibold(13.0), textColor: .white))
|
text: .plain(NSAttributedString(string: component.participant.peer?.compactDisplayTitle ?? "User \(component.participant.id)", font: Font.semibold(13.0), textColor: .white))
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - 6.0 * 2.0 - 12.0, height: 100.0)
|
containerSize: CGSize(width: availableSize.width - 6.0 * 2.0 - 12.0, height: 100.0)
|
||||||
@ -436,10 +438,10 @@ final class VideoChatParticipantThumbnailComponent: Component {
|
|||||||
final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
||||||
final class Participant: Equatable {
|
final class Participant: Equatable {
|
||||||
struct Key: Hashable {
|
struct Key: Hashable {
|
||||||
var id: EnginePeer.Id
|
var id: GroupCallParticipantsContext.Participant.Id
|
||||||
var isPresentation: Bool
|
var isPresentation: Bool
|
||||||
|
|
||||||
init(id: EnginePeer.Id, isPresentation: Bool) {
|
init(id: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.isPresentation = isPresentation
|
self.isPresentation = isPresentation
|
||||||
}
|
}
|
||||||
@ -449,7 +451,7 @@ final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
|||||||
let isPresentation: Bool
|
let isPresentation: Bool
|
||||||
|
|
||||||
var key: Key {
|
var key: Key {
|
||||||
return Key(id: self.participant.peer.id, isPresentation: self.isPresentation)
|
return Key(id: self.participant.id, isPresentation: self.isPresentation)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@ -657,6 +659,12 @@ final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
|||||||
let itemFrame = itemLayout.frame(at: i)
|
let itemFrame = itemLayout.frame(at: i)
|
||||||
|
|
||||||
let participantKey = participant.key
|
let participantKey = participant.key
|
||||||
|
|
||||||
|
var isSpeaking = false
|
||||||
|
if let participantPeer = participant.participant.peer {
|
||||||
|
isSpeaking = component.speakingParticipants.contains(participantPeer.id)
|
||||||
|
}
|
||||||
|
|
||||||
let _ = itemView.view.update(
|
let _ = itemView.view.update(
|
||||||
transition: itemTransition,
|
transition: itemTransition,
|
||||||
component: AnyComponent(VideoChatParticipantThumbnailComponent(
|
component: AnyComponent(VideoChatParticipantThumbnailComponent(
|
||||||
@ -665,7 +673,7 @@ final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
|||||||
participant: participant.participant,
|
participant: participant.participant,
|
||||||
isPresentation: participant.isPresentation,
|
isPresentation: participant.isPresentation,
|
||||||
isSelected: component.selectedParticipant == participant.key,
|
isSelected: component.selectedParticipant == participant.key,
|
||||||
isSpeaking: component.speakingParticipants.contains(participant.participant.peer.id),
|
isSpeaking: isSpeaking,
|
||||||
displayVideo: component.displayVideo,
|
displayVideo: component.displayVideo,
|
||||||
interfaceOrientation: component.interfaceOrientation,
|
interfaceOrientation: component.interfaceOrientation,
|
||||||
action: { [weak self] in
|
action: { [weak self] in
|
||||||
|
@ -133,14 +133,14 @@ private final class BlobView: UIView {
|
|||||||
|
|
||||||
final class VideoChatParticipantAvatarComponent: Component {
|
final class VideoChatParticipantAvatarComponent: Component {
|
||||||
let call: VideoChatCall
|
let call: VideoChatCall
|
||||||
let peer: EnginePeer
|
let peer: EnginePeer?
|
||||||
let myPeerId: EnginePeer.Id
|
let myPeerId: EnginePeer.Id
|
||||||
let isSpeaking: Bool
|
let isSpeaking: Bool
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
|
|
||||||
init(
|
init(
|
||||||
call: VideoChatCall,
|
call: VideoChatCall,
|
||||||
peer: EnginePeer,
|
peer: EnginePeer?,
|
||||||
myPeerId: EnginePeer.Id,
|
myPeerId: EnginePeer.Id,
|
||||||
isSpeaking: Bool,
|
isSpeaking: Bool,
|
||||||
theme: PresentationTheme
|
theme: PresentationTheme
|
||||||
@ -267,7 +267,7 @@ final class VideoChatParticipantAvatarComponent: Component {
|
|||||||
tintTransition.setTintColor(layer: blobView.blobsLayer, color: component.isSpeaking ? UIColor(rgb: 0x33C758) : component.theme.list.itemAccentColor)
|
tintTransition.setTintColor(layer: blobView.blobsLayer, color: component.isSpeaking ? UIColor(rgb: 0x33C758) : component.theme.list.itemAccentColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if component.peer.smallProfileImage != nil {
|
if component.peer?.smallProfileImage != nil {
|
||||||
avatarNode.setPeerV2(
|
avatarNode.setPeerV2(
|
||||||
context: component.call.accountContext,
|
context: component.call.accountContext,
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
@ -296,7 +296,7 @@ final class VideoChatParticipantAvatarComponent: Component {
|
|||||||
var isSpeaking: Bool
|
var isSpeaking: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
let peerId = component.peer.id
|
let peerId = component.peer?.id
|
||||||
let levelSignal: Signal<Level?, NoError>
|
let levelSignal: Signal<Level?, NoError>
|
||||||
if peerId == component.myPeerId {
|
if peerId == component.myPeerId {
|
||||||
levelSignal = component.call.myAudioLevelAndSpeaking
|
levelSignal = component.call.myAudioLevelAndSpeaking
|
||||||
|
@ -245,7 +245,9 @@ final class VideoChatParticipantVideoComponent: Component {
|
|||||||
gesture.cancel()
|
gesture.cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
component.contextAction?(EnginePeer(component.participant.peer), self.extractedContainerView, gesture)
|
if let participantPeer = component.participant.peer {
|
||||||
|
component.contextAction?(participantPeer, self.extractedContainerView, gesture)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,12 +318,12 @@ final class VideoChatParticipantVideoComponent: Component {
|
|||||||
let controlsAlpha: CGFloat = component.isUIHidden ? 0.0 : 1.0
|
let controlsAlpha: CGFloat = component.isUIHidden ? 0.0 : 1.0
|
||||||
|
|
||||||
if previousComponent == nil {
|
if previousComponent == nil {
|
||||||
let colors = calculateAvatarColors(context: component.call.accountContext, explicitColorIndex: nil, peerId: component.participant.peer.id, nameColor: component.participant.peer.nameColor, icon: .none, theme: component.theme)
|
let colors = calculateAvatarColors(context: component.call.accountContext, explicitColorIndex: nil, peerId: component.participant.peer?.id, nameColor: component.participant.peer?.nameColor, icon: .none, theme: component.theme)
|
||||||
|
|
||||||
self.backgroundGradientView.image = generateGradientImage(size: CGSize(width: 8.0, height: 32.0), colors: colors.reversed(), locations: [0.0, 1.0], direction: .vertical)
|
self.backgroundGradientView.image = generateGradientImage(size: CGSize(width: 8.0, height: 32.0), colors: colors.reversed(), locations: [0.0, 1.0], direction: .vertical)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let smallProfileImage = component.participant.peer.smallProfileImage {
|
if let smallProfileImage = component.participant.peer?.smallProfileImage {
|
||||||
let blurredAvatarView: UIImageView
|
let blurredAvatarView: UIImageView
|
||||||
if let current = self.blurredAvatarView {
|
if let current = self.blurredAvatarView {
|
||||||
blurredAvatarView = current
|
blurredAvatarView = current
|
||||||
@ -338,8 +340,8 @@ final class VideoChatParticipantVideoComponent: Component {
|
|||||||
|
|
||||||
if self.blurredAvatarDisposable == nil {
|
if self.blurredAvatarDisposable == nil {
|
||||||
//TODO:release synchronous
|
//TODO:release synchronous
|
||||||
if let imageCache = component.call.accountContext.imageCache as? DirectMediaImageCache, let peerReference = PeerReference(component.participant.peer) {
|
if let participantPeer = component.participant.peer, let imageCache = component.call.accountContext.imageCache as? DirectMediaImageCache, let peerReference = PeerReference(participantPeer._asPeer()) {
|
||||||
if let result = imageCache.getAvatarImage(peer: peerReference, resource: MediaResourceReference.avatar(peer: peerReference, resource: smallProfileImage.resource), immediateThumbnail: component.participant.peer.profileImageRepresentations.first?.immediateThumbnailData, size: 64, synchronous: false) {
|
if let result = imageCache.getAvatarImage(peer: peerReference, resource: MediaResourceReference.avatar(peer: peerReference, resource: smallProfileImage.resource), immediateThumbnail: participantPeer.profileImageRepresentations.first?.immediateThumbnailData, size: 64, synchronous: false) {
|
||||||
if let image = result.image {
|
if let image = result.image {
|
||||||
blurredAvatarView.image = blurredAvatarImage(image)
|
blurredAvatarView.image = blurredAvatarImage(image)
|
||||||
}
|
}
|
||||||
@ -402,7 +404,7 @@ final class VideoChatParticipantVideoComponent: Component {
|
|||||||
let titleSize = self.title.update(
|
let titleSize = self.title.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: component.participant.peer.debugDisplayTitle, font: Font.semibold(16.0), textColor: .white)),
|
text: .plain(NSAttributedString(string: component.participant.peer?.debugDisplayTitle ?? "User \(component.participant.id)", font: Font.semibold(16.0), textColor: .white)),
|
||||||
insets: titleInnerInsets,
|
insets: titleInnerInsets,
|
||||||
textShadowColor: UIColor(white: 0.0, alpha: 0.7),
|
textShadowColor: UIColor(white: 0.0, alpha: 0.7),
|
||||||
textShadowBlur: 8.0
|
textShadowBlur: 8.0
|
||||||
|
@ -92,10 +92,10 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct VideoParticipantKey: Hashable {
|
struct VideoParticipantKey: Hashable {
|
||||||
var id: EnginePeer.Id
|
var id: GroupCallParticipantsContext.Participant.Id
|
||||||
var isPresentation: Bool
|
var isPresentation: Bool
|
||||||
|
|
||||||
init(id: EnginePeer.Id, isPresentation: Bool) {
|
init(id: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.isPresentation = isPresentation
|
self.isPresentation = isPresentation
|
||||||
}
|
}
|
||||||
@ -608,7 +608,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
let isPresentation: Bool
|
let isPresentation: Bool
|
||||||
|
|
||||||
var key: VideoParticipantKey {
|
var key: VideoParticipantKey {
|
||||||
return VideoParticipantKey(id: self.participant.peer.id, isPresentation: self.isPresentation)
|
return VideoParticipantKey(id: self.participant.id, isPresentation: self.isPresentation)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(participant: GroupCallParticipantsContext.Participant, isPresentation: Bool) {
|
init(participant: GroupCallParticipantsContext.Participant, isPresentation: Bool) {
|
||||||
@ -673,7 +673,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
private var expandedThumbnailsView: ComponentView<Empty>?
|
private var expandedThumbnailsView: ComponentView<Empty>?
|
||||||
private var expandedSpeakingToast: ComponentView<Empty>?
|
private var expandedSpeakingToast: ComponentView<Empty>?
|
||||||
|
|
||||||
private var listItemViews: [EnginePeer.Id: ListItem] = [:]
|
private var listItemViews: [GroupCallParticipantsContext.Participant.Id: ListItem] = [:]
|
||||||
private let listItemViewContainer: UIView
|
private let listItemViewContainer: UIView
|
||||||
private let listItemViewSeparatorContainer: SimpleLayer
|
private let listItemViewSeparatorContainer: SimpleLayer
|
||||||
private let listItemsBackground = ComponentView<Empty>()
|
private let listItemsBackground = ComponentView<Empty>()
|
||||||
@ -959,7 +959,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var visibleParticipants: [EnginePeer.Id] = []
|
var visibleParticipants: [GroupCallParticipantsContext.Participant.Id] = []
|
||||||
|
|
||||||
for index in validGridItemIndices {
|
for index in validGridItemIndices {
|
||||||
let videoParticipant = self.gridParticipants[index]
|
let videoParticipant = self.gridParticipants[index]
|
||||||
@ -988,7 +988,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isItemExpanded || (index >= clippedVisibleGridItemRange.minIndex && index <= clippedVisibleGridItemRange.maxIndex) {
|
if isItemExpanded || (index >= clippedVisibleGridItemRange.minIndex && index <= clippedVisibleGridItemRange.maxIndex) {
|
||||||
visibleParticipants.append(videoParticipant.key.id)
|
visibleParticipants.append(videoParticipant.participant.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
var suppressItemExpansionCollapseAnimation = false
|
var suppressItemExpansionCollapseAnimation = false
|
||||||
@ -1049,6 +1049,11 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
itemAlpha = 1.0
|
itemAlpha = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isSpeaking = false
|
||||||
|
if let participantPeer = videoParticipant.participant.peer {
|
||||||
|
isSpeaking = component.speakingParticipants.contains(participantPeer.id)
|
||||||
|
}
|
||||||
|
|
||||||
let _ = itemView.view.update(
|
let _ = itemView.view.update(
|
||||||
transition: itemTransition,
|
transition: itemTransition,
|
||||||
component: AnyComponent(VideoChatParticipantVideoComponent(
|
component: AnyComponent(VideoChatParticipantVideoComponent(
|
||||||
@ -1056,9 +1061,9 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
call: component.call,
|
call: component.call,
|
||||||
participant: videoParticipant.participant,
|
participant: videoParticipant.participant,
|
||||||
isMyPeer: videoParticipant.participant.peer.id == component.participants?.myPeerId,
|
isMyPeer: videoParticipant.participant.peer?.id == component.participants?.myPeerId,
|
||||||
isPresentation: videoParticipant.isPresentation,
|
isPresentation: videoParticipant.isPresentation,
|
||||||
isSpeaking: component.speakingParticipants.contains(videoParticipant.participant.peer.id),
|
isSpeaking: isSpeaking,
|
||||||
maxVideoQuality: component.maxVideoQuality,
|
maxVideoQuality: component.maxVideoQuality,
|
||||||
isExpanded: isItemExpanded,
|
isExpanded: isItemExpanded,
|
||||||
isUIHidden: isItemUIHidden || self.isPinchToZoomActive,
|
isUIHidden: isItemUIHidden || self.isPinchToZoomActive,
|
||||||
@ -1205,23 +1210,23 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
self.gridItemViews.removeValue(forKey: itemId)
|
self.gridItemViews.removeValue(forKey: itemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
var validListItemIds: [EnginePeer.Id] = []
|
var validListItemIds: [GroupCallParticipantsContext.Participant.Id] = []
|
||||||
let visibleListItemRange = itemLayout.visibleListItemRange(for: self.scrollView.bounds)
|
let visibleListItemRange = itemLayout.visibleListItemRange(for: self.scrollView.bounds)
|
||||||
let clippedVisibleListItemRange = itemLayout.visibleListItemRange(for: clippedScrollViewBounds)
|
let clippedVisibleListItemRange = itemLayout.visibleListItemRange(for: clippedScrollViewBounds)
|
||||||
if visibleListItemRange.maxIndex >= visibleListItemRange.minIndex {
|
if visibleListItemRange.maxIndex >= visibleListItemRange.minIndex {
|
||||||
for i in visibleListItemRange.minIndex ... visibleListItemRange.maxIndex {
|
for i in visibleListItemRange.minIndex ... visibleListItemRange.maxIndex {
|
||||||
let itemFrame = itemLayout.listItemFrame(at: i)
|
let itemFrame = itemLayout.listItemFrame(at: i)
|
||||||
|
|
||||||
let participantPeerId: EnginePeer.Id
|
let participantItemId: GroupCallParticipantsContext.Participant.Id
|
||||||
let peerItemComponent: PeerListItemComponent
|
let peerItemComponent: PeerListItemComponent
|
||||||
if i < self.listParticipants.count {
|
if i < self.listParticipants.count {
|
||||||
let participant = self.listParticipants[i]
|
let participant = self.listParticipants[i]
|
||||||
participantPeerId = participant.peer.id
|
participantItemId = participant.id
|
||||||
|
|
||||||
let subtitle: PeerListItemComponent.Subtitle
|
let subtitle: PeerListItemComponent.Subtitle
|
||||||
if participant.peer.id == component.call.accountContext.account.peerId {
|
if participant.id == .peer(component.call.accountContext.account.peerId) {
|
||||||
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_You, color: .accent)
|
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_You, color: .accent)
|
||||||
} else if component.speakingParticipants.contains(participant.peer.id) {
|
} else if let participantPeer = participant.peer, component.speakingParticipants.contains(participantPeer.id) {
|
||||||
if let volume = participant.volume, volume / 100 != 100 {
|
if let volume = participant.volume, volume / 100 != 100 {
|
||||||
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeakingVolume("\(volume / 100)%").string, color: .constructive)
|
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeakingVolume("\(volume / 100)%").string, color: .constructive)
|
||||||
} else {
|
} else {
|
||||||
@ -1233,10 +1238,14 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusListening, color: .neutral)
|
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusListening, color: .neutral)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isSpeaking = false
|
||||||
|
if let participantPeer = participant.peer {
|
||||||
|
isSpeaking = component.speakingParticipants.contains(participantPeer.id)
|
||||||
|
}
|
||||||
let rightAccessoryComponent: AnyComponent<Empty> = AnyComponent(VideoChatParticipantStatusComponent(
|
let rightAccessoryComponent: AnyComponent<Empty> = AnyComponent(VideoChatParticipantStatusComponent(
|
||||||
muteState: participant.muteState,
|
muteState: participant.muteState,
|
||||||
hasRaiseHand: participant.hasRaiseHand,
|
hasRaiseHand: participant.hasRaiseHand,
|
||||||
isSpeaking: component.speakingParticipants.contains(participant.peer.id),
|
isSpeaking: isSpeaking,
|
||||||
theme: component.theme
|
theme: component.theme
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -1246,15 +1255,15 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
style: .generic,
|
style: .generic,
|
||||||
sideInset: 0.0,
|
sideInset: 0.0,
|
||||||
title: EnginePeer(participant.peer).displayTitle(strings: component.strings, displayOrder: .firstLast),
|
title: participant.peer?.displayTitle(strings: component.strings, displayOrder: .firstLast) ?? "User \(participant.id)",
|
||||||
avatarComponent: AnyComponent(VideoChatParticipantAvatarComponent(
|
avatarComponent: AnyComponent(VideoChatParticipantAvatarComponent(
|
||||||
call: component.call,
|
call: component.call,
|
||||||
peer: EnginePeer(participant.peer),
|
peer: participant.peer,
|
||||||
myPeerId: component.participants?.myPeerId ?? component.call.accountContext.account.peerId,
|
myPeerId: component.participants?.myPeerId ?? component.call.accountContext.account.peerId,
|
||||||
isSpeaking: component.speakingParticipants.contains(participant.peer.id),
|
isSpeaking: isSpeaking,
|
||||||
theme: component.theme
|
theme: component.theme
|
||||||
)),
|
)),
|
||||||
peer: EnginePeer(participant.peer),
|
peer: participant.peer,
|
||||||
subtitle: subtitle,
|
subtitle: subtitle,
|
||||||
subtitleAccessory: .none,
|
subtitleAccessory: .none,
|
||||||
presence: nil,
|
presence: nil,
|
||||||
@ -1280,7 +1289,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let invitedPeer = component.invitedPeers[i - self.listParticipants.count]
|
let invitedPeer = component.invitedPeers[i - self.listParticipants.count]
|
||||||
participantPeerId = invitedPeer.peer.id
|
participantItemId = .peer(invitedPeer.peer.id)
|
||||||
|
|
||||||
let subtitle: PeerListItemComponent.Subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusInvited, color: .neutral)
|
let subtitle: PeerListItemComponent.Subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusInvited, color: .neutral)
|
||||||
|
|
||||||
@ -1328,20 +1337,20 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
validListItemIds.append(participantPeerId)
|
validListItemIds.append(participantItemId)
|
||||||
|
|
||||||
if i >= clippedVisibleListItemRange.minIndex && i <= clippedVisibleListItemRange.maxIndex {
|
if i >= clippedVisibleListItemRange.minIndex && i <= clippedVisibleListItemRange.maxIndex {
|
||||||
visibleParticipants.append(participantPeerId)
|
visibleParticipants.append(participantItemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemTransition = transition
|
var itemTransition = transition
|
||||||
let itemView: ListItem
|
let itemView: ListItem
|
||||||
if let current = self.listItemViews[participantPeerId] {
|
if let current = self.listItemViews[participantItemId] {
|
||||||
itemView = current
|
itemView = current
|
||||||
} else {
|
} else {
|
||||||
itemTransition = itemTransition.withAnimation(.none)
|
itemTransition = itemTransition.withAnimation(.none)
|
||||||
itemView = ListItem()
|
itemView = ListItem()
|
||||||
self.listItemViews[participantPeerId] = itemView
|
self.listItemViews[participantItemId] = itemView
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = itemView.view.update(
|
let _ = itemView.view.update(
|
||||||
@ -1375,7 +1384,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var removedListItemIds: [EnginePeer.Id] = []
|
var removedListItemIds: [GroupCallParticipantsContext.Participant.Id] = []
|
||||||
for (itemId, itemView) in self.listItemViews {
|
for (itemId, itemView) in self.listItemViews {
|
||||||
if !validListItemIds.contains(itemId) {
|
if !validListItemIds.contains(itemId) {
|
||||||
removedListItemIds.append(itemId)
|
removedListItemIds.append(itemId)
|
||||||
@ -1512,7 +1521,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
expandedThumbnailsComponentView.alpha = expandedThumbnailsAlpha
|
expandedThumbnailsComponentView.alpha = expandedThumbnailsAlpha
|
||||||
|
|
||||||
let fromReferenceFrame: CGRect
|
let fromReferenceFrame: CGRect
|
||||||
if let index = self.gridParticipants.firstIndex(where: { $0.participant.peer.id == expandedVideoState.mainParticipant.id && $0.isPresentation == expandedVideoState.mainParticipant.isPresentation }) {
|
if let index = self.gridParticipants.firstIndex(where: { $0.participant.id == expandedVideoState.mainParticipant.id && $0.isPresentation == expandedVideoState.mainParticipant.isPresentation }) {
|
||||||
fromReferenceFrame = self.gridItemViewContainer.convert(itemLayout.gridItemFrame(at: index), to: self.expandedGridItemContainer)
|
fromReferenceFrame = self.gridItemViewContainer.convert(itemLayout.gridItemFrame(at: index), to: self.expandedGridItemContainer)
|
||||||
} else {
|
} else {
|
||||||
fromReferenceFrame = previousExpandedGridItemContainerFrame
|
fromReferenceFrame = previousExpandedGridItemContainerFrame
|
||||||
@ -1571,7 +1580,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
expandedControlsComponentView.alpha = expandedControlsAlpha
|
expandedControlsComponentView.alpha = expandedControlsAlpha
|
||||||
|
|
||||||
let fromReferenceFrame: CGRect
|
let fromReferenceFrame: CGRect
|
||||||
if let index = self.gridParticipants.firstIndex(where: { $0.participant.peer.id == expandedVideoState.mainParticipant.id && $0.isPresentation == expandedVideoState.mainParticipant.isPresentation }) {
|
if let index = self.gridParticipants.firstIndex(where: { $0.participant.id == expandedVideoState.mainParticipant.id && $0.isPresentation == expandedVideoState.mainParticipant.isPresentation }) {
|
||||||
fromReferenceFrame = self.gridItemViewContainer.convert(itemLayout.gridItemFrame(at: index), to: self.expandedGridItemContainer)
|
fromReferenceFrame = self.gridItemViewContainer.convert(itemLayout.gridItemFrame(at: index), to: self.expandedGridItemContainer)
|
||||||
} else {
|
} else {
|
||||||
fromReferenceFrame = previousExpandedGridItemContainerFrame
|
fromReferenceFrame = previousExpandedGridItemContainerFrame
|
||||||
@ -1591,7 +1600,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
self.expandedThumbnailsView = nil
|
self.expandedThumbnailsView = nil
|
||||||
|
|
||||||
if transition.containedViewLayoutTransition.isAnimated, let expandedThumbnailsComponentView = expandedThumbnailsView.view {
|
if transition.containedViewLayoutTransition.isAnimated, let expandedThumbnailsComponentView = expandedThumbnailsView.view {
|
||||||
if let collapsingItemView = self.gridItemViews.values.first(where: { $0.isCollapsing }), let index = self.gridParticipants.firstIndex(where: { $0.participant.peer.id == collapsingItemView.key.id && $0.isPresentation == collapsingItemView.key.isPresentation }) {
|
if let collapsingItemView = self.gridItemViews.values.first(where: { $0.isCollapsing }), let index = self.gridParticipants.firstIndex(where: { $0.participant.id == collapsingItemView.key.id && $0.isPresentation == collapsingItemView.key.isPresentation }) {
|
||||||
let targetLocalItemFrame = itemLayout.gridItemFrame(at: index)
|
let targetLocalItemFrame = itemLayout.gridItemFrame(at: index)
|
||||||
var targetItemFrame = self.gridItemViewContainer.convert(targetLocalItemFrame, to: self)
|
var targetItemFrame = self.gridItemViewContainer.convert(targetLocalItemFrame, to: self)
|
||||||
targetItemFrame.origin.y -= expandedGridItemContainerFrame.minY
|
targetItemFrame.origin.y -= expandedGridItemContainerFrame.minY
|
||||||
@ -1612,7 +1621,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
self.expandedControlsView = nil
|
self.expandedControlsView = nil
|
||||||
|
|
||||||
if transition.containedViewLayoutTransition.isAnimated, let expandedControlsComponentView = expandedControlsView.view {
|
if transition.containedViewLayoutTransition.isAnimated, let expandedControlsComponentView = expandedControlsView.view {
|
||||||
if let collapsingItemView = self.gridItemViews.values.first(where: { $0.isCollapsing }), let index = self.gridParticipants.firstIndex(where: { $0.participant.peer.id == collapsingItemView.key.id && $0.isPresentation == collapsingItemView.key.isPresentation }) {
|
if let collapsingItemView = self.gridItemViews.values.first(where: { $0.isCollapsing }), let index = self.gridParticipants.firstIndex(where: { $0.participant.id == collapsingItemView.key.id && $0.isPresentation == collapsingItemView.key.isPresentation }) {
|
||||||
let targetLocalItemFrame = itemLayout.gridItemFrame(at: index)
|
let targetLocalItemFrame = itemLayout.gridItemFrame(at: index)
|
||||||
var targetItemFrame = self.gridItemViewContainer.convert(targetLocalItemFrame, to: self)
|
var targetItemFrame = self.gridItemViewContainer.convert(targetLocalItemFrame, to: self)
|
||||||
targetItemFrame.origin.y -= expandedGridItemContainerFrame.minY
|
targetItemFrame.origin.y -= expandedGridItemContainerFrame.minY
|
||||||
@ -1630,7 +1639,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let expandedVideoState = component.expandedVideoState, expandedVideoState.isMainParticipantPinned, let participants = component.participants, !component.speakingParticipants.isEmpty, let firstOther = component.speakingParticipants.first(where: { $0 != expandedVideoState.mainParticipant.id }), let speakingPeer = participants.participants.first(where: { $0.peer.id == firstOther })?.peer {
|
if let expandedVideoState = component.expandedVideoState, expandedVideoState.isMainParticipantPinned, let participants = component.participants, !component.speakingParticipants.isEmpty, let firstOther = component.speakingParticipants.first(where: { expandedVideoState.mainParticipant.id != .peer($0) }), let speakingPeer = participants.participants.first(where: { $0.id == .peer(firstOther) })?.peer {
|
||||||
let expandedSpeakingToast: ComponentView<Empty>
|
let expandedSpeakingToast: ComponentView<Empty>
|
||||||
var expandedSpeakingToastTransition = transition
|
var expandedSpeakingToastTransition = transition
|
||||||
if let current = self.expandedSpeakingToast {
|
if let current = self.expandedSpeakingToast {
|
||||||
@ -1644,21 +1653,21 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
transition: expandedSpeakingToastTransition,
|
transition: expandedSpeakingToastTransition,
|
||||||
component: AnyComponent(VideoChatExpandedSpeakingToastComponent(
|
component: AnyComponent(VideoChatExpandedSpeakingToastComponent(
|
||||||
context: component.call.accountContext,
|
context: component.call.accountContext,
|
||||||
peer: EnginePeer(speakingPeer),
|
peer: speakingPeer,
|
||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
action: { [weak self] peer in
|
action: { [weak self] peer in
|
||||||
guard let self, let component = self.component, let participants = component.participants else {
|
guard let self, let component = self.component, let participants = component.participants else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let participant = participants.participants.first(where: { $0.peer.id == peer.id }) else {
|
guard let participant = participants.participants.first(where: { $0.id == .peer(peer.id) }) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var key: VideoParticipantKey?
|
var key: VideoParticipantKey?
|
||||||
if participant.presentationDescription != nil {
|
if participant.presentationDescription != nil {
|
||||||
key = VideoParticipantKey(id: peer.id, isPresentation: true)
|
key = VideoParticipantKey(id: .peer(peer.id), isPresentation: true)
|
||||||
} else if participant.videoDescription != nil {
|
} else if participant.videoDescription != nil {
|
||||||
key = VideoParticipantKey(id: peer.id, isPresentation: false)
|
key = VideoParticipantKey(id: .peer(peer.id), isPresentation: false)
|
||||||
}
|
}
|
||||||
if let key {
|
if let key {
|
||||||
component.updateMainParticipant(key, nil)
|
component.updateMainParticipant(key, nil)
|
||||||
@ -1701,7 +1710,13 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component.visibleParticipantsUpdated(Set(visibleParticipants))
|
component.visibleParticipantsUpdated(Set(visibleParticipants.compactMap {
|
||||||
|
if case let .peer(id) = $0 {
|
||||||
|
return id
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setEventCycleState(scrollView: UIScrollView, eventCycleState: EventCycleState?) {
|
func setEventCycleState(scrollView: UIScrollView, eventCycleState: EventCycleState?) {
|
||||||
@ -1712,7 +1727,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func itemFrame(peerId: EnginePeer.Id, isPresentation: Bool) -> CGRect? {
|
func itemFrame(peerId: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool) -> CGRect? {
|
||||||
for (key, itemView) in self.gridItemViews {
|
for (key, itemView) in self.gridItemViews {
|
||||||
if key.id == peerId && key.isPresentation == isPresentation {
|
if key.id == peerId && key.isPresentation == isPresentation {
|
||||||
if let itemComponentView = itemView.view.view {
|
if let itemComponentView = itemView.view.view {
|
||||||
@ -1723,7 +1738,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateItemPlaceholder(peerId: EnginePeer.Id, isPresentation: Bool, placeholder: VideoSource.Output) {
|
func updateItemPlaceholder(peerId: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool, placeholder: VideoSource.Output) {
|
||||||
for (key, itemView) in self.gridItemViews {
|
for (key, itemView) in self.gridItemViews {
|
||||||
if key.id == peerId && key.isPresentation == isPresentation {
|
if key.id == peerId && key.isPresentation == isPresentation {
|
||||||
if let itemComponentView = itemView.view.view as? VideoChatParticipantVideoComponent.View {
|
if let itemComponentView = itemView.view.view as? VideoChatParticipantVideoComponent.View {
|
||||||
@ -1781,7 +1796,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
if participant.videoDescription != nil {
|
if participant.videoDescription != nil {
|
||||||
hasVideo = true
|
hasVideo = true
|
||||||
let videoParticipant = VideoParticipant(participant: participant, isPresentation: false)
|
let videoParticipant = VideoParticipant(participant: participant, isPresentation: false)
|
||||||
if participant.peer.id == participants.myPeerId {
|
if participant.id == .peer(participants.myPeerId) {
|
||||||
gridParticipants.insert(videoParticipant, at: 0)
|
gridParticipants.insert(videoParticipant, at: 0)
|
||||||
} else {
|
} else {
|
||||||
gridParticipants.append(videoParticipant)
|
gridParticipants.append(videoParticipant)
|
||||||
@ -1790,14 +1805,14 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
if participant.presentationDescription != nil {
|
if participant.presentationDescription != nil {
|
||||||
hasVideo = true
|
hasVideo = true
|
||||||
let videoParticipant = VideoParticipant(participant: participant, isPresentation: true)
|
let videoParticipant = VideoParticipant(participant: participant, isPresentation: true)
|
||||||
if participant.peer.id == participants.myPeerId {
|
if participant.id == .peer(participants.myPeerId) {
|
||||||
gridParticipants.insert(videoParticipant, at: 0)
|
gridParticipants.insert(videoParticipant, at: 0)
|
||||||
} else {
|
} else {
|
||||||
gridParticipants.append(videoParticipant)
|
gridParticipants.append(videoParticipant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !hasVideo || component.layout.videoColumn != nil {
|
if !hasVideo || component.layout.videoColumn != nil {
|
||||||
if participant.peer.id == participants.myPeerId && !isFullyMuted {
|
if participant.id == .peer(participants.myPeerId) && !isFullyMuted {
|
||||||
listParticipants.insert(participant, at: 0)
|
listParticipants.insert(participant, at: 0)
|
||||||
} else {
|
} else {
|
||||||
listParticipants.append(participant)
|
listParticipants.append(participant)
|
||||||
@ -1927,7 +1942,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
for participant in participants.participants {
|
for participant in participants.participants {
|
||||||
var maxVideoQuality: PresentationGroupCallRequestedVideo.Quality = .medium
|
var maxVideoQuality: PresentationGroupCallRequestedVideo.Quality = .medium
|
||||||
if let expandedVideoState = component.expandedVideoState {
|
if let expandedVideoState = component.expandedVideoState {
|
||||||
if expandedVideoState.mainParticipant.id == participant.peer.id, !expandedVideoState.mainParticipant.isPresentation {
|
if expandedVideoState.mainParticipant.id == participant.id, !expandedVideoState.mainParticipant.isPresentation {
|
||||||
if component.maxVideoQuality == Int.max {
|
if component.maxVideoQuality == Int.max {
|
||||||
maxVideoQuality = .full
|
maxVideoQuality = .full
|
||||||
} else if component.maxVideoQuality == 360 {
|
} else if component.maxVideoQuality == 360 {
|
||||||
@ -1942,7 +1957,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
|
|
||||||
var maxPresentationQuality: PresentationGroupCallRequestedVideo.Quality = .medium
|
var maxPresentationQuality: PresentationGroupCallRequestedVideo.Quality = .medium
|
||||||
if let expandedVideoState = component.expandedVideoState {
|
if let expandedVideoState = component.expandedVideoState {
|
||||||
if expandedVideoState.mainParticipant.id == participant.peer.id, expandedVideoState.mainParticipant.isPresentation {
|
if expandedVideoState.mainParticipant.id == participant.id, expandedVideoState.mainParticipant.isPresentation {
|
||||||
if component.maxVideoQuality == Int.max {
|
if component.maxVideoQuality == Int.max {
|
||||||
maxVideoQuality = .full
|
maxVideoQuality = .full
|
||||||
} else if component.maxVideoQuality == 360 {
|
} else if component.maxVideoQuality == 360 {
|
||||||
|
@ -343,17 +343,17 @@ final class VideoChatScreenComponent: Component {
|
|||||||
sourceCallControllerView?.removeFromSuperview()
|
sourceCallControllerView?.removeFromSuperview()
|
||||||
}
|
}
|
||||||
|
|
||||||
var expandedPeer: (id: EnginePeer.Id, isPresentation: Bool)?
|
var expandedPeer: (id: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool)?
|
||||||
if let animateOutData, animateOutData.incomingVideoLayer != nil, let members = self.members {
|
if let animateOutData, animateOutData.incomingVideoLayer != nil, let members = self.members {
|
||||||
if let participant = members.participants.first(where: { $0.peer.id == animateOutData.incomingPeerId }) {
|
if let participant = members.participants.first(where: { $0.id == .peer(animateOutData.incomingPeerId) }) {
|
||||||
if let _ = participant.videoDescription {
|
if let _ = participant.videoDescription {
|
||||||
expandedPeer = (participant.peer.id, false)
|
expandedPeer = (participant.id, false)
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: true)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: true)
|
||||||
}
|
}
|
||||||
} else if let participant = members.participants.first(where: { $0.peer.id == sourceCallController.call.context.account.peerId }) {
|
} else if let participant = members.participants.first(where: { $0.id == .peer(sourceCallController.call.context.account.peerId) }) {
|
||||||
if let _ = participant.videoDescription {
|
if let _ = participant.videoDescription {
|
||||||
expandedPeer = (participant.peer.id, false)
|
expandedPeer = (participant.id, false)
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: true)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1164,7 +1164,8 @@ final class VideoChatScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
participants.append(GroupCallParticipantsContext.Participant(
|
participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: myPeer._asPeer(),
|
id: .peer(myPeer.id),
|
||||||
|
peer: myPeer,
|
||||||
ssrc: nil,
|
ssrc: nil,
|
||||||
videoDescription: myVideoDescription,
|
videoDescription: myVideoDescription,
|
||||||
presentationDescription: nil,
|
presentationDescription: nil,
|
||||||
@ -1189,7 +1190,8 @@ final class VideoChatScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
participants.append(GroupCallParticipantsContext.Participant(
|
participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: remotePeer._asPeer(),
|
id: .peer(remotePeer.id),
|
||||||
|
peer: remotePeer,
|
||||||
ssrc: nil,
|
ssrc: nil,
|
||||||
videoDescription: remoteVideoDescription,
|
videoDescription: remoteVideoDescription,
|
||||||
presentationDescription: nil,
|
presentationDescription: nil,
|
||||||
@ -1235,7 +1237,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
self.members = component.initialData.members
|
self.members = component.initialData.members
|
||||||
self.invitedPeers = component.initialData.invitedPeers
|
self.invitedPeers = component.initialData.invitedPeers
|
||||||
if let members = self.members {
|
if let members = self.members {
|
||||||
self.invitedPeers.removeAll(where: { invitedPeer in members.participants.contains(where: { $0.peer.id == invitedPeer.peer.id }) })
|
self.invitedPeers.removeAll(where: { invitedPeer in members.participants.contains(where: { $0.id == .peer(invitedPeer.peer.id) }) })
|
||||||
}
|
}
|
||||||
self.callState = component.initialData.callState
|
self.callState = component.initialData.callState
|
||||||
}
|
}
|
||||||
@ -1276,7 +1278,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
self.members = members
|
self.members = members
|
||||||
if let members {
|
if let members {
|
||||||
self.invitedPeers.removeAll(where: { invitedPeer in members.participants.contains(where: { $0.peer.id == invitedPeer.peer.id }) })
|
self.invitedPeers.removeAll(where: { invitedPeer in members.participants.contains(where: { $0.id == .peer(invitedPeer.peer.id) }) })
|
||||||
}
|
}
|
||||||
|
|
||||||
if let members, let expandedParticipantsVideoState = self.expandedParticipantsVideoState, !expandedParticipantsVideoState.isUIHidden {
|
if let members, let expandedParticipantsVideoState = self.expandedParticipantsVideoState, !expandedParticipantsVideoState.isUIHidden {
|
||||||
@ -1299,28 +1301,28 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
if let expandedParticipantsVideoState = self.expandedParticipantsVideoState, let members {
|
if let expandedParticipantsVideoState = self.expandedParticipantsVideoState, let members {
|
||||||
if CFAbsoluteTimeGetCurrent() > self.focusedSpeakerAutoSwitchDeadline, !expandedParticipantsVideoState.isMainParticipantPinned, let participant = members.participants.first(where: { participant in
|
if CFAbsoluteTimeGetCurrent() > self.focusedSpeakerAutoSwitchDeadline, !expandedParticipantsVideoState.isMainParticipantPinned, let participant = members.participants.first(where: { participant in
|
||||||
if let callState = self.callState, participant.peer.id == callState.myPeerId {
|
if let callState = self.callState, participant.id == .peer(callState.myPeerId) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if participant.videoDescription != nil || participant.presentationDescription != nil {
|
if participant.videoDescription != nil || participant.presentationDescription != nil {
|
||||||
if members.speakingParticipants.contains(participant.peer.id) {
|
if let participantPeer = participant.peer, members.speakingParticipants.contains(participantPeer.id) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}) {
|
}) {
|
||||||
if participant.peer.id != expandedParticipantsVideoState.mainParticipant.id {
|
if participant.id != expandedParticipantsVideoState.mainParticipant.id {
|
||||||
if participant.presentationDescription != nil {
|
if participant.presentationDescription != nil {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
} else {
|
} else {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
}
|
}
|
||||||
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let _ = members.participants.first(where: { participant in
|
if let _ = members.participants.first(where: { participant in
|
||||||
if participant.peer.id == expandedParticipantsVideoState.mainParticipant.id {
|
if participant.id == expandedParticipantsVideoState.mainParticipant.id {
|
||||||
if expandedParticipantsVideoState.mainParticipant.isPresentation {
|
if expandedParticipantsVideoState.mainParticipant.isPresentation {
|
||||||
if participant.presentationDescription == nil {
|
if participant.presentationDescription == nil {
|
||||||
return false
|
return false
|
||||||
@ -1344,9 +1346,9 @@ final class VideoChatScreenComponent: Component {
|
|||||||
return false
|
return false
|
||||||
}) {
|
}) {
|
||||||
if participant.presentationDescription != nil {
|
if participant.presentationDescription != nil {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
} else {
|
} else {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
}
|
}
|
||||||
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
||||||
} else {
|
} else {
|
||||||
@ -1365,8 +1367,8 @@ final class VideoChatScreenComponent: Component {
|
|||||||
var speakingParticipantPeers: [EnginePeer] = []
|
var speakingParticipantPeers: [EnginePeer] = []
|
||||||
if let members, !members.speakingParticipants.isEmpty {
|
if let members, !members.speakingParticipants.isEmpty {
|
||||||
for participant in members.participants {
|
for participant in members.participants {
|
||||||
if members.speakingParticipants.contains(participant.peer.id) {
|
if let participantPeer = participant.peer, members.speakingParticipants.contains(participantPeer.id) {
|
||||||
speakingParticipantPeers.append(EnginePeer(participant.peer))
|
speakingParticipantPeers.append(participantPeer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1401,7 +1403,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
var invitedPeers = invitedPeers
|
var invitedPeers = invitedPeers
|
||||||
if let members {
|
if let members {
|
||||||
invitedPeers.removeAll(where: { invitedPeer in members.participants.contains(where: { $0.peer.id == invitedPeer.peer.id }) })
|
invitedPeers.removeAll(where: { invitedPeer in members.participants.contains(where: { $0.id == .peer(invitedPeer.peer.id) }) })
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.invitedPeers != invitedPeers {
|
if self.invitedPeers != invitedPeers {
|
||||||
@ -1612,28 +1614,28 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
if let expandedParticipantsVideoState = self.expandedParticipantsVideoState {
|
if let expandedParticipantsVideoState = self.expandedParticipantsVideoState {
|
||||||
if CFAbsoluteTimeGetCurrent() > self.focusedSpeakerAutoSwitchDeadline, !expandedParticipantsVideoState.isMainParticipantPinned, let participant = members.participants.first(where: { participant in
|
if CFAbsoluteTimeGetCurrent() > self.focusedSpeakerAutoSwitchDeadline, !expandedParticipantsVideoState.isMainParticipantPinned, let participant = members.participants.first(where: { participant in
|
||||||
if let callState = self.callState, participant.peer.id == callState.myPeerId {
|
if let callState = self.callState, participant.id == .peer(callState.myPeerId) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if participant.videoDescription != nil || participant.presentationDescription != nil {
|
if participant.videoDescription != nil || participant.presentationDescription != nil {
|
||||||
if members.speakingParticipants.contains(participant.peer.id) {
|
if let participantPeer = participant.peer, members.speakingParticipants.contains(participantPeer.id) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}) {
|
}) {
|
||||||
if participant.peer.id != expandedParticipantsVideoState.mainParticipant.id {
|
if participant.id != expandedParticipantsVideoState.mainParticipant.id {
|
||||||
if participant.presentationDescription != nil {
|
if participant.presentationDescription != nil {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
} else {
|
} else {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
}
|
}
|
||||||
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let _ = members.participants.first(where: { participant in
|
if let _ = members.participants.first(where: { participant in
|
||||||
if participant.peer.id == expandedParticipantsVideoState.mainParticipant.id {
|
if participant.id == expandedParticipantsVideoState.mainParticipant.id {
|
||||||
if expandedParticipantsVideoState.mainParticipant.isPresentation {
|
if expandedParticipantsVideoState.mainParticipant.isPresentation {
|
||||||
if participant.presentationDescription == nil {
|
if participant.presentationDescription == nil {
|
||||||
return false
|
return false
|
||||||
@ -1657,9 +1659,9 @@ final class VideoChatScreenComponent: Component {
|
|||||||
return false
|
return false
|
||||||
}) {
|
}) {
|
||||||
if participant.presentationDescription != nil {
|
if participant.presentationDescription != nil {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: true), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
} else {
|
} else {
|
||||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: expandedParticipantsVideoState.isUIHidden)
|
||||||
}
|
}
|
||||||
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
self.focusedSpeakerAutoSwitchDeadline = CFAbsoluteTimeGetCurrent() + 1.0
|
||||||
} else {
|
} else {
|
||||||
@ -1678,8 +1680,8 @@ final class VideoChatScreenComponent: Component {
|
|||||||
var speakingParticipantPeers: [EnginePeer] = []
|
var speakingParticipantPeers: [EnginePeer] = []
|
||||||
if !members.speakingParticipants.isEmpty {
|
if !members.speakingParticipants.isEmpty {
|
||||||
for participant in members.participants {
|
for participant in members.participants {
|
||||||
if members.speakingParticipants.contains(participant.peer.id) {
|
if let participantPeer = participant.peer, members.speakingParticipants.contains(participantPeer.id) {
|
||||||
speakingParticipantPeers.append(EnginePeer(participant.peer))
|
speakingParticipantPeers.append(participantPeer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ extension VideoChatScreenComponent.View {
|
|||||||
disablePeerIds.append(groupCall.accountContext.account.peerId)
|
disablePeerIds.append(groupCall.accountContext.account.peerId)
|
||||||
if let members = self.members {
|
if let members = self.members {
|
||||||
for participant in members.participants {
|
for participant in members.participants {
|
||||||
if !disablePeerIds.contains(participant.peer.id) {
|
if let participantPeer = participant.peer, !disablePeerIds.contains(participantPeer.id) {
|
||||||
disablePeerIds.append(participant.peer.id)
|
disablePeerIds.append(participantPeer.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
|
|
||||||
var filters: [ChannelMembersSearchFilter] = []
|
var filters: [ChannelMembersSearchFilter] = []
|
||||||
if let members = self.members {
|
if let members = self.members {
|
||||||
filters.append(.disable(Array(members.participants.map { $0.peer.id })))
|
filters.append(.disable(Array(members.participants.compactMap { $0.peer?.id })))
|
||||||
}
|
}
|
||||||
if case let .channel(groupPeer) = groupPeer {
|
if case let .channel(groupPeer) = groupPeer {
|
||||||
if !groupPeer.hasPermission(.inviteMembers) && inviteLinks?.listenerLink == nil {
|
if !groupPeer.hasPermission(.inviteMembers) && inviteLinks?.listenerLink == nil {
|
||||||
|
@ -18,7 +18,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
guard let environment = self.environment else {
|
guard let environment = self.environment else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let members = self.members, let participant = members.participants.first(where: { $0.peer.id == id }) else {
|
guard let members = self.members, let participant = members.participants.first(where: { $0.id == .peer(id) }) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let currentCall = self.currentCall else {
|
guard let currentCall = self.currentCall else {
|
||||||
@ -35,10 +35,13 @@ extension VideoChatScreenComponent.View {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
var items: [ContextMenuItem] = []
|
guard let peer = participant.peer else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
var items: [ContextMenuItem] = []
|
||||||
var hasVolumeSlider = false
|
var hasVolumeSlider = false
|
||||||
let peer = participant.peer
|
|
||||||
if let muteState = muteState, !muteState.canUnmute || muteState.mutedByYou {
|
if let muteState = muteState, !muteState.canUnmute || muteState.mutedByYou {
|
||||||
} else {
|
} else {
|
||||||
if callState.canManageCall || callState.myPeerId != id {
|
if callState.canManageCall || callState.myPeerId != id {
|
||||||
@ -65,7 +68,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if callState.myPeerId == id && !hasVolumeSlider && ((participant.about?.isEmpty ?? true) || participant.peer.smallProfileImage == nil) {
|
if callState.myPeerId == id && !hasVolumeSlider && ((participant.about?.isEmpty ?? true) || participant.peer?.smallProfileImage == nil) {
|
||||||
items.append(.custom(VoiceChatInfoContextItem(text: environment.strings.VoiceChat_ImproveYourProfileText, icon: { theme in
|
items.append(.custom(VoiceChatInfoContextItem(text: environment.strings.VoiceChat_ImproveYourProfileText, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tip"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tip"), color: theme.actionSheet.primaryTextColor)
|
||||||
}), true))
|
}), true))
|
||||||
@ -134,7 +137,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if let peer = peer as? TelegramUser {
|
if case let .user(peer) = peer {
|
||||||
items.append(.action(ContextMenuActionItem(text: environment.strings.VoiceChat_ChangeName, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: environment.strings.VoiceChat_ChangeName, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/ChangeName"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/ChangeName"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { [weak self] _, f in
|
}, action: { [weak self] _, f in
|
||||||
@ -184,7 +187,9 @@ extension VideoChatScreenComponent.View {
|
|||||||
let _ = groupCall.updateMuteState(peerId: peer.id, isMuted: false)
|
let _ = groupCall.updateMuteState(peerId: peer.id, isMuted: false)
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
self.presentUndoOverlay(content: .voiceChatCanSpeak(text: environment.strings.VoiceChat_UserCanNowSpeak(EnginePeer(participant.peer).displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string), action: { _ in return true })
|
if let participantPeer = participant.peer {
|
||||||
|
self.presentUndoOverlay(content: .voiceChatCanSpeak(text: environment.strings.VoiceChat_UserCanNowSpeak(participantPeer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string), action: { _ in return true })
|
||||||
|
}
|
||||||
})))
|
})))
|
||||||
} else {
|
} else {
|
||||||
items.append(.action(ContextMenuActionItem(text: environment.strings.VoiceChat_MutePeer, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: environment.strings.VoiceChat_MutePeer, icon: { theme in
|
||||||
@ -207,7 +212,6 @@ extension VideoChatScreenComponent.View {
|
|||||||
guard let self, case let .group(groupCall) = self.currentCall else {
|
guard let self, case let .group(groupCall) = self.currentCall else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = groupCall.updateMuteState(peerId: peer.id, isMuted: false)
|
let _ = groupCall.updateMuteState(peerId: peer.id, isMuted: false)
|
||||||
f(.default)
|
f(.default)
|
||||||
})))
|
})))
|
||||||
@ -228,7 +232,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
let openTitle: String
|
let openTitle: String
|
||||||
let openIcon: UIImage?
|
let openIcon: UIImage?
|
||||||
if [Namespaces.Peer.CloudChannel, Namespaces.Peer.CloudGroup].contains(peer.id.namespace) {
|
if [Namespaces.Peer.CloudChannel, Namespaces.Peer.CloudGroup].contains(peer.id.namespace) {
|
||||||
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
if case let .channel(peer) = peer, case .broadcast = peer.info {
|
||||||
openTitle = environment.strings.VoiceChat_OpenChannel
|
openTitle = environment.strings.VoiceChat_OpenChannel
|
||||||
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels")
|
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels")
|
||||||
} else {
|
} else {
|
||||||
@ -256,7 +260,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
guard let navigationController else {
|
guard let navigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), keepStack: .always, purposefulAction: {}, peekData: nil))
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -293,7 +297,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
|
|
||||||
let nameDisplayOrder = presentationData.nameDisplayOrder
|
let nameDisplayOrder = presentationData.nameDisplayOrder
|
||||||
if let chatPeer {
|
if let chatPeer {
|
||||||
items.append(DeleteChatPeerActionSheetItem(context: groupCall.accountContext, peer: EnginePeer(peer), chatPeer: chatPeer, action: .removeFromGroup, strings: environment.strings, nameDisplayOrder: nameDisplayOrder))
|
items.append(DeleteChatPeerActionSheetItem(context: groupCall.accountContext, peer: peer, chatPeer: chatPeer, action: .removeFromGroup, strings: environment.strings, nameDisplayOrder: nameDisplayOrder))
|
||||||
}
|
}
|
||||||
|
|
||||||
items.append(ActionSheetButtonItem(title: environment.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak self, weak actionSheet] in
|
items.append(ActionSheetButtonItem(title: environment.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||||
@ -312,7 +316,7 @@ extension VideoChatScreenComponent.View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.presentUndoOverlay(content: .banned(text: environment.strings.VoiceChat_RemovedPeerText(EnginePeer(peer).displayTitle(strings: environment.strings, displayOrder: nameDisplayOrder)).string), action: { _ in return false })
|
self.presentUndoOverlay(content: .banned(text: environment.strings.VoiceChat_RemovedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: nameDisplayOrder)).string), action: { _ in return false })
|
||||||
}))
|
}))
|
||||||
|
|
||||||
actionSheet.setItemGroups([
|
actionSheet.setItemGroups([
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import SwiftSignalKit
|
|||||||
public protocol ConferenceCallE2EContextState: AnyObject {
|
public protocol ConferenceCallE2EContextState: AnyObject {
|
||||||
func getEmojiState() -> Data?
|
func getEmojiState() -> Data?
|
||||||
func getParticipantIds() -> [Int64]
|
func getParticipantIds() -> [Int64]
|
||||||
|
func getParticipants() -> [ConferenceCallE2EContext.BlockchainParticipant]
|
||||||
|
|
||||||
func applyBlock(block: Data)
|
func applyBlock(block: Data)
|
||||||
func applyBroadcastBlock(block: Data)
|
func applyBroadcastBlock(block: Data)
|
||||||
@ -25,6 +26,16 @@ public final class ConferenceCallE2EContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct BlockchainParticipant: Equatable {
|
||||||
|
public let userId: Int64
|
||||||
|
public let internalId: String
|
||||||
|
|
||||||
|
public init(userId: Int64, internalId: String) {
|
||||||
|
self.userId = userId
|
||||||
|
self.internalId = internalId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class Impl {
|
private final class Impl {
|
||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
|
|
||||||
@ -38,6 +49,7 @@ public final class ConferenceCallE2EContext {
|
|||||||
private let keyPair: TelegramKeyPair
|
private let keyPair: TelegramKeyPair
|
||||||
|
|
||||||
let e2eEncryptionKeyHashValue = ValuePromise<Data?>(nil)
|
let e2eEncryptionKeyHashValue = ValuePromise<Data?>(nil)
|
||||||
|
let blockchainParticipantsValue = ValuePromise<[BlockchainParticipant]>([])
|
||||||
|
|
||||||
private var e2ePoll0Offset: Int?
|
private var e2ePoll0Offset: Int?
|
||||||
private var e2ePoll0Timer: Foundation.Timer?
|
private var e2ePoll0Timer: Foundation.Timer?
|
||||||
@ -154,7 +166,7 @@ public final class ConferenceCallE2EContext {
|
|||||||
let keyPair = self.keyPair
|
let keyPair = self.keyPair
|
||||||
let userId = self.userId
|
let userId = self.userId
|
||||||
let initializeState = self.initializeState
|
let initializeState = self.initializeState
|
||||||
let (outBlocks, outEmoji) = self.state.with({ callState -> ([Data], Data) in
|
let (outBlocks, outEmoji, outBlockchainParticipants) = self.state.with({ callState -> ([Data], Data, [BlockchainParticipant]) in
|
||||||
if let state = callState.state {
|
if let state = callState.state {
|
||||||
for block in blocks {
|
for block in blocks {
|
||||||
if subChainId == 0 {
|
if subChainId == 0 {
|
||||||
@ -163,30 +175,31 @@ public final class ConferenceCallE2EContext {
|
|||||||
state.applyBroadcastBlock(block: block)
|
state.applyBroadcastBlock(block: block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data())
|
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data(), state.getParticipants())
|
||||||
} else {
|
} else {
|
||||||
if subChainId == 0 {
|
if subChainId == 0 {
|
||||||
guard let block = blocks.last else {
|
guard let block = blocks.last else {
|
||||||
return ([], Data())
|
return ([], Data(), [])
|
||||||
}
|
}
|
||||||
guard let state = initializeState(keyPair, userId, block) else {
|
guard let state = initializeState(keyPair, userId, block) else {
|
||||||
return ([], Data())
|
return ([], Data(), [])
|
||||||
}
|
}
|
||||||
callState.state = state
|
callState.state = state
|
||||||
for block in callState.pendingIncomingBroadcastBlocks {
|
for block in callState.pendingIncomingBroadcastBlocks {
|
||||||
state.applyBroadcastBlock(block: block)
|
state.applyBroadcastBlock(block: block)
|
||||||
}
|
}
|
||||||
callState.pendingIncomingBroadcastBlocks.removeAll()
|
callState.pendingIncomingBroadcastBlocks.removeAll()
|
||||||
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data())
|
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data(), state.getParticipants())
|
||||||
} else if subChainId == 1 {
|
} else if subChainId == 1 {
|
||||||
callState.pendingIncomingBroadcastBlocks.append(contentsOf: blocks)
|
callState.pendingIncomingBroadcastBlocks.append(contentsOf: blocks)
|
||||||
return ([], Data())
|
return ([], Data(), [])
|
||||||
} else {
|
} else {
|
||||||
return ([], Data())
|
return ([], Data(), [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
self.e2eEncryptionKeyHashValue.set(outEmoji.isEmpty ? nil : outEmoji)
|
self.e2eEncryptionKeyHashValue.set(outEmoji.isEmpty ? nil : outEmoji)
|
||||||
|
self.blockchainParticipantsValue.set(outBlockchainParticipants)
|
||||||
|
|
||||||
for outBlock in outBlocks {
|
for outBlock in outBlocks {
|
||||||
let _ = self.engine.calls.sendConferenceCallBroadcast(callId: self.callId, accessHash: self.accessHash, block: outBlock).startStandalone()
|
let _ = self.engine.calls.sendConferenceCallBroadcast(callId: self.callId, accessHash: self.accessHash, block: outBlock).startStandalone()
|
||||||
@ -278,6 +291,7 @@ public final class ConferenceCallE2EContext {
|
|||||||
let state = self.state
|
let state = self.state
|
||||||
let callId = self.callId
|
let callId = self.callId
|
||||||
let accessHash = self.accessHash
|
let accessHash = self.accessHash
|
||||||
|
let accountPeerId = engine.account.peerId
|
||||||
|
|
||||||
if !self.pendingKickPeers.isEmpty {
|
if !self.pendingKickPeers.isEmpty {
|
||||||
let pendingKickPeers = self.pendingKickPeers
|
let pendingKickPeers = self.pendingKickPeers
|
||||||
@ -363,9 +377,16 @@ public final class ConferenceCallE2EContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Peer ids that are in the blockchain but not in the server list
|
// Peer ids that are in the blockchain but not in the server list
|
||||||
let removedPeerIds = blockchainPeerIds.filter { blockchainPeerId in
|
var removedPeerIds = blockchainPeerIds.filter { blockchainPeerId in
|
||||||
return !result.participants.contains(where: { $0.peer.id.id._internalGetInt64Value() == blockchainPeerId })
|
return !result.participants.contains(where: { participant in
|
||||||
|
if case let .peer(id) = participant.id, id.namespace == Namespaces.Peer.CloudChannel, id.id._internalGetInt64Value() == blockchainPeerId {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
removedPeerIds.removeAll(where: { $0 == accountPeerId.id._internalGetInt64Value() })
|
||||||
|
|
||||||
if removedPeerIds.isEmpty {
|
if removedPeerIds.isEmpty {
|
||||||
return .single(false)
|
return .single(false)
|
||||||
@ -423,6 +444,12 @@ public final class ConferenceCallE2EContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var blockchainParticipants: Signal<[BlockchainParticipant], NoError> {
|
||||||
|
return self.impl.signalWith { impl, subscriber in
|
||||||
|
return impl.blockchainParticipantsValue.get().start(next: subscriber.putNext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public init(engine: TelegramEngine, callId: Int64, accessHash: Int64, userId: Int64, reference: InternalGroupCallReference, keyPair: TelegramKeyPair, initializeState: @escaping (TelegramKeyPair, Int64, Data) -> ConferenceCallE2EContextState?) {
|
public init(engine: TelegramEngine, callId: Int64, accessHash: Int64, userId: Int64, reference: InternalGroupCallReference, keyPair: TelegramKeyPair, initializeState: @escaping (TelegramKeyPair, Int64, Data) -> ConferenceCallE2EContextState?) {
|
||||||
let queue = Queue.mainQueue()
|
let queue = Queue.mainQueue()
|
||||||
let state = self.state
|
let state = self.state
|
||||||
|
@ -280,7 +280,7 @@ func _internal_getCurrentGroupCallInfo(account: Account, reference: InternalGrou
|
|||||||
|
|
||||||
let parsedParticipants = participants.compactMap { GroupCallParticipantsContext.Participant($0, transaction: transaction) }
|
let parsedParticipants = participants.compactMap { GroupCallParticipantsContext.Participant($0, transaction: transaction) }
|
||||||
return (
|
return (
|
||||||
parsedParticipants.map(\.peer.id),
|
parsedParticipants.compactMap(\.peer?.id),
|
||||||
nil
|
nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -847,9 +847,10 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId?, joinAs: PeerId?,
|
|||||||
presentationDescription = nil
|
presentationDescription = nil
|
||||||
}
|
}
|
||||||
let joinedVideo = (flags & (1 << 15)) != 0
|
let joinedVideo = (flags & (1 << 15)) != 0
|
||||||
if !state.participants.contains(where: { $0.peer.id == peer.id }) {
|
if !state.participants.contains(where: { $0.id == .peer(peer.id) }) {
|
||||||
state.participants.append(GroupCallParticipantsContext.Participant(
|
state.participants.append(GroupCallParticipantsContext.Participant(
|
||||||
peer: peer,
|
id: .peer(peer.id),
|
||||||
|
peer: EnginePeer(peer),
|
||||||
ssrc: ssrc,
|
ssrc: ssrc,
|
||||||
videoDescription: videoDescription,
|
videoDescription: videoDescription,
|
||||||
presentationDescription: presentationDescription,
|
presentationDescription: presentationDescription,
|
||||||
@ -1175,7 +1176,41 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var peer: Peer
|
public enum Id: Hashable, Comparable, CustomStringConvertible {
|
||||||
|
case peer(EnginePeer.Id)
|
||||||
|
case blockchain(String)
|
||||||
|
|
||||||
|
public var description: String {
|
||||||
|
switch self {
|
||||||
|
case let .peer(id):
|
||||||
|
return "\(id)"
|
||||||
|
case let .blockchain(internalId):
|
||||||
|
return internalId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func <(lhs: Id, rhs: Id) -> Bool {
|
||||||
|
switch lhs {
|
||||||
|
case let .peer(lhsId):
|
||||||
|
switch rhs {
|
||||||
|
case let .peer(rhsId):
|
||||||
|
return lhsId < rhsId
|
||||||
|
case .blockchain:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case let .blockchain(lhsData):
|
||||||
|
switch rhs {
|
||||||
|
case .peer:
|
||||||
|
return false
|
||||||
|
case let .blockchain(rhsData):
|
||||||
|
return lhsData < rhsData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var id: Id
|
||||||
|
public var peer: EnginePeer?
|
||||||
public var ssrc: UInt32?
|
public var ssrc: UInt32?
|
||||||
public var videoDescription: VideoDescription?
|
public var videoDescription: VideoDescription?
|
||||||
public var presentationDescription: VideoDescription?
|
public var presentationDescription: VideoDescription?
|
||||||
@ -1190,7 +1225,8 @@ public final class GroupCallParticipantsContext {
|
|||||||
public var joinedVideo: Bool
|
public var joinedVideo: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
peer: Peer,
|
id: Id,
|
||||||
|
peer: EnginePeer?,
|
||||||
ssrc: UInt32?,
|
ssrc: UInt32?,
|
||||||
videoDescription: VideoDescription?,
|
videoDescription: VideoDescription?,
|
||||||
presentationDescription: VideoDescription?,
|
presentationDescription: VideoDescription?,
|
||||||
@ -1204,6 +1240,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
about: String?,
|
about: String?,
|
||||||
joinedVideo: Bool
|
joinedVideo: Bool
|
||||||
) {
|
) {
|
||||||
|
self.id = id
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.ssrc = ssrc
|
self.ssrc = ssrc
|
||||||
self.videoDescription = videoDescription
|
self.videoDescription = videoDescription
|
||||||
@ -1220,7 +1257,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return "Participant(peer: \(peer.id): \(peer.debugDisplayTitle), ssrc: \(String(describing: self.ssrc))"
|
return "Participant(peer: \(self.id): \(peer?.debugDisplayTitle ?? "User \(self.id)"), ssrc: \(String(describing: self.ssrc))"
|
||||||
}
|
}
|
||||||
|
|
||||||
public mutating func mergeActivity(from other: Participant, mergeActivityTimestamp: Bool) {
|
public mutating func mergeActivity(from other: Participant, mergeActivityTimestamp: Bool) {
|
||||||
@ -1231,7 +1268,10 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
|
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
|
||||||
if !lhs.peer.isEqual(rhs.peer) {
|
if lhs.id != rhs.id {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.peer != rhs.peer {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.ssrc != rhs.ssrc {
|
if lhs.ssrc != rhs.ssrc {
|
||||||
@ -1318,7 +1358,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lhs.peer.id < rhs.peer.id
|
return lhs.id < rhs.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1352,13 +1392,15 @@ public final class GroupCallParticipantsContext {
|
|||||||
public mutating func mergeActivity(from other: State, myPeerId: PeerId?, previousMyPeerId: PeerId?, mergeActivityTimestamps: Bool) {
|
public mutating func mergeActivity(from other: State, myPeerId: PeerId?, previousMyPeerId: PeerId?, mergeActivityTimestamps: Bool) {
|
||||||
var indexMap: [PeerId: Int] = [:]
|
var indexMap: [PeerId: Int] = [:]
|
||||||
for i in 0 ..< other.participants.count {
|
for i in 0 ..< other.participants.count {
|
||||||
indexMap[other.participants[i].peer.id] = i
|
if let otherParticipantPeer = other.participants[i].peer {
|
||||||
|
indexMap[otherParticipantPeer.id] = i
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0 ..< self.participants.count {
|
for i in 0 ..< self.participants.count {
|
||||||
if let index = indexMap[self.participants[i].peer.id] {
|
if let selfParticipantPeer = self.participants[i].peer, let index = indexMap[selfParticipantPeer.id] {
|
||||||
self.participants[i].mergeActivity(from: other.participants[index], mergeActivityTimestamp: mergeActivityTimestamps)
|
self.participants[i].mergeActivity(from: other.participants[index], mergeActivityTimestamp: mergeActivityTimestamps)
|
||||||
if self.participants[i].peer.id == myPeerId || self.participants[i].peer.id == previousMyPeerId {
|
if selfParticipantPeer.id == myPeerId || selfParticipantPeer.id == previousMyPeerId {
|
||||||
self.participants[i].joinTimestamp = other.participants[index].joinTimestamp
|
self.participants[i].joinTimestamp = other.participants[index].joinTimestamp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1437,9 +1479,28 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class ResolvedBlockchainParticipant: Equatable {
|
||||||
|
let participant: ConferenceCallE2EContext.BlockchainParticipant
|
||||||
|
let peer: EnginePeer?
|
||||||
|
|
||||||
|
init(participant: ConferenceCallE2EContext.BlockchainParticipant, peer: EnginePeer?) {
|
||||||
|
self.participant = participant
|
||||||
|
self.peer = peer
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: ResolvedBlockchainParticipant, rhs: ResolvedBlockchainParticipant) -> Bool {
|
||||||
|
return lhs.participant == rhs.participant && lhs.peer == rhs.peer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct BlockchainState: Equatable {
|
||||||
|
var blockchainParticipants: [ResolvedBlockchainParticipant]
|
||||||
|
}
|
||||||
|
|
||||||
private struct InternalState: Equatable {
|
private struct InternalState: Equatable {
|
||||||
var state: State
|
var state: State
|
||||||
var overlayState: OverlayState
|
var overlayState: OverlayState
|
||||||
|
var blockchainState: BlockchainState
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Update {
|
public enum Update {
|
||||||
@ -1547,7 +1608,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
var sortAgain = false
|
var sortAgain = false
|
||||||
var canSeeHands = state.state.isCreator || state.state.adminIds.contains(accountPeerId)
|
var canSeeHands = state.state.isCreator || state.state.adminIds.contains(accountPeerId)
|
||||||
for participant in publicState.participants {
|
for participant in publicState.participants {
|
||||||
if participant.peer.id == myPeerId {
|
if participant.id == .peer(myPeerId) {
|
||||||
if let muteState = participant.muteState {
|
if let muteState = participant.muteState {
|
||||||
if muteState.canUnmute {
|
if muteState.canUnmute {
|
||||||
canSeeHands = true
|
canSeeHands = true
|
||||||
@ -1559,7 +1620,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i in 0 ..< publicState.participants.count {
|
for i in 0 ..< publicState.participants.count {
|
||||||
if let pendingMuteState = state.overlayState.pendingMuteStateChanges[publicState.participants[i].peer.id] {
|
if let participantPeer = publicState.participants[i].peer, let pendingMuteState = state.overlayState.pendingMuteStateChanges[participantPeer.id] {
|
||||||
publicState.participants[i].muteState = pendingMuteState.state
|
publicState.participants[i].muteState = pendingMuteState.state
|
||||||
publicState.participants[i].volume = pendingMuteState.volume
|
publicState.participants[i].volume = pendingMuteState.volume
|
||||||
}
|
}
|
||||||
@ -1578,6 +1639,27 @@ public final class GroupCallParticipantsContext {
|
|||||||
if sortAgain {
|
if sortAgain {
|
||||||
publicState.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: publicState.sortAscending) })
|
publicState.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: publicState.sortAscending) })
|
||||||
}
|
}
|
||||||
|
for blockchainParticipant in state.blockchainState.blockchainParticipants {
|
||||||
|
let blockchainParticipantPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(blockchainParticipant.participant.userId))
|
||||||
|
if !publicState.participants.contains(where: { $0.id == .peer(blockchainParticipantPeerId) }) {
|
||||||
|
publicState.participants.append(Participant(
|
||||||
|
id: .peer(blockchainParticipantPeerId),
|
||||||
|
peer: blockchainParticipant.peer,
|
||||||
|
ssrc: nil,
|
||||||
|
videoDescription: nil,
|
||||||
|
presentationDescription: nil,
|
||||||
|
joinTimestamp: 0,
|
||||||
|
raiseHandRating: nil,
|
||||||
|
hasRaiseHand: false,
|
||||||
|
activityTimestamp: nil,
|
||||||
|
activityRank: nil,
|
||||||
|
muteState: nil,
|
||||||
|
volume: nil,
|
||||||
|
about: nil,
|
||||||
|
joinedVideo: false
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
return publicState
|
return publicState
|
||||||
}
|
}
|
||||||
|> beforeNext { [weak self] next in
|
|> beforeNext { [weak self] next in
|
||||||
@ -1631,13 +1713,17 @@ public final class GroupCallParticipantsContext {
|
|||||||
|
|
||||||
public private(set) var serviceState: ServiceState
|
public private(set) var serviceState: ServiceState
|
||||||
|
|
||||||
init(account: Account, peerId: PeerId?, myPeerId: PeerId, id: Int64, reference: InternalGroupCallReference, state: State, previousServiceState: ServiceState?) {
|
private var e2eStateUpdateDisposable: Disposable?
|
||||||
|
private var pendingBlockchainState: [ResolvedBlockchainParticipant]?
|
||||||
|
private var pendingApplyBlockchainStateTimer: Foundation.Timer?
|
||||||
|
|
||||||
|
init(account: Account, peerId: PeerId?, myPeerId: PeerId, id: Int64, reference: InternalGroupCallReference, state: State, previousServiceState: ServiceState?, e2eContext: ConferenceCallE2EContext?) {
|
||||||
self.account = account
|
self.account = account
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.myPeerId = myPeerId
|
self.myPeerId = myPeerId
|
||||||
self.id = id
|
self.id = id
|
||||||
self.reference = reference
|
self.reference = reference
|
||||||
self.stateValue = InternalState(state: state, overlayState: OverlayState())
|
self.stateValue = InternalState(state: state, overlayState: OverlayState(), blockchainState: BlockchainState(blockchainParticipants: []))
|
||||||
self.statePromise = ValuePromise<InternalState>(self.stateValue)
|
self.statePromise = ValuePromise<InternalState>(self.stateValue)
|
||||||
self.serviceState = previousServiceState ?? ServiceState()
|
self.serviceState = previousServiceState ?? ServiceState()
|
||||||
|
|
||||||
@ -1674,7 +1760,9 @@ public final class GroupCallParticipantsContext {
|
|||||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||||
var indexMap: [PeerId: Int] = [:]
|
var indexMap: [PeerId: Int] = [:]
|
||||||
for i in 0 ..< updatedParticipants.count {
|
for i in 0 ..< updatedParticipants.count {
|
||||||
indexMap[updatedParticipants[i].peer.id] = i
|
if let participantPeer = updatedParticipants[i].peer {
|
||||||
|
indexMap[participantPeer.id] = i
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var updated = false
|
var updated = false
|
||||||
|
|
||||||
@ -1717,7 +1805,8 @@ public final class GroupCallParticipantsContext {
|
|||||||
isStream: strongSelf.stateValue.state.isStream,
|
isStream: strongSelf.stateValue.state.isStream,
|
||||||
version: strongSelf.stateValue.state.version
|
version: strongSelf.stateValue.state.version
|
||||||
),
|
),
|
||||||
overlayState: strongSelf.stateValue.overlayState
|
overlayState: strongSelf.stateValue.overlayState,
|
||||||
|
blockchainState: strongSelf.stateValue.blockchainState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1753,6 +1842,53 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
}, queue: .mainQueue())
|
}, queue: .mainQueue())
|
||||||
self.activityRankResetTimer?.start()
|
self.activityRankResetTimer?.start()
|
||||||
|
|
||||||
|
if let e2eContext {
|
||||||
|
let postbox = self.account.postbox
|
||||||
|
self.e2eStateUpdateDisposable = (e2eContext.blockchainParticipants
|
||||||
|
|> mapToSignal { value -> Signal<[ResolvedBlockchainParticipant], NoError> in
|
||||||
|
return postbox.transaction { transaction -> [ResolvedBlockchainParticipant] in
|
||||||
|
var result: [ResolvedBlockchainParticipant] = []
|
||||||
|
for participant in value {
|
||||||
|
let blockchainParticipantPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(participant.userId))
|
||||||
|
if let peer = transaction.getPeer(blockchainParticipantPeerId) {
|
||||||
|
result.append(ResolvedBlockchainParticipant(participant: participant, peer: EnginePeer(peer)))
|
||||||
|
} else {
|
||||||
|
result.append(ResolvedBlockchainParticipant(participant: participant, peer: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> deliverOnMainQueue).startStrict(next: { [weak self] blockchainParticipants in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pendingBlockchainState = blockchainParticipants
|
||||||
|
|
||||||
|
self.pendingApplyBlockchainStateTimer?.invalidate()
|
||||||
|
self.pendingApplyBlockchainStateTimer = nil
|
||||||
|
|
||||||
|
var hasUnknownParticipants: Bool = false
|
||||||
|
for blockchainParticipant in blockchainParticipants {
|
||||||
|
if !self.stateValue.state.participants.contains(where: { $0.id == .peer(EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(blockchainParticipant.participant.userId))) }) {
|
||||||
|
hasUnknownParticipants = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hasUnknownParticipants {
|
||||||
|
self.pendingApplyBlockchainStateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.applyPendingBlockchainState()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
self.applyPendingBlockchainState()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -1764,6 +1900,19 @@ public final class GroupCallParticipantsContext {
|
|||||||
self.activityRankResetTimer?.invalidate()
|
self.activityRankResetTimer?.invalidate()
|
||||||
self.resetInviteLinksDisposable.dispose()
|
self.resetInviteLinksDisposable.dispose()
|
||||||
self.subscribeDisposable.dispose()
|
self.subscribeDisposable.dispose()
|
||||||
|
self.e2eStateUpdateDisposable?.dispose()
|
||||||
|
self.pendingApplyBlockchainStateTimer?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func applyPendingBlockchainState() {
|
||||||
|
self.pendingApplyBlockchainStateTimer?.invalidate()
|
||||||
|
self.pendingApplyBlockchainStateTimer = nil
|
||||||
|
|
||||||
|
if let pendingBlockchainState = self.pendingBlockchainState {
|
||||||
|
self.pendingBlockchainState = nil
|
||||||
|
|
||||||
|
self.stateValue.blockchainState = BlockchainState(blockchainParticipants: pendingBlockchainState)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addUpdates(updates: [Update]) {
|
public func addUpdates(updates: [Update]) {
|
||||||
@ -1795,7 +1944,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
public func removeLocalPeerId() {
|
public func removeLocalPeerId() {
|
||||||
var state = self.stateValue.state
|
var state = self.stateValue.state
|
||||||
|
|
||||||
state.participants.removeAll(where: { $0.peer.id == self.myPeerId })
|
state.participants.removeAll(where: { $0.id == .peer(self.myPeerId) })
|
||||||
|
|
||||||
self.stateValue.state = state
|
self.stateValue.state = state
|
||||||
}
|
}
|
||||||
@ -1822,7 +1971,9 @@ public final class GroupCallParticipantsContext {
|
|||||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||||
var indexMap: [PeerId: Int] = [:]
|
var indexMap: [PeerId: Int] = [:]
|
||||||
for i in 0 ..< updatedParticipants.count {
|
for i in 0 ..< updatedParticipants.count {
|
||||||
indexMap[updatedParticipants[i].peer.id] = i
|
if let participantPeer = updatedParticipants[i].peer {
|
||||||
|
indexMap[participantPeer.id] = i
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var updated = false
|
var updated = false
|
||||||
|
|
||||||
@ -1869,7 +2020,8 @@ public final class GroupCallParticipantsContext {
|
|||||||
isStream: strongSelf.stateValue.state.isStream,
|
isStream: strongSelf.stateValue.state.isStream,
|
||||||
version: strongSelf.stateValue.state.version
|
version: strongSelf.stateValue.state.version
|
||||||
),
|
),
|
||||||
overlayState: strongSelf.stateValue.overlayState
|
overlayState: strongSelf.stateValue.overlayState,
|
||||||
|
blockchainState: strongSelf.stateValue.blockchainState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2000,7 +2152,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
|
|
||||||
for participantUpdate in update.participantUpdates {
|
for participantUpdate in update.participantUpdates {
|
||||||
if case .left = participantUpdate.participationStatusChange {
|
if case .left = participantUpdate.participationStatusChange {
|
||||||
if let index = updatedParticipants.firstIndex(where: { $0.peer.id == participantUpdate.peerId }) {
|
if let index = updatedParticipants.firstIndex(where: { $0.id == .peer(participantUpdate.peerId) }) {
|
||||||
updatedParticipants.remove(at: index)
|
updatedParticipants.remove(at: index)
|
||||||
updatedTotalCount = max(0, updatedTotalCount - 1)
|
updatedTotalCount = max(0, updatedTotalCount - 1)
|
||||||
strongSelf.memberEventsPipe.putNext(MemberEvent(peerId: participantUpdate.peerId, canUnmute: false, joined: false))
|
strongSelf.memberEventsPipe.putNext(MemberEvent(peerId: participantUpdate.peerId, canUnmute: false, joined: false))
|
||||||
@ -2017,7 +2169,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
var previousActivityRank: Int?
|
var previousActivityRank: Int?
|
||||||
var previousMuteState: GroupCallParticipantsContext.Participant.MuteState?
|
var previousMuteState: GroupCallParticipantsContext.Participant.MuteState?
|
||||||
var previousVolume: Int32?
|
var previousVolume: Int32?
|
||||||
if let index = updatedParticipants.firstIndex(where: { $0.peer.id == participantUpdate.peerId }) {
|
if let index = updatedParticipants.firstIndex(where: { $0.id == .peer(participantUpdate.peerId) }) {
|
||||||
previousJoinTimestamp = updatedParticipants[index].joinTimestamp
|
previousJoinTimestamp = updatedParticipants[index].joinTimestamp
|
||||||
previousActivityTimestamp = updatedParticipants[index].activityTimestamp
|
previousActivityTimestamp = updatedParticipants[index].activityTimestamp
|
||||||
previousActivityRank = updatedParticipants[index].activityRank
|
previousActivityRank = updatedParticipants[index].activityRank
|
||||||
@ -2054,7 +2206,8 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let participant = Participant(
|
let participant = Participant(
|
||||||
peer: peer,
|
id: .peer(peer.id),
|
||||||
|
peer: EnginePeer(peer),
|
||||||
ssrc: participantUpdate.ssrc,
|
ssrc: participantUpdate.ssrc,
|
||||||
videoDescription: participantUpdate.videoDescription,
|
videoDescription: participantUpdate.videoDescription,
|
||||||
presentationDescription: participantUpdate.presentationDescription,
|
presentationDescription: participantUpdate.presentationDescription,
|
||||||
@ -2111,7 +2264,8 @@ public final class GroupCallParticipantsContext {
|
|||||||
isStream: isStream,
|
isStream: isStream,
|
||||||
version: update.version
|
version: update.version
|
||||||
),
|
),
|
||||||
overlayState: updatedOverlayState
|
overlayState: updatedOverlayState,
|
||||||
|
blockchainState: strongSelf.stateValue.blockchainState
|
||||||
)
|
)
|
||||||
|
|
||||||
strongSelf.endedProcessingUpdate()
|
strongSelf.endedProcessingUpdate()
|
||||||
@ -2158,7 +2312,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for participant in self.stateValue.state.participants {
|
for participant in self.stateValue.state.participants {
|
||||||
if participant.peer.id == peerId {
|
if participant.id == .peer(peerId) {
|
||||||
var raiseHandEqual: Bool = true
|
var raiseHandEqual: Bool = true
|
||||||
if let raiseHand = raiseHand {
|
if let raiseHand = raiseHand {
|
||||||
raiseHandEqual = (participant.raiseHandRating == nil && !raiseHand) ||
|
raiseHandEqual = (participant.raiseHandRating == nil && !raiseHand) ||
|
||||||
@ -2744,14 +2898,14 @@ func _internal_updatedCurrentPeerGroupCall(postbox: Postbox, network: Network, a
|
|||||||
private func mergeAndSortParticipants(current currentParticipants: [GroupCallParticipantsContext.Participant], with updatedParticipants: [GroupCallParticipantsContext.Participant], sortAscending: Bool) -> [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: [GroupCallParticipantsContext.Participant.Id: Int] = [:]
|
||||||
for i in 0 ..< mergedParticipants.count {
|
for i in 0 ..< mergedParticipants.count {
|
||||||
existingParticipantIndices[mergedParticipants[i].peer.id] = i
|
existingParticipantIndices[mergedParticipants[i].id] = i
|
||||||
}
|
}
|
||||||
for participant in updatedParticipants {
|
for participant in updatedParticipants {
|
||||||
if let _ = existingParticipantIndices[participant.peer.id] {
|
if let _ = existingParticipantIndices[participant.id] {
|
||||||
} else {
|
} else {
|
||||||
existingParticipantIndices[participant.peer.id] = mergedParticipants.count
|
existingParticipantIndices[participant.id] = mergedParticipants.count
|
||||||
mergedParticipants.append(participant)
|
mergedParticipants.append(participant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2942,7 +3096,8 @@ extension GroupCallParticipantsContext.Participant {
|
|||||||
let joinedVideo = (flags & (1 << 15)) != 0
|
let joinedVideo = (flags & (1 << 15)) != 0
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
peer: peer,
|
id: .peer(peer.id),
|
||||||
|
peer: EnginePeer(peer),
|
||||||
ssrc: ssrc,
|
ssrc: ssrc,
|
||||||
videoDescription: videoDescription,
|
videoDescription: videoDescription,
|
||||||
presentationDescription: presentationDescription,
|
presentationDescription: presentationDescription,
|
||||||
|
@ -144,8 +144,8 @@ public extension TelegramEngine {
|
|||||||
return _internal_getVideoBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds, channelId: channelId, quality: quality)
|
return _internal_getVideoBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds, channelId: channelId, quality: quality)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func groupCall(peerId: PeerId?, myPeerId: PeerId, id: Int64, reference: InternalGroupCallReference, state: GroupCallParticipantsContext.State, previousServiceState: GroupCallParticipantsContext.ServiceState?) -> GroupCallParticipantsContext {
|
public func groupCall(peerId: PeerId?, myPeerId: PeerId, id: Int64, reference: InternalGroupCallReference, state: GroupCallParticipantsContext.State, previousServiceState: GroupCallParticipantsContext.ServiceState?, e2eContext: ConferenceCallE2EContext?) -> GroupCallParticipantsContext {
|
||||||
return GroupCallParticipantsContext(account: self.account, peerId: peerId, myPeerId: myPeerId, id: id, reference: reference, state: state, previousServiceState: previousServiceState)
|
return GroupCallParticipantsContext(account: self.account, peerId: peerId, myPeerId: myPeerId, id: id, reference: reference, state: state, previousServiceState: previousServiceState, e2eContext: e2eContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func serverTime() -> Signal<Int64, NoError> {
|
public func serverTime() -> Signal<Int64, NoError> {
|
||||||
|
@ -172,7 +172,9 @@ func _internal_joinCallLinkInformation(_ hash: String, account: Account) -> Sign
|
|||||||
}
|
}
|
||||||
var members: [EnginePeer] = []
|
var members: [EnginePeer] = []
|
||||||
for participant in call.topParticipants {
|
for participant in call.topParticipants {
|
||||||
members.append(EnginePeer(participant.peer))
|
if let peer = participant.peer {
|
||||||
|
members.append(peer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return .single(JoinCallLinkInformation(id: call.info.id, accessHash: call.info.accessHash, inviter: nil, members: members, totalMemberCount: call.info.participantCount))
|
return .single(JoinCallLinkInformation(id: call.info.id, accessHash: call.info.accessHash, inviter: nil, members: members, totalMemberCount: call.info.participantCount))
|
||||||
}
|
}
|
||||||
@ -198,7 +200,9 @@ func _internal_joinCallInvitationInformation(account: Account, messageId: Messag
|
|||||||
}
|
}
|
||||||
var members: [EnginePeer] = []
|
var members: [EnginePeer] = []
|
||||||
for participant in call.topParticipants {
|
for participant in call.topParticipants {
|
||||||
members.append(EnginePeer(participant.peer))
|
if let peer = participant.peer {
|
||||||
|
members.append(peer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return .single(JoinCallLinkInformation(id: call.info.id, accessHash: call.info.accessHash, inviter: nil, members: members, totalMemberCount: call.info.participantCount))
|
return .single(JoinCallLinkInformation(id: call.info.id, accessHash: call.info.accessHash, inviter: nil, members: members, totalMemberCount: call.info.participantCount))
|
||||||
}
|
}
|
||||||
|
@ -4,41 +4,30 @@ import SwiftSignalKit
|
|||||||
|
|
||||||
public struct CallListSettings: Codable, Equatable {
|
public struct CallListSettings: Codable, Equatable {
|
||||||
public var _showTab: Bool?
|
public var _showTab: Bool?
|
||||||
public var defaultShowTab: Bool?
|
|
||||||
|
|
||||||
public static var defaultSettings: CallListSettings {
|
public static var defaultSettings: CallListSettings {
|
||||||
return CallListSettings(showTab: false)
|
return CallListSettings(showTab: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public var showTab: Bool {
|
public var showTab: Bool {
|
||||||
get {
|
get {
|
||||||
if let value = self._showTab {
|
if let value = self._showTab {
|
||||||
return value
|
return value
|
||||||
} else if let defaultValue = self.defaultShowTab {
|
|
||||||
return defaultValue
|
|
||||||
} else {
|
} else {
|
||||||
return CallListSettings.defaultSettings.showTab
|
return true
|
||||||
}
|
}
|
||||||
} set {
|
} set {
|
||||||
self._showTab = newValue
|
self._showTab = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(showTab: Bool) {
|
public init(showTab: Bool?) {
|
||||||
self._showTab = showTab
|
self._showTab = showTab
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(showTab: Bool?, defaultShowTab: Bool?) {
|
|
||||||
self._showTab = showTab
|
|
||||||
self.defaultShowTab = defaultShowTab
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
|
||||||
if let alternativeDefaultValue = try container.decodeIfPresent(Int32.self, forKey: "defaultShowTab") {
|
|
||||||
self.defaultShowTab = alternativeDefaultValue != 0
|
|
||||||
}
|
|
||||||
if let value = try container.decodeIfPresent(Int32.self, forKey: "showTab") {
|
if let value = try container.decodeIfPresent(Int32.self, forKey: "showTab") {
|
||||||
self._showTab = value != 0
|
self._showTab = value != 0
|
||||||
}
|
}
|
||||||
@ -47,11 +36,6 @@ public struct CallListSettings: Codable, Equatable {
|
|||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
|
||||||
if let defaultShowTab = self.defaultShowTab {
|
|
||||||
try container.encode((defaultShowTab ? 1 : 0) as Int32, forKey: "defaultShowTab")
|
|
||||||
} else {
|
|
||||||
try container.encodeNil(forKey: "defaultShowTab")
|
|
||||||
}
|
|
||||||
if let showTab = self._showTab {
|
if let showTab = self._showTab {
|
||||||
try container.encode((showTab ? 1 : 0) as Int32, forKey: "showTab")
|
try container.encode((showTab ? 1 : 0) as Int32, forKey: "showTab")
|
||||||
} else {
|
} else {
|
||||||
@ -60,11 +44,11 @@ public struct CallListSettings: Codable, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: CallListSettings, rhs: CallListSettings) -> Bool {
|
public static func ==(lhs: CallListSettings, rhs: CallListSettings) -> Bool {
|
||||||
return lhs._showTab == rhs._showTab && lhs.defaultShowTab == rhs.defaultShowTab
|
return lhs._showTab == rhs._showTab
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedShowTab(_ showTab: Bool) -> CallListSettings {
|
public func withUpdatedShowTab(_ showTab: Bool) -> CallListSettings {
|
||||||
return CallListSettings(showTab: showTab, defaultShowTab: self.defaultShowTab)
|
return CallListSettings(showTab: showTab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 579cae3c3c70c6ed8bc0d88cc41de28bd50a7f1b
|
Subproject commit 36161286bd7fae1b9bb2e8dad817ae9af6d68055
|
@ -22,10 +22,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@interface TdCallParticipant : NSObject
|
@interface TdCallParticipant : NSObject
|
||||||
|
|
||||||
@property (nonatomic, strong, readonly) NSData *publicKey;
|
@property (nonatomic, strong, readonly) NSString *internalId;
|
||||||
@property (nonatomic, readonly) int64_t userId;
|
@property (nonatomic, readonly) int64_t userId;
|
||||||
|
|
||||||
- (nullable instancetype)initWithPublicKey:(NSData *)publicKey userId:(int64_t)userId;
|
- (nullable instancetype)initWithInternalId:(NSString *)internalId userId:(int64_t)userId;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
- (NSArray<NSData *> *)takeOutgoingBroadcastBlocks;
|
- (NSArray<NSData *> *)takeOutgoingBroadcastBlocks;
|
||||||
- (NSData *)emojiState;
|
- (NSData *)emojiState;
|
||||||
- (NSArray<NSNumber *> *)participantIds;
|
- (NSArray<TdCallParticipant *> *)participants;
|
||||||
|
|
||||||
- (void)applyBlock:(NSData *)block;
|
- (void)applyBlock:(NSData *)block;
|
||||||
- (void)applyBroadcastBlock:(NSData *)block;
|
- (void)applyBroadcastBlock:(NSData *)block;
|
||||||
|
13
third-party/td/TdBinding/Sources/TdBinding.mm
vendored
13
third-party/td/TdBinding/Sources/TdBinding.mm
vendored
@ -58,10 +58,10 @@ static NSString *hexStringFromData(NSData *data) {
|
|||||||
|
|
||||||
@implementation TdCallParticipant
|
@implementation TdCallParticipant
|
||||||
|
|
||||||
- (nullable instancetype)initWithPublicKey:(NSData *)publicKey userId:(int64_t)userId {
|
- (nullable instancetype)initWithInternalId:(NSString *)internalId userId:(int64_t)userId {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil) {
|
if (self != nil) {
|
||||||
_publicKey = publicKey;
|
_internalId = internalId;
|
||||||
_userId = userId;
|
_userId = userId;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@ -176,17 +176,18 @@ static NSString *hexStringFromData(NSData *data) {
|
|||||||
return outEmojiHash;
|
return outEmojiHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<NSNumber *> *)participantIds {
|
- (NSArray<TdCallParticipant *> *)participants {
|
||||||
auto result = tde2e_api::call_get_state(_callId);
|
auto result = tde2e_api::call_get_state(_callId);
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
return @[];
|
return @[];
|
||||||
}
|
}
|
||||||
auto state = result.value();
|
auto state = result.value();
|
||||||
NSMutableArray<NSNumber *> *participantIds = [[NSMutableArray alloc] init];
|
NSMutableArray<TdCallParticipant *> *participants = [[NSMutableArray alloc] init];
|
||||||
for (const auto &it : state.participants) {
|
for (const auto &it : state.participants) {
|
||||||
[participantIds addObject:[NSNumber numberWithLongLong:it.user_id]];
|
NSString *internalId = [[NSString alloc] initWithFormat:@"%lld", it.public_key_id];
|
||||||
|
[participants addObject:[[TdCallParticipant alloc] initWithInternalId:internalId userId:it.user_id]];
|
||||||
}
|
}
|
||||||
return participantIds;
|
return participants;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyBlock:(NSData *)block {
|
- (void)applyBlock:(NSData *)block {
|
||||||
|
2
third-party/td/td
vendored
2
third-party/td/td
vendored
@ -1 +1 @@
|
|||||||
Subproject commit a03a90470d6fca9a5a3db747ba3f3e4a465b5fe7
|
Subproject commit 04adfc87deea4c804def118e88c89a08c388b32b
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "11.9.1",
|
"app": "11.10",
|
||||||
"xcode": "16.2",
|
"xcode": "16.2",
|
||||||
"bazel": "7.3.1:981f82a470bad1349322b6f51c9c6ffa0aa291dab1014fac411543c12e661dff",
|
"bazel": "7.3.1:981f82a470bad1349322b6f51c9c6ffa0aa291dab1014fac411543c12e661dff",
|
||||||
"macos": "15"
|
"macos": "15"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user