mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-10 07:13:28 +01:00
243 lines
10 KiB
Swift
243 lines
10 KiB
Swift
// The MIT License (MIT)
|
||
//
|
||
// Copyright (c) 2015-2022 Alexander Grebenyuk (github.com/kean).
|
||
|
||
import Foundation
|
||
import os
|
||
|
||
// MARK: - ImagePipeline.Configuration
|
||
|
||
extension ImagePipeline {
|
||
/// The pipeline configuration.
|
||
public struct Configuration {
|
||
// MARK: - Dependencies
|
||
|
||
/// Image cache used by the pipeline.
|
||
public var imageCache: ImageCaching? {
|
||
// This exists simply to ensure we don't init ImageCache.shared if the
|
||
// user provides their own instance.
|
||
get { isCustomImageCacheProvided ? customImageCache : ImageCache.shared }
|
||
set {
|
||
customImageCache = newValue
|
||
isCustomImageCacheProvided = true
|
||
}
|
||
}
|
||
private var customImageCache: ImageCaching?
|
||
|
||
/// Data loader used by the pipeline.
|
||
public var dataLoader: DataLoading
|
||
|
||
/// Data cache used by the pipeline.
|
||
public var dataCache: DataCaching?
|
||
|
||
/// Default implementation uses shared `ImageDecoderRegistry` to create
|
||
/// a decoder that matches the context.
|
||
public var makeImageDecoder: (ImageDecodingContext) -> ImageDecoding? = ImageDecoderRegistry.shared.decoder(for:)
|
||
|
||
/// Returns `ImageEncoders.Default()` by default.
|
||
public var makeImageEncoder: (ImageEncodingContext) -> ImageEncoding = { _ in
|
||
ImageEncoders.Default()
|
||
}
|
||
|
||
// MARK: - Operation Queues
|
||
|
||
/// Data loading queue. Default maximum concurrent task count is 6.
|
||
public var dataLoadingQueue = OperationQueue(maxConcurrentCount: 6)
|
||
|
||
/// Data caching queue. Default maximum concurrent task count is 2.
|
||
public var dataCachingQueue = OperationQueue(maxConcurrentCount: 2)
|
||
|
||
/// Image decoding queue. Default maximum concurrent task count is 1.
|
||
public var imageDecodingQueue = OperationQueue(maxConcurrentCount: 1)
|
||
|
||
/// Image encoding queue. Default maximum concurrent task count is 1.
|
||
public var imageEncodingQueue = OperationQueue(maxConcurrentCount: 1)
|
||
|
||
/// Image processing queue. Default maximum concurrent task count is 2.
|
||
public var imageProcessingQueue = OperationQueue(maxConcurrentCount: 2)
|
||
|
||
#if !os(macOS)
|
||
/// Image decompressing queue. Default maximum concurrent task count is 2.
|
||
public var imageDecompressingQueue = OperationQueue(maxConcurrentCount: 2)
|
||
#endif
|
||
|
||
// MARK: - Options
|
||
|
||
/// A queue on which all callbacks, like `progress` and `completion`
|
||
/// callbacks are called. `.main` by default.
|
||
public var callbackQueue = DispatchQueue.main
|
||
|
||
#if !os(macOS)
|
||
/// Decompresses the loaded images. `true` by default.
|
||
///
|
||
/// Decompressing compressed image formats (such as JPEG) can significantly
|
||
/// improve drawing performance as it allows a bitmap representation to be
|
||
/// created in a background rather than on the main thread.
|
||
public var isDecompressionEnabled = true
|
||
#endif
|
||
|
||
/// `.storeOriginalData` by default.
|
||
public var dataCachePolicy = DataCachePolicy.storeOriginalData
|
||
|
||
/// Determines what images are stored in the disk cache.
|
||
public enum DataCachePolicy {
|
||
/// For requests with processors, encode and store processed images.
|
||
/// For requests with no processors, store original image data, unless
|
||
/// the resource is local (file:// or data:// scheme is used).
|
||
///
|
||
/// - warning: With this policy, the pipeline `loadData()` method
|
||
/// will not store the images in the disk cache for requests with
|
||
/// any processors applied – this method only loads data and doesn't
|
||
/// decode images.
|
||
case automatic
|
||
|
||
/// For all requests, only store the original image data, unless
|
||
/// the resource is local (file:// or data:// scheme is used).
|
||
case storeOriginalData
|
||
|
||
/// For all requests, encode and store decoded images after all
|
||
/// processors are applied.
|
||
///
|
||
/// - note: This is useful if you want to store images in a format
|
||
/// different than provided by a server, e.g. decompressed. In other
|
||
/// scenarios, consider using `.automatic` policy instead.
|
||
///
|
||
/// - warning: With this policy, the pipeline `loadData()` method
|
||
/// will not store the images in the disk cache – this method only
|
||
/// loads data and doesn't decode images.
|
||
case storeEncodedImages
|
||
|
||
/// For requests with processors, encode and store processed images.
|
||
/// For all requests, store original image data.
|
||
case storeAll
|
||
}
|
||
|
||
// Deprecated in 10.0.0
|
||
@available(*, deprecated, message: "Please use `dataCachePolicy` instead.")
|
||
public var dataCacheOptions: DataCacheOptions = DataCacheOptions() {
|
||
didSet {
|
||
let items = dataCacheOptions.storedItems
|
||
if items == [.finalImage] {
|
||
dataCachePolicy = .storeEncodedImages
|
||
} else if items == [.originalImageData] {
|
||
dataCachePolicy = .storeOriginalData
|
||
} else if items == [.finalImage, .originalImageData] {
|
||
dataCachePolicy = .storeAll
|
||
}
|
||
}
|
||
}
|
||
|
||
// Deprecated in 10.0.0
|
||
@available(*, deprecated, message: "Please use `dataCachePolicy` instead. The recommended policy is the new `.automatic` policy.")
|
||
public struct DataCacheOptions {
|
||
public var storedItems: Set<DataCacheItem> = [.originalImageData]
|
||
}
|
||
|
||
// Deprecated in 10.0.0
|
||
var _processors: [ImageProcessing] = []
|
||
|
||
/// `true` by default. If `true` the pipeline avoids duplicated work when
|
||
/// loading images. The work only gets cancelled when all the registered
|
||
/// requests are. The pipeline also automatically manages the priority of the
|
||
/// deduplicated work.
|
||
///
|
||
/// Let's take these two requests for example:
|
||
///
|
||
/// ```swift
|
||
/// let url = URL(string: "http://example.com/image")
|
||
/// pipeline.loadImage(with: ImageRequest(url: url, processors: [
|
||
/// ImageProcessors.Resize(size: CGSize(width: 44, height: 44)),
|
||
/// ImageProcessors.GaussianBlur(radius: 8)
|
||
/// ]))
|
||
/// pipeline.loadImage(with: ImageRequest(url: url, processors: [
|
||
/// ImageProcessors.Resize(size: CGSize(width: 44, height: 44))
|
||
/// ]))
|
||
/// ```
|
||
///
|
||
/// Nuke will load the image data only once, resize the image once and
|
||
/// apply the blur also only once. There is no duplicated work done at
|
||
/// any stage.
|
||
public var isTaskCoalescingEnabled = true
|
||
|
||
/// `true` by default. If `true` the pipeline will rate limit requests
|
||
/// to prevent trashing of the underlying systems (e.g. `URLSession`).
|
||
/// The rate limiter only comes into play when the requests are started
|
||
/// and cancelled at a high rate (e.g. scrolling through a collection view).
|
||
public var isRateLimiterEnabled = true
|
||
|
||
/// `false` by default. If `true` the pipeline will try to produce a new
|
||
/// image each time it receives a new portion of data from data loader.
|
||
/// The decoder used by the image loading session determines whether
|
||
/// to produce a partial image or not. The default image decoder
|
||
/// (`ImageDecoder`) supports progressive JPEG decoding.
|
||
public var isProgressiveDecodingEnabled = true
|
||
|
||
/// `false` by default. If `true`, the pipeline will store all of the
|
||
/// progressively generated previews in the memory cache. All of the
|
||
/// previews have `isPreview` flag set to `true`.
|
||
public var isStoringPreviewsInMemoryCache = true
|
||
|
||
/// If the data task is terminated (either because of a failure or a
|
||
/// cancellation) and the image was partially loaded, the next load will
|
||
/// resume where it left off. Supports both validators (`ETag`,
|
||
/// `Last-Modified`). Resumable downloads are enabled by default.
|
||
public var isResumableDataEnabled = true
|
||
|
||
// MARK: - Options (Shared)
|
||
|
||
/// If `true` pipeline will detect GIFs and set `animatedImageData`
|
||
/// (`UIImage` property). It will also disable processing of such images,
|
||
/// and alter the way cache cost is calculated. However, this will not
|
||
/// enable actual animated image rendering. To do that take a look at
|
||
/// satellite projects (FLAnimatedImage and Gifu plugins for Nuke).
|
||
/// `false` by default (to preserve resources).
|
||
static var _isAnimatedImageDataEnabled = false
|
||
|
||
/// `false` by default. If `true`, enables `os_signpost` logging for
|
||
/// measuring performance. You can visually see all the performance
|
||
/// metrics in `os_signpost` Instrument. For more information see
|
||
/// https://developer.apple.com/documentation/os/logging and
|
||
/// https://developer.apple.com/videos/play/wwdc2018/405/.
|
||
public static var isSignpostLoggingEnabled = false {
|
||
didSet {
|
||
log = isSignpostLoggingEnabled ?
|
||
OSLog(subsystem: "com.github.kean.Nuke.ImagePipeline", category: "Image Loading") :
|
||
.disabled
|
||
}
|
||
}
|
||
|
||
private var isCustomImageCacheProvided = false
|
||
|
||
var debugIsSyncImageEncoding = false
|
||
|
||
// MARK: - Initializer
|
||
|
||
/// Instantiates a default pipeline configuration.
|
||
///
|
||
/// - parameter dataLoader: `DataLoader()` by default.
|
||
public init(dataLoader: DataLoading = DataLoader()) {
|
||
self.dataLoader = dataLoader
|
||
}
|
||
|
||
/// A configuration with a `DataLoader` with an HTTP disk cache (`URLCache`)
|
||
/// with a size limit of 150 MB.
|
||
public static var withURLCache: Configuration { Configuration() }
|
||
|
||
/// A configuration with an aggressive disk cache (`DataCache`) with a
|
||
/// size limit of 150 MB. An HTTP cache (`URLCache`) is disabled.
|
||
public static var withDataCache: Configuration {
|
||
let dataLoader: DataLoader = {
|
||
let config = URLSessionConfiguration.default
|
||
config.urlCache = nil
|
||
return DataLoader(configuration: config)
|
||
}()
|
||
|
||
var config = Configuration()
|
||
config.dataLoader = dataLoader
|
||
config.dataCache = try? DataCache(name: "com.github.kean.Nuke.DataCache")
|
||
|
||
return config
|
||
}
|
||
}
|
||
}
|