123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- import UIKit
- class NCViewerPhotoViewController: UIViewController, UIScrollViewDelegate {
-
- let pagePadding: CGFloat = 10
- var pagingScrollView: UIScrollView!
- var recycledPages: Set<NCViewerPhotoImageScrollView> = []
- var visiblePages: Set<NCViewerPhotoImageScrollView> = []
- var firstVisiblePageIndexBeforeRotation: Int!
- var singleTap: UITapGestureRecognizer!
- var inTilingProcess: Set<String> = []
- var currentImageName: String = ""
-
- var metadata = tableMetadata()
- var metadatas = [tableMetadata]()
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- // Get Metadatas
- if let metadatas = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND typeFile == %@", metadata.account, metadata.serverUrl, k_metadataTypeFile_image), sorted: "fileName", ascending: true) {
- self.metadatas = metadatas
- }
-
- // single tap to show or hide navigation bar
- self.singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
- self.view.addGestureRecognizer(self.singleTap)
-
- self.pagingScrollView = UIScrollView(frame: self.frameForPagingScrollView())
- //self.updateBackgroundColor()
- self.pagingScrollView.showsVerticalScrollIndicator = false
- self.pagingScrollView.showsHorizontalScrollIndicator = false
- self.pagingScrollView.isPagingEnabled = true
- self.pagingScrollView.contentSize = self.contentSizeForPagingScrollView()
- self.pagingScrollView.delegate = self
- if #available(iOS 11.0, *) {
- pagingScrollView.contentInsetAdjustmentBehavior = .never
- } else {
- automaticallyAdjustsScrollViewInsets = false
- }
- self.view.addSubview(self.pagingScrollView)
- self.layoutPagingScrollView()
-
- self.tilePages()
- }
-
- //MARK: - Tiling and page configuration
-
- func tilePages() {
- // Calculate which pages should now be visible
- let visibleBounds = pagingScrollView.bounds
-
- var firstNeededPageIndex: Int = Int(floor(visibleBounds.minX/visibleBounds.width))
- var lastNeededPageIndex: Int = Int(floor((visibleBounds.maxX - 1)/visibleBounds.width))
- firstNeededPageIndex = max(firstNeededPageIndex, 0)
- lastNeededPageIndex = min(lastNeededPageIndex, metadatas.count - 1)
-
- //Recycle no longer needs pages
- for page in self.visiblePages {
- if page.index < firstNeededPageIndex || page.index > lastNeededPageIndex {
- self.recycledPages.insert(page)
- page.removeFromSuperview()
- }
- }
- self.visiblePages.subtract(self.recycledPages)
-
- //add missing pages
- for index in firstNeededPageIndex...lastNeededPageIndex {
- if !self.isDisplayingPage(forIndex: index) {
- let page = self.dequeueRecycledPage() ?? NCViewerPhotoImageScrollView()
-
- self.configure(page, for: index)
- self.pagingScrollView.addSubview(page)
- self.visiblePages.insert(page)
- }
- }
- }
-
- func dequeueRecycledPage() -> NCViewerPhotoImageScrollView? {
- if let page = self.recycledPages.first {
- self.recycledPages.removeFirst()
- return page
- }
- return nil
- }
-
- func isDisplayingPage(forIndex index: Int) -> Bool {
- for page in self.visiblePages {
- if page.index == index {
- return true
- }
- }
- return false
- }
-
- func configure(_ page: NCViewerPhotoImageScrollView, for index: Int) {
- self.singleTap.require(toFail: page.zoomingTap)
- page.backgroundColor = self.view.backgroundColor
- page.index = index
- page.frame = self.frameForPage(at: index)
- self.displayImage(at: index, in: page)
- }
-
- func displayImage(at index: Int, in page: NCViewerPhotoImageScrollView) {
- let metadata = metadatas[index]
- if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) == false {
- return
- }
- let imagePath = CCUtility.getDirectoryProviderStorageOcId(metadatas[index].ocId, fileNameView: metadatas[index].fileNameView)!
- let tileManager = NCViewerPhotoTileManager()
- if !tileManager.needsTilingImage(in: URL(fileURLWithPath: imagePath)) {
- let image: UIImage! = UIImage(contentsOfFile: imagePath)
- page.display(image)
- return
- }
- /*
- if tileManager.tilesMadeForImage(named: imageFileName) {
- let size = tileManager.sizeOfTiledImage(named: imageFileName)!
- let url = tileManager.urlOfTiledImage(named: imageFileName)
- page.displayTiledImage(in: url, size: size)
- }
- else {
-
- if self.inTilingProcess.contains(imageFileName) {
- if let placeholderURL = tileManager.urlOfPlaceholderOfImage(named: imageFileName) {
- let image: UIImage! = UIImage(contentsOfFile: placeholderURL.path)
- page.display(image)
- }
- return
- }
- else {
- self.inTilingProcess.insert(imageFileName)
- }
- tileManager.makeTiledImage(for: imageURL, placeholderCompletion: { (url, error) in
- if error == nil {
- let image: UIImage! = UIImage(contentsOfFile: url!.path)
- page.display(image)
- }
-
- }, tilingCompletion: { (imageName, imageSize, error) in
- if error == nil, imageName == self.currentImageName {
- let url = tileManager.urlOfTiledImage(named: imageName!)
- page.displayTiledImage(in: url, size: imageSize!)
-
- if self.inTilingProcess.contains(imageName!) {
- self.inTilingProcess.remove(imageName!)
- }
-
- }
- else {
- if error != nil {
- print(error!)
- }
- }
- })
- }
- */
- }
-
- //MARK: - ScrollView delegate methods
-
- func scrollViewDidScroll(_ scrollView: UIScrollView) {
- self.tilePages()
- }
-
- //MARK: - Frame calculations
-
- func frameForPagingScrollView(in size: CGSize? = nil) -> CGRect {
- var frame = self.view.bounds
-
- if size != nil {
- frame.size = size!
- }
-
- frame.origin.x -= pagePadding
- frame.size.width += 2*pagePadding
- return frame
- }
-
- func contentSizeForPagingScrollView() -> CGSize {
- let bounds = self.pagingScrollView.bounds
- return CGSize(width: bounds.size.width*CGFloat(metadatas.count), height: bounds.size.height)
- }
-
- func frameForPage(at index: Int) -> CGRect {
-
- let bounds = self.pagingScrollView.bounds
- var pageFrame = bounds
- pageFrame.size.width -= 2*pagePadding
- pageFrame.origin.x = (bounds.size.width*CGFloat(index)) + pagePadding
-
- return pageFrame
- }
-
- //MARK: - Rotation Configuration
-
- override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
- self.saveCurrentStatesForRotation()
- }
-
- override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
- self.restoreStatesForRotation(in: size)
- }
-
- /**
- Save current page and zooming states for device rotation.
- */
- func saveCurrentStatesForRotation() {
- let visibleBounds = pagingScrollView.bounds
- firstVisiblePageIndexBeforeRotation = Int(floor(visibleBounds.minX/visibleBounds.width))
- }
-
- /**
- Apply tracked informations for device rotation.
- */
- func restoreStatesForRotation(in size: CGSize) {
- // recalculate contentSize based on current orientation
- let pagingScrollViewFrame = self.frameForPagingScrollView(in: size)
- pagingScrollView?.frame = pagingScrollViewFrame
- pagingScrollView?.contentSize = self.contentSizeForPagingScrollView()
-
- // adjust frames and configuration of each visible page
- for page in visiblePages {
- let restorePoint = page.pointToCenterAfterRotation()
- let restoreScale = page.scaleToRestoreAfterRotation()
- page.frame = self.frameForPage(at: page.index)
- page.setMaxMinZoomScaleForCurrentBounds()
- page.restoreCenterPoint(to: restorePoint, oldScale: restoreScale)
- }
-
- // adjust contentOffset to preserve page location based on values collected prior to location
- var contentOffset = CGPoint.zero
-
- let pageWidth = pagingScrollView?.bounds.size.width ?? 1
- contentOffset.x = (CGFloat(firstVisiblePageIndexBeforeRotation) * pageWidth)
-
- pagingScrollView?.contentOffset = contentOffset
-
- }
-
- //MARK: - Handle Tap
-
- /// Single tap action which hides navigationBar by default implementation
- @objc func handleSingleTap() {
- /*
- let duration: TimeInterval = 0.2
-
- if self.navigationController != nil {
-
- if !self.navigationBarIsHidden {
-
- self.navigationBarIsHidden = true
- UIView.animate(withDuration: duration, animations: {
- self.navigationController!.navigationBar.alpha = 0
- self.updateBackgroundColor()
- }, completion: { (finished) in
- self.navigationController!.navigationBar.isHidden = true
- })
-
- }
- else {
- self.navigationBarIsHidden = false
- UIView.animate(withDuration: duration) {
- self.navigationController!.navigationBar.alpha = 1
- self.navigationController!.navigationBar.isHidden = false
- self.updateBackgroundColor()
- }
- }
- }
- */
- }
-
- /// Update background color. Default is white / black.
- /*
- func updateBackgroundColor() {
- if !self.navigationBarIsHidden {
- self.updateBackground(to: .white)
- }
- else {
- self.updateBackground(to: .black)
- }
- }
- */
-
- /*
- func updateBackground(to color: UIColor) {
- self.view.backgroundColor = color
- pagingScrollView?.backgroundColor = color
-
- for page in visiblePages {
- page.backgroundColor = color
- }
- }
- */
-
- func layoutPagingScrollView() {
- self.pagingScrollView.translatesAutoresizingMaskIntoConstraints = false
-
- let top = NSLayoutConstraint(item: self.pagingScrollView!, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1.0, constant: 0.0)
- let left = NSLayoutConstraint(item: self.pagingScrollView!, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1.0, constant: -10.0)
-
- let bottom = NSLayoutConstraint(item: self.pagingScrollView!, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: 0.0)
- let right = NSLayoutConstraint(item: self.pagingScrollView!, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1.0, constant: 10.0)
-
- self.view.addConstraints([top, left, bottom, right])
- }
- }
|