mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
129 lines
3.8 KiB
Swift
129 lines
3.8 KiB
Swift
// Created by Cal Stephens on 5/4/22.
|
|
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
|
|
// MARK: - CompatibilityIssue
|
|
|
|
/// A compatibility issue that was encountered while setting up an animation with the Core Animation engine
|
|
struct CompatibilityIssue: CustomStringConvertible {
|
|
let message: String
|
|
let context: String
|
|
|
|
var description: String {
|
|
"[\(context)] \(message)"
|
|
}
|
|
}
|
|
|
|
// MARK: - CompatibilityTracker
|
|
|
|
/// A type that tracks whether or not an animation is compatible with the Core Animation engine
|
|
final class CompatibilityTracker {
|
|
|
|
// MARK: Lifecycle
|
|
|
|
init(mode: Mode) {
|
|
self.mode = mode
|
|
}
|
|
|
|
// MARK: Internal
|
|
|
|
/// How compatibility issues should be handled
|
|
enum Mode {
|
|
/// When a compatibility issue is encountered, an error will be thrown immediately,
|
|
/// aborting the animation setup process as soon as possible.
|
|
case abort
|
|
|
|
/// When a compatibility issue is encountered, it is stored in `CompatibilityTracker.issues`
|
|
case track
|
|
}
|
|
|
|
enum Error: Swift.Error {
|
|
case encounteredCompatibilityIssue(CompatibilityIssue)
|
|
}
|
|
|
|
/// Records a compatibility issue that will be reported according to `CompatibilityTracker.Mode`
|
|
func logIssue(message: String, context: String) throws {
|
|
LottieLogger.shared.assert(!context.isEmpty, "Compatibility issue context is unexpectedly empty")
|
|
|
|
let issue = CompatibilityIssue(
|
|
// Compatibility messages are usually written in source files using multi-line strings,
|
|
// but converting them to be a single line makes it easier to read the ultimate log output.
|
|
message: message.replacingOccurrences(of: "\n", with: " "),
|
|
context: context)
|
|
|
|
switch mode {
|
|
case .abort:
|
|
throw CompatibilityTracker.Error.encounteredCompatibilityIssue(issue)
|
|
case .track:
|
|
issues.append(issue)
|
|
}
|
|
}
|
|
|
|
/// Asserts that a condition is true, otherwise logs a compatibility issue that will be reported
|
|
/// according to `CompatibilityTracker.Mode`
|
|
func assert(
|
|
_ condition: Bool,
|
|
_ message: @autoclosure () -> String,
|
|
context: @autoclosure () -> String)
|
|
throws
|
|
{
|
|
if !condition {
|
|
try logIssue(message: message(), context: context())
|
|
}
|
|
}
|
|
|
|
/// Reports the compatibility issues that were recorded when setting up the animation,
|
|
/// and clears the set of tracked issues.
|
|
func reportCompatibilityIssues(_ handler: ([CompatibilityIssue]) -> Void) {
|
|
handler(issues)
|
|
issues = []
|
|
}
|
|
|
|
// MARK: Private
|
|
|
|
private let mode: Mode
|
|
|
|
/// Compatibility issues encountered while setting up the animation
|
|
private var issues = [CompatibilityIssue]()
|
|
|
|
}
|
|
|
|
// MARK: - CompatibilityTrackerProviding
|
|
|
|
protocol CompatibilityTrackerProviding {
|
|
var compatibilityTracker: CompatibilityTracker { get }
|
|
var compatibilityIssueContext: String { get }
|
|
}
|
|
|
|
extension CompatibilityTrackerProviding {
|
|
/// Records a compatibility issue that will be reported according to `CompatibilityTracker.Mode`
|
|
func logCompatibilityIssue(_ message: String) throws {
|
|
try compatibilityTracker.logIssue(message: message, context: compatibilityIssueContext)
|
|
}
|
|
|
|
/// Asserts that a condition is true, otherwise logs a compatibility issue that will be reported
|
|
/// according to `CompatibilityTracker.Mode`
|
|
func compatibilityAssert(
|
|
_ condition: Bool,
|
|
_ message: @autoclosure () -> String)
|
|
throws
|
|
{
|
|
try compatibilityTracker.assert(condition, message(), context: compatibilityIssueContext)
|
|
}
|
|
}
|
|
|
|
// MARK: - LayerContext + CompatibilityTrackerProviding
|
|
|
|
extension LayerContext: CompatibilityTrackerProviding {
|
|
var compatibilityIssueContext: String {
|
|
layerName
|
|
}
|
|
}
|
|
|
|
// MARK: - LayerAnimationContext + CompatibilityTrackerProviding
|
|
|
|
extension LayerAnimationContext: CompatibilityTrackerProviding {
|
|
var compatibilityIssueContext: String {
|
|
currentKeypath.fullPath
|
|
}
|
|
}
|