diff --git a/iOS/Article/ArticleViewController.swift b/iOS/Article/ArticleViewController.swift index 352dd422d..89396ac74 100644 --- a/iOS/Article/ArticleViewController.swift +++ b/iOS/Article/ArticleViewController.swift @@ -444,11 +444,7 @@ private extension ArticleViewController { transition.maskFrame = webView.convert(webView.frame, to: nil) transition.originImage = image - let imageVC = UIStoryboard.main.instantiateController(ofType: ImageViewController.self) - imageVC.image = image - imageVC.modalPresentationStyle = .fullScreen - imageVC.transitioningDelegate = self - present(imageVC, animated: true) + coordinator.showFullScreenImage(image: image, transitioningDelegate: self) } } diff --git a/iOS/Article/ImageScrollView.swift b/iOS/Article/ImageScrollView.swift index 93292a06b..8439d7ce0 100644 --- a/iOS/Article/ImageScrollView.swift +++ b/iOS/Article/ImageScrollView.swift @@ -9,365 +9,352 @@ import UIKit @objc public protocol ImageScrollViewDelegate: UIScrollViewDelegate { - func imageScrollViewDidChangeOrientation(imageScrollView: ImageScrollView) func imageScrollViewDidGestureSwipeUp(imageScrollView: ImageScrollView) func imageScrollViewDidGestureSwipeDown(imageScrollView: ImageScrollView) } open class ImageScrollView: UIScrollView { - - @objc public enum ScaleMode: Int { - case aspectFill - case aspectFit - case widthFill - case heightFill - } - - @objc public enum Offset: Int { - case begining - case center - } - - static let kZoomInFactorFromMinWhenDoubleTap: CGFloat = 2 - - @objc open var imageContentMode: ScaleMode = .widthFill - @objc open var initialOffset: Offset = .begining - - @objc public private(set) var zoomView: UIImageView? = nil - - @objc open weak var imageScrollViewDelegate: ImageScrollViewDelegate? - - var imageSize: CGSize = CGSize.zero - private var pointToCenterAfterResize: CGPoint = CGPoint.zero - private var scaleToRestoreAfterResize: CGFloat = 1.0 - var maxScaleFromMinScale: CGFloat = 3.0 - + + @objc public enum ScaleMode: Int { + case aspectFill + case aspectFit + case widthFill + case heightFill + } + + @objc public enum Offset: Int { + case begining + case center + } + + static let kZoomInFactorFromMinWhenDoubleTap: CGFloat = 2 + + @objc open var imageContentMode: ScaleMode = .widthFill + @objc open var initialOffset: Offset = .begining + + @objc public private(set) var zoomView: UIImageView? = nil + + @objc open weak var imageScrollViewDelegate: ImageScrollViewDelegate? + + var imageSize: CGSize = CGSize.zero + private var pointToCenterAfterResize: CGPoint = CGPoint.zero + private var scaleToRestoreAfterResize: CGFloat = 1.0 + var maxScaleFromMinScale: CGFloat = 3.0 + var zoomedFrame: CGRect { return zoomView?.frame ?? CGRect.zero } - override open var frame: CGRect { - willSet { - if frame.equalTo(newValue) == false && newValue.equalTo(CGRect.zero) == false && imageSize.equalTo(CGSize.zero) == false { - prepareToResize() - } - } - - didSet { - if frame.equalTo(oldValue) == false && frame.equalTo(CGRect.zero) == false && imageSize.equalTo(CGSize.zero) == false { - recoverFromResizing() - } - } - } - - override public init(frame: CGRect) { - super.init(frame: frame) - - initialize() - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - - initialize() - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - private func initialize() { - showsVerticalScrollIndicator = false - showsHorizontalScrollIndicator = false - bouncesZoom = true - decelerationRate = UIScrollView.DecelerationRate.fast - delegate = self - - NotificationCenter.default.addObserver(self, selector: #selector(ImageScrollView.changeOrientationNotification), name: UIDevice.orientationDidChangeNotification, object: nil) - } - - @objc public func adjustFrameToCenter() { - - guard let unwrappedZoomView = zoomView else { - return - } - - var frameToCenter = unwrappedZoomView.frame - - // center horizontally - if frameToCenter.size.width < bounds.width { - frameToCenter.origin.x = (bounds.width - frameToCenter.size.width) / 2 - } else { - frameToCenter.origin.x = 0 - } - - // center vertically - if frameToCenter.size.height < bounds.height { - frameToCenter.origin.y = (bounds.height - frameToCenter.size.height) / 2 - } else { - frameToCenter.origin.y = 0 - } - - unwrappedZoomView.frame = frameToCenter - } - - private func prepareToResize() { - let boundsCenter = CGPoint(x: bounds.midX, y: bounds.midY) - pointToCenterAfterResize = convert(boundsCenter, to: zoomView) - - scaleToRestoreAfterResize = zoomScale - - // If we're at the minimum zoom scale, preserve that by returning 0, which will be converted to the minimum - // allowable scale when the scale is restored. - if scaleToRestoreAfterResize <= minimumZoomScale + CGFloat(Float.ulpOfOne) { - scaleToRestoreAfterResize = 0 - } - } - - private func recoverFromResizing() { - setMaxMinZoomScalesForCurrentBounds() - - // restore zoom scale, first making sure it is within the allowable range. - let maxZoomScale = max(minimumZoomScale, scaleToRestoreAfterResize) - zoomScale = min(maximumZoomScale, maxZoomScale) - - // restore center point, first making sure it is within the allowable range. - - // convert our desired center point back to our own coordinate space - let boundsCenter = convert(pointToCenterAfterResize, to: zoomView) - - // calculate the content offset that would yield that center point - var offset = CGPoint(x: boundsCenter.x - bounds.size.width/2.0, y: boundsCenter.y - bounds.size.height/2.0) - - // restore offset, adjusted to be within the allowable range - let maxOffset = maximumContentOffset() - let minOffset = minimumContentOffset() - - var realMaxOffset = min(maxOffset.x, offset.x) - offset.x = max(minOffset.x, realMaxOffset) - - realMaxOffset = min(maxOffset.y, offset.y) - offset.y = max(minOffset.y, realMaxOffset) - - contentOffset = offset - } - - private func maximumContentOffset() -> CGPoint { - return CGPoint(x: contentSize.width - bounds.width,y:contentSize.height - bounds.height) - } - - private func minimumContentOffset() -> CGPoint { - return CGPoint.zero - } - - // MARK: - Set up - - open func setup() { - var topSupperView = superview - - while topSupperView?.superview != nil { - topSupperView = topSupperView?.superview - } - - // Make sure views have already layout with precise frame - topSupperView?.layoutIfNeeded() - } - - // MARK: - Display image - - @objc open func display(image: UIImage) { - - if let zoomView = zoomView { - zoomView.removeFromSuperview() - } - - zoomView = UIImageView(image: image) - zoomView!.isUserInteractionEnabled = true - addSubview(zoomView!) - - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doubleTapGestureRecognizer(_:))) - tapGesture.numberOfTapsRequired = 2 - zoomView!.addGestureRecognizer(tapGesture) - + override open var frame: CGRect { + willSet { + if frame.equalTo(newValue) == false && newValue.equalTo(CGRect.zero) == false && imageSize.equalTo(CGSize.zero) == false { + prepareToResize() + } + } + + didSet { + if frame.equalTo(oldValue) == false && frame.equalTo(CGRect.zero) == false && imageSize.equalTo(CGSize.zero) == false { + recoverFromResizing() + } + } + } + + override public init(frame: CGRect) { + super.init(frame: frame) + + initialize() + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + private func initialize() { + showsVerticalScrollIndicator = false + showsHorizontalScrollIndicator = false + bouncesZoom = true + decelerationRate = UIScrollView.DecelerationRate.fast + delegate = self + } + + @objc public func adjustFrameToCenter() { + + guard let unwrappedZoomView = zoomView else { + return + } + + var frameToCenter = unwrappedZoomView.frame + + // center horizontally + if frameToCenter.size.width < bounds.width { + frameToCenter.origin.x = (bounds.width - frameToCenter.size.width) / 2 + } else { + frameToCenter.origin.x = 0 + } + + // center vertically + if frameToCenter.size.height < bounds.height { + frameToCenter.origin.y = (bounds.height - frameToCenter.size.height) / 2 + } else { + frameToCenter.origin.y = 0 + } + + unwrappedZoomView.frame = frameToCenter + } + + private func prepareToResize() { + let boundsCenter = CGPoint(x: bounds.midX, y: bounds.midY) + pointToCenterAfterResize = convert(boundsCenter, to: zoomView) + + scaleToRestoreAfterResize = zoomScale + + // If we're at the minimum zoom scale, preserve that by returning 0, which will be converted to the minimum + // allowable scale when the scale is restored. + if scaleToRestoreAfterResize <= minimumZoomScale + CGFloat(Float.ulpOfOne) { + scaleToRestoreAfterResize = 0 + } + } + + private func recoverFromResizing() { + setMaxMinZoomScalesForCurrentBounds() + + // restore zoom scale, first making sure it is within the allowable range. + let maxZoomScale = max(minimumZoomScale, scaleToRestoreAfterResize) + zoomScale = min(maximumZoomScale, maxZoomScale) + + // restore center point, first making sure it is within the allowable range. + + // convert our desired center point back to our own coordinate space + let boundsCenter = convert(pointToCenterAfterResize, to: zoomView) + + // calculate the content offset that would yield that center point + var offset = CGPoint(x: boundsCenter.x - bounds.size.width/2.0, y: boundsCenter.y - bounds.size.height/2.0) + + // restore offset, adjusted to be within the allowable range + let maxOffset = maximumContentOffset() + let minOffset = minimumContentOffset() + + var realMaxOffset = min(maxOffset.x, offset.x) + offset.x = max(minOffset.x, realMaxOffset) + + realMaxOffset = min(maxOffset.y, offset.y) + offset.y = max(minOffset.y, realMaxOffset) + + contentOffset = offset + } + + private func maximumContentOffset() -> CGPoint { + return CGPoint(x: contentSize.width - bounds.width,y:contentSize.height - bounds.height) + } + + private func minimumContentOffset() -> CGPoint { + return CGPoint.zero + } + + // MARK: - Set up + + open func setup() { + var topSupperView = superview + + while topSupperView?.superview != nil { + topSupperView = topSupperView?.superview + } + + // Make sure views have already layout with precise frame + topSupperView?.layoutIfNeeded() + } + + // MARK: - Display image + + @objc open func display(image: UIImage) { + + if let zoomView = zoomView { + zoomView.removeFromSuperview() + } + + zoomView = UIImageView(image: image) + zoomView!.isUserInteractionEnabled = true + addSubview(zoomView!) + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doubleTapGestureRecognizer(_:))) + tapGesture.numberOfTapsRequired = 2 + zoomView!.addGestureRecognizer(tapGesture) + let downSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeUpGestureRecognizer(_:))) downSwipeGesture.direction = .down zoomView!.addGestureRecognizer(downSwipeGesture) - + let upSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeDownGestureRecognizer(_:))) upSwipeGesture.direction = .up zoomView!.addGestureRecognizer(upSwipeGesture) - configureImageForSize(image.size) - } - - private func configureImageForSize(_ size: CGSize) { - imageSize = size - contentSize = imageSize - setMaxMinZoomScalesForCurrentBounds() - zoomScale = minimumZoomScale - - switch initialOffset { - case .begining: - contentOffset = CGPoint.zero - case .center: - let xOffset = contentSize.width < bounds.width ? 0 : (contentSize.width - bounds.width)/2 - let yOffset = contentSize.height < bounds.height ? 0 : (contentSize.height - bounds.height)/2 - - switch imageContentMode { - case .aspectFit: - contentOffset = CGPoint.zero - case .aspectFill: - contentOffset = CGPoint(x: xOffset, y: yOffset) - case .heightFill: - contentOffset = CGPoint(x: xOffset, y: 0) - case .widthFill: - contentOffset = CGPoint(x: 0, y: yOffset) - } - } - } - - private func setMaxMinZoomScalesForCurrentBounds() { - // calculate min/max zoomscale - let xScale = bounds.width / imageSize.width // the scale needed to perfectly fit the image width-wise - let yScale = bounds.height / imageSize.height // the scale needed to perfectly fit the image height-wise - - var minScale: CGFloat = 1 - - switch imageContentMode { - case .aspectFill: - minScale = max(xScale, yScale) - case .aspectFit: - minScale = min(xScale, yScale) - case .widthFill: - minScale = xScale - case .heightFill: - minScale = yScale - } - - - let maxScale = maxScaleFromMinScale*minScale - - // don't let minScale exceed maxScale. (If the image is smaller than the screen, we don't want to force it to be zoomed.) - if minScale > maxScale { - minScale = maxScale - } - - maximumZoomScale = maxScale - minimumZoomScale = minScale * 0.999 // the multiply factor to prevent user cannot scroll page while they use this control in UIPageViewController - } - - // MARK: - Gesture - - @objc func doubleTapGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { - // zoom out if it bigger than middle scale point. Else, zoom in - if zoomScale >= maximumZoomScale / 2.0 { - setZoomScale(minimumZoomScale, animated: true) - } else { - let center = gestureRecognizer.location(in: gestureRecognizer.view) - let zoomRect = zoomRectForScale(ImageScrollView.kZoomInFactorFromMinWhenDoubleTap * minimumZoomScale, center: center) - zoom(to: zoomRect, animated: true) - } - } - - @objc func swipeUpGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { + configureImageForSize(image.size) + } + + private func configureImageForSize(_ size: CGSize) { + imageSize = size + contentSize = imageSize + setMaxMinZoomScalesForCurrentBounds() + zoomScale = minimumZoomScale + + switch initialOffset { + case .begining: + contentOffset = CGPoint.zero + case .center: + let xOffset = contentSize.width < bounds.width ? 0 : (contentSize.width - bounds.width)/2 + let yOffset = contentSize.height < bounds.height ? 0 : (contentSize.height - bounds.height)/2 + + switch imageContentMode { + case .aspectFit: + contentOffset = CGPoint.zero + case .aspectFill: + contentOffset = CGPoint(x: xOffset, y: yOffset) + case .heightFill: + contentOffset = CGPoint(x: xOffset, y: 0) + case .widthFill: + contentOffset = CGPoint(x: 0, y: yOffset) + } + } + } + + private func setMaxMinZoomScalesForCurrentBounds() { + // calculate min/max zoomscale + let xScale = bounds.width / imageSize.width // the scale needed to perfectly fit the image width-wise + let yScale = bounds.height / imageSize.height // the scale needed to perfectly fit the image height-wise + + var minScale: CGFloat = 1 + + switch imageContentMode { + case .aspectFill: + minScale = max(xScale, yScale) + case .aspectFit: + minScale = min(xScale, yScale) + case .widthFill: + minScale = xScale + case .heightFill: + minScale = yScale + } + + + let maxScale = maxScaleFromMinScale*minScale + + // don't let minScale exceed maxScale. (If the image is smaller than the screen, we don't want to force it to be zoomed.) + if minScale > maxScale { + minScale = maxScale + } + + maximumZoomScale = maxScale + minimumZoomScale = minScale * 0.999 // the multiply factor to prevent user cannot scroll page while they use this control in UIPageViewController + } + + // MARK: - Gesture + + @objc func doubleTapGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { + // zoom out if it bigger than middle scale point. Else, zoom in + if zoomScale >= maximumZoomScale / 2.0 { + setZoomScale(minimumZoomScale, animated: true) + } else { + let center = gestureRecognizer.location(in: gestureRecognizer.view) + let zoomRect = zoomRectForScale(ImageScrollView.kZoomInFactorFromMinWhenDoubleTap * minimumZoomScale, center: center) + zoom(to: zoomRect, animated: true) + } + } + + @objc func swipeUpGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { if gestureRecognizer.state == .ended { imageScrollViewDelegate?.imageScrollViewDidGestureSwipeUp(imageScrollView: self) } } - - @objc func swipeDownGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { + + @objc func swipeDownGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { if gestureRecognizer.state == .ended { imageScrollViewDelegate?.imageScrollViewDidGestureSwipeDown(imageScrollView: self) } } - + private func zoomRectForScale(_ scale: CGFloat, center: CGPoint) -> CGRect { - var zoomRect = CGRect.zero - - // the zoom rect is in the content view's coordinates. - // at a zoom scale of 1.0, it would be the size of the imageScrollView's bounds. - // as the zoom scale decreases, so more content is visible, the size of the rect grows. - zoomRect.size.height = frame.size.height / scale - zoomRect.size.width = frame.size.width / scale - - // choose an origin so as to get the right center. - zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0) - zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0) - - return zoomRect - } - - open func refresh() { - if let image = zoomView?.image { - display(image: image) - } - } - - // MARK: - Actions - - @objc func changeOrientationNotification() { - // A weird bug that frames are not update right after orientation changed. Need delay a little bit with async. - DispatchQueue.main.async { - self.configureImageForSize(self.imageSize) - self.imageScrollViewDelegate?.imageScrollViewDidChangeOrientation(imageScrollView: self) - } - } + var zoomRect = CGRect.zero + + // the zoom rect is in the content view's coordinates. + // at a zoom scale of 1.0, it would be the size of the imageScrollView's bounds. + // as the zoom scale decreases, so more content is visible, the size of the rect grows. + zoomRect.size.height = frame.size.height / scale + zoomRect.size.width = frame.size.width / scale + + // choose an origin so as to get the right center. + zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0) + zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0) + + return zoomRect + } + + open func refresh() { + if let image = zoomView?.image { + display(image: image) + } + } + + open func resize() { + self.configureImageForSize(self.imageSize) + } } extension ImageScrollView: UIScrollViewDelegate { - - public func scrollViewDidScroll(_ scrollView: UIScrollView) { - imageScrollViewDelegate?.scrollViewDidScroll?(scrollView) - } - - public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { - imageScrollViewDelegate?.scrollViewWillBeginDragging?(scrollView) - } - - public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { - imageScrollViewDelegate?.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset) - } - - public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { - imageScrollViewDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate) - } - - public func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) { - imageScrollViewDelegate?.scrollViewWillBeginDecelerating?(scrollView) - } - - public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - imageScrollViewDelegate?.scrollViewDidEndDecelerating?(scrollView) - } - - public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { - imageScrollViewDelegate?.scrollViewDidEndScrollingAnimation?(scrollView) - } - - public func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) { - imageScrollViewDelegate?.scrollViewWillBeginZooming?(scrollView, with: view) - } - - public func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) { - imageScrollViewDelegate?.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale) - } - - public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { - return false - } - - @available(iOS 11.0, *) - public func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) { - imageScrollViewDelegate?.scrollViewDidChangeAdjustedContentInset?(scrollView) - } - - public func viewForZooming(in scrollView: UIScrollView) -> UIView? { - return zoomView - } - - public func scrollViewDidZoom(_ scrollView: UIScrollView) { - adjustFrameToCenter() - imageScrollViewDelegate?.scrollViewDidZoom?(scrollView) - } - + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + imageScrollViewDelegate?.scrollViewDidScroll?(scrollView) + } + + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + imageScrollViewDelegate?.scrollViewWillBeginDragging?(scrollView) + } + + public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + imageScrollViewDelegate?.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset) + } + + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + imageScrollViewDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate) + } + + public func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) { + imageScrollViewDelegate?.scrollViewWillBeginDecelerating?(scrollView) + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + imageScrollViewDelegate?.scrollViewDidEndDecelerating?(scrollView) + } + + public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { + imageScrollViewDelegate?.scrollViewDidEndScrollingAnimation?(scrollView) + } + + public func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) { + imageScrollViewDelegate?.scrollViewWillBeginZooming?(scrollView, with: view) + } + + public func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) { + imageScrollViewDelegate?.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale) + } + + public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { + return false + } + + @available(iOS 11.0, *) + public func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) { + imageScrollViewDelegate?.scrollViewDidChangeAdjustedContentInset?(scrollView) + } + + public func viewForZooming(in scrollView: UIScrollView) -> UIView? { + return zoomView + } + + public func scrollViewDidZoom(_ scrollView: UIScrollView) { + adjustFrameToCenter() + imageScrollViewDelegate?.scrollViewDidZoom?(scrollView) + } + } diff --git a/iOS/Article/ImageViewController.swift b/iOS/Article/ImageViewController.swift index b1c40a153..d837b4d4b 100644 --- a/iOS/Article/ImageViewController.swift +++ b/iOS/Article/ImageViewController.swift @@ -28,6 +28,13 @@ class ImageViewController: UIViewController { imageScrollView.display(image: image) } + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + coordinator.animate(alongsideTransition: { [weak self] context in + self?.imageScrollView.resize() + }) + } + @IBAction func share(_ sender: Any) { guard let image = image else { return } let activityViewController = UIActivityViewController(activityItems: [image], applicationActivities: nil) @@ -46,9 +53,6 @@ class ImageViewController: UIViewController { extension ImageViewController: ImageScrollViewDelegate { - func imageScrollViewDidChangeOrientation(imageScrollView: ImageScrollView) { - } - func imageScrollViewDidGestureSwipeUp(imageScrollView: ImageScrollView) { dismiss(animated: true) } diff --git a/iOS/RootSplitViewController.swift b/iOS/RootSplitViewController.swift index 89fb623f3..cf7040c42 100644 --- a/iOS/RootSplitViewController.swift +++ b/iOS/RootSplitViewController.swift @@ -14,6 +14,7 @@ class RootSplitViewController: UISplitViewController { var coordinator: SceneCoordinator! override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { [weak self] context in self?.coordinator.configureThreePanelMode(for: size) }) diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index a647e5b35..17c0dd94a 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -819,6 +819,14 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { masterFeedViewController.present(addViewController, animated: true) } + func showFullScreenImage(image: UIImage, transitioningDelegate: UIViewControllerTransitioningDelegate) { + let imageVC = UIStoryboard.main.instantiateController(ofType: ImageViewController.self) + imageVC.image = image + imageVC.modalPresentationStyle = .currentContext + imageVC.transitioningDelegate = transitioningDelegate + rootSplitViewController.present(imageVC, animated: true) + } + func toggleArticleExtractor() { guard let article = currentArticle else {