Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2020-11-29 23:51:32 +04:00
commit 1d0bc9ab6f
15 changed files with 4416 additions and 4524 deletions

View File

@ -5946,6 +5946,9 @@ Sorry for the inconvenience.";
"VoiceChat.RemovePeerConfirmation" = "Are you sure you want to remove %@ from the group chat?"; "VoiceChat.RemovePeerConfirmation" = "Are you sure you want to remove %@ from the group chat?";
"VoiceChat.RemovePeerRemove" = "Remove"; "VoiceChat.RemovePeerRemove" = "Remove";
"VoiceChat.PanelJoin" = "Join";
"VoiceChat.Title" = "Voice Chat";
"VoiceChat.UserInvited" = "You invited **%@** to the voice chat"; "VoiceChat.UserInvited" = "You invited **%@** to the voice chat";
"Notification.VoiceChatInvitation" = "%1$@ invited %2$@ to the voice chat"; "Notification.VoiceChatInvitation" = "%1$@ invited %2$@ to the voice chat";

View File

@ -390,6 +390,8 @@ open class NavigationController: UINavigationController, ContainableController,
globalScrollToTopNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -1.0), size: CGSize(width: layout.size.width, height: 1.0)) globalScrollToTopNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -1.0), size: CGSize(width: layout.size.width, height: 1.0))
} }
var overlayContainerLayout = layout
if let inCallStatusBar = self.inCallStatusBar { if let inCallStatusBar = self.inCallStatusBar {
var inCallStatusBarFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(layout.statusBarHeight ?? 0.0, max(40.0, layout.safeInsets.top)))) var inCallStatusBarFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(layout.statusBarHeight ?? 0.0, max(40.0, layout.safeInsets.top))))
if layout.deviceMetrics.hasTopNotch { if layout.deviceMetrics.hasTopNotch {
@ -541,8 +543,8 @@ open class NavigationController: UINavigationController, ContainableController,
containerTransition = transition containerTransition = transition
} }
containerTransition.updateFrame(node: overlayContainer, frame: CGRect(origin: CGPoint(), size: layout.size)) containerTransition.updateFrame(node: overlayContainer, frame: CGRect(origin: CGPoint(), size: overlayContainerLayout.size))
overlayContainer.update(layout: layout, transition: containerTransition) overlayContainer.update(layout: overlayContainerLayout, transition: containerTransition)
modalStyleOverlayTransitionFactor = max(modalStyleOverlayTransitionFactor, overlayContainer.controller.modalStyleOverlayTransitionFactor) modalStyleOverlayTransitionFactor = max(modalStyleOverlayTransitionFactor, overlayContainer.controller.modalStyleOverlayTransitionFactor)
@ -586,7 +588,7 @@ open class NavigationController: UINavigationController, ContainableController,
var previousModalContainer: NavigationModalContainer? var previousModalContainer: NavigationModalContainer?
var visibleModalCount = 0 var visibleModalCount = 0
var topModalIsFlat = false var topModalIsFlat = false
var isLandscape = layout.orientation == .landscape let isLandscape = layout.orientation == .landscape
var hasVisibleStandaloneModal = false var hasVisibleStandaloneModal = false
var topModalDismissProgress: CGFloat = 0.0 var topModalDismissProgress: CGFloat = 0.0

View File

@ -263,7 +263,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-309990731] = { return Api.Update.parse_updatePinnedMessages($0) } dict[-309990731] = { return Api.Update.parse_updatePinnedMessages($0) }
dict[-2054649973] = { return Api.Update.parse_updatePinnedChannelMessages($0) } dict[-2054649973] = { return Api.Update.parse_updatePinnedChannelMessages($0) }
dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) } dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) }
dict[-2046916883] = { return Api.Update.parse_updateGroupCall($0) } dict[1462009966] = { return Api.Update.parse_updateGroupCall($0) }
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) } dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) } dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }

View File

@ -6346,7 +6346,7 @@ public extension Api {
case updatePinnedMessages(flags: Int32, peer: Api.Peer, messages: [Int32], pts: Int32, ptsCount: Int32) case updatePinnedMessages(flags: Int32, peer: Api.Peer, messages: [Int32], pts: Int32, ptsCount: Int32)
case updatePinnedChannelMessages(flags: Int32, channelId: Int32, messages: [Int32], pts: Int32, ptsCount: Int32) case updatePinnedChannelMessages(flags: Int32, channelId: Int32, messages: [Int32], pts: Int32, ptsCount: Int32)
case updateGroupCallParticipants(call: Api.InputGroupCall, participants: [Api.GroupCallParticipant], version: Int32) case updateGroupCallParticipants(call: Api.InputGroupCall, participants: [Api.GroupCallParticipant], version: Int32)
case updateGroupCall(call: Api.GroupCall) case updateGroupCall(channelId: Int32, call: Api.GroupCall)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
@ -7094,10 +7094,11 @@ public extension Api {
} }
serializeInt32(version, buffer: buffer, boxed: false) serializeInt32(version, buffer: buffer, boxed: false)
break break
case .updateGroupCall(let call): case .updateGroupCall(let channelId, let call):
if boxed { if boxed {
buffer.appendInt32(-2046916883) buffer.appendInt32(1462009966)
} }
serializeInt32(channelId, buffer: buffer, boxed: false)
call.serialize(buffer, true) call.serialize(buffer, true)
break break
} }
@ -7277,8 +7278,8 @@ public extension Api {
return ("updatePinnedChannelMessages", [("flags", flags), ("channelId", channelId), ("messages", messages), ("pts", pts), ("ptsCount", ptsCount)]) return ("updatePinnedChannelMessages", [("flags", flags), ("channelId", channelId), ("messages", messages), ("pts", pts), ("ptsCount", ptsCount)])
case .updateGroupCallParticipants(let call, let participants, let version): case .updateGroupCallParticipants(let call, let participants, let version):
return ("updateGroupCallParticipants", [("call", call), ("participants", participants), ("version", version)]) return ("updateGroupCallParticipants", [("call", call), ("participants", participants), ("version", version)])
case .updateGroupCall(let call): case .updateGroupCall(let channelId, let call):
return ("updateGroupCall", [("call", call)]) return ("updateGroupCall", [("channelId", channelId), ("call", call)])
} }
} }
@ -8773,13 +8774,16 @@ public extension Api {
} }
} }
public static func parse_updateGroupCall(_ reader: BufferReader) -> Update? { public static func parse_updateGroupCall(_ reader: BufferReader) -> Update? {
var _1: Api.GroupCall? var _1: Int32?
_1 = reader.readInt32()
var _2: Api.GroupCall?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.GroupCall _2 = Api.parse(reader, signature: signature) as? Api.GroupCall
} }
let _c1 = _1 != nil let _c1 = _1 != nil
if _c1 { let _c2 = _2 != nil
return Api.Update.updateGroupCall(call: _1!) if _c1 && _c2 {
return Api.Update.updateGroupCall(channelId: _1!, call: _2!)
} }
else { else {
return nil return nil

View File

@ -32,6 +32,15 @@ private class CallStatusBarBackgroundNode: ASDisplayNode {
var presentationAudioLevel: CGFloat = 0.0 var presentationAudioLevel: CGFloat = 0.0
var phase: CGFloat = 0.0 var phase: CGFloat = 0.0
var transitionArguments: (Double, Double)?
var speaking = false {
didSet {
if self.speaking != oldValue {
self.transitionArguments = (CACurrentMediaTime(), 0.3)
}
}
}
private var animator: ConstantDisplayLinkAnimator? private var animator: ConstantDisplayLinkAnimator?
override init() { override init() {
@ -61,7 +70,7 @@ private class CallStatusBarBackgroundNode: ASDisplayNode {
} }
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? { override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
return CallStatusBarBackgroundNodeDrawingState(timestamp: CACurrentMediaTime(), amplitude: self.presentationAudioLevel, phase: self.phase, speaking: false, transitionArguments: nil) return CallStatusBarBackgroundNodeDrawingState(timestamp: CACurrentMediaTime(), amplitude: self.presentationAudioLevel, phase: self.phase, speaking: self.speaking, transitionArguments: self.transitionArguments)
} }
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) { @objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
@ -96,7 +105,7 @@ private class CallStatusBarBackgroundNode: ASDisplayNode {
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
let position: CGFloat = bounds.height - 6.0 let position: CGFloat = bounds.height - 6.0
let maxAmplitude: CGFloat = 8.0 let maxAmplitude: CGFloat = 12.0
let amplitude = max(0.35, parameters.amplitude) let amplitude = max(0.35, parameters.amplitude)
@ -126,7 +135,7 @@ private class CallStatusBarBackgroundNode: ASDisplayNode {
context.clip() context.clip()
} }
for i in (0 ..< 2).reversed() { for i in (0 ..< 3).reversed() {
let progress = 1.0 - CGFloat(i) / 3.0 let progress = 1.0 - CGFloat(i) / 3.0
var normalizedAmplitude = (1.5 * progress - 0.8) * amplitude var normalizedAmplitude = (1.5 * progress - 0.8) * amplitude
if i == 1 { if i == 1 {
@ -255,7 +264,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
if !strongSelf.currentIsMuted { if !strongSelf.currentIsMuted {
effectiveLevel = level effectiveLevel = level
} }
strongSelf.backgroundNode.audioLevel = effectiveLevel strongSelf.backgroundNode.audioLevel = max(0.0, min(1.0, effectiveLevel / 8.0))
})) }))
} }
self.didSetupData = true self.didSetupData = true
@ -297,6 +306,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
self.titleNode.frame = CGRect(origin: CGPoint(x: horizontalOrigin + animationSize + iconSpacing, y: verticalOrigin + floor((contentHeight - titleSize.height) / 2.0)), size: titleSize) self.titleNode.frame = CGRect(origin: CGPoint(x: horizontalOrigin + animationSize + iconSpacing, y: verticalOrigin + floor((contentHeight - titleSize.height) / 2.0)), size: titleSize)
self.subtitleNode.frame = CGRect(origin: CGPoint(x: horizontalOrigin + animationSize + iconSpacing + titleSize.width + spacing, y: verticalOrigin + floor((contentHeight - subtitleSize.height) / 2.0)), size: subtitleSize) self.subtitleNode.frame = CGRect(origin: CGPoint(x: horizontalOrigin + animationSize + iconSpacing + titleSize.width + spacing, y: verticalOrigin + floor((contentHeight - subtitleSize.height) / 2.0)), size: subtitleSize)
self.backgroundNode.speaking = !self.currentIsMuted
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height + 7.0)) self.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height + 7.0))
} }
} }

View File

@ -211,14 +211,13 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
self.separatorNode.backgroundColor = presentationData.theme.chat.historyNavigation.strokeColor self.separatorNode.backgroundColor = presentationData.theme.chat.historyNavigation.strokeColor
self.joinButtonTitleNode.attributedText = NSAttributedString(string: presentationData.strings.Channel_JoinChannel.uppercased(), font: Font.semibold(15.0), textColor: presentationData.theme.chat.inputPanel.actionControlForegroundColor) self.joinButtonTitleNode.attributedText = NSAttributedString(string: presentationData.strings.VoiceChat_PanelJoin.uppercased(), font: Font.semibold(15.0), textColor: presentationData.theme.chat.inputPanel.actionControlForegroundColor)
self.joinButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: presentationData.theme.chat.inputPanel.actionControlFillColor) self.joinButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: presentationData.theme.chat.inputPanel.actionControlFillColor)
//TODO:localize //TODO:localize
self.micButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 36.0, color: UIColor(rgb: 0x30b251)) self.micButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 36.0, color: UIColor(rgb: 0x30b251))
//TODO:localize self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.VoiceChat_Title, font: Font.semibold(15.0), textColor: presentationData.theme.chat.inputPanel.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: "Voice Chat", font: Font.semibold(15.0), textColor: presentationData.theme.chat.inputPanel.primaryTextColor)
self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: Font.regular(13.0), textColor: presentationData.theme.chat.inputPanel.secondaryTextColor) self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: Font.regular(13.0), textColor: presentationData.theme.chat.inputPanel.secondaryTextColor)
self.muteIconNode.image = PresentationResourcesChat.chatTitleMuteIcon(presentationData.theme) self.muteIconNode.image = PresentationResourcesChat.chatTitleMuteIcon(presentationData.theme)

View File

@ -168,9 +168,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|> map { value -> Bool in |> map { value -> Bool in
switch value { switch value {
case let .muted(isPushToTalkActive): case let .muted(isPushToTalkActive):
return isPushToTalkActive return !isPushToTalkActive
case .unmuted: case .unmuted:
return true return false
} }
} }
} }

View File

@ -488,10 +488,9 @@ public final class VoiceChatController: ViewController {
strongSelf.currentCallMembers = callMembers.participants strongSelf.currentCallMembers = callMembers.participants
} }
//TODO:localize let subtitle = strongSelf.presentationData.strings.VoiceChat_Panel_Members(Int32(max(1, callMembers.totalCount)))
let subtitle = strongSelf.presentationData.strings.Conversation_StatusMembers(Int32(max(1, callMembers.totalCount)))
if let titleView = strongSelf.controller?.navigationItem.titleView as? VoiceChatControllerTitleView { if let titleView = strongSelf.controller?.navigationItem.titleView as? VoiceChatControllerTitleView {
titleView.set(title: "Voice Chat", subtitle: subtitle) titleView.set(title: strongSelf.presentationData.strings.VoiceChat_Title, subtitle: subtitle)
} }
}) })
@ -760,13 +759,12 @@ public final class VoiceChatController: ViewController {
@objc private func actionButtonPressed() { @objc private func actionButtonPressed() {
if let callState = self.callState, case .connected = callState.networkState, let muteState = callState.muteState, !muteState.canUnmute { if let callState = self.callState, case .connected = callState.networkState, let muteState = callState.muteState, !muteState.canUnmute {
self.hapticFeedback.error()
self.actionButton.layer.addShakeAnimation()
return return
} }
self.hapticFeedback.error() self.call.toggleIsMuted()
self.actionButton.layer.addShakeAnimation()
// self.call.toggleIsMuted()
} }
@objc private func audioOutputPressed() { @objc private func audioOutputPressed() {

View File

@ -111,7 +111,7 @@ enum AccountStateMutationOperation {
case UpdateChatListFilter(id: Int32, filter: Api.DialogFilter?) case UpdateChatListFilter(id: Int32, filter: Api.DialogFilter?)
case UpdateReadThread(threadMessageId: MessageId, readMaxId: Int32, isIncoming: Bool, mainChannelMessage: MessageId?) case UpdateReadThread(threadMessageId: MessageId, readMaxId: Int32, isIncoming: Bool, mainChannelMessage: MessageId?)
case UpdateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32) case UpdateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32)
case UpdateGroupCall(call: Api.GroupCall) case UpdateGroupCall(peerId: PeerId, call: Api.GroupCall)
} }
struct HoleFromPreviousState { struct HoleFromPreviousState {
@ -282,8 +282,8 @@ struct AccountMutableState {
self.addOperation(.UpdateGroupCallParticipants(id: id, accessHash: accessHash, participants: participants, version: version)) self.addOperation(.UpdateGroupCallParticipants(id: id, accessHash: accessHash, participants: participants, version: version))
} }
mutating func updateGroupCall(call: Api.GroupCall) { mutating func updateGroupCall(peerId: PeerId, call: Api.GroupCall) {
self.addOperation(.UpdateGroupCall(call: call)) self.addOperation(.UpdateGroupCall(peerId: peerId, call: call))
} }
mutating func readGroupFeedInbox(groupId: PeerGroupId, index: MessageIndex) { mutating func readGroupFeedInbox(groupId: PeerGroupId, index: MessageIndex) {

View File

@ -1332,8 +1332,8 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
case let .inputGroupCall(id, accessHash): case let .inputGroupCall(id, accessHash):
updatedState.updateGroupCallParticipants(id: id, accessHash: accessHash, participants: participants, version: version) updatedState.updateGroupCallParticipants(id: id, accessHash: accessHash, participants: participants, version: version)
} }
case let .updateGroupCall(call): case let .updateGroupCall(channelId, call):
updatedState.updateGroupCall(call: call) updatedState.updateGroupCall(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), call: call)
case let .updateLangPackTooLong(langCode): case let .updateLangPackTooLong(langCode):
updatedState.updateLangPack(langCode: langCode, difference: nil) updatedState.updateLangPack(langCode: langCode, difference: nil)
case let .updateLangPack(difference): case let .updateLangPack(difference):
@ -2959,15 +2959,35 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
callId, callId,
.state(update: GroupCallParticipantsContext.Update.StateUpdate(participants: participants, version: version)) .state(update: GroupCallParticipantsContext.Update.StateUpdate(participants: participants, version: version))
)) ))
case let .UpdateGroupCall(call): case let .UpdateGroupCall(peerId, call):
switch call { switch call {
case .groupCall: case .groupCall:
break if let info = GroupCallInfo(call) {
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedChannelData {
return current.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
} else {
return current
}
})
}
case let .groupCallDiscarded(callId, _, _): case let .groupCallDiscarded(callId, _, _):
updatedGroupCallParticipants.append(( updatedGroupCallParticipants.append((
callId, callId,
.call(isTerminated: true) .call(isTerminated: true)
)) ))
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedChannelData {
if let activeCall = current.activeCall, activeCall.id == callId {
return current.withUpdatedActiveCall(nil)
} else {
return current
}
} else {
return current
}
})
} }
case let .UpdateLangPack(langCode, difference): case let .UpdateLangPack(langCode, difference):
if let difference = difference { if let difference = difference {

View File

@ -28,7 +28,7 @@ public struct GroupCallSummary: Equatable {
public var topParticipants: [GroupCallParticipantsContext.Participant] public var topParticipants: [GroupCallParticipantsContext.Participant]
} }
private extension GroupCallInfo { extension GroupCallInfo {
init?(_ call: Api.GroupCall) { init?(_ call: Api.GroupCall) {
switch call { switch call {
case let .groupCall(_, id, accessHash, participantCount, params, _): case let .groupCall(_, id, accessHash, participantCount, params, _):
@ -142,7 +142,7 @@ public func createGroupCall(account: Account, peerId: PeerId) -> Signal<GroupCal
var parsedCall: GroupCallInfo? var parsedCall: GroupCallInfo?
loop: for update in result.allUpdates { loop: for update in result.allUpdates {
switch update { switch update {
case let .updateGroupCall(call): case let .updateGroupCall(_, call):
parsedCall = GroupCallInfo(call) parsedCall = GroupCallInfo(call)
break loop break loop
default: default:
@ -316,7 +316,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, callId: Int64, acces
var maybeParsedCall: GroupCallInfo? var maybeParsedCall: GroupCallInfo?
loop: for update in updates.allUpdates { loop: for update in updates.allUpdates {
switch update { switch update {
case let .updateGroupCall(call): case let .updateGroupCall(_, call):
maybeParsedCall = GroupCallInfo(call) maybeParsedCall = GroupCallInfo(call)
break loop break loop
default: default:

View File

@ -1,153 +0,0 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import SyncCore
import SwiftSignalKit
import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
import StickerResources
import PhotoResources
import TelegramStringFormatting
import AnimatedCountLabelNode
import AnimatedNavigationStripeNode
import ContextUI
import RadialStatusNode
import AnimatedAvatarSetNode
final class ChatCallTitlePanelNode: ChatTitleAccessoryPanelNode {
private let context: AccountContext
private let tapButton: HighlightTrackingButtonNode
private let joinButton: HighlightableButtonNode
private let joinButtonTitleNode: ImmediateTextNode
private let joinButtonBackgroundNode: ASImageNode
private let titleNode: ImmediateTextNode
private let textNode: ImmediateTextNode
private let muteIconNode: ASImageNode
private let separatorNode: ASDisplayNode
private var theme: PresentationTheme?
private var currentLayout: (CGFloat, CGFloat, CGFloat)?
private var activeGroupCallInfo: ChatActiveGroupCallInfo?
private let queue = Queue()
init(context: AccountContext) {
self.context = context
self.tapButton = HighlightTrackingButtonNode()
self.joinButton = HighlightableButtonNode()
self.joinButtonTitleNode = ImmediateTextNode()
self.joinButtonBackgroundNode = ASImageNode()
self.titleNode = ImmediateTextNode()
self.textNode = ImmediateTextNode()
self.muteIconNode = ASImageNode()
self.separatorNode = ASDisplayNode()
self.separatorNode.isLayerBacked = true
super.init()
self.tapButton.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
if highlighted {
strongSelf.titleNode.layer.removeAnimation(forKey: "opacity")
strongSelf.titleNode.alpha = 0.4
strongSelf.textNode.layer.removeAnimation(forKey: "opacity")
strongSelf.textNode.alpha = 0.4
} else {
strongSelf.titleNode.alpha = 1.0
strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
strongSelf.textNode.alpha = 1.0
strongSelf.textNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
}
}
}
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
self.addSubnode(self.muteIconNode)
self.tapButton.addTarget(self, action: #selector(self.tapped), forControlEvents: [.touchUpInside])
self.addSubnode(self.tapButton)
self.joinButton.addSubnode(self.joinButtonBackgroundNode)
self.joinButton.addSubnode(self.joinButtonTitleNode)
self.addSubnode(self.joinButton)
self.joinButton.addTarget(self, action: #selector(self.tapped), forControlEvents: [.touchUpInside])
self.addSubnode(self.separatorNode)
}
deinit {
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> CGFloat {
let panelHeight: CGFloat = 50.0
self.tapButton.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))
self.activeGroupCallInfo = interfaceState.activeGroupCallInfo
if self.theme !== interfaceState.theme {
self.theme = interfaceState.theme
self.backgroundColor = interfaceState.theme.chat.historyNavigation.fillColor
self.separatorNode.backgroundColor = interfaceState.theme.chat.historyNavigation.strokeColor
self.joinButtonTitleNode.attributedText = NSAttributedString(string: interfaceState.strings.Channel_JoinChannel.uppercased(), font: Font.semibold(15.0), textColor: interfaceState.theme.chat.inputPanel.actionControlForegroundColor)
self.joinButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: interfaceState.theme.chat.inputPanel.actionControlFillColor)
//TODO:localize
self.titleNode.attributedText = NSAttributedString(string: "Voice Chat", font: Font.semibold(15.0), textColor: interfaceState.theme.chat.inputPanel.primaryTextColor)
self.textNode.attributedText = NSAttributedString(string: "4 members", font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
self.muteIconNode.image = PresentationResourcesChat.chatTitleMuteIcon(interfaceState.theme)
}
let joinButtonTitleSize = self.joinButtonTitleNode.updateLayout(CGSize(width: 150.0, height: .greatestFiniteMagnitude))
let joinButtonSize = CGSize(width: joinButtonTitleSize.width + 20.0, height: 28.0)
let joinButtonFrame = CGRect(origin: CGPoint(x: width - rightInset - 7.0 - joinButtonSize.width, y: floor((panelHeight - joinButtonSize.height) / 2.0)), size: joinButtonSize)
transition.updateFrame(node: self.joinButton, frame: joinButtonFrame)
transition.updateFrame(node: self.joinButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: joinButtonFrame.size))
transition.updateFrame(node: self.joinButtonTitleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((joinButtonFrame.width - joinButtonTitleSize.width) / 2.0), y: floorToScreenPixels((joinButtonFrame.height - joinButtonTitleSize.height) / 2.0)), size: joinButtonTitleSize))
let titleSize = self.titleNode.updateLayout(CGSize(width: width, height: .greatestFiniteMagnitude))
let textSize = self.textNode.updateLayout(CGSize(width: width, height: .greatestFiniteMagnitude))
let titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: 10.0), size: titleSize)
transition.updateFrame(node: self.titleNode, frame: titleFrame)
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((width - textSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: textSize))
if let image = self.muteIconNode.image {
transition.updateFrame(node: self.muteIconNode, frame: CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: titleFrame.minY + 5.0), size: image.size))
}
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelHeight - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel)))
return panelHeight
}
@objc private func tapped() {
guard let interfaceInteraction = self.interfaceInteraction else {
return
}
guard let activeGroupCallInfo = self.activeGroupCallInfo else {
return
}
interfaceInteraction.joinGroupCall(activeGroupCallInfo.activeCall)
}
}

View File

@ -133,9 +133,16 @@ public final class SharedWakeupManager {
return call?.account.id == account.id return call?.account.id == account.id
} }
|> distinctUntilChanged |> distinctUntilChanged
let isPlayingBackgroundActiveCall = combineLatest(queue: .mainQueue(), hasActiveCalls, hasActiveAudioSession)
|> map { hasActiveCalls, hasActiveAudioSession -> Bool in let hasActiveGroupCalls = (callManager?.currentGroupCallSignal ?? .single(nil))
return hasActiveCalls && hasActiveAudioSession |> map { call in
return call?.accountContext.account.id == account.id
}
|> distinctUntilChanged
let isPlayingBackgroundActiveCall = combineLatest(queue: .mainQueue(), hasActiveCalls, hasActiveGroupCalls, hasActiveAudioSession)
|> map { hasActiveCalls, hasActiveGroupCalls, hasActiveAudioSession -> Bool in
return (hasActiveCalls || hasActiveGroupCalls) && hasActiveAudioSession
} }
|> distinctUntilChanged |> distinctUntilChanged