Voice Chat UI fixes

This commit is contained in:
Ilya Laktyushin 2020-12-14 16:30:51 +04:00
parent 96f81db35f
commit 0606bcf8da
4 changed files with 82 additions and 17 deletions

View File

@ -39,6 +39,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
return self.statePromise.get()
}
let bottomNode: ASDisplayNode
private let containerNode: ASDisplayNode
private let backgroundNode: VoiceChatActionButtonBackgroundNode
private let iconNode: VoiceChatMicrophoneNode
@ -93,6 +94,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
}
init() {
self.bottomNode = ASDisplayNode()
self.containerNode = ASDisplayNode()
self.backgroundNode = VoiceChatActionButtonBackgroundNode()
self.iconNode = VoiceChatMicrophoneNode()
@ -102,6 +104,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
super.init()
self.addSubnode(self.bottomNode)
self.addSubnode(self.titleLabel)
self.addSubnode(self.subtitleLabel)
@ -178,6 +181,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
self.titleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: floor(size.height - totalHeight / 2.0) - 112.0), size: titleSize)
self.subtitleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - subtitleSize.width) / 2.0), y: self.titleLabel.frame.maxY + 1.0), size: subtitleSize)
self.bottomNode.frame = CGRect(origin: CGPoint(), size: size)
self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
self.backgroundNode.bounds = CGRect(origin: CGPoint(), size: size)

View File

@ -393,8 +393,8 @@ public final class VoiceChatController: ViewController {
fileprivate let bottomPanelNode: ASDisplayNode
private let bottomPanelBackgroundNode: ASDisplayNode
private let bottomCornersNode: ASImageNode
private let audioOutputNode: CallControllerButtonItemNode
private let leaveNode: CallControllerButtonItemNode
fileprivate let audioOutputNode: CallControllerButtonItemNode
fileprivate let leaveNode: CallControllerButtonItemNode
fileprivate let actionButton: VoiceChatActionButton
private let leftBorderNode: ASDisplayNode
private let rightBorderNode: ASDisplayNode
@ -1644,9 +1644,10 @@ public final class VoiceChatController: ViewController {
let sideButtonOffset = min(36.0, floor((((layout.size.width - 144.0) / 2.0) - sideButtonSize.width) / 2.0))
let sideButtonOrigin = max(sideButtonMinimalInset, floor((layout.size.width - 144.0) / 2.0) - sideButtonOffset - sideButtonSize.width)
transition.updateFrame(node: self.audioOutputNode, frame: CGRect(origin: CGPoint(x: sideButtonOrigin, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
transition.updateFrame(node: self.leaveNode, frame: CGRect(origin: CGPoint(x: layout.size.width - sideButtonOrigin - sideButtonSize.width, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
if self.audioOutputNode.supernode === self.bottomPanelNode {
transition.updateFrame(node: self.audioOutputNode, frame: CGRect(origin: CGPoint(x: sideButtonOrigin, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
transition.updateFrame(node: self.leaveNode, frame: CGRect(origin: CGPoint(x: layout.size.width - sideButtonOrigin - sideButtonSize.width, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
}
if isFirstTime {
while !self.enqueuedTransitions.isEmpty {
self.dequeueTransition()
@ -1669,6 +1670,10 @@ public final class VoiceChatController: ViewController {
self.contentContainer.view.bounds = initialBounds
}, completion: { _ in
if self.actionButton.supernode !== self.bottomPanelNode {
self.audioOutputNode.layer.removeAllAnimations()
self.leaveNode.layer.removeAllAnimations()
self.bottomPanelNode.addSubnode(self.audioOutputNode)
self.bottomPanelNode.addSubnode(self.leaveNode)
self.bottomPanelNode.addSubnode(self.actionButton)
self.containerLayoutUpdated(layout, navigationHeight :navigationHeight, transition: .immediate)
}
@ -1865,6 +1870,17 @@ public final class VoiceChatController: ViewController {
index += 1
}
if let accountPeer = self.accountPeer, !processedPeerIds.contains(accountPeer.id) {
entries.insert(.peer(PeerEntry(
peer: accountPeer,
presence: nil,
activityTimestamp: Int32.max - 1 - index,
state: .listening,
muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true),
canManageCall: callState?.canManageCall ?? false
)), at: 1)
}
for peer in invitedPeers {
if processedPeerIds.contains(peer.id) {
continue
@ -2235,7 +2251,7 @@ public final class VoiceChatController: ViewController {
return
}
let overlayController = VoiceChatOverlayController(actionButton: self.controllerNode.actionButton, navigationController: self.navigationController as? NavigationController)
let overlayController = VoiceChatOverlayController(actionButton: self.controllerNode.actionButton, audioOutputNode: self.controllerNode.audioOutputNode, leaveNode: self.controllerNode.leaveNode, navigationController: self.navigationController as? NavigationController)
if let navigationController = self.navigationController as? NavigationController {
navigationController.presentOverlay(controller: overlayController, inGlobal: true, blockInteraction: false)
}

View File

@ -86,24 +86,44 @@ public final class VoiceChatOverlayController: ViewController {
}
}
}
private var initialLeftButtonPosition: CGPoint?
private var initialRightButtonPosition: CGPoint?
func animateIn(from: CGRect) {
guard let actionButton = self.controller?.actionButton else {
guard let actionButton = self.controller?.actionButton, let leftButton = self.controller?.audioOutputNode, let rightButton = self.controller?.leaveNode else {
return
}
actionButton.update(snap: true, animated: !self.isSlidOffscreen && !self.isButtonHidden)
if self.isSlidOffscreen {
leftButton.isHidden = false
rightButton.isHidden = false
actionButton.layer.sublayerTransform = CATransform3DMakeTranslation(slideOffset, 0.0, 0.0)
return
} else if self.isButtonHidden {
leftButton.isHidden = false
rightButton.isHidden = false
actionButton.isHidden = true
return
}
self.initialLeftButtonPosition = leftButton.position
self.initialRightButtonPosition = rightButton.position
let center = CGPoint(x: actionButton.frame.width / 2.0, y: actionButton.frame.height / 2.0)
leftButton.layer.animatePosition(from: leftButton.position, to: center, duration: 0.15, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak leftButton] _ in
leftButton?.isHidden = true
leftButton?.layer.removeAllAnimations()
})
rightButton.layer.animatePosition(from: rightButton.position, to: center, duration: 0.15, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak rightButton] _ in
rightButton?.isHidden = true
rightButton?.layer.removeAllAnimations()
})
let targetPosition = actionButton.position
let sourcePoint = CGPoint(x: from.midX, y: from.midY)
let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y + 120.0)
let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y + 90.0)
let x1 = sourcePoint.x
let y1 = sourcePoint.y
@ -131,7 +151,7 @@ public final class VoiceChatOverlayController: ViewController {
private var animating = false
private var dismissed = false
func animateOut(reclaim: Bool, completion: @escaping (Bool) -> Void) {
guard let actionButton = self.controller?.actionButton, let layout = self.validLayout else {
guard let actionButton = self.controller?.actionButton, let leftButton = self.controller?.audioOutputNode, let rightButton = self.controller?.leaveNode, let layout = self.validLayout else {
return
}
@ -155,7 +175,7 @@ public final class VoiceChatOverlayController: ViewController {
} else {
self.animating = true
let sourcePoint = actionButton.position
var midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0 - 60.0, y: sourcePoint.y)
var midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0 - 25.0, y: (sourcePoint.y + targetPosition.y) / 2.0 + 25.0)
if sourcePoint.y < layout.size.height - 100.0 {
midPoint.x = (sourcePoint.x + targetPosition.x) / 2.0 + 30.0
midPoint.y = (sourcePoint.y + targetPosition.y) / 2.0 + 40.0
@ -180,9 +200,19 @@ public final class VoiceChatOverlayController: ViewController {
keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y)))
}
if let leftButtonPosition = self.initialLeftButtonPosition, let rightButtonPosition = self.initialRightButtonPosition {
let center = CGPoint(x: actionButton.frame.width / 2.0, y: actionButton.frame.height / 2.0)
leftButton.isHidden = false
leftButton.layer.animatePosition(from: center, to: leftButtonPosition, duration: 0.25, delay: 0.1, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false)
rightButton.isHidden = false
rightButton.layer.animatePosition(from: center, to: rightButtonPosition, duration: 0.25, delay: 0.1, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false)
}
actionButton.update(snap: false, animated: true)
actionButton.position = targetPosition
actionButton.layer.animateKeyframes(values: keyframes, duration: 0.34, keyPath: "position", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, completion: { _ in
actionButton.layer.animateKeyframes(values: keyframes, duration: 0.37, keyPath: "position", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, completion: { _ in
self.animating = false
completion(false)
})
@ -210,9 +240,20 @@ public final class VoiceChatOverlayController: ViewController {
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
self.validLayout = layout
if let actionButton = self.controller?.actionButton, !self.animating && !self.dismissed {
if let actionButton = self.controller?.actionButton, let leftButton = self.controller?.audioOutputNode, let rightButton = self.controller?.leaveNode, !self.animating && !self.dismissed {
let convertedRect = actionButton.view.convert(actionButton.bounds, to: self.view)
let insets = layout.insets(options: [.input])
let insets = layout.insets(options: [.input])
if !self.didAnimateIn {
let leftButtonFrame = leftButton.view.convert(leftButton.bounds, to: actionButton.bottomNode.view)
actionButton.bottomNode.addSubnode(leftButton)
leftButton.frame = leftButtonFrame
let rightButtonFrame = rightButton.view.convert(rightButton.bounds, to: actionButton.bottomNode.view)
actionButton.bottomNode.addSubnode(rightButton)
rightButton.frame = rightButtonFrame
}
transition.updatePosition(node: actionButton, position: CGPoint(x: layout.size.width - layout.safeInsets.right - 21.0, y: layout.size.height - insets.bottom - 22.0))
if actionButton.supernode !== self && !self.didAnimateIn {
@ -225,6 +266,8 @@ public final class VoiceChatOverlayController: ViewController {
}
private weak var actionButton: VoiceChatActionButton?
private weak var audioOutputNode: CallControllerButtonItemNode?
private weak var leaveNode: CallControllerButtonItemNode?
private var controllerNode: Node {
return self.displayNode as! Node
@ -232,8 +275,10 @@ public final class VoiceChatOverlayController: ViewController {
private var disposable: Disposable?
init(actionButton: VoiceChatActionButton, navigationController: NavigationController?) {
init(actionButton: VoiceChatActionButton, audioOutputNode: CallControllerButtonItemNode, leaveNode: CallControllerButtonItemNode, navigationController: NavigationController?) {
self.actionButton = actionButton
self.audioOutputNode = audioOutputNode
self.leaveNode = leaveNode
super.init(navigationBarPresentationData: nil)

View File

@ -37,7 +37,7 @@ func telegramStickerPackThumbnailRepresentationFromApiSize(datacenterId: Int32,
extension StickerPackCollectionInfo {
convenience init(apiSet: Api.StickerSet, namespace: ItemCollectionId.Namespace) {
switch apiSet {
case let .stickerSet(flags, _, id, accessHash, title, shortName, thumb, thumbDcId, count, nHash):
case let .stickerSet(flags, _, id, accessHash, title, shortName, thumbs, thumbDcId, count, nHash):
var setFlags: StickerPackCollectionInfoFlags = StickerPackCollectionInfoFlags()
if (flags & (1 << 2)) != 0 {
setFlags.insert(.isOfficial)
@ -50,7 +50,7 @@ extension StickerPackCollectionInfo {
}
var thumbnailRepresentation: TelegramMediaImageRepresentation?
if let thumb = thumb?.first, let thumbDcId = thumbDcId {
if let thumb = thumbs?.first, let thumbDcId = thumbDcId {
thumbnailRepresentation = telegramStickerPackThumbnailRepresentationFromApiSize(datacenterId: thumbDcId, size: thumb)
}