mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Peer header blur
This commit is contained in:
parent
47259ef808
commit
4a3c5e4089
@ -570,6 +570,64 @@ public final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
|||||||
|
|
||||||
private let fadeWidth: CGFloat = 70.0
|
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 {
|
public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let isSettings: Bool
|
private let isSettings: Bool
|
||||||
@ -579,7 +637,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
public let controlsClippingNode: ASDisplayNode
|
public let controlsClippingNode: ASDisplayNode
|
||||||
public let controlsClippingOffsetNode: ASDisplayNode
|
public let controlsClippingOffsetNode: ASDisplayNode
|
||||||
public let topShadowNode: ASImageNode
|
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)?
|
public var storyParams: (peer: EnginePeer, items: [EngineStoryItem], count: Int, hasUnseen: Bool, hasUnseenPrivate: Bool)?
|
||||||
private var expandedStorySetIndicator: ComponentView<Empty>?
|
private var expandedStorySetIndicator: ComponentView<Empty>?
|
||||||
@ -793,10 +851,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
self.topShadowNode.displayWithoutProcessing = true
|
self.topShadowNode.displayWithoutProcessing = true
|
||||||
self.topShadowNode.contentMode = .scaleToFill
|
self.topShadowNode.contentMode = .scaleToFill
|
||||||
|
|
||||||
self.bottomShadowNode = ASImageNode()
|
self.bottomShadowNode = PeerAvatarBottomShadowNode()
|
||||||
self.bottomShadowNode.displaysAsynchronously = false
|
|
||||||
self.bottomShadowNode.displayWithoutProcessing = true
|
|
||||||
self.bottomShadowNode.contentMode = .scaleToFill
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let size = CGSize(width: 88.0, height: 88.0)
|
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.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
|
||||||
context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
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.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
||||||
context.rotate(by: CGFloat.pi / 2.0)
|
context.rotate(by: CGFloat.pi / 2.0)
|
||||||
|
@ -136,7 +136,17 @@ public final class PeerInfoCoverComponent: Component {
|
|||||||
override public init(frame: CGRect) {
|
override public init(frame: CGRect) {
|
||||||
self.backgroundView = UIView()
|
self.backgroundView = UIView()
|
||||||
self.backgroundGradientLayer = SimpleGradientLayer()
|
self.backgroundGradientLayer = SimpleGradientLayer()
|
||||||
|
|
||||||
self.avatarBackgroundGradientLayer = 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 = SimpleGradientLayer()
|
||||||
self.avatarBackgroundPatternContentsLayer.compositingFilter = "overlayBlendMode"
|
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.endPoint = CGPoint(x: 0.5, y: 0.0)
|
||||||
self.backgroundGradientLayer.type = .axial
|
self.backgroundGradientLayer.type = .axial
|
||||||
self.backgroundGradientLayer.colors = [backgroundColor.cgColor, secondaryBackgroundColor.cgColor]
|
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)
|
self.backgroundGradientLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0)
|
||||||
|
|
||||||
let gradientHeight: CGFloat = component.defaultHeight
|
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()))
|
//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)
|
transition.setFrame(layer: self.avatarBackgroundPatternContentsLayer, frame: avatarPatternFrame)
|
||||||
|
|
||||||
self.avatarBackgroundPatternContentsLayer.type = .radial
|
self.avatarBackgroundPatternContentsLayer.type = .radial
|
||||||
@ -317,16 +326,7 @@ public final class PeerInfoCoverComponent: Component {
|
|||||||
UIColor(white: 0.0, alpha: 0.0).cgColor
|
UIColor(white: 0.0, alpha: 0.0).cgColor
|
||||||
]
|
]
|
||||||
|
|
||||||
let baseAvatarGradientAlpha: CGFloat = 0.24
|
transition.setFrame(layer: self.avatarBackgroundGradientLayer, frame: CGSize(width: 300.0, height: 300.0).centered(around: component.avatarCenter))
|
||||||
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.setAlpha(layer: self.avatarBackgroundGradientLayer, alpha: 1.0 - component.avatarTransitionFraction)
|
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))
|
let backgroundPatternContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height), size: CGSize(width: availableSize.width, height: 0.0))
|
||||||
|
@ -100,6 +100,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
colors.unseenColors = unseenColors
|
colors.unseenColors = unseenColors
|
||||||
colors.unseenCloseFriendsColors = colors.unseenColors
|
colors.unseenCloseFriendsColors = colors.unseenColors
|
||||||
|
colors.seenColors = colors.unseenColors
|
||||||
} else {
|
} else {
|
||||||
regularNavigationContentsSecondaryColor = theme.list.controlSecondaryColor
|
regularNavigationContentsSecondaryColor = theme.list.controlSecondaryColor
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self.avatarClippingNode = SparseNode()
|
self.avatarClippingNode = SparseNode()
|
||||||
self.avatarClippingNode.alpha = 0.996
|
self.avatarClippingNode.alpha = 0.996
|
||||||
self.avatarClippingNode.clipsToBounds = true
|
self.avatarClippingNode.clipsToBounds = true
|
||||||
|
|
||||||
self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded, isSettings: isSettings)
|
self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded, isSettings: isSettings)
|
||||||
|
|
||||||
self.titleNodeContainer = ASDisplayNode()
|
self.titleNodeContainer = ASDisplayNode()
|
||||||
@ -262,6 +263,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
self.regularContentNode.addSubnode(self.avatarClippingNode)
|
self.regularContentNode.addSubnode(self.avatarClippingNode)
|
||||||
self.avatarClippingNode.addSubnode(self.avatarListNode)
|
self.avatarClippingNode.addSubnode(self.avatarListNode)
|
||||||
|
|
||||||
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
|
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
|
||||||
self.regularContentNode.addSubnode(self.titleNodeContainer)
|
self.regularContentNode.addSubnode(self.titleNodeContainer)
|
||||||
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
|
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
|
||||||
@ -1101,7 +1103,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
let expandedTitleScale: CGFloat = 0.8
|
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 {
|
if self.isAvatarExpanded {
|
||||||
let minTitleSize = CGSize(width: titleSize.width * expandedTitleScale, height: titleSize.height * expandedTitleScale)
|
let minTitleSize = CGSize(width: titleSize.width * expandedTitleScale, height: titleSize.height * expandedTitleScale)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user