mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit 'bed5daf934b7f52962d706f6f72ff8ae123a3d13'
This commit is contained in:
commit
a67b70d22e
@ -297,7 +297,7 @@ public protocol PresentationGroupCall: class {
|
|||||||
func setVolume(peerId: PeerId, volume: Int32, sync: Bool)
|
func setVolume(peerId: PeerId, volume: Int32, sync: Bool)
|
||||||
func setCurrentAudioOutput(_ output: AudioSessionOutput)
|
func setCurrentAudioOutput(_ output: AudioSessionOutput)
|
||||||
|
|
||||||
func updateMuteState(peerId: PeerId, isMuted: Bool)
|
func updateMuteState(peerId: PeerId, isMuted: Bool) -> GroupCallParticipantsContext.Participant.MuteState?
|
||||||
|
|
||||||
func invitePeer(_ peerId: PeerId) -> Bool
|
func invitePeer(_ peerId: PeerId) -> Bool
|
||||||
func removedPeer(_ peerId: PeerId)
|
func removedPeer(_ peerId: PeerId)
|
||||||
|
@ -438,6 +438,10 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasAdditionalActions: Bool {
|
||||||
|
return self.additionalActionsNode != nil
|
||||||
|
}
|
||||||
|
|
||||||
init(presentationData: PresentationData, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void, displayTextSelectionTip: Bool, blurBackground: Bool) {
|
init(presentationData: PresentationData, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void, displayTextSelectionTip: Bool, blurBackground: Bool) {
|
||||||
self.blurBackground = blurBackground
|
self.blurBackground = blurBackground
|
||||||
self.shadowNode = ASImageNode()
|
self.shadowNode = ASImageNode()
|
||||||
@ -534,4 +538,14 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
|||||||
func animateIn() {
|
func animateIn() {
|
||||||
self.textSelectionTipNode?.animateIn()
|
self.textSelectionTipNode?.animateIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func animateOut(offset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
guard let additionalActionsNode = self.additionalActionsNode else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.animatePosition(node: additionalActionsNode, to: CGPoint(x: 0.0, y: offset / 2.0), additive: true)
|
||||||
|
additionalActionsNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||||
|
additionalActionsNode.layer.animateScale(from: 1.0, to: 0.75, duration: 0.15, removeOnCompletion: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1377,15 +1377,28 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if let previousActionsContainerNode = previousActionsContainerNode {
|
if let previousActionsContainerNode = previousActionsContainerNode {
|
||||||
if transition.isAnimated {
|
if transition.isAnimated {
|
||||||
transition.updateTransformScale(node: previousActionsContainerNode, scale: 0.1)
|
if previousActionsContainerNode.hasAdditionalActions && !self.actionsContainerNode.hasAdditionalActions {
|
||||||
previousActionsContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousActionsContainerNode] _ in
|
var initialFrame = self.actionsContainerNode.frame
|
||||||
previousActionsContainerNode?.removeFromSupernode()
|
let delta = (previousActionsContainerNode.frame.height - self.actionsContainerNode.frame.height)
|
||||||
})
|
initialFrame.origin.y = self.actionsContainerNode.frame.minY + previousActionsContainerNode.frame.height - self.actionsContainerNode.frame.height
|
||||||
|
transition.animateFrame(node: self.actionsContainerNode, from: initialFrame)
|
||||||
transition.animateTransformScale(node: self.actionsContainerNode, from: 0.1)
|
transition.animatePosition(node: previousActionsContainerNode, to: CGPoint(x: 0.0, y: -delta), removeOnCompletion: false, additive: true)
|
||||||
if transition.isAnimated {
|
previousActionsContainerNode.animateOut(offset: delta, transition: transition)
|
||||||
|
|
||||||
|
previousActionsContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousActionsContainerNode] _ in
|
||||||
|
previousActionsContainerNode?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
} else {
|
||||||
|
transition.updateTransformScale(node: previousActionsContainerNode, scale: 0.1)
|
||||||
|
previousActionsContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousActionsContainerNode] _ in
|
||||||
|
previousActionsContainerNode?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
|
||||||
|
transition.animateTransformScale(node: self.actionsContainerNode, from: 0.1)
|
||||||
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1316,7 +1316,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateMuteState(peerId: PeerId, isMuted: Bool) {
|
public func updateMuteState(peerId: PeerId, isMuted: Bool) -> GroupCallParticipantsContext.Participant.MuteState? {
|
||||||
let canThenUnmute: Bool
|
let canThenUnmute: Bool
|
||||||
if isMuted {
|
if isMuted {
|
||||||
var mutedByYou = false
|
var mutedByYou = false
|
||||||
@ -1334,14 +1334,20 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
mutedByYou = true
|
mutedByYou = true
|
||||||
canThenUnmute = true
|
canThenUnmute = true
|
||||||
}
|
}
|
||||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: isMuted ? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canThenUnmute, mutedByYou: mutedByYou) : nil, volume: nil)
|
let muteState = isMuted ? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canThenUnmute, mutedByYou: mutedByYou) : nil
|
||||||
|
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil)
|
||||||
|
return muteState
|
||||||
} else {
|
} else {
|
||||||
if peerId == self.accountContext.account.peerId {
|
if peerId == self.accountContext.account.peerId {
|
||||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil)
|
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil)
|
||||||
|
return nil
|
||||||
} else if self.stateValue.canManageCall || self.stateValue.adminIds.contains(self.accountContext.account.peerId) {
|
} else if self.stateValue.canManageCall || self.stateValue.adminIds.contains(self.accountContext.account.peerId) {
|
||||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), volume: nil)
|
let muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false)
|
||||||
|
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil)
|
||||||
|
return muteState
|
||||||
} else {
|
} else {
|
||||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil)
|
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,6 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
private final class Interaction {
|
private final class Interaction {
|
||||||
let updateIsMuted: (PeerId, Bool) -> Void
|
let updateIsMuted: (PeerId, Bool) -> Void
|
||||||
let openPeer: (PeerId) -> Void
|
|
||||||
let openInvite: () -> Void
|
let openInvite: () -> Void
|
||||||
let peerContextAction: (PeerEntry, ASDisplayNode, ContextGesture?) -> Void
|
let peerContextAction: (PeerEntry, ASDisplayNode, ContextGesture?) -> Void
|
||||||
let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
||||||
@ -146,13 +145,11 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
init(
|
init(
|
||||||
updateIsMuted: @escaping (PeerId, Bool) -> Void,
|
updateIsMuted: @escaping (PeerId, Bool) -> Void,
|
||||||
openPeer: @escaping (PeerId) -> Void,
|
|
||||||
openInvite: @escaping () -> Void,
|
openInvite: @escaping () -> Void,
|
||||||
peerContextAction: @escaping (PeerEntry, ASDisplayNode, ContextGesture?) -> Void,
|
peerContextAction: @escaping (PeerEntry, ASDisplayNode, ContextGesture?) -> Void,
|
||||||
setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void
|
setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void
|
||||||
) {
|
) {
|
||||||
self.updateIsMuted = updateIsMuted
|
self.updateIsMuted = updateIsMuted
|
||||||
self.openPeer = openPeer
|
|
||||||
self.openInvite = openInvite
|
self.openInvite = openInvite
|
||||||
self.peerContextAction = peerContextAction
|
self.peerContextAction = peerContextAction
|
||||||
self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions
|
self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions
|
||||||
@ -369,13 +366,11 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
let revealOptions: [VoiceChatParticipantItem.RevealOption] = []
|
let revealOptions: [VoiceChatParticipantItem.RevealOption] = []
|
||||||
|
|
||||||
return VoiceChatParticipantItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, presence: peerEntry.presence, text: text, icon: icon, enabled: true, selectable: peer.id != context.account.peerId, getAudioLevel: { return interaction.getAudioLevel(peer.id) }, revealOptions: revealOptions, revealed: peerEntry.revealed, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
return VoiceChatParticipantItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, presence: peerEntry.presence, text: text, icon: icon, enabled: true, selectable: peer.id != context.account.peerId || peerEntry.canManageCall, getAudioLevel: { return interaction.getAudioLevel(peer.id) }, revealOptions: revealOptions, revealed: peerEntry.revealed, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||||
interaction.setPeerIdWithRevealedOptions(peerId, fromPeerId)
|
interaction.setPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||||
}, action: {
|
}, action: { node in
|
||||||
interaction.openPeer(peer.id)
|
interaction.peerContextAction(peerEntry, node, nil)
|
||||||
}, contextAction: peer.id == context.account.peerId ? nil : { node, gesture in
|
}, contextAction: nil)
|
||||||
interaction.peerContextAction(peerEntry, node, gesture)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -563,16 +558,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
self.itemInteraction = Interaction(
|
self.itemInteraction = Interaction(
|
||||||
updateIsMuted: { [weak self] peerId, isMuted in
|
updateIsMuted: { [weak self] peerId, isMuted in
|
||||||
self?.call.updateMuteState(peerId: peerId, isMuted: isMuted)
|
let _ = self?.call.updateMuteState(peerId: peerId, isMuted: isMuted)
|
||||||
}, openPeer: { [weak self] peerId in
|
|
||||||
if let strongSelf = self, let navigationController = strongSelf.controller?.parentNavigationController {
|
|
||||||
let context = strongSelf.context
|
|
||||||
strongSelf.controller?.dismiss(completion: {
|
|
||||||
Queue.mainQueue().justDispatch {
|
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), keepStack: .always, purposefulAction: {}, peekData: nil))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, openInvite: { [weak self] in
|
}, openInvite: { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -809,144 +795,157 @@ public final class VoiceChatController: ViewController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let peer = entry.peer
|
let muteStatePromise = Promise<GroupCallParticipantsContext.Participant.MuteState?>(entry.muteState)
|
||||||
|
|
||||||
var items: [ContextMenuItem] = []
|
let itemsForEntry: (PeerEntry, GroupCallParticipantsContext.Participant.MuteState?) -> [ContextMenuItem] = { entry, muteState in
|
||||||
|
var items: [ContextMenuItem] = []
|
||||||
if peer.id != strongSelf.context.account.peerId {
|
|
||||||
if let muteState = entry.muteState, muteState.mutedByYou {
|
let peer = entry.peer
|
||||||
|
if let muteState = muteState, !muteState.canUnmute || muteState.mutedByYou {
|
||||||
} else {
|
} else {
|
||||||
items.append(.custom(VoiceChatVolumeContextItem(value: entry.volume.flatMap { CGFloat($0) / 10000.0 } ?? 1.0, valueChanged: { newValue, finished in
|
items.append(.custom(VoiceChatVolumeContextItem(value: entry.volume.flatMap { CGFloat($0) / 10000.0 } ?? 1.0, valueChanged: { newValue, finished in
|
||||||
if finished && newValue.isZero {
|
if finished && newValue.isZero {
|
||||||
|
let updatedMuteState = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
||||||
|
muteStatePromise.set(.single(updatedMuteState))
|
||||||
|
} else {
|
||||||
|
strongSelf.call.setVolume(peerId: peer.id, volume: Int32(newValue * 10000), sync: finished)
|
||||||
}
|
}
|
||||||
strongSelf.call.setVolume(peerId: peer.id, volume: Int32(newValue * 10000), sync: finished)
|
|
||||||
}), true))
|
}), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let callState = strongSelf.callState, (callState.canManageCall || callState.adminIds.contains(strongSelf.context.account.peerId)) {
|
if peer.id != strongSelf.context.account.peerId {
|
||||||
if callState.adminIds.contains(peer.id) {
|
if let callState = strongSelf.callState, (callState.canManageCall || callState.adminIds.contains(strongSelf.context.account.peerId)) {
|
||||||
if let _ = entry.muteState {
|
if callState.adminIds.contains(peer.id) {
|
||||||
|
if let _ = muteState {
|
||||||
|
} else {
|
||||||
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MutePeer, icon: { theme in
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Mute"), color: theme.actionSheet.primaryTextColor)
|
||||||
|
}, action: { _, f in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
||||||
|
f(.default)
|
||||||
|
})))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MutePeer, icon: { theme in
|
if let muteState = muteState, !muteState.canUnmute {
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Mute"), color: theme.actionSheet.primaryTextColor)
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_UnmutePeer, icon: { theme in
|
||||||
}, action: { _, f in
|
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Unmute"), color: theme.actionSheet.primaryTextColor)
|
||||||
guard let strongSelf = self else {
|
}, action: { _, f in
|
||||||
return
|
guard let strongSelf = self else {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
|
||||||
f(.default)
|
let _ = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: false)
|
||||||
})))
|
f(.default)
|
||||||
|
})))
|
||||||
|
} else {
|
||||||
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MutePeer, icon: { theme in
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Mute"), color: theme.actionSheet.primaryTextColor)
|
||||||
|
}, action: { _, f in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
||||||
|
f(.default)
|
||||||
|
})))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let muteState = entry.muteState, !muteState.canUnmute {
|
if let muteState = muteState, muteState.mutedByYou {
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_UnmutePeer, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_UnmuteForMe, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Unmute"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Unmute"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.call.updateMuteState(peerId: peer.id, isMuted: false)
|
let _ = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: false)
|
||||||
f(.default)
|
f(.default)
|
||||||
})))
|
})))
|
||||||
} else {
|
} else {
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MutePeer, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MuteForMe, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Mute"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Mute"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
let _ = strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
||||||
f(.default)
|
f(.default)
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if let muteState = entry.muteState, muteState.mutedByYou {
|
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_UnmuteForMe, icon: { theme in
|
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Unmute"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
}, action: { _, f in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.call.updateMuteState(peerId: peer.id, isMuted: false)
|
|
||||||
f(.default)
|
|
||||||
})))
|
|
||||||
} else {
|
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_MuteForMe, icon: { theme in
|
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Call/Context Menu/Mute"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
}, action: { _, f in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.call.updateMuteState(peerId: peer.id, isMuted: true)
|
|
||||||
f(.default)
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_OpenChat, icon: { theme in
|
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
}, action: { _, f in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.itemInteraction?.openPeer(peer.id)
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_OpenChat, icon: { theme in
|
||||||
f(.default)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.actionSheet.primaryTextColor)
|
||||||
})))
|
}, action: { _, f in
|
||||||
|
guard let strongSelf = self, let navigationController = strongSelf.controller?.parentNavigationController else {
|
||||||
if let callState = strongSelf.callState, (callState.canManageCall && !callState.adminIds.contains(peer.id)) {
|
return
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_RemovePeer, textColor: .destructive, icon: { theme in
|
}
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor)
|
|
||||||
}, action: { [weak self] c, _ in
|
let context = strongSelf.context
|
||||||
c.dismiss(completion: {
|
strongSelf.controller?.dismiss(completion: {
|
||||||
guard let strongSelf = self else {
|
Queue.mainQueue().justDispatch {
|
||||||
return
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer.id), keepStack: .always, purposefulAction: {}, peekData: nil))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme))
|
|
||||||
var items: [ActionSheetItem] = []
|
f(.default)
|
||||||
|
})))
|
||||||
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: peer, chatPeer: peer, action: .removeFromGroup, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
|
|
||||||
|
if let callState = strongSelf.callState, (callState.canManageCall && !callState.adminIds.contains(peer.id)) {
|
||||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak actionSheet] in
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_RemovePeer, textColor: .destructive, icon: { theme in
|
||||||
actionSheet?.dismissAnimated()
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor)
|
||||||
|
}, action: { [weak self] c, _ in
|
||||||
|
c.dismiss(completion: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = strongSelf.context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: strongSelf.context.account, peerId: strongSelf.call.peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)).start()
|
|
||||||
strongSelf.call.removedPeer(peer.id)
|
|
||||||
|
|
||||||
strongSelf.presentUndoOverlay(content: .banned(text: strongSelf.presentationData.strings.VoiceChat_RemovedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), action: { _ in return false })
|
|
||||||
}))
|
|
||||||
|
|
||||||
actionSheet.setItemGroups([
|
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme))
|
||||||
ActionSheetItemGroup(items: items),
|
var items: [ActionSheetItem] = []
|
||||||
ActionSheetItemGroup(items: [
|
|
||||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: peer, chatPeer: peer, action: .removeFromGroup, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
|
||||||
actionSheet?.dismissAnimated()
|
|
||||||
})
|
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak actionSheet] in
|
||||||
|
actionSheet?.dismissAnimated()
|
||||||
|
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = strongSelf.context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: strongSelf.context.account, peerId: strongSelf.call.peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)).start()
|
||||||
|
strongSelf.call.removedPeer(peer.id)
|
||||||
|
|
||||||
|
strongSelf.presentUndoOverlay(content: .banned(text: strongSelf.presentationData.strings.VoiceChat_RemovedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), action: { _ in return false })
|
||||||
|
}))
|
||||||
|
|
||||||
|
actionSheet.setItemGroups([
|
||||||
|
ActionSheetItemGroup(items: items),
|
||||||
|
ActionSheetItemGroup(items: [
|
||||||
|
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||||
|
actionSheet?.dismissAnimated()
|
||||||
|
})
|
||||||
|
])
|
||||||
])
|
])
|
||||||
])
|
strongSelf.controller?.present(actionSheet, in: .window(.root))
|
||||||
strongSelf.controller?.present(actionSheet, in: .window(.root))
|
})
|
||||||
})
|
})))
|
||||||
})))
|
}
|
||||||
}
|
}
|
||||||
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
guard !items.isEmpty else {
|
let items = muteStatePromise.get()
|
||||||
return
|
|> map { muteState -> [ContextMenuItem] in
|
||||||
|
return itemsForEntry(entry, muteState)
|
||||||
}
|
}
|
||||||
|
|
||||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme), source: .extracted(VoiceChatContextExtractedContentSource(controller: controller, sourceNode: sourceNode, keepInPlace: false, blurBackground: true)), items: .single(items), reactionItems: [], gesture: gesture)
|
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme), source: .extracted(VoiceChatContextExtractedContentSource(controller: controller, sourceNode: sourceNode, keepInPlace: false, blurBackground: true)), items: items, reactionItems: [], gesture: gesture)
|
||||||
strongSelf.controller?.presentInGlobalOverlay(contextController)
|
strongSelf.controller?.presentInGlobalOverlay(contextController)
|
||||||
}, setPeerIdWithRevealedOptions: { peerId, _ in
|
}, setPeerIdWithRevealedOptions: { peerId, _ in
|
||||||
updateState { state in
|
updateState { state in
|
||||||
|
@ -71,10 +71,10 @@ final class VoiceChatParticipantItem: ListViewItem {
|
|||||||
let revealOptions: [RevealOption]
|
let revealOptions: [RevealOption]
|
||||||
let revealed: Bool?
|
let revealed: Bool?
|
||||||
let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
||||||
let action: (() -> Void)?
|
let action: ((ASDisplayNode) -> Void)?
|
||||||
let contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
|
let contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
|
||||||
|
|
||||||
public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, context: AccountContext, peer: Peer, presence: PeerPresence?, text: ParticipantText, icon: Icon, enabled: Bool, selectable: Bool, getAudioLevel: (() -> Signal<Float, NoError>)?, revealOptions: [RevealOption], revealed: Bool?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil) {
|
public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, context: AccountContext, peer: Peer, presence: PeerPresence?, text: ParticipantText, icon: Icon, enabled: Bool, selectable: Bool, getAudioLevel: (() -> Signal<Float, NoError>)?, revealOptions: [RevealOption], revealed: Bool?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, action: ((ASDisplayNode) -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil) {
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.dateTimeFormat = dateTimeFormat
|
self.dateTimeFormat = dateTimeFormat
|
||||||
self.nameDisplayOrder = nameDisplayOrder
|
self.nameDisplayOrder = nameDisplayOrder
|
||||||
@ -131,9 +131,8 @@ final class VoiceChatParticipantItem: ListViewItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func selected(listView: ListView){
|
public func selected(listView: ListView) {
|
||||||
listView.clearHighlightAnimated(true)
|
listView.clearHighlightAnimated(true)
|
||||||
self.action?()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,6 +281,11 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
deinit {
|
deinit {
|
||||||
self.audioLevelDisposable.dispose()
|
self.audioLevelDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func selected() {
|
||||||
|
super.selected()
|
||||||
|
self.layoutParams?.0.action?(self.contextSourceNode)
|
||||||
|
}
|
||||||
|
|
||||||
func asyncLayout() -> (_ item: VoiceChatParticipantItem, _ params: ListViewItemLayoutParams, _ first: Bool, _ last: Bool) -> (ListViewItemNodeLayout, (Bool, Bool) -> Void) {
|
func asyncLayout() -> (_ item: VoiceChatParticipantItem, _ params: ListViewItemLayoutParams, _ first: Bool, _ last: Bool) -> (ListViewItemNodeLayout, (Bool, Bool) -> Void) {
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
|
@ -1093,7 +1093,6 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?, volume: Int32?) {
|
public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?, volume: Int32?) {
|
||||||
|
|
||||||
if let current = self.stateValue.overlayState.pendingMuteStateChanges[peerId] {
|
if let current = self.stateValue.overlayState.pendingMuteStateChanges[peerId] {
|
||||||
if current.state == muteState {
|
if current.state == muteState {
|
||||||
return
|
return
|
||||||
|
@ -870,7 +870,7 @@ final class ChatEmptyNode: ASDisplayNode {
|
|||||||
self.addSubnode(node)
|
self.addSubnode(node)
|
||||||
contentTransition = .immediate
|
contentTransition = .immediate
|
||||||
}
|
}
|
||||||
self.isUserInteractionEnabled = [.regular, .peerNearby].contains(contentType)
|
self.isUserInteractionEnabled = [.peerNearby, .greeting].contains(contentType)
|
||||||
|
|
||||||
let displayRect = CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top - insets.bottom))
|
let displayRect = CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top - insets.bottom))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user