Peer header blur

This commit is contained in:
Isaac 2023-11-24 13:52:21 +04:00
parent 47259ef808
commit 4a3c5e4089
4 changed files with 83 additions and 19 deletions

View File

@ -570,6 +570,64 @@ public final class PeerInfoAvatarListItemNode: ASDisplayNode {
private let fadeWidth: CGFloat = 70.0
public final class PeerAvatarBottomShadowNode: ASDisplayNode {
let backgroundNode: NavigationBackgroundNode
let backgroundGradientMaskLayer: SimpleGradientLayer
let imageView: UIImageView
override init() {
self.backgroundNode = NavigationBackgroundNode(color: .black, enableBlur: true)
self.backgroundGradientMaskLayer = SimpleGradientLayer()
self.backgroundNode.layer.mask = self.backgroundGradientMaskLayer
self.imageView = UIImageView()
self.imageView.contentMode = .scaleToFill
super.init()
//self.backgroundColor = .blue
self.backgroundGradientMaskLayer.type = .axial
self.backgroundGradientMaskLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
self.backgroundGradientMaskLayer.endPoint = CGPoint(x: 0.0, y: 0.0)
let baseGradientAlpha: CGFloat = 1.0
let numSteps = 8
let firstStep = 1
let firstLocation = 0.6
self.backgroundGradientMaskLayer.colors = (0 ..< numSteps).map { i in
if i < firstStep {
return UIColor(white: 1.0, alpha: 1.0).cgColor
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
return UIColor(white: 1.0, alpha: baseGradientAlpha * (1.0 - pow(step, 3.0))).cgColor
}
}
self.backgroundGradientMaskLayer.locations = (0 ..< numSteps).map { i -> NSNumber in
if i < firstStep {
return 0.0 as NSNumber
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
return (firstLocation + (1.0 - firstLocation) * step) as NSNumber
}
}
self.backgroundNode.updateColor(color: UIColor(white: 0.0, alpha: 0.1), enableSaturation: false, forceKeepBlur: true, transition: .immediate)
self.addSubnode(self.backgroundNode)
//self.layer.addSublayer(self.backgroundGradientMaskLayer)
//self.view.addSubview(self.imageView)
}
public func update(size: CGSize, transition: ContainedViewLayoutTransition) {
transition.updateFrame(view: self.imageView, frame: CGRect(origin: CGPoint(), size: size), beginWithCurrentState: true)
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size), beginWithCurrentState: true)
transition.updateFrame(layer: self.backgroundGradientMaskLayer, frame: CGRect(origin: CGPoint(), size: size), beginWithCurrentState: true)
self.backgroundNode.update(size: size, transition: transition)
}
}
public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
private let context: AccountContext
private let isSettings: Bool
@ -579,7 +637,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
public let controlsClippingNode: ASDisplayNode
public let controlsClippingOffsetNode: ASDisplayNode
public let topShadowNode: ASImageNode
public let bottomShadowNode: ASImageNode
public let bottomShadowNode: PeerAvatarBottomShadowNode
public var storyParams: (peer: EnginePeer, items: [EngineStoryItem], count: Int, hasUnseen: Bool, hasUnseenPrivate: Bool)?
private var expandedStorySetIndicator: ComponentView<Empty>?
@ -793,10 +851,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
self.topShadowNode.displayWithoutProcessing = true
self.topShadowNode.contentMode = .scaleToFill
self.bottomShadowNode = ASImageNode()
self.bottomShadowNode.displaysAsynchronously = false
self.bottomShadowNode.displayWithoutProcessing = true
self.bottomShadowNode.contentMode = .scaleToFill
self.bottomShadowNode = PeerAvatarBottomShadowNode()
do {
let size = CGSize(width: 88.0, height: 88.0)
@ -825,7 +880,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size))
})
self.bottomShadowNode.image = generateImage(image.size, contextGenerator: { size, context in
self.bottomShadowNode.imageView.image = generateImage(image.size, contextGenerator: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
context.rotate(by: CGFloat.pi / 2.0)

View File

@ -136,7 +136,17 @@ public final class PeerInfoCoverComponent: Component {
override public init(frame: CGRect) {
self.backgroundView = UIView()
self.backgroundGradientLayer = SimpleGradientLayer()
self.avatarBackgroundGradientLayer = SimpleGradientLayer()
let baseAvatarGradientAlpha: CGFloat = 0.4
let numSteps = 6
self.avatarBackgroundGradientLayer.colors = (0 ..< numSteps).map { i in
let step: CGFloat = 1.0 - CGFloat(i) / CGFloat(numSteps - 1)
return UIColor(white: 1.0, alpha: baseAvatarGradientAlpha * pow(step, 2.0)).cgColor
}
self.avatarBackgroundGradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
self.avatarBackgroundGradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
self.avatarBackgroundGradientLayer.type = .radial
self.avatarBackgroundPatternContentsLayer = SimpleGradientLayer()
self.avatarBackgroundPatternContentsLayer.compositingFilter = "overlayBlendMode"
@ -282,7 +292,6 @@ public final class PeerInfoCoverComponent: Component {
self.backgroundGradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
self.backgroundGradientLayer.type = .axial
self.backgroundGradientLayer.colors = [backgroundColor.cgColor, secondaryBackgroundColor.cgColor]
//self.backgroundGradientLayer.colors = [UIColor.green.cgColor, UIColor.blue.cgColor]
self.backgroundGradientLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
let gradientHeight: CGFloat = component.defaultHeight
@ -306,7 +315,7 @@ public final class PeerInfoCoverComponent: Component {
//transition.setFrame(view: self.avatarBackgroundPatternView, frame: CGSize(width: 200.0, height: 200.0).centered(around: CGPoint()))
let avatarPatternFrame = CGSize(width: 400.0, height: 400.0).centered(around: component.avatarCenter)
let avatarPatternFrame = CGSize(width: 380.0, height: 380.0).centered(around: component.avatarCenter)
transition.setFrame(layer: self.avatarBackgroundPatternContentsLayer, frame: avatarPatternFrame)
self.avatarBackgroundPatternContentsLayer.type = .radial
@ -317,16 +326,7 @@ public final class PeerInfoCoverComponent: Component {
UIColor(white: 0.0, alpha: 0.0).cgColor
]
let baseAvatarGradientAlpha: CGFloat = 0.24
let numSteps = 10
self.avatarBackgroundGradientLayer.colors = (0 ..< 10).map { i in
let step: CGFloat = 1.0 - CGFloat(i) / CGFloat(numSteps - 1)
return UIColor(white: 1.0, alpha: baseAvatarGradientAlpha * pow(step, 3.0)).cgColor
}
self.avatarBackgroundGradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
self.avatarBackgroundGradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
self.avatarBackgroundGradientLayer.type = .radial
transition.setFrame(layer: self.avatarBackgroundGradientLayer, frame: CGSize(width: 260.0, height: 260.0).centered(around: component.avatarCenter))
transition.setFrame(layer: self.avatarBackgroundGradientLayer, frame: CGSize(width: 300.0, height: 300.0).centered(around: component.avatarCenter))
transition.setAlpha(layer: self.avatarBackgroundGradientLayer, alpha: 1.0 - component.avatarTransitionFraction)
let backgroundPatternContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height), size: CGSize(width: availableSize.width, height: 0.0))

View File

@ -100,6 +100,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
}
colors.unseenColors = unseenColors
colors.unseenCloseFriendsColors = colors.unseenColors
colors.seenColors = colors.unseenColors
} else {
regularNavigationContentsSecondaryColor = theme.list.controlSecondaryColor
}

View File

@ -173,6 +173,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.avatarClippingNode = SparseNode()
self.avatarClippingNode.alpha = 0.996
self.avatarClippingNode.clipsToBounds = true
self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded, isSettings: isSettings)
self.titleNodeContainer = ASDisplayNode()
@ -262,6 +263,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.regularContentNode.addSubnode(self.avatarClippingNode)
self.avatarClippingNode.addSubnode(self.avatarListNode)
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
self.regularContentNode.addSubnode(self.titleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
@ -1101,7 +1103,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let expandedTitleScale: CGFloat = 0.8
transition.updateFrame(node: self.avatarListNode.listContainerNode.bottomShadowNode, frame: CGRect(origin: CGPoint(x: 0.0, y: expandedAvatarHeight - 70.0), size: CGSize(width: width, height: 70.0)))
var bottomShadowHeight: CGFloat = 72.0
if !self.isSettings {
bottomShadowHeight += 80.0
}
let bottomShadowFrame = CGRect(origin: CGPoint(x: 0.0, y: expandedAvatarHeight - bottomShadowHeight), size: CGSize(width: width, height: bottomShadowHeight))
transition.updateFrame(node: self.avatarListNode.listContainerNode.bottomShadowNode, frame: bottomShadowFrame, beginWithCurrentState: true)
self.avatarListNode.listContainerNode.bottomShadowNode.update(size: bottomShadowFrame.size, transition: transition)
if self.isAvatarExpanded {
let minTitleSize = CGSize(width: titleSize.width * expandedTitleScale, height: titleSize.height * expandedTitleScale)