Experimental avatar blur extension

This commit is contained in:
Isaac 2023-11-27 00:53:36 +04:00
parent aeabb402d1
commit a59d8e3247
2 changed files with 74 additions and 14 deletions

View File

@ -585,7 +585,7 @@ public final class PeerAvatarBottomShadowNode: ASDisplayNode {
super.init()
//self.backgroundColor = .blue
//self.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
self.backgroundGradientMaskLayer.type = .axial
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 numSteps = 8
let firstStep = 1
let firstLocation = 0.4
let firstLocation = 0.7
self.backgroundGradientMaskLayer.colors = (0 ..< numSteps).map { i in
if i < firstStep {
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 {
private let context: AccountContext
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 rightHighlightNode: ASDisplayNode
var highlightedSide: Bool?
@ -777,7 +817,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
self.context = context
self.isSettings = isSettings
self.contentNode = ASDisplayNode()
self.contentNode = AvatarListContentNode()
self.leftHighlightNode = ASDisplayNode()
self.leftHighlightNode.displaysAsynchronously = false
@ -1461,7 +1501,8 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
itemNode.delayCentralityLose = false
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 {
itemsAdded = true

View File

@ -822,7 +822,14 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
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 actionButtonKeys: [PeerInfoHeaderButtonKey] = self.isSettings ? [] : peerInfoHeaderActionButtons(peer: peer, isSecretChat: isSecretChat, isContact: isContact)
@ -1119,7 +1126,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let expandedTitleScale: CGFloat = 0.8
var bottomShadowHeight: CGFloat = 72.0
var bottomShadowHeight: CGFloat = 82.0
if !self.isSettings {
bottomShadowHeight += 80.0
}
@ -1321,10 +1328,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
var apparentAvatarFrame: CGRect
var apparentAvatarListFrame: CGRect
let controlsClippingFrame: CGRect
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())
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 {
var trueAvatarSize = transitionSourceAvatarFrame.size
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
}
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
}
@ -1355,6 +1368,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let clippingNodeRadiusTransition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut)
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.avatarOverlayNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize()))
@ -1370,21 +1384,26 @@ final class PeerInfoHeaderNode: ASDisplayNode {
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 {
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 {
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
}
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 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.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.updateFrame(node: self.avatarListNode.listContainerNode.controlsClippingNode, frame: CGRect(origin: CGPoint(x: -controlsClippingFrame.width / 2.0, y: -controlsClippingFrame.height / 2.0), size: controlsClippingFrame.size))