mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Voice Chat UI fixes
This commit is contained in:
parent
96f81db35f
commit
0606bcf8da
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user