AnimationTextProvider.swift 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
//
//  AnimationImageProvider.swift
//  Lottie_iOS
//
//  Created by Alexandr Goncharov on 07/06/2019.
//

// MARK: - AnimationKeypathTextProvider

/// Protocol for providing dynamic text to for a Lottie animation.
public protocol AnimationKeypathTextProvider: AnyObject {
  /// The text to display for the given `AnimationKeypath`.
  /// If `nil` is returned, continues using the existing default text value.
  func text(for keypath: AnimationKeypath, sourceText: String) -> String?
}

// MARK: - AnimationKeypathTextProvider

/// Legacy protocol for providing dynamic text for a Lottie animation.
/// Instead prefer conforming to `AnimationKeypathTextProvider`.
@available(*, deprecated, message: """
  `AnimationKeypathTextProvider` has been deprecated and renamed to `LegacyAnimationTextProvider`. \
  Instead, conform to `AnimationKeypathTextProvider` instead or conform to `LegacyAnimationTextProvider` explicitly.
  """)
public typealias AnimationTextProvider = LegacyAnimationTextProvider

// MARK: - LegacyAnimationTextProvider

/// Legacy protocol for providing dynamic text for a Lottie animation.
/// Instead prefer conforming to `AnimationKeypathTextProvider`.
public protocol LegacyAnimationTextProvider: AnimationKeypathTextProvider {
  /// Legacy method to look up the text to display for the given keypath.
  /// Instead, prefer implementing `AnimationKeypathTextProvider.`
  /// The behavior of this method depends on the current rendering engine:
  ///  - The Core Animation rendering engine always calls this method
  ///    with the full keypath (e.g. `MY_LAYER.text_value`).
  ///  - The Main Thread rendering engine always calls this method
  ///    with the final component of the key path (e.g. just `text_value`).
  func textFor(keypathName: String, sourceText: String) -> String
}

extension LegacyAnimationTextProvider {
  public func text(for _: AnimationKeypath, sourceText _: String) -> String? {
    nil
  }
}

// MARK: - DictionaryTextProvider

/// Text provider that simply map values from dictionary.
///  - The dictionary keys can either be the full layer keypath string (e.g. `MY_LAYER.text_value`)
///    or simply the final path component of the keypath (e.g. `text_value`).
public final class DictionaryTextProvider: AnimationKeypathTextProvider, LegacyAnimationTextProvider {

  // MARK: Lifecycle

  public init(_ values: [String: String]) {
    self.values = values
  }

  // MARK: Public

  public func text(for keypath: AnimationKeypath, sourceText: String) -> String? {
    if let valueForFullKeypath = values[keypath.fullPath] {
      valueForFullKeypath
    }

    else if
      let lastKeypathComponent = keypath.keys.last,
      let valueForLastComponent = values[lastKeypathComponent]
    {
      valueForLastComponent
    }

    else {
      sourceText
    }
  }

  /// Never called directly by Lottie, but we continue to implement this conformance for backwards compatibility.
  public func textFor(keypathName: String, sourceText: String) -> String {
    values[keypathName] ?? sourceText
  }

  // MARK: Internal

  let values: [String: String]
}

// MARK: Equatable

extension DictionaryTextProvider: Equatable {
  public static func ==(_ lhs: DictionaryTextProvider, _ rhs: DictionaryTextProvider) -> Bool {
    lhs.values == rhs.values
  }
}

// MARK: - DefaultTextProvider

/// Default text provider. Uses text in the animation file
public final class DefaultTextProvider: AnimationKeypathTextProvider, LegacyAnimationTextProvider {

  // MARK: Lifecycle

  public init() { }

  // MARK: Public

  public func textFor(keypathName _: String, sourceText: String) -> String {
    sourceText
  }

  public func text(for _: AnimationKeypath, sourceText: String) -> String {
    sourceText
  }
}

// MARK: Equatable

extension DefaultTextProvider: Equatable {
  public static func ==(_: DefaultTextProvider, _: DefaultTextProvider) -> Bool {
    true
  }
}