Voice Chat fixes

This commit is contained in:
Ilya Laktyushin 2021-03-13 03:14:31 +04:00
parent 73657fc155
commit 67ac8b10c3
18 changed files with 4033 additions and 3939 deletions

View File

@ -6263,3 +6263,6 @@ Sorry for the inconvenience.";
"VoiceChat.CancelSpeakRequest" = "Cancel Request to Speak";
"VoiceChat.RemovePeerConfirmationChannel" = "Are you sure you want to remove %@ from the channel?";
"VoiceChat.RemoveAndBanPeerConfirmation" = "“Do you want to remove %1$@ from the voice chat and ban them in %2$@?";
"Notification.VoiceChatStartedChannel" = "Voice chat started";

View File

@ -0,0 +1,21 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
final class CameraModeNode: ASDisplayNode {
enum Mode {
case photo
case video
case scan
}
override init() {
super.init()
}
func update(mode: Mode, transition: ContainedViewLayoutTransition) {
}
}

View File

@ -1339,17 +1339,21 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
override public func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.chatListDisplayNode.containerNode.updateEnableAdjacentFilterLoading(false)
func dismissAllUndoControllers() {
self.forEachController({ controller in
if let controller = controller as? UndoOverlayController {
controller.dismissWithCommitAction()
}
return true
})
}
override public func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.chatListDisplayNode.containerNode.updateEnableAdjacentFilterLoading(false)
self.dismissAllUndoControllers()
self.featuredFiltersDisposable.set(nil)
}

View File

@ -403,6 +403,8 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
private let filterBecameEmpty: (ChatListFilter?) -> Void
private let filterEmptyAction: (ChatListFilter?) -> Void
fileprivate var onFilterSwitch: (() -> Void)?
private var presentationData: PresentationData
private var itemNodes: [ChatListFilterTabEntryId: ChatListContainerItemNode] = [:]
@ -607,6 +609,8 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
@objc private func panGesture(_ recognizer: UIPanGestureRecognizer) {
switch recognizer.state {
case .began:
self.onFilterSwitch?()
self.transitionFractionOffset = 0.0
if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout, let itemNode = self.itemNodes[self.selectedId] {
for (id, itemNode) in self.itemNodes {
@ -792,6 +796,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
guard let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout else {
return
}
self.onFilterSwitch?()
if id != self.selectedId, let index = self.availableFilters.firstIndex(where: { $0.id == id }) {
if let itemNode = self.itemNodes[id] {
self.selectedId = id
@ -1057,6 +1062,12 @@ final class ChatListControllerNode: ASDisplayNode {
}
strongSelf.emptyListAction?()
}
self.containerNode.onFilterSwitch = { [weak self] in
if let strongSelf = self {
strongSelf.controller?.dismissAllUndoControllers()
}
}
}
override func didLoad() {

View File

@ -142,14 +142,14 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
text?.0 += "\n\n\(strings.Conversation_AlsoClearCacheTitle)"
}
case .removeFromGroup:
text = strings.VoiceChat_RemovePeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
text = strings.VoiceChat_RemoveAndBanPeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder), chatPeer.displayTitle(strings: strings, displayOrder: nameOrder))
case .removeFromChannel:
text = strings.VoiceChat_RemovePeerConfirmationChannel(peer.displayTitle(strings: strings, displayOrder: nameOrder))
default:
break
}
if let text = text {
var formattedAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: textFont, textColor: theme.primaryTextColor))
let formattedAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: textFont, textColor: theme.primaryTextColor))
for (_, range) in text.1 {
formattedAttributedText.addAttribute(.font, value: boldFont, range: range)
}

View File

@ -346,7 +346,13 @@ final class JoinLinkPreviewControllerNode: ViewControllerTracingNode, UIScrollVi
}
}
private var animatingOut = false
func animateOut(completion: (() -> Void)? = nil) {
guard !self.animatingOut else {
return
}
self.animatingOut = true
if self.contentNode != nil {
var dimCompleted = false
var offsetCompleted = false
@ -354,6 +360,7 @@ final class JoinLinkPreviewControllerNode: ViewControllerTracingNode, UIScrollVi
let internalCompletion: () -> Void = { [weak self] in
if let strongSelf = self, dimCompleted && offsetCompleted {
strongSelf.dismiss?()
strongSelf.animatingOut = true
}
completion?()
}

View File

@ -639,7 +639,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
}
}
var animatingOut = false
private var animatingOut = false
var outCompletion: (() -> Void)?
func animateOut(shared: Bool, completion: @escaping () -> Void) {
guard !self.animatingOut else {

View File

@ -445,6 +445,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private var markedAsCanBeRemoved = false
private let wasRemoved = Promise<Bool>(false)
private var leaving = false
private var stateValue: PresentationGroupCallState {
didSet {
@ -1391,7 +1392,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
}
if !participants.contains(where: { $0.peer.id == myPeerId }) {
if !participants.contains(where: { $0.peer.id == myPeerId }) && !strongSelf.leaving {
if let (myPeer, cachedData) = myPeerAndCachedData {
let about: String?
if let cachedData = cachedData as? CachedUserData {
@ -1436,7 +1437,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.stateValue.raisedHand = participant.raiseHandRating != nil
}
if let muteState = participant.muteState, muteState.canUnmute && previousRaisedHand {
if let muteState = participant.muteState, muteState.canUnmute && previousRaisedHand {
let _ = (strongSelf.accountContext.sharedContext.hasGroupCallOnScreen
|> take(1)
|> deliverOnMainQueue).start(next: { hasGroupCallOnScreen in
@ -1444,17 +1445,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return
}
let presentationData = strongSelf.accountContext.sharedContext.currentPresentationData.with { $0 }
if hasGroupCallOnScreen, let groupCallController = strongSelf.accountContext.sharedContext.currentGroupCallController {
var animateInAsReplacement = false
groupCallController.forEachController { c in
if let c = c as? UndoOverlayController {
animateInAsReplacement = true
c.dismiss()
}
return true
}
groupCallController.present(UndoOverlayController(presentationData: presentationData, content: .voiceChatCanSpeak(text: presentationData.strings.VoiceChat_YouCanNowSpeak), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in return true }), in: .current)
} else {
if !hasGroupCallOnScreen {
let title: String?
if let voiceChatTitle = strongSelf.stateValue.title {
title = voiceChatTitle
@ -1760,6 +1751,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
public func leave(terminateIfPossible: Bool) -> Signal<Bool, NoError> {
self.leaving = true
if let callInfo = self.internalState.callInfo, let localSsrc = self.currentLocalSsrc {
if terminateIfPossible {
self.leaveDisposable.set((stopGroupCall(account: self.account, peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash)

View File

@ -1410,7 +1410,17 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
func playRandomAnimation() {
if case .hand = self.iconState {
if let animationName = ["VoiceHand_1", "VoiceHand_2", "VoiceHand_3", "VoiceHand_4", "VoiceHand_5", "VoiceHand_6", "VoiceHand_7"].randomElement() {
var useTiredAnimation = false
let val = Float.random(in: 0.0..<1.0)
if val <= 0.01 {
useTiredAnimation = true
}
let normalAnimations = ["VoiceHand_1", "VoiceHand_2", "VoiceHand_3", "VoiceHand_4", "VoiceHand_7"]
let tiredAnimations = ["VoiceHand_5", "VoiceHand_6"]
let animations = useTiredAnimation ? tiredAnimations : normalAnimations
if let animationName = animations.randomElement() {
self.trackTo(item: ManagedAnimationItem(source: .local(animationName)))
}
}

View File

@ -1270,12 +1270,7 @@ public final class VoiceChatController: ViewController {
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme))
var items: [ActionSheetItem] = []
var action: DeleteChatPeerAction = .removeFromGroup
if let chatPeer = chatPeer as? TelegramChannel, case .broadcast = chatPeer.info {
action = .removeFromChannel
}
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: peer, chatPeer: peer, action: action, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: peer, chatPeer: chatPeer, action: .removeFromGroup, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()

View File

@ -95,17 +95,45 @@ public final class VoiceChatJoinScreen: ViewController {
return transaction.getPeerCachedData(peerId: peerId)
}
|> castError(GetCurrentGroupCallError.self)
let currentGroupCallId: Signal<Int64?, GetCurrentGroupCallError>
if let callManager = context.sharedContext.callManager {
currentGroupCallId = callManager.currentGroupCallSignal
|> castError(GetCurrentGroupCallError.self)
|> mapToSignal { call -> Signal<Int64?, GetCurrentGroupCallError> in
if let call = call {
return call.summaryState
|> castError(GetCurrentGroupCallError.self)
|> map { state -> Int64? in
return state?.info?.id
}
|> filter { id in
return id != nil
}
} else {
return .single(nil)
}
}
|> take(1)
} else {
currentGroupCallId = .single(nil)
}
self.disposable.set(combineLatest(queue: Queue.mainQueue(), signal, cachedGroupCallDisplayAsAvailablePeers(account: context.account, peerId: peerId) |> castError(GetCurrentGroupCallError.self), cachedData).start(next: { [weak self] peerAndCall, availablePeers, cachedData in
self.disposable.set(combineLatest(queue: Queue.mainQueue(), signal, cachedGroupCallDisplayAsAvailablePeers(account: context.account, peerId: peerId) |> castError(GetCurrentGroupCallError.self), cachedData, currentGroupCallId).start(next: { [weak self] peerAndCall, availablePeers, cachedData, currentGroupCallId in
if let strongSelf = self {
if let (peer, call) = peerAndCall {
if call.info.id == currentGroupCallId {
strongSelf.context.sharedContext.navigateToCurrentCall()
return
}
var defaultJoinAsPeerId: PeerId?
if let cachedData = cachedData as? CachedChannelData {
defaultJoinAsPeerId = cachedData.callJoinPeerId
} else if let cachedData = cachedData as? CachedGroupData {
defaultJoinAsPeerId = cachedData.callJoinPeerId
}
let activeCall = CachedChannelData.ActiveCall(id: call.info.id, accessHash: call.info.accessHash, title: call.info.title)
if availablePeers.count > 0 && defaultJoinAsPeerId == nil {
strongSelf.dismiss()
@ -481,13 +509,20 @@ public final class VoiceChatJoinScreen: ViewController {
}
}
private var animatingOut = false
func animateOut(completion: (() -> Void)? = nil) {
guard !self.animatingOut else {
return
}
self.animatingOut = true
if self.contentNode != nil {
var dimCompleted = false
var offsetCompleted = false
let internalCompletion: () -> Void = { [weak self] in
if let strongSelf = self, dimCompleted && offsetCompleted {
strongSelf.animatingOut = false
strongSelf.dismiss?()
}
completion?()

View File

@ -243,7 +243,6 @@ private func installRemoteStickerPacks(network: Network, infos: [StickerPackColl
}
private func removeRemoteStickerPacks(network: Network, infos: [StickerPackCollectionInfo]) -> Signal<Void, NoError> {
var signals: [Signal<Void, NoError>] = []
if infos.count > 0 {
if infos.count > 1 {
return network.request(Api.functions.messages.toggleStickerSets(flags: 1 << 0, stickersets: infos.map { .inputStickerSetID(id: $0.id.id, accessHash: $0.accessHash) }))
@ -267,7 +266,6 @@ private func removeRemoteStickerPacks(network: Network, infos: [StickerPackColle
}
private func archiveRemoteStickerPacks(network: Network, infos: [StickerPackCollectionInfo]) -> Signal<Void, NoError> {
var signals: [Signal<Void, NoError>] = []
if infos.count > 0 {
if infos.count > 1 {
return network.request(Api.functions.messages.toggleStickerSets(flags: 1 << 1, stickersets: infos.map { .inputStickerSetID(id: $0.id.id, accessHash: $0.accessHash) }))

View File

@ -451,9 +451,14 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
let titleString = strings.Notification_VoiceChatEnded(callDurationString(strings: strings, value: duration)).0
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
} else {
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
let titleString = strings.Notification_VoiceChatStarted(authorName)
attributedString = addAttributesToStringWithRanges(titleString, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
if message.author?.id.namespace == Namespaces.Peer.CloudChannel {
let titleString = strings.Notification_VoiceChatStartedChannel
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
} else {
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
let titleString = strings.Notification_VoiceChatStarted(authorName)
attributedString = addAttributesToStringWithRanges(titleString, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
}
}
case let .customText(text, entities):
attributedString = stringWithAppliedEntities(text, entities: entities, baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false)

File diff suppressed because one or more lines are too long

View File

@ -70,7 +70,7 @@ private class ChatHistoryListSelectionRecognizer: UIPanGestureRecognizer {
let dy = v1.y - v2.y
return sqrt(dx * dx + dy * dy)
}
if distance(firstLocation, secondLocation) > 100 {
if distance(firstLocation, secondLocation) > 70 {
self.state = .failed
}
}

View File

@ -1388,6 +1388,15 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
overrideImage = AvatarNodeImageOverride.none
item = nil
}
if let _ = overrideImage {
self.containerNode.isGestureEnabled = false
} else if peer.profileImageRepresentations.isEmpty {
self.containerNode.isGestureEnabled = false
} else {
self.containerNode.isGestureEnabled = false
}
self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: avatarSize, height: avatarSize), storeUnrounded: true)
self.isFirstAvatarLoading = false