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
86259ac889
commit
7d45ba44b9
@ -389,11 +389,13 @@ private final class VoiceChatActionButtonBackgroundNodeTransition {
|
|||||||
private class VoiceChatActionButtonBackgroundNodeDrawingState: NSObject {
|
private class VoiceChatActionButtonBackgroundNodeDrawingState: NSObject {
|
||||||
let timestamp: Double
|
let timestamp: Double
|
||||||
let state: VoiceChatActionButtonBackgroundNodeState
|
let state: VoiceChatActionButtonBackgroundNodeState
|
||||||
|
let simplified: Bool
|
||||||
let transition: VoiceChatActionButtonBackgroundNodeTransition?
|
let transition: VoiceChatActionButtonBackgroundNodeTransition?
|
||||||
|
|
||||||
init(timestamp: Double, state: VoiceChatActionButtonBackgroundNodeState, transition: VoiceChatActionButtonBackgroundNodeTransition?) {
|
init(timestamp: Double, state: VoiceChatActionButtonBackgroundNodeState, simplified: Bool, transition: VoiceChatActionButtonBackgroundNodeTransition?) {
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
self.state = state
|
self.state = state
|
||||||
|
self.simplified = simplified
|
||||||
self.transition = transition
|
self.transition = transition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,6 +404,7 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
private var state: VoiceChatActionButtonBackgroundNodeState
|
private var state: VoiceChatActionButtonBackgroundNodeState
|
||||||
private var hasState = false
|
private var hasState = false
|
||||||
private var transition: VoiceChatActionButtonBackgroundNodeTransition?
|
private var transition: VoiceChatActionButtonBackgroundNodeTransition?
|
||||||
|
private var simplified = false
|
||||||
|
|
||||||
var audioLevel: CGFloat = 0.0 {
|
var audioLevel: CGFloat = 0.0 {
|
||||||
didSet {
|
didSet {
|
||||||
@ -426,7 +429,7 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
self.displaysAsynchronously = true
|
self.displaysAsynchronously = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(state: VoiceChatActionButtonBackgroundNodeState, animated: Bool) {
|
func update(state: VoiceChatActionButtonBackgroundNodeState, simplified: Bool, animated: Bool) {
|
||||||
var animated = animated
|
var animated = animated
|
||||||
var hadState = true
|
var hadState = true
|
||||||
if !self.hasState {
|
if !self.hasState {
|
||||||
@ -435,6 +438,8 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
animated = false
|
animated = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.simplified = simplified
|
||||||
|
|
||||||
if state.type != self.state.type || !hadState {
|
if state.type != self.state.type || !hadState {
|
||||||
if animated {
|
if animated {
|
||||||
self.transition = VoiceChatActionButtonBackgroundNodeTransition(startTime: CACurrentMediaTime(), duration: 0.3, previousState: self.state)
|
self.transition = VoiceChatActionButtonBackgroundNodeTransition(startTime: CACurrentMediaTime(), duration: 0.3, previousState: self.state)
|
||||||
@ -491,13 +496,13 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||||
return VoiceChatActionButtonBackgroundNodeDrawingState(timestamp: CACurrentMediaTime(), state: self.state, transition: self.transition)
|
return VoiceChatActionButtonBackgroundNodeDrawingState(timestamp: CACurrentMediaTime(), state: self.state, simplified: self.simplified, transition: self.transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
@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) {
|
||||||
let context = UIGraphicsGetCurrentContext()!
|
let context = UIGraphicsGetCurrentContext()!
|
||||||
|
|
||||||
let drawStart = CACurrentMediaTime()
|
// let drawStart = CACurrentMediaTime()
|
||||||
|
|
||||||
if !isRasterizing {
|
if !isRasterizing {
|
||||||
context.setBlendMode(.copy)
|
context.setBlendMode(.copy)
|
||||||
@ -517,6 +522,7 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
|
|
||||||
var gradientTransition: CGFloat = 0.0
|
var gradientTransition: CGFloat = 0.0
|
||||||
var gradientImage: UIImage? = parameters.state.blueGradient
|
var gradientImage: UIImage? = parameters.state.blueGradient
|
||||||
|
var simpleColor: UIColor = blue
|
||||||
let gradientSize: CGFloat = bounds.width * 2.0
|
let gradientSize: CGFloat = bounds.width * 2.0
|
||||||
|
|
||||||
context.interpolationQuality = .low
|
context.interpolationQuality = .low
|
||||||
@ -537,19 +543,23 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
glowScale += gradientTransition * 0.3
|
glowScale += gradientTransition * 0.3
|
||||||
|
|
||||||
gradientImage = gradientTransition.isZero ? blobsState.blueGradient : blobsState.greenGradient
|
simpleColor = blue.interpolateTo(green, fraction: gradientTransition)!
|
||||||
if gradientTransition > 0.0 && gradientTransition < 1.0 {
|
|
||||||
gradientImage = generateImage(CGSize(width: 100.0, height: 100.0), contextGenerator: { size, context in
|
if !parameters.simplified {
|
||||||
context.interpolationQuality = .low
|
gradientImage = gradientTransition.isZero ? blobsState.blueGradient : blobsState.greenGradient
|
||||||
if let image = blobsState.blueGradient?.cgImage {
|
if gradientTransition > 0.0 && gradientTransition < 1.0 {
|
||||||
context.draw(image, in: CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 100.0)))
|
gradientImage = generateImage(CGSize(width: 100.0, height: 100.0), contextGenerator: { size, context in
|
||||||
}
|
context.interpolationQuality = .low
|
||||||
|
if let image = blobsState.blueGradient?.cgImage {
|
||||||
context.setAlpha(gradientTransition)
|
context.draw(image, in: CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 100.0)))
|
||||||
if let image = blobsState.greenGradient?.cgImage {
|
}
|
||||||
context.draw(image, in: CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 100.0)))
|
|
||||||
}
|
context.setAlpha(gradientTransition)
|
||||||
}, opaque: true, scale: deviceScale)!
|
if let image = blobsState.greenGradient?.cgImage {
|
||||||
|
context.draw(image, in: CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 100.0)))
|
||||||
|
}
|
||||||
|
}, opaque: true, scale: deviceScale)!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.saveGState()
|
context.saveGState()
|
||||||
@ -559,7 +569,10 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
|
|
||||||
context.clip(to: maskBounds, mask: radialMaskImage.cgImage!)
|
context.clip(to: maskBounds, mask: radialMaskImage.cgImage!)
|
||||||
|
|
||||||
if let gradient = gradientImage?.cgImage {
|
if parameters.simplified {
|
||||||
|
context.setFillColor(simpleColor.cgColor)
|
||||||
|
context.fill(bounds)
|
||||||
|
} else if let gradient = gradientImage?.cgImage {
|
||||||
context.draw(gradient, in: CGRect(origin: CGPoint(x: gradientCenter.x - gradientSize / 2.0, y: gradientCenter.y - gradientSize / 2.0), size: CGSize(width: gradientSize, height: gradientSize)))
|
context.draw(gradient, in: CGRect(origin: CGPoint(x: gradientCenter.x - gradientSize / 2.0, y: gradientCenter.y - gradientSize / 2.0), size: CGSize(width: gradientSize, height: gradientSize)))
|
||||||
}
|
}
|
||||||
context.restoreGState()
|
context.restoreGState()
|
||||||
@ -583,7 +596,10 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
|
|
||||||
context.setAlpha(blob.alpha)
|
context.setAlpha(blob.alpha)
|
||||||
|
|
||||||
if let gradient = gradientImage?.cgImage {
|
if parameters.simplified {
|
||||||
|
context.setFillColor(simpleColor.cgColor)
|
||||||
|
context.fill(bounds)
|
||||||
|
} else if let gradient = gradientImage?.cgImage {
|
||||||
context.draw(gradient, in: CGRect(origin: CGPoint(x: gradientCenter.x - gradientSize / 2.0, y: gradientCenter.y - gradientSize / 2.0), size: CGSize(width: gradientSize, height: gradientSize)))
|
context.draw(gradient, in: CGRect(origin: CGPoint(x: gradientCenter.x - gradientSize / 2.0, y: gradientCenter.y - gradientSize / 2.0), size: CGSize(width: gradientSize, height: gradientSize)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -660,8 +676,13 @@ private class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||||||
drawGradient = true
|
drawGradient = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if drawGradient, let gradient = gradientImage?.cgImage {
|
if drawGradient {
|
||||||
context.draw(gradient, in: CGRect(origin: CGPoint(x: gradientCenter.x - gradientSize / 2.0, y: gradientCenter.y - gradientSize / 2.0), size: CGSize(width: gradientSize, height: gradientSize)))
|
if parameters.simplified {
|
||||||
|
context.setFillColor(simpleColor.cgColor)
|
||||||
|
context.fill(bounds)
|
||||||
|
} else if let gradient = gradientImage?.cgImage {
|
||||||
|
context.draw(gradient, in: CGRect(origin: CGPoint(x: gradientCenter.x - gradientSize / 2.0, y: gradientCenter.y - gradientSize / 2.0), size: CGSize(width: gradientSize, height: gradientSize)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let clearInside = clearInside {
|
if let clearInside = clearInside {
|
||||||
@ -764,7 +785,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||||||
self.backgroundNode.audioLevel = normalizedLevel
|
self.backgroundNode.audioLevel = normalizedLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(size: CGSize, buttonSize: CGSize, state: VoiceChatActionButtonState, title: String, subtitle: String, animated: Bool = false) {
|
func update(size: CGSize, buttonSize: CGSize, state: VoiceChatActionButtonState, title: String, subtitle: String, simplified: Bool, animated: Bool = false) {
|
||||||
let updatedTitle = self.currentParams?.title != title
|
let updatedTitle = self.currentParams?.title != title
|
||||||
let updatedSubtitle = self.currentParams?.subtitle != subtitle
|
let updatedSubtitle = self.currentParams?.subtitle != subtitle
|
||||||
|
|
||||||
@ -793,7 +814,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||||||
case .connecting:
|
case .connecting:
|
||||||
backgroundState = VoiceChatActionButtonBackgroundNodeConnectingState(blueGradient: self.blueGradient)
|
backgroundState = VoiceChatActionButtonBackgroundNodeConnectingState(blueGradient: self.blueGradient)
|
||||||
}
|
}
|
||||||
self.backgroundNode.update(state: backgroundState, animated: true)
|
self.backgroundNode.update(state: backgroundState, simplified: simplified, animated: true)
|
||||||
|
|
||||||
if animated {
|
if animated {
|
||||||
if let snapshotView = self.titleLabel.view.snapshotContentTree(), updatedTitle {
|
if let snapshotView = self.titleLabel.view.snapshotContentTree(), updatedTitle {
|
||||||
@ -822,7 +843,15 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||||||
self.subtitleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - subtitleSize.width) / 2.0), y: self.titleLabel.frame.maxY + 1.0), size: subtitleSize)
|
self.subtitleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - subtitleSize.width) / 2.0), y: self.titleLabel.frame.maxY + 1.0), size: subtitleSize)
|
||||||
|
|
||||||
self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
|
self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
|
|
||||||
|
self.backgroundNode.bounds = CGRect(origin: CGPoint(), size: size)
|
||||||
|
self.backgroundNode.position = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
|
||||||
|
if simplified {
|
||||||
|
self.backgroundNode.transform = CATransform3DMakeScale(0.85, 0.85, 1.0)
|
||||||
|
} else {
|
||||||
|
self.backgroundNode.transform = CATransform3DIdentity
|
||||||
|
}
|
||||||
|
|
||||||
let iconSize = CGSize(width: 90.0, height: 90.0)
|
let iconSize = CGSize(width: 90.0, height: 90.0)
|
||||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize)
|
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize)
|
||||||
|
|
||||||
|
@ -839,8 +839,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
let sideButtonSize = CGSize(width: 60.0, height: 60.0)
|
let sideButtonSize = CGSize(width: 60.0, height: 60.0)
|
||||||
let centralButtonSize = CGSize(width: 300.0, height: 300.0)
|
let centralButtonSize = CGSize(width: 300.0, height: 300.0)
|
||||||
let sideButtonInset: CGFloat = 27.0
|
|
||||||
|
|
||||||
let actionButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - centralButtonSize.width) / 2.0), y: layout.size.height - bottomAreaHeight - layout.intrinsicInsets.bottom + floor((bottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize)
|
let actionButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - centralButtonSize.width) / 2.0), y: layout.size.height - bottomAreaHeight - layout.intrinsicInsets.bottom + floor((bottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize)
|
||||||
|
|
||||||
let actionButtonState: VoiceChatActionButtonState
|
let actionButtonState: VoiceChatActionButtonState
|
||||||
@ -888,7 +887,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.actionButton.isUserInteractionEnabled = actionButtonEnabled
|
self.actionButton.isUserInteractionEnabled = actionButtonEnabled
|
||||||
self.actionButton.update(size: centralButtonSize, buttonSize: CGSize(width: 144.0, height: 144.0), state: actionButtonState, title: actionButtonTitle, subtitle: actionButtonSubtitle, animated: true)
|
self.actionButton.update(size: centralButtonSize, buttonSize: CGSize(width: 144.0, height: 144.0), state: actionButtonState, title: actionButtonTitle, subtitle: actionButtonSubtitle, simplified: layout.size.width < 330.0, animated: true)
|
||||||
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
|
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
|
||||||
|
|
||||||
var audioMode: CallControllerButtonsSpeakerMode = .none
|
var audioMode: CallControllerButtonsSpeakerMode = .none
|
||||||
@ -942,8 +941,12 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
self.leaveNode.update(size: sideButtonSize, content: CallControllerButtonItemNode.Content(appearance: .color(.custom(0x4d120e)), image: .end), text: self.presentationData.strings.VoiceChat_Leave, transition: .immediate)
|
self.leaveNode.update(size: sideButtonSize, content: CallControllerButtonItemNode.Content(appearance: .color(.custom(0x4d120e)), image: .end), text: self.presentationData.strings.VoiceChat_Leave, transition: .immediate)
|
||||||
|
|
||||||
transition.updateFrame(node: self.audioOutputNode, frame: CGRect(origin: CGPoint(x: sideButtonInset, y: layout.size.height - bottomAreaHeight - layout.intrinsicInsets.bottom + floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
|
let sideButtonMinimalInset: CGFloat = 16.0
|
||||||
transition.updateFrame(node: self.leaveNode, frame: CGRect(origin: CGPoint(x: layout.size.width - sideButtonInset - sideButtonSize.width, y: layout.size.height - bottomAreaHeight - layout.intrinsicInsets.bottom + floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
|
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: layout.size.height - bottomAreaHeight - layout.intrinsicInsets.bottom + 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: layout.size.height - bottomAreaHeight - layout.intrinsicInsets.bottom + floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
|
||||||
|
|
||||||
if isFirstTime {
|
if isFirstTime {
|
||||||
while !self.enqueuedTransitions.isEmpty {
|
while !self.enqueuedTransitions.isEmpty {
|
||||||
|
@ -57,6 +57,7 @@ final class VoiceChatOptionsButton: HighlightableButtonNode {
|
|||||||
|
|
||||||
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 28.0, height: 28.0))
|
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 28.0, height: 28.0))
|
||||||
self.extractedContainerNode.frame = self.containerNode.bounds
|
self.extractedContainerNode.frame = self.containerNode.bounds
|
||||||
|
self.extractedContainerNode.contentRect = self.containerNode.bounds
|
||||||
self.iconNode.frame = self.containerNode.bounds
|
self.iconNode.frame = self.containerNode.bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user