mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Experimental avatar blur extension
This commit is contained in:
parent
aeabb402d1
commit
a59d8e3247
@ -585,7 +585,7 @@ public final class PeerAvatarBottomShadowNode: ASDisplayNode {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
//self.backgroundColor = .blue
|
//self.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
|
||||||
|
|
||||||
self.backgroundGradientMaskLayer.type = .axial
|
self.backgroundGradientMaskLayer.type = .axial
|
||||||
self.backgroundGradientMaskLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
|
self.backgroundGradientMaskLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
|
||||||
@ -594,7 +594,7 @@ public final class PeerAvatarBottomShadowNode: ASDisplayNode {
|
|||||||
let baseGradientAlpha: CGFloat = 1.0
|
let baseGradientAlpha: CGFloat = 1.0
|
||||||
let numSteps = 8
|
let numSteps = 8
|
||||||
let firstStep = 1
|
let firstStep = 1
|
||||||
let firstLocation = 0.4
|
let firstLocation = 0.7
|
||||||
self.backgroundGradientMaskLayer.colors = (0 ..< numSteps).map { i in
|
self.backgroundGradientMaskLayer.colors = (0 ..< numSteps).map { i in
|
||||||
if i < firstStep {
|
if i < firstStep {
|
||||||
return UIColor(white: 1.0, alpha: 1.0).cgColor
|
return UIColor(white: 1.0, alpha: 1.0).cgColor
|
||||||
@ -628,6 +628,46 @@ public final class PeerAvatarBottomShadowNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class AvatarListContentNode: ASDisplayNode {
|
||||||
|
final class View: UIView {
|
||||||
|
override static var layerClass: AnyClass {
|
||||||
|
return CAReplicatorLayer.self
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
let replicatorLayer = self.layer as! CAReplicatorLayer
|
||||||
|
replicatorLayer.instanceCount = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(size: CGSize) {
|
||||||
|
var instanceTransform = CATransform3DIdentity
|
||||||
|
instanceTransform = CATransform3DTranslate(instanceTransform, 0.0, (size.width - (size.height - size.width)) * 1.5 - 4.0, 0.0)
|
||||||
|
instanceTransform = CATransform3DScale(instanceTransform, 1.0, -2.0, 1.0)
|
||||||
|
|
||||||
|
let replicatorLayer = self.layer as! CAReplicatorLayer
|
||||||
|
replicatorLayer.instanceTransform = instanceTransform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.setViewBlock({
|
||||||
|
return View(frame: CGRect())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(size: CGSize) {
|
||||||
|
(self.view as? View)?.update(size: size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let isSettings: Bool
|
private let isSettings: Bool
|
||||||
@ -649,7 +689,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public let contentNode: ASDisplayNode
|
public let contentNode: AvatarListContentNode
|
||||||
let leftHighlightNode: ASDisplayNode
|
let leftHighlightNode: ASDisplayNode
|
||||||
let rightHighlightNode: ASDisplayNode
|
let rightHighlightNode: ASDisplayNode
|
||||||
var highlightedSide: Bool?
|
var highlightedSide: Bool?
|
||||||
@ -777,7 +817,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
self.context = context
|
self.context = context
|
||||||
self.isSettings = isSettings
|
self.isSettings = isSettings
|
||||||
|
|
||||||
self.contentNode = ASDisplayNode()
|
self.contentNode = AvatarListContentNode()
|
||||||
|
|
||||||
self.leftHighlightNode = ASDisplayNode()
|
self.leftHighlightNode = ASDisplayNode()
|
||||||
self.leftHighlightNode.displaysAsynchronously = false
|
self.leftHighlightNode.displaysAsynchronously = false
|
||||||
@ -1461,7 +1501,8 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
itemNode.delayCentralityLose = false
|
itemNode.delayCentralityLose = false
|
||||||
|
|
||||||
let indexOffset = CGFloat(i - self.currentIndex)
|
let indexOffset = CGFloat(i - self.currentIndex)
|
||||||
let itemFrame = CGRect(origin: CGPoint(x: indexOffset * size.width + self.transitionFraction * size.width - size.width / 2.0, y: -size.height / 2.0), size: size)
|
var itemFrame = CGRect(origin: CGPoint(x: indexOffset * size.width + self.transitionFraction * size.width - size.width / 2.0, y: -size.height / 2.0), size: size)
|
||||||
|
itemFrame.origin.y -= (size.height - size.width) * 0.5
|
||||||
|
|
||||||
if wasAdded {
|
if wasAdded {
|
||||||
itemsAdded = true
|
itemsAdded = true
|
||||||
|
@ -822,7 +822,14 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||||
|
|
||||||
let expandedAvatarControlsHeight: CGFloat = 61.0
|
let expandedAvatarControlsHeight: CGFloat = 61.0
|
||||||
let expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
|
var expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
|
||||||
|
if self.isSettings {
|
||||||
|
expandedAvatarListHeight = expandedAvatarListHeight + 60.0
|
||||||
|
} else {
|
||||||
|
let avatarEnlargementFactor: CGFloat = 1.35
|
||||||
|
expandedAvatarListHeight = floor(expandedAvatarListHeight * avatarEnlargementFactor)
|
||||||
|
}
|
||||||
|
|
||||||
let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight)
|
let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight)
|
||||||
|
|
||||||
let actionButtonKeys: [PeerInfoHeaderButtonKey] = self.isSettings ? [] : peerInfoHeaderActionButtons(peer: peer, isSecretChat: isSecretChat, isContact: isContact)
|
let actionButtonKeys: [PeerInfoHeaderButtonKey] = self.isSettings ? [] : peerInfoHeaderActionButtons(peer: peer, isSecretChat: isSecretChat, isContact: isContact)
|
||||||
@ -1119,7 +1126,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
let expandedTitleScale: CGFloat = 0.8
|
let expandedTitleScale: CGFloat = 0.8
|
||||||
|
|
||||||
var bottomShadowHeight: CGFloat = 72.0
|
var bottomShadowHeight: CGFloat = 82.0
|
||||||
if !self.isSettings {
|
if !self.isSettings {
|
||||||
bottomShadowHeight += 80.0
|
bottomShadowHeight += 80.0
|
||||||
}
|
}
|
||||||
@ -1321,10 +1328,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var apparentAvatarFrame: CGRect
|
var apparentAvatarFrame: CGRect
|
||||||
|
var apparentAvatarListFrame: CGRect
|
||||||
let controlsClippingFrame: CGRect
|
let controlsClippingFrame: CGRect
|
||||||
if self.isAvatarExpanded {
|
if self.isAvatarExpanded {
|
||||||
let expandedAvatarCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - contentOffset / 2.0)
|
let expandedAvatarCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.width / 2.0 - contentOffset / 2.0)
|
||||||
apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize())
|
apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize())
|
||||||
|
|
||||||
|
let expandedAvatarListCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - contentOffset / 2.0)
|
||||||
|
apparentAvatarListFrame = CGRect(origin: CGPoint(x: expandedAvatarListCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarListCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize())
|
||||||
|
|
||||||
if let transitionSourceAvatarFrame = transitionSourceAvatarFrame {
|
if let transitionSourceAvatarFrame = transitionSourceAvatarFrame {
|
||||||
var trueAvatarSize = transitionSourceAvatarFrame.size
|
var trueAvatarSize = transitionSourceAvatarFrame.size
|
||||||
if let storyStats = self.avatarListNode.avatarContainerNode.avatarNode.storyStats, storyStats.unseenCount != 0 {
|
if let storyStats = self.avatarListNode.avatarContainerNode.avatarNode.storyStats, storyStats.unseenCount != 0 {
|
||||||
@ -1345,6 +1357,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
trueAvatarSize.height -= 3.0 * 4.0
|
trueAvatarSize.height -= 3.0 * 4.0
|
||||||
}
|
}
|
||||||
apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - trueAvatarSize.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - trueAvatarSize.height / 2.0), size: trueAvatarSize)
|
apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - trueAvatarSize.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - trueAvatarSize.height / 2.0), size: trueAvatarSize)
|
||||||
|
apparentAvatarListFrame = apparentAvatarFrame
|
||||||
controlsClippingFrame = apparentAvatarFrame
|
controlsClippingFrame = apparentAvatarFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1355,6 +1368,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
let clippingNodeRadiusTransition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut)
|
let clippingNodeRadiusTransition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut)
|
||||||
clippingNodeRadiusTransition.updateCornerRadius(node: self.avatarClippingNode, cornerRadius: avatarClipOffset > 0.0 ? width / 2.5 : 0.0)
|
clippingNodeRadiusTransition.updateCornerRadius(node: self.avatarClippingNode, cornerRadius: avatarClipOffset > 0.0 ? width / 2.5 : 0.0)
|
||||||
|
|
||||||
|
let _ = apparentAvatarListFrame
|
||||||
transition.updateFrameAdditive(node: self.avatarListNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize()))
|
transition.updateFrameAdditive(node: self.avatarListNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize()))
|
||||||
transition.updateFrameAdditive(node: self.avatarOverlayNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize()))
|
transition.updateFrameAdditive(node: self.avatarOverlayNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize()))
|
||||||
|
|
||||||
@ -1370,21 +1384,26 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
avatarListContainerSize.height -= 1.33 * 5.0
|
avatarListContainerSize.height -= 1.33 * 5.0
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarListContainerFrame = CGRect(origin: CGPoint(x: -avatarListContainerSize.width / 2.0, y: -avatarListContainerSize.height / 2.0), size: avatarListContainerSize)
|
avatarListContainerFrame = CGRect(origin: CGPoint(x: -avatarListContainerSize.width / 2.0, y: -avatarListContainerSize.width / 2.0), size: avatarListContainerSize)
|
||||||
} else {
|
} else {
|
||||||
avatarListContainerFrame = CGRect(origin: CGPoint(x: -expandedAvatarListSize.width / 2.0, y: -expandedAvatarListSize.height / 2.0), size: expandedAvatarListSize)
|
avatarListContainerFrame = CGRect(origin: CGPoint(x: -expandedAvatarListSize.width / 2.0, y: -expandedAvatarListSize.width / 2.0), size: expandedAvatarListSize)
|
||||||
}
|
}
|
||||||
avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.height)
|
avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.width)
|
||||||
} else {
|
} else {
|
||||||
avatarListContainerFrame = CGRect(origin: CGPoint(x: -apparentAvatarFrame.width / 2.0, y: -apparentAvatarFrame.height / 2.0), size: apparentAvatarFrame.size)
|
let expandHeightFraction = expandedAvatarListSize.height / expandedAvatarListSize.width
|
||||||
|
avatarListContainerFrame = CGRect(origin: CGPoint(x: -apparentAvatarFrame.width / 2.0, y: -apparentAvatarFrame.width / 2.0 + expandHeightFraction * 0.0 * apparentAvatarFrame.width), size: apparentAvatarFrame.size)
|
||||||
avatarListContainerScale = avatarScale
|
avatarListContainerScale = avatarScale
|
||||||
}
|
}
|
||||||
transition.updateFrame(node: self.avatarListNode.listContainerNode, frame: avatarListContainerFrame)
|
transition.updateFrame(node: self.avatarListNode.listContainerNode, frame: avatarListContainerFrame)
|
||||||
let innerScale = avatarListContainerFrame.height / expandedAvatarListSize.height
|
let innerScale = avatarListContainerFrame.width / expandedAvatarListSize.width
|
||||||
let innerDeltaX = (avatarListContainerFrame.width - expandedAvatarListSize.width) / 2.0
|
let innerDeltaX = (avatarListContainerFrame.width - expandedAvatarListSize.width) / 2.0
|
||||||
let innerDeltaY = (avatarListContainerFrame.height - expandedAvatarListSize.height) / 2.0
|
var innerDeltaY = (avatarListContainerFrame.height - expandedAvatarListSize.height) / 2.0
|
||||||
|
if !self.isAvatarExpanded {
|
||||||
|
innerDeltaY += (expandedAvatarListSize.height - expandedAvatarListSize.width) * 0.5
|
||||||
|
}
|
||||||
transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale)
|
transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale)
|
||||||
transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDeltaX + expandedAvatarListSize.width / 2.0, y: innerDeltaY + expandedAvatarListSize.height / 2.0), size: CGSize()))
|
transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDeltaX + expandedAvatarListSize.width / 2.0, y: innerDeltaY + expandedAvatarListSize.height / 2.0), size: CGSize()))
|
||||||
|
self.avatarListNode.listContainerNode.contentNode.update(size: expandedAvatarListSize)
|
||||||
|
|
||||||
transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsClippingOffsetNode, frame: CGRect(origin: controlsClippingFrame.center, size: CGSize()))
|
transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsClippingOffsetNode, frame: CGRect(origin: controlsClippingFrame.center, size: CGSize()))
|
||||||
transition.updateFrame(node: self.avatarListNode.listContainerNode.controlsClippingNode, frame: CGRect(origin: CGPoint(x: -controlsClippingFrame.width / 2.0, y: -controlsClippingFrame.height / 2.0), size: controlsClippingFrame.size))
|
transition.updateFrame(node: self.avatarListNode.listContainerNode.controlsClippingNode, frame: CGRect(origin: CGPoint(x: -controlsClippingFrame.width / 2.0, y: -controlsClippingFrame.height / 2.0), size: controlsClippingFrame.size))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user