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
|
import SwiftUI
struct AsyncImageWithPreview<Placeholder: View>: View {
@EnvironmentObject var settings: Settings
var url: URL?
@Binding var loadingState: PostLoadingState
var finalLoadingState: PostLoadingState
var postURL: URL?
let placeholder: () -> Placeholder
@State private var currentScale: CGFloat = 1.0
@State private var finalScale: CGFloat = 1.0
@State private var currentOffset: CGSize = .zero
@State private var finalOffset: CGSize = .zero
#if os(iOS)
var keyWindow: UIWindow? {
guard
let window = UIApplication.shared.connectedScenes
.compactMap({ $0 as? UIWindowScene })
.flatMap(\.windows)
.first(where: \.isKeyWindow)
else {
return nil
}
return window
}
#endif
var body: some View {
AsyncImage(url: url) { image in
ZoomableImageView(image: image)
.onAppear {
loadingState = finalLoadingState
}
.contextMenu {
#if os(iOS)
Button {
guard let url else { return }
URLSession.shared.dataTask(with: url) { data, _, _ in
guard let data, let uiImage = UIImage(data: data) else { return }
UIImageWriteToSavedPhotosAlbum(uiImage, nil, nil, nil)
}
.resume()
} label: {
Label("Save Image", systemImage: "square.and.arrow.down")
}
#endif
#if os(iOS)
if settings.enableShareShortcut {
Button {
keyWindow?.rootViewController?.present(
UIActivityViewController(
activityItems: [url ?? URL(string: "")!], applicationActivities: nil
), animated: true
)
} label: {
Label("Share Image", systemImage: "square.and.arrow.up")
}
}
#endif
if let url = postURL {
Button {
#if os(iOS)
UIApplication.shared.open(url)
#else
NSWorkspace.shared.open(url)
#endif
} label: {
Label("Open in Safari", systemImage: "safari")
}
}
}
} placeholder: {
placeholder()
.onAppear {
loadingState = .loadingPreview
}
}
}
init(
url: URL?,
loadingStage: Binding<PostLoadingState>,
finalLoadingState: PostLoadingState = .loadingFile,
postURL: URL? = nil,
@ViewBuilder placeholder: @escaping () -> Placeholder = {
GeometryReader { geometry in
ProgressView()
.frame(width: geometry.size.width, height: geometry.size.height)
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
.padding()
}
}
) {
self.url = url
_loadingState = loadingStage
self.finalLoadingState = finalLoadingState
self.postURL = postURL
self.placeholder = placeholder
}
}
|