Skip to content

Commit 909c645

Browse files
authored
Add ImageRequest (#23844)
1 parent 1d8eeaf commit 909c645

File tree

3 files changed

+69
-47
lines changed

3 files changed

+69
-47
lines changed

WordPress/Classes/Services/MediaImageService.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ final class MediaImageService {
272272
// MARK: - Networking
273273

274274
private func data(for info: RemoteImageInfo, isCached: Bool) async throws -> Data {
275-
let options = ImageRequestOptions(isDiskCacheEnabled: isCached)
276-
return try await downloader.data(from: info.imageURL, host: info.host, options: options)
275+
let request = ImageRequest(url: info.imageURL, host: info.host, options: ImageRequestOptions(isDiskCacheEnabled: isCached))
276+
return try await downloader.data(for: request)
277277
}
278278

279279
private struct RemoteImageInfo {

WordPress/Classes/Utility/Media/ImageDownloader.swift

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
import UIKit
22

3-
struct ImageRequestOptions {
4-
/// Resize the thumbnail to the given size. By default, `nil`.
5-
///
6-
/// - warning: The size is in pixels.
7-
var size: CGSize?
8-
9-
/// If enabled, uses ``MemoryCache`` for caching decompressed images.
10-
var isMemoryCacheEnabled = true
11-
12-
/// If enabled, uses `URLSession` preconfigured with a custom `URLCache`
13-
/// with a relatively high disk capacity. By default, `true`.
14-
var isDiskCacheEnabled = true
15-
}
16-
173
/// The system that downloads and caches images, and prepares them for display.
184
actor ImageDownloader {
195
static let shared = ImageDownloader()
@@ -38,48 +24,44 @@ actor ImageDownloader {
3824
self.cache = cache
3925
}
4026

41-
// MARK: - Images (URL)
42-
43-
/// Downloads image for the given `URL`.
44-
func image(from url: URL, options: ImageRequestOptions = .init()) async throws -> UIImage {
45-
var request = URLRequest(url: url)
46-
request.addValue("image/*", forHTTPHeaderField: "Accept")
47-
return try await image(from: request, options: options)
27+
func image(from url: URL, host: MediaHost? = nil, options: ImageRequestOptions = .init()) async throws -> UIImage {
28+
try await image(for: ImageRequest(url: url, host: host, options: options))
4829
}
4930

50-
/// Downloads image for the given `URLRequest`.
51-
func image(from request: URLRequest, options: ImageRequestOptions = .init()) async throws -> UIImage {
52-
let key = makeKey(for: request.url, size: options.size)
31+
func image(for request: ImageRequest) async throws -> UIImage {
32+
let options = request.options
33+
let key = makeKey(for: request.source.url, size: options.size)
5334
if options.isMemoryCacheEnabled, let image = cache[key] {
5435
return image
5536
}
56-
let data = try await data(for: request, options: options)
37+
let data = try await data(for: request)
5738
let image = try await ImageDecoder.makeImage(from: data, size: options.size)
5839
if options.isMemoryCacheEnabled {
5940
cache[key] = image
6041
}
6142
return image
6243
}
6344

64-
// MARK: - Images (Blog)
65-
66-
/// Returns image for the given URL authenticated for the given host.
67-
func image(from imageURL: URL, host: MediaHost, options: ImageRequestOptions = .init()) async throws -> UIImage {
68-
let request = try await authenticatedRequest(for: imageURL, host: host)
69-
return try await image(from: request, options: options)
70-
}
71-
72-
/// Returns data for the given URL authenticated for the given host.
73-
func data(from imageURL: URL, host: MediaHost, options: ImageRequestOptions = .init()) async throws -> Data {
74-
let request = try await authenticatedRequest(for: imageURL, host: host)
75-
return try await data(for: request, options: options)
45+
func data(for request: ImageRequest) async throws -> Data {
46+
let urlRequest = try await makeURLRequest(for: request)
47+
return try await _data(for: urlRequest, options: request.options)
7648
}
7749

78-
private func authenticatedRequest(for imageURL: URL, host: MediaHost) async throws -> URLRequest {
79-
var request = try await MediaRequestAuthenticator()
80-
.authenticatedRequest(for: imageURL, host: host)
81-
request.setValue("image/*", forHTTPHeaderField: "Accept")
82-
return request
50+
private func makeURLRequest(for request: ImageRequest) async throws -> URLRequest {
51+
switch request.source {
52+
case .url(let url, let host):
53+
var request: URLRequest
54+
if let host {
55+
request = try await MediaRequestAuthenticator()
56+
.authenticatedRequest(for: url, host: host)
57+
} else {
58+
request = URLRequest(url: url)
59+
}
60+
request.addValue("image/*", forHTTPHeaderField: "Accept")
61+
return request
62+
case .urlRequest(let urlRequest):
63+
return urlRequest
64+
}
8365
}
8466

8567
// MARK: - Caching
@@ -115,8 +97,8 @@ actor ImageDownloader {
11597

11698
// MARK: - Networking
11799

118-
private func data(for request: URLRequest, options: ImageRequestOptions) async throws -> Data {
119-
let requestKey = request.urlRequest?.url?.absoluteString ?? ""
100+
private func _data(for request: URLRequest, options: ImageRequestOptions) async throws -> Data {
101+
let requestKey = request.url?.absoluteString ?? ""
120102
let task = tasks[requestKey] ?? ImageDataTask(key: requestKey, Task {
121103
try await self._data(for: request, options: options, key: requestKey)
122104
})
@@ -198,7 +180,7 @@ extension ImageDownloader {
198180
nonisolated func downloadImage(for request: URLRequest, completion: @escaping (UIImage?, Error?) -> Void) -> ImageDownloaderTask {
199181
let task = Task {
200182
do {
201-
let image = try await self.image(from: request, options: .init())
183+
let image = try await self.image(for: ImageRequest(urlRequest: request))
202184
completion(image, nil)
203185
} catch {
204186
completion(nil, error)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import UIKit
2+
3+
final class ImageRequest {
4+
enum Source {
5+
case url(URL, MediaHost?)
6+
case urlRequest(URLRequest)
7+
8+
var url: URL? {
9+
switch self {
10+
case .url(let url, _): url
11+
case .urlRequest(let request): request.url
12+
}
13+
}
14+
}
15+
16+
let source: Source
17+
let options: ImageRequestOptions
18+
19+
init(url: URL, host: MediaHost? = nil, options: ImageRequestOptions = .init()) {
20+
self.source = .url(url, host)
21+
self.options = options
22+
}
23+
24+
init(urlRequest: URLRequest, options: ImageRequestOptions = .init()) {
25+
self.source = .urlRequest(urlRequest)
26+
self.options = options
27+
}
28+
}
29+
30+
struct ImageRequestOptions {
31+
/// Resize the thumbnail to the given size. By default, `nil`.
32+
var size: CGSize?
33+
34+
/// If enabled, uses ``MemoryCache`` for caching decompressed images.
35+
var isMemoryCacheEnabled = true
36+
37+
/// If enabled, uses `URLSession` preconfigured with a custom `URLCache`
38+
/// with a relatively high disk capacity. By default, `true`.
39+
var isDiskCacheEnabled = true
40+
}

0 commit comments

Comments
 (0)