@@ -15,12 +15,16 @@ public struct ImageViewerRemote: View {
1515 @State var dragOffset : CGSize = CGSize . zero
1616 @State var dragOffsetPredicted : CGSize = CGSize . zero
1717
18+ @ObservedObject var loader : ImageLoader
19+
1820 public init ( imageURL: Binding < String > , viewerShown: Binding < Bool > , httpHeaders: [ String : String ] ? = nil , aspectRatio: Binding < CGFloat > ? = nil , disableCache: Bool ? = nil ) {
1921 _imageURL = imageURL
2022 _viewerShown = viewerShown
2123 _httpHeaders = State ( initialValue: httpHeaders)
2224 _disableCache = State ( initialValue: disableCache)
2325 self . aspectRatio = aspectRatio
26+
27+ loader = ImageLoader ( url: imageURL, httpHeaders: httpHeaders)
2428 }
2529
2630 func getURLRequest( url: String , headers: [ String : String ] ? ) -> URLRequest {
@@ -92,10 +96,30 @@ public struct ImageViewerRemote: View {
9296 . zIndex ( 1 )
9397 }
9498 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- )
99+ if loader. image != nil {
100+ Image ( uiImage: loader. image!)
101+ . resizable ( )
102+ . aspectRatio ( self . aspectRatio? . wrappedValue, contentMode: . fit)
103+ . offset ( x: self . dragOffset. width, y: self . dragOffset. height)
104+ . rotationEffect ( . init( degrees: Double ( self . dragOffset. width / 30 ) ) )
105+ . pinchToZoom ( )
106+ . gesture ( DragGesture ( )
107+ . onChanged { value in
108+ self . dragOffset = value. translation
109+ self . dragOffsetPredicted = value. predictedEndTranslation
110+ }
111+ . onEnded { value in
112+ 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 ) {
113+ self . viewerShown = false
114+ return
115+ }
116+ self . dragOffset = . zero
117+ }
118+ )
119+ }
120+ else {
121+ Text ( " Loading... " )
122+ }
99123 }
100124 }
101125 }
@@ -269,19 +293,43 @@ extension View {
269293
270294class ImageLoader : ObservableObject {
271295 @Published var image : UIImage ?
272- private let url : URLRequest
296+ private let url : Binding < String >
297+ private let headers : [ String : String ] ?
273298 private var cancellable : AnyCancellable ?
299+
300+ func getURLRequest( url: String , headers: [ String : String ] ? ) -> URLRequest {
301+ let url = URL ( string: url) !
302+ var request = URLRequest ( url: url)
303+ request. httpMethod = " GET "
304+
305+ if ( headers != nil ) {
306+ for (key, value) in headers! {
307+ print ( " adding header: \( key) : \( value) " )
308+ request. addValue ( " \( value) " , forHTTPHeaderField: " \( key) " )
309+ }
310+
311+ print ( " headers found, requesting URL image with headers: \( request. allHTTPHeaderFields) " )
312+ return request;
313+ }
314+ else {
315+ print ( " headers nil, requesting URL image with request: \( request) " )
316+ return request;
317+ }
318+ }
274319
275- init ( url: URLRequest ) {
320+ init ( url: Binding < String > , httpHeaders : [ String : String ] ? ) {
276321 self . url = url
322+ self . headers = httpHeaders
323+
324+ load ( )
277325 }
278326
279327 deinit {
280328 cancellable? . cancel ( )
281329 }
282330
283331 func load( ) {
284- cancellable = URLSession . shared. dataTaskPublisher ( for: url)
332+ cancellable = URLSession . shared. dataTaskPublisher ( for: getURLRequest ( url: self . url . wrappedValue , headers : self . headers ) )
285333 . map { UIImage ( data: $0. data) }
286334 . replaceError ( with: nil )
287335 . receive ( on: DispatchQueue . main)
@@ -292,57 +340,3 @@ class ImageLoader: ObservableObject {
292340 cancellable? . cancel ( )
293341 }
294342}
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