Skip to content

Commit fb03133

Browse files
committed
Use the generated thumbnails in the media gallery
1 parent 416b5f4 commit fb03133

File tree

2 files changed

+57
-103
lines changed

2 files changed

+57
-103
lines changed

Monal/Classes/MediaGallery.swift

Lines changed: 19 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -45,86 +45,27 @@ struct MediaGalleryView: View {
4545
}
4646
}
4747

48-
class MediaItem: Identifiable, ObservableObject {
49-
let id = UUID()
50-
let fileInfo: MLFiletransferInfo
51-
@Published var thumbnail: UIImage?
52-
53-
init(fileInfo: MLFiletransferInfo) {
54-
self.fileInfo = fileInfo
55-
self.thumbnail = nil
56-
Task { @MainActor in
57-
await generateThumbnail()
58-
}
59-
}
60-
61-
@MainActor
62-
func generateThumbnail() async {
63-
guard let cacheFilePath = fileInfo.cacheFilePath else {
64-
DDLogError("Failed to get cacheFilePath for: \(fileInfo)")
65-
self.thumbnail = UIImage(systemName: "exclamationmark.triangle")
66-
return
67-
}
68-
69-
if fileInfo.isImage {
70-
if let image = UIImage(contentsOfFile: cacheFilePath) {
71-
self.thumbnail = image
72-
} else {
73-
DDLogError("Failed to generate image thumbnail for: \(fileInfo)")
74-
self.thumbnail = UIImage(systemName: "photo")
75-
}
76-
return
77-
} else if fileInfo.isVideo {
78-
if let thumbnail = await videoPreview(for:fileInfo) {
79-
self.thumbnail = thumbnail
80-
} else {
81-
DDLogError("Failed to generate video thumbnail for: \(fileInfo)")
82-
self.thumbnail = UIImage(systemName: "video")
83-
}
84-
return
85-
}
86-
87-
DDLogError("Unsupported mime type: \(fileInfo.mimeType ?? "(unknown)")")
88-
self.thumbnail = UIImage(systemName: "doc")
89-
}
90-
91-
@MainActor
92-
func videoPreview(for fileInfo: MLFiletransferInfo) async -> UIImage? {
93-
let moviePath = URL(fileURLWithPath: fileInfo.cacheFilePath!)
94-
DDLogInfo("Trying to generate video thumbnail for: \(String(describing:fileInfo))")
95-
96-
let payload: NSDictionary? = try? await HelperTools.addUploadItemPreview(
97-
forItem:moviePath,
98-
provider:nil,
99-
andPayload:[:]
100-
).toTypedPromise().asyncOnMainActor()
101-
guard let image = payload?["preview"] as? UIImage else {
102-
return try? await HelperTools.generateVideoThumbnail(
103-
fromFile:fileInfo.cacheFilePath!,
104-
havingMimeType:fileInfo.mimeType! ,
105-
andFileExtension:fileInfo.fileExtension
106-
).toTypedPromise().asyncOnMainActor()
107-
}
108-
return image
109-
}
110-
}
111-
11248
struct MediaItemView: View {
113-
@StateObject private var item: MediaItem
49+
@StateObject private var fileInfo: ObservableKVOWrapper<MLFiletransferInfo>
11450

11551
init(fileInfo: MLFiletransferInfo) {
116-
_item = StateObject(wrappedValue: MediaItem(fileInfo: fileInfo))
52+
_fileInfo = StateObject(wrappedValue: ObservableKVOWrapper(fileInfo))
11753
}
11854

11955
var body: some View {
12056
ZStack {
12157
Group {
122-
if let thumbnail = item.thumbnail {
123-
Image(uiImage: thumbnail)
124-
.resizable()
125-
//.scaledToFit() //leaves empty room around image if not having a square format
126-
.scaledToFill() //this is what the ios gallery app uses (will crop the edges of that preview)
127-
} else {
58+
if (fileInfo.thumbnailURL as URL?) != nil {
59+
AsyncImage(url: fileInfo.thumbnailURL) { image in
60+
image
61+
.resizable()
62+
//.scaledToFit() //leaves empty room around image if not having a square format
63+
.scaledToFill() //this is what the ios gallery app uses (will crop the edges of that preview)
64+
} placeholder: { //placeholder while the thumbnail is being loaded from disk
65+
ProgressView()
66+
.progressViewStyle(CircularProgressViewStyle())
67+
}
68+
} else { //placeholder if the thumbnailURL is nil, for example while the thumbnail is being generated
12869
ProgressView()
12970
.progressViewStyle(CircularProgressViewStyle())
13071
}
@@ -134,7 +75,7 @@ struct MediaItemView: View {
13475
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
13576

13677
// Add play icon overlay for video files
137-
if item.fileInfo.isVideo {
78+
if fileInfo.isVideo {
13879
Image(systemName: "play.circle.fill")
13980
.resizable()
14081
.frame(width: 30, height: 30)
@@ -147,15 +88,15 @@ struct MediaItemView: View {
14788
}
14889

14990
struct MediaItemDetailView: View {
150-
@StateObject private var item: MediaItem
91+
@StateObject private var fileInfo: ObservableKVOWrapper<MLFiletransferInfo>
15192
@StateObject private var dismisser = SheetDismisserProtocol()
15293

15394
init(fileInfo: MLFiletransferInfo) {
154-
_item = StateObject(wrappedValue: MediaItem(fileInfo: fileInfo))
95+
_fileInfo = StateObject(wrappedValue: ObservableKVOWrapper(fileInfo))
15596
}
15697

15798
var body: some View {
158-
ImageViewerWrapper(info: item.fileInfo as MLFiletransferInfo, dismisser: dismisser)
99+
ImageViewerWrapper(info: fileInfo, dismisser: dismisser)
159100
.onAppear {
160101
let appDelegate = UIApplication.shared.delegate as! MonalAppDelegate
161102
if let hostingController = appDelegate.getTopViewController() as? UIHostingController<AnyView> {
@@ -199,18 +140,16 @@ struct MediaItemSwipeView: View {
199140
}
200141

201142
struct ImageViewerWrapper: View {
202-
let info: MLFiletransferInfo
143+
@ObservedObject var info: ObservableKVOWrapper<MLFiletransferInfo>
203144
let dismisser: SheetDismisserProtocol
204145

205146
var body: some View {
206147
Group {
207-
if info.downloadState == DownloadState.complete {
148+
if info.downloadState as DownloadState.RawValue == DownloadState.complete.rawValue {
208149
try? ImageViewer(delegate: dismisser, info: info)
209150
} else {
210151
Text("Invalid file data")
211152
}
212153
}
213154
}
214155
}
215-
216-

Monal/Classes/MediaViewer.swift

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ struct SVGRepresentation: Transferable {
4848

4949
struct ImageViewer: View {
5050
var delegate: SheetDismisserProtocol
51-
let info: MLFiletransferInfo
51+
@ObservedObject var info: ObservableKVOWrapper<MLFiletransferInfo>
5252
@State private var previewImage: UIImage?
5353
@State private var controlsVisible = false
5454
@StateObject private var customPlayer = CustomAVPlayer()
5555
@State private var isPlayerReady = false
5656

57-
init(delegate: SheetDismisserProtocol, info: MLFiletransferInfo) throws {
57+
init(delegate: SheetDismisserProtocol, info: ObservableKVOWrapper<MLFiletransferInfo>) throws {
5858
self.delegate = delegate
5959
self.info = info
6060
DDLogDebug("Loading image for info: \(String(describing:self.info))")
@@ -68,15 +68,15 @@ struct ImageViewer: View {
6868
if info.isSVGImage {
6969
VStack {
7070
ZoomableContainer(maxScale:8.0, doubleTapScale:4.0) {
71-
SVGView(contentsOf: info.fileURL!)
71+
SVGView(contentsOf: info.fileURL as URL)
7272
}
7373
}
7474
} else if info.isImage {
75-
if let image = UIImage(contentsOfFile:info.cacheFilePath!) {
75+
if let image = UIImage(contentsOfFile:info.cacheFilePath as String) {
7676
VStack {
7777
ZoomableContainer(maxScale:8.0, doubleTapScale:4.0) {
78-
if info.mimeType!.hasPrefix("image/gif") {
79-
GIFViewer(data:Binding(get: { try! NSData(contentsOfFile:info.cacheFilePath!) as Data }, set: { _ in }))
78+
if (info.mimeType as String).hasPrefix("image/gif") {
79+
GIFViewer(data:Binding(get: { try! NSData(contentsOfFile:info.cacheFilePath as String) as Data }, set: { _ in }))
8080
.scaledToFit()
8181
} else {
8282
Image(uiImage: image)
@@ -116,11 +116,11 @@ struct ImageViewer: View {
116116

117117
private func loadPreviewAndConfigurePlayer() async {
118118
if info.isSVGImage {
119-
previewImage = await HelperTools.renderUIImage(fromSVGURL: info.fileURL!).toTypedGuarantee().asyncOnMainActor()
119+
previewImage = await HelperTools.renderUIImage(fromSVGURL: info.fileURL as URL).toTypedGuarantee().asyncOnMainActor()
120120
} else if info.isImage {
121-
previewImage = UIImage(contentsOfFile:info.cacheFilePath!)
121+
previewImage = UIImage(contentsOfFile:info.cacheFilePath as String)
122122
} else if info.isVideo {
123-
if let filePath = info.cacheFilePath, let mimeType = info.mimeType {
123+
if let filePath = info.cacheFilePath as String?, let mimeType = info.mimeType as String? {
124124
customPlayer.configurePlayer(filePath: filePath, mimeType: mimeType)
125125
isPlayerReady = true
126126
}
@@ -182,56 +182,71 @@ struct InvalidFileView: View {
182182
}
183183

184184
struct ControlsOverlay: View {
185-
let info: MLFiletransferInfo
185+
@ObservedObject var info: ObservableKVOWrapper<MLFiletransferInfo>
186186
@Binding var previewImage: UIImage?
187187
let dismiss: () -> Void
188-
188+
189+
init(info: ObservableKVOWrapper<MLFiletransferInfo>, previewImage: Binding<UIImage?>, dismiss: @escaping () -> Void) {
190+
self.info = info
191+
_previewImage = previewImage
192+
self.dismiss = dismiss
193+
}
194+
189195
var body: some View {
190196
VStack {
191197
Color.background
192198
.ignoresSafeArea()
193199
.overlay(
194200
HStack {
195201
Spacer().frame(width: 20)
196-
Text(info.filename).foregroundColor(.primary)
202+
Text(info.filename as String).foregroundColor(.primary)
197203
Spacer()
198-
204+
199205
if let image = previewImage {
200206
if info.isSVGImage {
201207
ShareLink(
202208
item: SVGRepresentation(getData: {
203-
try! NSData(contentsOfFile: info.cacheFilePath!) as Data
209+
try! NSData(contentsOfFile: info.cacheFilePath as String) as Data
204210
}), preview: SharePreview("Share image", image: Image(uiImage: image))
205211
)
206212
.labelStyle(.iconOnly)
207213
.foregroundColor(.primary)
208-
} else if info.mimeType!.hasPrefix("image/gif") {
214+
} else if (info.mimeType as String).hasPrefix("image/gif") {
209215
ShareLink(
210216
item: GifRepresentation(getData: {
211-
try! NSData(contentsOfFile: info.cacheFilePath!) as Data
217+
try! NSData(contentsOfFile: info.cacheFilePath as String) as Data
212218
}), preview: SharePreview("Share image", image: Image(uiImage: image))
213219
)
214220
.labelStyle(.iconOnly)
215221
.foregroundColor(.primary)
216222
} else if info.isVideo {
217-
if let fileURL = info.fileURL {
218-
let mediaItem = MediaItem(fileInfo: info)
219-
ShareLink(item: fileURL, preview: SharePreview("Share video", image: Image(uiImage: mediaItem.thumbnail ?? UIImage(systemName: "video")!)))
220-
.labelStyle(.iconOnly)
221-
.foregroundColor(.primary)
223+
if let fileURL = info.fileURL as URL? {
224+
ShareLink(
225+
item: fileURL,
226+
preview: SharePreview(
227+
"Share video",
228+
image: Image(
229+
uiImage: info.thumbnailURL
230+
? UIImage(contentsOfFile: (info.thumbnailURL as URL).path)!
231+
: UIImage(systemName: "video")!
232+
)
233+
)
234+
)
235+
.labelStyle(.iconOnly)
236+
.foregroundColor(.primary)
222237
}
223238
} else {
224239
ShareLink(
225240
item: JpegRepresentation(getData: {
226-
try! NSData(contentsOfFile: info.cacheFilePath!) as Data
241+
try! NSData(contentsOfFile: info.cacheFilePath as String) as Data
227242
}), preview: SharePreview("Share image", image: Image(uiImage: image))
228243
)
229244
.labelStyle(.iconOnly)
230245
.foregroundColor(.primary)
231246
}
232247
Spacer().frame(width: 20)
233248
}
234-
249+
235250
Button(action: dismiss, label: {
236251
Image(systemName: "xmark")
237252
.foregroundColor(.primary)

0 commit comments

Comments
 (0)