-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathImageFunctions.swift
94 lines (85 loc) · 3.12 KB
/
ImageFunctions.swift
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
//
// ImageFunctions.swift
// Mlem
//
// Created by Eric Andrews on 2024-08-25.
//
import Foundation
import Nuke
import Photos
import SwiftUI
func saveMedia(url: URL) async {
do {
let (data, _) = try await ImagePipeline.shared.data(for: .init(url: url))
let imageSaver = ImageSaver()
if url.pathExtension.isMovieExtension {
try await imageSaver.writeVideoToPhotoAlbum(url: url)
ToastModel.main.add(.success("Video Saved"))
} else {
try await imageSaver.writeImageToPhotoAlbum(imageData: data)
ToastModel.main.add(.success("Image Saved"))
}
} catch {
ToastModel.main.add(.basic(
"Failed to save media",
subtitle: "You may need to allow Mlem to access your Photo Library in System Settings.",
color: .themedNegative,
duration: 5
))
}
}
func shareImage(url: URL, navigation: NavigationLayer) async {
if let fileUrl = await downloadImageToFileSystem(url: url) {
navigation.model?.shareInfo = .init(url: fileUrl)
}
}
func fullSizeUrl(url: URL?) -> URL? {
if let url, var components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
components.queryItems = components.queryItems?.filter { $0.name != "thumbnail" }
return components.url
}
return nil
}
/// Downloads the image at the given URL to the file system, returning the path to the downloaded image
func downloadImageToFileSystem(url: URL) async -> URL? {
do {
let (data, _) = try await ImagePipeline.shared.data(for: .init(url: url))
var fileName: String
// image proxies that use url query param don't have pathExtension so we extract it from the embedded url
if url.pathExtension.isEmpty,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems,
let baseUrlString = queryItems.first(where: { $0.name == "url" })?.value,
let baseUrl = URL(string: baseUrlString) {
fileName = baseUrl.lastPathComponent
} else {
fileName = url.lastPathComponent
}
if fileName.isEmpty {
assertionFailure("Empty fileName!")
return nil
}
let fileUrl = FileManager.default.temporaryDirectory.appending(path: fileName)
if FileManager.default.fileExists(atPath: fileUrl.absoluteString) {
try FileManager.default.removeItem(at: fileUrl)
}
try data.write(to: fileUrl)
return fileUrl
} catch {
handleError(error)
return nil
}
}
func downloadTextToFileSystem(fileName: String, text: String) async -> URL? {
do {
let fileUrl = FileManager.default.temporaryDirectory.appending(path: fileName)
if FileManager.default.fileExists(atPath: fileUrl.absoluteString) {
try FileManager.default.removeItem(at: fileUrl)
}
try text.write(to: fileUrl, atomically: true, encoding: String.Encoding.utf8)
return fileUrl
} catch {
handleError(error)
return nil
}
}