From a193e4bac56259e9fe032d1b7b206a4615f71b49 Mon Sep 17 00:00:00 2001 From: sameh Date: Wed, 11 Mar 2020 11:10:20 +0200 Subject: [PATCH 01/14] Adding blurred background view --- ImageViewer/Source/ItemBaseController.swift | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ImageViewer/Source/ItemBaseController.swift b/ImageViewer/Source/ItemBaseController.swift index 57cdfbe5..ea5ceb56 100644 --- a/ImageViewer/Source/ItemBaseController.swift +++ b/ImageViewer/Source/ItemBaseController.swift @@ -18,6 +18,7 @@ open class ItemBaseController: UIViewController, ItemController, UIGe //UI public var itemView = T() let scrollView = UIScrollView() + let backgroundView = UIImageView() let activityIndicatorView = UIActivityIndicatorView(style: .white) //DELEGATE / DATASOURCE @@ -108,6 +109,7 @@ open class ItemBaseController: UIViewController, ItemController, UIGe self.itemView.isHidden = isInitialController + configureBackgroundView() configureScrollView() configureGestureRecognizers() @@ -124,6 +126,16 @@ open class ItemBaseController: UIViewController, ItemController, UIGe // MARK: - Configuration + fileprivate func configureBackgroundView(){ + backgroundView.contentMode = .scaleToFill + backgroundView.frame = view.frame + let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark) + let blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView.frame = backgroundView.bounds + blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + backgroundView.addSubview(blurEffectView) + } + fileprivate func configureScrollView() { scrollView.showsHorizontalScrollIndicator = false @@ -177,7 +189,7 @@ open class ItemBaseController: UIViewController, ItemController, UIGe } fileprivate func createViewHierarchy() { - + self.view.addSubview(backgroundView) self.view.addSubview(scrollView) scrollView.addSubview(itemView) @@ -206,6 +218,7 @@ open class ItemBaseController: UIViewController, ItemController, UIGe var itemView = self?.itemView itemView?.image = image + self?.backgroundView.image = image itemView?.isAccessibilityElement = image.isAccessibilityElement itemView?.accessibilityLabel = image.accessibilityLabel itemView?.accessibilityTraits = image.accessibilityTraits From 4f6d6d990af1a9982c93020fb277ba3230ccb0a3 Mon Sep 17 00:00:00 2001 From: sameh Date: Wed, 11 Mar 2020 21:28:50 +0200 Subject: [PATCH 02/14] update version --- ImageViewer.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageViewer.podspec b/ImageViewer.podspec index 46313ff4..14852668 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.0.0" + s.version = "6.0.1" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. From ee2a9f5ba45a416f2b41e2a7639b1aadf6fb6d76 Mon Sep 17 00:00:00 2001 From: sameh Date: Mon, 23 Mar 2020 20:18:36 +0200 Subject: [PATCH 03/14] Added raw Video playing source --- ImageViewer/Source/GalleryItem.swift | 4 ++ .../Source/GalleryPagingDataSource.swift | 10 ++++ .../ThumbnailsViewController.swift | 2 +- ImageViewer/Source/VideoViewController.swift | 48 +++++++++++++++++-- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/ImageViewer/Source/GalleryItem.swift b/ImageViewer/Source/GalleryItem.swift index 0a8cb0d2..7eb9b952 100644 --- a/ImageViewer/Source/GalleryItem.swift +++ b/ImageViewer/Source/GalleryItem.swift @@ -7,14 +7,18 @@ // import UIKit +import AVKit public typealias ImageCompletion = (UIImage?) -> Void +public typealias VideoCompletion = (AVAsset?) -> Void public typealias FetchImageBlock = (@escaping ImageCompletion) -> Void +public typealias FetchVideoBlock = (@escaping VideoCompletion) -> Void public typealias ItemViewControllerBlock = (_ index: Int, _ itemCount: Int, _ fetchImageBlock: FetchImageBlock, _ configuration: GalleryConfiguration, _ isInitialController: Bool) -> UIViewController public enum GalleryItem { case image(fetchImageBlock: FetchImageBlock) case video(fetchPreviewImageBlock: FetchImageBlock, videoURL: URL) + case rawVideo(fetchPreviewImageBlock: FetchImageBlock, fetchRawVideoBlock: FetchVideoBlock) case custom(fetchImageBlock: FetchImageBlock, itemViewControllerBlock: ItemViewControllerBlock) } diff --git a/ImageViewer/Source/GalleryPagingDataSource.swift b/ImageViewer/Source/GalleryPagingDataSource.swift index 43ccbb22..79ec6701 100644 --- a/ImageViewer/Source/GalleryPagingDataSource.swift +++ b/ImageViewer/Source/GalleryPagingDataSource.swift @@ -102,6 +102,16 @@ final class GalleryPagingDataSource: NSObject, UIPageViewControllerDataSource { itemController.displacedViewsDataSource = displacedViewsDataSource return vc + + case .rawVideo(let fetchImageBlock, let fetchVideoBlock): + + let videoController = VideoViewController(index: itemIndex, itemCount: itemsDataSource.itemCount(), fetchImageBlock: fetchImageBlock, fetchVideoBlock:fetchVideoBlock, scrubber: scrubber, configuration: configuration, isInitialController: isInitial) + + videoController.delegate = itemControllerDelegate + videoController.displacedViewsDataSource = displacedViewsDataSource + + return videoController + } } } diff --git a/ImageViewer/Source/Thumbnails Controller/ThumbnailsViewController.swift b/ImageViewer/Source/Thumbnails Controller/ThumbnailsViewController.swift index 5555528f..0965eb0b 100644 --- a/ImageViewer/Source/Thumbnails Controller/ThumbnailsViewController.swift +++ b/ImageViewer/Source/Thumbnails Controller/ThumbnailsViewController.swift @@ -116,7 +116,7 @@ class ThumbnailsViewController: UICollectionViewController, UICollectionViewDele } } - case .video(let fetchImageBlock, _): + case .video(let fetchImageBlock, _),.rawVideo(fetchPreviewImageBlock: let fetchImageBlock, _): fetchImageBlock() { image in diff --git a/ImageViewer/Source/VideoViewController.swift b/ImageViewer/Source/VideoViewController.swift index 383a52c6..07f058db 100644 --- a/ImageViewer/Source/VideoViewController.swift +++ b/ImageViewer/Source/VideoViewController.swift @@ -16,10 +16,12 @@ class VideoViewController: ItemBaseController { fileprivate let swipeToDismissFadeOutAccelerationFactor: CGFloat = 6 - let videoURL: URL - let player: AVPlayer + let videoURL: URL? + var fetchVideoBlock:FetchVideoBlock? + var player: AVPlayer! unowned let scrubber: VideoScrubber + let fullHDScreenSizeLandscape = CGSize(width: 1920, height: 1080) let fullHDScreenSizePortrait = CGSize(width: 1080, height: 1920) let embeddedPlayButton = UIButton.circlePlayButton(70) @@ -31,8 +33,8 @@ class VideoViewController: ItemBaseController { self.videoURL = videoURL self.scrubber = scrubber - self.player = AVPlayer(url: self.videoURL) - + self.player = AVPlayer(url: videoURL) + ///Only those options relevant to the paging VideoViewController are explicitly handled here, the rest is handled by ItemViewControllers for item in configuration { @@ -48,6 +50,44 @@ class VideoViewController: ItemBaseController { super.init(index: index, itemCount: itemCount, fetchImageBlock: fetchImageBlock, configuration: configuration, isInitialController: isInitialController) } + init(index: Int, itemCount: Int, fetchImageBlock: @escaping FetchImageBlock, fetchVideoBlock: @escaping FetchVideoBlock, scrubber: VideoScrubber, configuration: GalleryConfiguration, isInitialController: Bool = false) { + + self.fetchVideoBlock = fetchVideoBlock + self.videoURL = nil + self.scrubber = scrubber + self.player = nil +// self.player = AVPlayer(playerItem: AVPlayerItem(asset: s)) + //AVPlayer(url: self.videoURL) + + ///Only those options relevant to the paging VideoViewController are explicitly handled here, the rest is handled by ItemViewControllers + for item in configuration { + + switch item { + + case .videoAutoPlay(let enabled): + autoPlayEnabled = enabled + + default: break + } + } + + super.init(index: index, itemCount: itemCount, fetchImageBlock: fetchImageBlock, configuration: configuration, isInitialController: isInitialController) + } + + public func fetchVideo() { + + fetchVideoBlock? { [weak self] video in + + if let video = video { + + DispatchQueue.main.async { + self?.activityIndicatorView.stopAnimating() + self?.player = AVPlayer(playerItem: AVPlayerItem(asset: video)) + } + } + } + } + override func viewDidLoad() { super.viewDidLoad() From 4d0a40f28ea6edda21243aeb33893e67beab75a4 Mon Sep 17 00:00:00 2001 From: Sameh Sayed Date: Fri, 27 Mar 2020 12:29:20 +0200 Subject: [PATCH 04/14] updated version --- ImageViewer.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageViewer.podspec b/ImageViewer.podspec index 14852668..6853e65e 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.0.1" + s.version = "6.1" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. From b27f6c3f6f7653b9e256da2f6a5396e0a7e8afd1 Mon Sep 17 00:00:00 2001 From: sameh Date: Fri, 3 Apr 2020 13:48:05 +0200 Subject: [PATCH 05/14] Revert "Added raw Video playing source" This reverts commit ee2a9f5ba45a416f2b41e2a7639b1aadf6fb6d76. --- ImageViewer/Source/VideoViewController.swift | 48 ++------------------ 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/ImageViewer/Source/VideoViewController.swift b/ImageViewer/Source/VideoViewController.swift index 07f058db..383a52c6 100644 --- a/ImageViewer/Source/VideoViewController.swift +++ b/ImageViewer/Source/VideoViewController.swift @@ -16,12 +16,10 @@ class VideoViewController: ItemBaseController { fileprivate let swipeToDismissFadeOutAccelerationFactor: CGFloat = 6 - let videoURL: URL? - var fetchVideoBlock:FetchVideoBlock? - var player: AVPlayer! + let videoURL: URL + let player: AVPlayer unowned let scrubber: VideoScrubber - let fullHDScreenSizeLandscape = CGSize(width: 1920, height: 1080) let fullHDScreenSizePortrait = CGSize(width: 1080, height: 1920) let embeddedPlayButton = UIButton.circlePlayButton(70) @@ -33,8 +31,8 @@ class VideoViewController: ItemBaseController { self.videoURL = videoURL self.scrubber = scrubber - self.player = AVPlayer(url: videoURL) - + self.player = AVPlayer(url: self.videoURL) + ///Only those options relevant to the paging VideoViewController are explicitly handled here, the rest is handled by ItemViewControllers for item in configuration { @@ -50,44 +48,6 @@ class VideoViewController: ItemBaseController { super.init(index: index, itemCount: itemCount, fetchImageBlock: fetchImageBlock, configuration: configuration, isInitialController: isInitialController) } - init(index: Int, itemCount: Int, fetchImageBlock: @escaping FetchImageBlock, fetchVideoBlock: @escaping FetchVideoBlock, scrubber: VideoScrubber, configuration: GalleryConfiguration, isInitialController: Bool = false) { - - self.fetchVideoBlock = fetchVideoBlock - self.videoURL = nil - self.scrubber = scrubber - self.player = nil -// self.player = AVPlayer(playerItem: AVPlayerItem(asset: s)) - //AVPlayer(url: self.videoURL) - - ///Only those options relevant to the paging VideoViewController are explicitly handled here, the rest is handled by ItemViewControllers - for item in configuration { - - switch item { - - case .videoAutoPlay(let enabled): - autoPlayEnabled = enabled - - default: break - } - } - - super.init(index: index, itemCount: itemCount, fetchImageBlock: fetchImageBlock, configuration: configuration, isInitialController: isInitialController) - } - - public func fetchVideo() { - - fetchVideoBlock? { [weak self] video in - - if let video = video { - - DispatchQueue.main.async { - self?.activityIndicatorView.stopAnimating() - self?.player = AVPlayer(playerItem: AVPlayerItem(asset: video)) - } - } - } - } - override func viewDidLoad() { super.viewDidLoad() From 65ecd02851f3e3b04682457537436a282272c6b4 Mon Sep 17 00:00:00 2001 From: sameh Date: Fri, 3 Apr 2020 13:50:18 +0200 Subject: [PATCH 06/14] dded video raw vc --- Example/ViewController.swift | 6 + ImageViewer.xcodeproj/project.pbxproj | 6 + .../Source/GalleryPagingDataSource.swift | 2 +- .../Source/VideoRawViewController.swift | 251 ++++++++++++++++++ 4 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 ImageViewer/Source/VideoRawViewController.swift diff --git a/Example/ViewController.swift b/Example/ViewController.swift index b7532fa6..571c9afb 100644 --- a/Example/ViewController.swift +++ b/Example/ViewController.swift @@ -7,6 +7,7 @@ // import UIKit +import AVKit extension UIImageView: DisplaceableView {} @@ -44,6 +45,11 @@ class ViewController: UIViewController { galleryItem = GalleryItem.video(fetchPreviewImageBlock: { $0(UIImage(named: "2")!) }, videoURL: URL (string: "http://video.dailymail.co.uk/video/mol/test/2016/09/21/5739239377694275356/1024x576_MP4_5739239377694275356.mp4")!) +// galleryItem = GalleryItem.rawVideo(fetchPreviewImageBlock: { $0(UIImage(named: "2")!) }, fetchRawVideoBlock: { w in +// w(AVAsset(url:URL(string: "http://video.dailymail.co.uk/video/mol/test/2016/09/21/5739239377694275356/1024x576_MP4_5739239377694275356.mp4")!)) +// }) + + case 4: let myFetchImageBlock: FetchImageBlock = { $0(imageView.image!) } diff --git a/ImageViewer.xcodeproj/project.pbxproj b/ImageViewer.xcodeproj/project.pbxproj index 521a5a95..9952d66a 100644 --- a/ImageViewer.xcodeproj/project.pbxproj +++ b/ImageViewer.xcodeproj/project.pbxproj @@ -28,6 +28,8 @@ C7897CEF1C1350B7006447FB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C7897CED1C1350B7006447FB /* LaunchScreen.storyboard */; }; C7897CF61C1356C6006447FB /* CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DABE631C12276800F5BD7B /* CGSize.swift */; }; C7DABE641C12276800F5BD7B /* CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DABE631C12276800F5BD7B /* CGSize.swift */; }; + D043A10B24374E630069591A /* VideoRawViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D043A10A24374E630069591A /* VideoRawViewController.swift */; }; + D043A10C243750650069591A /* VideoRawViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D043A10A24374E630069591A /* VideoRawViewController.swift */; }; EB057A151D510264007565F1 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB057A141D510264007565F1 /* AVPlayer.swift */; }; EB057A161D510264007565F1 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB057A141D510264007565F1 /* AVPlayer.swift */; }; EB17B3781D4A51D200EED1DA /* UIBezierPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB17B3771D4A51D200EED1DA /* UIBezierPath.swift */; }; @@ -111,6 +113,7 @@ C7897CF01C1350B7006447FB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C7DABE481C12245B00F5BD7B /* ImageViewer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ImageViewer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C7DABE631C12276800F5BD7B /* CGSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGSize.swift; sourceTree = ""; }; + D043A10A24374E630069591A /* VideoRawViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRawViewController.swift; sourceTree = ""; }; EB057A141D510264007565F1 /* AVPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AVPlayer.swift; sourceTree = ""; }; EB17B3771D4A51D200EED1DA /* UIBezierPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIBezierPath.swift; sourceTree = ""; }; EB17B37D1D4A5A2500EED1DA /* CAShapeLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAShapeLayer.swift; sourceTree = ""; }; @@ -353,6 +356,7 @@ EB6F46541D4660AC00984035 /* VideoView.swift */, EB60EE551D58EB4800CC5BA8 /* VideoScrubber.swift */, EB60EE581D590E8B00CC5BA8 /* Slider.swift */, + D043A10A24374E630069591A /* VideoRawViewController.swift */, ); name = Video; sourceTree = ""; @@ -556,6 +560,7 @@ 13BDF0721E573D10009C458F /* UIColor.swift in Sources */, 4CD1C49C1C16FF64008D5F84 /* CGPoint.swift in Sources */, EBA76F711D4F855C0094931F /* ItemBaseController.swift in Sources */, + D043A10C243750650069591A /* VideoRawViewController.swift in Sources */, EB4DEBC01C84A6FD00D5F897 /* UIView.swift in Sources */, EBAF4C631D3937AE0039CA93 /* ImageViewController.swift in Sources */, EB40C3771C9C5C48004EA215 /* GalleryItemsDataSource.swift in Sources */, @@ -598,6 +603,7 @@ EBA0A9541C89C653005B8DD3 /* GalleryConfiguration.swift in Sources */, EB17B3791D4A51D200EED1DA /* UIBezierPath.swift in Sources */, EB1DB6EA1D3E595D00DC9064 /* UIApplication.swift in Sources */, + D043A10B24374E630069591A /* VideoRawViewController.swift in Sources */, EBBFCB971D26CBA2007E7244 /* BlurView.swift in Sources */, EB8BEC7B1D3D1CB500DCE3EC /* ItemControllerDelegate.swift in Sources */, EB60EE5A1D590E8B00CC5BA8 /* Slider.swift in Sources */, diff --git a/ImageViewer/Source/GalleryPagingDataSource.swift b/ImageViewer/Source/GalleryPagingDataSource.swift index 79ec6701..d9c282ac 100644 --- a/ImageViewer/Source/GalleryPagingDataSource.swift +++ b/ImageViewer/Source/GalleryPagingDataSource.swift @@ -105,7 +105,7 @@ final class GalleryPagingDataSource: NSObject, UIPageViewControllerDataSource { case .rawVideo(let fetchImageBlock, let fetchVideoBlock): - let videoController = VideoViewController(index: itemIndex, itemCount: itemsDataSource.itemCount(), fetchImageBlock: fetchImageBlock, fetchVideoBlock:fetchVideoBlock, scrubber: scrubber, configuration: configuration, isInitialController: isInitial) + let videoController = VideoRawViewController(index: itemIndex, itemCount: itemsDataSource.itemCount(), fetchImageBlock: fetchImageBlock, fetchVideoBlock:fetchVideoBlock, scrubber: scrubber, configuration: configuration, isInitialController: isInitial) videoController.delegate = itemControllerDelegate videoController.displacedViewsDataSource = displacedViewsDataSource diff --git a/ImageViewer/Source/VideoRawViewController.swift b/ImageViewer/Source/VideoRawViewController.swift new file mode 100644 index 00000000..db908786 --- /dev/null +++ b/ImageViewer/Source/VideoRawViewController.swift @@ -0,0 +1,251 @@ +// +// VideoRawViewController.swift +// ImageViewer +// +// Created by Sameh sayed on 4/3/20. +// Copyright © 2020 MailOnline. All rights reserved. +// + +import Foundation +import UIKit +import AVFoundation + + +class VideoRawViewController: ItemBaseController { + + fileprivate let swipeToDismissFadeOutAccelerationFactor: CGFloat = 6 + + + var fetchVideoBlock:FetchVideoBlock? + + var player: AVPlayer? + unowned let scrubber: VideoScrubber + + let fullHDScreenSizeLandscape = CGSize(width: 1920, height: 1080) + let fullHDScreenSizePortrait = CGSize(width: 1080, height: 1920) + let embeddedPlayButton = UIButton.circlePlayButton(70) + + private var autoPlayStarted: Bool = false + private var autoPlayEnabled: Bool = false + + init(index: Int, itemCount: Int, fetchImageBlock: @escaping FetchImageBlock, fetchVideoBlock: @escaping FetchVideoBlock, scrubber: VideoScrubber, configuration: GalleryConfiguration, isInitialController: Bool = false) + { + self.fetchVideoBlock = fetchVideoBlock + self.scrubber = scrubber + + for item in configuration { + + switch item { + + case .videoAutoPlay(let enabled): + autoPlayEnabled = enabled + + default: break + } + } + super.init(index: index, itemCount: itemCount, fetchImageBlock: fetchImageBlock, configuration: configuration, isInitialController: isInitialController) + } + + override func viewDidLoad() { + super.viewDidLoad() + + if isInitialController == true { embeddedPlayButton.alpha = 0 } + } + + public func fetchVideo() { + activityIndicatorView.startAnimating() + + fetchVideoBlock? { [weak self] video in + + if let video = video { + + DispatchQueue.main.async { + self?.activityIndicatorView.stopAnimating() +// self?.player = + let s = video as? AVURLAsset + + self?.player = AVPlayer(url: s!.url) + //AVPlayer(playerItem: AVPlayerItem(asset: video)) + self?.embeddedPlayButton.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin, .flexibleBottomMargin, .flexibleRightMargin] + self?.view.addSubview(self!.embeddedPlayButton) + self?.embeddedPlayButton.center = self!.view.boundsCenter + self?.embeddedPlayButton.addTarget(self, action: #selector(self?.playVideoInitially), for: UIControl.Event.touchUpInside) + self?.itemView.player = self?.player + self?.itemView.contentMode = .scaleAspectFill + + self?.view.setNeedsLayout() + self?.view.layoutIfNeeded() + self?.performAutoPlay() + } + } + } + } + + override func viewWillAppear(_ animated: Bool) { + + self.player?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil) + self.player?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil) + + UIApplication.shared.beginReceivingRemoteControlEvents() + + super.viewWillAppear(animated) + } + + override func viewWillDisappear(_ animated: Bool) { + + self.player?.removeObserver(self, forKeyPath: "status") + self.player?.removeObserver(self, forKeyPath: "rate") + + UIApplication.shared.endReceivingRemoteControlEvents() + + super.viewWillDisappear(animated) + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + fetchVideo() + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + self.player?.pause() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + let isLandscape = itemView.bounds.width >= itemView.bounds.height + itemView.bounds.size = aspectFitSize(forContentOfSize: isLandscape ? fullHDScreenSizeLandscape : fullHDScreenSizePortrait, inBounds: self.scrollView.bounds.size) + itemView.center = scrollView.boundsCenter + } + + @objc func playVideoInitially() { + + self.player?.play() + + + UIView.animate(withDuration: 0.25, animations: { [weak self] in + + self?.embeddedPlayButton.alpha = 0 + + }, completion: { [weak self] _ in + + self?.embeddedPlayButton.isHidden = true + }) + } + + override func closeDecorationViews(_ duration: TimeInterval) { + + UIView.animate(withDuration: duration, animations: { [weak self] in + + self?.embeddedPlayButton.alpha = 0 + self?.itemView.previewImageView.alpha = 1 + }) + } + + override func presentItem(alongsideAnimation: () -> Void, completion: @escaping () -> Void) { + + let circleButtonAnimation = { + + UIView.animate(withDuration: 0.15, animations: { [weak self] in + self?.embeddedPlayButton.alpha = 1 + }) + } + + super.presentItem(alongsideAnimation: alongsideAnimation) { + + circleButtonAnimation() + completion() + } + } + + override func displacementTargetSize(forSize size: CGSize) -> CGSize { + + let isLandscape = itemView.bounds.width >= itemView.bounds.height + return aspectFitSize(forContentOfSize: isLandscape ? fullHDScreenSizeLandscape : fullHDScreenSizePortrait, inBounds: rotationAdjustedBounds().size) + } + + override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + + if keyPath == "rate" || keyPath == "status" { + + fadeOutEmbeddedPlayButton() + } + + else if keyPath == "contentOffset" { + + handleSwipeToDismissTransition() + } + + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + } + + func handleSwipeToDismissTransition() { + + guard let _ = swipingToDismiss else { return } + + embeddedPlayButton.center.y = view.center.y - scrollView.contentOffset.y + } + + func fadeOutEmbeddedPlayButton() { + + if (player?.isPlaying() ?? false) && embeddedPlayButton.alpha != 0 { + + UIView.animate(withDuration: 0.3, animations: { [weak self] in + + self?.embeddedPlayButton.alpha = 0 + }) + } + } + + override func remoteControlReceived(with event: UIEvent?) { + + if let event = event { + + if event.type == UIEvent.EventType.remoteControl { + + switch event.subtype { + + case .remoteControlTogglePlayPause: + + if (self.player?.isPlaying() ?? false) { + + self.player?.pause() + } + else { + + self.player?.play() + } + + case .remoteControlPause: + + self.player?.pause() + + case .remoteControlPlay: + + self.player?.play() + + case .remoteControlPreviousTrack: + + self.player?.pause() + self.player?.seek(to: CMTime(value: 0, timescale: 1)) + self.player?.play() + + default: + + break + } + } + } + } + + private func performAutoPlay() { + guard autoPlayEnabled else { return } + guard autoPlayStarted == false else { return } + + autoPlayStarted = true + embeddedPlayButton.isHidden = true + scrubber.play() + } +} From 2134d5b0b9b7a17d8e4c10f89bc655db2d3ed6f6 Mon Sep 17 00:00:00 2001 From: sameh Date: Fri, 3 Apr 2020 21:17:03 +0200 Subject: [PATCH 07/14] Optimized Raw Video --- .../Source/GalleryViewController.swift | 18 ++++++++- .../Source/VideoRawViewController.swift | 38 +++++++++++-------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/ImageViewer/Source/GalleryViewController.swift b/ImageViewer/Source/GalleryViewController.swift index 9101b0c8..62b779fc 100644 --- a/ImageViewer/Source/GalleryViewController.swift +++ b/ImageViewer/Source/GalleryViewController.swift @@ -613,7 +613,7 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { self?.thumbnailsButton?.alpha = targetAlpha self?.deleteButton?.alpha = targetAlpha - if let _ = self?.viewControllers?.first as? VideoViewController { + if let _ = self?.viewControllers?.first as? ItemBaseController { UIView.animate(withDuration: 0.3, animations: { [weak self] in @@ -626,14 +626,17 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { public func itemControllerWillAppear(_ controller: ItemController) { if let videoController = controller as? VideoViewController { + scrubber.player = videoController.player + } + if let videoController = controller as? VideoRawViewController { scrubber.player = videoController.player } } public func itemControllerWillDisappear(_ controller: ItemController) { - if let _ = controller as? VideoViewController { + if let _ = controller as? ItemBaseController { scrubber.player = nil @@ -661,6 +664,17 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { }) } } + + if let videoController = controller as? VideoRawViewController { + scrubber.player = videoController.player + if scrubber.alpha == 0 && decorationViewsHidden == false { + + UIView.animate(withDuration: 0.3, animations: { [weak self] in + + self?.scrubber.alpha = 1 + }) + } + } } open func itemControllerDidSingleTap(_ controller: ItemController) { diff --git a/ImageViewer/Source/VideoRawViewController.swift b/ImageViewer/Source/VideoRawViewController.swift index db908786..9cb4f5fa 100644 --- a/ImageViewer/Source/VideoRawViewController.swift +++ b/ImageViewer/Source/VideoRawViewController.swift @@ -60,15 +60,13 @@ class VideoRawViewController: ItemBaseController { if let video = video { DispatchQueue.main.async { - self?.activityIndicatorView.stopAnimating() -// self?.player = - let s = video as? AVURLAsset + guard let S = self else { return } - self?.player = AVPlayer(url: s!.url) - //AVPlayer(playerItem: AVPlayerItem(asset: video)) + self?.activityIndicatorView.stopAnimating() + self?.player = AVPlayer(playerItem: AVPlayerItem(asset: video)) self?.embeddedPlayButton.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin, .flexibleBottomMargin, .flexibleRightMargin] self?.view.addSubview(self!.embeddedPlayButton) - self?.embeddedPlayButton.center = self!.view.boundsCenter + self?.embeddedPlayButton.center = S.view.boundsCenter self?.embeddedPlayButton.addTarget(self, action: #selector(self?.playVideoInitially), for: UIControl.Event.touchUpInside) self?.itemView.player = self?.player self?.itemView.contentMode = .scaleAspectFill @@ -76,26 +74,30 @@ class VideoRawViewController: ItemBaseController { self?.view.setNeedsLayout() self?.view.layoutIfNeeded() self?.performAutoPlay() + self?.scrubber.player = self?.player + + + self?.player?.addObserver(S, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil) + self?.player?.addObserver(S, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil) } } } } override func viewWillAppear(_ animated: Bool) { - - self.player?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil) - self.player?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil) - UIApplication.shared.beginReceivingRemoteControlEvents() - + if player != nil { + self.player?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil) + self.player?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil) + } super.viewWillAppear(animated) } override func viewWillDisappear(_ animated: Bool) { - - self.player?.removeObserver(self, forKeyPath: "status") - self.player?.removeObserver(self, forKeyPath: "rate") - + if player != nil { + self.player?.removeObserver(self, forKeyPath: "status") + self.player?.removeObserver(self, forKeyPath: "rate") + } UIApplication.shared.endReceivingRemoteControlEvents() super.viewWillDisappear(animated) @@ -103,7 +105,11 @@ class VideoRawViewController: ItemBaseController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - fetchVideo() + if player == nil { + fetchVideo() + }else{ + self.performAutoPlay() + } } override func viewDidDisappear(_ animated: Bool) { From 3660553795b85ef7bc9030e3932cd5e570bbe7fd Mon Sep 17 00:00:00 2001 From: sameh Date: Sat, 4 Apr 2020 15:36:55 +0200 Subject: [PATCH 08/14] #update version --- ImageViewer.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageViewer.podspec b/ImageViewer.podspec index 6853e65e..255eb489 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.1" + s.version = "6.1.2" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. From f25d7f279c8dd302e45c7a3297c7ed57a230808f Mon Sep 17 00:00:00 2001 From: sameh Date: Mon, 3 Aug 2020 21:52:33 +0200 Subject: [PATCH 09/14] Added Catalyst support --- Example/Example.entitlements | 10 ++++++++++ ImageViewer.xcodeproj/project.pbxproj | 20 +++++++++++++++++++ ImageViewer/Source/Extensions/UIView.swift | 2 +- .../Source/GalleryViewController.swift | 9 +++++---- ImageViewer/Source/ItemBaseController.swift | 5 ++++- 5 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 Example/Example.entitlements diff --git a/Example/Example.entitlements b/Example/Example.entitlements new file mode 100644 index 00000000..ee95ab7e --- /dev/null +++ b/Example/Example.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + diff --git a/ImageViewer.xcodeproj/project.pbxproj b/ImageViewer.xcodeproj/project.pbxproj index 9952d66a..580be3c9 100644 --- a/ImageViewer.xcodeproj/project.pbxproj +++ b/ImageViewer.xcodeproj/project.pbxproj @@ -114,6 +114,7 @@ C7DABE481C12245B00F5BD7B /* ImageViewer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ImageViewer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C7DABE631C12276800F5BD7B /* CGSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGSize.swift; sourceTree = ""; }; D043A10A24374E630069591A /* VideoRawViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRawViewController.swift; sourceTree = ""; }; + D095DC2624D89B7F006F0173 /* Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Example.entitlements; sourceTree = ""; }; EB057A141D510264007565F1 /* AVPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AVPlayer.swift; sourceTree = ""; }; EB17B3771D4A51D200EED1DA /* UIBezierPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIBezierPath.swift; sourceTree = ""; }; EB17B37D1D4A5A2500EED1DA /* CAShapeLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAShapeLayer.swift; sourceTree = ""; }; @@ -188,6 +189,7 @@ C7897CE31C1350B7006447FB /* Example */ = { isa = PBXGroup; children = ( + D095DC2624D89B7F006F0173 /* Example.entitlements */, C7897CE41C1350B7006447FB /* AppDelegate.swift */, C7897CE61C1350B7006447FB /* ViewController.swift */, EB5253F31C8DCE9800EAA4A4 /* CounterView.swift */, @@ -464,7 +466,9 @@ TargetAttributes = { C7897CE11C1350B7006447FB = { CreatedOnToolsVersion = 7.1.1; + DevelopmentTeam = V862M46692; LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; }; C7DABE471C12245B00F5BD7B = { CreatedOnToolsVersion = 7.1.1; @@ -652,11 +656,19 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = V862M46692; INFOPLIST_FILE = Example/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.4; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = mailonline.Example; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SUPPORTS_MACCATALYST = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; }; @@ -666,11 +678,19 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = V862M46692; INFOPLIST_FILE = Example/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.4; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = mailonline.Example; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SUPPORTS_MACCATALYST = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; }; diff --git a/ImageViewer/Source/Extensions/UIView.swift b/ImageViewer/Source/Extensions/UIView.swift index 2d832cf0..7a12b652 100644 --- a/ImageViewer/Source/Extensions/UIView.swift +++ b/ImageViewer/Source/Extensions/UIView.swift @@ -41,6 +41,6 @@ extension DisplaceableView { func frameInCoordinatesOfScreen() -> CGRect { - return UIView().convert(self.bounds, to: UIScreen.main.coordinateSpace) + return UIView().convert(self.bounds, to: (UIApplication.shared.delegate as! AppDelegate).window!.coordinateSpace) } } diff --git a/ImageViewer/Source/GalleryViewController.swift b/ImageViewer/Source/GalleryViewController.swift index 62b779fc..75926e11 100644 --- a/ImageViewer/Source/GalleryViewController.swift +++ b/ImageViewer/Source/GalleryViewController.swift @@ -189,9 +189,10 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { fileprivate func configureOverlayView() { + let _bounds = (UIApplication.shared.delegate as! AppDelegate).window!.bounds + overlayView.bounds.size = _bounds.insetBy(dx: -_bounds.width / 2, dy: -_bounds.height / 2).size + overlayView.center = CGPoint(x: (_bounds.width / 2), y: (_bounds.height / 2)) - overlayView.bounds.size = UIScreen.main.bounds.insetBy(dx: -UIScreen.main.bounds.width / 2, dy: -UIScreen.main.bounds.height / 2).size - overlayView.center = CGPoint(x: (UIScreen.main.bounds.width / 2), y: (UIScreen.main.bounds.height / 2)) self.view.addSubview(overlayView) self.view.sendSubviewToBack(overlayView) @@ -315,8 +316,8 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { self.view.transform = transform self.view.bounds = bounds } - - overlayView.frame = view.bounds.insetBy(dx: -UIScreen.main.bounds.width * 2, dy: -UIScreen.main.bounds.height * 2) + let _bounds = (UIApplication.shared.delegate as! AppDelegate).window!.bounds + overlayView.frame = view.bounds.insetBy(dx: -_bounds.width * 2, dy: -_bounds.height * 2) layoutButton(closeButton, layout: closeLayout) layoutButton(thumbnailsButton, layout: thumbnailsLayout) diff --git a/ImageViewer/Source/ItemBaseController.swift b/ImageViewer/Source/ItemBaseController.swift index ea5ceb56..5c03cee5 100644 --- a/ImageViewer/Source/ItemBaseController.swift +++ b/ImageViewer/Source/ItemBaseController.swift @@ -128,7 +128,8 @@ open class ItemBaseController: UIViewController, ItemController, UIGe fileprivate func configureBackgroundView(){ backgroundView.contentMode = .scaleToFill - backgroundView.frame = view.frame + let _frame = (UIApplication.shared.delegate as! AppDelegate).window!.frame + backgroundView.frame = _frame let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark) let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.frame = backgroundView.bounds @@ -253,6 +254,8 @@ open class ItemBaseController: UIViewController, ItemController, UIGe scrollView.frame = self.view.bounds activityIndicatorView.center = view.boundsCenter + let _frame = (UIApplication.shared.delegate as! AppDelegate).window!.frame + backgroundView.frame = _frame if let size = itemView.image?.size , size != CGSize.zero { From 19c7ca80422578bc27a72395b48ed7c7ef1ad1df Mon Sep 17 00:00:00 2001 From: sameh Date: Mon, 3 Aug 2020 21:53:52 +0200 Subject: [PATCH 10/14] Version 6.2 --- ImageViewer.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageViewer.podspec b/ImageViewer.podspec index 255eb489..2ba150af 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.1.2" + s.version = "6.2" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. From b474b71148787e3679bd04733933d5066a56837d Mon Sep 17 00:00:00 2001 From: sameh Date: Mon, 3 Aug 2020 22:00:48 +0200 Subject: [PATCH 11/14] changing usage of window --- ImageViewer/Source/Extensions/UIView.swift | 2 +- ImageViewer/Source/GalleryViewController.swift | 4 ++-- ImageViewer/Source/ItemBaseController.swift | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ImageViewer/Source/Extensions/UIView.swift b/ImageViewer/Source/Extensions/UIView.swift index 7a12b652..46541743 100644 --- a/ImageViewer/Source/Extensions/UIView.swift +++ b/ImageViewer/Source/Extensions/UIView.swift @@ -41,6 +41,6 @@ extension DisplaceableView { func frameInCoordinatesOfScreen() -> CGRect { - return UIView().convert(self.bounds, to: (UIApplication.shared.delegate as! AppDelegate).window!.coordinateSpace) + return UIView().convert(self.bounds, to: UIApplication.shared.keyWindow!.coordinateSpace) } } diff --git a/ImageViewer/Source/GalleryViewController.swift b/ImageViewer/Source/GalleryViewController.swift index 75926e11..c3755948 100644 --- a/ImageViewer/Source/GalleryViewController.swift +++ b/ImageViewer/Source/GalleryViewController.swift @@ -189,7 +189,7 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { fileprivate func configureOverlayView() { - let _bounds = (UIApplication.shared.delegate as! AppDelegate).window!.bounds + let _bounds = UIApplication.shared.keyWindow!.bounds overlayView.bounds.size = _bounds.insetBy(dx: -_bounds.width / 2, dy: -_bounds.height / 2).size overlayView.center = CGPoint(x: (_bounds.width / 2), y: (_bounds.height / 2)) @@ -316,7 +316,7 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { self.view.transform = transform self.view.bounds = bounds } - let _bounds = (UIApplication.shared.delegate as! AppDelegate).window!.bounds + let _bounds = UIApplication.shared.keyWindow!.bounds overlayView.frame = view.bounds.insetBy(dx: -_bounds.width * 2, dy: -_bounds.height * 2) layoutButton(closeButton, layout: closeLayout) diff --git a/ImageViewer/Source/ItemBaseController.swift b/ImageViewer/Source/ItemBaseController.swift index 5c03cee5..7e2611be 100644 --- a/ImageViewer/Source/ItemBaseController.swift +++ b/ImageViewer/Source/ItemBaseController.swift @@ -128,7 +128,7 @@ open class ItemBaseController: UIViewController, ItemController, UIGe fileprivate func configureBackgroundView(){ backgroundView.contentMode = .scaleToFill - let _frame = (UIApplication.shared.delegate as! AppDelegate).window!.frame + let _frame = UIApplication.shared.keyWindow!.frame backgroundView.frame = _frame let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark) let blurEffectView = UIVisualEffectView(effect: blurEffect) @@ -254,7 +254,7 @@ open class ItemBaseController: UIViewController, ItemController, UIGe scrollView.frame = self.view.bounds activityIndicatorView.center = view.boundsCenter - let _frame = (UIApplication.shared.delegate as! AppDelegate).window!.frame + let _frame = UIApplication.shared.keyWindow!.frame backgroundView.frame = _frame if let size = itemView.image?.size , size != CGSize.zero { From 7b65e06f8a0f10fe00d1e3019a9b4d33a64c75fa Mon Sep 17 00:00:00 2001 From: sameh Date: Mon, 3 Aug 2020 22:01:02 +0200 Subject: [PATCH 12/14] version 6.2.1 --- ImageViewer.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageViewer.podspec b/ImageViewer.podspec index 2ba150af..a3040a19 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.2" + s.version = "6.2.1" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. From c293646fd5c2d690df31ac24de4eccc15f359091 Mon Sep 17 00:00:00 2001 From: sameh Date: Sat, 9 Jan 2021 22:00:59 +0200 Subject: [PATCH 13/14] Added availaibty check --- .DS_Store | Bin 0 -> 6148 bytes ImageViewer.podspec | 2 +- ImageViewer/Source/Extensions/UIView.swift | 10 +++++++--- 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1c8f2ef08bfeb8d3696f258a63bfdd42b9bc0c3c GIT binary patch literal 6148 zcmeHK%Sr<=6g{bh))y2+bU8~`1=k{swWSt(fQoDT7)0rd)?$~l@gMvJKg6|bzedkZ zf;wrt714X)=43MW+)PeLG67&Jlg=(s0#Kw2=2uwEF?laOV>#clOf)t}9W@-|40V)e zqP0O4Pz8RQ0VTdl0Y_!=5qF2#iWD_^+<%;oH($%x7_D8uAM} z7!wn;gDh{%^73trn+vl{IdaL9Fwcm!yKJUhGx(m;f=rjpFs5$ffd3ls3*1>7oT(b; z=>oNE^wNG1y^M249&m@ju7H#Fm@L`OCLieVg`?U9d*J*EyF9mZcijPKd_ z8;Y^LGk;{mVPc0`ssgG&R)Hn=Sd#OB#kEuhp(DX;Z%AkcR@S_TR0K<`xga7~l literal 0 HcmV?d00001 diff --git a/ImageViewer.podspec b/ImageViewer.podspec index a3040a19..99aa9238 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.2.1" + s.version = "6.2.2" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. diff --git a/ImageViewer/Source/Extensions/UIView.swift b/ImageViewer/Source/Extensions/UIView.swift index 46541743..fe52e01f 100644 --- a/ImageViewer/Source/Extensions/UIView.swift +++ b/ImageViewer/Source/Extensions/UIView.swift @@ -39,8 +39,12 @@ extension UIView { extension DisplaceableView { - func frameInCoordinatesOfScreen() -> CGRect { - - return UIView().convert(self.bounds, to: UIApplication.shared.keyWindow!.coordinateSpace) + func frameInCoordinatesOfScreen() -> CGRect + { + if #available(iOS 12.0, *) { + return UIView().convert(self.bounds, to: UIApplication.shared.keyWindow!.coordinateSpace) + } else { + return UIView().convert(self.bounds, to: UIScreen.main.coordinateSpace) + } } } From 80002a88ad474c691539c10ee8abfdbbd3087fcc Mon Sep 17 00:00:00 2001 From: sameh Date: Sun, 7 Mar 2021 15:50:15 +0200 Subject: [PATCH 14/14] fix scrubber position for SafeArea --- ImageViewer.podspec | 2 +- ImageViewer/Source/GalleryViewController.swift | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ImageViewer.podspec b/ImageViewer.podspec index 99aa9238..877ac53c 100644 --- a/ImageViewer.podspec +++ b/ImageViewer.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ImageViewer" - s.version = "6.2.2" + s.version = "6.2.3" s.summary = "An image viewer à la Twitter" s.description = <<-EOS ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images. diff --git a/ImageViewer/Source/GalleryViewController.swift b/ImageViewer/Source/GalleryViewController.swift index c3755948..3be81abe 100644 --- a/ImageViewer/Source/GalleryViewController.swift +++ b/ImageViewer/Source/GalleryViewController.swift @@ -421,7 +421,13 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate { scrubber.bounds = CGRect(origin: CGPoint.zero, size: CGSize(width: self.view.bounds.width, height: 40)) scrubber.center = self.view.boundsCenter - scrubber.frame.origin.y = (footerView?.frame.origin.y ?? self.view.bounds.maxY) - scrubber.bounds.height + + if #available(iOS 11.0, *) { + scrubber.frame.origin.y = (self.view.safeAreaLayoutGuide.layoutFrame.maxY) - scrubber.bounds.height + } else { + // Fallback on earlier versions + scrubber.frame.origin.y = (footerView?.frame.origin.y ?? self.view.bounds.maxY) - scrubber.bounds.height + } } @objc fileprivate func deleteItem() {