[WIP] Conference calls

This commit is contained in:
Isaac
2025-01-28 20:50:52 +04:00
parent 39c96712bd
commit 846e495d12
20 changed files with 875 additions and 336 deletions

View File

@@ -128,6 +128,7 @@ final class VideoChatParticipantsComponent: Component {
let call: VideoChatCall
let participants: Participants?
let invitedPeers: [EnginePeer]
let speakingParticipants: Set<EnginePeer.Id>
let expandedVideoState: ExpandedVideoState?
let maxVideoQuality: Int
@@ -147,6 +148,7 @@ final class VideoChatParticipantsComponent: Component {
init(
call: VideoChatCall,
participants: Participants?,
invitedPeers: [EnginePeer],
speakingParticipants: Set<EnginePeer.Id>,
expandedVideoState: ExpandedVideoState?,
maxVideoQuality: Int,
@@ -165,6 +167,7 @@ final class VideoChatParticipantsComponent: Component {
) {
self.call = call
self.participants = participants
self.invitedPeers = invitedPeers
self.speakingParticipants = speakingParticipants
self.expandedVideoState = expandedVideoState
self.maxVideoQuality = maxVideoQuality
@@ -189,6 +192,9 @@ final class VideoChatParticipantsComponent: Component {
if lhs.participants != rhs.participants {
return false
}
if lhs.invitedPeers != rhs.invitedPeers {
return false
}
if lhs.speakingParticipants != rhs.speakingParticipants {
return false
}
@@ -1183,50 +1189,37 @@ final class VideoChatParticipantsComponent: Component {
let clippedVisibleListItemRange = itemLayout.visibleListItemRange(for: clippedScrollViewBounds)
if visibleListItemRange.maxIndex >= visibleListItemRange.minIndex {
for i in visibleListItemRange.minIndex ... visibleListItemRange.maxIndex {
let participant = self.listParticipants[i]
validListItemIds.append(participant.peer.id)
if i >= clippedVisibleListItemRange.minIndex && i <= clippedVisibleListItemRange.maxIndex {
visibleParticipants.append(participant.peer.id)
}
var itemTransition = transition
let itemView: ListItem
if let current = self.listItemViews[participant.peer.id] {
itemView = current
} else {
itemTransition = itemTransition.withAnimation(.none)
itemView = ListItem()
self.listItemViews[participant.peer.id] = itemView
}
let itemFrame = itemLayout.listItemFrame(at: i)
let subtitle: PeerListItemComponent.Subtitle
if participant.peer.id == component.call.accountContext.account.peerId {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_You, color: .accent)
} else if component.speakingParticipants.contains(participant.peer.id) {
if let volume = participant.volume, volume / 100 != 100 {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeakingVolume("\(volume / 100)%").string, color: .constructive)
let participantPeerId: EnginePeer.Id
let peerItemComponent: PeerListItemComponent
if i < self.listParticipants.count {
let participant = self.listParticipants[i]
participantPeerId = participant.peer.id
let subtitle: PeerListItemComponent.Subtitle
if participant.peer.id == component.call.accountContext.account.peerId {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_You, color: .accent)
} else if component.speakingParticipants.contains(participant.peer.id) {
if let volume = participant.volume, volume / 100 != 100 {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeakingVolume("\(volume / 100)%").string, color: .constructive)
} else {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeaking, color: .constructive)
}
} else if let about = participant.about, !about.isEmpty {
subtitle = PeerListItemComponent.Subtitle(text: about, color: .neutral)
} else {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusSpeaking, color: .constructive)
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusListening, color: .neutral)
}
} else if let about = participant.about, !about.isEmpty {
subtitle = PeerListItemComponent.Subtitle(text: about, color: .neutral)
} else {
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusListening, color: .neutral)
}
let rightAccessoryComponent: AnyComponent<Empty> = AnyComponent(VideoChatParticipantStatusComponent(
muteState: participant.muteState,
hasRaiseHand: participant.hasRaiseHand,
isSpeaking: component.speakingParticipants.contains(participant.peer.id),
theme: component.theme
))
let _ = itemView.view.update(
transition: itemTransition,
component: AnyComponent(PeerListItemComponent(
let rightAccessoryComponent: AnyComponent<Empty> = AnyComponent(VideoChatParticipantStatusComponent(
muteState: participant.muteState,
hasRaiseHand: participant.hasRaiseHand,
isSpeaking: component.speakingParticipants.contains(participant.peer.id),
theme: component.theme
))
peerItemComponent = PeerListItemComponent(
context: component.call.accountContext,
theme: component.theme,
strings: component.strings,
@@ -1263,7 +1256,63 @@ final class VideoChatParticipantsComponent: Component {
}
component.openParticipantContextMenu(peer.id, sourceView, gesture)
}
)),
)
} else {
let invitedPeer = component.invitedPeers[i - self.listParticipants.count]
participantPeerId = invitedPeer.id
let subtitle: PeerListItemComponent.Subtitle
subtitle = PeerListItemComponent.Subtitle(text: component.strings.VoiceChat_StatusInvited, color: .neutral)
peerItemComponent = PeerListItemComponent(
context: component.call.accountContext,
theme: component.theme,
strings: component.strings,
style: .generic,
sideInset: 0.0,
title: invitedPeer.displayTitle(strings: component.strings, displayOrder: .firstLast),
avatarComponent: AnyComponent(VideoChatParticipantAvatarComponent(
call: component.call,
peer: invitedPeer,
myPeerId: component.participants?.myPeerId ?? component.call.accountContext.account.peerId,
isSpeaking: false,
theme: component.theme
)),
peer: invitedPeer,
subtitle: subtitle,
subtitleAccessory: .none,
presence: nil,
rightAccessoryComponent: nil,
selectionState: .none,
hasNext: false,
extractedTheme: PeerListItemComponent.ExtractedTheme(
inset: 2.0,
background: UIColor(white: 0.1, alpha: 1.0)
),
action: nil,
contextAction: nil
)
}
validListItemIds.append(participantPeerId)
if i >= clippedVisibleListItemRange.minIndex && i <= clippedVisibleListItemRange.maxIndex {
visibleParticipants.append(participantPeerId)
}
var itemTransition = transition
let itemView: ListItem
if let current = self.listItemViews[participantPeerId] {
itemView = current
} else {
itemTransition = itemTransition.withAnimation(.none)
itemView = ListItem()
self.listItemViews[participantPeerId] = itemView
}
let _ = itemView.view.update(
transition: itemTransition,
component: AnyComponent(peerItemComponent),
environment: {},
containerSize: itemFrame.size
)
@@ -1363,12 +1412,6 @@ final class VideoChatParticipantsComponent: Component {
isPresentation: participant.isPresentation
))
}
/*for participant in self.listParticipants {
thumbnailParticipants.append(VideoChatExpandedParticipantThumbnailsComponent.Participant(
participant: participant,
isPresentation: false
))
}*/
let expandedControlsAlpha: CGFloat = (expandedVideoState.isUIHidden || self.isPinchToZoomActive) ? 0.0 : 1.0
let expandedThumbnailsAlpha: CGFloat = expandedControlsAlpha
@@ -1770,7 +1813,7 @@ final class VideoChatParticipantsComponent: Component {
expandedInsets: component.expandedInsets,
safeInsets: component.safeInsets,
gridItemCount: gridParticipants.count,
listItemCount: listParticipants.count,
listItemCount: listParticipants.count + component.invitedPeers.count,
listItemHeight: measureListItemSize.height,
listTrailingItemHeight: inviteListItemSize.height
)