Tusker/Tusker/Screens/Attachment Gallery/GalleryViewController.swift

152 lines
5.1 KiB
Swift

// 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, LargeImageAnimatableViewController {
let attachments: [Attachment]
let sourceViews: WeakArray<UIImageView>
let startIndex: Int
let pages: [UIViewController]
var currentIndex: Int {
guard let vc = viewControllers?.first,
let index = pages.firstIndex(of: vc) else {
fatalError()
}
return index
}
var animationSourceView: UIImageView? { sourceViews[currentIndex] }
var animationImage: UIImage? {
if let page = pages[currentIndex] as? LoadingLargeImageViewController,
let image = page.largeImageVC?.image {
return image
} else {
return animationSourceView?.image
}
}
var animationGifData: Data? {
let attachment = attachments[currentIndex]
if attachment.url.pathExtension == "gif" {
return ImageCache.attachments.get(attachment.url)
} else {
return nil
}
}
var dismissInteractionController: LargeImageInteractionController?
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], sourceViews: [UIImageView?], startIndex: Int) {
self.attachments = attachments
self.sourceViews = WeakArray(sourceViews)
self.startIndex = startIndex
self.pages = attachments.map {
switch $0.kind {
case .image:
let vc = LoadingLargeImageViewController(attachment: $0)
vc.shrinkGestureEnabled = false
return vc
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()
}
}
// 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? LoadingLargeImageViewController,
let current = viewControllers!.first as? LoadingLargeImageViewController {
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()
}
}
}