Repository: airbnb/lottie-ios
File: Sources/Public/iOS/FilepathImageProvider.swift (Swift)

Code before:
import Foundation
#if canImport(UIKit)
import UIKit

/// Provides an image for a lottie animation from a provided Bundle.
public class FilepathImageProvider: AnimationImageProvider {

  // MARK: Lifecycle

  /// Initializes an image provider with a specific filepath.
  ///
  /// - Parameter filepath: The absolute filepath containing the images.
  ///
  public init(filepath: String, contentsGravity: CALayerContentsGravity = .resize) {
    self.filepath = URL(fileURLWithPath: filepath)
    self.contentsGravity = contentsGravity
  }

  public init(filepath: URL, contentsGravity: CALayerContentsGravity = .resize) {
    self.filepath = filepath
    self.contentsGravity = contentsGravity
  }

  // MARK: Public

  public var contentsGravity: CALayerContentsGravity

  public func imageForAsset(asset: ImageAsset) -> CGImage? {
    if
      asset.name.hasPrefix("data:"),
      let url = URL(string: asset.name),
      let data = try? Data(contentsOf: url),
      let image = UIImage(data: data)
    {
      return image.cgImage
    }

    let directPath = filepath.appendingPathComponent(asset.name).path
    if FileManager.default.fileExists(atPath: directPath) {
      return UIImage(contentsOfFile: directPath)?.cgImage
    }

    let pathWithDirectory = filepath.appendingPathComponent(asset.directory).appendingPathComponent(asset.name).path
    if FileManager.default.fileExists(atPath: pathWithDirectory) {
      return UIImage(contentsOfFile: pathWithDirectory)?.cgImage
    }

    LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle")
    return nil
  }


Review comment (suggestion):
This is a class so we probably want this to be internal and immutable

```suggestion
  let contentsGravity: CALayerContentsGravity
```

Code after:
import Foundation
#if canImport(UIKit)
import UIKit

/// Provides an image for a lottie animation from a provided Bundle.
public class FilepathImageProvider: AnimationImageProvider {

  // MARK: Lifecycle

  /// Initializes an image provider with a specific filepath.
  ///
  /// - Parameter filepath: The absolute filepath containing the images.
  /// - Parameter contentsGravity: The contents gravity to use when rendering the images.
  ///
  public init(filepath: String, contentsGravity: CALayerContentsGravity = .resize) {
    self.filepath = URL(fileURLWithPath: filepath)
    self.contentsGravity = contentsGravity
  }

  /// Initializes an image provider with a specific filepath.
  ///
  /// - Parameter filepath: The absolute filepath containing the images.
  /// - Parameter contentsGravity: The contents gravity to use when rendering the images.
  ///
  public init(filepath: URL, contentsGravity: CALayerContentsGravity = .resize) {
    self.filepath = filepath
    self.contentsGravity = contentsGravity
  }

  // MARK: Public

  public func imageForAsset(asset: ImageAsset) -> CGImage? {
    if
      asset.name.hasPrefix("data:"),
      let url = URL(string: asset.name),
      let data = try? Data(contentsOf: url),
      let image = UIImage(data: data)
    {
      return image.cgImage
    }

    let directPath = filepath.appendingPathComponent(asset.name).path
    if FileManager.default.fileExists(atPath: directPath) {
      return UIImage(contentsOfFile: directPath)?.cgImage
    }

    let pathWithDirectory = filepath.appendingPathComponent(asset.directory).appendingPathComponent(asset.name).path
    if FileManager.default.fileExists(atPath: pathWithDirectory) {
      return UIImage(contentsOfFile: pathWithDirectory)?.cgImage
    }