Skip to content

Commit 7f688a1

Browse files
committed
Added no cache option
1 parent caf1f99 commit 7f688a1

File tree

1 file changed

+119
-23
lines changed

1 file changed

+119
-23
lines changed

Sources/ImageViewerRemote/ImageViewerRemote.swift

Lines changed: 119 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import SwiftUI
22
import UIKit
33
import URLImage
4+
import Combine
45

56
@available(iOS 13.0, *)
67
public struct ImageViewerRemote: View {
78
@Binding var viewerShown: Bool
89
@Binding var imageURL: String
910
@State var httpHeaders: [String: String]?
11+
@State var disableCache: Bool?
1012

1113
var aspectRatio: Binding<CGFloat>?
1214

1315
@State var dragOffset: CGSize = CGSize.zero
1416
@State var dragOffsetPredicted: CGSize = CGSize.zero
1517

16-
public init(imageURL: Binding<String>, viewerShown: Binding<Bool>, httpHeaders: [String: String]? = nil, aspectRatio: Binding<CGFloat>? = nil) {
18+
public init(imageURL: Binding<String>, viewerShown: Binding<Bool>, httpHeaders: [String: String]? = nil, aspectRatio: Binding<CGFloat>? = nil, disableCache: Bool? = nil) {
1719
_imageURL = imageURL
1820
_viewerShown = viewerShown
1921
_httpHeaders = State(initialValue: httpHeaders)
22+
_disableCache = State(initialValue: disableCache)
2023
self.aspectRatio = aspectRatio
2124
}
2225

@@ -62,30 +65,38 @@ public struct ImageViewerRemote: View {
6265
.zIndex(2)
6366

6467
VStack {
65-
URLImage(getURLRequest(url: self.imageURL, headers: self.httpHeaders)) { proxy in
66-
proxy.image
67-
.resizable()
68-
.aspectRatio(self.aspectRatio?.wrappedValue, contentMode: .fit)
69-
.offset(x: self.dragOffset.width, y: self.dragOffset.height)
70-
.rotationEffect(.init(degrees: Double(self.dragOffset.width / 30)))
71-
.pinchToZoom()
72-
.gesture(DragGesture()
73-
.onChanged { value in
74-
self.dragOffset = value.translation
75-
self.dragOffsetPredicted = value.predictedEndTranslation
76-
}
77-
.onEnded { value in
78-
if((abs(self.dragOffset.height) + abs(self.dragOffset.width) > 570) || ((abs(self.dragOffsetPredicted.height)) / (abs(self.dragOffset.height)) > 3) || ((abs(self.dragOffsetPredicted.width)) / (abs(self.dragOffset.width))) > 3) {
79-
self.viewerShown = false
80-
return
68+
if(self.disableCache == nil || self.disableCache == false) {
69+
URLImage(getURLRequest(url: self.imageURL, headers: self.httpHeaders)) { proxy in
70+
proxy.image
71+
.resizable()
72+
.aspectRatio(self.aspectRatio?.wrappedValue, contentMode: .fit)
73+
.offset(x: self.dragOffset.width, y: self.dragOffset.height)
74+
.rotationEffect(.init(degrees: Double(self.dragOffset.width / 30)))
75+
.pinchToZoom()
76+
.gesture(DragGesture()
77+
.onChanged { value in
78+
self.dragOffset = value.translation
79+
self.dragOffsetPredicted = value.predictedEndTranslation
8180
}
82-
self.dragOffset = .zero
83-
}
84-
)
81+
.onEnded { value in
82+
if((abs(self.dragOffset.height) + abs(self.dragOffset.width) > 570) || ((abs(self.dragOffsetPredicted.height)) / (abs(self.dragOffset.height)) > 3) || ((abs(self.dragOffsetPredicted.width)) / (abs(self.dragOffset.width))) > 3) {
83+
self.viewerShown = false
84+
return
85+
}
86+
self.dragOffset = .zero
87+
}
88+
)
89+
}
90+
.frame(maxWidth: .infinity, maxHeight: .infinity)
91+
.background(Color(red: 0.12, green: 0.12, blue: 0.12, opacity: (1.0 - Double(abs(self.dragOffset.width) + abs(self.dragOffset.height)) / 1000)).edgesIgnoringSafeArea(.all))
92+
.zIndex(1)
93+
}
94+
else {
95+
AsyncImage(
96+
url: getURLRequest(url: self.imageURL, headers: self.httpHeaders),
97+
placeholder: Text("Loading ..."), aspectRatio: self.aspectRatio, dragOffset: self.$dragOffset, dragOffsetPredicted: self.$dragOffsetPredicted, viewerShown: self.$viewerShown
98+
)
8599
}
86-
.frame(maxWidth: .infinity, maxHeight: .infinity)
87-
.background(Color(red: 0.12, green: 0.12, blue: 0.12, opacity: (1.0 - Double(abs(self.dragOffset.width) + abs(self.dragOffset.height)) / 1000)).edgesIgnoringSafeArea(.all))
88-
.zIndex(1)
89100
}
90101
}
91102
.transition(AnyTransition.opacity.animation(.easeInOut(duration: 0.2)))
@@ -250,3 +261,88 @@ extension View {
250261
self.modifier(PinchToZoom())
251262
}
252263
}
264+
265+
266+
267+
268+
269+
270+
class ImageLoader: ObservableObject {
271+
@Published var image: UIImage?
272+
private let url: URLRequest
273+
private var cancellable: AnyCancellable?
274+
275+
init(url: URLRequest) {
276+
self.url = url
277+
}
278+
279+
deinit {
280+
cancellable?.cancel()
281+
}
282+
283+
func load() {
284+
cancellable = URLSession.shared.dataTaskPublisher(for: url)
285+
.map { UIImage(data: $0.data) }
286+
.replaceError(with: nil)
287+
.receive(on: DispatchQueue.main)
288+
.assign(to: \.image, on: self)
289+
}
290+
291+
func cancel() {
292+
cancellable?.cancel()
293+
}
294+
}
295+
296+
struct AsyncImage<Placeholder: View>: View {
297+
@ObservedObject private var loader: ImageLoader
298+
299+
private let placeholder: Placeholder?
300+
301+
var aspectRatio: Binding<CGFloat>?
302+
@Binding var dragOffset: CGSize
303+
@Binding var dragOffsetPredicted: CGSize
304+
@Binding var viewerShown: Bool
305+
306+
init(url: URLRequest, placeholder: Placeholder? = nil, aspectRatio: Binding<CGFloat>?, dragOffset: Binding<CGSize>, dragOffsetPredicted: Binding<CGSize>, viewerShown: Binding<Bool>) {
307+
loader = ImageLoader(url: url)
308+
self.placeholder = placeholder
309+
self.aspectRatio = aspectRatio
310+
_dragOffset = dragOffset
311+
_dragOffsetPredicted = dragOffsetPredicted
312+
_viewerShown = viewerShown
313+
}
314+
315+
var body: some View {
316+
image
317+
.onAppear(perform: loader.load)
318+
.onDisappear(perform: loader.cancel)
319+
}
320+
321+
private var image: some View {
322+
Group {
323+
if loader.image != nil {
324+
Image(uiImage: loader.image!)
325+
.resizable()
326+
.aspectRatio(self.aspectRatio?.wrappedValue, contentMode: .fit)
327+
.offset(x: self.dragOffset.width, y: self.dragOffset.height)
328+
.rotationEffect(.init(degrees: Double(self.dragOffset.width / 30)))
329+
.pinchToZoom()
330+
.gesture(DragGesture()
331+
.onChanged { value in
332+
self.dragOffset = value.translation
333+
self.dragOffsetPredicted = value.predictedEndTranslation
334+
}
335+
.onEnded { value in
336+
if((abs(self.dragOffset.height) + abs(self.dragOffset.width) > 570) || ((abs(self.dragOffsetPredicted.height)) / (abs(self.dragOffset.height)) > 3) || ((abs(self.dragOffsetPredicted.width)) / (abs(self.dragOffset.width))) > 3) {
337+
self.viewerShown = false
338+
return
339+
}
340+
self.dragOffset = .zero
341+
}
342+
)
343+
} else {
344+
placeholder
345+
}
346+
}
347+
}
348+
}

0 commit comments

Comments
 (0)