// GalleryViewController.swift // Tusker // // Created by Shadowfacts on 6/13/19. // Copyright © 2019 Shadowfacts. All rights reserved. // import UIKit import Pachyderm import AVFoundation import AVKit class GalleryViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { var dismissInteractionController: LargeImageInteractionController? let attachments: [Attachment] let sourcesInfo: [LargeImageViewController.SourceInfo?] let startIndex: Int let pages: [UIViewController] var currentIndex: Int { guard let vc = viewControllers?.first, let index = pages.firstIndex(of: vc) else { fatalError() } return index } override var prefersStatusBarHidden: Bool { return true } override var childForHomeIndicatorAutoHidden: UIViewController? { return viewControllers?.first } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return .allButUpsideDown } else { return .all } } init(attachments: [Attachment], sourcesInfo: [LargeImageViewController.SourceInfo?], startIndex: Int) { self.attachments = attachments self.sourcesInfo = sourcesInfo self.startIndex = startIndex self.pages = attachments.map { switch $0.kind { case .image: return AttachmentViewController(attachment: $0) case .video, .audio: let vc = AVPlayerViewController() vc.player = AVPlayer(url: $0.url) return vc default: fatalError() } } super.init(transitionStyle: .scroll, navigationOrientation: .horizontal) setViewControllers([pages[startIndex]], direction: .forward, animated: false) modalPresentationStyle = .fullScreen } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() self.dataSource = self self.delegate = self overrideUserInterfaceStyle = .dark dismissInteractionController = LargeImageInteractionController(viewController: self) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if let vc = pages[currentIndex] as? AVPlayerViewController { // when the gallery is first shown, after the transition finishes, the controls for the player controller appear semi-transparent // hiding the controls and then immediately reshowing them makes sure they're visible when the gallery is presented vc.showsPlaybackControls = false vc.showsPlaybackControls = true // begin playing the video as soon as we appear vc.player?.play() } } func imageForDismissalAnimation() -> UIImage? { if let sourceImage = sourcesInfo[currentIndex]?.image { return sourceImage } else { return (pages[currentIndex] as? AttachmentViewController)?.largeImageVC?.image } } // MARK: - Page View Controller Data Source func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let index = pages.firstIndex(of: viewController), index > 0 else { return nil } return pages[index - 1] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let index = pages.firstIndex(of: viewController), index < pages.count - 1 else { return nil } return pages[index + 1] } // MARK: - Page View Controller Delegate func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { if let pending = pendingViewControllers.first as? AttachmentViewController, let current = viewControllers!.first as? AttachmentViewController { pending.controlsVisible = current.controlsVisible } if let pending = pendingViewControllers.first as? AVPlayerViewController { // show controls and begin playing when the player page becomes visible pending.showsPlaybackControls = true pending.player?.play() } } }