mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Various fixes
This commit is contained in:
parent
5789d1b3e0
commit
ed8226a126
@ -173,8 +173,8 @@ final class PenTool: DrawingElement {
|
||||
self.lineWidth = lineWidth
|
||||
self.arrow = arrow
|
||||
|
||||
let minLineWidth = max(1.0, min(drawingSize.width, drawingSize.height) * 0.003)
|
||||
let maxLineWidth = max(10.0, min(drawingSize.width, drawingSize.height) * 0.09)
|
||||
let minLineWidth = max(1.0, min(drawingSize.width, drawingSize.height) * 0.0015)
|
||||
let maxLineWidth = max(10.0, min(drawingSize.width, drawingSize.height) * 0.05)
|
||||
let lineWidth = minLineWidth + (maxLineWidth - minLineWidth) * lineWidth
|
||||
|
||||
self.renderLineWidth = lineWidth
|
||||
|
||||
@ -233,59 +233,6 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
self.emitterSpotNode.layer.removeAllAnimations()
|
||||
self.emitterMaskFillNode.layer.removeAllAnimations()
|
||||
}
|
||||
|
||||
var spoilersLength: Int = 0
|
||||
if let spoilers = textNode.cachedLayout?.spoilers {
|
||||
for spoiler in spoilers {
|
||||
spoilersLength += spoiler.0.length
|
||||
}
|
||||
}
|
||||
|
||||
let timeToRead = min(45.0, ceil(max(4.0, Double(spoilersLength) * 0.04)))
|
||||
Queue.mainQueue().after(timeToRead * UIView.animationDurationFactor()) {
|
||||
if let (_, color, _, _, _) = self.currentParams {
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let animation = POPBasicAnimation()
|
||||
animation.property = (POPAnimatableProperty.property(withName: "color", initializer: { property in
|
||||
property?.readBlock = { node, values in
|
||||
if let color = (node as! InvisibleInkDustNode).emitter?.color {
|
||||
if let a = color.components {
|
||||
values?[0] = a[0]
|
||||
values?[1] = a[1]
|
||||
values?[2] = a[2]
|
||||
values?[3] = a[3]
|
||||
}
|
||||
}
|
||||
}
|
||||
property?.writeBlock = { node, values in
|
||||
if let values = values, let color = CGColor(colorSpace: colorSpace, components: values) {
|
||||
(node as! InvisibleInkDustNode).animColor = color
|
||||
(node as! InvisibleInkDustNode).updateEmitter()
|
||||
}
|
||||
}
|
||||
property?.threshold = 0.4
|
||||
}) as! POPAnimatableProperty)
|
||||
animation.fromValue = self.emitter?.color
|
||||
animation.toValue = color
|
||||
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||
animation.duration = 0.1
|
||||
animation.completionBlock = { [weak self] _, _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.animColor = nil
|
||||
strongSelf.updateEmitter()
|
||||
}
|
||||
}
|
||||
self.pop_add(animation, forKey: "color")
|
||||
}
|
||||
|
||||
Queue.mainQueue().after(0.15) {
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .linear)
|
||||
transition.updateAlpha(node: self, alpha: 1.0)
|
||||
transition.updateAlpha(node: textNode, alpha: 0.0, completion: { [weak self] _ in
|
||||
self?.isRevealed = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateEmitter() {
|
||||
|
||||
@ -257,12 +257,14 @@ public class MediaDustNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
|
||||
public func update(size: CGSize, color: UIColor) {
|
||||
public func update(size: CGSize, color: UIColor, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, color)
|
||||
|
||||
self.emitterNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.emitterMaskNode.frame = self.emitterNode.bounds
|
||||
self.emitterMaskFillNode.frame = self.emitterNode.bounds
|
||||
|
||||
let bounds = CGRect(origin: .zero, size: size)
|
||||
transition.updateFrame(node: self.emitterNode, frame: bounds)
|
||||
|
||||
self.emitterMaskNode.frame = bounds
|
||||
self.emitterMaskFillNode.frame = bounds
|
||||
|
||||
if self.isNodeLoaded {
|
||||
self.updateEmitter()
|
||||
|
||||
@ -13,6 +13,8 @@ import CheckNode
|
||||
import LegacyComponents
|
||||
import PhotoResources
|
||||
import InvisibleInkDustNode
|
||||
import ImageBlur
|
||||
import FastBlur
|
||||
|
||||
enum MediaPickerGridItemContent: Equatable {
|
||||
case asset(PHFetchResult<PHAsset>, Int)
|
||||
@ -116,6 +118,10 @@ final class MediaPickerGridItemNode: GridItemNode {
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.imageNode)
|
||||
|
||||
self.imageNode.contentUpdated = { [weak self] image in
|
||||
self?.spoilerNode?.setImage(image)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -367,14 +373,25 @@ final class MediaPickerGridItemNode: GridItemNode {
|
||||
self.updateHiddenMedia()
|
||||
}
|
||||
|
||||
private var didSetupSpoiler = false
|
||||
private func updateHasSpoiler(_ hasSpoiler: Bool) {
|
||||
var animated = true
|
||||
if !self.didSetupSpoiler {
|
||||
animated = false
|
||||
self.didSetupSpoiler = true
|
||||
}
|
||||
|
||||
if hasSpoiler {
|
||||
if self.spoilerNode == nil {
|
||||
let spoilerNode = SpoilerOverlayNode()
|
||||
self.insertSubnode(spoilerNode, aboveSubnode: self.imageNode)
|
||||
self.spoilerNode = spoilerNode
|
||||
|
||||
spoilerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
spoilerNode.setImage(self.imageNode.image)
|
||||
|
||||
if animated {
|
||||
spoilerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
self.spoilerNode?.update(size: self.bounds.size, transition: .immediate)
|
||||
self.spoilerNode?.frame = CGRect(origin: .zero, size: self.bounds.size)
|
||||
@ -422,14 +439,15 @@ final class MediaPickerGridItemNode: GridItemNode {
|
||||
}
|
||||
|
||||
class SpoilerOverlayNode: ASDisplayNode {
|
||||
private let blurNode: NavigationBackgroundNode
|
||||
private let blurNode: ASImageNode
|
||||
private let dustNode: MediaDustNode
|
||||
|
||||
private var maskView: UIView?
|
||||
private var maskLayer: CAShapeLayer?
|
||||
|
||||
override init() {
|
||||
self.blurNode = NavigationBackgroundNode(color: UIColor(rgb: 0x000000, alpha: 0.1), enableBlur: true)
|
||||
self.blurNode = ASImageNode()
|
||||
self.blurNode.displaysAsynchronously = false
|
||||
|
||||
self.dustNode = MediaDustNode()
|
||||
|
||||
@ -444,7 +462,6 @@ class SpoilerOverlayNode: ASDisplayNode {
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
|
||||
let maskView = UIView()
|
||||
self.maskView = maskView
|
||||
// self.dustNode.view.mask = maskView
|
||||
@ -456,26 +473,44 @@ class SpoilerOverlayNode: ASDisplayNode {
|
||||
self.maskLayer = maskLayer
|
||||
}
|
||||
|
||||
func setImage(_ image: UIImage?) {
|
||||
self.blurNode.image = image.flatMap { blurredImage($0) }
|
||||
}
|
||||
|
||||
func update(size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
self.blurNode.update(size: size, transition: transition)
|
||||
self.blurNode.frame = CGRect(origin: .zero, size: size)
|
||||
transition.updateFrame(node: self.blurNode, frame: CGRect(origin: .zero, size: size))
|
||||
|
||||
self.dustNode.frame = CGRect(origin: .zero, size: size)
|
||||
self.dustNode.update(size: size, color: .white)
|
||||
|
||||
// var leftOffset: CGFloat = 0.0
|
||||
// var rightOffset: CGFloat = 0.0
|
||||
// let corners = corners ?? ImageCorners(radius: 16.0)
|
||||
// if case .Tail = corners.bottomLeft {
|
||||
// leftOffset = 4.0
|
||||
// } else if case .Tail = corners.bottomRight {
|
||||
// rightOffset = 4.0
|
||||
// }
|
||||
// let rect = CGRect(origin: CGPoint(x: leftOffset, y: 0.0), size: CGSize(width: size.width - leftOffset - rightOffset, height: size.height))
|
||||
// let path = UIBezierPath(roundRect: rect, topLeftRadius: corners.topLeft.radius, topRightRadius: corners.topRight.radius, bottomLeftRadius: corners.bottomLeft.radius, bottomRightRadius: corners.bottomRight.radius)
|
||||
// let buttonPath = UIBezierPath(roundedRect: self.buttonNode.frame, cornerRadius: 16.0)
|
||||
// path.append(buttonPath)
|
||||
// path.usesEvenOddFillRule = true
|
||||
// self.maskLayer?.path = path.cgPath
|
||||
transition.updateFrame(node: self.dustNode, frame: CGRect(origin: .zero, size: size))
|
||||
self.dustNode.update(size: size, color: .white, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private func blurredImage(_ image: UIImage) -> UIImage? {
|
||||
guard let image = image.cgImage else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let thumbnailSize = CGSize(width: image.width, height: image.height)
|
||||
let thumbnailContextSize = thumbnailSize.aspectFilled(CGSize(width: 20.0, height: 20.0))
|
||||
if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) {
|
||||
thumbnailContext.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
c.draw(image, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||
|
||||
let thumbnailContext2Size = thumbnailSize.aspectFitted(CGSize(width: 100.0, height: 100.0))
|
||||
if let thumbnailContext2 = DrawingContext(size: thumbnailContext2Size, scale: 1.0) {
|
||||
thumbnailContext2.withFlippedContext { c in
|
||||
c.interpolationQuality = .none
|
||||
if let image = thumbnailContext.generateImage()?.cgImage {
|
||||
c.draw(image, in: CGRect(origin: CGPoint(), size: thumbnailContext2Size))
|
||||
}
|
||||
}
|
||||
imageFastBlur(Int32(thumbnailContext2Size.width), Int32(thumbnailContext2Size.height), Int32(thumbnailContext2.bytesPerRow), thumbnailContext2.bytes)
|
||||
adjustSaturationInContext(context: thumbnailContext2, saturation: 1.7)
|
||||
return thumbnailContext2.generateImage()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -131,6 +131,10 @@ private class MediaPickerSelectedItemNode: ASDisplayNode {
|
||||
strongSelf.updateHasSpoiler(hasSpoiler)
|
||||
}))
|
||||
}
|
||||
|
||||
self.imageNode.contentUpdated = { [weak self] image in
|
||||
self?.spoilerNode?.setImage(image)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -151,14 +155,25 @@ private class MediaPickerSelectedItemNode: ASDisplayNode {
|
||||
self.interaction?.openSelectedMedia(asset, self.imageNode.image)
|
||||
}
|
||||
|
||||
private var didSetupSpoiler = false
|
||||
private func updateHasSpoiler(_ hasSpoiler: Bool) {
|
||||
var animated = true
|
||||
if !self.didSetupSpoiler {
|
||||
animated = false
|
||||
self.didSetupSpoiler = true
|
||||
}
|
||||
|
||||
if hasSpoiler {
|
||||
if self.spoilerNode == nil {
|
||||
let spoilerNode = SpoilerOverlayNode()
|
||||
self.insertSubnode(spoilerNode, aboveSubnode: self.imageNode)
|
||||
self.spoilerNode = spoilerNode
|
||||
|
||||
spoilerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
spoilerNode.setImage(self.imageNode.image)
|
||||
|
||||
if animated {
|
||||
spoilerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
self.spoilerNode?.update(size: self.bounds.size, transition: .immediate)
|
||||
self.spoilerNode?.frame = CGRect(origin: .zero, size: self.bounds.size)
|
||||
@ -616,11 +631,15 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI
|
||||
}
|
||||
}
|
||||
|
||||
self.messageNodes?.first?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
self.messageNodes?.first?.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -30.0), duration: 0.4, delay: 0.0, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
if let topNode = self.messageNodes?.first {
|
||||
topNode.layer.animateAlpha(from: topNode.alpha, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
topNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -30.0), duration: 0.4, delay: 0.0, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
}
|
||||
|
||||
self.messageNodes?.last?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
self.messageNodes?.last?.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: 30.0), duration: 0.4, delay: 0.0, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
if let bottomNode = self.messageNodes?.last {
|
||||
bottomNode.layer.animateAlpha(from: bottomNode.alpha, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
bottomNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: 30.0), duration: 0.4, delay: 0.0, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
}
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
|
||||
@ -1157,7 +1157,7 @@ public func chatSecretPhoto(account: Account, photoReference: ImageMediaReferenc
|
||||
}
|
||||
}
|
||||
|
||||
private func adjustSaturationInContext(context: DrawingContext, saturation: CGFloat) {
|
||||
public func adjustSaturationInContext(context: DrawingContext, saturation: CGFloat) {
|
||||
var buffer = vImage_Buffer()
|
||||
buffer.data = context.bytes
|
||||
buffer.width = UInt(context.size.width * context.scale)
|
||||
|
||||
@ -251,15 +251,15 @@ private class ExtendedMediaOverlayNode: ASDisplayNode {
|
||||
self.maskLayer = maskLayer
|
||||
}
|
||||
|
||||
func update(size: CGSize, text: String, imageSignal: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize)?, imageFrame: CGRect, corners: ImageCorners?) {
|
||||
func update(size: CGSize, text: String, imageSignal: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize, CGSize)?, imageFrame: CGRect, corners: ImageCorners?) {
|
||||
let spacing: CGFloat = 2.0
|
||||
let padding: CGFloat = 10.0
|
||||
|
||||
if let (imageSignal, drawingSize) = imageSignal {
|
||||
if let (imageSignal, drawingSize, boundingSize) = imageSignal {
|
||||
self.blurredImageNode.setSignal(imageSignal)
|
||||
|
||||
let imageLayout = self.blurredImageNode.asyncLayout()
|
||||
let arguments = TransformImageArguments(corners: corners ?? ImageCorners(), imageSize: drawingSize, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets(), resizeMode: .blurBackground, emptyColor: .clear, custom: nil)
|
||||
let arguments = TransformImageArguments(corners: corners ?? ImageCorners(), imageSize: drawingSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .blurBackground, emptyColor: .clear, custom: nil)
|
||||
let apply = imageLayout(arguments)
|
||||
apply()
|
||||
|
||||
@ -277,7 +277,7 @@ private class ExtendedMediaOverlayNode: ASDisplayNode {
|
||||
self.blurredImageNode.frame = imageFrame
|
||||
|
||||
self.dustNode.frame = CGRect(origin: .zero, size: size)
|
||||
self.dustNode.update(size: size, color: .white)
|
||||
self.dustNode.update(size: size, color: .white, transition: .immediate)
|
||||
|
||||
if text.isEmpty {
|
||||
self.buttonNode.isHidden = true
|
||||
@ -320,7 +320,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
private let imageNode: TransformImageNode
|
||||
private var currentImageArguments: TransformImageArguments?
|
||||
private var currentHighQualityImageSignal: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize)?
|
||||
private var currentBlurredImageSignal: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize)?
|
||||
private var currentBlurredImageSignal: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize, CGSize)?
|
||||
private var highQualityImageNode: TransformImageNode?
|
||||
|
||||
private var videoNode: UniversalVideoNode?
|
||||
@ -1360,13 +1360,11 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
strongSelf.currentHighQualityImageSignal = (updateImageSignal(false, true), imageDimensions)
|
||||
|
||||
if let updateBlurredImageSignal = updateBlurredImageSignal {
|
||||
strongSelf.currentBlurredImageSignal = (updateBlurredImageSignal(false, true), imageDimensions)
|
||||
strongSelf.currentBlurredImageSignal = (updateBlurredImageSignal(false, true), drawingSize, boundingSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if let _ = secretBeginTimeAndTimeout {
|
||||
if updatedStatusSignal == nil, let fetchStatus = strongSelf.fetchStatus, case .Local = fetchStatus {
|
||||
if let statusNode = strongSelf.statusNode, case .secretTimeout = statusNode.state {
|
||||
|
||||
@ -4789,9 +4789,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
|
||||
var canReport = true
|
||||
if channel.isVerified {
|
||||
canReport = false
|
||||
}
|
||||
if channel.adminRights != nil {
|
||||
canReport = false
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user