-
-
Notifications
You must be signed in to change notification settings - Fork 298
Expand file tree
/
Copy pathMediaView+Configuration.swift
More file actions
252 lines (223 loc) · 7.88 KB
/
MediaView+Configuration.swift
File metadata and controls
252 lines (223 loc) · 7.88 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//
// MediaView+Configuration.swift
// TwidereX
//
// Created by Cirno MainasuK on 2021-10-14.
// Copyright © 2021 Twidere. All rights reserved.
//
import UIKit
import Combine
import CoreData
import CoreDataStack
import Photos
import AlamofireImage
import MastodonCore
extension MediaView {
public class Configuration: Hashable {
var disposeBag = Set<AnyCancellable>()
public let info: Info
public let language: String?
public let blurhash: String?
public let index: Int
public let total: Int
@Published public var isReveal = true
@Published public var previewImage: UIImage?
@Published public var blurhashImage: UIImage?
public var blurhashImageDisposeBag = Set<AnyCancellable>()
public init(
info: MediaView.Configuration.Info,
language: String?,
blurhash: String?,
index: Int,
total: Int
) {
self.info = info
self.language = language
self.blurhash = blurhash
self.index = index
self.total = total
}
public var aspectRadio: CGSize {
switch info {
case .image(let info): return info.aspectRadio
case .gif(let info): return info.aspectRadio
case .video(let info): return info.aspectRadio
}
}
public var previewURL: String? {
switch info {
case .image(let info):
return info.assetURL
case .gif(let info):
return info.previewURL
case .video(let info):
return info.previewURL
}
}
public var assetURL: String? {
switch info {
case .image(let info):
return info.assetURL
case .gif(let info):
return info.assetURL
case .video(let info):
return info.assetURL
}
}
public var resourceType: PHAssetResourceType {
switch info {
case .image:
return .photo
case .gif:
return .video
case .video:
return .video
}
}
public static func == (lhs: MediaView.Configuration, rhs: MediaView.Configuration) -> Bool {
return lhs.info == rhs.info
&& lhs.blurhash == rhs.blurhash
&& lhs.isReveal == rhs.isReveal
}
public func hash(into hasher: inout Hasher) {
hasher.combine(info)
hasher.combine(blurhash)
}
}
}
extension MediaView.Configuration {
public enum Info: Hashable {
case image(info: ImageInfo)
case gif(info: VideoInfo)
case video(info: VideoInfo)
}
public struct ImageInfo: Hashable {
public let aspectRadio: CGSize
public let assetURL: String?
public let altDescription: String?
public init(
aspectRadio: CGSize,
assetURL: String?,
altDescription: String?
) {
self.aspectRadio = aspectRadio
self.assetURL = assetURL
self.altDescription = altDescription
}
}
public struct VideoInfo: Hashable {
public let aspectRadio: CGSize
public let assetURL: String?
public let previewURL: String?
public let altDescription: String?
public let durationMS: Int?
public init(
aspectRadio: CGSize,
assetURL: String?,
previewURL: String?,
altDescription: String?,
durationMS: Int?
) {
self.aspectRadio = aspectRadio
self.assetURL = assetURL
self.previewURL = previewURL
self.durationMS = durationMS
self.altDescription = altDescription
}
}
}
extension MediaView.Configuration {
public func load() {
if let previewURL = previewURL,
let url = URL(string: previewURL)
{
let placeholder = UIImage.placeholder(color: .systemGray6)
let request = URLRequest(url: url)
ImageDownloader.default.download(request, completion: { [weak self] response in
guard let self = self else { return }
switch response.result {
case .success(let image):
self.previewImage = image
case .failure:
self.previewImage = placeholder
}
})
}
if let assetURL = assetURL,
let blurhash = blurhash
{
BlurhashImageCacheService.shared.image(
blurhash: blurhash,
size: aspectRadio,
url: assetURL
)
.assign(to: \.blurhashImage, on: self)
.store(in: &blurhashImageDisposeBag)
}
}
}
extension MediaView {
public static func configuration(status: StatusCompatible) -> [MediaView.Configuration] {
func videoInfo(from attachment: MastodonAttachment) -> MediaView.Configuration.VideoInfo {
MediaView.Configuration.VideoInfo(
aspectRadio: attachment.size,
assetURL: attachment.assetURL,
previewURL: attachment.previewURL,
altDescription: attachment.altDescription,
durationMS: attachment.durationMS
)
}
let status: StatusCompatible = status.reblog ?? status
let attachments = status.attachments
let configurations = attachments.enumerated().map { (idx, attachment) -> MediaView.Configuration in
let configuration: MediaView.Configuration = {
switch attachment.kind {
case .image:
let info = MediaView.Configuration.ImageInfo(
aspectRadio: attachment.size,
assetURL: attachment.assetURL,
altDescription: attachment.altDescription
)
return .init(
info: .image(info: info),
language: status.language,
blurhash: attachment.blurhash,
index: idx,
total: attachments.count
)
case .video:
let info = videoInfo(from: attachment)
return .init(
info: .video(info: info),
language: status.language,
blurhash: attachment.blurhash,
index: idx,
total: attachments.count
)
case .gifv:
let info = videoInfo(from: attachment)
return .init(
info: .gif(info: info),
language: status.language,
blurhash: attachment.blurhash,
index: idx,
total: attachments.count
)
case .audio:
let info = videoInfo(from: attachment)
return .init(
info: .video(info: info),
language: status.language,
blurhash: attachment.blurhash,
index: idx,
total: attachments.count
)
} // end switch
}()
configuration.load()
configuration.isReveal = status.isMediaSensitive ? status.isSensitiveToggled : true
return configuration
}
return configurations
}
}