chore: migrate to new version + fixed several critical bugs

- Migrated project to latest Telegram iOS base (v12.3.2+)
- Fixed circular dependency between GhostModeManager and MiscSettingsManager
- Fixed multiple Bazel build configuration errors (select() default conditions)
- Fixed duplicate type definitions in PeerInfoScreen
- Fixed swiftmodule directory resolution in build scripts
- Added Ghostgram Settings tab in main Settings menu with all 5 features
- Cleared sensitive credentials from config.json (template-only now)
- Excluded bazel-cache from version control
This commit is contained in:
ichmagmaus 812
2026-02-23 23:04:32 +01:00
parent 703e291bcb
commit db53826061
1017 changed files with 62337 additions and 40559 deletions
@@ -292,16 +292,18 @@ public class GlassBackgroundView: UIView {
public let isDark: Bool
public let tintColor: TintColor
public let isInteractive: Bool
public let isVisible: Bool
init(shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool) {
init(shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool, isVisible: Bool) {
self.shape = shape
self.isDark = isDark
self.tintColor = tintColor
self.isInteractive = isInteractive
self.isVisible = isVisible
}
}
private let backgroundNode: NavigationBackgroundNode?
private let legacyView: LegacyGlassView?
private let nativeView: UIVisualEffectView?
private let nativeViewClippingContext: ClippingShapeContext?
@@ -330,7 +332,7 @@ public class GlassBackgroundView: UIView {
public override init(frame: CGRect) {
if #available(iOS 26.0, *), !GlassBackgroundView.useCustomGlassImpl {
self.backgroundNode = nil
self.legacyView = nil
let glassEffect = UIGlassEffect(style: .regular)
glassEffect.isInteractive = false
@@ -346,8 +348,7 @@ public class GlassBackgroundView: UIView {
self.foregroundView = nil
self.shadowView = nil
} else {
let backgroundNode = NavigationBackgroundNode(color: .black, enableBlur: true, customBlurRadius: 8.0)
self.backgroundNode = backgroundNode
self.legacyView = LegacyGlassView(frame: CGRect())
self.nativeView = nil
self.nativeViewClippingContext = nil
self.nativeParamsView = nil
@@ -375,8 +376,8 @@ public class GlassBackgroundView: UIView {
if let nativeParamsView = self.nativeParamsView {
self.addSubview(nativeParamsView)
}
if let backgroundNode = self.backgroundNode {
self.addSubview(backgroundNode.view)
if let legacyView = self.legacyView {
self.addSubview(legacyView)
}
if let foregroundView = self.foregroundView {
self.addSubview(foregroundView)
@@ -390,6 +391,15 @@ public class GlassBackgroundView: UIView {
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.isUserInteractionEnabled {
return nil
}
if self.isHidden {
return nil
}
if self.alpha == 0.0 {
return nil
}
if let nativeView = self.nativeView {
if let result = nativeView.hitTest(self.convert(point, to: nativeView), with: event) {
return result
@@ -402,11 +412,11 @@ public class GlassBackgroundView: UIView {
return nil
}
public func update(size: CGSize, cornerRadius: CGFloat, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, transition: ComponentTransition) {
self.update(size: size, shape: .roundedRect(cornerRadius: cornerRadius), isDark: isDark, tintColor: tintColor, isInteractive: isInteractive, transition: transition)
public func update(size: CGSize, cornerRadius: CGFloat, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, isVisible: Bool = true, transition: ComponentTransition) {
self.update(size: size, shape: .roundedRect(cornerRadius: cornerRadius), isDark: isDark, tintColor: tintColor, isInteractive: isInteractive, isVisible: isVisible, transition: transition)
}
public func update(size: CGSize, shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, transition: ComponentTransition) {
public func update(size: CGSize, shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, isVisible: Bool = true, transition: ComponentTransition) {
if let nativeView = self.nativeView, let nativeViewClippingContext = self.nativeViewClippingContext, (nativeView.bounds.size != size || nativeViewClippingContext.shape != shape) {
nativeViewClippingContext.update(shape: shape, size: size, transition: transition)
@@ -416,15 +426,15 @@ public class GlassBackgroundView: UIView {
let nativeFrame = CGRect(origin: CGPoint(), size: size)
transition.setFrame(view: nativeView, frame: nativeFrame)
}
nativeView.overrideUserInterfaceStyle = isDark ? .dark : .light
}
if let backgroundNode = self.backgroundNode {
backgroundNode.updateColor(color: .clear, forceKeepBlur: tintColor.color.alpha != 1.0, transition: transition.containedViewLayoutTransition)
if let legacyView = self.legacyView {
switch shape {
case let .roundedRect(cornerRadius):
backgroundNode.update(size: size, cornerRadius: cornerRadius, transition: transition.containedViewLayoutTransition)
legacyView.update(size: size, cornerRadius: cornerRadius, transition: transition)
}
transition.setFrame(view: backgroundNode.view, frame: CGRect(origin: CGPoint(), size: size))
transition.setFrame(view: legacyView, frame: CGRect(origin: CGPoint(), size: size))
transition.setAlpha(view: legacyView, alpha: isVisible ? 1.0 : 0.0)
}
let shadowInset: CGFloat = 32.0
@@ -468,7 +478,7 @@ public class GlassBackgroundView: UIView {
innerBackgroundView.removeFromSuperview()
}
let params = Params(shape: shape, isDark: isDark, tintColor: tintColor, isInteractive: isInteractive)
let params = Params(shape: shape, isDark: isDark, tintColor: tintColor, isInteractive: isInteractive, isVisible: isVisible)
if self.params != params {
self.params = params
@@ -491,36 +501,73 @@ public class GlassBackgroundView: UIView {
context.setBlendMode(.copy)
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowInset + shadowInnerInset, y: shadowInset + shadowInnerInset), size: CGSize(width: size.width - shadowInset * 2.0 - shadowInnerInset * 2.0, height: size.height - shadowInset * 2.0 - shadowInnerInset * 2.0)))
})?.stretchableImage(withLeftCapWidth: Int(shadowInset + outerCornerRadius), topCapHeight: Int(shadowInset + outerCornerRadius))
transition.setAlpha(view: shadowView, alpha: isVisible ? 1.0 : 0.0)
}
if let foregroundView = self.foregroundView {
foregroundView.image = GlassBackgroundView.generateLegacyGlassImage(size: CGSize(width: outerCornerRadius * 2.0, height: outerCornerRadius * 2.0), inset: shadowInset, isDark: isDark, fillColor: tintColor.color)
let fillColor: UIColor
switch tintColor.kind {
case .panel:
if isDark {
fillColor = UIColor(white: 1.0, alpha: 1.0).mixedWith(.black, alpha: 1.0 - 0.11).withAlphaComponent(0.85)
} else {
fillColor = UIColor(white: 1.0, alpha: 0.7)
}
case .custom:
fillColor = tintColor.color
}
foregroundView.image = GlassBackgroundView.generateLegacyGlassImage(size: CGSize(width: outerCornerRadius * 2.0, height: outerCornerRadius * 2.0), inset: shadowInset, isDark: isDark, fillColor: fillColor)
transition.setAlpha(view: foregroundView, alpha: isVisible ? 1.0 : 0.0)
} else {
if let nativeParamsView = self.nativeParamsView, let nativeView = self.nativeView {
if #available(iOS 26.0, *) {
let glassEffect = UIGlassEffect(style: .regular)
switch tintColor.kind {
case .panel:
glassEffect.tintColor = UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.1)
case .custom:
glassEffect.tintColor = tintColor.color
}
glassEffect.isInteractive = params.isInteractive
var glassEffect: UIGlassEffect?
if transition.animation.isImmediate {
nativeView.effect = glassEffect
if isVisible {
let glassEffectValue = UIGlassEffect(style: .regular)
switch tintColor.kind {
case .panel:
if isDark {
glassEffectValue.tintColor = UIColor(white: 1.0, alpha: 0.025)
} else {
glassEffectValue.tintColor = UIColor(white: 1.0, alpha: 0.1)
}
case .custom:
glassEffectValue.tintColor = tintColor.color
}
glassEffectValue.isInteractive = params.isInteractive
glassEffect = glassEffectValue
}
if glassEffect == nil {
if nativeView.effect is UIGlassEffect {
if transition.animation.isImmediate {
nativeView.effect = nil
} else {
UIView.animate {
nativeView.effect = nil
}
}
}
} else {
UIView.animate(withDuration: 0.2, animations: {
if transition.animation.isImmediate {
nativeView.effect = glassEffect
})
} else {
if let glassEffect, let currentEffect = nativeView.effect as? UIGlassEffect, currentEffect.tintColor == glassEffect.tintColor, currentEffect.isInteractive == glassEffect.isInteractive {
} else {
UIView.animate {
nativeView.effect = glassEffect
}
}
}
}
if isDark {
nativeParamsView.lumaMin = 0.0
nativeParamsView.lumaMax = 0.15
} else {
nativeParamsView.lumaMin = 0.6
nativeParamsView.lumaMax = 0.61
nativeParamsView.lumaMin = 0.8
nativeParamsView.lumaMax = 0.801
}
}
}
@@ -537,6 +584,10 @@ public class GlassBackgroundView: UIView {
}
transition.setFrame(view: self.contentContainer, frame: CGRect(origin: CGPoint(), size: size))
}
override public func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
}
}
public final class GlassBackgroundContainerView: UIView {
@@ -595,9 +646,25 @@ public final class GlassBackgroundContainerView: UIView {
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.alpha.isZero {
return nil
}
if self.isHidden {
return nil
}
if !self.isUserInteractionEnabled {
return nil
}
for view in self.contentView.subviews.reversed() {
if let result = view.hitTest(self.convert(point, to: view), with: event), result.isUserInteractionEnabled {
return result
}
}
guard let result = self.contentView.hitTest(point, with: event) else {
return nil
}
return result
}
@@ -609,8 +676,8 @@ public final class GlassBackgroundContainerView: UIView {
nativeParamsView.lumaMin = 0.0
nativeParamsView.lumaMax = 0.15
} else {
nativeParamsView.lumaMin = 0.6
nativeParamsView.lumaMax = 0.61
nativeParamsView.lumaMin = 0.8
nativeParamsView.lumaMax = 0.801
}
transition.setFrame(view: nativeView, frame: CGRect(origin: CGPoint(), size: size))
@@ -618,6 +685,10 @@ public final class GlassBackgroundContainerView: UIView {
transition.setFrame(view: legacyView, frame: CGRect(origin: CGPoint(), size: size))
}
}
override public func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
}
}
private extension CGContext {
@@ -736,8 +807,8 @@ public extension GlassBackgroundView {
}
}
addShadow(context, true, CGPoint(), 10.0, 0.0, UIColor(white: 0.0, alpha: 0.06), .normal)
addShadow(context, true, CGPoint(), 20.0, 0.0, UIColor(white: 0.0, alpha: 0.06), .normal)
addShadow(context, true, CGPoint(), 30.0, 0.0, UIColor(white: 0.0, alpha: 0.045), .normal)
addShadow(context, true, CGPoint(), 20.0, 0.0, UIColor(white: 0.0, alpha: 0.01), .normal)
var a: CGFloat = 0.0
var b: CGFloat = 0.0
@@ -745,7 +816,7 @@ public extension GlassBackgroundView {
fillColor.getHue(nil, saturation: &s, brightness: &b, alpha: &a)
let innerImage: UIImage
if size == CGSize(width: 40.0 + inset * 2.0, height: 40.0 + inset * 2.0), b >= 0.2 {
/*if size == CGSize(width: 40.0 + inset * 2.0, height: 40.0 + inset * 2.0), b >= 0.2 {
innerImage = UIGraphicsImageRenderer(size: size).image { ctx in
let context = ctx.cgContext
@@ -798,10 +869,78 @@ public extension GlassBackgroundView {
addShadow(context, false, CGPoint(x: 0.64, y: 0.64), 1.2, 0.0, UIColor(white: 1.0, alpha: edgeAlpha), .normal)
}
}
}
}*/
context.addEllipse(in: CGRect(origin: CGPoint(x: inset, y: inset), size: innerSize))
context.clip()
innerImage = UIGraphicsImageRenderer(size: size).image { ctx in
let context = ctx.cgContext
context.setFillColor(fillColor.cgColor)
var ellipseRect = CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset)
context.fillEllipse(in: ellipseRect)
let lineWidth: CGFloat = isDark ? 0.8 : 0.8
let strokeColor: UIColor
let blendMode: CGBlendMode
let baseAlpha: CGFloat = isDark ? 0.3 : 0.6
if s == 0.0 && abs(a - 0.7) < 0.1 && !isDark {
blendMode = .normal
strokeColor = UIColor(white: 1.0, alpha: baseAlpha)
} else if s <= 0.3 && !isDark {
blendMode = .normal
strokeColor = UIColor(white: 1.0, alpha: 0.7 * baseAlpha)
} else if b >= 0.2 {
let maxAlpha: CGFloat = isDark ? 0.7 : 0.8
blendMode = .overlay
strokeColor = UIColor(white: 1.0, alpha: max(0.5, min(1.0, maxAlpha * s)) * baseAlpha)
} else {
blendMode = .normal
strokeColor = UIColor(white: 1.0, alpha: 0.5 * baseAlpha)
}
context.setStrokeColor(strokeColor.cgColor)
ellipseRect = CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset)
context.addEllipse(in: ellipseRect)
context.clip()
ellipseRect = CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5)
context.setBlendMode(blendMode)
let radius = ellipseRect.height * 0.5
let smallerRadius = radius - lineWidth * 1.33
context.move(to: CGPoint(x: ellipseRect.minX, y: ellipseRect.minY + radius))
// Top-left corner (regular radius)
context.addArc(tangent1End: CGPoint(x: ellipseRect.minX, y: ellipseRect.minY), tangent2End: CGPoint(x: ellipseRect.minX + radius, y: ellipseRect.minY), radius: radius)
context.addLine(to: CGPoint(x: ellipseRect.maxX - smallerRadius, y: ellipseRect.minY))
// Top-right corner (smaller radius)
context.addArc(tangent1End: CGPoint(x: ellipseRect.maxX, y: ellipseRect.minY), tangent2End: CGPoint(x: ellipseRect.maxX, y: ellipseRect.minY + smallerRadius), radius: smallerRadius)
context.addLine(to: CGPoint(x: ellipseRect.maxX, y: ellipseRect.maxY - radius))
// Bottom-right corner (regular radius)
context.addArc(tangent1End: CGPoint(x: ellipseRect.maxX, y: ellipseRect.maxY), tangent2End: CGPoint(x: ellipseRect.maxX - radius, y: ellipseRect.maxY), radius: radius)
context.addLine(to: CGPoint(x: ellipseRect.minX + smallerRadius, y: ellipseRect.maxY))
// Bottom-left corner (smaller radius)
context.addArc(tangent1End: CGPoint(x: ellipseRect.minX, y: ellipseRect.maxY), tangent2End: CGPoint(x: ellipseRect.minX, y: ellipseRect.maxY - smallerRadius), radius: smallerRadius)
context.closePath()
context.strokePath()
context.resetClip()
context.setBlendMode(.normal)
//let image = makeInnerShadowPillImageExact(size: CGSize(width: size.width - inset * 2.0, height: size.height - inset * 2.0), scale: UIScreenScale, glossColor: UIColor(white: 1.0, alpha: 1.0), borderWidth: 1.33)
/*let image = generateCircleImage(diameter: size.width - inset * 2.0, lineWidth: 0.5, color: UIColor(white: 1.0, alpha: 1.0))!
if s == 0.0 && abs(a - 0.7) < 0.1 && !isDark {
image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .normal, alpha: 1.0)
} else if s <= 0.3 && !isDark {
image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .normal, alpha: 0.7)
} else if b >= 0.2 {
let maxAlpha: CGFloat = isDark ? 0.7 : 0.8
image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .overlay, alpha: max(0.5, min(1.0, maxAlpha * s)))
} else {
image.draw(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset), blendMode: .normal, alpha: 0.5)
}*/
}
innerImage.draw(in: CGRect(origin: CGPoint(), size: size))
}.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5))
}
@@ -892,12 +1031,20 @@ public final class GlassBackgroundComponent: Component {
private let cornerRadius: CGFloat
private let isDark: Bool
private let tintColor: GlassBackgroundView.TintColor
private let isInteractive: Bool
public init(size: CGSize, cornerRadius: CGFloat, isDark: Bool, tintColor: GlassBackgroundView.TintColor) {
public init(
size: CGSize,
cornerRadius: CGFloat,
isDark: Bool,
tintColor: GlassBackgroundView.TintColor,
isInteractive: Bool = false
) {
self.size = size
self.cornerRadius = cornerRadius
self.isDark = isDark
self.tintColor = tintColor
self.isInteractive = isInteractive
}
public static func == (lhs: GlassBackgroundComponent, rhs: GlassBackgroundComponent) -> Bool {
@@ -913,12 +1060,15 @@ public final class GlassBackgroundComponent: Component {
if lhs.tintColor != rhs.tintColor {
return false
}
if lhs.isInteractive != rhs.isInteractive {
return false
}
return true
}
public final class View: GlassBackgroundView {
func update(component: GlassBackgroundComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
self.update(size: component.size, cornerRadius: component.cornerRadius, isDark: component.isDark, tintColor: component.tintColor, transition: transition)
self.update(size: component.size, cornerRadius: component.cornerRadius, isDark: component.isDark, tintColor: component.tintColor, isInteractive: component.isInteractive, transition: transition)
return component.size
}
@@ -0,0 +1,178 @@
import Foundation
import UIKit
import Display
import ComponentFlow
import MeshTransform
private let backdropLayerClass: NSObject? = {
let name = ("CA" as NSString).appendingFormat("BackdropLayer")
if let cls = NSClassFromString(name as String) as AnyObject as? NSObject {
return cls
}
return nil
}()
@inline(__always)
private func getMethod<T>(object: NSObject, selector: String) -> T? {
guard let method = object.method(for: NSSelectorFromString(selector)) else {
return nil
}
return unsafeBitCast(method, to: T.self)
}
private var cachedBackdropLayerAllocMethod: (@convention(c) (AnyObject, Selector) -> NSObject?, Selector)?
private func invokeBackdropLayerCreateMethod() -> NSObject? {
guard let backdropLayerClass = backdropLayerClass else {
return nil
}
if let cachedBackdropLayerAllocMethod {
return cachedBackdropLayerAllocMethod.0(backdropLayerClass, cachedBackdropLayerAllocMethod.1)
} else {
let method: (@convention(c) (AnyObject, Selector) -> NSObject?)? = getMethod(object: backdropLayerClass, selector: "alloc")
if let method {
let selector = NSSelectorFromString("alloc")
cachedBackdropLayerAllocMethod = (method, selector)
return method(backdropLayerClass, selector)
} else {
return nil
}
}
}
private var cachedBackdropLayerInitMethod: (@convention(c) (NSObject, Selector) -> NSObject?, Selector)?
private func invokeBackdropLayerInitMethod(object: NSObject) -> NSObject? {
if let cachedBackdropLayerInitMethod {
return cachedBackdropLayerInitMethod.0(object, cachedBackdropLayerInitMethod.1)
} else {
let method: (@convention(c) (AnyObject, Selector) -> NSObject?)? = getMethod(object: object, selector: "init")
if let method {
let selector = NSSelectorFromString("init")
cachedBackdropLayerInitMethod = (method, selector)
return method(object, selector)
} else {
return nil
}
}
}
private var cachedBackdropLayerSetScaleMethod: (@convention(c) (NSObject, Selector, Double) -> Void, Selector)?
private func invokeBackdropLayerSetScaleMethod(object: NSObject, scale: Double) {
if let cachedBackdropLayerSetScaleMethod {
cachedBackdropLayerSetScaleMethod.0(object, cachedBackdropLayerSetScaleMethod.1, scale)
} else {
let method: (@convention(c) (AnyObject, Selector, Double) -> Void)? = getMethod(object: object, selector: "setScale:")
if let method {
let selector = NSSelectorFromString("setScale:")
cachedBackdropLayerSetScaleMethod = (method, selector)
return method(object, selector, scale)
}
}
}
private final class BackdropLayerDelegate: NSObject, CALayerDelegate {
func action(for layer: CALayer, forKey event: String) -> CAAction? {
return nullAction
}
}
final class LegacyGlassView: UIView {
private struct Params: Equatable {
let size: CGSize
let cornerRadius: CGFloat
init(size: CGSize, cornerRadius: CGFloat) {
self.size = size
self.cornerRadius = cornerRadius
}
}
private var params: Params?
private let backdropLayer: CALayer?
private let backdropLayerDelegate: BackdropLayerDelegate
override init(frame: CGRect) {
self.backdropLayerDelegate = BackdropLayerDelegate()
self.backdropLayer = invokeBackdropLayerCreateMethod().flatMap(invokeBackdropLayerInitMethod) as? CALayer
super.init(frame: frame)
self.layer.cornerCurve = .circular
self.clipsToBounds = true
if let backdropLayer = self.backdropLayer {
self.layer.addSublayer(backdropLayer)
backdropLayer.delegate = self.backdropLayerDelegate
let blur: CGFloat
let scale: CGFloat
blur = 2.0
scale = 1.0
invokeBackdropLayerSetScaleMethod(object: backdropLayer, scale: scale)
backdropLayer.rasterizationScale = scale
if let blurFilter = CALayer.blur() {
blurFilter.setValue(blur as NSNumber, forKey: "inputRadius")
backdropLayer.filters = [blurFilter]
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(size: CGSize, cornerRadius: CGFloat, transition: ComponentTransition) {
let params = Params(size: size, cornerRadius: cornerRadius)
if self.params == params {
return
}
self.params = params
guard let backdropLayer = self.backdropLayer else {
return
}
transition.setCornerRadius(layer: self.layer, cornerRadius: cornerRadius)
transition.setFrame(layer: backdropLayer, frame: CGRect(origin: CGPoint(), size: size))
if !"".isEmpty {
let size = CGSize(width: max(1.0, size.width), height: max(1.0, size.height))
let cornerRadius = min(min(size.width, size.height) * 0.5, cornerRadius)
let displacementMagnitudePoints: CGFloat = 20.0
let displacementMagnitudeU = displacementMagnitudePoints / size.width
let displacementMagnitudeV = displacementMagnitudePoints / size.height
let outerEdgeDistance = 2.0
if let displacementMap = generateDisplacementMap(size: size, cornerRadius: cornerRadius, edgeDistance: min(12.0, cornerRadius), scale: 1.0) {
let meshTransform = generateGlassMeshFromDisplacementMap(
size: size,
cornerRadius: cornerRadius,
displacementMap: displacementMap,
displacementMagnitudeU: displacementMagnitudeU,
displacementMagnitudeV: displacementMagnitudeV,
cornerResolution: 12,
outerEdgeDistance: outerEdgeDistance,
bezier: DisplacementBezier(
x1: 0.816137566137566,
y1: 0.20502645502645533,
x2: 0.5806878306878306,
y2: 0.873015873015873
)
).mesh.makeValue()
if let meshTransform {
if !transition.animation.isImmediate, let previousTransform = backdropLayer.value(forKey: "meshTransform") as? NSObject {
backdropLayer.removeAnimation(forKey: "meshTransform")
backdropLayer.setValue(meshTransform, forKey: "meshTransform")
transition.animateMeshTransform(layer: backdropLayer, from: previousTransform, to: meshTransform)
} else {
backdropLayer.setValue(meshTransform, forKey: "meshTransform")
}
}
}
}
}
}