123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- import UIKit
- class NCViewerPhotoView: UIScrollView, UIScrollViewDelegate {
-
- let pagePadding: CGFloat = 10
- 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]()
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
- NotificationCenter.default.addObserver(self, selector: #selector(self.changeTheming), name: NSNotification.Name(rawValue: "changeTheming"), object: nil)
- }
-
- @objc func setup(metadata: tableMetadata, view: UIView) {
-
- self.metadata = metadata
- 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
- singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
- addGestureRecognizer(self.singleTap)
-
- showsVerticalScrollIndicator = false
- showsHorizontalScrollIndicator = false
- isPagingEnabled = true
- contentSize = self.contentSizeForPagingScrollView()
- delegate = self
- view.addSubview(self)
-
- tilePages()
- }
-
- @objc func changeTheming() {
- backgroundColor = NCBrandColor.sharedInstance.backgroundView
- }
-
- //MARK: - Tiling and page configuration
-
- func tilePages() {
- // Calculate which pages should now be visible
- let visibleBounds = self.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.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.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.bounds
-
- if size != nil {
- frame.size = size!
- }
-
- frame.origin.x -= pagePadding
- frame.size.width += 2*pagePadding
- return frame
- }
-
- func contentSizeForPagingScrollView() -> CGSize {
- let bounds = self.bounds
- return CGSize(width: bounds.size.width*CGFloat(metadatas.count), height: bounds.size.height)
- }
-
- func frameForPage(at index: Int) -> CGRect {
-
- let bounds = self.bounds
- var pageFrame = bounds
- pageFrame.size.width -= 2*pagePadding
- pageFrame.origin.x = (bounds.size.width*CGFloat(index)) + pagePadding
-
- return pageFrame
- }
-
- func saveCurrentStatesForRotation() {
- let visibleBounds = self.bounds
- firstVisiblePageIndexBeforeRotation = Int(floor(visibleBounds.minX/visibleBounds.width))
- }
-
- func restoreStatesForRotation(in size: CGSize) {
- // recalculate contentSize based on current orientation
- let pagingScrollViewFrame = self.frameForPagingScrollView(in: size)
- self.frame = pagingScrollViewFrame
- self.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 = self.bounds.size.width
- contentOffset.x = (CGFloat(firstVisiblePageIndexBeforeRotation) * pageWidth)
-
- self.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
- }
- }
- */
- }
|