mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Group call participants may not have a peer available (support blockchain ids)
This commit is contained in:
parent
1ab31f1b44
commit
7593cc2724
@ -389,7 +389,10 @@ public extension GroupCallParticipantsContext.Participant {
|
||||
guard let videoDescription = self.videoDescription else {
|
||||
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)
|
||||
}, minQuality: minQuality, maxQuality: maxQuality)
|
||||
}
|
||||
@ -401,7 +404,10 @@ public extension GroupCallParticipantsContext.Participant {
|
||||
guard let presentationDescription = self.presentationDescription else {
|
||||
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)
|
||||
}, minQuality: minQuality, maxQuality: maxQuality)
|
||||
}
|
||||
|
@ -57,7 +57,8 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
|
||||
id: call.id,
|
||||
reference: .id(id: call.id, accessHash: call.accessHash),
|
||||
state: state,
|
||||
previousServiceState: nil
|
||||
previousServiceState: nil,
|
||||
e2eContext: nil
|
||||
)
|
||||
|
||||
self.participantsContext = context
|
||||
|
@ -425,8 +425,8 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
||||
if let members = currentMembers {
|
||||
var speakingPeers: [Peer] = []
|
||||
for member in members.participants {
|
||||
if members.speakingParticipants.contains(member.peer.id) {
|
||||
speakingPeers.append(member.peer)
|
||||
if let memberPeer = member.peer, members.speakingParticipants.contains(memberPeer.id) {
|
||||
speakingPeers.append(memberPeer._asPeer())
|
||||
}
|
||||
}
|
||||
speakingPeer = speakingPeers.first
|
||||
|
@ -395,7 +395,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
if data.info.isStream {
|
||||
self.avatarsContent = self.avatarsContext.update(peers: [], animated: false)
|
||||
} 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 {
|
||||
self.imageDisposable = nil
|
||||
@ -430,7 +430,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
if let info = summaryState.info, info.isStream {
|
||||
strongSelf.avatarsContent = strongSelf.avatarsContext.update(peers: [], animated: false)
|
||||
} 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 {
|
||||
@ -513,7 +513,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
if data.info.isStream {
|
||||
self.avatarsContent = self.avatarsContext.update(peers: [], animated: false)
|
||||
} 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
|
||||
|
@ -908,7 +908,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
var found = false
|
||||
if let members {
|
||||
for participant in members.participants {
|
||||
if participant.peer.id == waitForRemotePeerId {
|
||||
if participant.id == .peer(waitForRemotePeerId) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@ -921,7 +921,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
if waitForLocalVideo {
|
||||
if let members {
|
||||
for participant in members.participants {
|
||||
if participant.peer.id == state.myPeerId {
|
||||
if participant.id == .peer(state.myPeerId) {
|
||||
if participant.videoDescription == nil {
|
||||
return false
|
||||
}
|
||||
@ -932,7 +932,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
if let waitForRemoteVideo {
|
||||
if let members {
|
||||
for participant in members.participants {
|
||||
if participant.peer.id == waitForRemoteVideo {
|
||||
if participant.id == .peer(waitForRemoteVideo) {
|
||||
if participant.videoDescription == nil {
|
||||
return false
|
||||
}
|
||||
|
@ -331,9 +331,13 @@ private final class ConferenceCallE2EContextStateImpl: ConferenceCallE2EContextS
|
||||
func getEmojiState() -> Data? {
|
||||
return self.call.emojiState()
|
||||
}
|
||||
|
||||
func getParticipants() -> [ConferenceCallE2EContext.BlockchainParticipant] {
|
||||
return self.call.participants().map { ConferenceCallE2EContext.BlockchainParticipant(userId: $0.userId, internalId: $0.internalId) }
|
||||
}
|
||||
|
||||
func getParticipantIds() -> [Int64] {
|
||||
return self.call.participantIds().compactMap { $0.int64Value }
|
||||
return self.call.participants().map { $0.userId }
|
||||
}
|
||||
|
||||
func applyBlock(block: Data) {
|
||||
@ -1246,7 +1250,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
|
||||
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.participantsContextStateDisposable.set((combineLatest(queue: .mainQueue(),
|
||||
myPeerData,
|
||||
@ -1274,14 +1278,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
if oldMyPeerId != myPeerId {
|
||||
for i in 0 ..< participants.count {
|
||||
if participants[i].peer.id == oldMyPeerId {
|
||||
if participants[i].id == .peer(oldMyPeerId) {
|
||||
participants.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !participants.contains(where: { $0.peer.id == myPeerId }) {
|
||||
if !participants.contains(where: { $0.id == .peer(myPeerId) }) {
|
||||
if let (myPeer, aboutText) = myPeerData {
|
||||
let about: String?
|
||||
if let aboutText = aboutText {
|
||||
@ -1290,7 +1294,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
about = " "
|
||||
}
|
||||
participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: myPeer._asPeer(),
|
||||
id: .peer(myPeer.id),
|
||||
peer: myPeer,
|
||||
ssrc: nil,
|
||||
videoDescription: nil,
|
||||
presentationDescription: nil,
|
||||
@ -1315,7 +1320,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
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)
|
||||
didUpdateInvitedPeers = true
|
||||
}
|
||||
@ -1370,7 +1375,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
about = " "
|
||||
}
|
||||
participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: myPeer._asPeer(),
|
||||
id: .peer(myPeer.id),
|
||||
peer: myPeer,
|
||||
ssrc: nil,
|
||||
videoDescription: nil,
|
||||
presentationDescription: nil,
|
||||
@ -1495,7 +1501,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
isStream: callInfo.isStream,
|
||||
version: 0
|
||||
),
|
||||
previousServiceState: nil
|
||||
previousServiceState: nil,
|
||||
e2eContext: self.e2eContext
|
||||
)
|
||||
self.temporaryParticipantsContext = nil
|
||||
self.participantsContext = participantsContext
|
||||
@ -1555,7 +1562,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
about = " "
|
||||
}
|
||||
participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: myPeer._asPeer(),
|
||||
id: .peer(myPeer.id),
|
||||
peer: myPeer,
|
||||
ssrc: nil,
|
||||
videoDescription: nil,
|
||||
presentationDescription: nil,
|
||||
@ -1967,11 +1975,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
self.ssrcMapping.removeAll()
|
||||
for participant in joinCallResult.state.participants {
|
||||
if let ssrc = participant.ssrc {
|
||||
self.ssrcMapping[ssrc] = SsrcMapping(peerId: participant.peer.id, isPresentation: false)
|
||||
if let ssrc = participant.ssrc, let participantPeer = participant.peer {
|
||||
self.ssrcMapping[ssrc] = SsrcMapping(peerId: participantPeer.id, isPresentation: false)
|
||||
}
|
||||
if let presentationSsrc = participant.presentationDescription?.audioSsrc {
|
||||
self.ssrcMapping[presentationSsrc] = SsrcMapping(peerId: participant.peer.id, isPresentation: true)
|
||||
if let presentationSsrc = participant.presentationDescription?.audioSsrc, let participantPeer = participant.peer {
|
||||
self.ssrcMapping[presentationSsrc] = SsrcMapping(peerId: participantPeer.id, isPresentation: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2268,7 +2276,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
id: callInfo.id,
|
||||
reference: reference,
|
||||
state: initialState,
|
||||
previousServiceState: serviceState
|
||||
previousServiceState: serviceState,
|
||||
e2eContext: self.e2eContext
|
||||
)
|
||||
self.temporaryParticipantsContext = nil
|
||||
self.participantsContext = participantsContext
|
||||
@ -2367,14 +2376,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
if let (ignorePeerId, ignoreSsrc) = self.ignorePreviousJoinAsPeerId {
|
||||
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)
|
||||
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 {
|
||||
let about: String?
|
||||
if let cachedData = cachedData as? CachedUserData {
|
||||
@ -2386,7 +2395,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
|
||||
participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: myPeer,
|
||||
id: .peer(myPeer.id),
|
||||
peer: EnginePeer(myPeer),
|
||||
ssrc: nil,
|
||||
videoDescription: nil,
|
||||
presentationDescription: nil,
|
||||
@ -2415,13 +2425,17 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
let about: String?
|
||||
if let cachedData = cachedData as? CachedUserData {
|
||||
@ -2431,7 +2445,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
} else {
|
||||
about = " "
|
||||
}
|
||||
participant.peer = myPeer
|
||||
participant.peer = EnginePeer(myPeer)
|
||||
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)
|
||||
didUpdateInvitedPeers = true
|
||||
}
|
||||
@ -2646,24 +2660,28 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if remainingSsrcs.contains(audioSsrc) {
|
||||
remainingSsrcs.remove(audioSsrc)
|
||||
|
||||
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
||||
kind: .audio,
|
||||
peerId: participant.peer.id.id._internalGetInt64Value(),
|
||||
audioSsrc: audioSsrc,
|
||||
videoDescription: nil
|
||||
))
|
||||
if let participantPeer = participant.peer {
|
||||
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
||||
kind: .audio,
|
||||
peerId: participantPeer.id.id._internalGetInt64Value(),
|
||||
audioSsrc: audioSsrc,
|
||||
videoDescription: nil
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if let screencastSsrc = participant.presentationDescription?.audioSsrc {
|
||||
if remainingSsrcs.contains(screencastSsrc) {
|
||||
remainingSsrcs.remove(screencastSsrc)
|
||||
|
||||
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
||||
kind: .audio,
|
||||
peerId: participant.peer.id.id._internalGetInt64Value(),
|
||||
audioSsrc: screencastSsrc,
|
||||
videoDescription: nil
|
||||
))
|
||||
if let participantPeer = participant.peer {
|
||||
result.append(OngoingGroupCallContext.MediaChannelDescription(
|
||||
kind: .audio,
|
||||
peerId: participantPeer.id.id._internalGetInt64Value(),
|
||||
audioSsrc: screencastSsrc,
|
||||
videoDescription: nil
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2849,7 +2867,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
if let participantsContext = self.participantsContext, let immediateState = participantsContext.immediateState {
|
||||
for participant in immediateState.participants {
|
||||
if participant.peer.id == previousPeerId {
|
||||
if participant.id == .peer(previousPeerId) {
|
||||
self.temporaryJoinTimestamp = participant.joinTimestamp
|
||||
self.temporaryActivityTimestamp = participant.activityTimestamp
|
||||
self.temporaryActivityRank = participant.activityRank
|
||||
@ -3008,7 +3026,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
return
|
||||
}
|
||||
for participant in membersValue.participants {
|
||||
if participant.peer.id == self.joinAsPeerId {
|
||||
if participant.id == .peer(self.joinAsPeerId) {
|
||||
if participant.hasRaiseHand {
|
||||
return
|
||||
}
|
||||
@ -3024,7 +3042,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
return
|
||||
}
|
||||
for participant in membersValue.participants {
|
||||
if participant.peer.id == self.joinAsPeerId {
|
||||
if participant.id == .peer(self.joinAsPeerId) {
|
||||
if !participant.hasRaiseHand {
|
||||
return
|
||||
}
|
||||
|
@ -143,7 +143,9 @@ final class VideoChatParticipantThumbnailComponent: Component {
|
||||
gesture.cancel()
|
||||
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)
|
||||
transition.setFrame(view: avatarNode.view, frame: avatarFrame)
|
||||
avatarNode.updateSize(size: avatarSize)
|
||||
if component.participant.peer.smallProfileImage != nil {
|
||||
avatarNode.setPeerV2(context: component.call.accountContext, theme: component.theme, peer: EnginePeer(component.participant.peer), displayDimensions: avatarSize)
|
||||
if component.participant.peer?.smallProfileImage != nil {
|
||||
avatarNode.setPeerV2(context: component.call.accountContext, theme: component.theme, peer: component.participant.peer, displayDimensions: avatarSize)
|
||||
} 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(
|
||||
@ -241,7 +243,7 @@ final class VideoChatParticipantThumbnailComponent: Component {
|
||||
let titleSize = self.title.update(
|
||||
transition: .immediate,
|
||||
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: {},
|
||||
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 Participant: Equatable {
|
||||
struct Key: Hashable {
|
||||
var id: EnginePeer.Id
|
||||
var id: GroupCallParticipantsContext.Participant.Id
|
||||
var isPresentation: Bool
|
||||
|
||||
init(id: EnginePeer.Id, isPresentation: Bool) {
|
||||
init(id: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool) {
|
||||
self.id = id
|
||||
self.isPresentation = isPresentation
|
||||
}
|
||||
@ -449,7 +451,7 @@ final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
||||
let isPresentation: Bool
|
||||
|
||||
var key: Key {
|
||||
return Key(id: self.participant.peer.id, isPresentation: self.isPresentation)
|
||||
return Key(id: self.participant.id, isPresentation: self.isPresentation)
|
||||
}
|
||||
|
||||
init(
|
||||
@ -657,6 +659,12 @@ final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
||||
let itemFrame = itemLayout.frame(at: i)
|
||||
|
||||
let participantKey = participant.key
|
||||
|
||||
var isSpeaking = false
|
||||
if let participantPeer = participant.participant.peer {
|
||||
isSpeaking = component.speakingParticipants.contains(participantPeer.id)
|
||||
}
|
||||
|
||||
let _ = itemView.view.update(
|
||||
transition: itemTransition,
|
||||
component: AnyComponent(VideoChatParticipantThumbnailComponent(
|
||||
@ -665,7 +673,7 @@ final class VideoChatExpandedParticipantThumbnailsComponent: Component {
|
||||
participant: participant.participant,
|
||||
isPresentation: participant.isPresentation,
|
||||
isSelected: component.selectedParticipant == participant.key,
|
||||
isSpeaking: component.speakingParticipants.contains(participant.participant.peer.id),
|
||||
isSpeaking: isSpeaking,
|
||||
displayVideo: component.displayVideo,
|
||||
interfaceOrientation: component.interfaceOrientation,
|
||||
action: { [weak self] in
|
||||
|
@ -133,14 +133,14 @@ private final class BlobView: UIView {
|
||||
|
||||
final class VideoChatParticipantAvatarComponent: Component {
|
||||
let call: VideoChatCall
|
||||
let peer: EnginePeer
|
||||
let peer: EnginePeer?
|
||||
let myPeerId: EnginePeer.Id
|
||||
let isSpeaking: Bool
|
||||
let theme: PresentationTheme
|
||||
|
||||
init(
|
||||
call: VideoChatCall,
|
||||
peer: EnginePeer,
|
||||
peer: EnginePeer?,
|
||||
myPeerId: EnginePeer.Id,
|
||||
isSpeaking: Bool,
|
||||
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)
|
||||
}
|
||||
|
||||
if component.peer.smallProfileImage != nil {
|
||||
if component.peer?.smallProfileImage != nil {
|
||||
avatarNode.setPeerV2(
|
||||
context: component.call.accountContext,
|
||||
theme: component.theme,
|
||||
@ -296,7 +296,7 @@ final class VideoChatParticipantAvatarComponent: Component {
|
||||
var isSpeaking: Bool
|
||||
}
|
||||
|
||||
let peerId = component.peer.id
|
||||
let peerId = component.peer?.id
|
||||
let levelSignal: Signal<Level?, NoError>
|
||||
if peerId == component.myPeerId {
|
||||
levelSignal = component.call.myAudioLevelAndSpeaking
|
||||
|
@ -245,7 +245,9 @@ final class VideoChatParticipantVideoComponent: Component {
|
||||
gesture.cancel()
|
||||
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
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
if let smallProfileImage = component.participant.peer.smallProfileImage {
|
||||
if let smallProfileImage = component.participant.peer?.smallProfileImage {
|
||||
let blurredAvatarView: UIImageView
|
||||
if let current = self.blurredAvatarView {
|
||||
blurredAvatarView = current
|
||||
@ -338,8 +340,8 @@ final class VideoChatParticipantVideoComponent: Component {
|
||||
|
||||
if self.blurredAvatarDisposable == nil {
|
||||
//TODO:release synchronous
|
||||
if let imageCache = component.call.accountContext.imageCache as? DirectMediaImageCache, let peerReference = PeerReference(component.participant.peer) {
|
||||
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 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: participantPeer.profileImageRepresentations.first?.immediateThumbnailData, size: 64, synchronous: false) {
|
||||
if let image = result.image {
|
||||
blurredAvatarView.image = blurredAvatarImage(image)
|
||||
}
|
||||
@ -402,7 +404,7 @@ final class VideoChatParticipantVideoComponent: Component {
|
||||
let titleSize = self.title.update(
|
||||
transition: .immediate,
|
||||
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,
|
||||
textShadowColor: UIColor(white: 0.0, alpha: 0.7),
|
||||
textShadowBlur: 8.0
|
||||
|
@ -92,10 +92,10 @@ final class VideoChatParticipantsComponent: Component {
|
||||
}
|
||||
|
||||
struct VideoParticipantKey: Hashable {
|
||||
var id: EnginePeer.Id
|
||||
var id: GroupCallParticipantsContext.Participant.Id
|
||||
var isPresentation: Bool
|
||||
|
||||
init(id: EnginePeer.Id, isPresentation: Bool) {
|
||||
init(id: GroupCallParticipantsContext.Participant.Id, isPresentation: Bool) {
|
||||
self.id = id
|
||||
self.isPresentation = isPresentation
|
||||
}
|
||||
@ -608,7 +608,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
let isPresentation: Bool
|
||||
|
||||
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) {
|
||||
@ -673,7 +673,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
private var expandedThumbnailsView: 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 listItemViewSeparatorContainer: SimpleLayer
|
||||
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 {
|
||||
let videoParticipant = self.gridParticipants[index]
|
||||
@ -988,7 +988,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
}
|
||||
|
||||
if isItemExpanded || (index >= clippedVisibleGridItemRange.minIndex && index <= clippedVisibleGridItemRange.maxIndex) {
|
||||
visibleParticipants.append(videoParticipant.key.id)
|
||||
visibleParticipants.append(videoParticipant.participant.id)
|
||||
}
|
||||
|
||||
var suppressItemExpansionCollapseAnimation = false
|
||||
@ -1048,6 +1048,11 @@ final class VideoChatParticipantsComponent: Component {
|
||||
} else {
|
||||
itemAlpha = 1.0
|
||||
}
|
||||
|
||||
var isSpeaking = false
|
||||
if let participantPeer = videoParticipant.participant.peer {
|
||||
isSpeaking = component.speakingParticipants.contains(participantPeer.id)
|
||||
}
|
||||
|
||||
let _ = itemView.view.update(
|
||||
transition: itemTransition,
|
||||
@ -1056,9 +1061,9 @@ final class VideoChatParticipantsComponent: Component {
|
||||
strings: component.strings,
|
||||
call: component.call,
|
||||
participant: videoParticipant.participant,
|
||||
isMyPeer: videoParticipant.participant.peer.id == component.participants?.myPeerId,
|
||||
isMyPeer: videoParticipant.participant.peer?.id == component.participants?.myPeerId,
|
||||
isPresentation: videoParticipant.isPresentation,
|
||||
isSpeaking: component.speakingParticipants.contains(videoParticipant.participant.peer.id),
|
||||
isSpeaking: isSpeaking,
|
||||
maxVideoQuality: component.maxVideoQuality,
|
||||
isExpanded: isItemExpanded,
|
||||
isUIHidden: isItemUIHidden || self.isPinchToZoomActive,
|
||||
@ -1205,23 +1210,23 @@ final class VideoChatParticipantsComponent: Component {
|
||||
self.gridItemViews.removeValue(forKey: itemId)
|
||||
}
|
||||
|
||||
var validListItemIds: [EnginePeer.Id] = []
|
||||
var validListItemIds: [GroupCallParticipantsContext.Participant.Id] = []
|
||||
let visibleListItemRange = itemLayout.visibleListItemRange(for: self.scrollView.bounds)
|
||||
let clippedVisibleListItemRange = itemLayout.visibleListItemRange(for: clippedScrollViewBounds)
|
||||
if visibleListItemRange.maxIndex >= visibleListItemRange.minIndex {
|
||||
for i in visibleListItemRange.minIndex ... visibleListItemRange.maxIndex {
|
||||
let itemFrame = itemLayout.listItemFrame(at: i)
|
||||
|
||||
let participantPeerId: EnginePeer.Id
|
||||
let participantItemId: GroupCallParticipantsContext.Participant.Id
|
||||
let peerItemComponent: PeerListItemComponent
|
||||
if i < self.listParticipants.count {
|
||||
let participant = self.listParticipants[i]
|
||||
participantPeerId = participant.peer.id
|
||||
participantItemId = participant.id
|
||||
|
||||
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)
|
||||
} 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 {
|
||||
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeakingVolume("\(volume / 100)%").string, color: .constructive)
|
||||
} else {
|
||||
@ -1233,10 +1238,14 @@ final class VideoChatParticipantsComponent: Component {
|
||||
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(
|
||||
muteState: participant.muteState,
|
||||
hasRaiseHand: participant.hasRaiseHand,
|
||||
isSpeaking: component.speakingParticipants.contains(participant.peer.id),
|
||||
isSpeaking: isSpeaking,
|
||||
theme: component.theme
|
||||
))
|
||||
|
||||
@ -1246,15 +1255,15 @@ final class VideoChatParticipantsComponent: Component {
|
||||
strings: component.strings,
|
||||
style: .generic,
|
||||
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(
|
||||
call: component.call,
|
||||
peer: EnginePeer(participant.peer),
|
||||
peer: participant.peer,
|
||||
myPeerId: component.participants?.myPeerId ?? component.call.accountContext.account.peerId,
|
||||
isSpeaking: component.speakingParticipants.contains(participant.peer.id),
|
||||
isSpeaking: isSpeaking,
|
||||
theme: component.theme
|
||||
)),
|
||||
peer: EnginePeer(participant.peer),
|
||||
peer: participant.peer,
|
||||
subtitle: subtitle,
|
||||
subtitleAccessory: .none,
|
||||
presence: nil,
|
||||
@ -1280,7 +1289,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
)
|
||||
} else {
|
||||
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)
|
||||
|
||||
@ -1328,20 +1337,20 @@ final class VideoChatParticipantsComponent: Component {
|
||||
)
|
||||
}
|
||||
|
||||
validListItemIds.append(participantPeerId)
|
||||
validListItemIds.append(participantItemId)
|
||||
|
||||
if i >= clippedVisibleListItemRange.minIndex && i <= clippedVisibleListItemRange.maxIndex {
|
||||
visibleParticipants.append(participantPeerId)
|
||||
visibleParticipants.append(participantItemId)
|
||||
}
|
||||
|
||||
var itemTransition = transition
|
||||
let itemView: ListItem
|
||||
if let current = self.listItemViews[participantPeerId] {
|
||||
if let current = self.listItemViews[participantItemId] {
|
||||
itemView = current
|
||||
} else {
|
||||
itemTransition = itemTransition.withAnimation(.none)
|
||||
itemView = ListItem()
|
||||
self.listItemViews[participantPeerId] = itemView
|
||||
self.listItemViews[participantItemId] = itemView
|
||||
}
|
||||
|
||||
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 {
|
||||
if !validListItemIds.contains(itemId) {
|
||||
removedListItemIds.append(itemId)
|
||||
@ -1512,7 +1521,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
expandedThumbnailsComponentView.alpha = expandedThumbnailsAlpha
|
||||
|
||||
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)
|
||||
} else {
|
||||
fromReferenceFrame = previousExpandedGridItemContainerFrame
|
||||
@ -1571,7 +1580,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
expandedControlsComponentView.alpha = expandedControlsAlpha
|
||||
|
||||
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)
|
||||
} else {
|
||||
fromReferenceFrame = previousExpandedGridItemContainerFrame
|
||||
@ -1591,7 +1600,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
self.expandedThumbnailsView = nil
|
||||
|
||||
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)
|
||||
var targetItemFrame = self.gridItemViewContainer.convert(targetLocalItemFrame, to: self)
|
||||
targetItemFrame.origin.y -= expandedGridItemContainerFrame.minY
|
||||
@ -1612,7 +1621,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
self.expandedControlsView = nil
|
||||
|
||||
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)
|
||||
var targetItemFrame = self.gridItemViewContainer.convert(targetLocalItemFrame, to: self)
|
||||
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>
|
||||
var expandedSpeakingToastTransition = transition
|
||||
if let current = self.expandedSpeakingToast {
|
||||
@ -1644,21 +1653,21 @@ final class VideoChatParticipantsComponent: Component {
|
||||
transition: expandedSpeakingToastTransition,
|
||||
component: AnyComponent(VideoChatExpandedSpeakingToastComponent(
|
||||
context: component.call.accountContext,
|
||||
peer: EnginePeer(speakingPeer),
|
||||
peer: speakingPeer,
|
||||
strings: component.strings,
|
||||
theme: component.theme,
|
||||
action: { [weak self] peer in
|
||||
guard let self, let component = self.component, let participants = component.participants else {
|
||||
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
|
||||
}
|
||||
var key: VideoParticipantKey?
|
||||
if participant.presentationDescription != nil {
|
||||
key = VideoParticipantKey(id: peer.id, isPresentation: true)
|
||||
key = VideoParticipantKey(id: .peer(peer.id), isPresentation: true)
|
||||
} else if participant.videoDescription != nil {
|
||||
key = VideoParticipantKey(id: peer.id, isPresentation: false)
|
||||
key = VideoParticipantKey(id: .peer(peer.id), isPresentation: false)
|
||||
}
|
||||
if let key {
|
||||
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?) {
|
||||
@ -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 {
|
||||
if key.id == peerId && key.isPresentation == isPresentation {
|
||||
if let itemComponentView = itemView.view.view {
|
||||
@ -1723,7 +1738,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
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 {
|
||||
if key.id == peerId && key.isPresentation == isPresentation {
|
||||
if let itemComponentView = itemView.view.view as? VideoChatParticipantVideoComponent.View {
|
||||
@ -1781,7 +1796,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
if participant.videoDescription != nil {
|
||||
hasVideo = true
|
||||
let videoParticipant = VideoParticipant(participant: participant, isPresentation: false)
|
||||
if participant.peer.id == participants.myPeerId {
|
||||
if participant.id == .peer(participants.myPeerId) {
|
||||
gridParticipants.insert(videoParticipant, at: 0)
|
||||
} else {
|
||||
gridParticipants.append(videoParticipant)
|
||||
@ -1790,14 +1805,14 @@ final class VideoChatParticipantsComponent: Component {
|
||||
if participant.presentationDescription != nil {
|
||||
hasVideo = 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)
|
||||
} else {
|
||||
gridParticipants.append(videoParticipant)
|
||||
}
|
||||
}
|
||||
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)
|
||||
} else {
|
||||
listParticipants.append(participant)
|
||||
@ -1927,7 +1942,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
for participant in participants.participants {
|
||||
var maxVideoQuality: PresentationGroupCallRequestedVideo.Quality = .medium
|
||||
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 {
|
||||
maxVideoQuality = .full
|
||||
} else if component.maxVideoQuality == 360 {
|
||||
@ -1942,7 +1957,7 @@ final class VideoChatParticipantsComponent: Component {
|
||||
|
||||
var maxPresentationQuality: PresentationGroupCallRequestedVideo.Quality = .medium
|
||||
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 {
|
||||
maxVideoQuality = .full
|
||||
} else if component.maxVideoQuality == 360 {
|
||||
|
@ -343,17 +343,17 @@ final class VideoChatScreenComponent: Component {
|
||||
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 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 {
|
||||
expandedPeer = (participant.peer.id, false)
|
||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: true)
|
||||
expandedPeer = (participant.id, false)
|
||||
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 {
|
||||
expandedPeer = (participant.peer.id, false)
|
||||
self.expandedParticipantsVideoState = VideoChatParticipantsComponent.ExpandedVideoState(mainParticipant: VideoChatParticipantsComponent.VideoParticipantKey(id: participant.peer.id, isPresentation: false), isMainParticipantPinned: false, isUIHidden: true)
|
||||
expandedPeer = (participant.id, false)
|
||||
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(
|
||||
peer: myPeer._asPeer(),
|
||||
id: .peer(myPeer.id),
|
||||
peer: myPeer,
|
||||
ssrc: nil,
|
||||
videoDescription: myVideoDescription,
|
||||
presentationDescription: nil,
|
||||
@ -1189,7 +1190,8 @@ final class VideoChatScreenComponent: Component {
|
||||
}
|
||||
|
||||
participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: remotePeer._asPeer(),
|
||||
id: .peer(remotePeer.id),
|
||||
peer: remotePeer,
|
||||
ssrc: nil,
|
||||
videoDescription: remoteVideoDescription,
|
||||
presentationDescription: nil,
|
||||
@ -1235,7 +1237,7 @@ final class VideoChatScreenComponent: Component {
|
||||
self.members = component.initialData.members
|
||||
self.invitedPeers = component.initialData.invitedPeers
|
||||
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
|
||||
}
|
||||
@ -1276,7 +1278,7 @@ final class VideoChatScreenComponent: Component {
|
||||
|
||||
self.members = 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 {
|
||||
@ -1299,28 +1301,28 @@ final class VideoChatScreenComponent: Component {
|
||||
|
||||
if let expandedParticipantsVideoState = self.expandedParticipantsVideoState, let members {
|
||||
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
|
||||
}
|
||||
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 false
|
||||
}) {
|
||||
if participant.peer.id != expandedParticipantsVideoState.mainParticipant.id {
|
||||
if participant.id != expandedParticipantsVideoState.mainParticipant.id {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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 participant.presentationDescription == nil {
|
||||
return false
|
||||
@ -1344,9 +1346,9 @@ final class VideoChatScreenComponent: Component {
|
||||
return false
|
||||
}) {
|
||||
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 {
|
||||
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
|
||||
} else {
|
||||
@ -1365,8 +1367,8 @@ final class VideoChatScreenComponent: Component {
|
||||
var speakingParticipantPeers: [EnginePeer] = []
|
||||
if let members, !members.speakingParticipants.isEmpty {
|
||||
for participant in members.participants {
|
||||
if members.speakingParticipants.contains(participant.peer.id) {
|
||||
speakingParticipantPeers.append(EnginePeer(participant.peer))
|
||||
if let participantPeer = participant.peer, members.speakingParticipants.contains(participantPeer.id) {
|
||||
speakingParticipantPeers.append(participantPeer)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1401,7 +1403,7 @@ final class VideoChatScreenComponent: Component {
|
||||
|
||||
var invitedPeers = invitedPeers
|
||||
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 {
|
||||
@ -1612,28 +1614,28 @@ final class VideoChatScreenComponent: Component {
|
||||
|
||||
if let expandedParticipantsVideoState = self.expandedParticipantsVideoState {
|
||||
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
|
||||
}
|
||||
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 false
|
||||
}) {
|
||||
if participant.peer.id != expandedParticipantsVideoState.mainParticipant.id {
|
||||
if participant.id != expandedParticipantsVideoState.mainParticipant.id {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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 participant.presentationDescription == nil {
|
||||
return false
|
||||
@ -1657,9 +1659,9 @@ final class VideoChatScreenComponent: Component {
|
||||
return false
|
||||
}) {
|
||||
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 {
|
||||
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
|
||||
} else {
|
||||
@ -1678,8 +1680,8 @@ final class VideoChatScreenComponent: Component {
|
||||
var speakingParticipantPeers: [EnginePeer] = []
|
||||
if !members.speakingParticipants.isEmpty {
|
||||
for participant in members.participants {
|
||||
if members.speakingParticipants.contains(participant.peer.id) {
|
||||
speakingParticipantPeers.append(EnginePeer(participant.peer))
|
||||
if let participantPeer = participant.peer, members.speakingParticipants.contains(participantPeer.id) {
|
||||
speakingParticipantPeers.append(participantPeer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ extension VideoChatScreenComponent.View {
|
||||
disablePeerIds.append(groupCall.accountContext.account.peerId)
|
||||
if let members = self.members {
|
||||
for participant in members.participants {
|
||||
if !disablePeerIds.contains(participant.peer.id) {
|
||||
disablePeerIds.append(participant.peer.id)
|
||||
if let participantPeer = participant.peer, !disablePeerIds.contains(participantPeer.id) {
|
||||
disablePeerIds.append(participantPeer.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,7 +99,7 @@ extension VideoChatScreenComponent.View {
|
||||
|
||||
var filters: [ChannelMembersSearchFilter] = []
|
||||
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 !groupPeer.hasPermission(.inviteMembers) && inviteLinks?.listenerLink == nil {
|
||||
|
@ -18,7 +18,7 @@ extension VideoChatScreenComponent.View {
|
||||
guard let environment = self.environment else {
|
||||
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
|
||||
}
|
||||
guard let currentCall = self.currentCall else {
|
||||
@ -35,10 +35,13 @@ extension VideoChatScreenComponent.View {
|
||||
return []
|
||||
}
|
||||
|
||||
var items: [ContextMenuItem] = []
|
||||
guard let peer = participant.peer else {
|
||||
return []
|
||||
}
|
||||
|
||||
var items: [ContextMenuItem] = []
|
||||
var hasVolumeSlider = false
|
||||
let peer = participant.peer
|
||||
|
||||
if let muteState = muteState, !muteState.canUnmute || muteState.mutedByYou {
|
||||
} else {
|
||||
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
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tip"), color: theme.actionSheet.primaryTextColor)
|
||||
}), 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
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/ChangeName"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { [weak self] _, f in
|
||||
@ -184,7 +187,9 @@ extension VideoChatScreenComponent.View {
|
||||
let _ = groupCall.updateMuteState(peerId: peer.id, isMuted: false)
|
||||
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 {
|
||||
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 {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = groupCall.updateMuteState(peerId: peer.id, isMuted: false)
|
||||
f(.default)
|
||||
})))
|
||||
@ -228,7 +232,7 @@ extension VideoChatScreenComponent.View {
|
||||
let openTitle: String
|
||||
let openIcon: UIImage?
|
||||
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
|
||||
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels")
|
||||
} else {
|
||||
@ -256,7 +260,7 @@ extension VideoChatScreenComponent.View {
|
||||
guard let navigationController else {
|
||||
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
|
||||
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
|
||||
@ -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([
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import SwiftSignalKit
|
||||
public protocol ConferenceCallE2EContextState: AnyObject {
|
||||
func getEmojiState() -> Data?
|
||||
func getParticipantIds() -> [Int64]
|
||||
func getParticipants() -> [ConferenceCallE2EContext.BlockchainParticipant]
|
||||
|
||||
func applyBlock(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 let queue: Queue
|
||||
|
||||
@ -38,6 +49,7 @@ public final class ConferenceCallE2EContext {
|
||||
private let keyPair: TelegramKeyPair
|
||||
|
||||
let e2eEncryptionKeyHashValue = ValuePromise<Data?>(nil)
|
||||
let blockchainParticipantsValue = ValuePromise<[BlockchainParticipant]>([])
|
||||
|
||||
private var e2ePoll0Offset: Int?
|
||||
private var e2ePoll0Timer: Foundation.Timer?
|
||||
@ -154,7 +166,7 @@ public final class ConferenceCallE2EContext {
|
||||
let keyPair = self.keyPair
|
||||
let userId = self.userId
|
||||
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 {
|
||||
for block in blocks {
|
||||
if subChainId == 0 {
|
||||
@ -163,30 +175,31 @@ public final class ConferenceCallE2EContext {
|
||||
state.applyBroadcastBlock(block: block)
|
||||
}
|
||||
}
|
||||
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data())
|
||||
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data(), state.getParticipants())
|
||||
} else {
|
||||
if subChainId == 0 {
|
||||
guard let block = blocks.last else {
|
||||
return ([], Data())
|
||||
return ([], Data(), [])
|
||||
}
|
||||
guard let state = initializeState(keyPair, userId, block) else {
|
||||
return ([], Data())
|
||||
return ([], Data(), [])
|
||||
}
|
||||
callState.state = state
|
||||
for block in callState.pendingIncomingBroadcastBlocks {
|
||||
state.applyBroadcastBlock(block: block)
|
||||
}
|
||||
callState.pendingIncomingBroadcastBlocks.removeAll()
|
||||
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data())
|
||||
return (state.takeOutgoingBroadcastBlocks(), state.getEmojiState() ?? Data(), state.getParticipants())
|
||||
} else if subChainId == 1 {
|
||||
callState.pendingIncomingBroadcastBlocks.append(contentsOf: blocks)
|
||||
return ([], Data())
|
||||
return ([], Data(), [])
|
||||
} else {
|
||||
return ([], Data())
|
||||
return ([], Data(), [])
|
||||
}
|
||||
}
|
||||
})
|
||||
self.e2eEncryptionKeyHashValue.set(outEmoji.isEmpty ? nil : outEmoji)
|
||||
self.blockchainParticipantsValue.set(outBlockchainParticipants)
|
||||
|
||||
for outBlock in outBlocks {
|
||||
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 callId = self.callId
|
||||
let accessHash = self.accessHash
|
||||
let accountPeerId = engine.account.peerId
|
||||
|
||||
if !self.pendingKickPeers.isEmpty {
|
||||
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
|
||||
let removedPeerIds = blockchainPeerIds.filter { blockchainPeerId in
|
||||
return !result.participants.contains(where: { $0.peer.id.id._internalGetInt64Value() == blockchainPeerId })
|
||||
var removedPeerIds = blockchainPeerIds.filter { blockchainPeerId in
|
||||
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 {
|
||||
return .single(false)
|
||||
@ -422,6 +443,12 @@ public final class ConferenceCallE2EContext {
|
||||
return impl.e2eEncryptionKeyHashValue.get().start(next: subscriber.putNext)
|
||||
}
|
||||
}
|
||||
|
||||
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?) {
|
||||
let queue = Queue.mainQueue()
|
||||
|
@ -280,7 +280,7 @@ func _internal_getCurrentGroupCallInfo(account: Account, reference: InternalGrou
|
||||
|
||||
let parsedParticipants = participants.compactMap { GroupCallParticipantsContext.Participant($0, transaction: transaction) }
|
||||
return (
|
||||
parsedParticipants.map(\.peer.id),
|
||||
parsedParticipants.compactMap(\.peer?.id),
|
||||
nil
|
||||
)
|
||||
}
|
||||
@ -847,9 +847,10 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId?, joinAs: PeerId?,
|
||||
presentationDescription = nil
|
||||
}
|
||||
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(
|
||||
peer: peer,
|
||||
id: .peer(peer.id),
|
||||
peer: EnginePeer(peer),
|
||||
ssrc: ssrc,
|
||||
videoDescription: videoDescription,
|
||||
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 videoDescription: VideoDescription?
|
||||
public var presentationDescription: VideoDescription?
|
||||
@ -1190,7 +1225,8 @@ public final class GroupCallParticipantsContext {
|
||||
public var joinedVideo: Bool
|
||||
|
||||
public init(
|
||||
peer: Peer,
|
||||
id: Id,
|
||||
peer: EnginePeer?,
|
||||
ssrc: UInt32?,
|
||||
videoDescription: VideoDescription?,
|
||||
presentationDescription: VideoDescription?,
|
||||
@ -1204,6 +1240,7 @@ public final class GroupCallParticipantsContext {
|
||||
about: String?,
|
||||
joinedVideo: Bool
|
||||
) {
|
||||
self.id = id
|
||||
self.peer = peer
|
||||
self.ssrc = ssrc
|
||||
self.videoDescription = videoDescription
|
||||
@ -1220,7 +1257,7 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -1231,7 +1268,10 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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) {
|
||||
var indexMap: [PeerId: Int] = [:]
|
||||
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 {
|
||||
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)
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -1547,7 +1589,7 @@ public final class GroupCallParticipantsContext {
|
||||
var sortAgain = false
|
||||
var canSeeHands = state.state.isCreator || state.state.adminIds.contains(accountPeerId)
|
||||
for participant in publicState.participants {
|
||||
if participant.peer.id == myPeerId {
|
||||
if participant.id == .peer(myPeerId) {
|
||||
if let muteState = participant.muteState {
|
||||
if muteState.canUnmute {
|
||||
canSeeHands = true
|
||||
@ -1559,7 +1601,7 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
}
|
||||
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].volume = pendingMuteState.volume
|
||||
}
|
||||
@ -1631,7 +1673,9 @@ public final class GroupCallParticipantsContext {
|
||||
|
||||
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?
|
||||
|
||||
init(account: Account, peerId: PeerId?, myPeerId: PeerId, id: Int64, reference: InternalGroupCallReference, state: State, previousServiceState: ServiceState?, e2eContext: ConferenceCallE2EContext?) {
|
||||
self.account = account
|
||||
self.peerId = peerId
|
||||
self.myPeerId = myPeerId
|
||||
@ -1660,7 +1704,7 @@ public final class GroupCallParticipantsContext {
|
||||
if let peerId {
|
||||
let activityCategory: PeerActivitySpace.Category = .voiceChat
|
||||
self.activitiesDisposable = (self.account.peerInputActivities(peerId: PeerActivitySpace(peerId: peerId, category: activityCategory))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] activities in
|
||||
|> deliverOnMainQueue).start(next: { [weak self] activities in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -1674,7 +1718,9 @@ public final class GroupCallParticipantsContext {
|
||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||
var indexMap: [PeerId: Int] = [:]
|
||||
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
|
||||
|
||||
@ -1753,6 +1799,16 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
}, queue: .mainQueue())
|
||||
self.activityRankResetTimer?.start()
|
||||
|
||||
if let e2eContext {
|
||||
self.e2eStateUpdateDisposable = (e2eContext.blockchainParticipants
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] blockchainParticipants in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = self
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -1764,6 +1820,7 @@ public final class GroupCallParticipantsContext {
|
||||
self.activityRankResetTimer?.invalidate()
|
||||
self.resetInviteLinksDisposable.dispose()
|
||||
self.subscribeDisposable.dispose()
|
||||
self.e2eStateUpdateDisposable?.dispose()
|
||||
}
|
||||
|
||||
public func addUpdates(updates: [Update]) {
|
||||
@ -1795,7 +1852,7 @@ public final class GroupCallParticipantsContext {
|
||||
public func removeLocalPeerId() {
|
||||
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
|
||||
}
|
||||
@ -1822,7 +1879,9 @@ public final class GroupCallParticipantsContext {
|
||||
var updatedParticipants = strongSelf.stateValue.state.participants
|
||||
var indexMap: [PeerId: Int] = [:]
|
||||
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
|
||||
|
||||
@ -2000,7 +2059,7 @@ public final class GroupCallParticipantsContext {
|
||||
|
||||
for participantUpdate in update.participantUpdates {
|
||||
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)
|
||||
updatedTotalCount = max(0, updatedTotalCount - 1)
|
||||
strongSelf.memberEventsPipe.putNext(MemberEvent(peerId: participantUpdate.peerId, canUnmute: false, joined: false))
|
||||
@ -2017,7 +2076,7 @@ public final class GroupCallParticipantsContext {
|
||||
var previousActivityRank: Int?
|
||||
var previousMuteState: GroupCallParticipantsContext.Participant.MuteState?
|
||||
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
|
||||
previousActivityTimestamp = updatedParticipants[index].activityTimestamp
|
||||
previousActivityRank = updatedParticipants[index].activityRank
|
||||
@ -2054,7 +2113,8 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
}
|
||||
let participant = Participant(
|
||||
peer: peer,
|
||||
id: .peer(peer.id),
|
||||
peer: EnginePeer(peer),
|
||||
ssrc: participantUpdate.ssrc,
|
||||
videoDescription: participantUpdate.videoDescription,
|
||||
presentationDescription: participantUpdate.presentationDescription,
|
||||
@ -2158,7 +2218,7 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
|
||||
for participant in self.stateValue.state.participants {
|
||||
if participant.peer.id == peerId {
|
||||
if participant.id == .peer(peerId) {
|
||||
var raiseHandEqual: Bool = true
|
||||
if let raiseHand = raiseHand {
|
||||
raiseHandEqual = (participant.raiseHandRating == nil && !raiseHand) ||
|
||||
@ -2744,14 +2804,14 @@ func _internal_updatedCurrentPeerGroupCall(postbox: Postbox, network: Network, a
|
||||
private func mergeAndSortParticipants(current currentParticipants: [GroupCallParticipantsContext.Participant], with updatedParticipants: [GroupCallParticipantsContext.Participant], sortAscending: Bool) -> [GroupCallParticipantsContext.Participant] {
|
||||
var mergedParticipants = currentParticipants
|
||||
|
||||
var existingParticipantIndices: [PeerId: Int] = [:]
|
||||
var existingParticipantIndices: [GroupCallParticipantsContext.Participant.Id: Int] = [:]
|
||||
for i in 0 ..< mergedParticipants.count {
|
||||
existingParticipantIndices[mergedParticipants[i].peer.id] = i
|
||||
existingParticipantIndices[mergedParticipants[i].id] = i
|
||||
}
|
||||
for participant in updatedParticipants {
|
||||
if let _ = existingParticipantIndices[participant.peer.id] {
|
||||
if let _ = existingParticipantIndices[participant.id] {
|
||||
} else {
|
||||
existingParticipantIndices[participant.peer.id] = mergedParticipants.count
|
||||
existingParticipantIndices[participant.id] = mergedParticipants.count
|
||||
mergedParticipants.append(participant)
|
||||
}
|
||||
}
|
||||
@ -2942,7 +3002,8 @@ extension GroupCallParticipantsContext.Participant {
|
||||
let joinedVideo = (flags & (1 << 15)) != 0
|
||||
|
||||
self.init(
|
||||
peer: peer,
|
||||
id: .peer(peer.id),
|
||||
peer: EnginePeer(peer),
|
||||
ssrc: ssrc,
|
||||
videoDescription: videoDescription,
|
||||
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)
|
||||
}
|
||||
|
||||
public func groupCall(peerId: PeerId?, myPeerId: PeerId, id: Int64, reference: InternalGroupCallReference, state: GroupCallParticipantsContext.State, previousServiceState: GroupCallParticipantsContext.ServiceState?) -> GroupCallParticipantsContext {
|
||||
return GroupCallParticipantsContext(account: self.account, peerId: peerId, myPeerId: myPeerId, id: id, reference: reference, state: state, previousServiceState: previousServiceState)
|
||||
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, e2eContext: e2eContext)
|
||||
}
|
||||
|
||||
public func serverTime() -> Signal<Int64, NoError> {
|
||||
|
@ -172,7 +172,9 @@ func _internal_joinCallLinkInformation(_ hash: String, account: Account) -> Sign
|
||||
}
|
||||
var members: [EnginePeer] = []
|
||||
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))
|
||||
}
|
||||
@ -198,7 +200,9 @@ func _internal_joinCallInvitationInformation(account: Account, messageId: Messag
|
||||
}
|
||||
var members: [EnginePeer] = []
|
||||
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))
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TdCallParticipant : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSData *publicKey;
|
||||
@property (nonatomic, strong, readonly) NSString *internalId;
|
||||
@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
|
||||
|
||||
@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (NSArray<NSData *> *)takeOutgoingBroadcastBlocks;
|
||||
- (NSData *)emojiState;
|
||||
- (NSArray<NSNumber *> *)participantIds;
|
||||
- (NSArray<TdCallParticipant *> *)participants;
|
||||
|
||||
- (void)applyBlock:(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
|
||||
|
||||
- (nullable instancetype)initWithPublicKey:(NSData *)publicKey userId:(int64_t)userId {
|
||||
- (nullable instancetype)initWithInternalId:(NSString *)internalId userId:(int64_t)userId {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_publicKey = publicKey;
|
||||
_internalId = internalId;
|
||||
_userId = userId;
|
||||
}
|
||||
return self;
|
||||
@ -176,17 +176,18 @@ static NSString *hexStringFromData(NSData *data) {
|
||||
return outEmojiHash;
|
||||
}
|
||||
|
||||
- (NSArray<NSNumber *> *)participantIds {
|
||||
- (NSArray<TdCallParticipant *> *)participants {
|
||||
auto result = tde2e_api::call_get_state(_callId);
|
||||
if (!result.is_ok()) {
|
||||
return @[];
|
||||
}
|
||||
auto state = result.value();
|
||||
NSMutableArray<NSNumber *> *participantIds = [[NSMutableArray alloc] init];
|
||||
NSMutableArray<TdCallParticipant *> *participants = [[NSMutableArray alloc] init];
|
||||
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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user